DataProviderMaintainer::supports()   A
last analyzed

Complexity

Conditions 5
Paths 5

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 11
dl 0
loc 22
rs 9.6111
c 0
b 0
f 0
cc 5
nc 5
nop 1
1
<?php declare(strict_types=1);
2
3
namespace HMoragrega\PhpSpec\DataProvider\Maintainer;
4
5
use HMoragrega\PhpSpec\DataProvider\Parser\DataProviderExtractor;
6
use HMoragrega\PhpSpec\DataProvider\Parser\ExampleParser;
7
use PhpSpec\Loader\Node\ExampleNode;
8
use PhpSpec\Runner\CollaboratorManager;
9
use PhpSpec\Runner\Maintainer\Maintainer;
10
use PhpSpec\Runner\MatcherManager;
11
use PhpSpec\Specification;
12
13
class DataProviderMaintainer implements Maintainer
14
{
15
    const EXAMPLE_NUMBER_PATTERN = '/^(\d+)\)/';
16
17
    /**
18
     * @var ExampleParser
19
     */
20
    private $exampleParser;
21
22
    /**
23
     * @var DataProviderExtractor
24
     */
25
    private $dataProviderExtractor;
26
27
    /**
28
     * @var array[]
29
     */
30
    private $providerData = [];
31
32
    /**
33
     * @param ExampleParser         $exampleParser
34
     * @param DataProviderExtractor $dataProviderExtractor
35
     */
36
    public function __construct(ExampleParser $exampleParser, DataProviderExtractor $dataProviderExtractor)
37
    {
38
        $this->exampleParser         = $exampleParser;
39
        $this->dataProviderExtractor = $dataProviderExtractor;
40
    }
41
42
    /**
43
     * @param ExampleNode $example
44
     *
45
     * @return boolean
46
     * @throws \ReflectionException
47
     */
48
    public function supports(ExampleNode $example): bool
49
    {
50
        $dataProviderMethod = $this->exampleParser->getDataProvider($example);
51
        if (!$dataProviderMethod) {
52
            return false;
53
        }
54
55
        if (isset($this->providerData[$dataProviderMethod])) {
56
            return true;
57
        }
58
59
        $providedData = $this->dataProviderExtractor->getProvidedData($example, $dataProviderMethod);
60
61
        foreach ($providedData as $dataRow) {
62
            if (!is_array($dataRow)) {
63
                return false;
64
            }
65
        }
66
67
        $this->providerData[$dataProviderMethod] = $providedData;
68
69
        return true;
70
    }
71
72
    /**
73
     * @param ExampleNode         $example
74
     * @param Specification       $context
75
     * @param MatcherManager      $matchers
76
     * @param CollaboratorManager $collaborators
77
     */
78
    public function prepare(ExampleNode $example, Specification $context, MatcherManager $matchers, CollaboratorManager $collaborators): void
79
    {
80
        $exampleNum   = $this->getExampleNumber($example->getTitle());
81
        $providedData = $this->providerData[$this->exampleParser->getDataProvider($example)];
82
83
        if (!array_key_exists($exampleNum, $providedData)) {
84
            return;
85
        }
86
87
        $data               = $providedData[$exampleNum];
88
        $function           = $example->getFunctionReflection();
89
        $numberOfParameters = $function->getNumberOfParameters();
90
91
        foreach ($function->getParameters() as $position => $parameter) {
92
            if ($numberOfParameters < count($data)) {
93
                $position++;
94
            }
95
96
            if (!isset($data[$position])) {
97
                continue;
98
            }
99
100
            $collaborators->set($parameter->getName(), $data[$position]);
101
        }
102
    }
103
104
    /**
105
     * @param ExampleNode         $example
106
     * @param Specification       $context
107
     * @param MatcherManager      $matchers
108
     * @param CollaboratorManager $collaborators
109
     */
110
    public function teardown(ExampleNode $example, Specification $context, MatcherManager $matchers, CollaboratorManager $collaborators): void
111
    {
112
        unset($this->providerData[$this->exampleParser->getDataProvider($example)]);
113
    }
114
115
    /**
116
     * @return integer
117
     */
118
    public function getPriority(): int
119
    {
120
        return 50;
121
    }
122
123
    /**
124
     * @param string $title
125
     *
126
     * @return int
127
     */
128
    private function getExampleNumber(string $title): int
129
    {
130
        if (!preg_match(self::EXAMPLE_NUMBER_PATTERN, $title, $matches)) {
131
            return 0;
132
        }
133
134
        return (int) $matches[1] - 1;
135
    }
136
}