+++ /dev/null
-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.
--- /dev/null
+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.
--- /dev/null
+<?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';
+}
+++ /dev/null
-<?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';
-}
namespace Friendica\Core\Hooks\Capabilities;
/**
- * creates special instance and decorator treatments for given classes
+ * creates special instances for given classes
*/
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;
}
use Friendica\Core\Hooks\Exceptions\HookRegisterArgumentException;
/**
- * Register strategies and decorator/treatment handling for given classes
+ * Register strategies for given classes
*/
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;
}
class DiceInstanceManager implements ICanCreateInstances, ICanRegisterInstances
{
protected $instance = [];
- protected $decorator = [];
/** @var Dice */
protected $dice;
}
/** {@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);
}
}
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;
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)) {
}
}
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;
}
}
}
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;
$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();
$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();
*
*/
-use Friendica\Core\Hooks\Capabilities\HookType as H;
+use Friendica\Core\Hooks\Capabilities\BehavioralHookType as H;
use Friendica\Core\Logger\Type;
use Psr\Log;
Type\StreamLogger::class => ['stream'],
],
],
- H::DECORATOR => [
- Log\LoggerInterface::class => [
- Type\ProfilerLogger::class,
- ],
- ],
];
namespace Friendica\Test\Util\Hooks\InstanceMocks;
-class FakeInstance
+class FakeInstance implements IAmADecoratedInterface
{
protected $aText = null;
protected $cBool = null;
$this->aText = $aText;
$this->cBool = $cBool;
$this->bText = $bText;
+
+ return '';
}
public function getAText(): ?string
{
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++;
}
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();
}
}
<?php
return [
- \Friendica\Core\Hooks\Capabilities\HookType::STRATEGY => [
+ \Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
\Psr\Log\LoggerInterface::class => [
\Psr\Log\NullLogger::class => [''],
],
'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 => [''],
],
'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 => ['', ''],
],
'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 => [''],
],
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
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 [
/**
* @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 = [];
$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);
/**
* @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);
}
/**
- * @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());
}
}
<?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,
],
<?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,
],
];
<?php
return [
- \Friendica\Core\Hooks\Capabilities\HookType::STRATEGY => [
+ \Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
\Psr\Log\LoggerInterface::class => [
\Psr\Log\NullLogger::class => [''],
],
];
EOF,
'addonsArray' => [
- \Friendica\Core\Hooks\Capabilities\HookType::STRATEGY => [
+ \Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
\Psr\Log\LoggerInterface::class => [
\Psr\Log\NullLogger::class => ['null'],
],
<?php
return [
- \Friendica\Core\Hooks\Capabilities\HookType::STRATEGY => [
+ \Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
\Psr\Log\LoggerInterface::class => [
\Psr\Log\NullLogger::class => [''],
],
];
EOF,
'addonsArray' => [
- \Friendica\Core\Hooks\Capabilities\HookType::STRATEGY => [
+ \Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
\Psr\Log\LoggerInterface::class => [
\Psr\Log\NullLogger::class => 'null',
],
<?php
return [
- \Friendica\Core\Hooks\Capabilities\HookType::STRATEGY => [
+ \Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
\Psr\Log\LoggerInterface::class => [
\Psr\Log\NullLogger::class => [''],
],
];
EOF,
'addonsArray' => [
- \Friendica\Core\Hooks\Capabilities\HookType::STRATEGY => [
+ \Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
\Psr\Log\LoggerInterface::class => [
\Psr\Log\NullLogger::class => [''],
],
];
EOF,
'addonsArray' => [
- \Friendica\Core\Hooks\Capabilities\HookType::STRATEGY => [
+ \Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [
\Psr\Log\LoggerInterface::class => [
\Psr\Log\NullLogger::class => [''],
],