Completed
Pull Request — master (#25)
by yuuki
06:15 queued 03:40
created

RayAspectKernel   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 131
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 17
Bugs 4 Features 2
Metric Value
wmc 14
c 17
b 4
f 2
lcom 1
cbo 8
dl 0
loc 131
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A register() 0 8 2
A dispatch() 0 18 3
A getCompiler() 0 4 1
A makeCompileDir() 0 4 1
A makeCacheableDir() 0 7 2
A makeDirectories() 0 8 2
A resolveContextualBindings() 0 8 2
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
    }
64
65
    /**
66
     * @param null $module
67
     *
68
     * @throws ClassNotFoundException
69
     */
70
    public function register($module = null)
71
    {
72
        if (!class_exists($module)) {
73
            throw new ClassNotFoundException($module);
74
        }
75
        $this->aspectResolver = (new $module($this->app));
76
        $this->aspectResolver->attach();
77
    }
78
79
    /**
80
     * boot aspect kernel
81
     */
82
    public function dispatch()
83
    {
84
        foreach ($this->aspectResolver->getResolver() as $class => $pointcuts) {
85
            $bind = (new AspectBind($this->filesystem, $this->configure['cache_dir'], $this->cacheable))
86
                ->bind($class, $pointcuts);
87
            $compiledClass = $this->compiler->compile($class, $bind);
88
89
            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...
90
                $this->resolveContextualBindings($class, $compiledClass);
91
            }
92
            $this->app->bind($class, function ($app) use ($bind, $compiledClass) {
93
                $instance = $app->make($compiledClass);
94
                $instance->bindings = $bind->getBindings();
95
96
                return $instance;
97
            });
98
        }
99
    }
100
101
    /**
102
     * @return Compiler
103
     */
104
    protected function getCompiler()
105
    {
106
        return new Compiler($this->configure['compile_dir']);
107
    }
108
109
    /**
110
     * make source compile file directory
111
     *
112
     * @return void
113
     */
114
    protected function makeCompileDir()
115
    {
116
        $this->makeDirectories($this->configure['compile_dir'], 0777);
117
    }
118
119
    /**
120
     * make aspect cache directory
121
     *
122
     * @codeCoverageIgnore
123
     * @return void
124
     */
125
    protected function makeCacheableDir()
126
    {
127
        if ($this->configure['cache']) {
128
            $this->makeDirectories($this->configure['cache_dir'], 0777);
129
            $this->cacheable = true;
130
        }
131
    }
132
133
    /**
134
     * @param string $dir
135
     * @param int    $mode
136
     */
137
    private function makeDirectories($dir, $mode = 0777)
138
    {
139
        // @codeCoverageIgnoreStart
140
        if (!$this->filesystem->exists($dir)) {
141
            $this->filesystem->makeDirectory($dir, $mode, true);
142
        }
143
        // @codeCoverageIgnoreEnd
144
    }
145
146
    /**
147
     * @param string $class
148
     * @param string $compiledClass
149
     */
150
    protected function resolveContextualBindings($class, $compiledClass)
151
    {
152
        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...
153
            $this->app->when($compiledClass)
154
                ->needs($abstract)
155
                ->give($concrete);
156
        }
157
    }
158
}
159