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.

WorkflowDescriptorContext   D
last analyzed

Complexity

Total Complexity 102

Size/Duplication

Total Lines 799
Duplicated Lines 18.52 %

Coupling/Cohesion

Components 2
Dependencies 7

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 102
c 3
b 0
f 0
lcom 2
cbo 7
dl 148
loc 799
rs 4.4444

26 Methods

Rating   Name   Duplication   Size   Complexity  
A createDescriptor() 0 8 2
B createDescriptorByNameBasedOnXml() 0 26 3
A createDescriptorByNameBasedOnXmlAndExpectToGetAnExceptionMessage() 0 11 2
B callAMethodDescriptorIGetTheValueOf() 0 25 3
B callAMethodDescriptorTheArgumentsOfTheMethod() 0 29 5
B callAMethodDescriptorIExpectToGetAnExceptionMessageTheArgumentsOfTheMethod() 0 32 5
A callAMethodDescriptorIExpectToGetAnException() 19 19 3
A callAMethodDescriptorIExpectToGetAnExceptionMessage() 19 19 3
B callAMethodDescriptorIGetTheValueOfTheArgumentsOfTheMethod() 0 38 5
A callAMethodDescriptor() 0 16 3
B iSaveToDescriptorXmlNotDomDocumentCompareWithXml() 8 27 5
B iSaveToDescriptorXmlCompareWithXml() 8 32 5
A iSaveToDescriptorXmlIExpectToGetAnException() 22 22 3
A iSaveToDescriptorXmlIExpectToGetAnExceptionMessage() 22 22 3
A iValidatedDescriptorIExpectToGetAnExceptionMessage() 17 17 3
A iValidatedDescriptorIExpectToGetAnException() 17 17 3
A beforeScenarioWithTagWorkflowDescriptor() 0 4 1
B afterStepWithTagWorkflowDescriptor() 0 12 5
A getLastCreatedDescriptor() 0 9 2
A beforeScenario() 0 4 1
A afterScenario() 0 4 1
A getWorkflowDescriptorNamespace() 0 4 1
B factoryDescriptor() 0 26 4
C getTheDescriptorUsingTheMethodOf() 5 28 8
D getTheDescriptorUsingTheMethodOfTheArgumentsOfTheMethod() 5 45 10
C intelligentTransformArgument() 6 60 13

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 WorkflowDescriptorContext 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 WorkflowDescriptorContext, 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 OldTownWorkflowBehatTestBootstrap;
7
8
use Behat\Behat\Context\Context;
9
use Behat\Behat\Context\SnippetAcceptingContext;
10
use OldTown\Workflow\Loader\AbstractDescriptor;
11
use Behat\Gherkin\Node\PyStringNode;
12
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
13
use Behat\Gherkin\Node\ScenarioInterface;
14
use Behat\Behat\Hook\Scope\AfterStepScope;
15
use Behat\Behat\Tester\Result\ExecutedStepResult;
16
use Behat\Gherkin\Node\TableNode;
17
use OldTown\Workflow\Loader\WriteXmlInterface;
18
use PHPUnit_Framework_Assert;
19
use RuntimeException;
20
use DOMElement;
21
22
23
/**
24
 * Defines application features from the specific context.
25
 */
26
class WorkflowDescriptorContext implements Context, SnippetAcceptingContext
27
{
28
    /**
29
     *
30
     * @var string
31
     */
32
    protected $workflowDescriptorNamespace = 'OldTown\Workflow\Loader';
33
34
    /**
35
     * Последний созданный дескриптор
36
     *
37
     * @var AbstractDescriptor
38
     */
39
    protected $lastCreatedDescriptor;
40
41
    /**
42
     * @var
43
     */
44
    protected $currentScenario;
45
46
    /**
47
     * @Given Create descriptor :nameDescriptor
48
     *
49
     * @param $nameDescriptor
50
     *
51
     * @return AbstractDescriptor
52
     *
53
     * @throws \RuntimeException
54
     */
55
    public function createDescriptor($nameDescriptor)
56
    {
57
        try {
58
            return $this->factoryDescriptor($nameDescriptor);
59
        } catch (\Exception $e) {
60
            throw new \RuntimeException($e->getMessage(), $e->getCode(), $e);
61
        }
62
    }
63
64
65
    /**
66
     * @Given Create descriptor :nameDescriptor based on xml:
67
     *
68
     * @param string       $nameDescriptor
69
     * @param PyStringNode $xml
70
     *
71
     * @return AbstractDescriptor
72
     * @throws \RuntimeException
73
     */
74
    public function createDescriptorByNameBasedOnXml($nameDescriptor, PyStringNode $xml)
75
    {
76
        $useXmlErrors = libxml_use_internal_errors();
77
        try {
78
            libxml_use_internal_errors(true);
79
            libxml_clear_errors();
80
81
            $xmlDoc = new \DOMDocument();
82
            $xmlDoc->loadXML($xml->getRaw());
83
84
            $libxmlGetLastError = libxml_get_last_error();
85
            if ($libxmlGetLastError instanceof \LibXMLError) {
86
                throw new \RuntimeException($libxmlGetLastError->message, $libxmlGetLastError->code);
87
            }
88
89
            $descriptor = $this->factoryDescriptor($nameDescriptor, $xmlDoc->firstChild);
0 ignored issues
show
Documentation introduced by
$xmlDoc->firstChild is of type object<DOMNode>, but the function expects a null|object<DOMElement>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
90
91
            libxml_use_internal_errors($useXmlErrors);
92
93
            return $descriptor;
94
        } catch (\Exception $e) {
95
            libxml_clear_errors();
96
            libxml_use_internal_errors($useXmlErrors);
97
            throw new \RuntimeException($e->getMessage(), $e->getCode(), $e);
98
        }
99
    }
100
101
102
    /**
103
     * @When Create descriptor :nameDescriptor based on xml. I expect exception with the text :expectedExceptionMessage. Xml source:
104
     *
105
     * @param string       $nameDescriptor
106
     * @param string       $expectedExceptionMessage
107
     * @param PyStringNode $xml
108
     *
109
     * @return AbstractDescriptor
110
     */
111
    public function createDescriptorByNameBasedOnXmlAndExpectToGetAnExceptionMessage($nameDescriptor, $expectedExceptionMessage, PyStringNode $xml)
112
    {
113
        $actualExceptionMessage = null;
114
        try {
115
            $this->createDescriptorByNameBasedOnXml($nameDescriptor, $xml);
116
        } catch (\Exception $e) {
117
            $actualExceptionMessage = $e->getMessage();
118
        }
119
120
        PHPUnit_Framework_Assert::assertEquals($expectedExceptionMessage, $actualExceptionMessage);
121
    }
122
123
    /**
124
     * @Then Call a method descriptor :nameMethod, I get the value of :expectedResult
125
     *
126
     * @param $nameMethod
127
     * @param $expectedResult
128
     *
129
     * @throws \RuntimeException
130
     */
131
    public function callAMethodDescriptorIGetTheValueOf($nameMethod, $expectedResult)
132
    {
133
        try {
134
            $descriptor = $this->getLastCreatedDescriptor();
135
            $r = new \ReflectionObject($descriptor);
136
137
            if (!$r->hasMethod($nameMethod)) {
138
                $errMsg = "Method {$nameMethod}  does not exist";
139
                throw new \InvalidArgumentException($errMsg);
140
            }
141
142
            $actualValue = $r->getMethod($nameMethod)->invoke($descriptor);
143
144
            $errMsg = sprintf(
145
                "Bug with attribute of \"%s\". Expected value: %s. Actual value: %s",
146
                $nameMethod,
147
                $expectedResult,
148
                $actualValue
149
            );
150
151
            PHPUnit_Framework_Assert::assertEquals($expectedResult, $actualValue, $errMsg);
152
        } catch (\Exception $e) {
153
            throw new \RuntimeException($e->getMessage(), $e->getCode(), $e);
154
        }
155
    }
156
157
158
    /**
159
     * @Transform /^\(.+?\).+?$/
160
     *
161
     * @param $expectedResult
162
     *
163
     * @return mixed
164
     * @throws \RuntimeException
165
     */
166
    public function intelligentTransformArgument($expectedResult)
167
    {
168
        $outputArray = [];
169
        preg_match_all('/^\((.+?)\)(.+?)$/', $expectedResult, $outputArray);
170
171
172
        if (3 !== count($outputArray)) {
173
            return $expectedResult;
174
        }
175
176 View Code Duplication
        if (!(is_array($outputArray[1]) && 1 === count($outputArray[1]))) {
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
            return $expectedResult;
178
        }
179
180
181 View Code Duplication
        if (!(is_array($outputArray[2]) && 1 === count($outputArray[2]))) {
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...
182
            return $expectedResult;
183
        }
184
185
        $originalType = $outputArray[1][0];
186
        $type = strtolower($originalType);
187
188
        $value = $outputArray[2][0];
189
190
        $result = $value;
191
        switch ($type) {
192
            case 'boolean':
193
            case 'bool': {
194
                $prepareValue = trim($result);
195
                $prepareValue = strtolower($prepareValue);
196
197
                $falseStrings = [
198
                    ''      => '',
199
                    'false' => 'false',
200
                    '0'     => '0',
201
                ];
202
203
                $result = !array_key_exists($prepareValue, $falseStrings);
204
205
                break;
206
            }
207
            case 'null': {
208
                $result = '(null)null' === $expectedResult ? null : $expectedResult;
209
                break;
210
            }
211
            case '\\domdocument':
212
            case 'domdocument': {
213
                if ('(DOMDocument)domDocument' === $expectedResult) {
214
                    $result = new \DOMDocument();
215
                }
216
217
                break;
218
            }
219
            default: {
220
221
            }
222
        }
223
224
        return $result;
225
    }
226
227
    /**
228
     * @When Call a method descriptor :nameMethod. The arguments of the method:
229
     *
230
     * @param           $nameMethod
231
     * @param TableNode $table
232
     *
233
     * @throws RuntimeException
234
     */
235
    public function callAMethodDescriptorTheArgumentsOfTheMethod($nameMethod, TableNode $table)
236
    {
237
        try {
238
            $descriptor = $this->getLastCreatedDescriptor();
239
            $r = new \ReflectionObject($descriptor);
240
241
            if (!$r->hasMethod($nameMethod)) {
242
                $errMsg = "Method {$nameMethod}  does not exist";
243
                throw new \InvalidArgumentException($errMsg);
244
            }
245
246
            $rows = $table->getHash();
247
            if (1 !== count($rows)) {
248
                $errMsg = 'Incorrect arguments';
249
                throw new \InvalidArgumentException($errMsg);
250
            }
251
252
            $args = $rows[0];
253
254
            $transformArg = [];
255
            foreach ($args as $index => $arg) {
256
                $transformArg[$index] = $this->intelligentTransformArgument($arg);
257
            }
258
259
            $r->getMethod($nameMethod)->invokeArgs($descriptor, $transformArg);
260
        } catch (\Exception $e) {
261
            throw new \RuntimeException($e->getMessage(), $e->getCode(), $e);
262
        }
263
    }
264
265
266
    /**
267
     * @When Call a method descriptor :nameMethod. I expect to get an exception message :expectedExceptionMessage. The arguments of the method:
268
     *
269
     * @param $nameMethod
270
     * @param $expectedExceptionMessage
271
     * @param TableNode $table
272
     *
273
     */
274
    public function callAMethodDescriptorIExpectToGetAnExceptionMessageTheArgumentsOfTheMethod($nameMethod, $expectedExceptionMessage, TableNode $table)
275
    {
276
        $actualExceptionMessage = null;
277
        try {
278
            $descriptor = $this->getLastCreatedDescriptor();
279
            $r = new \ReflectionObject($descriptor);
280
281
            if (!$r->hasMethod($nameMethod)) {
282
                $errMsg = "Method {$nameMethod}  does not exist";
283
                throw new \InvalidArgumentException($errMsg);
284
            }
285
286
            $rows = $table->getHash();
287
            if (1 !== count($rows)) {
288
                $errMsg = 'Incorrect arguments';
289
                throw new \InvalidArgumentException($errMsg);
290
            }
291
292
            $args = $rows[0];
293
294
            $transformArg = [];
295
            foreach ($args as $index => $arg) {
296
                $transformArg[$index] = $this->intelligentTransformArgument($arg);
297
            }
298
299
            $r->getMethod($nameMethod)->invokeArgs($descriptor, $transformArg);
300
        } catch (\Exception $e) {
301
            $actualExceptionMessage = $e->getMessage();
302
        }
303
304
        PHPUnit_Framework_Assert::assertEquals($expectedExceptionMessage, $actualExceptionMessage);
305
    }
306
307
    /**
308
     * @Then Call a method descriptor :nameMethod. I expect to get an exception :expectedException
309
     *
310
     * @param string $nameMethod
311
     * @param string $expectedException
312
     */
313 View Code Duplication
    public function callAMethodDescriptorIExpectToGetAnException($nameMethod, $expectedException)
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...
314
    {
315
        $actualException = null;
316
        try {
317
            $descriptor = $this->getLastCreatedDescriptor();
318
            $r = new \ReflectionObject($descriptor);
319
320
            if (!$r->hasMethod($nameMethod)) {
321
                $errMsg = "Method {$nameMethod}  does not exist";
322
                throw new \InvalidArgumentException($errMsg);
323
            }
324
325
            $r->getMethod($nameMethod)->invoke($descriptor);
326
        } catch (\Exception $e) {
327
            $actualException = $e;
328
        }
329
330
        PHPUnit_Framework_Assert::assertInstanceOf($expectedException, $actualException);
331
    }
332
333
    /**
334
     * @Then Call a method descriptor :nameMethod. I expect to get an exception message :expectedExceptionMessage
335
     *
336
     * @param $nameMethod
337
     * @param $expectedExceptionMessage
338
     */
339 View Code Duplication
    public function callAMethodDescriptorIExpectToGetAnExceptionMessage($nameMethod, $expectedExceptionMessage)
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...
340
    {
341
        $actualExceptionMessage = null;
342
        try {
343
            $descriptor = $this->getLastCreatedDescriptor();
344
            $r = new \ReflectionObject($descriptor);
345
346
            if (!$r->hasMethod($nameMethod)) {
347
                $errMsg = "Method {$nameMethod}  does not exist";
348
                throw new \InvalidArgumentException($errMsg);
349
            }
350
351
            $r->getMethod($nameMethod)->invoke($descriptor);
352
        } catch (\Exception $e) {
353
            $actualExceptionMessage = $e->getMessage();
354
        }
355
356
        PHPUnit_Framework_Assert::assertEquals($expectedExceptionMessage, $actualExceptionMessage);
357
    }
358
359
360
361
362
    /**
363
     * @Then Call a method descriptor :nameMethod, I get the value of :expectedResult. The arguments of the method:
364
     *
365
     * @param string    $nameMethod
366
     * @param string    $expectedResult
367
     * @param TableNode $table
368
     *
369
     * @throws \RuntimeException
370
     *
371
     */
372
    public function callAMethodDescriptorIGetTheValueOfTheArgumentsOfTheMethod($nameMethod, $expectedResult, TableNode $table)
373
    {
374
        try {
375
            $descriptor = $this->getLastCreatedDescriptor();
376
            $r = new \ReflectionObject($descriptor);
377
378
            if (!$r->hasMethod($nameMethod)) {
379
                $errMsg = "Method {$nameMethod}  does not exist";
380
                throw new \InvalidArgumentException($errMsg);
381
            }
382
383
            $rows = $table->getHash();
384
            if (1 !== count($rows)) {
385
                $errMsg = 'Incorrect arguments';
386
                throw new \InvalidArgumentException($errMsg);
387
            }
388
389
            $args = $rows[0];
390
391
            $transformArg = [];
392
            foreach ($args as $index => $arg) {
393
                $transformArg[$index] = $this->intelligentTransformArgument($arg);
394
            }
395
396
397
            $actualValue = $r->getMethod($nameMethod)->invokeArgs($descriptor, $transformArg);
398
399
            $errMsg = sprintf(
400
                "Bug with attribute of \"variable-name\". Expected value: %s. Actual value: %s",
401
                $expectedResult,
402
                $actualValue
403
            );
404
405
            PHPUnit_Framework_Assert::assertEquals($expectedResult, $actualValue, $errMsg);
406
        } catch (\Exception $e) {
407
            throw new \RuntimeException($e->getMessage(), $e->getCode(), $e);
408
        }
409
    }
410
411
    /**
412
     * @When Call a method descriptor :nameMethod
413
     *
414
     * @param $nameMethod
415
     *
416
     * @throws RuntimeException
417
     */
418
    public function callAMethodDescriptor($nameMethod)
419
    {
420
        try {
421
            $descriptor = $this->getLastCreatedDescriptor();
422
            $r = new \ReflectionObject($descriptor);
423
424
            if (!$r->hasMethod($nameMethod)) {
425
                $errMsg = "Method {$nameMethod}  does not exist";
426
                throw new \InvalidArgumentException($errMsg);
427
            }
428
429
            $r->getMethod($nameMethod)->invoke($descriptor);
430
        } catch (\Exception $e) {
431
            throw new \RuntimeException($e->getMessage(), $e->getCode(), $e);
432
        }
433
    }
434
435
436
    /**
437
     * @Then I save to descriptor xml. Not DomDocument. Compare with xml:
438
     *
439
     * @param PyStringNode $expectedXmlNode
440
     *
441
     * @throws \RuntimeException
442
     *
443
     */
444
    public function iSaveToDescriptorXmlNotDomDocumentCompareWithXml(PyStringNode $expectedXmlNode)
445
    {
446
        try {
447
            $descriptor = $this->getLastCreatedDescriptor();
448
            if (!$descriptor instanceof WriteXmlInterface) {
449
                $errMsg = 'Descriptor not implement WriteXmlInterface';
450
                throw new \RuntimeException($errMsg);
451
            }
452
453
            $result = $descriptor->writeXml();
454
455 View Code Duplication
            if ($result instanceof \DOMDocument) {
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...
456
                $actualXml = $result->saveXML();
457
            } elseif ($result instanceof \DOMElement) {
458
                $actualXml = $result->ownerDocument->saveXML($result);
459
            } else {
460
                $errMsg = 'Incorrect result writeXml';
461
                throw new \RuntimeException($errMsg);
462
            }
463
464
            $expectedXml = $expectedXmlNode->getRaw();
465
466
            PHPUnit_Framework_Assert::assertXmlStringEqualsXmlString($expectedXml, $actualXml);
467
        } catch (\Exception $e) {
468
            throw new \RuntimeException($e->getMessage(), $e->getCode(), $e);
469
        }
470
    }
471
472
473
    /**
474
     * @Then     I save to descriptor xml. Compare with xml:
475
     *
476
     * @param PyStringNode $expectedXmlNode
477
     *
478
     * @throws \RuntimeException
479
     *
480
     */
481
    public function iSaveToDescriptorXmlCompareWithXml(PyStringNode $expectedXmlNode)
482
    {
483
        try {
484
            $dom = new \DOMDocument();
485
            $dom->encoding = 'UTF-8';
486
            $dom->xmlVersion = '1.0';
487
            $dom->formatOutput = true;
488
489
            $descriptor = $this->getLastCreatedDescriptor();
490
            if (!$descriptor instanceof WriteXmlInterface) {
491
                $errMsg = 'Descriptor not implement WriteXmlInterface';
492
                throw new \RuntimeException($errMsg);
493
            }
494
495
            $result = $descriptor->writeXml($dom);
496
497 View Code Duplication
            if ($result instanceof \DOMDocument) {
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...
498
                $actualXml = $result->saveXML();
499
            } elseif ($result instanceof \DOMElement) {
500
                $actualXml = $result->ownerDocument->saveXML($result);
501
            } else {
502
                $errMsg = 'Incorrect result writeXml';
503
                throw new \RuntimeException($errMsg);
504
            }
505
506
            $expectedXml = $expectedXmlNode->getRaw();
507
508
            PHPUnit_Framework_Assert::assertXmlStringEqualsXmlString($expectedXml, $actualXml);
509
        } catch (\Exception $e) {
510
            throw new \RuntimeException($e->getMessage(), $e->getCode(), $e);
511
        }
512
    }
513
514
    /**
515
     * @Then I save to descriptor xml. I expect to get an exception :expectedException
516
     *
517
     * @param string $expectedException
518
     */
519 View Code Duplication
    public function iSaveToDescriptorXmlIExpectToGetAnException($expectedException)
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...
520
    {
521
        $actualException = null;
522
        try {
523
            $dom = new \DOMDocument();
524
            $dom->encoding = 'UTF-8';
525
            $dom->xmlVersion = '1.0';
526
            $dom->formatOutput = true;
527
528
            $descriptor = $this->getLastCreatedDescriptor();
529
            if (!$descriptor instanceof WriteXmlInterface) {
530
                $errMsg = 'Descriptor not implement WriteXmlInterface';
531
                throw new \RuntimeException($errMsg);
532
            }
533
534
            $descriptor->writeXml($dom);
535
        } catch (\Exception $e) {
536
            $actualException = $e;
537
        }
538
539
        PHPUnit_Framework_Assert::assertInstanceOf($expectedException, $actualException);
540
    }
541
542
    /**
543
     * @Then     I save to descriptor xml. I expect to get an exception message :expectedException
544
     *
545
     * @param $expectedExceptionMessage
546
     *
547
     */
548 View Code Duplication
    public function iSaveToDescriptorXmlIExpectToGetAnExceptionMessage($expectedExceptionMessage)
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...
549
    {
550
        $actualExceptionMessage = null;
551
        try {
552
            $dom = new \DOMDocument();
553
            $dom->encoding = 'UTF-8';
554
            $dom->xmlVersion = '1.0';
555
            $dom->formatOutput = true;
556
557
            $descriptor = $this->getLastCreatedDescriptor();
558
            if (!$descriptor instanceof WriteXmlInterface) {
559
                $errMsg = 'Descriptor not implement WriteXmlInterface';
560
                throw new \RuntimeException($errMsg);
561
            }
562
563
            $descriptor->writeXml($dom);
564
        } catch (\Exception $e) {
565
            $actualExceptionMessage = $e->getMessage();
566
        }
567
568
        PHPUnit_Framework_Assert::assertEquals($expectedExceptionMessage, $actualExceptionMessage);
569
    }
570
571
572
573
    /**
574
     * @Then I validated descriptor. I expect to get an exception message :expectedExceptionMessage
575
     *
576
     * @param $expectedExceptionMessage
577
     *
578
     */
579 View Code Duplication
    public function iValidatedDescriptorIExpectToGetAnExceptionMessage($expectedExceptionMessage)
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...
580
    {
581
        $actualExceptionMessage = null;
582
        try {
583
            $descriptor = $this->getLastCreatedDescriptor();
584
            if (!method_exists($descriptor, 'validate')) {
585
                $errMsg = 'Descriptor does not support validation';
586
                throw new \RuntimeException($errMsg);
587
            }
588
589
            call_user_func_array([$descriptor, 'validate'], []);
590
        } catch (\Exception $e) {
591
            $actualExceptionMessage = $e->getMessage();
592
        }
593
594
        PHPUnit_Framework_Assert::assertEquals($expectedExceptionMessage, $actualExceptionMessage);
595
    }
596
597
598
    /**
599
     * @Then I validated descriptor. I expect to get an exception :expectedException
600
     *
601
     * @param string $expectedException
602
     */
603 View Code Duplication
    public function iValidatedDescriptorIExpectToGetAnException($expectedException)
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...
604
    {
605
        $actualException = null;
606
        try {
607
            $descriptor = $this->getLastCreatedDescriptor();
608
            if (!method_exists($descriptor, 'validate')) {
609
                $errMsg = 'Descriptor does not support validation';
610
                throw new \RuntimeException($errMsg);
611
            }
612
613
            call_user_func([$descriptor, 'validate']);
614
        } catch (\Exception $e) {
615
            $actualException = $e;
616
        }
617
618
        PHPUnit_Framework_Assert::assertInstanceOf($expectedException, $actualException);
619
    }
620
621
622
    /**
623
     * @BeforeScenario @workflowDescriptor
624
     */
625
    public function beforeScenarioWithTagWorkflowDescriptor()
626
    {
627
        $this->lastCreatedDescriptor = null;
628
    }
629
630
    /**
631
     * @AfterStep
632
     *
633
     * @param AfterStepScope $scope
634
     */
635
    public function afterStepWithTagWorkflowDescriptor(AfterStepScope $scope)
636
    {
637
        if ($this->currentScenario instanceof ScenarioInterface && $this->currentScenario->hasTag('workflowDescriptor')) {
638
            $result = $scope->getTestResult();
639
            if ($result instanceof ExecutedStepResult) {
640
                $descriptor = $result->getCallResult()->getReturn();
641
                if ($descriptor instanceof AbstractDescriptor) {
642
                    $this->lastCreatedDescriptor = $descriptor;
643
                }
644
            }
645
        }
646
    }
647
648
    /**
649
     * Возвращает последний созданный дескриптор
650
     *
651
     * @return AbstractDescriptor
652
     *
653
     * @throws \RuntimeException
654
     */
655
    protected function getLastCreatedDescriptor()
656
    {
657
        if (!$this->lastCreatedDescriptor instanceof AbstractDescriptor) {
658
            $errMsg = 'Descriptor does not exist';
659
            throw new \RuntimeException($errMsg);
660
        }
661
662
        return $this->lastCreatedDescriptor;
663
    }
664
665
666
    /**
667
     * @BeforeScenario
668
     *
669
     * @param BeforeScenarioScope $scope
670
     */
671
    public function beforeScenario(BeforeScenarioScope $scope)
672
    {
673
        $this->currentScenario = $scope->getScenario();
674
    }
675
676
677
    /**
678
     * @AfterScenario
679
     */
680
    public function afterScenario()
681
    {
682
        $this->currentScenario = null;
683
    }
684
685
    /**
686
     * Наймспейс в котором находятся дескрипторы Workflow
687
     *
688
     * @return string
689
     */
690
    public function getWorkflowDescriptorNamespace()
691
    {
692
        return $this->workflowDescriptorNamespace;
693
    }
694
695
    /**
696
     * Фабрика по созданию дескрипторов
697
     *
698
     * @param string     $name
699
     *
700
     * @param DOMElement $element
701
     *
702
     * @return AbstractDescriptor
703
     * @throws RuntimeException
704
     */
705
    protected function factoryDescriptor($name, DOMElement $element = null)
706
    {
707
        $ns = $this->getWorkflowDescriptorNamespace();
708
        $class = "{$ns}\\{$name}";
709
710
        if (!class_exists($class)) {
711
            $errMsg = "Class not found {$class}";
712
            throw new \RuntimeException($errMsg);
713
        }
714
715
        $r = new \ReflectionClass($class);
716
        if (null === $element) {
717
            $descriptor = $r->newInstance();
718
        } else {
719
            $descriptor = $r->newInstanceArgs([
720
                $element
721
            ]);
722
        }
723
724
        if (!$descriptor instanceof AbstractDescriptor) {
725
            $errMsg = 'Descriptor not instance of AbstractDescriptor';
726
            throw new \RuntimeException($errMsg);
727
        }
728
729
        return $descriptor;
730
    }
731
732
    /**
733
     * @Given Get the descriptor using the method of :methodName
734
     *
735
     * @param $methodName
736
     *
737
     * @return AbstractDescriptor
738
     * @throws RuntimeException
739
     */
740
    public function getTheDescriptorUsingTheMethodOf($methodName)
741
    {
742
        try {
743
            $descriptor = $this->getLastCreatedDescriptor();
744
            if (!method_exists($descriptor, $methodName)) {
745
                $errMsg = "Descriptor does not support method {$methodName}";
746
                throw new \RuntimeException($errMsg);
747
            }
748
749
            $descriptors = call_user_func([$descriptor, $methodName]);
750
751
            $targetDescriptor = $descriptors;
752 View Code Duplication
            if ((is_array($descriptors) || $descriptors instanceof \Traversable) && 1 === count($descriptors)) {
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...
753
                $iterator = is_array($descriptors) ? $descriptors : iterator_to_array($descriptors);
754
                reset($iterator);
755
                $targetDescriptor = current($iterator);
756
            }
757
758
            if (!$targetDescriptor instanceof AbstractDescriptor) {
759
                $errMsg = 'Descriptor not instance of AbstractDescriptor';
760
                throw new \RuntimeException($errMsg);
761
            }
762
763
            return $targetDescriptor;
764
        } catch (\Exception $e) {
765
            throw new \RuntimeException($e->getMessage(), $e->getCode(), $e);
766
        }
767
    }
768
769
770
    /**
771
     * @When Get the descriptor using the method of :methodName. The arguments of the method:
772
     *
773
     * @param           $methodName
774
     * @param TableNode $table
775
     *
776
     * @return mixed
777
     * @throws \RuntimeException
778
     */
779
    public function getTheDescriptorUsingTheMethodOfTheArgumentsOfTheMethod($methodName, TableNode $table)
780
    {
781
        try {
782
            $descriptor = $this->getLastCreatedDescriptor();
783
784
785
            $r = new \ReflectionObject($descriptor);
786
787
            if (!$r->hasMethod($methodName)) {
788
                $errMsg = "Method {$methodName}  does not exist";
789
                throw new \InvalidArgumentException($errMsg);
790
            }
791
792
            $rows = $table->getHash();
793
            if (1 !== count($rows)) {
794
                $errMsg = 'Incorrect arguments';
795
                throw new \InvalidArgumentException($errMsg);
796
            }
797
798
            $args = $rows[0];
799
800
            $transformArg = [];
801
            foreach ($args as $index => $arg) {
802
                $transformArg[$index] = $this->intelligentTransformArgument($arg);
803
            }
804
805
            $descriptors = $r->getMethod($methodName)->invokeArgs($descriptor, $transformArg);
806
807
            $targetDescriptor = $descriptors;
808 View Code Duplication
            if ((is_array($descriptors) || $descriptors instanceof \Traversable) && 1 === count($descriptors)) {
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...
809
                $iterator = is_array($descriptors) ? $descriptors : iterator_to_array($descriptors);
810
                reset($iterator);
811
                $targetDescriptor = current($iterator);
812
            }
813
814
            if (!$targetDescriptor instanceof AbstractDescriptor) {
815
                $errMsg = 'Descriptor not instance of AbstractDescriptor';
816
                throw new \RuntimeException($errMsg);
817
            }
818
819
            return $targetDescriptor;
820
        } catch (\Exception $e) {
821
            throw new \RuntimeException($e->getMessage(), $e->getCode(), $e);
822
        }
823
    }
824
}
825