Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b08fdb1801 | |||
| a0b975003a | |||
| 81250722ea | |||
| b7712d3d9d | |||
| c38fb6ac4c | |||
| 7827b8d5b1 |
+68
-6
@@ -6,34 +6,75 @@ namespace Kiri\Di;
|
|||||||
|
|
||||||
class ChangeSet
|
class ChangeSet
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
private array $changedFiles = [];
|
private array $changedFiles = [];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
private array $removedFiles = [];
|
private array $removedFiles = [];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
private array $changedClasses = [];
|
private array $changedClasses = [];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
private array $removedClasses = [];
|
private array $removedClasses = [];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $file
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function addChangedFile(string $file): void
|
public function addChangedFile(string $file): void
|
||||||
{
|
{
|
||||||
$this->changedFiles[$file] = true;
|
$this->changedFiles[$file] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $file
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function addRemovedFile(string $file): void
|
public function addRemovedFile(string $file): void
|
||||||
{
|
{
|
||||||
$this->removedFiles[$file] = true;
|
$this->removedFiles[$file] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $class
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function addChangedClass(string $class): void
|
public function addChangedClass(string $class): void
|
||||||
{
|
{
|
||||||
$this->changedClasses[$class] = true;
|
$this->changedClasses[$class] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $class
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function addRemovedClass(string $class): void
|
public function addRemovedClass(string $class): void
|
||||||
{
|
{
|
||||||
$this->removedClasses[$class] = true;
|
$this->removedClasses[$class] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ChangeSet $changeSet
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
public function merge(ChangeSet $changeSet): self
|
public function merge(ChangeSet $changeSet): self
|
||||||
{
|
{
|
||||||
foreach ($changeSet->getChangedFiles() as $file) {
|
foreach ($changeSet->getChangedFiles() as $file) {
|
||||||
@@ -55,39 +96,60 @@ class ChangeSet
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function getChangedFiles(): array
|
public function getChangedFiles(): array
|
||||||
{
|
{
|
||||||
return array_keys($this->changedFiles);
|
return array_keys($this->changedFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function getRemovedFiles(): array
|
public function getRemovedFiles(): array
|
||||||
{
|
{
|
||||||
return array_keys($this->removedFiles);
|
return array_keys($this->removedFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function getChangedClasses(): array
|
public function getChangedClasses(): array
|
||||||
{
|
{
|
||||||
return array_keys($this->changedClasses);
|
return array_keys($this->changedClasses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function getRemovedClasses(): array
|
public function getRemovedClasses(): array
|
||||||
{
|
{
|
||||||
return array_keys($this->removedClasses);
|
return array_keys($this->removedClasses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function hasChanges(): bool
|
public function hasChanges(): bool
|
||||||
{
|
{
|
||||||
return $this->changedFiles !== []
|
return $this->changedFiles !== [] || $this->removedFiles !== [] || $this->changedClasses !== [] || $this->removedClasses !== [];
|
||||||
|| $this->removedFiles !== []
|
|
||||||
|| $this->changedClasses !== []
|
|
||||||
|| $this->removedClasses !== [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function toArray(): array
|
public function toArray(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'changed_files' => $this->getChangedFiles(),
|
'changed_files' => $this->getChangedFiles(),
|
||||||
'removed_files' => $this->getRemovedFiles(),
|
'removed_files' => $this->getRemovedFiles(),
|
||||||
'changed_classes' => $this->getChangedClasses(),
|
'changed_classes' => $this->getChangedClasses(),
|
||||||
'removed_classes' => $this->getRemovedClasses(),
|
'removed_classes' => $this->getRemovedClasses(),
|
||||||
];
|
];
|
||||||
|
|||||||
+85
-2
@@ -207,6 +207,75 @@ class Container implements ContainerInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理所有非基础设施类的单例引用,释放 Swoole 常驻进程中的内存
|
||||||
|
* 保留框架核心类(Kiri、Database、Psr、Symfony)的单例
|
||||||
|
* 应在请求/任务完成后调用,防止单例映射无限增长
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function clearNonInfrastructure(): void
|
||||||
|
{
|
||||||
|
$keepPrefixes = [
|
||||||
|
ContainerInterface::class,
|
||||||
|
'Kiri\\', 'Database\\', 'Psr\\', 'Symfony\\',
|
||||||
|
'Swoole\\', 'MongoDB\\',
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach (array_keys($this->_singletons) as $className) {
|
||||||
|
$shouldKeep = false;
|
||||||
|
foreach ($keepPrefixes as $prefix) {
|
||||||
|
if (str_starts_with($className, $prefix)) {
|
||||||
|
$shouldKeep = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$shouldKeep) {
|
||||||
|
unset($this->_singletons[$className]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (array_keys($this->_reflection) as $className) {
|
||||||
|
$shouldKeep = false;
|
||||||
|
foreach ($keepPrefixes as $prefix) {
|
||||||
|
if (str_starts_with($className, $prefix)) {
|
||||||
|
$shouldKeep = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$shouldKeep) {
|
||||||
|
unset($this->_reflection[$className]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (array_keys($this->_parameters) as $className) {
|
||||||
|
$shouldKeep = false;
|
||||||
|
foreach ($keepPrefixes as $prefix) {
|
||||||
|
if (str_starts_with($className, $prefix)) {
|
||||||
|
$shouldKeep = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$shouldKeep) {
|
||||||
|
unset($this->_parameters[$className]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前单例缓存统计信息,用于内存监控
|
||||||
|
* @return array{singletons: int, reflections: int, params: int}
|
||||||
|
*/
|
||||||
|
public function getMemoryStats(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'singletons' => count($this->_singletons),
|
||||||
|
'reflections' => count($this->_reflection),
|
||||||
|
'params' => count($this->_parameters),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $className
|
* @param string $className
|
||||||
* @param array $construct
|
* @param array $construct
|
||||||
@@ -225,7 +294,14 @@ class Container implements ContainerInterface
|
|||||||
$construct = $this->getMethodParams($handler);
|
$construct = $this->getMethodParams($handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
$newInstance = $reflect->newInstanceArgs($construct);
|
$isController = class_exists(\Kiri\Router\Base\Controller::class) && $reflect->isSubclassOf(\Kiri\Router\Base\Controller::class);
|
||||||
|
$needsProxy = !$isController && class_exists(\Kiri\Router\Defer\DeferRegistry::class) && \Kiri\Router\Defer\DeferRegistry::hasAny($className);
|
||||||
|
|
||||||
|
if ($needsProxy) {
|
||||||
|
$newInstance = \Kiri\Router\Defer\DeferProxyGenerator::create($className, $construct);
|
||||||
|
} else {
|
||||||
|
$newInstance = $reflect->newInstanceArgs($construct);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->runInit($reflect, static::configure($newInstance, $config));
|
return $this->runInit($reflect, static::configure($newInstance, $config));
|
||||||
}
|
}
|
||||||
@@ -252,7 +328,14 @@ class Container implements ContainerInterface
|
|||||||
if (empty($construct) && ($handler = $reflect->getConstructor()) !== null) {
|
if (empty($construct) && ($handler = $reflect->getConstructor()) !== null) {
|
||||||
$construct = $this->getMethodParams($handler);
|
$construct = $this->getMethodParams($handler);
|
||||||
}
|
}
|
||||||
$newInstance = $reflect->newInstanceArgs($construct);
|
$isController = class_exists(\Kiri\Router\Base\Controller::class) && $reflect->isSubclassOf(\Kiri\Router\Base\Controller::class);
|
||||||
|
$needsProxy = !$isController && class_exists(\Kiri\Router\Defer\DeferRegistry::class) && \Kiri\Router\Defer\DeferRegistry::hasAny($reflect->getName());
|
||||||
|
|
||||||
|
if ($needsProxy) {
|
||||||
|
$newInstance = \Kiri\Router\Defer\DeferProxyGenerator::create($reflect->getName(), $construct);
|
||||||
|
} else {
|
||||||
|
$newInstance = $reflect->newInstanceArgs($construct);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->runInit($reflect, static::configure($newInstance, $config));
|
return $this->runInit($reflect, static::configure($newInstance, $config));
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-3
@@ -6,13 +6,16 @@ namespace Kiri\Di;
|
|||||||
|
|
||||||
class HotReloadState
|
class HotReloadState
|
||||||
{
|
{
|
||||||
private const MAX_AGE_SECONDS = 30;
|
private const int MAX_AGE_SECONDS = 30;
|
||||||
|
|
||||||
public function store(array $changedFiles): void
|
public function store(array $changedFiles): void
|
||||||
{
|
{
|
||||||
|
$normalizedFiles = array_map([$this, 'normalizePath'], array_filter($changedFiles));
|
||||||
|
$normalizedFiles = array_values(array_unique($normalizedFiles));
|
||||||
|
|
||||||
$payload = [
|
$payload = [
|
||||||
'timestamp' => time(),
|
'timestamp' => time(),
|
||||||
'changed_files' => array_values(array_unique(array_map([$this, 'normalizePath'], array_filter($changedFiles)))),
|
'changed_files' => $normalizedFiles,
|
||||||
];
|
];
|
||||||
|
|
||||||
$directory = dirname($this->getFilePath());
|
$directory = dirname($this->getFilePath());
|
||||||
@@ -46,7 +49,9 @@ class HotReloadState
|
|||||||
}
|
}
|
||||||
|
|
||||||
$files = is_array($data['changed_files'] ?? null) ? $data['changed_files'] : [];
|
$files = is_array($data['changed_files'] ?? null) ? $data['changed_files'] : [];
|
||||||
return array_values(array_unique(array_map([$this, 'normalizePath'], $files)));
|
$files = array_map([$this, 'normalizePath'], $files);
|
||||||
|
$files = array_values(array_unique($files));
|
||||||
|
return $files;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getFilePath(): string
|
private function getFilePath(): string
|
||||||
|
|||||||
+44
-1
@@ -8,6 +8,13 @@ class ScanManifest
|
|||||||
{
|
{
|
||||||
private array $entries = [];
|
private array $entries = [];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $path
|
||||||
|
* @param int $mtime
|
||||||
|
* @param array $classes
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function set(string $path, int $mtime, array $classes): void
|
public function set(string $path, int $mtime, array $classes): void
|
||||||
{
|
{
|
||||||
$this->entries[$path] = [
|
$this->entries[$path] = [
|
||||||
@@ -16,21 +23,41 @@ class ScanManifest
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $path
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function has(string $path): bool
|
public function has(string $path): bool
|
||||||
{
|
{
|
||||||
return isset($this->entries[$path]);
|
return isset($this->entries[$path]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $path
|
||||||
|
* @return int|null
|
||||||
|
*/
|
||||||
public function getMtime(string $path): ?int
|
public function getMtime(string $path): ?int
|
||||||
{
|
{
|
||||||
return $this->entries[$path]['mtime'] ?? null;
|
return $this->entries[$path]['mtime'] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $path
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function getClasses(string $path): array
|
public function getClasses(string $path): array
|
||||||
{
|
{
|
||||||
return $this->entries[$path]['classes'] ?? [];
|
return $this->entries[$path]['classes'] ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $path
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function remove(string $path): array
|
public function remove(string $path): array
|
||||||
{
|
{
|
||||||
$classes = $this->getClasses($path);
|
$classes = $this->getClasses($path);
|
||||||
@@ -38,20 +65,36 @@ class ScanManifest
|
|||||||
return $classes;
|
return $classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function all(): array
|
public function all(): array
|
||||||
{
|
{
|
||||||
return $this->entries;
|
return $this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|null $prefix
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function paths(?string $prefix = null): array
|
public function paths(?string $prefix = null): array
|
||||||
{
|
{
|
||||||
if ($prefix === null) {
|
if ($prefix === null) {
|
||||||
return array_keys($this->entries);
|
return array_keys($this->entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
return array_values(array_filter(array_keys($this->entries), fn(string $path) => str_starts_with($path, $prefix)));
|
$keys = array_keys($this->entries);
|
||||||
|
$filtered = array_filter($keys, fn(string $path) => str_starts_with($path, $prefix));
|
||||||
|
return array_values($filtered);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $entries
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function fromArray(array $entries): void
|
public function fromArray(array $entries): void
|
||||||
{
|
{
|
||||||
$this->entries = [];
|
$this->entries = [];
|
||||||
|
|||||||
+32
-118
@@ -8,6 +8,7 @@ use DirectoryIterator;
|
|||||||
use Kiri\Abstracts\Component;
|
use Kiri\Abstracts\Component;
|
||||||
use Kiri\Di\Inject\Container;
|
use Kiri\Di\Inject\Container;
|
||||||
use Kiri\Di\Inject\Skip;
|
use Kiri\Di\Inject\Skip;
|
||||||
|
use Kiri\Di\Interface\InjectMethodInterface;
|
||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
use ReflectionClass;
|
use ReflectionClass;
|
||||||
use ReflectionMethod;
|
use ReflectionMethod;
|
||||||
@@ -41,7 +42,6 @@ class Scanner extends Component
|
|||||||
'cache_enabled' => false,
|
'cache_enabled' => false,
|
||||||
'cache_ttl' => 3600,
|
'cache_ttl' => 3600,
|
||||||
'debug' => false,
|
'debug' => false,
|
||||||
'class_name_strategy' => 'auto',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
@@ -79,11 +79,6 @@ class Scanner extends Component
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->syncLegacyState();
|
$this->syncLegacyState();
|
||||||
|
|
||||||
if ($this->config['cache_enabled']) {
|
|
||||||
$this->saveToCache($cacheFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->changeSet;
|
return $this->changeSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,6 +113,7 @@ class Scanner extends Component
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->syncLegacyState();
|
$this->syncLegacyState();
|
||||||
|
|
||||||
return $this->changeSet;
|
return $this->changeSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,9 +235,12 @@ class Scanner extends Component
|
|||||||
private function loadAndParseFile(string $path): array
|
private function loadAndParseFile(string $path): array
|
||||||
{
|
{
|
||||||
$this->optimizeWithOpcache($path);
|
$this->optimizeWithOpcache($path);
|
||||||
require_once $path;
|
|
||||||
|
|
||||||
$classes = $this->getClassNamesForFile($path);
|
$before = get_declared_classes();
|
||||||
|
require_once $path;
|
||||||
|
$after = get_declared_classes();
|
||||||
|
|
||||||
|
$classes = array_values(array_diff($after, $before));
|
||||||
foreach ($classes as $class) {
|
foreach ($classes as $class) {
|
||||||
if (class_exists($class)) {
|
if (class_exists($class)) {
|
||||||
$this->analyzeClass($class);
|
$this->analyzeClass($class);
|
||||||
@@ -251,104 +250,6 @@ class Scanner extends Component
|
|||||||
return $classes;
|
return $classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getClassNamesForFile(string $path): array
|
|
||||||
{
|
|
||||||
$strategy = $this->config['class_name_strategy'];
|
|
||||||
$classes = [];
|
|
||||||
|
|
||||||
if (in_array($strategy, ['auto', 'extract', 'both'], true)) {
|
|
||||||
$class = $this->extractClassNameFromFile($path);
|
|
||||||
if ($class !== null) {
|
|
||||||
$classes[] = $class;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($classes === [] || in_array($strategy, ['rename', 'both'], true)) {
|
|
||||||
$classes[] = $this->renamePathToClassName($path);
|
|
||||||
}
|
|
||||||
|
|
||||||
return array_values(array_unique(array_filter($classes)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private function canExtractClassName(): bool
|
|
||||||
{
|
|
||||||
return function_exists('token_get_all');
|
|
||||||
}
|
|
||||||
|
|
||||||
private function extractClassNameFromFile(string $path): ?string
|
|
||||||
{
|
|
||||||
if (!$this->canExtractClassName()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$content = @file_get_contents($path);
|
|
||||||
if ($content === false || $content === '') {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$tokens = @token_get_all($content);
|
|
||||||
if (!$tokens) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$namespace = '';
|
|
||||||
$class = '';
|
|
||||||
$collectingNamespace = false;
|
|
||||||
$collectingClass = false;
|
|
||||||
$previousToken = null;
|
|
||||||
|
|
||||||
foreach ($tokens as $token) {
|
|
||||||
if (is_array($token)) {
|
|
||||||
$text = $token[1];
|
|
||||||
|
|
||||||
if ($token[0] === T_NAMESPACE) {
|
|
||||||
$namespace = '';
|
|
||||||
$collectingNamespace = true;
|
|
||||||
} elseif ($collectingNamespace && in_array($token[0], [T_STRING, T_NAME_QUALIFIED, T_NS_SEPARATOR], true)) {
|
|
||||||
$namespace .= $text;
|
|
||||||
} elseif ($collectingNamespace && $token[0] === T_WHITESPACE) {
|
|
||||||
} elseif (in_array($token[0], [T_CLASS, T_INTERFACE, T_TRAIT, T_ENUM], true) && $previousToken !== T_DOUBLE_COLON && $previousToken !== T_NEW) {
|
|
||||||
$collectingClass = true;
|
|
||||||
} elseif ($collectingClass && $token[0] === T_STRING) {
|
|
||||||
$class = $text;
|
|
||||||
break;
|
|
||||||
} elseif ($collectingNamespace) {
|
|
||||||
$collectingNamespace = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($token[0] !== T_WHITESPACE) {
|
|
||||||
$previousToken = $token[0];
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($collectingNamespace && ($token === ';' || $token === '{')) {
|
|
||||||
$collectingNamespace = false;
|
|
||||||
}
|
|
||||||
if ($token === '{') {
|
|
||||||
$collectingClass = false;
|
|
||||||
}
|
|
||||||
$previousToken = $token;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($class === '') {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $namespace !== '' ? $namespace . '\\' . $class : $class;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function renamePathToClassName(string $path): string
|
|
||||||
{
|
|
||||||
$relativePath = str_replace($this->basePath, '', $this->normalizePath($path));
|
|
||||||
$relativePath = str_replace('.php', '', $relativePath);
|
|
||||||
$parts = explode('/', trim($relativePath, '/\\'));
|
|
||||||
$parts = array_values(array_filter($parts, fn(string $part) => $part !== ''));
|
|
||||||
$parts = array_map('ucfirst', $parts);
|
|
||||||
|
|
||||||
return implode('\\', $parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function optimizeWithOpcache(string $path): void
|
private function optimizeWithOpcache(string $path): void
|
||||||
{
|
{
|
||||||
if ($this->hasOpcache === null) {
|
if ($this->hasOpcache === null) {
|
||||||
@@ -403,7 +304,7 @@ class Scanner extends Component
|
|||||||
|
|
||||||
private function analyzeClassMethods(ReflectionClass $reflect, string $class): void
|
private function analyzeClassMethods(ReflectionClass $reflect, string $class): void
|
||||||
{
|
{
|
||||||
foreach ($reflect->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
|
foreach ($reflect->getMethods() as $method) {
|
||||||
if ($method->isStatic() || $method->getDeclaringClass()->getName() !== $class) {
|
if ($method->isStatic() || $method->getDeclaringClass()->getName() !== $class) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -422,7 +323,7 @@ class Scanner extends Component
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$instance = $attribute->newInstance();
|
$instance = $attribute->newInstance();
|
||||||
if (method_exists($instance, 'dispatch')) {
|
if ($instance instanceof InjectMethodInterface) {
|
||||||
$instance->dispatch($class, $method->getName());
|
$instance->dispatch($class, $method->getName());
|
||||||
}
|
}
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
@@ -561,16 +462,26 @@ class Scanner extends Component
|
|||||||
return array_map(fn($attr) => $attr->getName(), $reflect->getAttributes());
|
return array_map(fn($attr) => $attr->getName(), $reflect->getAttributes());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStats(): array
|
public function getStats(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'total_files' => count($this->files),
|
'total_files' => count($this->files),
|
||||||
'cached_mtimes' => count($this->fileMtimes),
|
'cached_mtimes' => count($this->fileMtimes),
|
||||||
'base_path' => $this->basePath,
|
'base_path' => $this->basePath,
|
||||||
'config' => $this->config,
|
'config' => $this->config,
|
||||||
'manifest_entries' => count($this->manifest->all()),
|
'manifest_entries' => count($this->manifest->all()),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回 Master 扫描产生的完整清单数据,供 Worker 轻量重建注解路由
|
||||||
|
* @return array{string: array{mtime: int, classes: string[]}}
|
||||||
|
*/
|
||||||
|
public function getManifestClasses(): array
|
||||||
|
{
|
||||||
|
return $this->manifest->all();
|
||||||
|
}
|
||||||
|
|
||||||
public function reset(): void
|
public function reset(): void
|
||||||
{
|
{
|
||||||
@@ -684,6 +595,9 @@ class Scanner extends Component
|
|||||||
if (method_exists($this->container, 'forgetClass')) {
|
if (method_exists($this->container, 'forgetClass')) {
|
||||||
$this->container->forgetClass($class);
|
$this->container->forgetClass($class);
|
||||||
}
|
}
|
||||||
|
if (class_exists(\Kiri\Router\Defer\DeferRegistry::class)) {
|
||||||
|
\Kiri\Router\Defer\DeferRegistry::removeClass($class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=8.4",
|
"php": ">=8.5",
|
||||||
"psr/container": "^2.0"
|
"psr/container": "^2.0"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|||||||
Reference in New Issue
Block a user