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