Builder::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 21
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
c 0
b 0
f 0
nc 1
nop 9
dl 0
loc 21
rs 9.9666

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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 Spryker\Zed\Oms\OmsConfig;
20
use Symfony\Component\Finder\Finder as SymfonyFinder;
21
22
class Builder implements BuilderInterface
23
{
24
    /**
25
     * @var \SimpleXMLElement
26
     */
27
    protected $rootElement;
28
29
    /**
30
     * @var array<\Spryker\Zed\Oms\Business\Process\ProcessInterface>
31
     */
32
    protected static $processBuffer = [];
33
34
    /**
35
     * @var \Spryker\Zed\Oms\Business\Process\EventInterface
36
     */
37
    protected $event;
38
39
    /**
40
     * @var \Spryker\Zed\Oms\Business\Process\StateInterface
41
     */
42
    protected $state;
43
44
    /**
45
     * @var \Spryker\Zed\Oms\Business\Process\TransitionInterface
46
     */
47
    protected $transition;
48
49
    /**
50
     * @var \Spryker\Zed\Oms\Business\Process\ProcessInterface
51
     */
52
    protected $process;
53
54
    /**
55
     * @var array|string
56
     */
57
    protected $processDefinitionLocation;
58
59
    /**
60
     * @var string
61
     */
62
    protected $subProcessPrefixDelimiter;
63
64
    /**
65
     * @var \Spryker\Zed\Oms\Business\Reader\ProcessCacheReaderInterface
66
     */
67
    protected ProcessCacheReaderInterface $processCacheReader;
68
69
    /**
70
     * @var \Spryker\Zed\Oms\Business\Writer\ProcessCacheWriterInterface
71
     */
72
    protected ProcessCacheWriterInterface $processCacheWriter;
73
74
    /**
75
     * @var \Spryker\Zed\Oms\OmsConfig
76
     */
77
    protected OmsConfig $config;
78
79
    /**
80
     * @param \Spryker\Zed\Oms\Business\Process\EventInterface $event
81
     * @param \Spryker\Zed\Oms\Business\Process\StateInterface $state
82
     * @param \Spryker\Zed\Oms\Business\Process\TransitionInterface $transition
83
     * @param \Spryker\Zed\Oms\Business\Process\ProcessInterface $process
84
     * @param array|string $processDefinitionLocation
85
     * @param \Spryker\Zed\Oms\Business\Reader\ProcessCacheReaderInterface $processCacheReader
86
     * @param \Spryker\Zed\Oms\Business\Writer\ProcessCacheWriterInterface $processCacheWriter
87
     * @param \Spryker\Zed\Oms\OmsConfig $config
88
     * @param string $subProcessPrefixDelimiter
89
     */
90
    public function __construct(
91
        EventInterface $event,
92
        StateInterface $state,
93
        TransitionInterface $transition,
94
        ProcessInterface $process,
95
        $processDefinitionLocation,
96
        ProcessCacheReaderInterface $processCacheReader,
97
        ProcessCacheWriterInterface $processCacheWriter,
98
        OmsConfig $config,
99
        $subProcessPrefixDelimiter = ' - '
100
    ) {
101
        $this->event = $event;
102
        $this->state = $state;
103
        $this->transition = $transition;
104
        $this->process = $process;
105
        $this->processCacheReader = $processCacheReader;
106
        $this->processCacheWriter = $processCacheWriter;
107
        $this->config = $config;
108
        $this->subProcessPrefixDelimiter = $subProcessPrefixDelimiter;
109
110
        $this->setProcessDefinitionLocation($processDefinitionLocation);
111
    }
112
113
    /**
114
     * @param string $processName
115
     * @param bool $regenerateCache
116
     *
117
     * @return \Spryker\Zed\Oms\Business\Process\ProcessInterface
118
     */
119
    public function createProcess($processName, bool $regenerateCache = false): ProcessInterface
120
    {
121
        if (isset(static::$processBuffer[$processName])) {
122
            return static::$processBuffer[$processName];
123
        }
124
125
        if (!$this->config->isProcessCacheEnabled()) {
126
            $mainProcess = $this->createMainProcess($processName);
127
128
            static::$processBuffer[$processName] = $mainProcess;
129
130
            return static::$processBuffer[$processName];
131
        }
132
133
        $isProcessCached = $this->processCacheReader->hasProcess($processName);
134
135
        if ($isProcessCached) {
136
            $process = $this->processCacheReader->getProcess($processName);
137
        }
138
139
        if (!$isProcessCached || $regenerateCache) {
140
            $process = $this->createMainProcess($processName);
141
            $this->processCacheWriter->cacheProcess($process, $processName);
142
        }
143
144
        static::$processBuffer[$processName] = $process;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $process does not seem to be defined for all execution paths leading up to this point.
Loading history...
145
146
        return static::$processBuffer[$processName];
147
    }
148
149
    /**
150
     * @param string $processName
151
     *
152
     * @return \Spryker\Zed\Oms\Business\Process\ProcessInterface
153
     */
154
    protected function createMainProcess(string $processName): ProcessInterface
155
    {
156
        $this->rootElement = $this->loadXmlFromProcessName($processName);
157
158
        $this->mergeSubProcessFiles();
159
160
        /** @var array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> $processMap */
161
        $processMap = [];
162
163
        [$processMap, $mainProcess] = $this->createSubProcess($processMap);
164
165
        $stateToProcessMap = $this->createStates($processMap);
166
167
        $this->createSubProcesses($processMap);
168
169
        $eventMap = $this->createEvents();
170
171
        $this->createTransitions($stateToProcessMap, $processMap, $eventMap);
172
173
        return $mainProcess->warmupCache();
174
    }
175
176
    /**
177
     * @return void
178
     */
179
    protected function mergeSubProcessFiles()
180
    {
181
        foreach ($this->rootElement->children() as $xmlProcess) {
182
            $processFile = $this->getAttributeString($xmlProcess, 'file');
0 ignored issues
show
Bug introduced by
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 ignore-type  annotation

182
            $processFile = $this->getAttributeString(/** @scrutinizer ignore-type */ $xmlProcess, 'file');
Loading history...
183
            $processName = $this->getAttributeString($xmlProcess, 'name');
184
            $processPrefix = $this->getAttributeString($xmlProcess, 'prefix');
185
186
            if ($processFile) {
187
                $xmlSubProcess = $this->loadXmlFromFileName(str_replace(' ', '_', $processFile));
188
189
                if ($processName) {
190
                    $xmlSubProcess->children()->process[0]['name'] = $processName;
0 ignored issues
show
Bug introduced by
The property process does not seem to exist on SimpleXMLElement.
Loading history...
191
                }
192
193
                $this->recursiveMerge($xmlSubProcess, $this->rootElement, $processPrefix);
194
            }
195
        }
196
    }
197
198
    /**
199
     * @param \SimpleXMLElement $fromXmlElement
200
     * @param \SimpleXMLElement $intoXmlNode
201
     * @param string|null $prefix
202
     *
203
     * @return void
204
     */
205
    protected function recursiveMerge($fromXmlElement, $intoXmlNode, $prefix = null)
206
    {
207
        /** @var array<\SimpleXMLElement> $xmlElements */
208
        $xmlElements = $fromXmlElement->children();
209
        if (!$xmlElements) {
210
            return;
211
        }
212
213
        foreach ($xmlElements as $xmlElement) {
214
            $xmlElement = $this->prefixSubProcessElementValue($xmlElement, $prefix);
215
            $xmlElement = $this->prefixSubProcessElementAttributes($xmlElement, $prefix);
216
217
            $child = $intoXmlNode->addChild($xmlElement->getName(), $xmlElement);
218
            $attributes = $xmlElement->attributes();
219
            foreach ($attributes as $k => $v) {
220
                $child->addAttribute($k, $v);
221
            }
222
223
            $this->recursiveMerge($xmlElement, $child, $prefix);
224
        }
225
    }
226
227
    /**
228
     * @param \SimpleXMLElement $xmlElement
229
     * @param string|null $prefix
230
     *
231
     * @return \SimpleXMLElement
232
     */
233
    protected function prefixSubProcessElementValue(SimpleXMLElement $xmlElement, $prefix = null)
234
    {
235
        if ($prefix === null) {
236
            return $xmlElement;
237
        }
238
239
        $namespaceDependentElementNames = ['source', 'target', 'event'];
240
241
        if (in_array($xmlElement->getName(), $namespaceDependentElementNames)) {
242
            $xmlElement[0] = $prefix . $this->subProcessPrefixDelimiter . $xmlElement[0];
243
        }
244
245
        return $xmlElement;
246
    }
247
248
    /**
249
     * @param \SimpleXMLElement $xmlElement
250
     * @param string|null $prefix
251
     *
252
     * @return \SimpleXMLElement
253
     */
254
    protected function prefixSubProcessElementAttributes(SimpleXMLElement $xmlElement, $prefix = null)
255
    {
256
        if ($prefix === null) {
257
            return $xmlElement;
258
        }
259
260
        $namespaceDependentElementNames = ['state', 'event'];
261
262
        if (in_array($xmlElement->getName(), $namespaceDependentElementNames)) {
263
            $xmlElement->attributes()['name'] = $prefix . $this->subProcessPrefixDelimiter . $xmlElement->attributes()['name'];
264
        }
265
266
        return $xmlElement;
267
    }
268
269
    /**
270
     * @param string $fileName
271
     *
272
     * @return \SimpleXMLElement
273
     */
274
    protected function loadXmlFromFileName($fileName)
275
    {
276
        $definitionFile = $this->locateProcessDefinition($fileName);
277
278
        return $this->loadXml($definitionFile->getContents());
279
    }
280
281
    /**
282
     * @param string $fileName
283
     *
284
     * @return \Symfony\Component\Finder\SplFileInfo
285
     */
286
    private function locateProcessDefinition($fileName)
287
    {
288
        $finder = $this->buildFinder($fileName);
289
290
        /** @phpstan-var \Symfony\Component\Finder\SplFileInfo */
291
        return current(iterator_to_array($finder->getIterator()));
292
    }
293
294
    /**
295
     * @param string $processName
296
     *
297
     * @return \SimpleXMLElement
298
     */
299
    protected function loadXmlFromProcessName($processName)
300
    {
301
        return $this->loadXmlFromFileName($processName . '.xml');
302
    }
303
304
    /**
305
     * @param string $xml
306
     *
307
     * @return \SimpleXMLElement
308
     */
309
    protected function loadXml($xml)
310
    {
311
        return new SimpleXMLElement($xml);
312
    }
313
314
    /**
315
     * @return array
316
     */
317
    protected function createEvents()
318
    {
319
        $eventMap = [];
320
321
        foreach ($this->rootElement as $xmlProcess) {
322
            if (!isset($xmlProcess->events)) {
323
                continue;
324
            }
325
326
            $xmlEvents = $xmlProcess->events->children();
327
            foreach ($xmlEvents as $xmlEvent) {
328
                $event = clone $this->event;
329
                $eventId = $this->getAttributeString($xmlEvent, 'name');
0 ignored issues
show
Bug introduced by
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 ignore-type  annotation

329
                $eventId = $this->getAttributeString(/** @scrutinizer ignore-type */ $xmlEvent, 'name');
Loading history...
330
                $event->setCommand($this->getAttributeString($xmlEvent, 'command'));
331
                $event->setManual($this->getAttributeBoolean($xmlEvent, 'manual'));
0 ignored issues
show
Bug introduced by
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 ignore-type  annotation

331
                $event->setManual($this->getAttributeBoolean(/** @scrutinizer ignore-type */ $xmlEvent, 'manual'));
Loading history...
332
                $event->setOnEnter($this->getAttributeBoolean($xmlEvent, 'onEnter'));
333
                $event->setTimeout($this->getAttributeString($xmlEvent, 'timeout'));
334
                $event->setTimeoutProcessor($this->getAttributeString($xmlEvent, 'timeoutProcessor'));
335
                if ($eventId === null) {
336
                    continue;
337
                }
338
339
                $event->setName($eventId);
340
                $eventMap[$event->getName()] = $event;
341
            }
342
        }
343
344
        return $eventMap;
345
    }
346
347
    /**
348
     * @param array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> $processMap
349
     *
350
     * @return array
351
     */
352
    protected function createSubProcess(array $processMap)
353
    {
354
        $mainProcess = null;
355
        $xmlProcesses = $this->rootElement->children();
356
357
        /** @var \SimpleXMLElement $xmlProcess */
358
        foreach ($xmlProcesses as $xmlProcess) {
359
            $process = clone $this->process;
360
            $processName = $this->getAttributeString($xmlProcess, 'name');
0 ignored issues
show
Bug introduced by
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 ignore-type  annotation

360
            $processName = $this->getAttributeString(/** @scrutinizer ignore-type */ $xmlProcess, 'name');
Loading history...
361
            $process->setName($processName);
362
            $processMap[$processName] = $process;
363
            $process->setIsMain($this->getAttributeBoolean($xmlProcess, 'main'));
0 ignored issues
show
Bug introduced by
It seems like $xmlProcess 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 ignore-type  annotation

363
            $process->setIsMain($this->getAttributeBoolean(/** @scrutinizer ignore-type */ $xmlProcess, 'main'));
Loading history...
364
365
            $process->setFile($this->getAttributeString($xmlProcess, 'file'));
366
367
            if ($process->getIsMain()) {
368
                $mainProcess = $process;
369
            }
370
        }
371
372
        return [$processMap, $mainProcess];
373
    }
374
375
    /**
376
     * @param array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> $processMap
377
     *
378
     * @return void
379
     */
380
    protected function createSubProcesses(array $processMap)
381
    {
382
        foreach ($this->rootElement as $xmlProcess) {
383
            $processName = $this->getAttributeString($xmlProcess, 'name');
0 ignored issues
show
Bug introduced by
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 ignore-type  annotation

383
            $processName = $this->getAttributeString(/** @scrutinizer ignore-type */ $xmlProcess, 'name');
Loading history...
384
385
            $process = $processMap[$processName];
386
387
            if ($xmlProcess->subprocesses) {
388
                $xmlSubProcesses = $xmlProcess->subprocesses->children();
389
390
                foreach ($xmlSubProcesses as $xmlSubProcess) {
391
                    $subProcessName = (string)$xmlSubProcess;
392
                    $subProcess = $processMap[$subProcessName];
393
                    $process->addSubProcess($subProcess);
394
                }
395
            }
396
        }
397
    }
398
399
    /**
400
     * @param array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> $processMap
401
     *
402
     * @return array<\Spryker\Zed\Oms\Business\Process\ProcessInterface>
403
     */
404
    protected function createStates(array $processMap)
405
    {
406
        $stateToProcessMap = [];
407
408
        $xmlProcesses = $this->rootElement->children();
409
        foreach ($xmlProcesses as $xmlProcess) {
410
            $processName = $this->getAttributeString($xmlProcess, 'name');
0 ignored issues
show
Bug introduced by
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 ignore-type  annotation

410
            $processName = $this->getAttributeString(/** @scrutinizer ignore-type */ $xmlProcess, 'name');
Loading history...
411
            $process = $processMap[$processName];
412
413
            if ($xmlProcess->states) {
414
                $xmlStates = $xmlProcess->states->children();
415
                /** @var \SimpleXMLElement $xmlState */
416
                foreach ($xmlStates as $xmlState) {
417
                    $state = clone $this->state;
418
                    $state->setName($this->getAttributeString($xmlState, 'name'));
419
                    $state->setDisplay($this->getAttributeString($xmlState, 'display'));
420
                    $state->setReserved($this->getAttributeBoolean($xmlState, 'reserved'));
0 ignored issues
show
Bug introduced by
It seems like $xmlState 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 ignore-type  annotation

420
                    $state->setReserved($this->getAttributeBoolean(/** @scrutinizer ignore-type */ $xmlState, 'reserved'));
Loading history...
421
                    $state->setProcess($process);
422
423
                    /** @var array $stateFlag */
424
                    $stateFlag = $xmlState->flag;
425
                    if ($stateFlag) {
426
                        $flags = $xmlState->children();
0 ignored issues
show
Bug introduced by
The method children() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

426
                        /** @scrutinizer ignore-call */ 
427
                        $flags = $xmlState->children();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
427
                        foreach ($flags->flag as $flag) {
428
                            $state->addFlag((string)$flag);
429
                        }
430
                    }
431
432
                    $process->addState($state);
433
                    $stateToProcessMap[$state->getName()] = $process;
434
                }
435
            }
436
        }
437
438
        return $stateToProcessMap;
439
    }
440
441
    /**
442
     * @param array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> $stateToProcessMap
443
     * @param array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> $processMap
444
     * @param array<\Spryker\Zed\Oms\Business\Process\EventInterface> $eventMap
445
     *
446
     * @throws \LogicException
447
     *
448
     * @return void
449
     */
450
    protected function createTransitions(array $stateToProcessMap, array $processMap, array $eventMap)
451
    {
452
        foreach ($this->rootElement as $xmlProcess) {
453
            if ($xmlProcess->transitions) {
454
                $xmlTransitions = $xmlProcess->transitions->children();
455
456
                $processName = $this->getAttributeString($xmlProcess, 'name');
0 ignored issues
show
Bug introduced by
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 ignore-type  annotation

456
                $processName = $this->getAttributeString(/** @scrutinizer ignore-type */ $xmlProcess, 'name');
Loading history...
457
458
                foreach ($xmlTransitions as $xmlTransition) {
459
                    $transition = clone $this->transition;
460
461
                    $transition->setCondition($this->getAttributeString($xmlTransition, 'condition'));
462
463
                    $transition->setHappy($this->getAttributeBoolean($xmlTransition, 'happy'));
0 ignored issues
show
Bug introduced by
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 ignore-type  annotation

463
                    $transition->setHappy($this->getAttributeBoolean(/** @scrutinizer ignore-type */ $xmlTransition, 'happy'));
Loading history...
464
465
                    $sourceName = (string)$xmlTransition->source;
466
467
                    if (!isset($stateToProcessMap[$sourceName])) {
468
                        throw new LogicException(sprintf('Source: %s does not exist.', $sourceName));
469
                    }
470
471
                    $sourceProcess = $stateToProcessMap[$sourceName];
472
                    $sourceState = $sourceProcess->getState($sourceName);
473
                    $transition->setSource($sourceState);
474
                    $sourceState->addOutgoingTransition($transition);
475
476
                    $targetName = (string)$xmlTransition->target;
477
478
                    if (!isset($stateToProcessMap[$targetName])) {
479
                        throw new LogicException('Target: "' . $targetName . '" does not exist from source: "' . $sourceName . '"');
480
                    }
481
                    $targetProcess = $stateToProcessMap[$targetName];
482
                    $targetState = $targetProcess->getState($targetName);
483
                    $transition->setTarget($targetState);
484
                    $targetState->addIncomingTransition($transition);
485
486
                    if (isset($xmlTransition->event)) {
487
                        $eventId = (string)$xmlTransition->event;
488
489
                        if (!isset($eventMap[$eventId])) {
490
                            throw new LogicException('Event: "' . $eventId . '" does not exist from source: "' . $sourceName . '"');
491
                        }
492
493
                        $event = $eventMap[$eventId];
494
                        $event->addTransition($transition);
495
                        $transition->setEvent($event);
496
                    }
497
498
                    $processMap[$processName]->addTransition($transition);
499
                }
500
            }
501
        }
502
    }
503
504
    /**
505
     * @param \SimpleXMLElement $xmlElement
506
     * @param string $attributeName
507
     *
508
     * @return string|null
509
     */
510
    protected function getAttributeString(SimpleXMLElement $xmlElement, $attributeName)
511
    {
512
        $string = (string)$xmlElement->attributes()[$attributeName];
513
        $string = ($string === '') ? null : $string;
514
515
        return $string;
516
    }
517
518
    /**
519
     * @param \SimpleXMLElement $xmlElement
520
     * @param string $attributeName
521
     *
522
     * @return bool
523
     */
524
    protected function getAttributeBoolean(SimpleXMLElement $xmlElement, $attributeName)
525
    {
526
        return (string)$xmlElement->attributes()[$attributeName] === 'true';
527
    }
528
529
    /**
530
     * @param array|string|null $processDefinitionLocation
531
     *
532
     * @return void
533
     */
534
    private function setProcessDefinitionLocation($processDefinitionLocation)
535
    {
536
        $this->processDefinitionLocation = $processDefinitionLocation;
537
    }
538
539
    /**
540
     * @param string $fileName
541
     *
542
     * @return \Symfony\Component\Finder\Finder
543
     */
544
    protected function buildFinder($fileName)
545
    {
546
        $finder = $this->getFinder();
547
        $finder->in($this->processDefinitionLocation);
548
        if (strpos($fileName, '/') !== false) {
549
            $finder->path($this->createSubProcessPathPattern($fileName));
550
            $finder->name(basename($fileName));
551
        } else {
552
            $finder->name($fileName);
553
        }
554
555
        $this->validateFinder($finder, $fileName);
556
557
        return $finder;
558
    }
559
560
    /**
561
     * @return \Symfony\Component\Finder\Finder
562
     */
563
    protected function getFinder()
564
    {
565
        return new SymfonyFinder();
566
    }
567
568
    /**
569
     * @param \Symfony\Component\Finder\Finder $finder
570
     * @param string $fileName
571
     *
572
     * @throws \Spryker\Zed\Oms\Business\Exception\StatemachineException
573
     *
574
     * @return void
575
     */
576
    protected function validateFinder(SymfonyFinder $finder, $fileName)
577
    {
578
        if ($finder->count() > 1) {
579
            throw new StatemachineException(
580
                sprintf(
581
                    '"%s" found in more then one location. Could not determine which one to choose. Please check your process definition location',
582
                    $fileName,
583
                ),
584
            );
585
        }
586
587
        if ($finder->count() === 0) {
588
            throw new StatemachineException(
589
                sprintf(
590
                    'Could not find "%s". Please check your process definition location',
591
                    $fileName,
592
                ),
593
            );
594
        }
595
    }
596
597
    /**
598
     * @param string $fileName
599
     *
600
     * @return string
601
     */
602
    protected function createSubProcessPathPattern($fileName)
603
    {
604
        return '/\b' . preg_quote(dirname($fileName), '/') . '\b/';
605
    }
606
}
607