Completed
Push — experimental/3.1 ( 3ded70...5f55e6 )
by chihiro
18:23 queued 18:05
created

Di::generateServiceProvider()   C

Complexity

Conditions 11
Paths 17

Size

Total Lines 53
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 30
CRAP Score 11.0295

Importance

Changes 0
Metric Value
cc 11
eloc 31
nc 17
nop 0
dl 0
loc 53
ccs 30
cts 32
cp 0.9375
crap 11.0295
rs 6.2926
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Eccube\Di;
4
5
use Doctrine\Common\Annotations\Reader;
6
use Eccube\Annotation\Inject;
7
use Eccube\Application;
8
use Pimple\Container;
9
use Symfony\Component\Finder\Finder;
10
11
class Di
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
12
{
13
14
    /**
15
     * @var string
16
     */
17
    private $providerDir;
18
19
    /**
20
     * @var string
21
     */
22
    private $providerClass;
23
24
    /**
25
     * @var Scanner[]
26
     */
27
    private $scanners;
28
29
    /**
30
     * @var Reader
31
     */
32
    private $reader;
33
34
    /**
35
     * @var bool
36
     */
37
    private $debug;
38
39
    private static $template = '<?php
40
41
/**
42
 * {{ provider_class }}
43
 *
44
 * This class has been auto-generated by Eccube\Di\ProviderGenerator
45
 */
46
class {{ provider_class }} implements \Pimple\ServiceProviderInterface
47
{
48
    public function register(\Pimple\Container $app)
49
    {
50
{{ snippets|raw }}
51
    }
52
}';
53
54
    /**
55
     * Di constructor.
56
     * @param string $providerDir
0 ignored issues
show
introduced by
Expected 4 spaces after parameter type; 1 found
Loading history...
57
     * @param string $providerClass
0 ignored issues
show
introduced by
Expected 4 spaces after parameter type; 1 found
Loading history...
58
     * @param Scanner[] $scanners
59
     * @param Reader $reader
0 ignored issues
show
introduced by
Expected 4 spaces after parameter type; 1 found
Loading history...
60
     * @param bool $debug
0 ignored issues
show
introduced by
Expected 6 spaces after parameter type; 1 found
Loading history...
61
     */
62 1142
    public function __construct($providerDir, $providerClass, array $scanners, Reader $reader, $debug)
63
    {
64 1142
        $this->providerDir = $providerDir;
65 1142
        $this->providerClass = $providerClass;
66 1142
        $this->scanners = $scanners;
67 1142
        $this->reader = $reader;
68 1142
        $this->debug = $debug;
69
    }
70
71
72 18
    public function isApplication($class)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
73
    {
74 18
        return $class === Application::class;
75
    }
76
77 1142
    public function getProviderPath()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
78
    {
79 1142
        return $this->providerDir.'/'.$this->providerClass.'.php';
80
    }
81
82 1140
    public function build(Container $container)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
83
    {
84 1140
        if ($this->debug || false === file_exists($this->getProviderPath())) {
85 22
            $this->generateServiceProvider();
86
        }
87
88 1140
        $path = $this->getProviderPath();
89 1140
        $class = $this->providerClass;
90
91 1140
        require_once $path;
92
93 1140
        $container->register(new $class());
94
    }
95
96 23
    public function findClasses(array $dirs)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
97
    {
98 23
        $files = Finder::create()
99 23
            ->in($dirs)
100 23
            ->name('*.php')
101 23
            ->files();
102
103 23
        $classes = [];
104 23
        $includedFiles = [];
105 23
        foreach ($files as $file) {
106 23
            $path = $file->getRealPath();
107 23
            require_once $path;
108 23
            $includedFiles[] = $path;
109
        }
110
111 23
        $declared = get_declared_classes();
112
113 23 View Code Duplication
        foreach ($declared as $className) {
114 23
            $rc = new \ReflectionClass($className);
115 23
            $sourceFile = $rc->getFileName();
116 23
            if (in_array($sourceFile, $includedFiles)) {
117 23
                $classes[] = $className;
118
            }
119
        }
120
121 23
        return $classes;
122
    }
123
124 22
    private function generateServiceProvider()
125
    {
126 22
        if (!is_dir($this->providerDir) && !@mkdir($this->providerDir, 0777, true) && !is_dir($this->providerDir)) {
127
            throw new \RuntimeException(
128
                sprintf('ProviderGenerator was not able to create directory "%s"', $this->providerDir)
129
            );
130
        }
131
132 22
        $scanDirs = array_reduce($this->scanners, function($result, Scanner $wiring) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
133 22
            return array_merge($result, $wiring->getScanDirs());
134 22
        }, []);
135
136 22
        $classes = $this->findClasses($scanDirs);
137
138 22
        $twig = new \Twig_Environment(new \Twig_Loader_Array());
139 22
        $twig->addFunction(new \Twig_SimpleFunction('is_app', [$this, 'isApplication']));
140
141 22
        $snippets = '';
142
143 22
        foreach ($this->scanners as $wiring) {
144 22
            $components = [];
145
146 22
            foreach ($classes as $className) {
147 22
                $rc = new \ReflectionClass($className);
148 22
                $anno = $wiring->findAnnotation($this->reader, $rc);
149 22
                if ($anno) {
150 22
                    $component = $components[] = $wiring->createComponentDefinition($anno, $rc);
151
152 22
                    $refProps = $rc->getProperties();
153 22
                    foreach ($refProps as $refProp) {
154 18
                        $anno = $this->reader->getPropertyAnnotation($refProp, Inject::class);
155 18
                        if (is_null($anno)) {
156 15
                            continue;
157
                        }
158 22
                        $component->addDenendency(new Dependency($anno->value, $refProp->getName()));
159
                    }
160
                }
161
            }
162
163 22
            if (!empty($components)) {
164 22
                if ($snippets) $snippets .= PHP_EOL;
165 22
                $snippets .= $wiring->generate($twig, $components);
166 22
                $snippets .= $wiring->generateExtend($twig, $components);
167
            }
168
        }
169
170 22
        $content = $twig->createTemplate(self::$template)->render([
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
171 22
            'provider_class' => $this->providerClass,
172 22
            'snippets' => preg_replace('/^/m', '        ', $snippets)
173
        ]);
174
175 22
        file_put_contents($this->getProviderPath(), $content);
176
    }
177
}
178