Files
kiri-core/Annotation/Loader.php
T

240 lines
4.8 KiB
PHP
Raw Normal View History

2021-03-03 18:35:04 +08:00
<?php
namespace Annotation;
use DirectoryIterator;
2021-03-23 16:14:05 +08:00
use Exception;
2021-07-12 17:17:36 +08:00
use ReflectionClass;
use ReflectionException;
2021-08-11 01:04:57 +08:00
use Kiri\Abstracts\BaseObject;
use Kiri\Kiri;
2021-03-03 18:35:04 +08:00
use Throwable;
/**
* Class Loader
* @package Annotation
*/
class Loader extends BaseObject
{
2021-08-05 15:55:27 +08:00
private array $_classes = [];
2021-07-27 16:08:16 +08:00
2021-08-05 15:55:27 +08:00
private array $_directory = [];
2021-07-27 16:08:16 +08:00
2021-08-05 15:55:27 +08:00
private array $_property = [];
2021-07-27 16:08:16 +08:00
2021-08-05 15:55:27 +08:00
private array $_methods = [];
2021-07-27 16:08:16 +08:00
/**
* @param $path
* @param $namespace
* @throws Exception
*/
public function loader($path, $namespace)
{
$this->_scanDir(new DirectoryIterator($path), $namespace);
}
/**
* @param string $class
* @param string $property
2021-08-05 15:55:27 +08:00
* @return \ReflectionProperty|array|null
2021-08-04 16:32:28 +08:00
* @throws ReflectionException
2021-07-27 16:08:16 +08:00
*/
2021-08-05 15:55:27 +08:00
public function getProperty(string $class, string $property = ''): \ReflectionProperty|array|null
2021-07-27 16:08:16 +08:00
{
2021-08-11 01:04:57 +08:00
return Kiri::getDi()->getClassReflectionProperty($class, $property);
2021-07-27 16:08:16 +08:00
}
/**
* @param string $class
* @param object $handler
* @return $this
* @throws ReflectionException
* @throws Exception
*/
public function injectProperty(string $class, object $handler): static
{
2021-08-11 01:04:57 +08:00
$di = Kiri::getDi();
2021-07-27 16:08:16 +08:00
$reflect = $di->getReflect($class);
$di->propertyInject($reflect, $handler);
return $this;
}
/**
* @param string $class
* @param string $method
* @return mixed
*/
public function getMethod(string $class, string $method = ''): array
{
2021-08-05 15:55:27 +08:00
if (!isset($this->_methods[$class])) {
2021-07-27 16:08:16 +08:00
return [];
}
2021-08-05 15:55:27 +08:00
$properties = $this->_methods[$class];
2021-07-27 16:08:16 +08:00
if (!empty($method) && isset($properties[$method])) {
return $properties[$method];
}
return $properties;
}
/**
* @param DirectoryIterator $paths
* @param $namespace
2021-08-05 16:30:45 +08:00
* @param array $exclude
2021-07-27 16:08:16 +08:00
* @throws Exception
*/
2021-08-05 16:30:45 +08:00
public function _scanDir(DirectoryIterator $paths, $namespace, array $exclude = [])
2021-07-27 16:08:16 +08:00
{
foreach ($paths as $path) {
if ($path->isDot() || str_starts_with($path->getFilename(), '.')) {
continue;
}
2021-08-05 16:30:45 +08:00
if ($this->inExclude($exclude, $path->getRealPath())) {
continue;
}
2021-07-27 16:08:16 +08:00
if ($path->isDir()) {
$iterator = new DirectoryIterator($path->getRealPath());
$directory = rtrim($path->getRealPath(), '/');
2021-08-05 15:55:27 +08:00
if (!isset($this->_directory[$directory])) {
$this->_directory[$directory] = [];
2021-07-27 16:08:16 +08:00
}
$this->_scanDir($iterator, $namespace);
} else {
$this->readFile($path, $namespace);
}
}
}
/**
* @param DirectoryIterator $path
* @param $namespace
* @throws Exception
*/
private function readFile(DirectoryIterator $path, $namespace)
{
try {
if ($path->getExtension() !== 'php') {
return;
}
$replace = $this->getReflect($path, $namespace);
2021-08-04 16:32:28 +08:00
if (!$replace->getAttributes(Target::class)) {
return;
}
2021-07-27 16:08:16 +08:00
$this->appendFileToDirectory($path->getRealPath(), $replace->getName());
} catch (Throwable $throwable) {
2021-08-04 17:49:45 +08:00
$this->error(jTraceEx($throwable), 'throwable');
2021-07-27 16:08:16 +08:00
}
}
/**
* @param DirectoryIterator $path
* @param string $namespace
* @return ReflectionClass|null
2021-08-04 17:32:14 +08:00
* @throws ReflectionException
2021-07-27 16:08:16 +08:00
*/
private function getReflect(DirectoryIterator $path, string $namespace): ?ReflectionClass
{
2021-08-11 01:04:57 +08:00
return Kiri::getDi()->getReflect($this->explodeFileName($path, $namespace));
2021-07-27 16:08:16 +08:00
}
/**
* @param string $path
2021-08-05 15:55:27 +08:00
* @param array $exclude
2021-07-27 16:15:28 +08:00
* @return array
2021-07-27 16:08:16 +08:00
* @throws Exception
*/
2021-08-05 15:55:27 +08:00
public function loadByDirectory(string $path, array $exclude = []): array
2021-07-27 16:08:16 +08:00
{
try {
$path = '/' . trim($path, '/');
$paths = [];
2021-08-05 15:55:27 +08:00
foreach ($this->_directory as $key => $_path) {
2021-07-27 16:08:16 +08:00
$key = '/' . trim($key, '/');
2021-08-05 15:55:27 +08:00
if (!str_starts_with($key, $path) || $this->inExclude($exclude, $path)) {
2021-07-27 16:08:16 +08:00
continue;
}
2021-08-05 15:55:27 +08:00
unset($this->_directory[$key]);
2021-07-27 16:08:16 +08:00
foreach ($_path as $item) {
2021-08-03 11:08:56 +08:00
$paths[] = $item;
2021-07-27 16:08:16 +08:00
}
}
return $paths;
} catch (Throwable $exception) {
$this->addError($exception, 'throwable');
return [];
}
}
2021-08-05 15:55:27 +08:00
/**
* @param array $exclude
* @param $path
* @return bool
*/
private function inExclude(array $exclude, $path): bool
{
if (empty($exclude)) {
return false;
}
foreach ($exclude as $value) {
2021-08-05 16:39:50 +08:00
if (str_starts_with($path, $value)) {
2021-08-05 15:55:27 +08:00
return true;
}
}
return false;
}
2021-07-27 16:08:16 +08:00
/**
* @param DirectoryIterator $path
* @param string $namespace
* @return string
*/
private function explodeFileName(DirectoryIterator $path, string $namespace): string
{
$replace = str_replace(APP_PATH . 'app', '', $path->getRealPath());
$replace = str_replace('.php', '', $replace);
$replace = str_replace(DIRECTORY_SEPARATOR, '\\', $replace);
$explode = explode('\\', $replace);
array_shift($explode);
return $namespace . '\\' . implode('\\', $explode);
}
/**
* @param string $filePath
* @param string $className
*/
public function appendFileToDirectory(string $filePath, string $className)
{
$array = explode('/', $filePath);
unset($array[count($array) - 1]);
$array = '/' . trim(implode('/', $array), '/');
2021-08-05 15:55:27 +08:00
$this->_directory[$array][] = $className;
2021-07-27 16:08:16 +08:00
}
2021-07-27 00:35:50 +08:00
2021-03-03 18:35:04 +08:00
}