WorkerCompilerPass   A
last analyzed

Complexity

Total Complexity 41

Size/Duplication

Total Lines 254
Duplicated Lines 0 %

Test Coverage

Coverage 92.03%

Importance

Changes 6
Bugs 3 Features 0
Metric Value
wmc 41
eloc 123
c 6
b 3
f 0
dl 0
loc 254
ccs 127
cts 138
cp 0.9203
rs 9.1199

12 Methods

Rating   Name   Duplication   Size   Complexity  
A process() 0 34 3
A testClass() 0 9 3
A setupAliases() 0 11 1
A getClass() 0 19 5
A setupDoctrineManagers() 0 14 3
A getJobClass() 0 14 3
A getJobTimingManagerType() 0 8 2
A setupTaggedServices() 0 17 3
A setupAlias() 0 16 4
A getJobClassArchive() 0 18 5
A getDirectory() 0 16 6
A addMethodCalls() 0 8 3

How to fix   Complexity   

Complex Class

Complex classes like WorkerCompilerPass often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use WorkerCompilerPass, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Dtc\QueueBundle\DependencyInjection\Compiler;
4
5
use Dtc\QueueBundle\Exception\ClassNotFoundException;
6
use Dtc\QueueBundle\Exception\ClassNotSubclassException;
7
use Dtc\QueueBundle\Model\Job;
8
use Dtc\QueueBundle\Model\JobTiming;
9
use Dtc\QueueBundle\Model\Run;
10
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Config...dConfigurationException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use Symfony\Component\DependencyInjection\Alias;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\DependencyInjection\Alias was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Depend...r\CompilerPassInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
use Symfony\Component\DependencyInjection\ContainerBuilder;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Depend...ection\ContainerBuilder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
use Symfony\Component\DependencyInjection\Definition;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\DependencyInjection\Definition was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
use Symfony\Component\DependencyInjection\Reference;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\DependencyInjection\Reference was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
16
17
class WorkerCompilerPass implements CompilerPassInterface
18
{
19 1
    use WorkerCompilerTrait;
20
21 4
    public function process(ContainerBuilder $container)
22
    {
23 4
        if (false === $container->hasDefinition('dtc_queue.manager.worker')) {
24 4
            return;
25
        }
26
27 4
        $this->setupAliases($container);
28
29 4
        $definition = $container->getDefinition('dtc_queue.manager.worker');
30
31 4
        $jobClass = $this->getJobClass($container);
32 3
        $jobArchiveClass = $this->getJobClassArchive($container);
33 3
        $container->setParameter('dtc_queue.class.job', $jobClass);
34 3
        $container->setParameter('dtc_queue.class.job_archive', $jobArchiveClass);
35
36 3
        $managerType = $this->getRunManagerType($container);
37 3
        $jobTimingManagerType = $this->getJobTimingManagerType($container);
38 3
        $container->setParameter('dtc_queue.class.job_timing', $this->getClass(
39 3
            $container,
40
            $jobTimingManagerType,
41 3
            'job_timing',
42 3
            'JobTiming',
43 3
            JobTiming::class
44
        ));
45 3
        $container->setParameter('dtc_queue.class.run', $this->getClass($container, $managerType, 'run', 'Run', Run::class));
46 3
        $container->setParameter('dtc_queue.class.run_archive', $this->getClass($container, $managerType, 'run_archive', 'RunArchive', Run::class));
47
48 3
        $this->setupTaggedServices($container, $definition);
49 2
        $eventDispatcher = $container->getDefinition('dtc_queue.event_dispatcher');
50 2
        foreach ($container->findTaggedServiceIds('dtc_queue.event_subscriber') as $id => $attributes) {
51
            $eventSubscriber = $container->getDefinition($id);
52
            $eventDispatcher->addMethodCall('addSubscriber', [$eventSubscriber]);
53
        }
54 2
        $this->setupDoctrineManagers($container);
55 2
    }
56
57
    /**
58
     * Add any extra method calls needed.
59
     *
60
     * @param string $managerType
61
     */
62 4
    protected function addMethodCalls(ContainerBuilder $container, $managerType)
63
    {
64 4
        if ('orm' === $managerType && $container->hasDefinition('doctrine')) {
65 1
            $doctrine = $container->getDefinition('doctrine');
66 1
            $container->getDefinition('dtc_queue.doctrine_listener')->addMethodCall('setRegistry', [$doctrine]);
67 1
            $container->getDefinition('dtc_queue.manager.job.orm')->addMethodCall('setRegistry', [$doctrine]);
68 1
            $container->getDefinition('dtc_queue.manager.run.orm')->addMethodCall('setRegistry', [$doctrine]);
69 1
            $container->getDefinition('dtc_queue.manager.job_timing.orm')->addMethodCall('setRegistry', [$doctrine]);
70
        }
71 4
    }
72
73
    /**
74
     * @param string $type
75
     */
76 4
    protected function setupAlias(ContainerBuilder $container, $defaultManagerType, $type)
77
    {
78 4
        $definitionName = 'dtc_queue.'.$type.'.'.$defaultManagerType;
79 4
        if (!$container->hasDefinition($definitionName) && !$container->hasAlias($definitionName)) {
80
            throw new InvalidConfigurationException("No $type manager found for dtc_queue.$type.$defaultManagerType");
81
        }
82 4
        if ($container->hasDefinition($definitionName)) {
83 4
            $alias = new Alias('dtc_queue.'.$type.'.'.$defaultManagerType);
84 4
            $alias->setPublic(true);
85 4
            $container->setAlias('dtc_queue.'.$type, $alias);
86
87 4
            return;
88
        }
89
90
        $container->getAlias($definitionName)->setPublic(true);
91
        $container->setAlias('dtc_queue.'.$type, $container->getAlias($definitionName));
92
    }
93
94 4
    protected function setupAliases(ContainerBuilder $container)
95
    {
96 4
        $defaultManagerType = $container->getParameter('dtc_queue.manager.job');
97 4
        $this->addMethodCalls($container, $defaultManagerType);
98 4
        $this->setupAlias($container, $defaultManagerType, 'manager.job');
99 4
        $runManagerType = $container->getParameter($this->getRunManagerType($container));
100 4
        $this->addMethodCalls($container, $runManagerType);
101 4
        $this->setupAlias($container, $runManagerType, 'manager.run');
102 4
        $jobTimingManagerType = $container->getParameter($this->getJobTimingManagerType($container));
103 4
        $this->addMethodCalls($container, $jobTimingManagerType);
104 4
        $this->setupAlias($container, $jobTimingManagerType, 'manager.job_timing');
105 4
    }
106
107
    /**
108
     * @throws
109
     */
110 3
    protected function setupTaggedServices(ContainerBuilder $container, Definition $definition)
111
    {
112 3
        $jobManagerRef = [new Reference('dtc_queue.manager.job')];
113
        // Add each worker to workerManager, make sure each worker has instance to work
114 3
        foreach ($container->findTaggedServiceIds('dtc_queue.worker') as $id => $attributes) {
115 2
            $worker = $container->getDefinition($id);
116 2
            $class = $container->getDefinition($id)->getClass();
117
118 2
            $refClass = new \ReflectionClass($class);
119 2
            $workerClass = 'Dtc\QueueBundle\Model\Worker';
120 2
            if (!$refClass->isSubclassOf($workerClass)) {
121 1
                throw new \InvalidArgumentException(sprintf('Service "%s" must extend class "%s".', $id, $workerClass));
122
            }
123
124
            // Give each worker access to job manager
125 1
            $worker->addMethodCall('setJobManager', $jobManagerRef);
126 1
            $definition->addMethodCall('addWorker', [new Reference($id)]);
127
        }
128 2
    }
129
130 2
    protected function setupDoctrineManagers(ContainerBuilder $container)
131
    {
132 2
        $documentManager = $container->getParameter('dtc_queue.odm.document_manager');
133
134 2
        $odmManager = "doctrine_mongodb.odm.{$documentManager}_document_manager";
135 2
        if ($container->has($odmManager)) {
136
            $container->setAlias('dtc_queue.document_manager', $odmManager);
137
        }
138
139 2
        $entityManager = $container->getParameter('dtc_queue.orm.entity_manager');
140
141 2
        $ormManager = "doctrine.orm.{$entityManager}_entity_manager";
142 2
        if ($container->has($ormManager)) {
143
            $container->setAlias('dtc_queue.entity_manager', $ormManager);
144
        }
145 2
    }
146
147
    /**
148
     * @param $managerType
149
     *
150
     * @return string|null
151
     */
152 4
    protected function getDirectory($managerType)
153
    {
154 4
        switch ($managerType) {
155 4
            case 'odm':
156 3
                return 'Document';
157 2
            case 'beanstalkd':
158 1
                return 'Beanstalkd';
159 2
            case 'rabbit_mq':
160 1
                return 'RabbitMQ';
161 2
            case 'orm':
162 1
                return 'Entity';
163 2
            case 'redis':
164 1
                return 'Redis';
165
        }
166
167 1
        return null;
168
    }
169
170
    /**
171
     * Determines the job class based on the queue manager type.
172
     *
173
     * @return mixed|string
174
     *
175
     * @throws
176
     */
177 4
    protected function getJobClass(ContainerBuilder $container)
178
    {
179 4
        $jobClass = $container->getParameter('dtc_queue.class.job');
180 4
        if (!$jobClass) {
181 4
            if ($directory = $this->getDirectory($managerType = $container->getParameter('dtc_queue.manager.job'))) {
182 3
                $jobClass = 'Dtc\QueueBundle\\'.$directory.'\Job';
183
            } else {
184 1
                throw new InvalidConfigurationException('Unknown manager.job type '.$managerType.' - please specify a Job class in the \'class\' configuration parameter');
185
            }
186
        }
187
188 3
        $this->testClass($jobClass, Job::class);
189
190 3
        return $jobClass;
191
    }
192
193 4
    protected function getJobTimingManagerType(ContainerBuilder $container)
194
    {
195 4
        $managerType = $this->getRunManagerType($container);
196 4
        if ($container->hasParameter('dtc_queue.manager.job_timing')) {
197 4
            $managerType = 'dtc_queue.manager.job_timing';
198
        }
199
200 4
        return $managerType;
201
    }
202
203
    /**
204
     * @param string $managerType
205
     * @param string $type
206
     * @param string $className
207
     */
208 3
    protected function getClass(ContainerBuilder $container, $managerType, $type, $className, $baseClass)
209
    {
210 3
        $runClass = $container->hasParameter('dtc_queue.class.'.$type) ? $container->getParameter('dtc_queue.class.'.$type) : null;
211 3
        if (!$runClass) {
212 3
            switch ($container->getParameter($managerType)) {
213 3
                case 'odm':
214 3
                    $runClass = 'Dtc\\QueueBundle\\Document\\'.$className;
215 3
                    break;
216 1
                case 'orm':
217 1
                    $runClass = 'Dtc\\QueueBundle\\Entity\\'.$className;
218 1
                    break;
219
                default:
220
                    $runClass = $baseClass;
221
            }
222
        }
223
224 3
        $this->testClass($runClass, $baseClass);
225
226 3
        return $runClass;
227
    }
228
229
    /**
230
     * @throws ClassNotFoundException
231
     * @throws ClassNotSubclassException
232
     */
233 3
    protected function testClass($className, $parent)
234
    {
235 3
        if (!class_exists($className)) {
236
            throw new ClassNotFoundException("Can't find class $className");
237
        }
238
239 3
        $test = new $className();
240 3
        if (!$test instanceof $className) {
241
            throw new ClassNotSubclassException("$className must be instance of (or derived from) $parent");
242
        }
243 3
    }
244
245
    /**
246
     * Determines the job class based on the queue manager type.
247
     *
248
     * @return mixed|string
249
     *
250
     * @throws ClassNotFoundException
251
     * @throws ClassNotSubclassException
252
     */
253 3
    protected function getJobClassArchive(ContainerBuilder $container)
254
    {
255 3
        $jobArchiveClass = $container->getParameter('dtc_queue.class.job_archive');
256 3
        if (!$jobArchiveClass) {
257 3
            switch ($container->getParameter('dtc_queue.manager.job')) {
258 3
                case 'odm':
259 3
                    $jobArchiveClass = 'Dtc\\QueueBundle\\Document\\JobArchive';
260 3
                    break;
261 1
                case 'orm':
262 1
                    $jobArchiveClass = 'Dtc\\QueueBundle\\Entity\\JobArchive';
263 1
                    break;
264
            }
265
        }
266 3
        if (null !== $jobArchiveClass) {
267 3
            $this->testClass($jobArchiveClass, Job::class);
268
        }
269
270 3
        return $jobArchiveClass;
271
    }
272
}
273