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.

ResultDescriptor   C
last analyzed

Complexity

Total Complexity 77

Size/Duplication

Total Lines 572
Duplicated Lines 18.53 %

Coupling/Cohesion

Components 1
Dependencies 11

Test Coverage

Coverage 100%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
wmc 77
c 4
b 0
f 0
lcom 1
cbo 11
dl 106
loc 572
ccs 236
cts 236
cp 1
rs 5.3019

25 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 3
F init() 24 74 14
A getOldStatus() 0 4 1
A setOldStatus() 0 6 1
A getStatus() 0 4 1
A setStatus() 0 6 1
A getDueDate() 0 4 1
A getJoin() 0 4 1
A setJoin() 0 6 1
A getSplit() 0 4 1
A setSplit() 0 6 1
A getStep() 0 4 1
A setStep() 0 7 1
A getOwner() 0 4 1
A setOwner() 0 6 1
A getDisplayName() 0 4 1
A setDisplayName() 0 15 3
A getValidators() 0 4 1
A setValidators() 0 6 1
A getPreFunctions() 0 4 1
A getPostFunctions() 0 4 1
A printPostFunctions() 21 21 4
A printPreFunctions() 20 20 4
D writeXml() 41 82 23
C validate() 0 34 8

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like ResultDescriptor often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ResultDescriptor, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @link https://github.com/old-town/old-town-workflow
4
 * @author  Malofeykin Andrey  <[email protected]>
5
 */
6
namespace OldTown\Workflow\Loader;
7
8
use DOMElement;
9
use OldTown\Workflow\Exception\InvalidDescriptorException;
10
use OldTown\Workflow\Exception\InvalidWorkflowDescriptorException;
11
use OldTown\Workflow\Exception\InvalidWriteWorkflowException;
12
use SplObjectStorage;
13
use DOMDocument;
14
15
/**
16
 * Class ConditionDescriptor
17
 *
18
 * @package OldTown\Workflow\Loader
19
 *
20
 * @method ActionDescriptor getParent()
21
 */
22
class ResultDescriptor extends AbstractDescriptor implements ValidateDescriptorInterface, WriteXmlInterface
23
{
24
    use Traits\IdTrait;
25
26
    /**
27
     * Предыдущий статус
28
     *
29
     * @var string
30
     */
31
    protected $oldStatus;
32
33
    /**
34
     * Статус
35
     *
36
     * @var string
37
     */
38
    protected $status;
39
40
    /**
41
     * Срок
42
     *
43
     * @var string
44
     */
45
    protected $dueDate;
46
47
    /**
48
     * @var integer|null
49
     */
50
    protected $join;
51
52
    /**
53
     * @var integer|null
54
     */
55
    protected $split;
56
57
    /**
58
     * @var integer
59
     */
60
    protected $step;
61
62
    /**
63
     * @var bool
64
     */
65
    protected $hasStep = false;
66
67
    /**
68
     * @var string
69
     */
70
    protected $owner;
71
72
    /**
73
     * @var string
74
     */
75
    protected $displayName;
76
77
    /**
78
     * @var ValidatorDescriptor[]|SplObjectStorage
79
     */
80
    protected $validators;
81
82
    /**
83
     * @var FunctionDescriptor[]|SplObjectStorage
84
     */
85
    protected $preFunctions;
86
87
    /**
88
     * @var FunctionDescriptor[]|SplObjectStorage
89
     */
90
    protected $postFunctions;
91
92
    /**
93
     * Если флаг установлен в true, то не запускаем инициализацию дескриптора для элемента
94
     *
95
     * @var bool
96
     */
97
    protected $flagNotExecuteInit = false;
98
99
    /**
100
     * @param $element
101
     */
102 101
    public function __construct(DOMElement $element = null)
103
    {
104 101
        $validators = new SplObjectStorage();
105 101
        $this->setValidators($validators);
106
107 101
        $this->preFunctions = new SplObjectStorage();
108 101
        $this->postFunctions = new SplObjectStorage();
109
110 101
        parent::__construct($element);
111
112 101
        if (null !== $element && !$this->flagNotExecuteInit) {
113 81
            $this->init($element);
114 81
        }
115 101
    }
116
117
    /**
118
     * @param DOMElement $result
119
     *
120
     * @return void
121
     */
122 98
    protected function init(DOMElement $result)
123
    {
124 98
        $oldStatus = XmlUtil::getRequiredAttributeValue($result, 'old-status');
125 98
        $this->setOldStatus($oldStatus);
126 98
        if ($result->hasAttribute('status')) {
127 75
            $status = XmlUtil::getRequiredAttributeValue($result, 'status');
128 75
            $this->setStatus($status);
129 75
        }
130
131 98
        $this->parseId($result, false);
132
133 98
        if ($result->hasAttribute('due-date')) {
134 5
            $this->dueDate = XmlUtil::getRequiredAttributeValue($result, 'due-date');
135 5
        }
136
137 98
        if ($result->hasAttribute('split')) {
138 17
            $split = XmlUtil::getRequiredAttributeValue($result, 'split');
139 17
            $this->setSplit($split);
140 17
        }
141
142
143 98
        if ($result->hasAttribute('join')) {
144 21
            $join = XmlUtil::getRequiredAttributeValue($result, 'join');
145 21
            $this->setJoin($join);
146 21
        }
147
148 98
        if ($result->hasAttribute('step')) {
149 76
            $step = XmlUtil::getRequiredAttributeValue($result, 'step');
150 76
            $this->setStep($step);
151 76
        }
152
153 98
        if ($result->hasAttribute('owner')) {
154 20
            $owner = XmlUtil::getRequiredAttributeValue($result, 'owner');
155 20
            $this->setOwner($owner);
156 20
        }
157
158 98
        if ($result->hasAttribute('display-name')) {
159 5
            $displayName = XmlUtil::getRequiredAttributeValue($result, 'display-name');
160 5
            $this->setDisplayName($displayName);
161 5
        }
162
163
        // set up validators -- OPTIONAL
164 98
        $v = XMLUtil::getChildElement($result, 'validators');
165 98 View Code Duplication
        if (null !== $v) {
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...
166 6
            $validators = XMLUtil::getChildElements($v, 'validator');
167 6
            foreach ($validators as $validator) {
168 6
                $validatorDescriptor = DescriptorFactory::getFactory()->createValidatorDescriptor($validator);
169 6
                $validatorDescriptor->setParent($this);
170 6
                $this->validators->attach($validatorDescriptor);
171 6
            }
172 6
        }
173
174
        // set up pre-functions -- OPTIONAL
175 98
        $pre = XMLUtil::getChildElement($result, 'pre-functions');
176 98 View Code Duplication
        if (null !== $pre) {
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...
177 6
            $preFunctions = XMLUtil::getChildElements($pre, 'function');
178 6
            foreach ($preFunctions as $preFunction) {
179 6
                $functionDescriptor = DescriptorFactory::getFactory()->createFunctionDescriptor($preFunction);
180 6
                $functionDescriptor->setParent($this);
181 6
                $this->preFunctions->attach($functionDescriptor);
182 6
            }
183 6
        }
184
185
        // set up post-functions - OPTIONAL
186 98
        $post = XMLUtil::getChildElement($result, 'post-functions');
187 98 View Code Duplication
        if (null !== $post) {
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...
188 17
            $postFunctions = XMLUtil::getChildElements($post, 'function');
189 17
            foreach ($postFunctions as $postFunction) {
190 17
                $functionDescriptor = DescriptorFactory::getFactory()->createFunctionDescriptor($postFunction);
191 17
                $functionDescriptor->setParent($this);
192 17
                $this->postFunctions->attach($functionDescriptor);
193 17
            }
194 17
        }
195 98
    }
196
197
    /**
198
     * Возвращает предыдущий статус
199
     *
200
     * @return string
201
     */
202 47
    public function getOldStatus()
203
    {
204 47
        return $this->oldStatus;
205
    }
206
207
    /**
208
     * Устанавливает значение предыдующего статуса
209
     *
210
     * @param string $oldStatus
211
     *
212
     * @return $this
213
     */
214 98
    public function setOldStatus($oldStatus)
215
    {
216 98
        $this->oldStatus = $oldStatus;
217
218 98
        return $this;
219
    }
220
221
    /**
222
     * Возвращает статус
223
     *
224
     * @return string
225
     */
226 52
    public function getStatus()
227
    {
228 52
        return $this->status;
229
    }
230
231
    /**
232
     * Устанавливает статус
233
     *
234
     * @param string $status
235
     *
236
     * @return $this
237
     */
238 75
    public function setStatus($status)
239
    {
240 75
        $this->status = (string)$status;
241
242 75
        return $this;
243
    }
244
245
    /**
246
     * Срок
247
     *
248
     * @return string
249
     */
250 47
    public function getDueDate()
251
    {
252 47
        return $this->dueDate;
253
    }
254
255
    /**
256
     * @return int|null
257
     */
258 70
    public function getJoin()
259
    {
260 70
        return $this->join;
261
    }
262
263
    /**
264
     * @param int $join
265
     *
266
     * @return $this
267
     */
268 21
    public function setJoin($join)
269
    {
270 21
        $this->join = (integer)$join;
271
272 21
        return $this;
273
    }
274
275
    /**
276
     * @return int|null
277
     */
278 67
    public function getSplit()
279
    {
280 67
        return $this->split;
281
    }
282
283
    /**
284
     * @param int|null $split
285
     *
286
     * @return $this
287
     */
288 17
    public function setSplit($split)
289
    {
290 17
        $this->split = (integer)$split;
291
292 17
        return $this;
293
    }
294
295
    /**
296
     * @return int
297
     */
298 41
    public function getStep()
299
    {
300 41
        return $this->step;
301
    }
302
303
    /**
304
     * @param int $step
305
     *
306
     * @return $this
307
     */
308 76
    public function setStep($step)
309
    {
310 76
        $this->step = (integer)$step;
311 76
        $this->hasStep = true;
312
313 76
        return $this;
314
    }
315
316
    /**
317
     * @return string
318
     */
319 35
    public function getOwner()
320
    {
321 35
        return $this->owner;
322
    }
323
324
    /**
325
     * @param string $owner
326
     *
327
     * @return $this
328
     */
329 20
    public function setOwner($owner)
330
    {
331 20
        $this->owner = (string)$owner;
332
333 20
        return $this;
334
    }
335
336
    /**
337
     * @return string
338
     */
339 21
    public function getDisplayName()
340
    {
341 21
        return $this->displayName;
342
    }
343
344
    /**
345
     * @param string $displayName
346
     *
347
     * @return $this
348
     */
349 7
    public function setDisplayName($displayName)
350
    {
351
        /** @var ActionDescriptor $parent */
352 7
        $parent = $this->getParent();
353 7
        if ($parent instanceof ActionDescriptor) {
354 2
            $parentName = $parent->getName();
355 2
            if ($displayName === $parentName) {
356 1
                $this->displayName = null;
357 1
                return $this;
358
            }
359 1
        }
360 6
        $this->displayName = $displayName;
361
362 6
        return $this;
363
    }
364
365
    /**
366
     * @return ValidatorDescriptor[]|SplObjectStorage
367
     */
368 58
    public function getValidators()
369
    {
370 58
        return $this->validators;
371
    }
372
373
    /**
374
     * @param ValidatorDescriptor[]|SplObjectStorage $validators
375
     *
376
     * @return $this
377
     */
378 101
    public function setValidators(SplObjectStorage $validators)
379
    {
380 101
        $this->validators = $validators;
381
382 101
        return $this;
383
    }
384
385
    /**
386
     * @return FunctionDescriptor[]|SplObjectStorage
387
     */
388 57
    public function getPreFunctions()
389
    {
390 57
        return $this->preFunctions;
391
    }
392
393
    /**
394
     * @return FunctionDescriptor[]|SplObjectStorage
395
     */
396 56
    public function getPostFunctions()
397
    {
398 56
        return $this->postFunctions;
399
    }
400
401
    /**
402
     * Вывод информации о функциях пост обработки
403
     *
404
     * @param DOMDocument $dom
405
     * @return DOMElement|null
406
     * @throws InvalidWriteWorkflowException
407
     */
408 24 View Code Duplication
    protected function printPostFunctions(DOMDocument $dom)
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...
409
    {
410 24
        $postFunctions = $this->getPostFunctions();
411 24
        if ($postFunctions->count() > 0) {
412 15
            $postFunctionsElements = $dom->createElement('post-functions');
413 15
            foreach ($postFunctions as $function) {
414
                try {
415 15
                    $functionElement = $function->writeXml($dom);
416 15
                } catch (\Exception $e) {
417 1
                    $errMsg  = 'Ошибка сохранения workflow. Ошибка в post-function';
418 1
                    throw new InvalidWriteWorkflowException($errMsg, $e->getCode(), $e);
419
                }
420
421 14
                $postFunctionsElements->appendChild($functionElement);
422 14
            }
423
424 14
            return $postFunctionsElements;
425
        }
426
427 20
        return null;
428
    }
429
430
    /**
431
     * Вывод информации о функциях пред обработки
432
     *
433
     * @param DOMDocument $dom
434
     * @return DOMElement|null
435
     *
436
     * @throws InvalidWriteWorkflowException
437
     */
438 25 View Code Duplication
    protected function printPreFunctions(DOMDocument $dom)
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...
439
    {
440 25
        $preFunctions = $this->getPreFunctions();
441 25
        if ($preFunctions->count() > 0) {
442 4
            $preFunctionsElements = $dom->createElement('pre-functions');
443 4
            foreach ($preFunctions as $function) {
444
                try {
445 4
                    $functionElement = $function->writeXml($dom);
446 4
                } catch (\Exception $e) {
447 1
                    $errMsg  = 'Ошибка сохранения workflow. Ошибка в pre-function';
448 1
                    throw new InvalidWriteWorkflowException($errMsg, $e->getCode(), $e);
449
                }
450 3
                $preFunctionsElements->appendChild($functionElement);
451 3
            }
452
453 3
            return $preFunctionsElements;
454
        }
455
456 21
        return null;
457
    }
458
459
460
    /**
461
     * Создает DOMElement - эквивалентный состоянию дескриптора
462
     *
463
     * @param DOMDocument $dom
464
     *
465
     * @return DOMElement
466
     * @throws InvalidDescriptorException
467
     * @throws InvalidWriteWorkflowException
468
     */
469 26
    public function writeXml(DOMDocument $dom = null)
470
    {
471 26
        if (null === $dom) {
472 1
            $errMsg = 'Не передан DOMDocument';
473 1
            throw new InvalidWriteWorkflowException($errMsg);
474
        }
475 25
        $descriptor = $dom->createElement('unconditional-result');
476
477 25
        if ($this->hasId()) {
478 2
            $id = $this->getId();
479 2
            $descriptor->setAttribute('id', $id);
480 2
        }
481
482 25
        $dueDate = $this->getDueDate();
483 25 View Code Duplication
        if (null !== $dueDate && is_string($dueDate) && strlen($dueDate) > 0) {
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...
484 2
            $descriptor->setAttribute('due-date', $dueDate);
485 2
        }
486
487 25
        $oldStatus = $this->getOldStatus();
488 25
        if (null === $oldStatus) {
489 1
            $errMsg = 'Некорректное значение для атрибута old-status';
490 1
            throw new InvalidDescriptorException($errMsg);
491
        }
492 24
        $descriptor->setAttribute('old-status', $oldStatus);
493
494
495
496 24
        $join = $this->getJoin();
497 24
        $split = $this->getSplit();
498 24 View Code Duplication
        if (null !== $join && 0 !== $join) {
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...
499 15
            $descriptor->setAttribute('join', $join);
500 24
        } elseif (null !== $split && 0 !== $split) {
501 13
            $descriptor->setAttribute('split', $split);
502 13
        } else {
503 20
            $status = $this->getStatus();
504 20
            if (null === $status) {
505 1
                $errMsg = 'Некорректное значение для атрибута status';
506 1
                throw new InvalidDescriptorException($errMsg);
507
            }
508 19
            $descriptor->setAttribute('status', $status);
509
510 19
            $step = $this->getStep();
511 19
            if (null === $step) {
512 1
                $errMsg = 'Некорректное значение для атрибута step';
513 1
                throw new InvalidDescriptorException($errMsg);
514
            }
515 18
            $descriptor->setAttribute('step', $step);
516
517 18
            $owner = $this->getOwner();
518 18
            if (null !== $owner && is_string($owner) && strlen($owner) > 0) {
519 15
                $descriptor->setAttribute('owner', $owner);
520 15
            }
521
522 18
            $displayName = $this->getDisplayName();
523 18
            if (null !== $displayName && is_string($displayName) && strlen($displayName) > 0) {
524 2
                $descriptor->setAttribute('display-name', $displayName);
525 2
            }
526
        }
527
528 22
        $validators = $this->getValidators();
529 22 View Code Duplication
        if ($validators->count() > 0) {
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...
530 2
            $validatorsDescriptor = $dom->createElement('validators');
531 2
            $descriptor->appendChild($validatorsDescriptor);
532
533 2
            foreach ($validators as $validator) {
534 2
                $validatorElement = $validator->writeXml($dom);
535 2
                $validatorsDescriptor->appendChild($validatorElement);
536 2
            }
537 2
        }
538
539 22
        $preFunctionsElement = $this->printPreFunctions($dom);
540 21
        if (null !== $preFunctionsElement) {
541 2
            $descriptor->appendChild($preFunctionsElement);
542 2
        }
543
544 21
        $postFunctionsElement = $this->printPostFunctions($dom);
545 20
        if (null !== $postFunctionsElement) {
546 2
            $descriptor->appendChild($postFunctionsElement);
547 2
        }
548
549 20
        return $descriptor;
550
    }
551
552
553
    /**
554
     * Валидация дескриптора
555
     *
556
     * @return void
557
     * @throws InvalidWorkflowDescriptorException
558
     */
559 28
    public function validate()
560
    {
561 28
        $preFunctions = $this->getPreFunctions();
562 28
        $postFunctions = $this->getPostFunctions();
563 28
        $validators = $this->getValidators();
564
565 28
        ValidationHelper::validate($preFunctions);
566 28
        ValidationHelper::validate($postFunctions);
567 28
        ValidationHelper::validate($validators);
568
569 28
        $split = $this->getSplit();
570 28
        $join = $this->getJoin();
571
572 28
        $parent = $this->getParent();
573 28
        if ((null === $split) && (null === $join) && !($parent instanceof ActionDescriptor && ($parent->isFinish()))) {
574 26
            $errMsg = '';
575 26
            $id = (integer)$this->getId();
576 26
            if (is_numeric($id)) {
577 26
                $errMsg .= sprintf('#%s:', $id);
578 26
            }
579 26
            $errMsg .= 'Если не указано значение атрибутов split или join, необходимо указать';
580
581 26
            if (!$this->hasStep) {
582 1
                $errMsg .= ' id следующего шага';
583 1
                throw new InvalidWorkflowDescriptorException($errMsg);
584
            }
585
586 25
            $status = $this->getStatus();
587 25
            if (!$status) {
588 1
                $errMsg .= ' статус';
589 1
                throw new InvalidWorkflowDescriptorException($errMsg);
590
            }
591 24
        }
592 26
    }
593
}
594