18 private $dependents = [];
23 private $patches = [];
28 private $patchFactory;
35 private $appliedPatches = [];
40 private $patchHistory;
45 private $iterator =
null;
50 private $reverseIterator =
null;
55 private $cyclomaticStack = [];
64 $this->patchFactory = $patchFactory;
65 $this->patchHistory = $patchHistory;
73 private function registerDependents(
string $patchName)
75 $dependencies = $patchName::getDependencies();
77 foreach ($dependencies as $dependency) {
78 $this->dependents[$dependency][] = $patchName;
90 if ($this->patchHistory->isApplied($patchName)) {
91 $this->appliedPatches[$patchName] = $patchName;
92 $this->registerDependents($patchName);
96 if (isset($this->patches[$patchName])) {
97 return $this->patches[$patchName];
100 $this->patches[$patchName] = $patchName;
110 private function getDependentPatches(
string $patch)
118 if (isset($this->dependents[$patchName])) {
119 foreach ($this->dependents[$patchName] as $dependent) {
120 if (isset($this->appliedPatches[$dependent])) {
121 $dependent = $this->appliedPatches[$dependent];
122 $patches = array_replace($patches, $this->getDependentPatches($dependent));
123 $patches[$dependent] = $dependent;
124 unset($this->appliedPatches[$dependent]);
136 private function getDependencies(
string $patch)
140 $this->cyclomaticStack[$patch] =
true;
142 foreach ($deps as $dep) {
143 if (isset($this->cyclomaticStack[$dep])) {
144 throw new \LogicException(
"Cyclomatic dependency during patch installation");
156 $depInstances = array_replace($depInstances, $this->getDependencies($this->patches[$dep]));
157 $depInstances[$depInstance] = $depInstance;
160 unset($this->cyclomaticStack[$patch]);
161 return $depInstances;
174 if ($this->reverseIterator ===
null) {
175 $reversePatches = [];
177 while (!empty($this->appliedPatches)) {
178 $patch = array_pop($this->appliedPatches);
179 $reversePatches = array_replace($reversePatches, $this->getDependentPatches($patch));
180 $reversePatches[$patch] = $patch;
183 $this->reverseIterator = new \ArrayIterator($reversePatches);
186 return $this->reverseIterator;
198 if ($this->iterator ===
null) {
199 $installPatches = [];
200 $patchInstances = $this->patches;
202 while (!empty($patchInstances)) {
203 $firstPatch = array_shift($patchInstances);
204 $deps = $this->getDependencies($firstPatch);
209 foreach ($deps as $dep) {
210 unset($patchInstances[$dep]);
213 $installPatches = array_replace($installPatches, $deps);
214 $installPatches[$firstPatch] = $firstPatch;
217 $this->iterator = new \ArrayIterator($installPatches);
220 return $this->iterator;
call_user_func($callable, $param)
registerPatch(string $patchName)
__construct(PatchFactory $patchFactory, PatchHistory $patchHistory)