Completed
Push — master ( 17631a...07adb9 )
by Matthew
05:11
created

WorkerCompilerPass::testRunClass()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

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