]> git.mxchange.org Git - friendica.git/blob - src/Core/Hooks/Model/InstanceManager.php
Apply suggestions from code review
[friendica.git] / src / Core / Hooks / Model / InstanceManager.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2023, the Friendica project
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  */
21
22 namespace Friendica\Core\Hooks\Model;
23
24 use Dice\Dice;
25 use Friendica\Core\Hooks\Capabilities\IAmAStrategy;
26 use Friendica\Core\Hooks\Capabilities\ICanManageInstances;
27 use Friendica\Core\Hooks\Exceptions\HookInstanceException;
28 use Friendica\Core\Hooks\Exceptions\HookRegisterArgumentException;
29
30 /** {@inheritDoc} */
31 class InstanceManager implements ICanManageInstances
32 {
33         protected $instance          = [];
34         protected $instanceArguments = [];
35         protected $decorator         = [];
36
37         /** @var Dice */
38         protected $dice;
39
40         public function __construct(Dice $dice)
41         {
42                 $this->dice = $dice;
43         }
44
45         /** {@inheritDoc} */
46         public function registerStrategy(string $interface, string $name, string $class, array $arguments = null): ICanManageInstances
47         {
48                 if (!is_a($class, $interface, true)) {
49                         throw new HookRegisterArgumentException(sprintf('%s is not a valid class for the interface %s', $class, $interface));
50                 }
51
52                 if (!is_a($class, IAmAStrategy::class, true)) {
53                         throw new HookRegisterArgumentException(sprintf('%s does not inherit from the marker interface %s', $class, IAmAStrategy::class));
54                 }
55
56                 if (!empty($this->instance[$interface][$name])) {
57                         throw new HookRegisterArgumentException(sprintf('A class with the name %s is already set for the interface %s', $name, $interface));
58                 }
59
60                 $this->instance[$interface][$name]          = $class;
61                 $this->instanceArguments[$interface][$name] = $arguments;
62
63                 return $this;
64         }
65
66         /** {@inheritDoc} */
67         public function registerDecorator(string $class, string $decoratorClass, array $arguments = []): ICanManageInstances
68         {
69                 if (!is_a($decoratorClass, $class, true)) {
70                         throw new HookRegisterArgumentException(sprintf('%s is not a valid substitution for the given class or interface %s', $decoratorClass, $class));
71                 }
72
73                 $this->decorator[$class][] = [
74                         'class'     => $decoratorClass,
75                         'arguments' => $arguments,
76                 ];
77
78                 return $this;
79         }
80
81         /** {@inheritDoc} */
82         public function getInstance(string $class, string $name, array $arguments = []): object
83         {
84                 if (empty($this->instance[$class][$name])) {
85                         throw new HookInstanceException(sprintf('The class with the name %s isn\'t registered for the class or interface %s', $name, $class));
86                 }
87
88                 $instance = $this->dice->create($this->instance[$class][$name], array_merge($this->instanceArguments[$class][$name] ?? [], $arguments));
89
90                 foreach ($this->decorator[$class] ?? [] as $decorator) {
91                         $this->dice = $this->dice->addRule($class, [
92                                 'instanceOf'      => $decorator['class'],
93                                 'constructParams' => empty($decorator['arguments']) ? null : $decorator['arguments'],
94                                 /// @todo maybe support call structures for hooks as well in a later stage - could make factory calls easier
95                                 'call'          => null,
96                                 'substitutions' => [$class => $instance],
97                         ]);
98
99                         $instance = $this->dice->create($class);
100                 }
101
102                 return $instance;
103         }
104 }