Completed
Push — master ( 27aa78...27daf5 )
by Matthew
14:56
created

WorkerCompilerPass::process()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 30
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 3.0059

Importance

Changes 0
Metric Value
dl 0
loc 30
ccs 21
cts 23
cp 0.913
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 21
nc 3
nop 1
crap 3.0059
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 3
    public function process(ContainerBuilder $container)
21
    {
22 3
        if (false === $container->hasDefinition('dtc_queue.worker_manager')) {
23 3
            return;
24
        }
25
26 3
        $this->setupAliases($container);
27
28 3
        $definition = $container->getDefinition('dtc_queue.worker_manager');
29 3
        $jobManagerRef = array(new Reference('dtc_queue.job_manager'));
30
31 3
        $jobClass = $this->getJobClass($container);
32 3
        $jobArchiveClass = $this->getJobClassArchive($container);
33 3
        $container->setParameter('dtc_queue.class_job', $jobClass);
34 3
        $container->setParameter('dtc_queue.class_job_archive', $jobArchiveClass);
35
36 3
        $managerType = $this->getRunManagerType($container);
37 3
        $container->setParameter('dtc_queue.class_job_timing', $this->getClass($container, $managerType, 'job_timing',
38 3
            'JobTiming', JobTiming::class));
39 3
        $container->setParameter('dtc_queue.class_run', $this->getClass($container, $managerType, 'run', 'Run', Run::class));
40 3
        $container->setParameter('dtc_queue.class_run_archive', $this->getClass($container, $managerType, 'run_archive', 'RunArchive', Run::class));
41
42 3
        $this->setupTaggedServices($container, $definition, $jobManagerRef, $jobClass);
43 2
        $eventDispatcher = $container->getDefinition('dtc_queue.event_dispatcher');
44 2
        foreach ($container->findTaggedServiceIds('dtc_queue.event_subscriber') as $id => $attributes) {
45
            $eventSubscriber = $container->getDefinition($id);
46
            $eventDispatcher->addMethodCall('addSubscriber', [$eventSubscriber]);
47 2
        }
48 2
        $this->setupDoctrineManagers($container);
49 2
    }
50
51 3
    protected function setupAlias(ContainerBuilder $container, $defaultManagerType, $type)
52
    {
53 3
        $definitionName = 'dtc_queue.'.$type.'.'.$defaultManagerType;
54 3
        if (!$container->hasDefinition($definitionName) && !$container->hasAlias($definitionName)) {
55
            throw new InvalidConfigurationException("No job manager found for dtc_queue.$type.$defaultManagerType");
56
        }
57 3
        if ($container->hasDefinition($definitionName)) {
58 3
            $alias = new Alias('dtc_queue.'.$type.'.'.$defaultManagerType);
59 3
            $container->setAlias('dtc_queue.'.$type, $alias);
60 3
        } else {
61
            $container->setAlias('dtc_queue.'.$type, $container->getAlias($definitionName));
62
        }
63 3
    }
64
65 3
    protected function setupAliases(ContainerBuilder $container)
66
    {
67 3
        $defaultManagerType = $container->getParameter('dtc_queue.default_manager');
68 3
        $this->setupAlias($container, $defaultManagerType, 'job_manager');
69 3
        $defaultRunManagerType = $container->getParameter('dtc_queue.run_manager');
70 3
        $this->setupAlias($container, $defaultRunManagerType, 'run_manager');
71 3
    }
72
73
    /**
74
     * @param ContainerBuilder $container
75
     * @param Reference[]      $jobManagerRef
76
     * @param string           $jobClass
77
     */
78 3
    protected function setupTaggedServices(ContainerBuilder $container, Definition $definition, array $jobManagerRef, $jobClass)
79
    {
80
        // Add each worker to workerManager, make sure each worker has instance to work
81 3
        foreach ($container->findTaggedServiceIds('dtc_queue.worker') as $id => $attributes) {
82 2
            $worker = $container->getDefinition($id);
83 2
            $class = $container->getDefinition($id)->getClass();
84
85 2
            $refClass = new \ReflectionClass($class);
86 2
            $workerClass = 'Dtc\QueueBundle\Model\Worker';
87 2
            if (!$refClass->isSubclassOf($workerClass)) {
88 1
                throw new \InvalidArgumentException(sprintf('Service "%s" must extend class "%s".', $id, $workerClass));
89
            }
90
91
            // Give each worker access to job manager
92 1
            $worker->addMethodCall('setJobManager', $jobManagerRef);
93 1
            $worker->addMethodCall('setJobClass', array($jobClass));
94
95 1
            $definition->addMethodCall('addWorker', array(new Reference($id)));
96 2
        }
97 2
    }
98
99 2
    protected function setupDoctrineManagers(ContainerBuilder $container)
100
    {
101 2
        $documentManager = $container->getParameter('dtc_queue.document_manager');
102
103 2
        $odmManager = "doctrine_mongodb.odm.{$documentManager}_document_manager";
104 2
        if ($container->has($odmManager)) {
105
            $container->setAlias('dtc_queue.document_manager', $odmManager);
106
            GridSourceCompilerPass::addGridSource($container, 'dtc_queue.grid_source.live_jobs.odm');
107
        }
108
109 2
        $entityManager = $container->getParameter('dtc_queue.entity_manager');
110
111 2
        $ormManager = "doctrine.orm.{$entityManager}_entity_manager";
112 2
        if ($container->has($ormManager)) {
113
            $container->setAlias('dtc_queue.entity_manager', $ormManager);
114
            GridSourceCompilerPass::addGridSource($container, 'dtc_queue.grid_source.live_jobs.orm');
115
        }
116 2
    }
117
118
    /**
119
     * @param $managerType
120
     *
121
     * @return null|string
122
     */
123 3
    protected function getDirectory($managerType)
124
    {
125
        switch ($managerType) {
126 3
            case 'mongodb': // deprecated remove in 3.0
127 3
            case 'odm':
128 3
                return 'Document';
129
            case 'beanstalkd':
130
                return 'Beanstalkd';
131
            case 'rabbit_mq':
132
                return 'RabbitMQ';
133
            case 'orm':
134
                return 'Entity';
135
        }
136
137
        return null;
138
    }
139
140
    /**
141
     * Determines the job class based on the queue manager type.
142
     *
143
     * @param ContainerBuilder $container
144
     *
145
     * @return mixed|string
146
     *
147
     * @throws InvalidConfigurationException
148
     */
149 3
    protected function getJobClass(ContainerBuilder $container)
150
    {
151 3
        $jobClass = $container->getParameter('dtc_queue.class_job');
152 3
        if (!$jobClass) {
153 3
            if ($directory = $this->getDirectory($managerType = $container->getParameter('dtc_queue.default_manager'))) {
154 3
                $jobClass = 'Dtc\QueueBundle\\'.$directory.'\Job';
155 3
            } else {
156
                throw new InvalidConfigurationException('Unknown default_manager type '.$managerType.' - please specify a Job class in the \'class\' configuration parameter');
157
            }
158 3
        }
159
160 3
        $this->testClass($jobClass, Job::class);
161
162 3
        return $jobClass;
163
    }
164
165 3
    protected function getRunManagerType(ContainerBuilder $container)
166
    {
167 3
        $managerType = 'dtc_queue.default_manager';
168 3
        if ($container->hasParameter('dtc_queue.run_manager')) {
169 3
            $managerType = 'dtc_queue.run_manager';
170 3
        }
171
172 3
        return $managerType;
173
    }
174
175 3
    protected function getClass(ContainerBuilder $container, $managerType, $type, $className, $baseClass)
176
    {
177 3
        $runClass = $container->hasParameter('dtc_queue.class_'.$type) ? $container->getParameter('dtc_queue.class_'.$type) : null;
178 3
        if (!$runClass) {
179 3
            switch ($container->getParameter($managerType)) {
180 3
                case 'mongodb': // deprecated remove in 3.0
181 3
                case 'odm':
182 3
                    $runClass = 'Dtc\\QueueBundle\\Document\\'.$className;
183 3
                    break;
184
                case 'orm':
185
                    $runClass = 'Dtc\\QueueBundle\\Entity\\'.$className;
186
                    break;
187
                default:
188
                    $runClass = $baseClass;
189 3
            }
190 3
        }
191
192 3
        $this->testClass($runClass, $baseClass);
193
194 3
        return $runClass;
195
    }
196
197
    /**
198
     * @throws ClassNotFoundException
199
     * @throws ClassNotSubclassException
200
     */
201 3
    protected function testClass($className, $parent)
202
    {
203 3
        if (!class_exists($className)) {
204
            throw new ClassNotFoundException("Can't find class $className");
205
        }
206
207 3
        $test = new $className();
208 3
        if (!$test instanceof $className) {
209
            throw new ClassNotSubclassException("$className must be instance of (or derived from) $parent");
210
        }
211 3
    }
212
213
    /**
214
     * Determines the job class based on the queue manager type.
215
     *
216
     * @param ContainerBuilder $container
217
     *
218
     * @return mixed|string
219
     *
220
     * @throws ClassNotFoundException
221
     * @throws ClassNotSubclassException
222
     */
223 3
    protected function getJobClassArchive(ContainerBuilder $container)
224
    {
225 3
        $jobArchiveClass = $container->getParameter('dtc_queue.class_job_archive');
226 3
        if (!$jobArchiveClass) {
227 3
            switch ($container->getParameter('dtc_queue.default_manager')) {
228 3
                case 'mongodb': // deprecated remove in 4.0
229 3
                case 'odm':
230 3
                    $jobArchiveClass = 'Dtc\\QueueBundle\\Document\\JobArchive';
231 3
                    break;
232
                case 'orm':
233
                    $jobArchiveClass = 'Dtc\\QueueBundle\\Entity\\JobArchive';
234
                    break;
235 3
            }
236 3
        }
237 3
        if (null !== $jobArchiveClass) {
238 3
            $this->testClass($jobArchiveClass, Job::class);
239 3
        }
240
241 3
        return $jobArchiveClass;
242
    }
243
}
244