Skip to content

Commit

Permalink
chore: add initial classes
Browse files Browse the repository at this point in the history
  • Loading branch information
Harald Ziegler authored and zieglerh committed Mar 10, 2024
1 parent dc4f8e8 commit 98fc7de
Show file tree
Hide file tree
Showing 20 changed files with 1,078 additions and 0 deletions.
21 changes: 21 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
root = true

[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 4

[*.php]
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false

[*.{yml,yaml}]
indent_size = 4

[*.json]
indent_style = space
indent_size = 2
4 changes: 4 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Arguments for tools
PHPCS_ARGS="--extensions=php --ignore="*/Tests/*,*/Resources/views/*" --standard=$PHPCS_RULESET_FILE ./src -s"
PHPMD_ARGS="./src text $PHPMD_RULESET_FILE --exclude=\"*/Resources/views/*\""
PHPSTAN_ARGS="analyse -c phpstan.neon src"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/.idea
/vendor
/composer.lock
136 changes: 136 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# EventManagerBundle

Subscribe to Events via PHP Attribute Tags without any configuration and only via function arguments

## Installation

### Composer
```bash
composer require zieglerh/pimcore-event-manager-bundle:^1.0
```

## Benefits

- define EventSubscribers simple with PHP Attributes
- subscribe to only used events
- caching via symfony cache

## Usage

Create an EventSubscriber class and implement `EventManagerBundle\EventSubscriber\EventSubscriberInterface`.

Make sure your class folder is defined in services.yml.

Use `EnabledTrait` in your class.

Create a function and define function Properties with one or more events.

The arguments can be the event subject or the event class.

```php
#[Event(DocumentEvents::PRE_ADD)]
#[Event(DocumentEvents::PRE_UPDATE)]
public function check(Document\Link $link): void
```

To speed up bulk tasks, you can enable and disable the EventSubscriber from anywhere via static functions.

### Examples

DataObjects

```php
<?php

namespace App\EventSubscriber;

use EventManagerBundle\Event\Event;
use EventManagerBundle\EventSubscriber\EnabledTrait;
use EventManagerBundle\EventSubscriber\EventSubscriberInterface;
use Pimcore\Event\DataObjectEvents;
use Pimcore\Model\DataObject\MyModel;

/**
* Class MyModelSubscriber
*
* @package App\EventSubscriber
*/
class MyModelSubscriber implements EventSubscriberInterface
{
use EnabledTrait;

/**
* @param MyModel $object
*
* @return void
* @throws \JsonException
*/
#[Event(DataObjectEvents::PRE_UPDATE)]
#[Event(DataObjectEvents::PRE_ADD)]
private function doSomething(MyModel $object): void
{
// implementation
}
}

```

Documents with $event example

```php
<?php

namespace App\EventSubscriber;

use EventManagerBundle\Event\Event;
use EventManagerBundle\EventSubscriber\EnabledTrait;
use EventManagerBundle\EventSubscriber\EventSubscriberInterface;
use Pimcore\Event\DocumentEvents;
use Pimcore\Model\Document;
use Pimcore\Event\Model\DocumentEvent;

/**
* Class DocumentSubscriber
*
* @package App\EventSubscriber
*/
class DocumentSubscriber implements EventSubscriberInterface
{
use EnabledTrait;

/**
* @param Document\Link $link
*
* @return void
*/
#[Event(DocumentEvents::PRE_ADD)]
#[Event(DocumentEvents::PRE_UPDATE)]
public function doSomething(Document\Link $link, DocumentEvent $event): void
{
// implementation
}
}
```

Basically any event from *Events.php classes

```php
// e.g. vendor/pimcore/pimcore/lib/Event/UserRoleEvents.php
/**
* @Event("Pimcore\Event\Model\UserRoleEvent")
*
* @var string
*/
const PRE_ADD = 'pimcore.user.preAdd';

// from @Event docblock you can see, it will fire a UserRoleEvent
// ...
// inside
\Pimcore\Model\User\AbstractUser::save()
// you will see
$this->dispatchEvent(new UserRoleEvent($this), UserRoleEvents::PRE_UPDATE);
// you can use either User or Role or UserRole or Folder class as function argument
// and optional UserRoleEvent as event argument
```


31 changes: 31 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "zieglerh/pimcore-event-manager",
"description": "Bind events via PHP Attributes in EventSubscribers",
"type": "pimcore-bundle",
"license": "GPL-3.0-or-later",
"authors": [
{
"name": "Harald Ziegler",
"email": "h.ziegler@sent.com"
}
],
"autoload": {
"psr-4": {
"EventManagerBundle\\": "src"
}
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/zieglerh/php-code-quality"
}
],
"require": {
"php": "^8.0",
"pimcore/pimcore": "^11.0",
"symfony/dependency-injection": "^6.0"
},
"require-dev": {
"zieglerh/php-code-quality": "^1.0"
}
}
12 changes: 12 additions & 0 deletions phpstan-parameters.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
parameters:
level: 6

paths:
- src

excludePaths:
- '*/node_modules/*'

ignoreErrors:
- '#no value type specified in iterable type array\.$#'
- '#\$configurator of method Symfony\\Component\\DependencyInjection\\ContainerBuilder\:\:registerAttributeForAutoconfiguration\(\) expects callable#'
4 changes: 4 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
includes:
- vendor/phpstan/phpstan-symfony/extension.neon
- vendor/phpstan/phpstan-symfony/rules.neon
- phpstan-parameters.neon
56 changes: 56 additions & 0 deletions rector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

use Rector\CodeQuality\Rector\FunctionLike\SimplifyUselessVariableRector;
use Rector\CodeQuality\Rector\If_\ExplicitBoolCompareRector;
use Rector\Config\RectorConfig;
use Rector\DeadCode\Rector\Assign\RemoveUnusedVariableAssignRector;
use Rector\DeadCode\Rector\ClassMethod\RemoveUnusedPrivateMethodParameterRector;
use Rector\DeadCode\Rector\ClassMethod\RemoveUselessParamTagRector;
use Rector\DeadCode\Rector\ClassMethod\RemoveUselessReturnTagRector;
use Rector\DeadCode\Rector\Property\RemoveUselessVarTagRector;
use Rector\Naming\Rector\Assign\RenameVariableToMatchMethodCallReturnTypeRector;
use Rector\Naming\Rector\Class_\RenamePropertyToMatchTypeRector;
use Rector\Naming\Rector\ClassMethod\RenameParamToMatchTypeRector;
use Rector\Naming\Rector\ClassMethod\RenameVariableToMatchNewTypeRector;
use Rector\Naming\Rector\Foreach_\RenameForeachValueVariableToMatchExprVariableRector;
use Rector\Naming\Rector\Foreach_\RenameForeachValueVariableToMatchMethodCallReturnTypeRector;
use Rector\Php80\Rector\FunctionLike\MixedTypeRector;
use Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector;
use Rector\Strict\Rector\Empty_\DisallowedEmptyRuleFixerRector;
use Rector\Strict\Rector\Ternary\DisallowedShortTernaryRuleFixerRector;

$skipDependencyInjectionPath = __DIR__ . '/*/DependencyInjection/*';

return RectorConfig::configure()
->withPaths([
__DIR__ . '/src',
])
->withSkip([
__DIR__ . '/*/node_modules/*',
RemoveUselessParamTagRector::class,
RemoveUselessReturnTagRector::class,
MixedTypeRector::class,
RenameParamToMatchTypeRector::class,
RenameForeachValueVariableToMatchMethodCallReturnTypeRector::class,
DisallowedEmptyRuleFixerRector::class,
RemoveUselessVarTagRector::class,
NullToStrictStringFuncCallArgRector::class,
ExplicitBoolCompareRector::class,
DisallowedShortTernaryRuleFixerRector::class,
RenamePropertyToMatchTypeRector::class,
RenameVariableToMatchNewTypeRector::class,
RenameVariableToMatchMethodCallReturnTypeRector::class,
RenameForeachValueVariableToMatchExprVariableRector::class,
RemoveUnusedPrivateMethodParameterRector::class,
SimplifyUselessVariableRector::class => [
$skipDependencyInjectionPath,
],
RemoveUnusedVariableAssignRector::class => [
$skipDependencyInjectionPath,
],
])
->withPhpSets()
->withPHPStanConfigs([
__DIR__ . '/phpstan.neon',
])
->withPreparedSets(true, true, true, true, true, true, true, true, true);
89 changes: 89 additions & 0 deletions src/DependencyInjection/Compiler/EventManagerPass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright Harald Ziegler <h.ziegler@sent.com>
*/
declare(strict_types=1);

namespace EventManagerBundle\DependencyInjection\Compiler;

use Pimcore\Model\DataObject\Concrete;
use EventManagerBundle\EventManager;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
* Class EventManagerPass
*
* @package EventManagerBundle\DependencyInjection\Compiler
*/
class EventManagerPass implements CompilerPassInterface
{
/**
* Configuration for EventManager
*
* @var array
*/
private static array $config = [
'subscribers' => [],
'typeMap' => [],
'arguments' => [],
];

/**
* Add subscriber config
*
* @param string $eventMethod
* @param string $className
* @param string $subscriberMethod
* @param array $methodParameters
*
* @return void
*/
public static function addSubscriber(
string $eventMethod,
string $className,
string $subscriberMethod,
array $methodParameters,
): void {
self::$config['subscribers'][$eventMethod][$className][$subscriberMethod] = $methodParameters;

foreach ($methodParameters as $parameters) {
foreach ($parameters as $parameter) {
if (is_subclass_of($parameter, Concrete::class)) {
$object = new $parameter();
self::$config['typeMap']['concrete'][$object->getClassName()][$className] = true;
}
}
}
}

/**
* Add event argument config
*
* @param string $attribute
* @param string $className
* @param string $subscriberMethod
*
* @return void
*/
public static function addEventArgument(string $attribute, string $className, string $subscriberMethod): void
{
self::$config['arguments'][$attribute][$className][$subscriberMethod] = true;
}

/**
* Process compiler
*
* @param ContainerBuilder $container
*
* @return void
*/
public function process(ContainerBuilder $container): void
{
$definition = $container->getDefinition(EventManager::class);
$definition->setArgument('$config', self::$config);
}
}
Loading

0 comments on commit 98fc7de

Please sign in to comment.