This repository was archived by the owner on Mar 27, 2024. It is now read-only.
Repository navigation
Expand file tree
/
Copy pathModularModuleTrait.php
More file actions
162 lines (144 loc) · 5.27 KB
/
Copy pathModularModuleTrait.php
File metadata and controls
162 lines (144 loc) · 5.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
<?php
namespace RebelCode\Modular\Module;
use ArrayAccess;
use Dhii\Collection\AddCapableInterface;
use Dhii\Modular\Module\ModuleInterface;
use Psr\Container\ContainerInterface;
use stdClass;
use Traversable;
/**
* Functionality for modules that load other modules.
*
* This implementation constructs a "master" composite container on {@see _setup()} that contains a child container
* with all of the module instances as services. Each module is then {@see _setup()} and their provided containers, if
* any, are attached to the master container, which is then returned.
*
* On {@see _run()}, every module's {@see run()} method is invoked with the given container.
*
* It is very important to use a composite container that can work with a {@see Traversable} list of containers that is
* initially empty and populated later. This is the only sane remedy for the chicken-egg problem.
*
* @since [*next-version*]
*/
trait ModularModuleTrait
{
/**
* The list of module instances, mapped by their keys.
*
* @since [*next-version*]
*
* @var ModuleInterface[]|Traversable
*/
protected $modules;
/**
* Sets up the modules, constructing the master composite container.
*
* @since [*next-version*]
*
* @return ContainerInterface The created composite container.
*/
protected function _setup()
{
// The list of containers that will be added to the composite container
$containers = $this->_createAddCapableList();
// The composite container - the container for this modular module
$composite = $this->_createCompositeContainer($containers);
// The initial container that will be used to initialize the modules
$initContainer = $this->_getInitialContainer($composite);
if ($initContainer !== null) {
$containers->add($initContainer);
}
$this->modules = [];
// Get the modules to set up
$modules = $this->_getModules($initContainer);
$moduleContainers = [];
foreach ($modules as $_module) {
// Set up the module and collect its container
if ($_container = $_module->setup()) {
$moduleContainers[] = $_container;
}
// Save module instance
$this->modules[$this->_getModuleServiceKey($_module)] = $_module;
}
// Create a container that has the module instances as services, and add it to the list
$containers->add($this->_createContainer($this->modules, $composite));
// Add the containers retrieved from the modules, to the list
foreach (array_reverse($moduleContainers) as $_moduleContainer) {
$containers->add($_moduleContainer);
}
// Construct the master container and return
return $composite;
}
/**
* Runs the modules.
*
* @since [*next-version*]
*
* @param ContainerInterface|null $c The DI container.
*/
protected function _run(ContainerInterface $c = null)
{
foreach ($this->modules as $_module) {
$_module->run($c);
}
}
/**
* Retrieves the service key for the service that represents a module.
*
* @since [*next-version*]
*
* @param ModuleInterface $module The module instance.
*
* @return string The module service key.
*/
abstract protected function _getModuleServiceKey(ModuleInterface $module);
/**
* Retrieves the module instances to load.
*
* @since [*next-version*]
*
* @param ContainerInterface|null $container The container to initialize containers with.
*
* @return ModuleInterface[]|Traversable A list of module instances.
*/
abstract protected function _getModules(ContainerInterface $container = null);
/**
* Retrieves the container to use to initialize modules.
*
* @since [*next-version*]
*
* @param ContainerInterface|null $parent The parent container, if any.
*
* @return ContainerInterface|null The container instance, if any.
*/
abstract protected function _getInitialContainer(ContainerInterface $parent = null);
/**
* Creates a container instance with the given service definitions.
*
* @since [*next-version*]
*
* @param callable[]|ArrayAccess|stdClass|ContainerInterface $definitions The service definitions.
* @param ContainerInterface|null $parent The parent container instance, if any.
*
* @return ContainerInterface The created container instance.
*/
abstract protected function _createContainer($definitions = [], ContainerInterface $parent = null);
/**
* Creates a composite container with the given children container instances.
*
* @since [*next-version*]
*
* @param ContainerInterface[]|Traversable $containers The children container instances.
*
* @return ContainerInterface The created composite container instance.
*/
abstract protected function _createCompositeContainer($containers);
/**
* Creates a new, modifiable list.
*
* @since [*next-version*]
*
* @return AddCapableInterface|Traversable The traversable, modifiable list.
*/
abstract protected function _createAddCapableList();
}