Completed
Push — master ( 4109b7...859c70 )
by Matthew
08:07 queued 02:26
created

WorkerCompilerPass::process()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 28
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 3.0067

Importance

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