Passed
Push — master ( 35a7ab...d29e83 )
by Matthew
07:21
created

WorkerCompilerPass::getJobClassArchive()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 12
nc 8
nop 1
dl 0
loc 18
ccs 13
cts 13
cp 1
crap 5
rs 9.5555
c 0
b 0
f 0
1
<?php
2
3
namespace Dtc\QueueBundle\DependencyInjection\Compiler;
4
5
use Dtc\GridBundle\DependencyInjection\Compiler\GridSourceCompilerPass;
6
use Dtc\QueueBundle\Model\Job;
7
use Dtc\QueueBundle\Model\JobTiming;
8
use Dtc\QueueBundle\Model\Run;
9
use Dtc\QueueBundle\Exception\ClassNotFoundException;
10
use Dtc\QueueBundle\Exception\ClassNotSubclassException;
11
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
12
use Symfony\Component\DependencyInjection\Alias;
13
use Symfony\Component\DependencyInjection\ContainerBuilder;
14
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
15
use Symfony\Component\DependencyInjection\Definition;
16
use Symfony\Component\DependencyInjection\Reference;
17
18
class WorkerCompilerPass implements CompilerPassInterface
19
{
20 4
    public function process(ContainerBuilder $container)
21
    {
22 4
        if (false === $container->hasDefinition('dtc_queue.manager.worker')) {
23 4
            return;
24
        }
25
26 4
        $this->setupAliases($container);
27
28 4
        $definition = $container->getDefinition('dtc_queue.manager.worker');
29
30 4
        $jobClass = $this->getJobClass($container);
31 3
        $jobArchiveClass = $this->getJobClassArchive($container);
32 3
        $container->setParameter('dtc_queue.class.job', $jobClass);
33 3
        $container->setParameter('dtc_queue.class.job_archive', $jobArchiveClass);
34
35 3
        $managerType = $this->getRunManagerType($container);
36 3
        $jobTimingManagerType = $this->getJobTimingManagerType($container);
37 3
        $container->setParameter('dtc_queue.class.job_timing', $this->getClass(
38 3
            $container,
39
            $jobTimingManagerType,
40 3
            'job_timing',
41 3
            'JobTiming',
42 3
            JobTiming::class
43
        ));
44 3
        $container->setParameter('dtc_queue.class.run', $this->getClass($container, $managerType, 'run', 'Run', Run::class));
45 3
        $container->setParameter('dtc_queue.class.run_archive', $this->getClass($container, $managerType, 'run_archive', 'RunArchive', Run::class));
46
47 3
        $this->setupTaggedServices($container, $definition);
48 2
        $eventDispatcher = $container->getDefinition('dtc_queue.event_dispatcher');
49 2
        foreach ($container->findTaggedServiceIds('dtc_queue.event_subscriber') as $id => $attributes) {
50
            $eventSubscriber = $container->getDefinition($id);
51
            $eventDispatcher->addMethodCall('addSubscriber', [$eventSubscriber]);
52
        }
53 2
        $this->setupDoctrineManagers($container);
54 2
        $this->addLiveJobs($container);
55 2
    }
56
57
    /**
58
     * Add any extra method calls needed.
59
     *
60
     * @param ContainerBuilder $container
61
     * @param string           $defaultManagerType
62
     */
63 4
    protected function addMethodCalls(ContainerBuilder $container, $defaultManagerType)
64
    {
65 4
        if ('orm' === $defaultManagerType) {
66 1
            $doctrine = $container->getDefinition('doctrine');
67 1
            $container->getDefinition('dtc_queue.doctrine_listener')->addMethodCall('setRegistry', [$doctrine]);
68 1
            $container->getDefinition('dtc_queue.manager.job.orm')->addMethodCall('setRegistry', [$doctrine]);
69 1
            $container->getDefinition('dtc_queue.manager.run.orm')->addMethodCall('setRegistry', [$doctrine]);
70 1
            $container->getDefinition('dtc_queue.manager.job_timing.orm')->addMethodCall('setRegistry', [$doctrine]);
71
        }
72 4
    }
73
74
    /**
75
     * @param string $type
76
     */
77 4
    protected function setupAlias(ContainerBuilder $container, $defaultManagerType, $type)
78
    {
79 4
        $definitionName = 'dtc_queue.'.$type.'.'.$defaultManagerType;
80 4
        if (!$container->hasDefinition($definitionName) && !$container->hasAlias($definitionName)) {
81
            throw new InvalidConfigurationException("No $type manager found for dtc_queue.$type.$defaultManagerType");
82
        }
83 4
        if ($container->hasDefinition($definitionName)) {
84 4
            $alias = new Alias('dtc_queue.'.$type.'.'.$defaultManagerType);
85 4
            $alias->setPublic(true);
86 4
            $container->setAlias('dtc_queue.'.$type, $alias);
87
88 4
            return;
89
        }
90
91
        $container->getAlias($definitionName)->setPublic(true);
92
        $container->setAlias('dtc_queue.'.$type, $container->getAlias($definitionName));
93
    }
94
95 4
    protected function setupAliases(ContainerBuilder $container)
96
    {
97 4
        $defaultManagerType = $container->getParameter('dtc_queue.manager.job');
98 4
        $this->addMethodCalls($container, $defaultManagerType);
99 4
        $this->setupAlias($container, $defaultManagerType, 'manager.job');
100 4
        $runManagerType = $container->getParameter($this->getRunManagerType($container));
101 4
        $this->addMethodCalls($container, $runManagerType);
102 4
        $this->setupAlias($container, $runManagerType, 'manager.run');
103 4
        $jobTimingManagerType = $container->getParameter($this->getJobTimingManagerType($container));
104 4
        $this->addMethodCalls($container, $jobTimingManagerType);
105 4
        $this->setupAlias($container, $jobTimingManagerType, 'manager.job_timing');
106 4
    }
107
108
    /**
109
     * @param ContainerBuilder $container
110
     * @param Definition       $definition
111
     */
112 3
    protected function setupTaggedServices(ContainerBuilder $container, Definition $definition)
113
    {
114 3
        $jobManagerRef = array(new Reference('dtc_queue.manager.job'));
115
        // Add each worker to workerManager, make sure each worker has instance to work
116 3
        foreach ($container->findTaggedServiceIds('dtc_queue.worker') as $id => $attributes) {
117 2
            $worker = $container->getDefinition($id);
118 2
            $class = $container->getDefinition($id)->getClass();
119
120 2
            $refClass = new \ReflectionClass($class);
121 2
            $workerClass = 'Dtc\QueueBundle\Model\Worker';
122 2
            if (!$refClass->isSubclassOf($workerClass)) {
123 1
                throw new \InvalidArgumentException(sprintf('Service "%s" must extend class "%s".', $id, $workerClass));
124
            }
125
126
            // Give each worker access to job manager
127 1
            $worker->addMethodCall('setJobManager', $jobManagerRef);
128 1
            $definition->addMethodCall('addWorker', array(new Reference($id)));
129
        }
130 2
    }
131
132
    /**
133
     * @param ContainerBuilder $container
134
     */
135 2
    protected function setupDoctrineManagers(ContainerBuilder $container)
136
    {
137 2
        $documentManager = $container->getParameter('dtc_queue.odm.document_manager');
138
139 2
        $odmManager = "doctrine_mongodb.odm.{$documentManager}_document_manager";
140 2
        if ($container->has($odmManager)) {
141
            $container->setAlias('dtc_queue.document_manager', $odmManager);
142
        }
143
144 2
        $entityManager = $container->getParameter('dtc_queue.orm.entity_manager');
145
146 2
        $ormManager = "doctrine.orm.{$entityManager}_entity_manager";
147 2
        if ($container->has($ormManager)) {
148
            $container->setAlias('dtc_queue.entity_manager', $ormManager);
149
        }
150 2
    }
151
152
    /**
153
     * @param ContainerBuilder $container
154
     */
155 2
    protected function addLiveJobs(ContainerBuilder $container)
156
    {
157 2
        $jobReflection = new \ReflectionClass($container->getParameter('dtc_queue.class.job'));
158
159 2
        if (!class_exists('Dtc\GridBundle\DtcGridBundle')) {
160
            return;
161
        }
162
163 2
        if ($jobReflection->isSubclassOf(\Dtc\QueueBundle\Document\BaseJob::class)) {
164 2
            GridSourceCompilerPass::addGridSource($container, 'dtc_queue.grid_source.jobs_waiting.odm');
165 2
            GridSourceCompilerPass::addGridSource($container, 'dtc_queue.grid_source.jobs_running.odm');
166
        }
167 2
        if ($jobReflection->isSubclassOf(\Dtc\QueueBundle\Entity\BaseJob::class)) {
168 1
            GridSourceCompilerPass::addGridSource($container, 'dtc_queue.grid_source.jobs_waiting.orm');
169 1
            GridSourceCompilerPass::addGridSource($container, 'dtc_queue.grid_source.jobs_running.orm');
170
        }
171 2
    }
172
173
    /**
174
     * @param $managerType
175
     *
176
     * @return string|null
177
     */
178 4
    protected function getDirectory($managerType)
179
    {
180 4
        switch ($managerType) {
181 4
            case 'odm':
182 3
                return 'Document';
183 2
            case 'beanstalkd':
184 1
                return 'Beanstalkd';
185 2
            case 'rabbit_mq':
186 1
                return 'RabbitMQ';
187 2
            case 'orm':
188 1
                return 'Entity';
189 2
            case 'redis':
190 1
                return 'Redis';
191
        }
192
193 1
        return null;
194
    }
195
196
    /**
197
     * Determines the job class based on the queue manager type.
198
     *
199
     * @param ContainerBuilder $container
200
     *
201
     * @return mixed|string
202
     *
203
     * @throws InvalidConfigurationException
204
     */
205 4
    protected function getJobClass(ContainerBuilder $container)
206
    {
207 4
        $jobClass = $container->getParameter('dtc_queue.class.job');
208 4
        if (!$jobClass) {
209 4
            if ($directory = $this->getDirectory($managerType = $container->getParameter('dtc_queue.manager.job'))) {
210 3
                $jobClass = 'Dtc\QueueBundle\\'.$directory.'\Job';
211
            } else {
212 1
                throw new InvalidConfigurationException('Unknown manager.job type '.$managerType.' - please specify a Job class in the \'class\' configuration parameter');
213
            }
214
        }
215
216 3
        $this->testClass($jobClass, Job::class);
217
218 3
        return $jobClass;
219
    }
220
221 4
    protected function getRunManagerType(ContainerBuilder $container)
222
    {
223 4
        $managerType = 'dtc_queue.manager.job';
224 4
        if ($container->hasParameter('dtc_queue.manager.run')) {
225 4
            $managerType = 'dtc_queue.manager.run';
226
        }
227
228 4
        return $managerType;
229
    }
230
231 4
    protected function getJobTimingManagerType(ContainerBuilder $container)
232
    {
233 4
        $managerType = $this->getRunManagerType($container);
234 4
        if ($container->hasParameter('dtc_queue.manager.job_timing')) {
235 4
            $managerType = 'dtc_queue.manager.job_timing';
236
        }
237
238 4
        return $managerType;
239
    }
240
241
    /**
242
     * @param string $managerType
243
     * @param string $type
244
     * @param string $className
245
     */
246 3
    protected function getClass(ContainerBuilder $container, $managerType, $type, $className, $baseClass)
247
    {
248 3
        $runClass = $container->hasParameter('dtc_queue.class.'.$type) ? $container->getParameter('dtc_queue.class.'.$type) : null;
249 3
        if (!$runClass) {
250 3
            switch ($container->getParameter($managerType)) {
251 3
                case 'odm':
252 3
                    $runClass = 'Dtc\\QueueBundle\\Document\\'.$className;
253 3
                    break;
254 1
                case 'orm':
255 1
                    $runClass = 'Dtc\\QueueBundle\\Entity\\'.$className;
256 1
                    break;
257
                default:
258
                    $runClass = $baseClass;
259
            }
260
        }
261
262 3
        $this->testClass($runClass, $baseClass);
263
264 3
        return $runClass;
265
    }
266
267
    /**
268
     * @throws ClassNotFoundException
269
     * @throws ClassNotSubclassException
270
     */
271 3
    protected function testClass($className, $parent)
272
    {
273 3
        if (!class_exists($className)) {
274
            throw new ClassNotFoundException("Can't find class $className");
275
        }
276
277 3
        $test = new $className();
278 3
        if (!$test instanceof $className) {
279
            throw new ClassNotSubclassException("$className must be instance of (or derived from) $parent");
280
        }
281 3
    }
282
283
    /**
284
     * Determines the job class based on the queue manager type.
285
     *
286
     * @param ContainerBuilder $container
287
     *
288
     * @return mixed|string
289
     *
290
     * @throws ClassNotFoundException
291
     * @throws ClassNotSubclassException
292
     */
293 3
    protected function getJobClassArchive(ContainerBuilder $container)
294
    {
295 3
        $jobArchiveClass = $container->getParameter('dtc_queue.class.job_archive');
296 3
        if (!$jobArchiveClass) {
297 3
            switch ($container->getParameter('dtc_queue.manager.job')) {
298 3
                case 'odm':
299 3
                    $jobArchiveClass = 'Dtc\\QueueBundle\\Document\\JobArchive';
300 3
                    break;
301 1
                case 'orm':
302 1
                    $jobArchiveClass = 'Dtc\\QueueBundle\\Entity\\JobArchive';
303 1
                    break;
304
            }
305
        }
306 3
        if (null !== $jobArchiveClass) {
307 3
            $this->testClass($jobArchiveClass, Job::class);
308
        }
309
310 3
        return $jobArchiveClass;
311
    }
312
}
313