Passed
Push — master ( 48455b...7b662e )
by Hannes
03:55 queued 02:10
created

CompilerFacade::compileProject()   B

Complexity

Conditions 9
Paths 64

Size

Total Lines 59
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 27
nc 64
nop 2
dl 0
loc 59
rs 8.0555
c 0
b 0
f 0

How to fix   Long Method   

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
        'route-factory' => Doctrine\RouteFactory::CLASS,
22
        'compiler' => Compiler::CLASS,
23
        'core-compiler-passes' => [
24
            Dsl\RouteCompilerPass::CLASS,
25
            Dsl\BasePathCompilerPass::CLASS,
26
            Dsl\PipeCompilerPass::CLASS,
27
        ],
28
        'compiler-passes' => [],
29
        'code-generator' => Aura\CodeGenerator::CLASS,
30
        'target-namespace' => '',
31
        'target-classname' => 'HttpRouter',
32
    ];
33
34
    public function compileProject(SettingsInterface $settings, RouteCollectionInterface &$routes = null): string
35
    {
36
        $settings = new ManagedSettings($settings, new ArraySettings(self::DEFAULT_SETTINGS));
37
38
        $container = new NaiveContainer;
39
40
        if ($settings->hasSetting('container')) {
41
            /** @var ContainerInterface */
42
            $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...
43
        }
44
45
        if ($container->has($settings->getSetting('bootstrap'))) {
46
            /** @var BootstrapInterface */
47
            $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...
48
            $bootstrap->bootstrap($settings);
49
        }
50
51
        /** @var RouteFactoryInterface */
52
        $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...
53
54
        /** @var RouteCollectionInterface[] */
55
        $collections = [];
56
57
        foreach ((array)$settings->getSetting('source-classes') as $classname) {
58
            $collections[] = $routeFactory->createRoutesFrom($classname);
59
        }
60
61
        if ($settings->getSetting('source-dir')) {
62
            $classFinder = new Psr4ClassFinder(
63
                $settings->getSetting('source-dir'),
64
                $settings->getSetting('source-prefix')
65
            );
66
67
            foreach ($classFinder as $classname) {
68
                $collections[] = $routeFactory->createRoutesFrom((string)$classname);
69
            }
70
        }
71
72
        /** @var CompilerInterface */
73
        $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...
74
75
        foreach (['core-compiler-passes', 'compiler-passes'] as $settingName) {
76
            foreach ((array)$settings->getSetting($settingName) as $serviceName) {
77
                $compilerPass = $container->get($serviceName);
78
79
                if (!$compilerPass instanceof CompilerPassInterface) {
80
                    throw new CompilerException("Service '$serviceName' must implement CompilerPassInterface");
81
                }
82
83
                $compiler->addCompilerPass($compilerPass);
84
            }
85
        }
86
87
        $routes = $compiler->compile(...$collections);
88
89
        /** @var CodeGeneratorInterface */
90
        $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...
91
92
        return $generator->generateRouterCode($settings, $routes);
93
    }
94
95
    private function build(
96
        string $setting,
97
        string $requiredClass,
98
        ContainerInterface $container,
99
        SettingsInterface $settings
100
    ) {
101
        $obj = $container->get($settings->getSetting($setting));
102
103
        if (!$obj instanceof $requiredClass) {
104
            throw new CompilerException(
105
                "Service '{$settings->getSetting($setting)}' must implement $requiredClass"
106
            );
107
        }
108
109
        return $obj;
110
    }
111
}
112