Files
kiri-container/Scanner.php
T

144 lines
3.8 KiB
PHP
Raw Normal View History

2023-04-16 16:40:44 +08:00
<?php
declare(strict_types=1);
namespace Kiri\Di;
2023-12-12 10:56:43 +08:00
use Kiri\Di\Inject\Container;
2023-04-16 16:40:44 +08:00
use Kiri\Abstracts\Component;
2023-04-24 22:31:08 +08:00
use Kiri\Di\Inject\Skip;
2023-12-12 10:56:43 +08:00
use Psr\Container\ContainerInterface;
2023-12-18 16:28:00 +08:00
use ReflectionClass;
2023-08-03 14:08:16 +08:00
use ReflectionMethod;
2023-04-16 16:40:44 +08:00
class Scanner extends Component
{
2023-05-25 16:59:17 +08:00
/**
2023-12-12 10:56:43 +08:00
* @var ContainerInterface
2023-05-25 16:59:17 +08:00
*/
2023-12-12 10:56:43 +08:00
#[Container(ContainerInterface::class)]
public ContainerInterface $container;
2023-05-25 16:59:17 +08:00
2023-12-19 16:26:22 +08:00
/**
* @var array
*/
public array $files = [];
2023-05-25 16:59:17 +08:00
/**
2023-12-12 10:56:43 +08:00
* @param string $path
2023-05-25 16:59:17 +08:00
* @return void
2023-12-12 15:35:35 +08:00
* @throws
2023-05-25 16:59:17 +08:00
*/
2023-12-12 10:56:43 +08:00
public function load_directory(string $path): void
2023-05-25 16:59:17 +08:00
{
2023-12-12 10:56:43 +08:00
$dir = new \DirectoryIterator($path);
$skip = \config('scanner.skip', []);
foreach ($dir as $value) {
if ($value->isDot() || str_starts_with($value->getFilename(), '.')) {
2023-08-17 16:15:07 +08:00
continue;
}
2023-12-12 10:56:43 +08:00
if ($value->isDir()) {
if (in_array($value->getRealPath() . '/', $skip)) {
2023-05-25 16:59:17 +08:00
continue;
}
2023-12-12 10:56:43 +08:00
$this->load_directory($value->getRealPath());
} else if ($value->getExtension() == 'php') {
2023-12-19 17:50:59 +08:00
if (in_array($value->getRealPath(), $this->files)) {
continue;
2023-12-19 16:44:38 +08:00
}
2023-12-19 17:50:59 +08:00
$this->files[] = $value->getRealPath();
$this->load_file($value->getRealPath());
2023-05-25 16:59:17 +08:00
}
}
}
/**
* @param string $file
* @return string
*/
private function rename(string $file): string
{
$filter = array_filter(explode('/', $file), function ($value) {
if (empty($value)) {
return false;
}
return ucfirst($value);
});
return ucfirst(implode('\\', $filter));
}
/**
* @param string $path
* @return void
2023-12-12 15:35:35 +08:00
* @throws
2023-05-25 16:59:17 +08:00
*/
private function load_file(string $path): void
{
try {
require_once "$path";
$path = str_replace($_SERVER['PWD'], '', $path);
$path = str_replace('.php', '', $path);
2023-12-12 10:56:43 +08:00
$this->parseFile($path);
2023-05-25 16:59:17 +08:00
} catch (\Throwable $throwable) {
error($throwable);
}
}
2023-04-16 16:40:44 +08:00
2023-12-12 10:56:43 +08:00
/**
* @param $file
* @return void
2023-12-12 15:35:35 +08:00
* @throws
2023-12-12 10:56:43 +08:00
*/
protected function parseFile($file): void
{
$class = $this->rename($file);
if (class_exists($class)) {
$reflect = $this->container->getReflectionClass($class);
if ($reflect->isInstantiable()) {
2023-12-18 21:55:43 +08:00
if ($reflect->isTrait() || $reflect->isEnum() || $reflect->isInterface()) {
2023-12-18 17:18:54 +08:00
return;
}
2023-12-18 16:28:00 +08:00
$attributes = $this->skipNames($reflect);
if (in_array(Skip::class, $attributes) || in_array(\Attribute::class, $attributes)) {
2023-12-18 16:20:38 +08:00
return;
}
2023-12-18 17:10:34 +08:00
foreach ($reflect->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
2023-12-12 10:56:43 +08:00
if ($method->isStatic() || $method->getDeclaringClass()->getName() != $class) {
continue;
}
$attributes = $method->getAttributes();
foreach ($attributes as $attribute) {
if (!class_exists($attribute->getName())) {
continue;
}
2023-12-18 22:23:16 +08:00
$attribute->newInstance()->dispatch($class, $method->getName());
2023-12-12 10:56:43 +08:00
}
}
}
}
}
2023-12-18 16:28:00 +08:00
/**
* @param ReflectionClass $reflect
* @return array
*/
protected function skipNames(ReflectionClass $reflect): array
{
$attributes = $reflect->getAttributes();
$names = [];
foreach ($attributes as $attribute) {
$names[] = $attribute->getName();
}
return $names;
}
2023-04-16 16:40:44 +08:00
}