CompilerFacade::compileProject()   B
last analyzed

Complexity

Conditions 10
Paths 128

Size

Total Lines 63
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 10
eloc 29
c 3
b 0
f 0
nc 128
nop 2
dl 0
loc 63
rs 7.4333

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
declare(strict_types = 1);
4
5
namespace inroutephp\inroute\Compiler;
6
7
use inroutephp\inroute\Compiler\Settings\ArraySettings;
8
use inroutephp\inroute\Compiler\Settings\ManagedSettings;
9
use inroutephp\inroute\Compiler\Settings\SettingsInterface;
10
use inroutephp\inroute\Compiler\Exception\CompilerException;
11
use inroutephp\inroute\Runtime\NaiveContainer;
12
use Psr\Container\ContainerInterface;
13
14
final class CompilerFacade
15
{
16
    private const DEFAULT_SETTINGS = [
17
        'bootstrap' => Doctrine\Bootstrap::CLASS,
18
        'source-dir' => '',
19
        'source-prefix' => '',
20
        'source-classes' => [],
21
        'ignore-annotations' => [],
22
        'route-factory' => Doctrine\RouteFactory::CLASS,
23
        'compiler' => Compiler::CLASS,
24
        'core-compiler-passes' => [
25
            Dsl\RouteCompilerPass::CLASS,
26
            Dsl\BasePathCompilerPass::CLASS,
27
            Dsl\PipeCompilerPass::CLASS,
28
        ],
29
        'compiler-passes' => [],
30
        'code-generator' => Aura\CodeGenerator::CLASS,
31
        'target-namespace' => '',
32
        'target-classname' => 'HttpRouter',
33
    ];
34
35
    public function compileProject(SettingsInterface $settings, RouteCollectionInterface &$routes = null): string
36
    {
37
        $settings = new ManagedSettings($settings, new ArraySettings(self::DEFAULT_SETTINGS));
38
39
        foreach ((array)$settings->getSetting('ignore-annotations') as $annotation) {
40
            \Doctrine\Common\Annotations\AnnotationReader::addGlobalIgnoredName((string)$annotation);
41
        }
42
43
        $container = new NaiveContainer;
44
45
        if ($settings->hasSetting('container')) {
46
            /** @var ContainerInterface */
47
            $container = $this->build('container', ContainerInterface::CLASS, $container, $settings);
0 ignored issues
show
Bug introduced by
The constant Psr\Container\ContainerInterface::CLASS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
48
        }
49
50
        if ($container->has($settings->getSetting('bootstrap'))) {
51
            /** @var BootstrapInterface */
52
            $bootstrap = $this->build('bootstrap', BootstrapInterface::CLASS, $container, $settings);
0 ignored issues
show
Bug introduced by
The constant inroutephp\inroute\Compi...otstrapInterface::CLASS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
53
            $bootstrap->bootstrap($settings);
54
        }
55
56
        /** @var RouteFactoryInterface */
57
        $routeFactory = $this->build('route-factory', RouteFactoryInterface::CLASS, $container, $settings);
0 ignored issues
show
Bug introduced by
The constant inroutephp\inroute\Compi...FactoryInterface::CLASS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
58
59
        /** @var RouteCollectionInterface[] */
60
        $collections = [];
61
62
        foreach ((array)$settings->getSetting('source-classes') as $classname) {
63
            $collections[] = $routeFactory->createRoutesFrom($classname);
64
        }
65
66
        if ($settings->getSetting('source-dir')) {
67
            $classFinder = new Psr4ClassFinder(
68
                $settings->getSetting('source-dir'),
69
                $settings->getSetting('source-prefix')
70
            );
71
72
            foreach ($classFinder as $classname) {
73
                $collections[] = $routeFactory->createRoutesFrom((string)$classname);
74
            }
75
        }
76
77
        /** @var CompilerInterface */
78
        $compiler = $this->build('compiler', CompilerInterface::CLASS, $container, $settings);
0 ignored issues
show
Bug introduced by
The constant inroutephp\inroute\Compi...ompilerInterface::CLASS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
79
80
        foreach (['core-compiler-passes', 'compiler-passes'] as $settingName) {
81
            foreach ((array)$settings->getSetting($settingName) as $serviceName) {
82
                $compilerPass = $container->get($serviceName);
83
84
                if (!$compilerPass instanceof CompilerPassInterface) {
85
                    throw new CompilerException("Service '$serviceName' must implement CompilerPassInterface");
86
                }
87
88
                $compiler->addCompilerPass($compilerPass);
89
            }
90
        }
91
92
        $routes = $compiler->compile(...$collections);
93
94
        /** @var CodeGeneratorInterface */
95
        $generator = $this->build('code-generator', CodeGeneratorInterface::CLASS, $container, $settings);
0 ignored issues
show
Bug introduced by
The constant inroutephp\inroute\Compi...neratorInterface::CLASS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
96
97
        return $generator->generateRouterCode($settings, $routes);
98
    }
99
100
    private function build(
101
        string $setting,
102
        string $requiredClass,
103
        ContainerInterface $container,
104
        SettingsInterface $settings
105
    ): object {
106
        $obj = $container->get($settings->getSetting($setting));
107
108
        if (!$obj instanceof $requiredClass) {
109
            throw new CompilerException(
110
                "Service '{$settings->getSetting($setting)}' must implement $requiredClass"
111
            );
112
        }
113
114
        return $obj;
115
    }
116
}
117