Completed
Push — app ( d2c122...aa71e8 )
by Akihito
05:34
created

Compiler::__invoke()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 22
ccs 12
cts 12
cp 1
rs 9.2
cc 2
eloc 12
nc 2
nop 3
crap 2
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 1
    public function __invoke($appName, $context, $appDir) : string
30
    {
31 1
        $appMeta = new AppMeta($appName, $context, $appDir);
32 1
        $injector = new AppInjector($appName, $context);
33 1
        $cache = $injector->getInstance(Cache::class);
34 1
        $reader = $injector->getInstance(AnnotationReader::class);
35
        /* @var $reader \Doctrine\Common\Annotations\Reader */
36 1
        $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 1
        (new Bootstrap)->newApp($appMeta, $context, $cache);
41
42
        // check resource injection and create annotation cache
43 1
        foreach ($appMeta->getResourceListGenerator() as list($className)) {
44 1
            $this->scanClass($injector, $reader, $namedParams, $className);
45
        }
46 1
        $logFile = $appMeta->logDir . '/compile.log';
47 1
        $this->saveCompileLog($appMeta, $context, $logFile);
48
49 1
        return $logFile;
50
    }
51
52 1
    private function scanClass(InjectorInterface $injector, Reader $reader, NamedParameterInterface $namedParams, string $className)
53
    {
54 1
        $instance = $injector->getInstance($className);
55 1
        $class = new \ReflectionClass($className);
56 1
        $reader->getClassAnnotations($class);
57 1
        $methods = $class->getMethods();
58 1
        foreach ($methods as $method) {
59 1
            $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 1
            if ($this->isMagicMethod($methodName)) {
61 1
                continue;
62
            }
63 1
            $this->saveNamedParam($namedParams, $instance, $methodName);
64
            // method annotation
65 1
            $reader->getMethodAnnotations($method);
66
        }
67 1
    }
68
69 1
    private function isMagicMethod($method) : bool
70
    {
71 1
        return \in_array($method, ['__sleep', '__wakeup', 'offsetGet', 'offsetSet', 'offsetExists', 'offsetUnset', 'count', 'ksort', 'asort', 'jsonSerialize'], true);
72
    }
73
74 1
    private function saveNamedParam(NamedParameterInterface $namedParameter, $instance, string $method)
75
    {
76
        // named parameter
77 1
        if (! \in_array($method, ['onGet', 'onPost', 'onPut', 'onPatch', 'onDelete', 'onHead'], true)) {
78 1
            return;
79
        }
80
        try {
81 1
            $namedParameter->getParameters([$instance, $method], []);
82 1
        } catch (ParameterException $e) {
83 1
            return;
84
        }
85 1
    }
86
87 1
    private function saveCompileLog(AbstractAppMeta $appMeta, string $context, string $logFile)
88
    {
89 1
        $module = (new Module)($appMeta, $context);
90
        /** @var AbstractModule $module */
91 1
        $container = $module->getContainer();
92 1
        foreach ($appMeta->getResourceListGenerator() as list($class)) {
93 1
            new Bind($container, $class);
94
        }
95 1
        file_put_contents($logFile, (string) $module);
96 1
    }
97
}
98