Completed
Push — master ( 0b2176...a454e0 )
by Matthew
05:42
created

WorkerCompilerPass::setupAliases()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

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