1 | <?php |
||
29 | abstract class AspectKernel |
||
30 | { |
||
31 | |||
32 | /** |
||
33 | * Version of kernel |
||
34 | */ |
||
35 | const VERSION = '2.1.0'; |
||
36 | |||
37 | /** |
||
38 | * Kernel options |
||
39 | * |
||
40 | * @var array |
||
41 | */ |
||
42 | protected $options = [ |
||
43 | 'features' => 0 |
||
44 | ]; |
||
45 | |||
46 | /** |
||
47 | * Single instance of kernel |
||
48 | * |
||
49 | * @var static |
||
50 | */ |
||
51 | protected static $instance; |
||
52 | |||
53 | /** |
||
54 | * Default class name for container, can be redefined in children |
||
55 | * |
||
56 | * @var string |
||
57 | */ |
||
58 | protected static $containerClass = GoAspectContainer::class; |
||
59 | |||
60 | /** |
||
61 | * Flag to determine if kernel was already initialized or not |
||
62 | * |
||
63 | * @var bool |
||
64 | */ |
||
65 | protected $wasInitialized = false; |
||
66 | |||
67 | /** |
||
68 | * Aspect container instance |
||
69 | * |
||
70 | * @var AspectContainer |
||
71 | */ |
||
72 | protected $container; |
||
73 | |||
74 | /** |
||
75 | * Protected constructor is used to prevent direct creation, but allows customization if needed |
||
76 | */ |
||
77 | protected function __construct() {} |
||
78 | |||
79 | /** |
||
80 | * Returns the single instance of kernel |
||
81 | */ |
||
82 | 1 | public static function getInstance(): self |
|
83 | { |
||
84 | 1 | if (!self::$instance) { |
|
85 | 1 | self::$instance = new static(); |
|
86 | } |
||
87 | |||
88 | 1 | return self::$instance; |
|
89 | } |
||
90 | |||
91 | /** |
||
92 | * Init the kernel and make adjustments |
||
93 | * |
||
94 | * @param array $options Associative array of options for kernel |
||
95 | */ |
||
96 | 1 | public function init(array $options = []) |
|
97 | { |
||
98 | 1 | if ($this->wasInitialized) { |
|
99 | return; |
||
100 | } |
||
101 | |||
102 | 1 | $this->options = $this->normalizeOptions($options); |
|
103 | 1 | define('AOP_ROOT_DIR', $this->options['appDir']); |
|
104 | 1 | define('AOP_CACHE_DIR', $this->options['cacheDir']); |
|
105 | |||
106 | /** @var $container AspectContainer */ |
||
107 | 1 | $container = $this->container = new $this->options['containerClass']; |
|
108 | 1 | $container->set('kernel', $this); |
|
109 | 1 | $container->set('kernel.interceptFunctions', $this->hasFeature(Features::INTERCEPT_FUNCTIONS)); |
|
110 | 1 | $container->set('kernel.options', $this->options); |
|
111 | |||
112 | 1 | SourceTransformingLoader::register(); |
|
113 | |||
114 | 1 | foreach ($this->registerTransformers() as $sourceTransformer) { |
|
115 | 1 | SourceTransformingLoader::addTransformer($sourceTransformer); |
|
116 | } |
||
117 | |||
118 | // Register kernel resources in the container for debug mode |
||
119 | 1 | if ($this->options['debug']) { |
|
120 | 1 | $this->addKernelResourcesToContainer($container); |
|
121 | } |
||
122 | |||
123 | 1 | AopComposerLoader::init($this->options, $container); |
|
124 | |||
125 | // Register all AOP configuration in the container |
||
126 | 1 | $this->configureAop($container); |
|
127 | |||
128 | 1 | $this->wasInitialized = true; |
|
129 | 1 | } |
|
130 | |||
131 | /** |
||
132 | * Returns an aspect container |
||
133 | */ |
||
134 | 1 | public function getContainer(): AspectContainer |
|
135 | { |
||
136 | 1 | return $this->container; |
|
137 | } |
||
138 | |||
139 | /** |
||
140 | * Checks if kernel configuration has enabled specific feature |
||
141 | * |
||
142 | * @see \Go\Aop\Features enumeration class for features |
||
143 | */ |
||
144 | 1 | public function hasFeature(int $featureToCheck): bool |
|
145 | { |
||
146 | 1 | return ($this->options['features'] & $featureToCheck) !== 0; |
|
147 | } |
||
148 | |||
149 | /** |
||
150 | * Returns list of kernel options |
||
151 | */ |
||
152 | 1 | public function getOptions(): array |
|
153 | { |
||
154 | 1 | return $this->options; |
|
155 | } |
||
156 | |||
157 | /** |
||
158 | * Returns default options for kernel. Available options: |
||
159 | * |
||
160 | * debug - boolean Determines whether or not kernel is in debug mode |
||
161 | * appDir - string Path to the application root directory. |
||
162 | * cacheDir - string Path to the cache directory where compiled classes will be stored |
||
163 | * cacheFileMode - integer Binary mask of permission bits that is set to cache files |
||
164 | * annotationCache - Doctrine\Common\Cache\Cache. If not provided, Doctrine\Common\Cache\PhpFileCache is used. |
||
165 | * features - integer Binary mask of features |
||
166 | * includePaths - array Whitelist of directories where aspects should be applied. Empty for everywhere. |
||
167 | * excludePaths - array Blacklist of directories or files where aspects shouldn't be applied. |
||
168 | */ |
||
169 | 1 | protected function getDefaultOptions(): array |
|
170 | { |
||
171 | return [ |
||
172 | 1 | 'debug' => false, |
|
173 | 'appDir' => __DIR__ . '/../../../../../', |
||
174 | 'cacheDir' => null, |
||
175 | 1 | 'cacheFileMode' => 0770 & ~umask(), // Respect user umask() policy |
|
176 | 1 | 'features' => 0, |
|
177 | 'annotationCache' => null, |
||
178 | 'includePaths' => [], |
||
179 | 'excludePaths' => [], |
||
180 | 1 | 'containerClass' => static::$containerClass, |
|
181 | ]; |
||
182 | } |
||
183 | |||
184 | |||
185 | /** |
||
186 | * Normalizes options for the kernel |
||
187 | * |
||
188 | * @param array $options List of options |
||
189 | */ |
||
190 | 1 | protected function normalizeOptions(array $options): array |
|
191 | { |
||
192 | 1 | $options = array_replace($this->getDefaultOptions(), $options); |
|
193 | |||
194 | 1 | $options['cacheDir'] = PathResolver::realpath($options['cacheDir']); |
|
195 | |||
196 | 1 | if (!$options['cacheDir']) { |
|
197 | throw new \RuntimeException('You need to provide valid cache directory for Go! AOP framework.'); |
||
198 | } |
||
199 | |||
200 | 1 | $options['excludePaths'][] = $options['cacheDir']; |
|
201 | 1 | $options['excludePaths'][] = __DIR__ . '/../'; |
|
202 | 1 | $options['appDir'] = PathResolver::realpath($options['appDir']); |
|
203 | 1 | $options['cacheFileMode'] = (int) $options['cacheFileMode']; |
|
204 | 1 | $options['includePaths'] = PathResolver::realpath($options['includePaths']); |
|
205 | 1 | $options['excludePaths'] = PathResolver::realpath($options['excludePaths']); |
|
206 | |||
207 | 1 | return $options; |
|
208 | } |
||
209 | |||
210 | /** |
||
211 | * Configures an AspectContainer with advisors, aspects and pointcuts |
||
212 | */ |
||
213 | abstract protected function configureAop(AspectContainer $container); |
||
214 | |||
215 | /** |
||
216 | * Returns list of source transformers, that will be applied to the PHP source |
||
217 | * |
||
218 | * @return SourceTransformer[] |
||
219 | * @internal This method is internal and should not be used outside this project |
||
220 | */ |
||
221 | 1 | protected function registerTransformers(): array |
|
222 | { |
||
251 | |||
252 | /** |
||
253 | * Add resources of kernel to the container |
||
254 | */ |
||
255 | 1 | protected function addKernelResourcesToContainer(AspectContainer $container): void |
|
263 | } |
||
264 |