Completed
Push — 1.x ( ad94ee...15aa48 )
by Akihito
14s
created

AppInjector::cleanupDir()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.2098

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 10
ccs 5
cts 7
cp 0.7143
rs 9.4285
cc 3
eloc 6
nc 1
nop 1
crap 3.2098
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\Package\Exception\InvalidContextException;
12
use BEAR\Package\Provide\Resource\ResourceObjectModule;
13
use Ray\Compiler\DiCompiler;
14
use Ray\Compiler\Exception\NotCompiled;
15
use Ray\Compiler\ScriptInjector;
16
use Ray\Di\AbstractModule;
17
use Ray\Di\InjectorInterface;
18
use Ray\Di\Name;
19
20
final class AppInjector implements InjectorInterface
21
{
22
    /**
23
     * @var InjectorInterface
24
     */
25
    private $injector;
26
27
    /**
28
     * @var AppMeta
29
     */
30
    private $appMeta;
31
32 8
    public function __construct($name, $contexts)
33
    {
34 8
        $this->appMeta = new AppMeta($name, $contexts);
35 8
        $this->injector = $this->getInjector($this->appMeta, $contexts);
36 6
    }
37
38
    /**
39
     * {@inheritdoc}
40
     */
41 6
    public function getInstance($interface, $name = Name::ANY)
42
    {
43
        try {
44 6
            return $this->injector->getInstance($interface, $name);
45 1
        } catch (NotCompiled $e) {
46 1
            file_put_contents(sprintf('%s/%s', $this->appMeta->logDir, 'compile-err.log'), (string) $e);
47
48 1
            throw $e;
49
        }
50
    }
51
52
    /**
53
     * @param AbstractAppMeta $appMeta
54
     * @param string          $contexts
55
     *
56
     * @return InjectorInterface
57
     */
58 8
    private function getInjector(AbstractAppMeta $appMeta, $contexts)
59
    {
60 8
        $module = $this->newModule($appMeta, $contexts);
61 6
        $module->override(new AppMetaModule($appMeta));
62 6
        $scriptDir = $appMeta->tmpDir;
63 6
        $scriptInjector = new ScriptInjector($scriptDir);
64
        try {
65 6
            $injector = $scriptInjector->getInstance(InjectorInterface::class);
66 4
        } catch (NotCompiled $e) {
67 4
            $this->compile($module, $appMeta, $scriptDir);
0 ignored issues
show
Bug introduced by
It seems like $module defined by $this->newModule($appMeta, $contexts) on line 60 can be null; however, BEAR\Package\AppInjector::compile() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
68 4
            $injector = $scriptInjector->getInstance(InjectorInterface::class);
69
        }
70
71 6
        return $injector;
72
    }
73
74
    /**
75
     * Compile dependencies
76
     *
77
     * @param AbstractModule  $module
78
     * @param AbstractAppMeta $appMeta
79
     * @param string          $contexts
0 ignored issues
show
Bug introduced by
There is no parameter named $contexts. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
Coding Style introduced by
Doc comment for parameter $contexts does not match actual variable name $scriptDir
Loading history...
80
     */
81 4
    private function compile(AbstractModule $module, AbstractAppMeta $appMeta, $scriptDir)
82
    {
83 4
        $hashFile = $appMeta->tmpDir . '/compile_hash';
84 4
        $moduleHash = md5(serialize($module));
85 4
        $isUnchanged = file_exists($hashFile) && (file_get_contents($hashFile) === $moduleHash);
86 4
        if ($isUnchanged) {
87
            return;
88
        }
89 4
        $this->cleanupDir($scriptDir);
90 4
        $compiler = new DiCompiler($module, $scriptDir);
91 4
        $compiler->compile();
92 4
        file_put_contents($hashFile, $moduleHash);
93 4
    }
94
95
    /**
96
     * Return configured module
97
     *
98
     * @param AbstractAppMeta $appMeta
99
     * @param string          $contexts
100
     *
101
     * @return AbstractModule
102
     */
103 8
    private function newModule(AbstractAppMeta $appMeta, $contexts)
104
    {
105 8
        $contextsArray = array_reverse(explode('-', $contexts));
106 8
        $module = null;
107 8
        foreach ($contextsArray as $context) {
108 8
            $class = $appMeta->name . '\Module\\' . ucwords($context) . 'Module';
109 8
            if (! class_exists($class)) {
110 6
                $class = 'BEAR\Package\Context\\' . ucwords($context) . 'Module';
111
            }
112 8
            if (! is_a($class, AbstractModule::class, true)) {
113 2
                throw new InvalidContextException($class);
114
            }
115
            /* @var $module AbstractModule */
116 6
            $module = new $class($module);
117
        }
118 6
        $module->install(new ResourceObjectModule($appMeta));
119
120 6
        return $module;
121
    }
122
123
    /**
124
     * @param string $tmpDir Cleanup directory
125
     */
126
    private function cleanupDir($tmpDir)
127
    {
128 4
        $unlink = function ($path) use (&$unlink) {
129 4
            foreach (glob(rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . '*') as $file) {
130
                is_dir($file) ? $unlink($file) : unlink($file);
131
                @rmdir($file);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
132
            }
133 4
        };
134 4
        $unlink($tmpDir);
135 4
    }
136
}
137