Security update for permissions_by_term
[yaffs-website] / vendor / behat / behat / src / Behat / Behat / Gherkin / Specification / Locator / FilesystemFeatureLocator.php
1 <?php
2
3 /*
4  * This file is part of the Behat.
5  * (c) Konstantin Kudryashov <ever.zet@gmail.com>
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\Behat\Gherkin\Specification\Locator;
12
13 use Behat\Behat\Gherkin\Specification\LazyFeatureIterator;
14 use Behat\Gherkin\Filter\PathsFilter;
15 use Behat\Gherkin\Gherkin;
16 use Behat\Testwork\Specification\Locator\SpecificationLocator;
17 use Behat\Testwork\Specification\NoSpecificationsIterator;
18 use Behat\Testwork\Suite\Exception\SuiteConfigurationException;
19 use Behat\Testwork\Suite\Suite;
20 use RecursiveDirectoryIterator;
21 use RecursiveIteratorIterator;
22 use RegexIterator;
23
24 /**
25  * Loads gherkin features from the filesystem using gherkin parser.
26  *
27  * @author Konstantin Kudryashov <ever.zet@gmail.com>
28  */
29 final class FilesystemFeatureLocator implements SpecificationLocator
30 {
31     /**
32      * @var Gherkin
33      */
34     private $gherkin;
35     /**
36      * @var string
37      */
38     private $basePath;
39
40     /**
41      * Initializes loader.
42      *
43      * @param Gherkin $gherkin
44      * @param string  $basePath
45      */
46     public function __construct(Gherkin $gherkin, $basePath)
47     {
48         $this->gherkin = $gherkin;
49         $this->basePath = $basePath;
50     }
51
52     /**
53      * {@inheritdoc}
54      */
55     public function getLocatorExamples()
56     {
57         return array(
58             "a dir <comment>(features/)</comment>",
59             "a feature <comment>(*.feature)</comment>",
60             "a scenario at specific line <comment>(*.feature:10)</comment>.",
61             "all scenarios at or after a specific line <comment>(*.feature:10-*)</comment>.",
62             "all scenarios at a line within a specific range <comment>(*.feature:10-20)</comment>."
63         );
64     }
65
66     /**
67      * {@inheritdoc}
68      */
69     public function locateSpecifications(Suite $suite, $locator)
70     {
71         if (!$suite->hasSetting('paths')) {
72             return new NoSpecificationsIterator($suite);
73         }
74
75         $suiteLocators = $this->getSuitePaths($suite);
76
77         if ($locator) {
78             $filters = array(new PathsFilter($suiteLocators));
79
80             return new LazyFeatureIterator($suite, $this->gherkin, $this->findFeatureFiles($locator), $filters);
81         }
82
83         $featurePaths = array();
84         foreach ($suiteLocators as $suiteLocator) {
85             $featurePaths = array_merge($featurePaths, $this->findFeatureFiles($suiteLocator));
86         }
87
88         return new LazyFeatureIterator($suite, $this->gherkin, $featurePaths);
89     }
90
91     /**
92      * Returns array of feature paths configured for the provided suite.
93      *
94      * @param Suite $suite
95      *
96      * @return string[]
97      *
98      * @throws SuiteConfigurationException If `paths` setting is not an array
99      */
100     private function getSuitePaths(Suite $suite)
101     {
102         if (!is_array($suite->getSetting('paths'))) {
103             throw new SuiteConfigurationException(
104                 sprintf('`paths` setting of the "%s" suite is expected to be an array, %s given.',
105                     $suite->getName(),
106                     gettype($suite->getSetting('paths'))
107                 ),
108                 $suite->getName()
109             );
110         }
111
112         return $suite->getSetting('paths');
113     }
114
115     /**
116      * Loads feature files paths from provided path.
117      *
118      * @param string $path
119      *
120      * @return string[]
121      */
122     private function findFeatureFiles($path)
123     {
124         $absolutePath = $this->findAbsolutePath($path);
125
126         if (!$absolutePath) {
127             return array($path);
128         }
129
130         if (is_file($absolutePath)) {
131             return array($absolutePath);
132         }
133
134         $iterator = new RegexIterator(
135             new RecursiveIteratorIterator(
136                 new RecursiveDirectoryIterator(
137                     $absolutePath,
138                     RecursiveDirectoryIterator::FOLLOW_SYMLINKS | RecursiveDirectoryIterator::SKIP_DOTS
139                 )
140             ),
141             '/^.+\.feature$/i',
142             RegexIterator::MATCH
143         );
144
145         $paths = array_map('strval', iterator_to_array($iterator));
146         uasort($paths, 'strnatcasecmp');
147
148         return $paths;
149     }
150
151     /**
152      * Finds absolute path for provided relative (relative to base features path).
153      *
154      * @param string $path Relative path
155      *
156      * @return string
157      */
158     private function findAbsolutePath($path)
159     {
160         if (is_file($path) || is_dir($path)) {
161             return realpath($path);
162         }
163
164         if (null === $this->basePath) {
165             return false;
166         }
167
168         if (is_file($this->basePath . DIRECTORY_SEPARATOR . $path)
169             || is_dir($this->basePath . DIRECTORY_SEPARATOR . $path)
170         ) {
171             return realpath($this->basePath . DIRECTORY_SEPARATOR . $path);
172         }
173
174         return false;
175     }
176 }