Passed
Push — master ( 39c189...908039 )
by Jean-Christophe
11:37
created

Preloader::addClass()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 7
c 2
b 0
f 0
dl 0
loc 11
ccs 0
cts 11
cp 0
rs 10
cc 4
nc 4
nop 1
crap 20
1
<?php
2
3
namespace Ubiquity\cache;
4
5
use Ubiquity\cache\preloading\PreloaderInternalTrait;
6
7
/**
8
 * Ubiquity\cache$Preloader
9
 * This class is part of Ubiquity
10
 *
11
 * @author jcheron <[email protected]>
12
 * @version 1.0.1
13
 *
14
 */
15
class Preloader {
16
	use PreloaderInternalTrait;
17
18
	/**
19
	 * Creates a new loader instance for this application.
20
	 *
21
	 * @param string $appRoot The app root
22
	 */
23
	public function __construct($appRoot) {
24
		$this->vendorDir = $appRoot . './../vendor/';
25
		$this->loader = require $this->vendorDir . 'autoload.php';
26
	}
27
28
	/**
29
	 * Adds paths to be scanned during preloading.
30
	 *
31
	 * @param string ...$paths
32
	 * @return Preloader
33
	 */
34
	public function paths(string ...$paths): Preloader {
35
		foreach ( $paths as $path ) {
36
			$this->addDir ( $path );
37
		}
38
		return $this;
39
	}
40
41
	/**
42
	 * Adds namespaces to exclude from preloading.
43
	 *
44
	 * @param string ...$names
45
	 * @return Preloader
46
	 */
47
	public function exclude(string ...$names): Preloader {
48
		$this->excludeds = \array_merge ( $this->excludeds, $names );
49
		return $this;
50
	}
51
52
	/**
53
	 * Adds a class to preload.
54
	 *
55
	 * @param string $class
56
	 * @return bool
57
	 */
58
	public function addClass(string $class): bool {
59
		if (! $this->isExcluded ( $class )) {
60
			if (! isset ( $this->classes [$class] )) {
61
				$path = $this->getPathFromClass ( $class );
62
				if (isset ( $path )) {
63
					$this->classes [$class] = $path;
64
					return true;
65
				}
66
			}
67
		}
68
		return false;
69
	}
70
71
	/**
72
	 * Adds an array of classes to preload.
73
	 *
74
	 * @param array $classes
75
	 */
76
	public function addClasses(array $classes) {
77
		foreach ( $classes as $class ) {
78
			$this->addClass ( $class );
79
		}
80
	}
81
82
	/**
83
	 * Preload all added classes.
84
	 */
85
	public function load() {
86
		foreach ( $this->classes as $class => $file ) {
87
			if (! $this->isExcluded ( $class )) {
88
				$this->loadClass ( $class, $file );
89
			}
90
		}
91
	}
92
93
	/**
94
	 * Returns a generated associative array of classes to preload (key: class, value: file).
95
	 *
96
	 * @return array
97
	 */
98
	public function generateClassesFiles(): array {
99
		$ret = [ ];
100
		foreach ( $this->classes as $class => $file ) {
101
			if (! $this->isExcluded ( $class )) {
102
				$ret [$class] = \realpath ( $file );
103
			}
104
		}
105
		return $ret;
106
	}
107
108
	/**
109
	 * Generate a file containing the associative array of classes to preload (classes-files=>[key: class, value: file}).
110
	 *
111
	 * @param string $filename
112
	 * @param ?bool $preserve
113
	 * @return int
114
	 */
115
	public function generateToFile(string $filename, ?bool $preserve = true): int {
116
		$array = [ ];
117
		if ($preserve && \file_exists ( $filename )) {
118
			$array = include $filename;
119
		}
120
		$array ['classes-files'] = $this->generateClassesFiles ();
121
		$content = "<?php\nreturn " . $this->asPhpArray ( $array, 'array', 1, true ) . ";";
122
		return \file_put_contents ( $filename, $content );
123
	}
124
125
	/**
126
	 * Adds a directory to be scanned during preloading.
127
	 *
128
	 * @param string $dirname
129
	 * @return \Ubiquity\cache\Preloader
130
	 */
131
	public function addDir(string $dirname): Preloader {
132
		$files = $this->glob_recursive ( $dirname . DIRECTORY_SEPARATOR . '*.php' );
133
		foreach ( $files as $file ) {
134
			$class = $this->getClassFullNameFromFile ( $file );
135
			if (isset ( $class )) {
136
				$this->addClassFile ( $class, $file );
137
			}
138
		}
139
		return $this;
140
	}
141
142
	/**
143
	 * Adds a part of an existing library to be preloaded.
144
	 * The available libraries can be obtained with the getLibraries method.
145
	 *
146
	 * @param string $library
147
	 * @param ?string $part
148
	 * @return bool
149
	 */
150
	public function addLibraryPart(string $library, ?string $part = ''): bool {
151
		if (isset ( self::$libraries [$library] )) {
152
			$dir = $this->vendorDir . self::$libraries [$library] . $part;
153
			if (\file_exists ( $dir )) {
154
				$this->addDir ( $dir );
155
				return true;
156
			}
157
		}
158
		return false;
159
	}
160
161
	/**
162
	 * Adds Ubiquity framework controller and routing classes preload.
163
	 *
164
	 * @return \Ubiquity\cache\Preloader
165
	 */
166
	public function addUbiquityControllers() {
167
		$this->addLibraryPart ( 'ubiquity', 'controllers' );
168
		$this->addClass ( 'Ubiquity\\events\\EventManager' );
169
		$this->addClass ( 'Ubiquity\\log\\Logger' );
170
		$this->exclude ( 'Ubiquity\\controllers\\crud', 'Ubiquity\\controllers\\rest', 'Ubiquity\\controllers\\seo', 'Ubiquity\\controllers\\auth' );
171
		return $this;
172
	}
173
174
	/**
175
	 * Adds Ubiquity framework cache system classes to preload.
176
	 *
177
	 * @return \Ubiquity\cache\Preloader
178
	 */
179
	public function addUbiquityCache() {
180
		$this->addClass ( 'Ubiquity\\cache\\CacheManager' );
181
		$this->addClass ( 'Ubiquity\\cache\\system\\ArrayCache' );
182
		return $this;
183
	}
184
185
	/**
186
	 * Adds Ubiquity framework PDO classes to preload.
187
	 *
188
	 * @return \Ubiquity\cache\Preloader
189
	 */
190
	public function addUbiquityPdo() {
191
		$this->addClass ( 'Ubiquity\\db\\Database' );
192
		$this->addClass ( 'Ubiquity\\cache\\database\\DbCache' );
193
		$this->addClass ( 'Ubiquity\\db\\SqlUtils' );
194
		$this->addLibraryPart ( 'ubiquity', 'db/providers' );
195
		return $this;
196
	}
197
198
	/**
199
	 * Adds Ubiquity framework ORM classes to preload.
200
	 *
201
	 * @return \Ubiquity\cache\Preloader
202
	 */
203
	public function addUbiquityORM() {
204
		$this->addLibraryPart ( 'ubiquity', 'orm' );
205
		$this->addClass ( 'Ubiquity\\events\\DAOEvents' );
206
		return $this;
207
	}
208
209
	/**
210
	 * Adds Ubiquity framework Http classes to preload.
211
	 *
212
	 * @return \Ubiquity\cache\Preloader
213
	 */
214
	public function addUbiquityHttpUtils() {
215
		$this->addClass ( 'Ubiquity\\utils\\http\\URequest' );
216
		$this->addClass ( 'Ubiquity\\utils\\http\\UResponse' );
217
		$this->addClass ( 'Ubiquity\\utils\\http\\foundation\\PhpHttp' );
218
		return $this;
219
	}
220
221
	/**
222
	 * Adds Ubiquity framework MicroTemplateEngine classes to preload.
223
	 *
224
	 * @return \Ubiquity\cache\Preloader
225
	 */
226
	public function addUbiquityViews() {
227
		$this->addClass ( 'Ubiquity\\views\\View' );
228
		$this->addClass ( 'Ubiquity\\views\\engine\\micro\\MicroTemplateEngine' );
229
		return $this;
230
	}
231
232
	/**
233
	 * Adds Ubiquity framework Translations classes to preload.
234
	 *
235
	 * @return \Ubiquity\cache\Preloader
236
	 */
237
	public function addUbiquityTranslations() {
238
		$this->addLibraryPart ( 'ubiquity', 'translation' );
239
		return $this;
240
	}
241
242
	/**
243
	 * Adds Ubiquity-workerman classes to preload.
244
	 *
245
	 * @return \Ubiquity\cache\Preloader
246
	 */
247
	public function addUbiquityWorkerman() {
248
		$this->addClasses ( [ 'Ubiquity\\servers\\workerman\\WorkermanServer','Ubiquity\\utils\\http\\foundation\\WorkermanHttp' ] );
249
		return $this;
250
	}
251
252
	/**
253
	 * Adds Ubiquity-swoole classes to preload.
254
	 *
255
	 * @return \Ubiquity\cache\Preloader
256
	 */
257
	public function addUbiquitySwoole() {
258
		$this->addClasses ( [ 'Ubiquity\\servers\\swoole\\SwooleServer','Ubiquity\\utils\\http\\foundation\\SwooleHttp' ] );
259
		return $this;
260
	}
261
262
	/**
263
	 * Adds classes from an application part (app folder) to preload.
264
	 *
265
	 * @param string $part
266
	 * @return \Ubiquity\cache\Preloader
267
	 */
268
	public function addApplicationPart(?string $part = '') {
269
		$this->addLibraryPart ( 'application', $part );
270
		return $this;
271
	}
272
273
	/**
274
	 *
275
	 * @param string $dir
276
	 * @return \Ubiquity\cache\Preloader
277
	 */
278
	public function addApplicationModels($dir = 'models') {
279
		$this->addLibraryPart ( 'application', $dir );
280
		return $this;
281
	}
282
283
	/**
284
	 *
285
	 * @param string $dir
286
	 * @return \Ubiquity\cache\Preloader
287
	 */
288
	public function addApplicationCache($dir = 'cache') {
289
		$this->addLibraryPart ( 'application', $dir );
290
		return $this;
291
	}
292
293
	/**
294
	 *
295
	 * @param string $dir
296
	 * @return \Ubiquity\cache\Preloader
297
	 */
298
	public function addApplicationControllers($dir = 'controllers') {
299
		$this->addLibraryPart ( 'application', $dir );
300
		$this->exclude ( $dir . '\\MaintenanceController', $dir . '\\Admin' );
301
		return $this;
302
	}
303
304
	/**
305
	 * Add Ubiquity hot classes for preloading
306
	 *
307
	 * @param boolean $hasDatabase
308
	 * @return \Ubiquity\cache\Preloader
309
	 */
310
	public function addUbiquityBasics($hasDatabase = true) {
311
		$this->addUbiquityCache ();
312
		$this->addUbiquityControllers ();
313
		$this->addUbiquityHttpUtils ();
314
		if ($hasDatabase) {
315
			$this->addUbiquityPdo ();
316
			$this->addUbiquityORM ();
317
		}
318
		return $this;
319
	}
320
321
	/**
322
	 * Adds Twig templating system classes to preload.
323
	 *
324
	 * @return \Ubiquity\cache\Preloader
325
	 */
326
	public function addUbiquityTwig() {
327
		$this->addClasses ( [ 'Ubiquity\\views\\engine\\Twig','Twig\\Cache\\FilesystemCache','Twig\\Extension\\CoreExtension','Twig\\Extension\\EscaperExtension','Twig\\Extension\\OptimizerExtension','Twig\\Extension\\StagingExtension','Twig\\ExtensionSet','Twig\\Template','Twig\\TemplateWrapper' ] );
328
		return $this;
329
	}
330
331
	/**
332
	 * Defines classes to be preloaded in a file returning an associative array keys : (classes-files, excludeds, paths, classes, libraries-parts, callback).
333
	 *
334
	 * @param string $appRoot
335
	 * @param string $filename
336
	 * @return bool
337
	 */
338
	public static function fromFile(string $appRoot, string $filename): bool {
339
		if (\file_exists ( $filename )) {
340
			$array = include $filename;
341
			return self::fromArray ( $appRoot, $array );
342
		}
343
		return false;
344
	}
345
346
	/**
347
	 * Defines classes to be preloaded with an associative array keys : (classes-files, excludeds, paths, classes, libraries-parts, callback).
348
	 *
349
	 * @param string $appRoot
350
	 * @param array $array
351
	 * @return bool
352
	 */
353
	public static function fromArray(string $appRoot, array $array): bool {
354
		$pre = new self ( $appRoot );
355
		self::$count = 0;
356
		if (isset ( $array ['classes-files'] )) {
357
			$pre->classes = $array ['classes-files'];
358
		}
359
		if (isset ( $array ['excludeds'] )) {
360
			$pre->excludeds = $array ['excludeds'];
361
		}
362
		if (isset ( $array ['paths'] )) {
363
			foreach ( $array ['paths'] as $path ) {
364
				$pre->addDir ( $path );
365
			}
366
		}
367
		if (isset ( $array ['classes'] )) {
368
			foreach ( $array ['classes'] as $class ) {
369
				$pre->addClass ( $class );
370
			}
371
		}
372
		if (isset ( $array ['libraries-parts'] )) {
373
			foreach ( $array ['libraries-parts'] as $library => $parts ) {
374
				foreach ( $parts as $part ) {
375
					$pre->addLibraryPart ( $library, $part );
376
				}
377
			}
378
		}
379
		if (isset ( $array ['callback'] )) {
380
			if (\is_callable ( $array ['callback'] )) {
381
				$call = $array ['callback'];
382
				$call ( $pre );
383
			}
384
		}
385
		$pre->load ();
386
		return self::$count > 0;
387
	}
388
389
	/**
390
	 * Generates a preload classes-files array from cached files
391
	 *
392
	 * @param boolean $resetExisting
393
	 */
394
	public function generateClassesFromRunning($resetExisting = true) {
395
		$cache = \opcache_get_status ( true );
396
		if ($resetExisting) {
397
			$this->classes = [ ];
398
		}
399
		foreach ( $cache ['scripts'] as $script ) {
400
			$path = $script ['full_path'];
401
			$class = $this->getClassFullNameFromFile ( $path );
402
			if (isset ( $class )) {
403
				$this->addClassFile ( $class, $path );
404
			}
405
		}
406
	}
407
408
	/**
409
	 * Returns an array of available libraries to be preloaded
410
	 *
411
	 * @return array
412
	 */
413
	public static function getLibraries() {
414
		return \array_keys ( self::$libraries );
415
	}
416
}
417
418