GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Branch dev (d5e133)
by Андрей
20:27 queued 13s
created

Dispatcher::onLoadMetadataHandler()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 25
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 25
rs 8.5806
c 1
b 0
f 0
cc 4
eloc 15
nc 4
nop 1
1
<?php
2
/**
3
 * @link https://github.com/old-town/workflow-zf2-dispatch
4
 * @author  Malofeykin Andrey  <[email protected]>
5
 */
6
namespace OldTown\Workflow\ZF2\Dispatch\Dispatcher;
7
8
use OldTown\Workflow\TransientVars\TransientVarsInterface;
9
use Zend\EventManager\EventManagerAwareTrait;
10
use OldTown\Workflow\ZF2\ServiceEngine\Workflow as WorkflowService;
11
use OldTown\Workflow\ZF2\Dispatch\Metadata\Reader\ReaderInterface;
12
use ReflectionClass;
13
use OldTown\Workflow\ZF2\Dispatch\Metadata\Storage\MetadataInterface;
14
use Zend\Mvc\Controller\AbstractController;
15
use Traversable;
16
use Zend\Stdlib\ArrayUtils;
17
use Zend\Validator\ValidatorPluginManager;
18
use Zend\Validator\ValidatorChain;
19
use Zend\Validator\ValidatorInterface;
20
use OldTown\Workflow\TransientVars\BaseTransientVars;
21
use OldTown\Workflow\ZF2\ServiceEngine\Workflow\TransitionResultInterface;
22
23
/**
24
 * Class Dispatcher
25
 *
26
 * @package OldTown\Workflow\ZF2\Dispatch\Dispatcher
27
 */
28
class Dispatcher implements DispatcherInterface
29
{
30
    use EventManagerAwareTrait;
31
32
    /**
33
     * @var string
34
     */
35
    const WORKFLOW_DISPATCH_EVENT = 'workflowDispatchEvent';
36
37
    /**
38
     * Имя класса события
39
     *
40
     * @var string
41
     */
42
    protected $workflowDispatchEventClassName = WorkflowDispatchEvent::class;
43
44
    /**
45
     * Имя класса события
46
     *
47
     * @var string
48
     */
49
    protected $transientVarsClassName = BaseTransientVars::class;
50
51
    /**
52
     * @var WorkflowService
53
     */
54
    protected $workflowService;
55
56
    /**
57
     * @var ReaderInterface
58
     */
59
    protected $metadataReader;
60
61
    /**
62
     * @var ValidatorPluginManager
63
     */
64
    protected $validatorManager;
65
66
    /**
67
     * @param array $options
68
     */
69
    public function __construct(array $options = [])
70
    {
71
        call_user_func_array([$this, 'init'], $options);
72
    }
73
74
    /**
75
     * @param WorkflowService        $workflowService
76
     * @param ReaderInterface        $metadataReader
77
     * @param ValidatorPluginManager $validatorManager
78
     */
79
    protected function init(WorkflowService $workflowService, ReaderInterface $metadataReader, ValidatorPluginManager $validatorManager)
80
    {
81
        $this->setWorkflowService($workflowService);
82
        $this->setMetadataReader($metadataReader);
83
        $this->setValidatorManager($validatorManager);
84
    }
85
86
    /**
87
     * Фабрика для создания событий
88
     *
89
     * @return WorkflowDispatchEventInterface
90
     */
91 View Code Duplication
    public function workflowDispatchEventFactory()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
92
    {
93
        $className = $this->getWorkflowDispatchEventClassName();
94
        $r = new ReflectionClass($className);
95
96
        $instance = $r->newInstance();
97
98
        if (!$instance instanceof WorkflowDispatchEventInterface) {
99
            $errMsg = sprintf('Class %s not implement %s', $className, WorkflowDispatchEventInterface::class);
100
            throw new Exception\WorkflowDispatchEventException($errMsg);
101
        }
102
103
        return $instance;
104
    }
105
106
    /**
107
     * Диспетчирезация работы с workflow
108
     *
109
     * @param WorkflowDispatchEventInterface $event
110
     *
111
     * @return void
112
     */
113
    public function dispatch(WorkflowDispatchEventInterface $event)
114
    {
115
        $event->getMvcEvent()->setParam(static::WORKFLOW_DISPATCH_EVENT, $event);
116
        $event->setTarget($this);
117
118
        $metadataResult = $this->getEventManager()->trigger(WorkflowDispatchEventInterface::LOAD_METADATA_EVENT, $event, function ($test) {
119
            return ($test instanceof MetadataInterface);
120
        });
121
        $metadata = $metadataResult->last();
122
123
        if (!$metadata instanceof MetadataInterface) {
124
            return;
125
        }
126
127
        $event->setMetadata($metadata);
128
129
        $prepareData = [];
130
        if ($metadata->isFlagRunPrepareData()) {
131
            $prepareDataResults = $this->getEventManager()->trigger(WorkflowDispatchEventInterface::PREPARE_DATA_EVENT, $event);
132
            foreach ($prepareDataResults as $prepareDataResult) {
133
                if (is_array($prepareDataResult) || $prepareDataResult instanceof Traversable) {
134
                    $prepareData = ArrayUtils::merge($prepareData, $prepareDataResult);
0 ignored issues
show
Bug introduced by
It seems like $prepareDataResult defined by $prepareDataResult on line 132 can also be of type object<Traversable>; however, Zend\Stdlib\ArrayUtils::merge() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
135
                }
136
            }
137
        }
138
        $event->setPrepareData($prepareData);
139
140
141
        $flagRunWorkflow = $metadata->isWorkflowDispatch();
142
        if (true === $flagRunWorkflow) {
143
            $dispatchConditionsResults = $this->getEventManager()->trigger(WorkflowDispatchEventInterface::CHECK_RUN_WORKFLOW_EVENT, $event);
144
            foreach ($dispatchConditionsResults as $dispatchConditionsResult) {
145
                if (false === $dispatchConditionsResult) {
146
                    $flagRunWorkflow = false;
147
                    break;
148
                }
149
            }
150
        }
151
152
        if (true === $flagRunWorkflow) {
153
            $runWorkflowResults = $this->getEventManager()->trigger(WorkflowDispatchEventInterface::RUN_WORKFLOW_EVENT, $event, function ($result) {
154
                return ($result instanceof TransitionResultInterface);
155
            });
156
157
            $workflowResult = $runWorkflowResults->last();
158
            if ($workflowResult instanceof TransitionResultInterface) {
159
                $event->setWorkflowResult($workflowResult);
160
            }
161
        }
162
    }
163
164
    /**
165
     * Добавление подписчиков по умолчанию
166
     *
167
     */
168
    public function attachDefaultListeners()
169
    {
170
        $em = $this->getEventManager();
171
        $em->attach(WorkflowDispatchEventInterface::LOAD_METADATA_EVENT, [$this, 'onLoadMetadataHandler']);
172
        $em->attach(WorkflowDispatchEventInterface::PREPARE_DATA_EVENT, [$this, 'onPrepareDataHandler']);
173
        $em->attach(WorkflowDispatchEventInterface::CHECK_RUN_WORKFLOW_EVENT, [$this, 'onCheckRunWorkflowHandler']);
174
        $em->attach(WorkflowDispatchEventInterface::RUN_WORKFLOW_EVENT, [$this, 'onRunWorkflowHandler']);
175
    }
176
177
    /**
178
     * Получение метаданных
179
     *
180
     * @param WorkflowDispatchEventInterface $e
181
     *
182
     * @return MetadataInterface|null
183
     */
184
    public function onLoadMetadataHandler(WorkflowDispatchEventInterface $e)
185
    {
186
        $mvcEvent = $e->getMvcEvent();
187
        $controller = $mvcEvent->getTarget();
188
        if (!$controller instanceof AbstractController) {
189
            return null;
190
        }
191
192
        $routeMatch = $mvcEvent->getRouteMatch();
193
        if (!$routeMatch) {
194
            return null;
195
        }
196
197
        $action = $routeMatch->getParam('action', 'not-found');
198
        $actionMethod = AbstractController::getMethodFromAction($action);
199
200
        if (!method_exists($controller, $actionMethod)) {
201
            return null;
202
        }
203
204
        $controllerClassName = get_class($controller);
205
        $metadata = $this->getMetadataReader()->loadMetadataForAction($controllerClassName, $actionMethod);
206
207
        return $metadata;
208
    }
209
210
    /**
211
     * @param WorkflowDispatchEventInterface $e
212
     *
213
     * @return mixed|null
214
     */
215
    public function onPrepareDataHandler(WorkflowDispatchEventInterface $e)
216
    {
217
        $metadata = $e->getMetadata();
218
219
        $type = $metadata->getPrepareDataMethod();
220
        $handler = $metadata->getPrepareDataHandler();
221
222
        $prepareDataResult = null;
0 ignored issues
show
Unused Code introduced by
$prepareDataResult is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
223
        switch ($type) {
224
            case 'method': {
225
                $mvcEvent = $e->getMvcEvent();
226
                $controller = $mvcEvent->getTarget();
227
                if (!$controller instanceof AbstractController) {
228
                    $errMsg = sprintf('Controller not implement %s', AbstractController::class);
229
                    throw new Exception\PrepareDataException($errMsg);
230
                }
231
                $callback = [$controller, $handler];
232
                if (!is_callable($callback)) {
233
                    $errMsg = sprintf('Invalid handler"%s"', $handler);
234
                    throw new Exception\PrepareDataException($errMsg);
235
                }
236
                $prepareDataResult = call_user_func($callback, $e);
237
                if (null === $prepareDataResult) {
238
                    $prepareDataResult = [];
239
                }
240
241
                break;
242
            }
243
            default: {
244
                $errMsg = sprintf('Preparing data for Workflow will fail. Unknown handler type %s.', $type);
245
                throw new Exception\PrepareDataException($errMsg);
246
            }
247
        }
248
249
        if (!is_array($prepareDataResult) && !$prepareDataResult instanceof Traversable) {
250
            $errMsg = 'Data preparation The results should be an array or Traversable';
251
            throw new Exception\PrepareDataException($errMsg);
252
        }
253
254
255
        return $prepareDataResult;
256
    }
257
258
    /**
259
     * Проверка, на то нужно ли запускать workflow
260
     *
261
     * @param WorkflowDispatchEventInterface $e
262
     *
263
     * @return boolean|null
264
     */
265
    public function onCheckRunWorkflowHandler(WorkflowDispatchEventInterface $e)
266
    {
267
        $metadata = $e->getMetadata();
268
        if (!$metadata->getFlagHasConditions()) {
269
            return null;
270
        }
271
272
        $conditions = $metadata->getConditions();
273
274
        $validatorManager = $this->getValidatorManager();
275
276
        /** @var ValidatorChain $validatorChains */
277
        $validatorChains = $validatorManager->get(ValidatorChain::class);
278
279
        $mvcEvent = $e->getMvcEvent();
280
        $controller = $mvcEvent->getTarget();
281
        if (!$controller instanceof AbstractController) {
282
            $controller = null;
283
        }
284
285
286
        foreach ($conditions as $condition) {
287
            $type = $condition->getType();
288
            $handler = $condition->getHandler();
289
            switch ($type) {
290
                case 'method': {
291
                    if (null === $controller) {
292
                        $errMsg = 'Controller not specified';
293
                        throw new Exception\CheckRunWorkflowEventException($errMsg);
294
                    }
295
                    $callback = [$controller, $handler];
296
297
                    /** @var ValidatorInterface $callbackValidator */
298
                    $callbackValidator = $validatorManager->get('callback', $callback);
299
300
                    $validatorChains->attach($callbackValidator);
301
302
                    break;
303
                }
304
                case 'service': {
305
                    $validatorParams = $condition->getParams();
306
                    /** @var ValidatorInterface $validator */
307
                    $validator = $validatorManager->get($handler, $validatorParams);
308
309
                    $validatorChains->attach($validator);
310
311
                    break;
312
                }
313
                default: {
314
                    $errMsg = sprintf('Preparing data for Workflow will fail. Unknown handler type %s.', $type);
315
                    throw new Exception\PrepareDataException($errMsg);
316
                }
317
            }
318
        }
319
320
        $flagRunWorkflow = $validatorChains->isValid($e);
321
322
        return $flagRunWorkflow;
323
    }
324
325
    /**
326
     * Запуск workflow
327
     *
328
     * @param WorkflowDispatchEventInterface $e
329
     *
330
     * @return TransitionResultInterface
331
     */
332
    public function onRunWorkflowHandler(WorkflowDispatchEventInterface $e)
333
    {
334
        $mvcEvent = $e->getMvcEvent();
335
336
        $routeMatch = $mvcEvent->getRouteMatch();
337
        if (!$routeMatch) {
338
            return null;
339
        }
340
341
        $metadata = $e->getMetadata();
342
343
        $workflowManagerNameParam = $metadata->getWorkflowManagerNameRouterParam();
344
        $workflowManagerName = $routeMatch->getParam($workflowManagerNameParam, null);
345
        if (null === $workflowManagerName) {
346
            $errMsg = sprintf('Param "%s" not found', $workflowManagerNameParam);
347
            throw new Exception\InvalidArgumentException($errMsg);
348
        }
349
350
        $workflowActionNameParam = $metadata->getWorkflowActionNameRouterParam();
351
        $workflowActionName = $routeMatch->getParam($workflowActionNameParam, null);
352
        if (null === $workflowActionName) {
353
            $errMsg = sprintf('Param "%s" not found', $workflowActionNameParam);
354
            throw new Exception\InvalidArgumentException($errMsg);
355
        }
356
357
358
        $workflowActivity = $metadata->getWorkflowRunType();
359
        $transientVars = $this->factoryTransientVars();
360
361
        $prepareData = $e->getPrepareData();
362
        foreach ($prepareData as $key => $value) {
363
            $transientVars[$key] = $value;
364
        }
365
366
        $result = null;
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
367
        switch ($workflowActivity) {
368 View Code Duplication
            case 'initialize': {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
369
                $workflowNameParam = $metadata->getWorkflowNameRouterParam();
370
                $workflowName = $routeMatch->getParam($workflowNameParam, null);
371
                if (null === $workflowName) {
372
                    $errMsg = sprintf('Param "%s" not found', $workflowNameParam);
373
                    throw new Exception\InvalidArgumentException($errMsg);
374
                }
375
376
                $result = $this->getWorkflowService()->initialize($workflowManagerName, $workflowName, $workflowActionName, $transientVars);
377
                break;
378
            }
379 View Code Duplication
            case 'doAction': {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
380
                $entryIdParam = $metadata->getEntryIdRouterParam();
381
                $entryId = $routeMatch->getParam($entryIdParam, null);
382
                if (null === $entryId) {
383
                    $errMsg = sprintf('Param "%s" not found', $entryIdParam);
384
                    throw new Exception\InvalidArgumentException($errMsg);
385
                }
386
387
                $result = $this->getWorkflowService()->doAction($workflowManagerName, $entryId, $workflowActionName, $transientVars);
388
                break;
389
            }
390
            default: {
391
                $errMsg = sprintf('Invalid activity %s', $workflowActivity);
392
                throw new Exception\InvalidArgumentException($errMsg);
393
            }
394
        }
395
396
        return $result;
397
    }
398
399
    /**
400
     *
401
     * @return TransientVarsInterface
402
     */
403 View Code Duplication
    public function factoryTransientVars()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
404
    {
405
        $className = $this->getTransientVarsClassName();
406
        $r = new ReflectionClass($className);
407
408
        $instance = $r->newInstance();
409
410
        if (!$instance instanceof TransientVarsInterface) {
411
            $errMsg = sprintf('Class %s not implement %s', $className, TransientVarsInterface::class);
412
            throw new Exception\WorkflowDispatchEventException($errMsg);
413
        }
414
415
        return $instance;
416
    }
417
418
419
    /**
420
     * @return WorkflowService
421
     */
422
    public function getWorkflowService()
423
    {
424
        return $this->workflowService;
425
    }
426
427
    /**
428
     * @param WorkflowService $workflowService
429
     *
430
     * @return $this
431
     */
432
    public function setWorkflowService(WorkflowService $workflowService)
433
    {
434
        $this->workflowService = $workflowService;
435
436
        return $this;
437
    }
438
439
    /**
440
     * @return ReaderInterface
441
     */
442
    public function getMetadataReader()
443
    {
444
        return $this->metadataReader;
445
    }
446
447
    /**
448
     * @param ReaderInterface $metadataReader
449
     *
450
     * @return $this
451
     */
452
    public function setMetadataReader(ReaderInterface $metadataReader)
453
    {
454
        $this->metadataReader = $metadataReader;
455
456
        return $this;
457
    }
458
459
    /**
460
     * @return ValidatorPluginManager
461
     */
462
    public function getValidatorManager()
463
    {
464
        return $this->validatorManager;
465
    }
466
467
    /**
468
     * @param ValidatorPluginManager $validatorManager
469
     *
470
     * @return $this
471
     */
472
    public function setValidatorManager(ValidatorPluginManager $validatorManager)
473
    {
474
        $this->validatorManager = $validatorManager;
475
476
        return $this;
477
    }
478
479
    /**
480
     * @return string
481
     */
482
    public function getWorkflowDispatchEventClassName()
483
    {
484
        return $this->workflowDispatchEventClassName;
485
    }
486
487
    /**
488
     * @param string $workflowDispatchEventClassName
489
     *
490
     * @return $this
491
     */
492
    public function setWorkflowDispatchEventClassName($workflowDispatchEventClassName)
493
    {
494
        $this->workflowDispatchEventClassName = (string)$workflowDispatchEventClassName;
495
496
        return $this;
497
    }
498
499
    /**
500
     * @return string
501
     */
502
    public function getTransientVarsClassName()
503
    {
504
        return $this->transientVarsClassName;
505
    }
506
507
    /**
508
     * @param string $transientVarsClassName
509
     *
510
     * @return $this
511
     */
512
    public function setTransientVarsClassName($transientVarsClassName)
513
    {
514
        $this->transientVarsClassName = (string)$transientVarsClassName;
515
516
        return $this;
517
    }
518
}
519