Skip to content

Commit

Permalink
[Twig Hooks] Introduce DisabledHookable object to mark disabled hooka…
Browse files Browse the repository at this point in the history
…bles
  • Loading branch information
jakubtobiasz committed Apr 24, 2024
1 parent 91db7f0 commit da72e2b
Show file tree
Hide file tree
Showing 26 changed files with 223 additions and 396 deletions.
24 changes: 17 additions & 7 deletions src/TwigHooks/src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Sylius\TwigHooks\DependencyInjection;

use Sylius\TwigHooks\Hookable\DisabledHookable;
use Sylius\TwigHooks\Hookable\HookableComponent;
use Sylius\TwigHooks\Hookable\HookableTemplate;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
Expand Down Expand Up @@ -39,6 +40,7 @@ private function addSupportedHookableTypesConfiguration(ArrayNodeDefinition $roo
->defaultValue([
'template' => HookableTemplate::class,
'component' => HookableComponent::class,
'disabled' => DisabledHookable::class,
])
->scalarPrototype()->end()
->end()
Expand All @@ -57,15 +59,19 @@ private function addHooksConfiguration(ArrayNodeDefinition $rootNode): void
->arrayPrototype()
->beforeNormalization()
->always(function ($v) {
$component = $v['component'] ?? null;
$template = $v['template'] ?? null;
$isComponentDefined = isset($v['component']);
$isTemplateDefined = isset($v['template']);
$isDisabled = isset($v['enabled']) && $v['enabled'] === false;

if (null === $component && null === $template) {
if (!$isComponentDefined && !$isTemplateDefined && !$isDisabled) {
return $v;
}

$v['type'] = null !== $component ? 'component' : 'template';
$v['target'] = $component ?? $template;
$v['type'] = match (true) {

Check failure on line 70 in src/TwigHooks/src/DependencyInjection/Configuration.php

View workflow job for this annotation

GitHub Actions / Continuous Integration (PHP 8.1 / Symfony ^5.4)

Match expression does not handle remaining value: true

Check failure on line 70 in src/TwigHooks/src/DependencyInjection/Configuration.php

View workflow job for this annotation

GitHub Actions / Continuous Integration (PHP 8.1 / Symfony ^6.4)

Match expression does not handle remaining value: true

Check failure on line 70 in src/TwigHooks/src/DependencyInjection/Configuration.php

View workflow job for this annotation

GitHub Actions / Continuous Integration (PHP 8.2 / Symfony ^5.4)

Match expression does not handle remaining value: true

Check failure on line 70 in src/TwigHooks/src/DependencyInjection/Configuration.php

View workflow job for this annotation

GitHub Actions / Continuous Integration (PHP 8.2 / Symfony ^6.4)

Match expression does not handle remaining value: true

Check failure on line 70 in src/TwigHooks/src/DependencyInjection/Configuration.php

View workflow job for this annotation

GitHub Actions / Continuous Integration (PHP 8.3 / Symfony ^5.4)

Match expression does not handle remaining value: true

Check failure on line 70 in src/TwigHooks/src/DependencyInjection/Configuration.php

View workflow job for this annotation

GitHub Actions / Continuous Integration (PHP 8.3 / Symfony ^6.4)

Match expression does not handle remaining value: true
$isDisabled => 'disabled',
$isComponentDefined => 'component',
$isTemplateDefined => 'template',
};

return $v;
})
Expand All @@ -74,11 +80,16 @@ private function addHooksConfiguration(ArrayNodeDefinition $rootNode): void
->always(static function ($v) {
$component = $v['component'] ?? null;
$template = $v['template'] ?? null;
$enabled = $v['enabled'] ?? true;

if (null !== $component && null !== $template) {
throw new \InvalidArgumentException('You cannot define both "component" and "template" at the same time.');
}

if ($enabled && null === $component && null === $template) {
throw new \InvalidArgumentException('You must define either "component" or "template" for enabled hookables.');
}

if (null === $component && [] !== $v['props']) {
throw new \InvalidArgumentException('"Props" cannot be defined for non-component hookables.');
}
Expand All @@ -88,8 +99,7 @@ private function addHooksConfiguration(ArrayNodeDefinition $rootNode): void
->end()
->canBeDisabled()
->children()
->scalarNode('type')->defaultValue('template')->end()
->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
->scalarNode('type')->defaultNull()->end()
->scalarNode('component')->defaultNull()->end()
->scalarNode('template')->defaultNull()->end()
->arrayNode('context')
Expand Down
62 changes: 26 additions & 36 deletions src/TwigHooks/src/DependencyInjection/TwigHooksExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Sylius\TwigHooks\DependencyInjection;

use Sylius\TwigHooks\Hookable\DisabledHookable;
use Sylius\TwigHooks\Hookable\HookableComponent;
use Sylius\TwigHooks\Hookable\HookableTemplate;
use Symfony\Component\Config\FileLocator;
Expand All @@ -30,14 +31,7 @@ public function load(array $configs, ContainerBuilder $container): void
}

/**
* @param array<string, array<string, array{
* type: string,
* target: string,
* context: array<string, mixed>,
* configuration: array<string, mixed>,
* priority: int,
* enabled: bool,
* }>> $hooks
* @param array<string, mixed> $hooks
* @param array<string, string> $supportedHookableTypes
*/
private function registerHooks(ContainerBuilder $container, array $hooks, array $supportedHookableTypes): void
Expand All @@ -60,15 +54,7 @@ private function registerHooks(ContainerBuilder $container, array $hooks, array
}

/**
* @param array{
* type: string,
* target: string,
* props?: array<string, mixed>,
* context: array<string, mixed>,
* configuration: array<string, mixed>,
* priority: int,
* enabled: bool,
* } $hookable
* @param array<string, mixed> $hookable
*/
private function registerHookable(
ContainerBuilder $container,
Expand All @@ -80,19 +66,13 @@ private function registerHookable(
match ($class) {
HookableTemplate::class => $this->registerTemplateHookable($container, $hookName, $hookableName, $hookable),
HookableComponent::class => $this->registerComponentHookable($container, $hookName, $hookableName, $hookable),
DisabledHookable::class => $this->registerDisabledHookable($container, $hookName, $hookableName),
default => throw new \InvalidArgumentException(sprintf('Unsupported hookable class "%s".', $class)),
};
}

/**
* @param array{
* type: string,
* target: string,
* context: array<string, mixed>,
* configuration: array<string, mixed>,
* priority: int,
* enabled: bool,
* } $hookable
* @param array<string, mixed> $hookable
*/
private function registerTemplateHookable(
ContainerBuilder $container,
Expand All @@ -105,7 +85,7 @@ private function registerTemplateHookable(
->setArguments([
$hookName,
$hookableName,
$hookable['target'],
$hookable['template'],
$hookable['context'],
$hookable['configuration'],
$hookable['priority'],
Expand All @@ -116,15 +96,7 @@ private function registerTemplateHookable(
}

/**
* @param array{
* type: string,
* target: string,
* props?: array<string, mixed>,
* context: array<string, mixed>,
* configuration: array<string, mixed>,
* priority: int,
* enabled: bool,
* } $hookable
* @param array<string, mixed> $hookable
*/
private function registerComponentHookable(
ContainerBuilder $container,
Expand All @@ -137,7 +109,7 @@ private function registerComponentHookable(
->setArguments([
$hookName,
$hookableName,
$hookable['target'],
$hookable['component'],
$hookable['props'] ?? [],
$hookable['context'],
$hookable['configuration'],
Expand All @@ -147,4 +119,22 @@ private function registerComponentHookable(
->addTag('twig_hooks.hookable', ['priority' => $hookable['priority']])
;
}

private function registerDisabledHookable(
ContainerBuilder $container,
string $hookName,
string $hookableName,
): void {
$container
->register(sprintf('twig_hooks.hook.%s.hookable.%s', $hookName, $hookableName), DisabledHookable::class)
->setArguments([
$hookName,
$hookableName,
[],
[],
null,
])
->addTag('twig_hooks.hookable', ['priority' => 0])
;
}
}
46 changes: 24 additions & 22 deletions src/TwigHooks/src/Hookable/AbstractHookable.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,42 +6,44 @@

abstract class AbstractHookable
{
public readonly string $id;

public readonly string $hookName;

public readonly string $name;

public readonly array $context;

Check failure on line 15 in src/TwigHooks/src/Hookable/AbstractHookable.php

View workflow job for this annotation

GitHub Actions / Continuous Integration (PHP 8.1 / Symfony ^5.4)

Property Sylius\TwigHooks\Hookable\AbstractHookable::$context type has no value type specified in iterable type array.

Check failure on line 15 in src/TwigHooks/src/Hookable/AbstractHookable.php

View workflow job for this annotation

GitHub Actions / Continuous Integration (PHP 8.1 / Symfony ^6.4)

Property Sylius\TwigHooks\Hookable\AbstractHookable::$context type has no value type specified in iterable type array.

Check failure on line 15 in src/TwigHooks/src/Hookable/AbstractHookable.php

View workflow job for this annotation

GitHub Actions / Continuous Integration (PHP 8.2 / Symfony ^5.4)

Property Sylius\TwigHooks\Hookable\AbstractHookable::$context type has no value type specified in iterable type array.

Check failure on line 15 in src/TwigHooks/src/Hookable/AbstractHookable.php

View workflow job for this annotation

GitHub Actions / Continuous Integration (PHP 8.2 / Symfony ^6.4)

Property Sylius\TwigHooks\Hookable\AbstractHookable::$context type has no value type specified in iterable type array.

Check failure on line 15 in src/TwigHooks/src/Hookable/AbstractHookable.php

View workflow job for this annotation

GitHub Actions / Continuous Integration (PHP 8.3 / Symfony ^5.4)

Property Sylius\TwigHooks\Hookable\AbstractHookable::$context type has no value type specified in iterable type array.

Check failure on line 15 in src/TwigHooks/src/Hookable/AbstractHookable.php

View workflow job for this annotation

GitHub Actions / Continuous Integration (PHP 8.3 / Symfony ^6.4)

Property Sylius\TwigHooks\Hookable\AbstractHookable::$context type has no value type specified in iterable type array.

public readonly array $configuration;

Check failure on line 17 in src/TwigHooks/src/Hookable/AbstractHookable.php

View workflow job for this annotation

GitHub Actions / Continuous Integration (PHP 8.1 / Symfony ^5.4)

Property Sylius\TwigHooks\Hookable\AbstractHookable::$configuration type has no value type specified in iterable type array.

Check failure on line 17 in src/TwigHooks/src/Hookable/AbstractHookable.php

View workflow job for this annotation

GitHub Actions / Continuous Integration (PHP 8.1 / Symfony ^6.4)

Property Sylius\TwigHooks\Hookable\AbstractHookable::$configuration type has no value type specified in iterable type array.

Check failure on line 17 in src/TwigHooks/src/Hookable/AbstractHookable.php

View workflow job for this annotation

GitHub Actions / Continuous Integration (PHP 8.2 / Symfony ^5.4)

Property Sylius\TwigHooks\Hookable\AbstractHookable::$configuration type has no value type specified in iterable type array.

Check failure on line 17 in src/TwigHooks/src/Hookable/AbstractHookable.php

View workflow job for this annotation

GitHub Actions / Continuous Integration (PHP 8.2 / Symfony ^6.4)

Property Sylius\TwigHooks\Hookable\AbstractHookable::$configuration type has no value type specified in iterable type array.

Check failure on line 17 in src/TwigHooks/src/Hookable/AbstractHookable.php

View workflow job for this annotation

GitHub Actions / Continuous Integration (PHP 8.3 / Symfony ^5.4)

Property Sylius\TwigHooks\Hookable\AbstractHookable::$configuration type has no value type specified in iterable type array.

Check failure on line 17 in src/TwigHooks/src/Hookable/AbstractHookable.php

View workflow job for this annotation

GitHub Actions / Continuous Integration (PHP 8.3 / Symfony ^6.4)

Property Sylius\TwigHooks\Hookable\AbstractHookable::$configuration type has no value type specified in iterable type array.

private readonly ?int $priority;

public const DEFAULT_PRIORITY = 0;

/**
* @param array<string, mixed> $context
* @param array<string, mixed> $configuration
*/
public function __construct (
public readonly string $hookName,
public readonly string $name,
public readonly string $target,
public readonly array $context = [],
public readonly array $configuration = [],
protected readonly ?int $priority = null,
protected readonly ?bool $enabled = null,
string $hookName,
string $name,
array $context = [],
array $configuration = [],
?int $priority = null,
) {
$this->id = sprintf('%s#%s', $hookName, $name);
$this->hookName = $hookName;
$this->name = $name;
$this->context = $context;
$this->configuration = $configuration;
$this->priority = $priority;
}

public function getId(): string
{
return sprintf('%s#%s', $this->hookName, $this->name);
}

public function getPriority(): int
public function priority(): int
{
return $this->priority ?? self::DEFAULT_PRIORITY;
}

public function isEnabled(): bool
{
return $this->enabled ?? true;
}

abstract public function overwriteWith(self $hookable): self;

abstract public function getType(): string;

/**
* @return array<string, mixed>
*/
Expand Down
29 changes: 29 additions & 0 deletions src/TwigHooks/src/Hookable/DisabledHookable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace Sylius\TwigHooks\Hookable;

class DisabledHookable extends AbstractHookable
{
public function __construct(
string $hookName,
string $name,
array $context = [],
array $configuration = [],
?int $priority = null,
) {
parent::__construct($hookName, $name, $context, $configuration, $priority);
}

public function toArray(): array
{
return [
'hookName' => $this->hookName,
'name' => $this->name,
'context' => $this->context,
'configuration' => $this->configuration,
'priority' => $this->priority(),
];
}
}
56 changes: 9 additions & 47 deletions src/TwigHooks/src/Hookable/HookableComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,71 +6,33 @@

class HookableComponent extends AbstractHookable
{
public const TYPE_NAME = 'component';

/**
* @param array<string, mixed> $props
* @param array<string, mixed> $context
* @param array<string, mixed> $configuration
*/
public function __construct (
public readonly string $hookName,
public readonly string $name,
public readonly string $target,
string $hookName,
string $name,
public readonly string $component,
public readonly array $props = [],
public readonly array $context = [],
public readonly array $configuration = [],
protected readonly ?int $priority = null,
protected readonly ?bool $enabled = null,
array $context = [],
array $configuration = [],
?int $priority = null,
) {
}

public function getType(): string
{
return self::TYPE_NAME;
}

/**
* @return array<string, mixed>
*/
public function getProps(): array
{
return $this->props;
}

public function overwriteWith(AbstractHookable $hookable): AbstractHookable
{
if ($hookable->name !== $this->name) {
throw new \InvalidArgumentException(sprintf(
'Cannot overwrite hookable with different name. Expected "%s", got "%s".',
$this->name,
$hookable->name,
));
}

return new self(
$hookable->hookName,
$this->name,
$hookable->target,
$hookable instanceof HookableComponent ? array_merge($this->props, $hookable->props) : [],
array_merge($this->context, $hookable->context),
array_merge($this->configuration, $hookable->configuration),
$hookable->getPriority(),
$hookable->isEnabled(),
);
parent::__construct($hookName, $name, $context, $configuration, $priority);
}

public function toArray(): array
{
return [
'hookName' => $this->hookName,
'name' => $this->name,
'target' => $this->target,
'component' => $this->component,
'props' => $this->props,
'context' => $this->context,
'configuration' => $this->configuration,
'priority' => $this->getPriority(),
'enabled' => $this->isEnabled(),
'priority' => $this->priority(),
];
}
}
Loading

0 comments on commit da72e2b

Please sign in to comment.