Add tests for InstanceManager and remove Decorator hook logic (avoid complex Dice logic)

This commit is contained in:
Philipp 2023-07-17 00:10:15 +02:00
parent 527622df4a
commit 93af6f0564
No known key found for this signature in database
GPG key ID: 24A7501396EB5432
14 changed files with 218 additions and 390 deletions

View file

@ -21,7 +21,11 @@
namespace Friendica\Core\Hooks\Capabilities;
interface HookType
/**
* 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.
@ -29,11 +33,5 @@ interface HookType
* @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';
const EVENT = 'event';
}

View 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;
}

View 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;
}

View 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);
}
}

View 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;
}
}
}

View 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();