Completed
Push — app ( d2c122 )
by Akihito
02:39
created

Compiler::scanClass()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 16
ccs 0
cts 12
cp 0
rs 9.4285
cc 3
eloc 11
nc 3
nop 4
crap 12
1
<?php
2
/**
3
 * This file is part of the BEAR.Package package.
4
 *
5
 * @license http://opensource.org/licenses/MIT MIT
6
 */
7
namespace BEAR\Package;
8
9
use BEAR\AppMeta\AbstractAppMeta;
10
use BEAR\AppMeta\AppMeta;
11
use BEAR\Resource\Exception\ParameterException;
12
use BEAR\Resource\NamedParameterInterface;
13
use Doctrine\Common\Annotations\AnnotationReader;
14
use Doctrine\Common\Annotations\Reader;
15
use Doctrine\Common\Cache\Cache;
16
use Ray\Di\AbstractModule;
17
use Ray\Di\Bind;
18
use Ray\Di\InjectorInterface;
19
20
final class Compiler
21
{
22
    /**
23
     * Compile application
24
     *
25
     * @param string $appName application name "MyVendor|MyProject"
26
     * @param string $context application context "prod-app"
27
     * @param string $appDir  application path
28
     */
29
    public function __invoke($appName, $context, $appDir) : string
30
    {
31
        $appMeta = new AppMeta($appName, $context, $appDir);
32
        $injector = new AppInjector($appName, $context);
33
        $cache = $injector->getInstance(Cache::class);
34
        $reader = $injector->getInstance(AnnotationReader::class);
35
        /* @var $reader \Doctrine\Common\Annotations\Reader */
36
        $namedParams = $injector->getInstance(NamedParameterInterface::class);
37
        /* @var $namedParams NamedParameterInterface */
38
39
        // create DI factory class and AOP compiled class for all resources and save $app cache.
40
        (new Bootstrap)->newApp($appMeta, $context, $cache);
41
42
        // check resource injection and create annotation cache
43
        foreach ($appMeta->getResourceListGenerator() as list($className)) {
44
            $this->scanClass($injector, $reader, $namedParams, $className);
45
        }
46
        $logFile = $appMeta->logDir . '/compile.log';
47
        $this->saveCompileLog($appMeta, $context, $logFile);
48
49
        return $logFile;
50
    }
51
52
    private function scanClass(InjectorInterface $injector, Reader $reader, NamedParameterInterface $namedParams, string $className)
53
    {
54
        $instance = $injector->getInstance($className);
55
        $class = new \ReflectionClass($className);
56
        $reader->getClassAnnotations($class);
57
        $methods = $class->getMethods();
58
        foreach ($methods as $method) {
59
            $methodName = $method->getName();
0 ignored issues
show
Bug introduced by
Consider using $method->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
60
            if ($this->isMagicMethod($methodName)) {
61
                continue;
62
            }
63
            $this->saveNamedParam($namedParams, $instance, $methodName);
64
            // method annotation
65
            $reader->getMethodAnnotations($method);
66
        }
67
    }
68
69
    private function isMagicMethod($method) : bool
70
    {
71
        return \in_array($method, ['__sleep', '__wakeup', 'offsetGet', 'offsetSet', 'offsetExists', 'offsetUnset', 'count', 'ksort', 'asort', 'jsonSerialize'], true);
72
    }
73
74
    private function saveNamedParam(NamedParameterInterface $namedParameter, $instance, string $method)
75
    {
76
        // named parameter
77
        if (! \in_array($method, ['onGet', 'onPost', 'onPut', 'onPatch', 'onDelete', 'onHead'], true)) {
78
            return;
79
        }
80
        try {
81
            $namedParameter->getParameters([$instance, $method], []);
82
        } catch (ParameterException $e) {
83
            return;
84
        }
85
    }
86
87
    private function saveCompileLog(AbstractAppMeta $appMeta, string $context, string $logFile)
88
    {
89
        $module = (new Module)($appMeta, $context);
90
        /** @var AbstractModule $module */
91
        $container = $module->getContainer();
92
        foreach ($appMeta->getResourceListGenerator() as list($class)) {
93
            new Bind($container, $class);
94
        }
95
        file_put_contents($logFile, (string) $module);
96
    }
97
}
98