Completed
Pull Request — master (#161)
by Phil
13:29
created

ArrayLoader   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 286
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 32
lcom 1
cbo 8
dl 0
loc 286
ccs 107
cts 107
cp 1
rs 9.84
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A supports() 0 4 3
A load() 0 16 4
A loadFeatureHash() 0 27 5
A loadBackgroundHash() 0 16 1
A loadScenarioHash() 0 17 1
A loadStepHash() 0 25 4
A loadOutlineHash() 0 35 3
A loadStepsHash() 0 9 2
A loadTableHash() 0 4 1
A loadPyStringHash() 0 11 3
A examplesAreInArray() 0 4 1
A processExamplesArray() 0 15 4
1
<?php
2
3
/*
4
 * This file is part of the Behat Gherkin.
5
 * (c) Konstantin Kudryashov <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Behat\Gherkin\Loader;
12
13
use Behat\Gherkin\Node\BackgroundNode;
14
use Behat\Gherkin\Node\ExampleTableNode;
15
use Behat\Gherkin\Node\FeatureNode;
16
use Behat\Gherkin\Node\OutlineNode;
17
use Behat\Gherkin\Node\PyStringNode;
18
use Behat\Gherkin\Node\ScenarioNode;
19
use Behat\Gherkin\Node\StepNode;
20
use Behat\Gherkin\Node\TableNode;
21
22
/**
23
 * From-array loader.
24
 *
25
 * @author Konstantin Kudryashov <[email protected]>
26
 */
27
class ArrayLoader implements LoaderInterface
28
{
29
    /**
30
     * Checks if current loader supports provided resource.
31
     *
32
     * @param mixed $resource Resource to load
33
     *
34
     * @return Boolean
35
     */
36 1
    public function supports($resource)
37
    {
38 1
        return is_array($resource) && (isset($resource['features']) || isset($resource['feature']));
39
    }
40
41
    /**
42
     * Loads features from provided resource.
43
     *
44
     * @param mixed $resource Resource to load
45
     *
46
     * @return FeatureNode[]
47
     */
48 43
    public function load($resource)
49
    {
50 43
        $features = array();
51
52 43
        if (isset($resource['features'])) {
53 8
            foreach ($resource['features'] as $iterator => $hash) {
54 7
                $feature = $this->loadFeatureHash($hash, $iterator);
55 7
                $features[] = $feature;
56 8
            }
57 43
        } elseif (isset($resource['feature'])) {
58 35
            $feature = $this->loadFeatureHash($resource['feature']);
59 35
            $features[] = $feature;
60 35
        }
61
62 43
        return $features;
63
    }
64
65
    /**
66
     * Loads feature from provided feature hash.
67
     *
68
     * @param array   $hash Feature hash
69
     * @param integer $line
70
     *
71
     * @return FeatureNode
72
     */
73 42
    protected function loadFeatureHash(array $hash, $line = 0)
74
    {
75 42
        $hash = array_merge(
76
            array(
77 42
                'title' => null,
78 42
                'description' => null,
79 42
                'tags' => array(),
80 42
                'keyword' => 'Feature',
81 42
                'language' => 'en',
82 42
                'line' => $line,
83 42
                'scenarios' => array(),
84 42
            ),
85
            $hash
86 42
        );
87 42
        $background = isset($hash['background']) ? $this->loadBackgroundHash($hash['background']) : null;
88
89 42
        $scenarios = array();
90 42
        foreach ((array) $hash['scenarios'] as $scenarioIterator => $scenarioHash) {
91 35
            if (isset($scenarioHash['type']) && 'outline' === $scenarioHash['type']) {
92 12
                $scenarios[] = $this->loadOutlineHash($scenarioHash, $scenarioIterator);
93 12
            } else {
94 28
                $scenarios[] = $this->loadScenarioHash($scenarioHash, $scenarioIterator);
95
            }
96 42
        }
97
98 42
        return new FeatureNode($hash['title'], $hash['description'], $hash['tags'], $background, $scenarios, $hash['keyword'], $hash['language'], null, $hash['line']);
99
    }
100
101
    /**
102
     * Loads background from provided hash.
103
     *
104
     * @param array $hash Background hash
105
     *
106
     * @return BackgroundNode
107
     */
108 8
    protected function loadBackgroundHash(array $hash)
109
    {
110 8
        $hash = array_merge(
111
            array(
112 8
                'title' => null,
113 8
                'keyword' => 'Background',
114 8
                'line' => 0,
115 8
                'steps' => array(),
116 8
            ),
117
            $hash
118 8
        );
119
120 8
        $steps = $this->loadStepsHash($hash['steps']);
121
122 8
        return new BackgroundNode($hash['title'], $steps, $hash['keyword'], $hash['line']);
123
    }
124
125
    /**
126
     * Loads scenario from provided scenario hash.
127
     *
128
     * @param array   $hash Scenario hash
129
     * @param integer $line Scenario definition line
130
     *
131
     * @return ScenarioNode
132
     */
133 28
    protected function loadScenarioHash(array $hash, $line = 0)
134
    {
135 28
        $hash = array_merge(
136
            array(
137 28
                'title' => null,
138 28
                'tags' => array(),
139 28
                'keyword' => 'Scenario',
140 28
                'line' => $line,
141 28
                'steps' => array(),
142 28
            ),
143
            $hash
144 28
        );
145
146 28
        $steps = $this->loadStepsHash($hash['steps']);
147
148 28
        return new ScenarioNode($hash['title'], $hash['tags'], $steps, $hash['keyword'], $hash['line']);
149
    }
150
151
    /**
152
     * Loads outline from provided outline hash.
153
     *
154
     * @param array   $hash Outline hash
155
     * @param integer $line Outline definition line
156
     *
157
     * @return OutlineNode
158
     */
159 12
    protected function loadOutlineHash(array $hash, $line = 0)
160
    {
161 12
        $hash = array_merge(
162
            array(
163 12
                'title' => null,
164 12
                'tags' => array(),
165 12
                'keyword' => 'Scenario Outline',
166 12
                'line' => $line,
167 12
                'steps' => array(),
168 12
                'examples' => array(),
169 12
            ),
170
            $hash
171 12
        );
172
173 12
        $steps = $this->loadStepsHash($hash['steps']);
174
175 12
        if (isset($hash['examples']['keyword'])) {
176 1
            $examplesKeyword = $hash['examples']['keyword'];
177 1
            unset($hash['examples']['keyword']);
178 1
        } else {
179 11
            $examplesKeyword = 'Examples';
180
        }
181
182 12
        $exHash = $hash['examples'];
183
        $examples = array();
184 12
185
        if ($this->examplesAreInArray($exHash)) {
186
            $examples = $this->processExamplesArray($exHash, $examplesKeyword, $examples);
187
        } else {
188
            // examples as a single table - we create an array with the only one element
189
            $examples[] = new ExampleTableNode($exHash, $examplesKeyword);;
190
        }
191
192
        return new OutlineNode($hash['title'], $hash['tags'], $steps, $examples, $hash['keyword'], $hash['line']);
193
    }
194 37
195
    /**
196 37
     * Loads steps from provided hash.
197 37
     *
198 30
     * @param array $hash
199 37
     *
200
     * @return StepNode[]
201 37
     */
202
    private function loadStepsHash(array $hash)
203
    {
204
        $steps = array();
205
        foreach ($hash as $stepIterator => $stepHash) {
206
            $steps[] = $this->loadStepHash($stepHash, $stepIterator);
207
        }
208
209
        return $steps;
210
    }
211
212 30
    /**
213
     * Loads step from provided hash.
214 30
     *
215
     * @param array   $hash Step hash
216 30
     * @param integer $line Step definition line
217 30
     *
218 30
     * @return StepNode
219 30
     */
220 30
    protected function loadStepHash(array $hash, $line = 0)
221 30
    {
222 30
        $hash = array_merge(
223
            array(
224 30
                'keyword_type' => 'Given',
225
                'type' => 'Given',
226 30
                'text' => null,
227 30
                'keyword' => 'Scenario',
228 9
                'line' => $line,
229 4
                'arguments' => array(),
230 9
            ),
231 7
            $hash
232 7
        );
233 30
234
        $arguments = array();
235 30
        foreach ($hash['arguments'] as $argumentHash) {
236
            if ('table' === $argumentHash['type']) {
237
                $arguments[] = $this->loadTableHash($argumentHash['rows']);
238
            } elseif ('pystring' === $argumentHash['type']) {
239
                $arguments[] = $this->loadPyStringHash($argumentHash, $hash['line'] + 1);
240
            }
241
        }
242
243
        return new StepNode($hash['type'], $hash['text'], $arguments, $hash['line'], $hash['keyword_type']);
244
    }
245 4
246
    /**
247 4
     * Loads table from provided hash.
248
     *
249
     * @param array $hash Table hash
250
     *
251
     * @return TableNode
252
     */
253
    protected function loadTableHash(array $hash)
254
    {
255
        return new TableNode($hash);
256
    }
257
258 7
    /**
259
     * Loads PyString from provided hash.
260 7
     *
261
     * @param array   $hash PyString hash
262 7
     * @param integer $line
263 7
     *
264 7
     * @return PyStringNode
265 7
     */
266
    protected function loadPyStringHash(array $hash, $line = 0)
267 7
    {
268
        $line = isset($hash['line']) ? $hash['line'] : $line;
269
270
        $strings = array();
271
        foreach (explode("\n", $hash['text']) as $string) {
272
            $strings[] = $string;
273
        }
274
275
        return new PyStringNode($strings, $line);
276
    }
277
278
    /**
279
     * Checks if examples node is an array
280
     * @param $exHash object hash
281
     * @return bool
282
     */
283
    private function examplesAreInArray($exHash)
284
    {
285
        return isset($exHash[0]);
286
    }
287
288
    /**
289
     * Processes cases when examples are in the form of array of arrays
290
     * OR in the form of array of objects
291
     *
292
     * @param $exHash array hash
293
     * @param $examplesKeyword string
294
     * @param $examples array
295
     * @return array
296
     */
297
    private function processExamplesArray($exHash, $examplesKeyword, $examples)
298
    {
299
        for ($i = 0; $i < count($exHash); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
300
            if (isset($exHash[$i]['table'])) {
301
                // we have examples as objects, hence there could be tags
302
                $exHashTags = isset($exHash[$i]['tags']) ? $exHash[$i]['tags'] : array();
303
                $examples[] = new ExampleTableNode($exHash[$i]['table'], $examplesKeyword, $exHashTags);
304
            } else {
305
                // we have examples as arrays
306
                $examples[] = new ExampleTableNode($exHash[$i], $examplesKeyword);
307
            }
308
        }
309
310
        return $examples;
311
    }
312
}
313