Completed
Push — master ( 4bd1d2...9b1cea )
by yuuki
10s
created

RayAspectKernel::dispatch()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 22
rs 8.9197
c 0
b 0
f 0
cc 4
eloc 13
nc 4
nop 0
1
<?php
2
3
/**
4
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
7
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
9
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
10
 * THE SOFTWARE.
11
 *
12
 * This software consists of voluntary contributions made by many individuals
13
 * and is licensed under the MIT license.
14
 *
15
 * Copyright (c) 2015-2016 Yuuki Takezawa
16
 *
17
 */
18
namespace Ytake\LaravelAspect;
19
20
use Ray\Aop\Compiler;
21
use Illuminate\Filesystem\Filesystem;
22
use Illuminate\Contracts\Container\Container;
23
use Ytake\LaravelAspect\Exception\ClassNotFoundException;
24
25
/**
26
 * Class RayAspectKernel
27
 */
28
class RayAspectKernel implements AspectDriverInterface
29
{
30
    /** @var Container */
31
    protected $app;
32
33
    /** @var array */
34
    protected $configure;
35
36
    /** @var Compiler */
37
    protected $compiler;
38
39
    /** @var Filesystem */
40
    protected $filesystem;
41
42
    /** @var bool */
43
    protected $cacheable = false;
44
45
    /** @var \Ytake\LaravelAspect\Modules\AspectModule */
46
    protected $aspectResolver;
47
48
    /**
49
     * RayAspectKernel constructor.
50
     *
51
     * @param Container  $app
52
     * @param Filesystem $filesystem
53
     * @param array      $configure
54
     */
55
    public function __construct(Container $app, Filesystem $filesystem, array $configure)
56
    {
57
        $this->app = $app;
58
        $this->filesystem = $filesystem;
59
        $this->configure = $configure;
60
        $this->makeCompileDir();
61
        $this->makeCacheableDir();
62
        $this->compiler = $this->getCompiler();
63
        $this->registerAspectModule();
64
    }
65
66
    /**
67
     * @param null|string $module
68
     *
69
     * @throws ClassNotFoundException
70
     */
71
    public function register($module = null)
72
    {
73
        if (!class_exists($module)) {
74
            throw new ClassNotFoundException($module);
75
        }
76
        $this->aspectResolver = (new $module($this->app));
77
        $this->aspectResolver->attach();
78
    }
79
80
    /**
81
     * boot aspect kernel
82
     */
83
    public function dispatch()
84
    {
85
        if (is_null($this->aspectResolver)) {
86
            return;
87
        }
88
89
        foreach ($this->aspectResolver->getResolver() as $class => $pointcuts) {
90
            $bind = (new AspectBind($this->filesystem, $this->configure['cache_dir'], $this->cacheable))
91
                ->bind($class, $pointcuts);
92
            $compiledClass = $this->compiler->compile($class, $bind);
93
94
            if (isset($this->app->contextual[$class])) {
0 ignored issues
show
Bug introduced by
Accessing contextual on the interface Illuminate\Contracts\Container\Container suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
95
                $this->resolveContextualBindings($class, $compiledClass);
96
            }
97
            $this->app->bind($class, function ($app) use ($bind, $compiledClass) {
98
                $instance = $app->make($compiledClass);
99
                $instance->bindings = $bind->getBindings();
100
101
                return $instance;
102
            });
103
        }
104
    }
105
106
    /**
107
     * @return Compiler
108
     */
109
    protected function getCompiler()
110
    {
111
        return new Compiler($this->configure['compile_dir']);
112
    }
113
114
    /**
115
     * make source compile file directory
116
     *
117
     * @return void
118
     */
119
    protected function makeCompileDir()
120
    {
121
        $this->makeDirectories($this->configure['compile_dir'], 0777);
122
    }
123
124
    /**
125
     * make aspect cache directory
126
     *
127
     * @codeCoverageIgnore
128
     * @return void
129
     */
130
    protected function makeCacheableDir()
131
    {
132
        if ($this->configure['cache']) {
133
            $this->makeDirectories($this->configure['cache_dir'], 0777);
134
            $this->cacheable = true;
135
        }
136
    }
137
138
    /**
139
     * @param string $dir
140
     * @param int    $mode
141
     */
142
    private function makeDirectories($dir, $mode = 0777)
143
    {
144
        // @codeCoverageIgnoreStart
145
        if (!$this->filesystem->exists($dir)) {
146
            $this->filesystem->makeDirectory($dir, $mode, true);
147
        }
148
        // @codeCoverageIgnoreEnd
149
    }
150
151
    /**
152
     * register Aspect Module
153
     */
154
    protected function registerAspectModule()
155
    {
156
        if (isset($this->configure['modules'])) {
157
            foreach ($this->configure['modules'] as $module) {
158
                $this->register($module);
159
            }
160
        }
161
    }
162
163
    /**
164
     * @param string $class
165
     * @param string $compiledClass
166
     */
167
    protected function resolveContextualBindings($class, $compiledClass)
168
    {
169
        foreach ($this->app->contextual[$class] as $abstract => $concrete) {
0 ignored issues
show
Bug introduced by
Accessing contextual on the interface Illuminate\Contracts\Container\Container suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
170
            $this->app->when($compiledClass)
171
                ->needs($abstract)
172
                ->give($concrete);
173
        }
174
    }
175
}
176