Refactor test structure and update paths for improved organization

This commit is contained in:
crazywhalecc
2025-12-10 11:15:44 +08:00
parent 78375632b4
commit bde1440617
43 changed files with 4396 additions and 2941 deletions

View File

@@ -352,8 +352,6 @@ class ArtifactExtractor
* @param string $name Artifact name (for error messages)
* @param string $source_file Path to the source file or directory
* @param string $cache_type Cache type: archive, git, local
*
* @throws WrongUsageException if source file does not exist
*/
protected function validateSourceFile(string $name, string $source_file, string $cache_type): void
{

View File

@@ -35,8 +35,6 @@ class ApplicationContext
* @param array $options Initialization options
* - 'debug': Enable debug mode (disables compilation)
* - 'definitions': Additional container definitions
*
* @throws \RuntimeException If already initialized
*/
public static function initialize(array $options = []): Container
{
@@ -60,7 +58,8 @@ class ApplicationContext
self::$debug = $options['debug'] ?? false;
self::$container = $builder->build();
self::$invoker = new CallbackInvoker(self::$container);
// Get invoker from container to ensure singleton consistency
self::$invoker = self::$container->get(CallbackInvoker::class);
return self::$container;
}
@@ -126,7 +125,8 @@ class ApplicationContext
public static function getInvoker(): CallbackInvoker
{
if (self::$invoker === null) {
self::$invoker = new CallbackInvoker(self::getContainer());
// Get from container to ensure singleton consistency
self::$invoker = self::getContainer()->get(CallbackInvoker::class);
}
return self::$invoker;
}
@@ -139,14 +139,18 @@ class ApplicationContext
*/
public static function invoke(callable $callback, array $context = []): mixed
{
logger()->debug('[INVOKE] ' . (is_array($callback) ? (is_object($callback[0]) ? get_class($callback[0]) : $callback[0]) . '::' . $callback[1] : (is_string($callback) ? $callback : 'Closure')));
if (function_exists('logger')) {
logger()->debug('[INVOKE] ' . (is_array($callback) ? (is_object($callback[0]) ? get_class($callback[0]) : $callback[0]) . '::' . $callback[1] : (is_string($callback) ? $callback : 'Closure')));
}
// get if callback has attribute PatchDescription
$ref = new \ReflectionFunction(\Closure::fromCallable($callback));
$attributes = $ref->getAttributes(PatchDescription::class);
foreach ($attributes as $attribute) {
$attrInstance = $attribute->newInstance();
logger()->info(ConsoleColor::magenta('[PATCH]') . ConsoleColor::green(" {$attrInstance->description}"));
if (function_exists('logger')) {
logger()->info(ConsoleColor::magenta('[PATCH]') . ConsoleColor::green(" {$attrInstance->description}"));
}
}
return self::getInvoker()->invoke($callback, $context);
}

View File

@@ -5,12 +5,13 @@ declare(strict_types=1);
namespace StaticPHP\DI;
use DI\Container;
use StaticPHP\Exception\SPCInternalException;
/**
* CallbackInvoker is responsible for invoking callbacks with automatic dependency injection.
* It supports context-based parameter resolution, allowing temporary bindings without polluting the container.
*/
class CallbackInvoker
readonly class CallbackInvoker
{
public function __construct(
private Container $container
@@ -34,8 +35,6 @@ class CallbackInvoker
* @param array $context Context parameters (type => value or name => value)
*
* @return mixed The return value of the callback
*
* @throws \RuntimeException If a required parameter cannot be resolved
*/
public function invoke(callable $callback, array $context = []): mixed
{
@@ -64,8 +63,13 @@ class CallbackInvoker
// 3. Look up in container by type
if ($typeName !== null && !$this->isBuiltinType($typeName) && $this->container->has($typeName)) {
$args[] = $this->container->get($typeName);
continue;
try {
$args[] = $this->container->get($typeName);
continue;
} catch (\Throwable $e) {
// Container failed to resolve (e.g., missing constructor params)
// Fall through to try default value or nullable
}
}
// 4. Use default value if available
@@ -81,7 +85,7 @@ class CallbackInvoker
}
// Cannot resolve parameter
throw new \RuntimeException(
throw new SPCInternalException(
"Cannot resolve parameter '{$paramName}'" .
($typeName ? " of type '{$typeName}'" : '') .
' for callback invocation'
@@ -120,19 +124,20 @@ class CallbackInvoker
// If value is an object, add mappings for all parent classes and interfaces
if (is_object($value)) {
$reflection = new \ReflectionClass($value);
$originalReflection = new \ReflectionClass($value);
// Add concrete class
$expanded[$reflection->getName()] = $value;
$expanded[$originalReflection->getName()] = $value;
// Add all parent classes
$reflection = $originalReflection;
while ($parent = $reflection->getParentClass()) {
$expanded[$parent->getName()] = $value;
$reflection = $parent;
}
// Add all interfaces
$interfaces = (new \ReflectionClass($value))->getInterfaceNames();
// Add all interfaces - reuse original reflection
$interfaces = $originalReflection->getInterfaceNames();
foreach ($interfaces as $interface) {
$expanded[$interface] = $value;
}

View File

@@ -404,8 +404,6 @@ class PackageInstaller
/**
* Validate that a package has required artifacts.
*
* @throws WrongUsageException if target/library package has no source or platform binary
*/
private function validatePackageArtifact(Package $package): void
{

View File

@@ -25,7 +25,7 @@ class Registry
*/
public static function loadRegistry(string $registry_file, bool $auto_require = true): void
{
$yaml = file_get_contents($registry_file);
$yaml = @file_get_contents($registry_file);
if ($yaml === false) {
throw new RegistryException("Failed to read registry file: {$registry_file}");
}