ILIAS  release_7 Revision v7.30-3-g800a261c036
ObjectiveIterator.php
Go to the documentation of this file.
1<?php
2
3/* Copyright (c) 2019 Richard Klees <richard.klees@concepts-and-training.de> Extended GPL, see docs/LICENSE */
4
5namespace ILIAS\Setup;
6
13class ObjectiveIterator implements \Iterator
14{
18 protected $environment;
19
23 protected $objective;
24
28 protected $stack;
29
33 protected $current;
34
38 protected $returned;
39
43 protected $failed;
44
49
50
52 {
54 $this->objective = $objective;
55 $this->rewind();
56 }
57
58 public function setEnvironment(Environment $environment) : void
59 {
61 }
62
64 {
65 if (!isset($this->returned[$objective->getHash()])) {
66 throw new \LogicException(
67 "You may only mark objectives as failed that have been returned by this iterator."
68 );
69 }
70
71 $this->failed[$objective->getHash()] = true;
72 }
73
74 public function rewind()
75 {
76 $this->stack = [$this->objective];
77 $this->current = null;
78 $this->returned = [];
79 $this->failed = [];
80 $this->reverse_dependencies = [];
81 $this->next();
82 }
83
84 public function current()
85 {
86 if ($this->current === null) {
87 throw new \LogicException(
88 "Iterator is finished or wasn't initialized correctly internally."
89 );
90 }
91 return $this->current;
92 }
93
94 public function key()
95 {
96 return $this->current()->getHash();
97 }
98
99 public function next()
100 {
101 if (count($this->stack) === 0) {
102 $this->current = null;
103 return;
104 }
105
106 $cur = array_pop($this->stack);
107 $hash = $cur->getHash();
108
109 if (isset($this->returned[$hash]) || isset($this->failed[$hash])) {
110 $this->next();
111 return;
112 }
113
114 $preconditions = [];
115 $failed_preconditions = [];
116 foreach ($cur->getPreconditions($this->environment) as $p) {
117 $h = $p->getHash();
118 if (!isset($this->returned[$h]) || isset($this->failed[$h])) {
119 $preconditions[] = $p;
120 }
121
122 if (isset($this->failed[$h])) {
123 $failed_preconditions[] = $p;
124 }
125 }
126
127 // We only have preconditions left that we know to have failed.
128 if (
129 count($preconditions) !== 0 &&
130 count($preconditions) === count($failed_preconditions)
131 ) {
132 $this->returned[$hash] = true;
133 $this->markAsFailed($cur);
134 if (count($this->stack) === 0) {
135 throw new UnachievableException(
136 "Objective '" . $cur->getLabel() . "' had failed preconditions:\n - " .
137 implode("\n - ", array_map(function ($o) {
138 return $o->getLabel();
139 }, $failed_preconditions))
140 );
141 }
142 $this->next();
143 return;
144 }
145
146 // No preconditions open, we can proceed with the objective.
147 if (count($preconditions) === 0) {
148 $this->returned[$hash] = true;
149 $this->current = $cur;
150 return;
151 }
152
153 $this->stack[] = $cur;
154 $this->detectDependencyCycles($hash, $hash);
155 foreach (array_reverse($preconditions) as $p) {
156 $this->stack[] = $p;
157 $this->setReverseDependency($p->getHash(), $hash);
158 }
159 $this->next();
160 }
161
162 public function valid()
163 {
164 return $this->current !== null;
165 }
166
167 protected function detectDependencyCycles(string $cur, string $next)
168 {
169 if (!isset($this->reverse_dependencies[$next])) {
170 return;
171 }
172 if (in_array($cur, $this->reverse_dependencies[$next])) {
173 throw new UnachievableException(
174 "The objectives contain a dependency cycle and won't all be achievable."
175 );
176 }
177 foreach ($this->reverse_dependencies[$next] as $d) {
178 $this->detectDependencyCycles($cur, $d);
179 }
180 }
181
182 protected function setReverseDependency(string $other, string $cur)
183 {
184 if (!isset($this->reverse_dependencies[$other])) {
185 $this->reverse_dependencies[$other] = [];
186 }
187 $this->reverse_dependencies[$other][] = $cur;
188 }
189}
An exception for terminatinating execution or to throw for unit testing.
Tries to enumerate all preconditions for the given objective, where the ones that can be achieved (i....
setEnvironment(Environment $environment)
markAsFailed(Objective $objective)
setReverseDependency(string $other, string $cur)
detectDependencyCycles(string $cur, string $next)
__construct(Environment $environment, Objective $objective)
Signals that some goal won't be achievable by actions of the system ever.
for( $i=6;$i< 13;$i++) for($i=1; $i< 13; $i++) $d
Definition: date.php:296
environment()
Definition: environment.php:3
An environment holds resources to be used in the setup process.
Definition: Environment.php:12
An objective is a desired state of the system that is supposed to be created by the setup.
Definition: Objective.php:15
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...