Completed
Push — master ( ad518d...0b0f4b )
by Matthew
05:51
created

WorkerCompilerPass::setupAliases()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

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