]> git.mxchange.org Git - friendica.git/commitdiff
Add tests for InstanceManager and remove Decorator hook logic (avoid complex Dice...
authorPhilipp <admin@philipp.info>
Sun, 16 Jul 2023 22:10:15 +0000 (00:10 +0200)
committerPhilipp <admin@philipp.info>
Sun, 16 Jul 2023 22:10:15 +0000 (00:10 +0200)
15 files changed:
doc/AddonsStrategyDecorator.md [deleted file]
doc/StrategyHooks.md [new file with mode: 0644]
src/Core/Hooks/Capabilities/BehavioralHookType.php [new file with mode: 0644]
src/Core/Hooks/Capabilities/HookType.php [deleted file]
src/Core/Hooks/Capabilities/ICanCreateInstances.php
src/Core/Hooks/Capabilities/ICanRegisterInstances.php
src/Core/Hooks/Model/DiceInstanceManager.php
src/Core/Hooks/Util/HookFileManager.php
src/Core/Logger/Factory/Logger.php
static/hooks.config.php
tests/Util/Hooks/InstanceMocks/FakeInstance.php
tests/Util/Hooks/InstanceMocks/FakeInstanceDecorator.php
tests/src/Core/Addon/Model/AddonLoaderTest.php
tests/src/Core/Hooks/Model/InstanceManagerTest.php
tests/src/Core/Hooks/Util/HookFileManagerTest.php

diff --git a/doc/AddonsStrategyDecorator.md b/doc/AddonsStrategyDecorator.md
deleted file mode 100644 (file)
index 51456da..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-Friendica strategy and decorator Hooks
-===========================================
-
-* [Home](help)
-
-## Strategy hooks
-
-This type of hook is based on the [Strategy Design Pattern](https://refactoring.guru/design-patterns/strategy).
-
-A strategy class defines a possible implementation of a given interface based on a unique name.
-Every name is possible as long as it's unique and not `null`.
-Using an empty name (`''`) is possible as well and should be used as the "default" implementation.
-To register a strategy, use the [`ICanRegisterInstance`](../src/Core/Hooks/Capabilities/ICanRegisterInstances.php) interface.
-
-After registration, a caller can automatically create this instance with the [`ICanCreateInstances`](../src/Core/Hooks/Capabilities/ICanCreateInstances.php) interface and the chosen name.
-
-This is useful in case there are different, possible implementations for the same purpose, like for logging, locking, caching, ...
-
-Normally, a config entry is used to choose the right implementation at runtime.
-And if no config entry is set, the "default" implementation should be used.
-
-### Example
-
-```php
-interface ExampleInterface
-{
-       public function testMethod();
-}
-
-public class ConcreteClassA implements ExampleInterface
-{
-       public function testMethod()
-       {
-               echo "concrete class A";
-       }
-}
-
-public class ConcreteClassB implements ExampleInterface
-{
-       public function testMethod()
-       {
-               echo "concrete class B";
-       }
-}
-
-/** @var \Friendica\Core\Hooks\Capabilities\ICanRegisterInstances $instanceRegister */
-$instanceRegister->registerStrategy(ExampleInterface::class, ConcreteClassA::class, 'A');
-$instanceRegister->registerStrategy(ExampleInterface::class, ConcreteClassB::class, 'B');
-
-/** @var \Friendica\Core\Hooks\Capabilities\ICanCreateInstances $instanceManager */
-/** @var ConcreteClassA $concreteClass */
-$concreteClass = $instanceManager->createWithName(ExampleInterface::class, 'A');
-
-$concreteClass->testMethod();
-// output:
-// "concrete class A";
-```
-
-## Decorator hooks
-
-This type of hook is based on the [Decorator Design Pattern](https://refactoring.guru/design-patterns/decorator).
-
-A decorator class extends a given strategy instance (see  [Strategy hooks](#strategy-hooks)]).
-To register a decorator, use the [`ICanRegisterInstance`](../src/Core/Hooks/Capabilities/ICanRegisterInstances.php) interface.
-
-After registration, a caller can automatically create an instance with the [`ICanCreateInstances`](../src/Core/Hooks/Capabilities/ICanCreateInstances.php) interface and the decorator will wrap its logic around the call.
-
-This is useful in case you want to extend a given class but the given class isn't responsible for these business logic. Or you want to extend an interface without knowing the concrete implementation.
-For example profiling logger calls, Friendica is using a [`ProfilerLogger`](../src/Core/Logger/Type/ProfilerLogger.php), which wraps all other logging implementations and traces each log call.
-
-Normally, a config entry is used to enable/disable decorator.
-
-### Example
-
-```php
-interface ExampleInterface
-{
-       public function testMethod();
-}
-
-public class ConcreteClassA implements ExampleInterface
-{
-       public function testMethod()
-       {
-               echo "concrete class A";
-       }
-}
-
-public class DecoratorClassA implements ExampleInterface
-{
-       /** @var ExampleInterface */
-       protected $example;
-
-       public function __construct(ExampleInterface $example)
-       {
-               $this->example = $example;
-       }
-
-       public function testMethod()
-       {
-               echo "decorated!\n";
-               $this->example->testMethod();
-       }
-}
-
-/** @var \Friendica\Core\Hooks\Capabilities\ICanRegisterInstances $instanceRegister */
-$instanceRegister->registerStrategy(ExampleInterface::class, ConcreteClassA::class, 'A');
-$instanceRegister->registerDecorator(ExampleInterface::class, DecoratorClassA::class);
-
-/** @var \Friendica\Core\Hooks\Capabilities\ICanCreateInstances $instanceManager */
-/** @var ConcreteClassA $concreteClass */
-$concreteClass = $instanceManager->createWithName(ExampleInterface::class, 'A');
-
-$concreteClass->testMethod();
-// output:
-// "decorated!"
-// "concrete class A";
-```
-
-## hooks.config.php
-
-To avoid registering all strategies and decorators manually inside the code, Friendica introduced the [`hooks.config.php`](../static/hooks.config.php) file.
-
-There, you can register all kind of strategies and decorators in one file.
-
-### [`HookType::STRATEGY`](../src/Core/Hooks/Capabilities/HookType.php)
-
-For each given interface, a list of key-value pairs can be set, where the key is the concrete implementation class and the value is an array of unique names.
-
-### [`HookType::DECORATOR`](../src/Core/Hooks/Capabilities/HookType.php)
-
-For each given interface, a list of concrete decorator classes can be set.
-
-### Example
-
-```php
-use Friendica\Core\Hooks\Capabilities\HookType as H;
-
-return [
-       H::STRATEGY  => [
-               ExampleInterface::class => [
-                       ConcreteClassA::class => ['A'],
-                       ConcreteClassB::class => ['B'],
-               ],
-       ],
-       H::DECORATOR => [
-               ExampleInterface::class => [
-                       DecoratorClassA::class,
-               ],
-       ],
-];
-```
-
-## Addons
-
-The hook logic is useful for decoupling the Friendica core logic, but its primary goal is to modularize Friendica in creating addons.
-
-Therefor you can either use the interfaces directly as shown above, or you can place your own `hooks.config.php` file inside a `static` directory directly under your addon core directory.
-Friendica will automatically search these config files for each **activated** addon and register the given hooks.
diff --git a/doc/StrategyHooks.md b/doc/StrategyHooks.md
new file mode 100644 (file)
index 0000000..cb355f9
--- /dev/null
@@ -0,0 +1,89 @@
+Friendica strategy Hooks
+===========================================
+
+* [Home](help)
+
+## Strategy hooks
+
+This type of hook is based on the [Strategy Design Pattern](https://refactoring.guru/design-patterns/strategy).
+
+A strategy class defines a possible implementation of a given interface based on a unique name.
+Every name is possible as long as it's unique and not `null`.
+Using an empty name (`''`) is possible as well and should be used as the "default" implementation.
+To register a strategy, use the [`ICanRegisterInstance`](../src/Core/Hooks/Capabilities/ICanRegisterInstances.php) interface.
+
+After registration, a caller can automatically create this instance with the [`ICanCreateInstances`](../src/Core/Hooks/Capabilities/ICanCreateInstances.php) interface and the chosen name.
+
+This is useful in case there are different, possible implementations for the same purpose, like for logging, locking, caching, ...
+
+Normally, a config entry is used to choose the right implementation at runtime.
+And if no config entry is set, the "default" implementation should be used.
+
+### Example
+
+```php
+interface ExampleInterface
+{
+       public function testMethod();
+}
+
+public class ConcreteClassA implements ExampleInterface
+{
+       public function testMethod()
+       {
+               echo "concrete class A";
+       }
+}
+
+public class ConcreteClassB implements ExampleInterface
+{
+       public function testMethod()
+       {
+               echo "concrete class B";
+       }
+}
+
+/** @var \Friendica\Core\Hooks\Capabilities\ICanRegisterInstances $instanceRegister */
+$instanceRegister->registerStrategy(ExampleInterface::class, ConcreteClassA::class, 'A');
+$instanceRegister->registerStrategy(ExampleInterface::class, ConcreteClassB::class, 'B');
+
+/** @var \Friendica\Core\Hooks\Capabilities\ICanCreateInstances $instanceManager */
+/** @var ConcreteClassA $concreteClass */
+$concreteClass = $instanceManager->create(ExampleInterface::class, 'A');
+
+$concreteClass->testMethod();
+// output:
+// "concrete class A";
+```
+
+## hooks.config.php
+
+To avoid registering all strategies manually inside the code, Friendica introduced the [`hooks.config.php`](../static/hooks.config.php) file.
+
+There, you can register all kind of strategies  in one file.
+
+### [`HookType::STRATEGY`](../src/Core/Hooks/Capabilities/HookType.php)
+
+For each given interface, a list of key-value pairs can be set, where the key is the concrete implementation class and the value is an array of unique names.
+
+### Example
+
+```php
+use Friendica\Core\Hooks\Capabilities\BehavioralHookType as H;
+
+return [
+       H::STRATEGY  => [
+               ExampleInterface::class => [
+                       ConcreteClassA::class => ['A'],
+                       ConcreteClassB::class => ['B'],
+               ],
+       ],
+];
+```
+
+## Addons
+
+The hook logic is useful for decoupling the Friendica core logic, but its primary goal is to modularize Friendica in creating addons.
+
+Therefor you can either use the interfaces directly as shown above, or you can place your own `hooks.config.php` file inside a `static` directory directly under your addon core directory.
+Friendica will automatically search these config files for each **activated** addon and register the given hooks.
diff --git a/src/Core/Hooks/Capabilities/BehavioralHookType.php b/src/Core/Hooks/Capabilities/BehavioralHookType.php
new file mode 100644 (file)
index 0000000..6336406
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2023, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Core\Hooks\Capabilities;
+
+/**
+ * An enum of hook types, based on behavioral design patterns
+ * @see https://refactoring.guru/design-patterns/behavioral-patterns
+ */
+interface BehavioralHookType
+{
+       /**
+        * Defines the key for the list of strategy-hooks.
+        *
+        * @see https://refactoring.guru/design-patterns/strategy
+        */
+       const STRATEGY = 'strategy';
+       const EVENT    = 'event';
+}
diff --git a/src/Core/Hooks/Capabilities/HookType.php b/src/Core/Hooks/Capabilities/HookType.php
deleted file mode 100644 (file)
index 6fea41e..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2023, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Core\Hooks\Capabilities;
-
-interface HookType
-{
-       /**
-        * Defines the key for the list of strategy-hooks.
-        *
-        * @see https://refactoring.guru/design-patterns/strategy
-        */
-       const STRATEGY = 'strategy';
-       /**
-        * Defines the key for the list of decorator-hooks.
-        *
-        * @see  https://refactoring.guru/design-patterns/decorator
-        */
-       const DECORATOR = 'decorator';
-       const EVENT     = 'event';
-}
index 9714304746d6e88ef01da3d9b3c71d92388669af..f2e4b8b0a1761e12ed789cb5443e4ef242ea6e00 100644 (file)
@@ -22,7 +22,7 @@
 namespace Friendica\Core\Hooks\Capabilities;
 
 /**
- * creates special instance and decorator treatments for given classes
+ * creates special instances for given classes
  */
 interface ICanCreateInstances
 {
@@ -31,27 +31,11 @@ interface ICanCreateInstances
         *
         * The instance will be build based on the registered strategy and the (unique) name
         *
-        * In case, there are registered decorators for this class as well, all decorators of the list will be wrapped
-        * around the instance before returning it
-        *
         * @param string $class     The fully-qualified name of the given class or interface which will get returned
         * @param string $name      An arbitrary identifier to find a concrete instance strategy.
         * @param array  $arguments Additional arguments, which can be passed to the constructor of "$class" at runtime
         *
         * @return object The concrete instance of the type "$class"
         */
-       public function createWithName(string $class, string $name, array $arguments = []): object;
-
-       /**
-        * Returns a new instance of a given class
-        *
-        * In case, there are registered decorators for this class as well, all decorators of the list will be wrapped
-        * around the instance before returning it
-        *
-        * @param string $class     The fully-qualified name of the given class or interface which will get returned
-        * @param array  $arguments Additional arguments, which can be passed to the constructor of "$class" at runtime
-        *
-        * @return object The concrete instance of the type "$class"
-        */
-       public function create(string $class, array $arguments = []): object;
+       public function create(string $class, string $name, array $arguments = []): object;
 }
index 23a77ab35b18f693bd8c735beafb8fb49735d7ff..f7689bbee7726697d3a20d40236df7d95596a238 100644 (file)
@@ -24,7 +24,7 @@ namespace Friendica\Core\Hooks\Capabilities;
 use Friendica\Core\Hooks\Exceptions\HookRegisterArgumentException;
 
 /**
- * Register strategies and decorator/treatment handling for given classes
+ * Register strategies for given classes
  */
 interface ICanRegisterInstances
 {
@@ -43,21 +43,4 @@ interface ICanRegisterInstances
         * @throws HookRegisterArgumentException in case the given class for the interface isn't valid or already set
         */
        public function registerStrategy(string $interface, string $class, ?string $name = null): self;
-
-       /**
-        * Register a new decorator for a given class or interface
-        *
-        * @see  https://refactoring.guru/design-patterns/decorator
-        *
-        * @note Decorator attach new behaviors to classes without changing them or without letting them know about it.
-        *
-        * @param string $class          The fully-qualified class or interface name, which gets decorated by a class
-        * @param string $decoratorClass The fully-qualified name of the class which mimics the given class or interface and adds new functionality
-        *                               A placeholder for dependencies is possible as well
-        *
-        * @return $this This interface for chain-calls
-        *
-        * @throws HookRegisterArgumentException in case the given class for the class or interface isn't valid
-        */
-       public function registerDecorator(string $class, string $decoratorClass): self;
 }
index efbee444aac5344493f367333ef18e3092907fc1..7c35dfe4df2265eddd123e629bc6ad17fc87696b 100644 (file)
@@ -36,7 +36,6 @@ use Friendica\Core\Hooks\Util\HookFileManager;
 class DiceInstanceManager implements ICanCreateInstances, ICanRegisterInstances
 {
        protected $instance  = [];
-       protected $decorator = [];
 
        /** @var Dice */
        protected $dice;
@@ -60,52 +59,12 @@ class DiceInstanceManager implements ICanCreateInstances, ICanRegisterInstances
        }
 
        /** {@inheritDoc} */
-       public function registerDecorator(string $class, string $decoratorClass): ICanRegisterInstances
-       {
-               $this->decorator[$class][] = $decoratorClass;
-
-               return $this;
-       }
-
-       /** {@inheritDoc} */
-       public function create(string $class, array $arguments = []): object
-       {
-               $instanceClassName = $class;
-               $instanceRule      = $this->dice->getRule($instanceClassName) ?? [];
-
-               $instanceRule = array_replace_recursive($instanceRule, [
-                       'constructParams' => $arguments,
-               ]);
-
-               $this->dice = $this->dice->addRule($instanceClassName, $instanceRule);
-
-               foreach ($this->decorator[$class] ?? [] as $decorator) {
-                       $dependencyRule = $this->dice->getRule($decorator);
-                       for ($i = 0; $i < count($dependencyRule['call'] ?? []); $i++) {
-                               $dependencyRule['call'][$i][1] = [[Dice::INSTANCE => $instanceClassName]];
-                       }
-                       $dependencyRule['constructParams'] = $arguments;
-                       $dependencyRule['substitutions']   = [
-                               $class => $instanceClassName,
-                       ];
-
-                       $this->dice = $this->dice->addRule($decorator, $dependencyRule);
-
-                       $instanceClassName = $decorator;
-               }
-
-               return $this->dice->create($instanceClassName);
-       }
-
-       /** {@inheritDoc} */
-       public function createWithName(string $class, string $name, array $arguments = []): object
+       public function create(string $class, string $name, array $arguments = []): object
        {
                if (empty($this->instance[$class][$name])) {
                        throw new HookInstanceException(sprintf('The class with the name %s isn\'t registered for the class or interface %s', $name, $class));
                }
 
-               $instanceClassName = $this->instance[$class][$name];
-
-               return $this->create($instanceClassName, $arguments);
+               return $this->dice->create($this->instance[$class][$name], $arguments);
        }
 }
index e25641e367a33a5d9651461ba27f717150dcf845..b83f2b49c600df5446b37e8cad94414c2fe46034 100644 (file)
@@ -22,7 +22,7 @@
 namespace Friendica\Core\Hooks\Util;
 
 use Friendica\Core\Addon\Capabilities\ICanLoadAddons;
-use Friendica\Core\Hooks\Capabilities\HookType;
+use Friendica\Core\Hooks\Capabilities\BehavioralHookType;
 use Friendica\Core\Hooks\Capabilities\ICanRegisterInstances;
 use Friendica\Core\Hooks\Exceptions\HookConfigException;
 
@@ -63,7 +63,7 @@ class HookFileManager
 
                foreach ($this->hookConfig as $hookType => $classList) {
                        switch ($hookType) {
-                               case HookType::STRATEGY:
+                               case BehavioralHookType::STRATEGY:
                                        foreach ($classList as $interface => $strategy) {
                                                foreach ($strategy as $dependencyName => $names) {
                                                        if (is_array($names)) {
@@ -76,17 +76,6 @@ class HookFileManager
                                                }
                                        }
                                        break;
-                               case HookType::DECORATOR:
-                                       foreach ($classList as $interface => $decorators) {
-                                               if (is_array($decorators)) {
-                                                       foreach ($decorators as $decorator) {
-                                                               $instanceRegister->registerDecorator($interface, $decorator);
-                                                       }
-                                               } else {
-                                                       $instanceRegister->registerDecorator($interface, $decorators);
-                                               }
-                                       }
-                                       break;
                        }
                }
        }
index 3fde878a34d086202995adc5984506e2714635c8..81f8887efcca04152ef8c9af943a534240df5f51 100644 (file)
@@ -24,6 +24,8 @@ namespace Friendica\Core\Logger\Factory;
 use Friendica\Core\Config\Capability\IManageConfigValues;
 use Friendica\Core\Hooks\Capabilities\ICanCreateInstances;
 use Friendica\Core\Logger\Capabilities\LogChannel;
+use Friendica\Core\Logger\Type\ProfilerLogger as ProfilerLoggerClass;
+use Friendica\Util\Profiler;
 use Psr\Log\LoggerInterface;
 use Psr\Log\NullLogger;
 use Throwable;
@@ -41,7 +43,7 @@ class Logger
                $this->channel = $channel;
        }
 
-       public function create(ICanCreateInstances $createInstances, IManageConfigValues $config): LoggerInterface
+       public function create(ICanCreateInstances $createInstances, IManageConfigValues $config, Profiler $profiler): LoggerInterface
        {
                if (empty($config->get('system', 'debugging') ?? false)) {
                        return new NullLogger();
@@ -50,7 +52,13 @@ class Logger
                $name = $config->get('system', 'logger_config') ?? '';
 
                try {
-                       return $createInstances->createWithName(LoggerInterface::class, $name, [$this->channel]);
+                       /** @var LoggerInterface $logger */
+                       $logger = $createInstances->create(LoggerInterface::class, $name, [$this->channel]);
+                       if ($config->get('system', 'profiling') ?? false) {
+                               return new ProfilerLoggerClass($logger, $profiler);
+                       } else {
+                               return $logger;
+                       }
                } catch (Throwable $e) {
                        // No logger ...
                        return new NullLogger();
index bc235913c5877b607364eb2311601be2ff8e2cd0..d46762f87113069eb72a1a379117be1ad5bf747e 100644 (file)
@@ -19,7 +19,7 @@
  *
  */
 
-use Friendica\Core\Hooks\Capabilities\HookType as H;
+use Friendica\Core\Hooks\Capabilities\BehavioralHookType as H;
 use Friendica\Core\Logger\Type;
 use Psr\Log;
 
@@ -31,9 +31,4 @@ return [
                        Type\StreamLogger::class => ['stream'],
                ],
        ],
-       H::DECORATOR => [
-               Log\LoggerInterface::class => [
-                       Type\ProfilerLogger::class,
-               ],
-       ],
 ];
index 9a0e9dd6faa35c07dcb500b6222e8790affc7151..64fe2c5adf58d2d2eaa7064c712e3197e9c68ffb 100644 (file)
@@ -21,7 +21,7 @@
 
 namespace Friendica\Test\Util\Hooks\InstanceMocks;
 
-class FakeInstance
+class FakeInstance implements IAmADecoratedInterface
 {
        protected $aText = null;
        protected $cBool = null;
@@ -39,6 +39,8 @@ class FakeInstance
                $this->aText = $aText;
                $this->cBool = $cBool;
                $this->bText = $bText;
+
+               return '';
        }
 
        public function getAText(): ?string
index af4db96c442f34850c8b36cb7eb6c7ccb339712a..40ab78a25730f6aae21da8e1451b4e3110e4ea9d 100644 (file)
@@ -25,14 +25,14 @@ class FakeInstanceDecorator implements IAmADecoratedInterface
 {
        public static $countInstance = 0;
 
+       const PREFIX = 'prefix1';
+
        /** @var IAmADecoratedInterface */
        protected $orig;
-       protected $prefix = '';
 
-       public function __construct(IAmADecoratedInterface $orig, string $prefix = '')
+       public function __construct(IAmADecoratedInterface $orig)
        {
                $this->orig   = $orig;
-               $this->prefix = $prefix;
 
                self::$countInstance++;
        }
@@ -44,16 +44,16 @@ class FakeInstanceDecorator implements IAmADecoratedInterface
 
        public function getAText(): ?string
        {
-               return $this->prefix . $this->orig->getAText();
+               return static::PREFIX . $this->orig->getAText();
        }
 
        public function getBText(): ?string
        {
-               return $this->prefix . $this->orig->getBText();
+               return static::PREFIX . $this->orig->getBText();
        }
 
        public function getCBool(): ?bool
        {
-               return $this->prefix . $this->orig->getCBool();
+               return static::PREFIX . $this->orig->getCBool();
        }
 }
index 4496cd42f60c8f84ef19a119b76403c065b6c52f..be125535f38a5681653e78dbc2294ae3b0a761c2 100644 (file)
@@ -54,7 +54,7 @@ class AddonLoaderTest extends MockedTest
 <?php
 
 return [
-       \Friendica\Core\Hooks\Capabilities\HookType::STRATEGY => [
+       \Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
                \Psr\Log\LoggerInterface::class => [
                        \Psr\Log\NullLogger::class => [''],
                ],
@@ -79,7 +79,7 @@ EOF;
                                        'addon/testaddon1/static/hooks.config.php' => $this->content,
                                ],
                                'assertion' => [
-                                       \Friendica\Core\Hooks\Capabilities\HookType::STRATEGY => [
+                                       \Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
                                                \Psr\Log\LoggerInterface::class => [
                                                        \Psr\Log\NullLogger::class => [''],
                                                ],
@@ -94,7 +94,7 @@ EOF;
                                        'addon/testaddon2/static/hooks.config.php' => $this->content,
                                ],
                                'assertion' => [
-                                       \Friendica\Core\Hooks\Capabilities\HookType::STRATEGY => [
+                                       \Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
                                                \Psr\Log\LoggerInterface::class => [
                                                        \Psr\Log\NullLogger::class => ['', ''],
                                                ],
@@ -118,7 +118,7 @@ EOF;
                                        'addon/testaddon2/static/hooks.config.php' => $this->content,
                                ],
                                'assertion' => [
-                                       \Friendica\Core\Hooks\Capabilities\HookType::STRATEGY => [
+                                       \Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
                                                \Psr\Log\LoggerInterface::class => [
                                                        \Psr\Log\NullLogger::class => [''],
                                                ],
index 200500d63e8b49b037ff09b7e09ab804a1f866a8..de2bdc6b834cc9c3c8302972586e32f6bca04ba7 100644 (file)
 namespace Friendica\Test\src\Core\Hooks\Model;
 
 use Dice\Dice;
+use Friendica\Core\Hooks\Exceptions\HookInstanceException;
+use Friendica\Core\Hooks\Exceptions\HookRegisterArgumentException;
 use Friendica\Core\Hooks\Model\DiceInstanceManager;
+use Friendica\Core\Hooks\Util\HookFileManager;
 use Friendica\Test\MockedTest;
 use Friendica\Test\Util\Hooks\InstanceMocks\FakeInstance;
 use Friendica\Test\Util\Hooks\InstanceMocks\FakeInstanceDecorator;
 use Friendica\Test\Util\Hooks\InstanceMocks\IAmADecoratedInterface;
+use Mockery\MockInterface;
 
 class InstanceManagerTest extends MockedTest
 {
-       public function testEqualButNotSameInstance()
-       {
-               $instance = new DiceInstanceManager(new Dice());
-
-               $instance->registerStrategy(IAmADecoratedInterface::class, 'fake', FakeInstance::class);
+       /** @var HookFileManager|MockInterface */
+       protected $hookFileManager;
 
-               $getInstanceA = $instance->createWithName(IAmADecoratedInterface::class, 'fake');
-               $getInstanceB = $instance->createWithName(IAmADecoratedInterface::class, 'fake');
+       protected function setUp(): void
+       {
+               parent::setUp();
 
-               self::assertEquals($getInstanceA, $getInstanceB);
-               self::assertNotSame($getInstanceA, $getInstanceB);
+               $this->hookFileManager = \Mockery::mock(HookFileManager::class);
+               $this->hookFileManager->shouldReceive('setupHooks')->withAnyArgs();
        }
 
        protected function tearDown(): void
@@ -50,6 +52,19 @@ class InstanceManagerTest extends MockedTest
                parent::tearDown();
        }
 
+       public function testEqualButNotSameInstance()
+       {
+               $instance = new DiceInstanceManager(new Dice(), $this->hookFileManager);
+
+               $instance->registerStrategy(IAmADecoratedInterface::class, FakeInstance::class, 'fake');
+
+               $getInstanceA = $instance->create(IAmADecoratedInterface::class, 'fake');
+               $getInstanceB = $instance->create(IAmADecoratedInterface::class, 'fake');
+
+               self::assertEquals($getInstanceA, $getInstanceB);
+               self::assertNotSame($getInstanceA, $getInstanceB);
+       }
+
        public function dataTests(): array
        {
                return [
@@ -79,9 +94,9 @@ class InstanceManagerTest extends MockedTest
        /**
         * @dataProvider dataTests
         */
-       public function testInstanceWithConstructorAnonymArgs(string $aString = null, bool $cBool = null, string $bString = null)
+       public function testInstanceWithArgs(string $aString = null, bool $cBool = null, string $bString = null)
        {
-               $instance = new DiceInstanceManager(new Dice());
+               $instance = new DiceInstanceManager(new Dice(), $this->hookFileManager);
 
                $args = [];
 
@@ -95,12 +110,12 @@ class InstanceManagerTest extends MockedTest
                        $args[] = $cBool;
                }
 
-               $instance->registerStrategy(IAmADecoratedInterface::class, 'fake', FakeInstance::class, $args);
+               $instance->registerStrategy(IAmADecoratedInterface::class, FakeInstance::class, 'fake');
 
                /** @var IAmADecoratedInterface $getInstanceA */
-               $getInstanceA = $instance->createWithName(IAmADecoratedInterface::class, 'fake');
+               $getInstanceA = $instance->create(IAmADecoratedInterface::class, 'fake', $args);
                /** @var IAmADecoratedInterface $getInstanceB */
-               $getInstanceB = $instance->createWithName(IAmADecoratedInterface::class, 'fake');
+               $getInstanceB = $instance->create(IAmADecoratedInterface::class, 'fake', $args);
 
                self::assertEquals($getInstanceA, $getInstanceB);
                self::assertNotSame($getInstanceA, $getInstanceB);
@@ -115,25 +130,29 @@ class InstanceManagerTest extends MockedTest
        /**
         * @dataProvider dataTests
         */
-       public function testInstanceConstructorAndGetInstanceWithNamedArgs(string $aString = null, bool $cBool = null, string $bString = null)
+       public function testInstanceWithTwoStrategies(string $aString = null, bool $cBool = null, string $bString = null)
        {
-               $instance = new DiceInstanceManager(new Dice());
+               $instance = new DiceInstanceManager(new Dice(), $this->hookFileManager);
 
                $args = [];
 
                if (isset($aString)) {
                        $args[] = $aString;
                }
+               if (isset($bString)) {
+                       $args[] = $bString;
+               }
                if (isset($cBool)) {
                        $args[] = $cBool;
                }
 
-               $instance->registerStrategy(IAmADecoratedInterface::class, 'fake', FakeInstance::class, $args);
+               $instance->registerStrategy(IAmADecoratedInterface::class, FakeInstance::class, 'fake');
+               $instance->registerStrategy(IAmADecoratedInterface::class, FakeInstance::class, 'fake23');
 
                /** @var IAmADecoratedInterface $getInstanceA */
-               $getInstanceA = $instance->createWithName(IAmADecoratedInterface::class, 'fake', [$bString]);
+               $getInstanceA = $instance->create(IAmADecoratedInterface::class, 'fake', $args);
                /** @var IAmADecoratedInterface $getInstanceB */
-               $getInstanceB = $instance->createWithName(IAmADecoratedInterface::class, 'fake', [$bString]);
+               $getInstanceB = $instance->create(IAmADecoratedInterface::class, 'fake23', $args);
 
                self::assertEquals($getInstanceA, $getInstanceB);
                self::assertNotSame($getInstanceA, $getInstanceB);
@@ -146,113 +165,74 @@ class InstanceManagerTest extends MockedTest
        }
 
        /**
-        * @dataProvider dataTests
+        * Test the exception in case the interface was already registered
         */
-       public function testInstanceWithTwoStrategies(string $aString = null, bool $cBool = null, string $bString = null)
+       public function testDoubleRegister()
        {
-               $instance = new DiceInstanceManager(new Dice());
-
-               $args = [];
-
-               if (isset($aString)) {
-                       $args[] = $aString;
-               }
-               if (isset($cBool)) {
-                       $args[] = $cBool;
-               }
+               self::expectException(HookRegisterArgumentException::class);
+               self::expectExceptionMessage(sprintf('A class with the name %s is already set for the interface %s', 'fake', IAmADecoratedInterface::class));
 
-               $instance->registerStrategy(IAmADecoratedInterface::class, 'fake', FakeInstance::class, $args);
-               $instance->registerStrategy(IAmADecoratedInterface::class, 'fake23', FakeInstance::class, $args);
+               $instance = new DiceInstanceManager(new Dice(), $this->hookFileManager);
+               $instance->registerStrategy(IAmADecoratedInterface::class, FakeInstance::class, 'fake');
+               $instance->registerStrategy(IAmADecoratedInterface::class, FakeInstance::class, 'fake');
+       }
 
-               /** @var IAmADecoratedInterface $getInstanceA */
-               $getInstanceA = $instance->createWithName(IAmADecoratedInterface::class, 'fake', [$bString]);
-               /** @var IAmADecoratedInterface $getInstanceB */
-               $getInstanceB = $instance->createWithName(IAmADecoratedInterface::class, 'fake23', [$bString]);
+       /**
+        * Test the exception in case the name of the instance isn't registered
+        */
+       public function testWrongInstanceName()
+       {
+               self::expectException(HookInstanceException::class      );
+               self::expectExceptionMessage(sprintf('The class with the name %s isn\'t registered for the class or interface %s', 'fake', IAmADecoratedInterface::class));
 
-               self::assertEquals($getInstanceA, $getInstanceB);
-               self::assertNotSame($getInstanceA, $getInstanceB);
-               self::assertEquals($aString, $getInstanceA->getAText());
-               self::assertEquals($aString, $getInstanceB->getAText());
-               self::assertEquals($bString, $getInstanceA->getBText());
-               self::assertEquals($bString, $getInstanceB->getBText());
-               self::assertEquals($cBool, $getInstanceA->getCBool());
-               self::assertEquals($cBool, $getInstanceB->getCBool());
+               $instance = new DiceInstanceManager(new Dice(), $this->hookFileManager);
+               $instance->create(IAmADecoratedInterface::class, 'fake');
        }
 
        /**
+        * Test in case there are already some rules
+        *
         * @dataProvider dataTests
         */
-       public function testDecorator(string $aString = null, bool $cBool = null, string $bString = null)
+       public function testWithGivenRules(string $aString = null, bool $cBool = null, string $bString = null)
        {
-               $instance = new DiceInstanceManager(new Dice());
-
                $args = [];
 
                if (isset($aString)) {
                        $args[] = $aString;
                }
-               if (isset($cBool)) {
-                       $args[] = $cBool;
+               if (isset($bString)) {
+                       $args[] = $bString;
                }
 
-               $prefix = 'prefix1';
-
-               $instance->registerStrategy(IAmADecoratedInterface::class, 'fake', FakeInstance::class, $args);
-               $instance->registerStrategy(IAmADecoratedInterface::class, 'fake23', FakeInstance::class, $args);
-               $instance->registerDecorator(IAmADecoratedInterface::class, FakeInstanceDecorator::class, [$prefix]);
-
-               /** @var IAmADecoratedInterface $getInstanceA */
-               $getInstanceA = $instance->createWithName(IAmADecoratedInterface::class, 'fake', [$bString]);
-               /** @var IAmADecoratedInterface $getInstanceB */
-               $getInstanceB = $instance->createWithName(IAmADecoratedInterface::class, 'fake23', [$bString]);
-
-               self::assertEquals(2, FakeInstanceDecorator::$countInstance);
-               self::assertEquals($getInstanceA, $getInstanceB);
-               self::assertNotSame($getInstanceA, $getInstanceB);
-               self::assertEquals($prefix . $aString, $getInstanceA->getAText());
-               self::assertEquals($prefix . $aString, $getInstanceB->getAText());
-               self::assertEquals($prefix . $bString, $getInstanceA->getBText());
-               self::assertEquals($prefix . $bString, $getInstanceB->getBText());
-               self::assertEquals($prefix . $cBool, $getInstanceA->getCBool());
-               self::assertEquals($prefix . $cBool, $getInstanceB->getCBool());
-       }
-
-       /**
-        * @dataProvider dataTests
-        */
-       public function testTwoDecoratorWithPrefix(string $aString = null, bool $cBool = null, string $bString = null)
-       {
-               $instance = new DiceInstanceManager(new Dice());
+               $dice = (new Dice())->addRules([
+                       FakeInstance::class => [
+                               'constructParams' => $args,
+                       ],
+               ]);
 
                $args = [];
 
-               if (isset($aString)) {
-                       $args[] = $aString;
-               }
                if (isset($cBool)) {
                        $args[] = $cBool;
                }
 
-               $prefix = 'prefix1';
+               $instance = new DiceInstanceManager($dice, $this->hookFileManager);
 
-               $instance->registerStrategy(IAmADecoratedInterface::class, 'fake', FakeInstance::class, $args);
-               $instance->registerStrategy(IAmADecoratedInterface::class, 'fake23', FakeInstance::class, $args);
-               $instance->registerDecorator(IAmADecoratedInterface::class, FakeInstanceDecorator::class, [$prefix]);
-               $instance->registerDecorator(IAmADecoratedInterface::class, FakeInstanceDecorator::class);
+               $instance->registerStrategy(IAmADecoratedInterface::class, FakeInstance::class, 'fake');
 
                /** @var IAmADecoratedInterface $getInstanceA */
-               $getInstanceA = $instance->createWithName(IAmADecoratedInterface::class, 'fake', [$bString]);
+               $getInstanceA = $instance->create(IAmADecoratedInterface::class, 'fake', $args);
                /** @var IAmADecoratedInterface $getInstanceB */
-               $getInstanceB = $instance->createWithName(IAmADecoratedInterface::class, 'fake23', [$bString]);
+               $getInstanceB = $instance->create(IAmADecoratedInterface::class, 'fake', $args);
 
-               self::assertEquals(4, FakeInstanceDecorator::$countInstance);
                self::assertEquals($getInstanceA, $getInstanceB);
                self::assertNotSame($getInstanceA, $getInstanceB);
-               self::assertEquals($prefix . $aString, $getInstanceA->getAText());
-               self::assertEquals($prefix . $aString, $getInstanceB->getAText());
-               self::assertEquals($prefix . $bString, $getInstanceA->getBText());
-               self::assertEquals($prefix . $bString, $getInstanceB->getBText());
-               self::assertEquals($prefix . $cBool, $getInstanceA->getCBool());
-               self::assertEquals($prefix . $cBool, $getInstanceB->getCBool());
+               self::assertEquals($aString, $getInstanceA->getAText());
+               self::assertEquals($aString, $getInstanceB->getAText());
+               self::assertEquals($bString, $getInstanceA->getBText());
+               self::assertEquals($bString, $getInstanceB->getBText());
+               self::assertEquals($cBool, $getInstanceA->getCBool());
+               self::assertEquals($cBool, $getInstanceB->getCBool());
        }
 }
index cbd9a63b1a010ef55c919f5fdaaaacb3aa859df6..746bfa7ca3589a87168c26b1b8874668e3b0c7e2 100644 (file)
@@ -31,12 +31,12 @@ class HookFileManagerTest extends MockedTest
 <?php
 
 return [
-       \Friendica\Core\Hooks\Capabilities\HookType::STRATEGY => [
+       \Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
                \Psr\Log\LoggerInterface::class => [
                        \Psr\Log\NullLogger::class => [''],
                ],
        ],
-       \Friendica\Core\Hooks\Capabilities\HookType::DECORATOR => [
+       \Friendica\Core\Hooks\Capabilities\BehavioralHookType::DECORATOR => [
                \Psr\Log\LoggerInterface::class => [
                        \Psr\Log\NullLogger::class,
                ],
@@ -56,12 +56,12 @@ EOF,
 <?php
 
 return [
-       \Friendica\Core\Hooks\Capabilities\HookType::STRATEGY => [
+       \Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
                \Psr\Log\LoggerInterface::class => [
                        \Psr\Log\NullLogger::class => '',
                ],
        ],
-       \Friendica\Core\Hooks\Capabilities\HookType::DECORATOR => [
+       \Friendica\Core\Hooks\Capabilities\BehavioralHookType::DECORATOR => [
                \Psr\Log\LoggerInterface::class => \Psr\Log\NullLogger::class,
        ],
 ];
@@ -79,7 +79,7 @@ EOF,
 <?php
 
 return [
-       \Friendica\Core\Hooks\Capabilities\HookType::STRATEGY => [
+       \Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
                \Psr\Log\LoggerInterface::class => [
                        \Psr\Log\NullLogger::class => [''],
                ],
@@ -87,7 +87,7 @@ return [
 ];
 EOF,
                                'addonsArray' => [
-                                       \Friendica\Core\Hooks\Capabilities\HookType::STRATEGY => [
+                                       \Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
                                                \Psr\Log\LoggerInterface::class => [
                                                        \Psr\Log\NullLogger::class => ['null'],
                                                ],
@@ -104,7 +104,7 @@ EOF,
 <?php
 
 return [
-       \Friendica\Core\Hooks\Capabilities\HookType::STRATEGY => [
+       \Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
                \Psr\Log\LoggerInterface::class => [
                        \Psr\Log\NullLogger::class => [''],
                ],
@@ -112,7 +112,7 @@ return [
 ];
 EOF,
                                'addonsArray' => [
-                                       \Friendica\Core\Hooks\Capabilities\HookType::STRATEGY => [
+                                       \Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
                                                \Psr\Log\LoggerInterface::class => [
                                                        \Psr\Log\NullLogger::class => 'null',
                                                ],
@@ -130,7 +130,7 @@ EOF,
 <?php
 
 return [
-       \Friendica\Core\Hooks\Capabilities\HookType::STRATEGY => [
+       \Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
                \Psr\Log\LoggerInterface::class => [
                        \Psr\Log\NullLogger::class => [''],
                ],
@@ -138,7 +138,7 @@ return [
 ];
 EOF,
                                'addonsArray' => [
-                                       \Friendica\Core\Hooks\Capabilities\HookType::STRATEGY => [
+                                       \Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
                                                \Psr\Log\LoggerInterface::class => [
                                                        \Psr\Log\NullLogger::class => [''],
                                                ],
@@ -163,7 +163,7 @@ return [
 ];
 EOF,
                                'addonsArray' => [
-                                       \Friendica\Core\Hooks\Capabilities\HookType::STRATEGY => [
+                                       \Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
                                                \Psr\Log\LoggerInterface::class => [
                                                        \Psr\Log\NullLogger::class => [''],
                                                ],