1 | <?php |
||||
2 | |||||
3 | /** |
||||
4 | * Copyright © 2016-present Spryker Systems GmbH. All rights reserved. |
||||
5 | * Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file. |
||||
6 | */ |
||||
7 | |||||
8 | namespace Spryker\Zed\Oms\Business\OrderStateMachine; |
||||
9 | |||||
10 | use LogicException; |
||||
11 | use SimpleXMLElement; |
||||
12 | use Spryker\Zed\Oms\Business\Exception\StatemachineException; |
||||
13 | use Spryker\Zed\Oms\Business\Process\EventInterface; |
||||
14 | use Spryker\Zed\Oms\Business\Process\ProcessInterface; |
||||
15 | use Spryker\Zed\Oms\Business\Process\StateInterface; |
||||
16 | use Spryker\Zed\Oms\Business\Process\TransitionInterface; |
||||
17 | use Spryker\Zed\Oms\Business\Reader\ProcessCacheReaderInterface; |
||||
18 | use Spryker\Zed\Oms\Business\Writer\ProcessCacheWriterInterface; |
||||
19 | use Symfony\Component\Finder\Finder as SymfonyFinder; |
||||
20 | |||||
21 | class Builder implements BuilderInterface |
||||
22 | { |
||||
23 | /** |
||||
24 | * @var \SimpleXMLElement |
||||
25 | */ |
||||
26 | protected $rootElement; |
||||
27 | |||||
28 | /** |
||||
29 | * @var array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> |
||||
30 | */ |
||||
31 | protected static $processBuffer = []; |
||||
32 | |||||
33 | /** |
||||
34 | * @var \Spryker\Zed\Oms\Business\Process\EventInterface |
||||
35 | */ |
||||
36 | protected $event; |
||||
37 | |||||
38 | /** |
||||
39 | * @var \Spryker\Zed\Oms\Business\Process\StateInterface |
||||
40 | */ |
||||
41 | protected $state; |
||||
42 | |||||
43 | /** |
||||
44 | * @var \Spryker\Zed\Oms\Business\Process\TransitionInterface |
||||
45 | */ |
||||
46 | protected $transition; |
||||
47 | |||||
48 | /** |
||||
49 | * @var \Spryker\Zed\Oms\Business\Process\ProcessInterface |
||||
50 | */ |
||||
51 | protected $process; |
||||
52 | |||||
53 | /** |
||||
54 | * @var array|string |
||||
55 | */ |
||||
56 | protected $processDefinitionLocation; |
||||
57 | |||||
58 | /** |
||||
59 | * @var string |
||||
60 | */ |
||||
61 | protected $subProcessPrefixDelimiter; |
||||
62 | |||||
63 | /** |
||||
64 | * @var \Spryker\Zed\Oms\Business\Reader\ProcessCacheReaderInterface |
||||
65 | */ |
||||
66 | protected ProcessCacheReaderInterface $processCacheReader; |
||||
67 | |||||
68 | /** |
||||
69 | * @var \Spryker\Zed\Oms\Business\Writer\ProcessCacheWriterInterface |
||||
70 | */ |
||||
71 | protected ProcessCacheWriterInterface $processCacheWriter; |
||||
72 | |||||
73 | /** |
||||
74 | * @param \Spryker\Zed\Oms\Business\Process\EventInterface $event |
||||
75 | * @param \Spryker\Zed\Oms\Business\Process\StateInterface $state |
||||
76 | * @param \Spryker\Zed\Oms\Business\Process\TransitionInterface $transition |
||||
77 | * @param \Spryker\Zed\Oms\Business\Process\ProcessInterface $process |
||||
78 | * @param array|string $processDefinitionLocation |
||||
79 | * @param \Spryker\Zed\Oms\Business\Reader\ProcessCacheReaderInterface $processCacheReader |
||||
80 | * @param \Spryker\Zed\Oms\Business\Writer\ProcessCacheWriterInterface $processCacheWriter |
||||
81 | * @param string $subProcessPrefixDelimiter |
||||
82 | */ |
||||
83 | public function __construct( |
||||
84 | EventInterface $event, |
||||
85 | StateInterface $state, |
||||
86 | TransitionInterface $transition, |
||||
87 | ProcessInterface $process, |
||||
88 | $processDefinitionLocation, |
||||
89 | ProcessCacheReaderInterface $processCacheReader, |
||||
90 | ProcessCacheWriterInterface $processCacheWriter, |
||||
91 | $subProcessPrefixDelimiter = ' - ' |
||||
92 | ) { |
||||
93 | $this->event = $event; |
||||
94 | $this->state = $state; |
||||
95 | $this->transition = $transition; |
||||
96 | $this->process = $process; |
||||
97 | $this->processCacheReader = $processCacheReader; |
||||
98 | $this->processCacheWriter = $processCacheWriter; |
||||
99 | $this->subProcessPrefixDelimiter = $subProcessPrefixDelimiter; |
||||
100 | |||||
101 | $this->setProcessDefinitionLocation($processDefinitionLocation); |
||||
102 | } |
||||
103 | |||||
104 | /** |
||||
105 | * @param string $processName |
||||
106 | * |
||||
107 | * @return \Spryker\Zed\Oms\Business\Process\ProcessInterface |
||||
108 | */ |
||||
109 | public function createProcess($processName) |
||||
110 | { |
||||
111 | if (isset(static::$processBuffer[$processName])) { |
||||
112 | return static::$processBuffer[$processName]; |
||||
113 | } |
||||
114 | |||||
115 | if ($this->processCacheReader->hasProcess($processName)) { |
||||
116 | static::$processBuffer[$processName] = $this->processCacheReader->getProcess($processName); |
||||
117 | |||||
118 | return static::$processBuffer[$processName]; |
||||
119 | } |
||||
120 | |||||
121 | $mainProcess = $this->createMainProcess($processName); |
||||
122 | |||||
123 | static::$processBuffer[$processName] = $mainProcess; |
||||
124 | |||||
125 | $this->processCacheWriter->cacheProcess($mainProcess, $processName); |
||||
126 | |||||
127 | return static::$processBuffer[$processName]; |
||||
128 | } |
||||
129 | |||||
130 | /** |
||||
131 | * @param string $processName |
||||
132 | * |
||||
133 | * @return \Spryker\Zed\Oms\Business\Process\ProcessInterface |
||||
134 | */ |
||||
135 | protected function createMainProcess(string $processName): ProcessInterface |
||||
136 | { |
||||
137 | $this->rootElement = $this->loadXmlFromProcessName($processName); |
||||
138 | |||||
139 | $this->mergeSubProcessFiles(); |
||||
140 | |||||
141 | /** @var array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> $processMap */ |
||||
142 | $processMap = []; |
||||
143 | |||||
144 | [$processMap, $mainProcess] = $this->createSubProcess($processMap); |
||||
145 | |||||
146 | $stateToProcessMap = $this->createStates($processMap); |
||||
147 | |||||
148 | $this->createSubProcesses($processMap); |
||||
149 | |||||
150 | $eventMap = $this->createEvents(); |
||||
151 | |||||
152 | $this->createTransitions($stateToProcessMap, $processMap, $eventMap); |
||||
153 | |||||
154 | return $mainProcess->warmupCache(); |
||||
155 | } |
||||
156 | |||||
157 | /** |
||||
158 | * @return void |
||||
159 | */ |
||||
160 | protected function mergeSubProcessFiles() |
||||
161 | { |
||||
162 | foreach ($this->rootElement->children() as $xmlProcess) { |
||||
163 | $processFile = $this->getAttributeString($xmlProcess, 'file'); |
||||
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||||
164 | $processName = $this->getAttributeString($xmlProcess, 'name'); |
||||
165 | $processPrefix = $this->getAttributeString($xmlProcess, 'prefix'); |
||||
166 | |||||
167 | if ($processFile) { |
||||
168 | $xmlSubProcess = $this->loadXmlFromFileName(str_replace(' ', '_', $processFile)); |
||||
169 | |||||
170 | if ($processName) { |
||||
171 | $xmlSubProcess->children()->process[0]['name'] = $processName; |
||||
172 | } |
||||
173 | |||||
174 | $this->recursiveMerge($xmlSubProcess, $this->rootElement, $processPrefix); |
||||
175 | } |
||||
176 | } |
||||
177 | } |
||||
178 | |||||
179 | /** |
||||
180 | * @param \SimpleXMLElement $fromXmlElement |
||||
181 | * @param \SimpleXMLElement $intoXmlNode |
||||
182 | * @param string|null $prefix |
||||
183 | * |
||||
184 | * @return void |
||||
185 | */ |
||||
186 | protected function recursiveMerge($fromXmlElement, $intoXmlNode, $prefix = null) |
||||
187 | { |
||||
188 | /** @var array<\SimpleXMLElement> $xmlElements */ |
||||
189 | $xmlElements = $fromXmlElement->children(); |
||||
190 | if (!$xmlElements) { |
||||
191 | return; |
||||
192 | } |
||||
193 | |||||
194 | foreach ($xmlElements as $xmlElement) { |
||||
195 | $xmlElement = $this->prefixSubProcessElementValue($xmlElement, $prefix); |
||||
196 | $xmlElement = $this->prefixSubProcessElementAttributes($xmlElement, $prefix); |
||||
197 | |||||
198 | $child = $intoXmlNode->addChild($xmlElement->getName(), $xmlElement); |
||||
199 | $attributes = $xmlElement->attributes(); |
||||
200 | foreach ($attributes as $k => $v) { |
||||
201 | $child->addAttribute($k, $v); |
||||
202 | } |
||||
203 | |||||
204 | $this->recursiveMerge($xmlElement, $child, $prefix); |
||||
205 | } |
||||
206 | } |
||||
207 | |||||
208 | /** |
||||
209 | * @param \SimpleXMLElement $xmlElement |
||||
210 | * @param string|null $prefix |
||||
211 | * |
||||
212 | * @return \SimpleXMLElement |
||||
213 | */ |
||||
214 | protected function prefixSubProcessElementValue(SimpleXMLElement $xmlElement, $prefix = null) |
||||
215 | { |
||||
216 | if ($prefix === null) { |
||||
217 | return $xmlElement; |
||||
218 | } |
||||
219 | |||||
220 | $namespaceDependentElementNames = ['source', 'target', 'event']; |
||||
221 | |||||
222 | if (in_array($xmlElement->getName(), $namespaceDependentElementNames)) { |
||||
223 | $xmlElement[0] = $prefix . $this->subProcessPrefixDelimiter . $xmlElement[0]; |
||||
224 | } |
||||
225 | |||||
226 | return $xmlElement; |
||||
227 | } |
||||
228 | |||||
229 | /** |
||||
230 | * @param \SimpleXMLElement $xmlElement |
||||
231 | * @param string|null $prefix |
||||
232 | * |
||||
233 | * @return \SimpleXMLElement |
||||
234 | */ |
||||
235 | protected function prefixSubProcessElementAttributes(SimpleXMLElement $xmlElement, $prefix = null) |
||||
236 | { |
||||
237 | if ($prefix === null) { |
||||
238 | return $xmlElement; |
||||
239 | } |
||||
240 | |||||
241 | $namespaceDependentElementNames = ['state', 'event']; |
||||
242 | |||||
243 | if (in_array($xmlElement->getName(), $namespaceDependentElementNames)) { |
||||
244 | $xmlElement->attributes()['name'] = $prefix . $this->subProcessPrefixDelimiter . $xmlElement->attributes()['name']; |
||||
245 | } |
||||
246 | |||||
247 | return $xmlElement; |
||||
248 | } |
||||
249 | |||||
250 | /** |
||||
251 | * @param string $fileName |
||||
252 | * |
||||
253 | * @return \SimpleXMLElement |
||||
254 | */ |
||||
255 | protected function loadXmlFromFileName($fileName) |
||||
256 | { |
||||
257 | $definitionFile = $this->locateProcessDefinition($fileName); |
||||
258 | |||||
259 | return $this->loadXml($definitionFile->getContents()); |
||||
260 | } |
||||
261 | |||||
262 | /** |
||||
263 | * @param string $fileName |
||||
264 | * |
||||
265 | * @return \Symfony\Component\Finder\SplFileInfo |
||||
266 | */ |
||||
267 | private function locateProcessDefinition($fileName) |
||||
268 | { |
||||
269 | $finder = $this->buildFinder($fileName); |
||||
270 | |||||
271 | /** @phpstan-var \Symfony\Component\Finder\SplFileInfo */ |
||||
272 | return current(iterator_to_array($finder->getIterator())); |
||||
273 | } |
||||
274 | |||||
275 | /** |
||||
276 | * @param string $processName |
||||
277 | * |
||||
278 | * @return \SimpleXMLElement |
||||
279 | */ |
||||
280 | protected function loadXmlFromProcessName($processName) |
||||
281 | { |
||||
282 | return $this->loadXmlFromFileName($processName . '.xml'); |
||||
283 | } |
||||
284 | |||||
285 | /** |
||||
286 | * @param string $xml |
||||
287 | * |
||||
288 | * @return \SimpleXMLElement |
||||
289 | */ |
||||
290 | protected function loadXml($xml) |
||||
291 | { |
||||
292 | return new SimpleXMLElement($xml); |
||||
293 | } |
||||
294 | |||||
295 | /** |
||||
296 | * @return array |
||||
297 | */ |
||||
298 | protected function createEvents() |
||||
299 | { |
||||
300 | $eventMap = []; |
||||
301 | |||||
302 | foreach ($this->rootElement as $xmlProcess) { |
||||
303 | if (!isset($xmlProcess->events)) { |
||||
304 | continue; |
||||
305 | } |
||||
306 | |||||
307 | $xmlEvents = $xmlProcess->events->children(); |
||||
308 | foreach ($xmlEvents as $xmlEvent) { |
||||
309 | $event = clone $this->event; |
||||
310 | $eventId = $this->getAttributeString($xmlEvent, 'name'); |
||||
0 ignored issues
–
show
It seems like
$xmlEvent can also be of type null ; however, parameter $xmlElement of Spryker\Zed\Oms\Business...r::getAttributeString() does only seem to accept SimpleXMLElement , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
311 | $event->setCommand($this->getAttributeString($xmlEvent, 'command')); |
||||
312 | $event->setManual($this->getAttributeBoolean($xmlEvent, 'manual')); |
||||
0 ignored issues
–
show
It seems like
$xmlEvent can also be of type null ; however, parameter $xmlElement of Spryker\Zed\Oms\Business...::getAttributeBoolean() does only seem to accept SimpleXMLElement , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
313 | $event->setOnEnter($this->getAttributeBoolean($xmlEvent, 'onEnter')); |
||||
314 | $event->setTimeout($this->getAttributeString($xmlEvent, 'timeout')); |
||||
315 | $event->setTimeoutProcessor($this->getAttributeString($xmlEvent, 'timeoutProcessor')); |
||||
316 | if ($eventId === null) { |
||||
317 | continue; |
||||
318 | } |
||||
319 | |||||
320 | $event->setName($eventId); |
||||
321 | $eventMap[$event->getName()] = $event; |
||||
322 | } |
||||
323 | } |
||||
324 | |||||
325 | return $eventMap; |
||||
326 | } |
||||
327 | |||||
328 | /** |
||||
329 | * @param array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> $processMap |
||||
330 | * |
||||
331 | * @return array |
||||
332 | */ |
||||
333 | protected function createSubProcess(array $processMap) |
||||
334 | { |
||||
335 | $mainProcess = null; |
||||
336 | $xmlProcesses = $this->rootElement->children(); |
||||
337 | |||||
338 | /** @var \SimpleXMLElement $xmlProcess */ |
||||
339 | foreach ($xmlProcesses as $xmlProcess) { |
||||
340 | $process = clone $this->process; |
||||
341 | $processName = $this->getAttributeString($xmlProcess, 'name'); |
||||
0 ignored issues
–
show
It seems like
$xmlProcess can also be of type null ; however, parameter $xmlElement of Spryker\Zed\Oms\Business...r::getAttributeString() does only seem to accept SimpleXMLElement , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
342 | $process->setName($processName); |
||||
343 | $processMap[$processName] = $process; |
||||
344 | $process->setIsMain($this->getAttributeBoolean($xmlProcess, 'main')); |
||||
345 | |||||
346 | $process->setFile($this->getAttributeString($xmlProcess, 'file')); |
||||
347 | |||||
348 | if ($process->getIsMain()) { |
||||
349 | $mainProcess = $process; |
||||
350 | } |
||||
351 | } |
||||
352 | |||||
353 | return [$processMap, $mainProcess]; |
||||
354 | } |
||||
355 | |||||
356 | /** |
||||
357 | * @param array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> $processMap |
||||
358 | * |
||||
359 | * @return void |
||||
360 | */ |
||||
361 | protected function createSubProcesses(array $processMap) |
||||
362 | { |
||||
363 | foreach ($this->rootElement as $xmlProcess) { |
||||
364 | $processName = $this->getAttributeString($xmlProcess, 'name'); |
||||
0 ignored issues
–
show
It seems like
$xmlProcess can also be of type null ; however, parameter $xmlElement of Spryker\Zed\Oms\Business...r::getAttributeString() does only seem to accept SimpleXMLElement , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
365 | |||||
366 | $process = $processMap[$processName]; |
||||
367 | |||||
368 | if ($xmlProcess->subprocesses) { |
||||
369 | $xmlSubProcesses = $xmlProcess->subprocesses->children(); |
||||
370 | |||||
371 | foreach ($xmlSubProcesses as $xmlSubProcess) { |
||||
372 | $subProcessName = (string)$xmlSubProcess; |
||||
373 | $subProcess = $processMap[$subProcessName]; |
||||
374 | $process->addSubProcess($subProcess); |
||||
375 | } |
||||
376 | } |
||||
377 | } |
||||
378 | } |
||||
379 | |||||
380 | /** |
||||
381 | * @param array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> $processMap |
||||
382 | * |
||||
383 | * @return array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> |
||||
384 | */ |
||||
385 | protected function createStates(array $processMap) |
||||
386 | { |
||||
387 | $stateToProcessMap = []; |
||||
388 | |||||
389 | $xmlProcesses = $this->rootElement->children(); |
||||
390 | foreach ($xmlProcesses as $xmlProcess) { |
||||
391 | $processName = $this->getAttributeString($xmlProcess, 'name'); |
||||
0 ignored issues
–
show
It seems like
$xmlProcess can also be of type null ; however, parameter $xmlElement of Spryker\Zed\Oms\Business...r::getAttributeString() does only seem to accept SimpleXMLElement , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
392 | $process = $processMap[$processName]; |
||||
393 | |||||
394 | if ($xmlProcess->states) { |
||||
395 | $xmlStates = $xmlProcess->states->children(); |
||||
396 | /** @var \SimpleXMLElement $xmlState */ |
||||
397 | foreach ($xmlStates as $xmlState) { |
||||
398 | $state = clone $this->state; |
||||
399 | $state->setName($this->getAttributeString($xmlState, 'name')); |
||||
400 | $state->setDisplay($this->getAttributeString($xmlState, 'display')); |
||||
401 | $state->setReserved($this->getAttributeBoolean($xmlState, 'reserved')); |
||||
402 | $state->setProcess($process); |
||||
403 | |||||
404 | /** @var array $stateFlag */ |
||||
405 | $stateFlag = $xmlState->flag; |
||||
406 | if ($stateFlag) { |
||||
407 | $flags = $xmlState->children(); |
||||
408 | foreach ($flags->flag as $flag) { |
||||
409 | $state->addFlag((string)$flag); |
||||
410 | } |
||||
411 | } |
||||
412 | |||||
413 | $process->addState($state); |
||||
414 | $stateToProcessMap[$state->getName()] = $process; |
||||
415 | } |
||||
416 | } |
||||
417 | } |
||||
418 | |||||
419 | return $stateToProcessMap; |
||||
420 | } |
||||
421 | |||||
422 | /** |
||||
423 | * @param array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> $stateToProcessMap |
||||
424 | * @param array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> $processMap |
||||
425 | * @param array<\Spryker\Zed\Oms\Business\Process\EventInterface> $eventMap |
||||
426 | * |
||||
427 | * @throws \LogicException |
||||
428 | * |
||||
429 | * @return void |
||||
430 | */ |
||||
431 | protected function createTransitions(array $stateToProcessMap, array $processMap, array $eventMap) |
||||
432 | { |
||||
433 | foreach ($this->rootElement as $xmlProcess) { |
||||
434 | if ($xmlProcess->transitions) { |
||||
435 | $xmlTransitions = $xmlProcess->transitions->children(); |
||||
436 | |||||
437 | $processName = $this->getAttributeString($xmlProcess, 'name'); |
||||
0 ignored issues
–
show
It seems like
$xmlProcess can also be of type null ; however, parameter $xmlElement of Spryker\Zed\Oms\Business...r::getAttributeString() does only seem to accept SimpleXMLElement , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
438 | |||||
439 | foreach ($xmlTransitions as $xmlTransition) { |
||||
440 | $transition = clone $this->transition; |
||||
441 | |||||
442 | $transition->setCondition($this->getAttributeString($xmlTransition, 'condition')); |
||||
443 | |||||
444 | $transition->setHappy($this->getAttributeBoolean($xmlTransition, 'happy')); |
||||
0 ignored issues
–
show
It seems like
$xmlTransition can also be of type null ; however, parameter $xmlElement of Spryker\Zed\Oms\Business...::getAttributeBoolean() does only seem to accept SimpleXMLElement , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
445 | |||||
446 | $sourceName = (string)$xmlTransition->source; |
||||
447 | |||||
448 | if (!isset($stateToProcessMap[$sourceName])) { |
||||
449 | throw new LogicException(sprintf('Source: %s does not exist.', $sourceName)); |
||||
450 | } |
||||
451 | |||||
452 | $sourceProcess = $stateToProcessMap[$sourceName]; |
||||
453 | $sourceState = $sourceProcess->getState($sourceName); |
||||
454 | $transition->setSource($sourceState); |
||||
455 | $sourceState->addOutgoingTransition($transition); |
||||
456 | |||||
457 | $targetName = (string)$xmlTransition->target; |
||||
458 | |||||
459 | if (!isset($stateToProcessMap[$targetName])) { |
||||
460 | throw new LogicException('Target: "' . $targetName . '" does not exist from source: "' . $sourceName . '"'); |
||||
461 | } |
||||
462 | $targetProcess = $stateToProcessMap[$targetName]; |
||||
463 | $targetState = $targetProcess->getState($targetName); |
||||
464 | $transition->setTarget($targetState); |
||||
465 | $targetState->addIncomingTransition($transition); |
||||
466 | |||||
467 | if (isset($xmlTransition->event)) { |
||||
468 | $eventId = (string)$xmlTransition->event; |
||||
469 | |||||
470 | if (!isset($eventMap[$eventId])) { |
||||
471 | throw new LogicException('Event: "' . $eventId . '" does not exist from source: "' . $sourceName . '"'); |
||||
472 | } |
||||
473 | |||||
474 | $event = $eventMap[$eventId]; |
||||
475 | $event->addTransition($transition); |
||||
476 | $transition->setEvent($event); |
||||
477 | } |
||||
478 | |||||
479 | $processMap[$processName]->addTransition($transition); |
||||
480 | } |
||||
481 | } |
||||
482 | } |
||||
483 | } |
||||
484 | |||||
485 | /** |
||||
486 | * @param \SimpleXMLElement $xmlElement |
||||
487 | * @param string $attributeName |
||||
488 | * |
||||
489 | * @return string|null |
||||
490 | */ |
||||
491 | protected function getAttributeString(SimpleXMLElement $xmlElement, $attributeName) |
||||
492 | { |
||||
493 | $string = (string)$xmlElement->attributes()[$attributeName]; |
||||
494 | $string = ($string === '') ? null : $string; |
||||
495 | |||||
496 | return $string; |
||||
497 | } |
||||
498 | |||||
499 | /** |
||||
500 | * @param \SimpleXMLElement $xmlElement |
||||
501 | * @param string $attributeName |
||||
502 | * |
||||
503 | * @return bool |
||||
504 | */ |
||||
505 | protected function getAttributeBoolean(SimpleXMLElement $xmlElement, $attributeName) |
||||
506 | { |
||||
507 | return (string)$xmlElement->attributes()[$attributeName] === 'true'; |
||||
508 | } |
||||
509 | |||||
510 | /** |
||||
511 | * @param array|string|null $processDefinitionLocation |
||||
512 | * |
||||
513 | * @return void |
||||
514 | */ |
||||
515 | private function setProcessDefinitionLocation($processDefinitionLocation) |
||||
516 | { |
||||
517 | $this->processDefinitionLocation = $processDefinitionLocation; |
||||
518 | } |
||||
519 | |||||
520 | /** |
||||
521 | * @param string $fileName |
||||
522 | * |
||||
523 | * @return \Symfony\Component\Finder\Finder |
||||
524 | */ |
||||
525 | protected function buildFinder($fileName) |
||||
526 | { |
||||
527 | $finder = $this->getFinder(); |
||||
528 | $finder->in($this->processDefinitionLocation); |
||||
529 | if (strpos($fileName, '/') !== false) { |
||||
530 | $finder->path($this->createSubProcessPathPattern($fileName)); |
||||
531 | $finder->name(basename($fileName)); |
||||
532 | } else { |
||||
533 | $finder->name($fileName); |
||||
534 | } |
||||
535 | |||||
536 | $this->validateFinder($finder, $fileName); |
||||
537 | |||||
538 | return $finder; |
||||
539 | } |
||||
540 | |||||
541 | /** |
||||
542 | * @return \Symfony\Component\Finder\Finder |
||||
543 | */ |
||||
544 | protected function getFinder() |
||||
545 | { |
||||
546 | return new SymfonyFinder(); |
||||
547 | } |
||||
548 | |||||
549 | /** |
||||
550 | * @param \Symfony\Component\Finder\Finder $finder |
||||
551 | * @param string $fileName |
||||
552 | * |
||||
553 | * @throws \Spryker\Zed\Oms\Business\Exception\StatemachineException |
||||
554 | * |
||||
555 | * @return void |
||||
556 | */ |
||||
557 | protected function validateFinder(SymfonyFinder $finder, $fileName) |
||||
558 | { |
||||
559 | if ($finder->count() > 1) { |
||||
560 | throw new StatemachineException( |
||||
561 | sprintf( |
||||
562 | '"%s" found in more then one location. Could not determine which one to choose. Please check your process definition location', |
||||
563 | $fileName, |
||||
564 | ), |
||||
565 | ); |
||||
566 | } |
||||
567 | |||||
568 | if ($finder->count() === 0) { |
||||
569 | throw new StatemachineException( |
||||
570 | sprintf( |
||||
571 | 'Could not find "%s". Please check your process definition location', |
||||
572 | $fileName, |
||||
573 | ), |
||||
574 | ); |
||||
575 | } |
||||
576 | } |
||||
577 | |||||
578 | /** |
||||
579 | * @param string $fileName |
||||
580 | * |
||||
581 | * @return string |
||||
582 | */ |
||||
583 | protected function createSubProcessPathPattern($fileName) |
||||
584 | { |
||||
585 | return '/\b' . preg_quote(dirname($fileName), '/') . '\b/'; |
||||
586 | } |
||||
587 | } |
||||
588 |