Completed
Push — master ( 6e2d34...04fc36 )
by Alejandro
02:07
created

AbstractAnnotatedFactory::createAnnotationReader()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 25
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 4

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 25
ccs 15
cts 15
cp 1
rs 8.5806
cc 4
eloc 15
nc 3
nop 1
crap 4
1
<?php
2
namespace Acelaya\ZsmAnnotatedServices\Factory;
3
4
use Acelaya\ZsmAnnotatedServices\Annotation\Inject;
5
use Acelaya\ZsmAnnotatedServices\Exception\RuntimeException;
6
use Doctrine\Common\Annotations\AnnotationReader;
7
use Doctrine\Common\Annotations\AnnotationRegistry;
8
use Doctrine\Common\Annotations\CachedReader;
9
use Doctrine\Common\Cache\Cache;
10
use Zend\ServiceManager\ServiceLocatorInterface;
11
12
abstract class AbstractAnnotatedFactory
13
{
14
    const CACHE_SERVICE = 'Acelaya\ZsmAnnotatedServices\Cache';
15
16
    /**
17
     * @var AnnotationReader
18
     */
19
    private static $annotationReader;
20
21 8
    protected function processDependenciesFromAnnotations(ServiceLocatorInterface $container, $serviceName)
22
    {
23 8
        if (! class_exists($serviceName)) {
24 1
            throw new RuntimeException(sprintf(
25
                'Annotated factories can only be used with services that are identified by their FQCN. ' .
26 1
                'Provided "%s" service name is not a valid class.',
27
                $serviceName
28
            ));
29
        }
30
31 7
        $annotationReader = $this->createAnnotationReader($container);
32 7
        $refClass = new \ReflectionClass($serviceName);
33 7
        $constructor = $refClass->getConstructor();
34 7
        if (! isset($constructor)) {
35 1
            return new $serviceName();
36
        }
37
38
        /** @var Inject $inject */
39 6
        $inject = $annotationReader->getMethodAnnotation($constructor, Inject::class);
40 6
        if (! isset($inject)) {
41 1
            throw new RuntimeException(sprintf(
42
                'You need to use the "%s" annotation in your services constructors so that he "%s" factory can ' .
43 1
                'create them.',
44 1
                static::class,
45 1
                Inject::class
46
            ));
47
        }
48
49 5
        $services = [];
50 5
        foreach ($inject->getServices() as $serviceKey) {
51 5
            if (! $container->has($serviceKey)) {
52 1
                throw new RuntimeException(sprintf(
53 1
                    'Defined injectable service "%s" could not be found in container.',
54
                    $serviceKey
55
                ));
56
            }
57
58 4
            $services[] = $container->get($serviceKey);
59
        }
60
61
        // TODO use array unpacking instead of reflection when dropping PHP 5.5 support
62
        // return new $serviceName(...$services);
1 ignored issue
show
Unused Code Comprehensibility introduced by
73% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
63 4
        return $refClass->newInstanceArgs($services);
64
    }
65
66
    /**
67
     * @param ServiceLocatorInterface $container
68
     * @return AnnotationReader|CachedReader
69
     */
70 7
    private function createAnnotationReader(ServiceLocatorInterface $container)
71
    {
72 7
        if (isset(self::$annotationReader)) {
73 5
            return self::$annotationReader;
74
        }
75
76 2
        AnnotationRegistry::registerLoader(function ($class) {
77 2
            $file = str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
78 2
            $file = realpath(__DIR__ . '/../Annotation/' . basename($file));
79 2
            if (! $file) {
80 2
                return false;
81
            }
82
83 1
            require_once $file;
84 1
            return true;
85 2
        });
86
87 2
        if (! $container->has(self::CACHE_SERVICE)) {
88 1
            return self::$annotationReader = new AnnotationReader();
89
        } else {
90
            /** @var Cache $cache */
91 1
            $cache = $container->get(self::CACHE_SERVICE);
92 1
            return self::$annotationReader = new CachedReader(new AnnotationReader(), $cache);
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Doctrine\Common\Ann...tationReader(), $cache) of type object<Doctrine\Common\Annotations\CachedReader> is incompatible with the declared type object<Doctrine\Common\A...tions\AnnotationReader> of property $annotationReader.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
93
        }
94
    }
95
}
96