Completed
Push — master ( 63073a...1fb20e )
by yuuki
14s
created

RayAspectKernel::weave()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
c 0
b 0
f 0
rs 9.0534
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
use Ytake\LaravelAspect\Modules\AspectModule;
25
26
/**
27
 * Class RayAspectKernel
28
 */
29
class RayAspectKernel implements AspectDriverInterface
30
{
31
    /** @var Container|\Illuminate\Container\Container */
32
    protected $app;
33
34
    /** @var array */
35
    protected $configure;
36
37
    /** @var Compiler */
38
    protected $compiler;
39
40
    /** @var Filesystem */
41
    protected $filesystem;
42
43
    /** @var bool */
44
    protected $cacheable = false;
45
46
    /** @var AspectModule */
47
    protected $aspectResolver;
48
49
    /** @var AspectModule[] */
50
    protected $registerModules = [];
51
52
    /**
53
     * RayAspectKernel constructor.
54
     *
55
     * @param Container  $app
56
     * @param Filesystem $filesystem
57
     * @param array      $configure
58
     */
59
    public function __construct(Container $app, Filesystem $filesystem, array $configure)
60
    {
61
        $this->app = $app;
62
        $this->filesystem = $filesystem;
63
        $this->configure = $configure;
64
        $this->makeCompileDir();
65
        $this->makeCacheableDir();
66
        $this->compiler = $this->getCompiler();
67
        $this->registerAspectModule();
68
    }
69
70
    /**
71
     * @param null|string $module
72
     *
73
     * @throws ClassNotFoundException
74
     */
75
    public function register($module = null)
76
    {
77
        if (!class_exists($module)) {
78
            throw new ClassNotFoundException($module);
79
        }
80
        $this->aspectResolver = (new $module($this->app));
81
        $this->aspectResolver->attach();
82
    }
83
84
    /**
85
     * weaving
86
     */
87
    public function weave()
88
    {
89
        if (is_null($this->aspectResolver)) {
90
            return;
91
        }
92
        foreach ($this->aspectResolver->getResolver() as $class => $pointcuts) {
93
            $bind = (new AspectBind($this->filesystem, $this->configure['cache_dir'], $this->cacheable))
94
                ->bind($class, $pointcuts);
95
            $compiledClass = $this->compiler->compile($class, $bind);
96
97
            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...
98
                $this->resolveContextualBindings($class, $compiledClass);
99
            }
100
            $this->app->bind($class, function (Container $app) use ($bind, $compiledClass) {
101
                $instance = $app->make($compiledClass);
102
                $instance->bindings = $bind->getBindings();
103
104
                return $instance;
105
            });
106
        }
107
    }
108
109
    /**
110
     * @deprecated
111
     * boot aspect kernel
112
     */
113
    public function dispatch()
114
    {
115
        $this->weave();
116
    }
117
118
    /**
119
     * @return Compiler
120
     */
121
    protected function getCompiler()
122
    {
123
        return new Compiler($this->configure['compile_dir']);
124
    }
125
126
    /**
127
     * make source compile file directory
128
     *
129
     * @return void
130
     */
131
    protected function makeCompileDir()
132
    {
133
        $this->makeDirectories($this->configure['compile_dir'], 0777);
134
    }
135
136
    /**
137
     * make aspect cache directory
138
     *
139
     * @codeCoverageIgnore
140
     * @return void
141
     */
142
    protected function makeCacheableDir()
143
    {
144
        if ($this->configure['cache']) {
145
            $this->makeDirectories($this->configure['cache_dir'], 0777);
146
            $this->cacheable = true;
147
        }
148
    }
149
150
    /**
151
     * @param string $dir
152
     * @param int    $mode
153
     */
154
    private function makeDirectories($dir, $mode = 0777)
155
    {
156
        // @codeCoverageIgnoreStart
157
        if (!$this->filesystem->exists($dir)) {
158
            $this->filesystem->makeDirectory($dir, $mode, true);
159
        }
160
        // @codeCoverageIgnoreEnd
161
    }
162
163
    /**
164
     * register Aspect Module
165
     */
166
    protected function registerAspectModule()
167
    {
168
        if (isset($this->configure['modules'])) {
169
            foreach ($this->configure['modules'] as $module) {
170
                $this->register($module);
171
            }
172
        }
173
    }
174
175
    /**
176
     * @param string $class
177
     * @param string $compiledClass
178
     */
179
    protected function resolveContextualBindings($class, $compiledClass)
180
    {
181
        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...
182
            $this->app->when($compiledClass)
183
                ->needs($abstract)
184
                ->give($concrete);
185
        }
186
    }
187
}
188