Completed
Push — master ( 16d212...b7b31c )
by Matthew
07:34 queued 05:11
created

WorkerCompilerPass::getDirectory()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 16
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 15.2788

Importance

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