GearmanParser::loadBundleNamespaceMap()   B
last analyzed

Complexity

Conditions 6
Paths 2

Size

Total Lines 44

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 44
ccs 16
cts 16
cp 1
rs 8.5937
c 0
b 0
f 0
cc 6
nc 2
nop 2
crap 6
1
<?php
2
3
/**
4
 * Gearman Bundle for Symfony2 / Symfony3
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 *
9
 * Feel free to edit as you please, and have fun.
10
 *
11
 * @author Marc Morera <[email protected]>
12
 */
13
14
namespace Mkk\GearmanBundle\Service;
15
16
use Doctrine\Common\Annotations\Reader;
17
use Symfony\Component\Finder\Finder;
18
use Symfony\Component\HttpKernel\KernelInterface;
19
use Mkk\GearmanBundle\Driver\Gearman\Work as WorkAnnotation;
20
use Mkk\GearmanBundle\Module\WorkerClass as Worker;
21
use Mkk\GearmanBundle\Module\WorkerCollection;
22
23
/**
24
 * Gearman parsing methods
25
 *
26
 * This class has responability of parsing, if needed, all defined bundle files
27
 * looking for some Workers.
28
 */
29
class GearmanParser
30
{
31
32
    /**
33
     * @var array
34
     *
35
     * Bundles loaded by kernel
36
     */
37
    private $kernelBundles;
38
39
    /**
40
     * @var Reader
41
     *
42
     * Annotation Reader
43
     */
44
    private $reader;
45
46
    /**
47
     * @var Finder
48
     *
49
     * Finder
50
     */
51
    private $finder;
52
53
    /**
54
     * @var array
55
     *
56
     * Bundles available to perform search
57
     */
58
    private $bundles;
59
60
    /**
61
     * @var array
62
     *
63
     * Namespaces paths to be searched
64
     */
65
    private $resources;
66
67
    /**
68
     * @var array
69
     *
70
     * Collection of servers to connect
71
     */
72
    private $servers;
73
74
    /**
75
     * @var array
76
     *
77
     * Default settings defined by user in config.yml
78
     */
79
    private $defaultSettings;
80
81
    /**
82
     * Root kernel directory
83
     *
84
     * @var string
85
     */
86
    private $rootDir;
87
88
    /**
89
     * Construct method
90
     *
91
     * @param KernelInterface $kernel          Kernel instance
92
     * @param Reader          $reader          Reader
93
     * @param Finder          $finder          Finder
94
     * @param array           $bundles         Bundle array where to parse workers, defined on condiguration
95
     * @param array           $resources       Array of namespace paths to be searched for worker annotations
96
     * @param array           $servers         Server list defined on configuration
97
     * @param array           $defaultSettings Default settings defined on configuration
98
     */
99 9
    public function __construct(
100
        KernelInterface $kernel,
101
        Reader $reader,
102
        Finder $finder,
103
        array $bundles,
104
        array $resources,
105
        array $servers,
106
        array $defaultSettings
107
    )
108
    {
109 9
        $this->kernelBundles = $kernel->getBundles();
110 9
        $this->reader = $reader;
111 9
        $this->finder = $finder;
112 9
        $this->bundles = $bundles;
113 9
        $this->resources = $resources;
114 9
        $this->servers = $servers;
115 9
        $this->defaultSettings = $defaultSettings;
116 9
        $this->rootDir = $kernel->getRootDir();
117 9
    }
118
119
    /**
120
     * Loads Worker Collection from parsed files
121
     *
122
     * @return WorkerCollection collection of all info
123
     */
124 3
    public function load()
125
    {
126 3
        list($paths, $excludedPaths) = $this->loadBundleNamespaceMap($this->kernelBundles, $this->bundles);
127 3
        $paths = array_merge($paths, $this->loadResourceNamespaceMap($this->rootDir, $this->resources));
128
129 3
        return $this->parseNamespaceMap($this->finder, $this->reader, $paths, $excludedPaths);
130
    }
131
132
    /**
133
     * Return Gearman bundle settings, previously loaded by method load()
134
     *
135
     * If settings are not loaded, a SettingsNotLoadedException Exception is thrown
136
     *
137
     * @param array $kernelBundles Kernel bundles
138
     * @param array $bundles       Bundle array of settings
139
     *
140
     * @return array Return an array containing paths and ignore paths
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array[].

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
141
     */
142 8
    public function loadBundleNamespaceMap(array $kernelBundles, array $bundles)
143
    {
144 8
        $paths = array();
145 8
        $excludedPaths = array();
146
147
        /**
148
         * Iteratinc all bundle settings
149
         */
150 8
        foreach ($bundles as $bundleSettings) {
151
152 5
            if (!$bundleSettings['active']) {
153
154 1
                break;
155
            }
156
157 4
            $bundleNamespace = $bundleSettings['name'];
158 4
            $bundlePath = $kernelBundles[$bundleNamespace]->getPath();
159
160 4
            if (!empty($bundleSettings['include'])) {
161
162 2
                foreach ($bundleSettings['include'] as $include) {
163
164 2
                    $paths[] = rtrim(rtrim($bundlePath, '/') . '/' . $include, '/') . '/';
165
                }
166
167
            } else {
168
169
                /**
170
                 * If no include is set, include all namespace
171
                 */
172 2
                $paths[] = rtrim($bundlePath, '/') . '/';
173
            }
174
175 4
            foreach ($bundleSettings['ignore'] as $ignore) {
176
177 4
                $excludedPaths[] = trim($ignore, '/');
178
            }
179
        }
180
181
        return array(
182 8
            $paths,
183 8
            $excludedPaths,
184
        );
185
    }
186
187
    /**
188
     * Get resource paths
189
     * @param string $rootDir
190
     * @param array $resources
191
     * @return array
192
     */
193
    public function loadResourceNamespaceMap($rootDir, array $resources)
194
    {
195 4
        return array_map(function($resource) use ($rootDir) {
196 1
            return $rootDir . '/' . trim($resource, '/') . '/';
197 4
        }, $resources);
198
    }
199
200
    /**
201
     * Perform a parsing inside all namespace map
202
     *
203
     * Creates an empty worker collection and, if exist some parseable files
204
     * parse them, filling this object
205
     *
206
     * @param Finder $finder        Finder
207
     * @param Reader $reader        Reader
208
     * @param array  $paths         Paths where to look for
209
     * @param array  $excludedPaths Paths to ignore
210
     *
211
     * @return WorkerCollection collection of all info
212
     */
213 5
    public function parseNamespaceMap(
214
        Finder $finder,
215
        Reader $reader,
216
        array $paths,
217
        array $excludedPaths
218
    )
219
    {
220 5
        $workerCollection = new WorkerCollection;
221
222 5
        if (!empty($paths)) {
223
224
            $finder
225 1
                ->files()
226 1
                ->followLinks()
227 1
                ->exclude($excludedPaths)
228 1
                ->in($paths)
229 1
                ->name('*.php');
230
231 1
            $this->parseFiles($finder, $reader, $workerCollection);
232
        }
233
234 5
        return $workerCollection;
235
    }
236
237
    /**
238
     * Load all workers with their jobs
239
     *
240
     * @param Finder           $finder           Finder
241
     * @param Reader           $reader           Reader
242
     * @param WorkerCollection $workerCollection Worker collection
243
     *
244
     * @return GearmanParser self Object
245
     */
246
    public function parseFiles(
247
        Finder $finder,
248
        Reader $reader,
249
        WorkerCollection $workerCollection
250
    )
251
    {
252
253
        /**
254
         * Every file found is parsed
255
         */
256
        foreach ($finder as $file) {
257
258
            /**
259
             * File is accepted to be parsed
260
             */
261
            $classNamespace = $this->getFileClassNamespace($file->getRealpath());
262
            $reflectionClass = new \ReflectionClass($classNamespace);
263
            $classAnnotations = $reader->getClassAnnotations($reflectionClass);
264
265
            /**
266
             * Every annotation found is parsed
267
             */
268
            foreach ($classAnnotations as $annotation) {
269
270
                /**
271
                 * Annotation is only laoded if is typeof WorkAnnotation
272
                 */
273
                if ($annotation instanceof WorkAnnotation) {
274
275
                    /**
276
                     * Creates new Worker element with all its Job data
277
                     */
278
                    $worker = new Worker($annotation, $reflectionClass, $reader, $this->servers, $this->defaultSettings);
279
                    $workerCollection->add($worker);
280
                }
281
            }
282
        }
283
284
        return $this;
285
    }
286
287
    /**
288
     * Returns file class namespace, if exists
289
     *
290
     * @param string $file A PHP file path
291
     *
292
     * @return string|false Full class namespace if found, false otherwise
293
     */
294 2
    public function getFileClassNamespace($file)
295
    {
296 2
        $filenameBlock = explode(DIRECTORY_SEPARATOR, $file);
297 2
        $filename = explode('.', end($filenameBlock), 2);
298 2
        $filename = reset($filename);
299
300 2
        preg_match('/\snamespace\s+(.+?);/s', file_get_contents($file), $match);
301
302 2
        return    is_array($match) && isset($match[1])
303 2
                ? $match[1] . '\\' . $filename
304 2
                : false;
305
    }
306
}
307