Some checks failed
Deploy Application / deploy (push) Has been cancelled
164 lines
6.1 KiB
PHP
164 lines
6.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Framework\Attributes\Execution;
|
|
|
|
use App\Framework\Attributes\Execution\AttributeExecutionContext;
|
|
use App\Framework\Attributes\Execution\AttributeRunner;
|
|
use App\Framework\Attributes\Execution\CallbackExecutor;
|
|
use App\Framework\Attributes\Execution\CallbackMetadataExtractor;
|
|
use App\Framework\Attributes\Execution\Handlers\PermissionGuard;
|
|
use App\Framework\Attributes\Execution\Policies\Policies;
|
|
use App\Framework\Attributes\Execution\Policies\UserPolicies;
|
|
use App\Framework\Attributes\Guard;
|
|
use App\Framework\Core\ValueObjects\ClassName;
|
|
use App\Framework\DI\Container;
|
|
use App\Framework\DI\DefaultContainer;
|
|
use App\Framework\DI\MethodInvoker;
|
|
use App\Framework\Discovery\Results\AttributeRegistry;
|
|
use App\Framework\Discovery\Results\DiscoveryRegistry;
|
|
use App\Framework\Discovery\ValueObjects\AttributeTarget;
|
|
use App\Framework\Discovery\ValueObjects\DiscoveredAttribute;
|
|
use App\Framework\Reflection\SimpleReflectionService;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
final class AttributeExecutionIntegrationTest extends TestCase
|
|
{
|
|
private Container $container;
|
|
private DiscoveryRegistry $discoveryRegistry;
|
|
private AttributeRunner $runner;
|
|
private CallbackMetadataExtractor $extractor;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->container = new DefaultContainer();
|
|
$this->container->instance(MethodInvoker::class, new MethodInvoker(
|
|
$this->container,
|
|
new SimpleReflectionService()
|
|
));
|
|
|
|
$this->discoveryRegistry = new DiscoveryRegistry(
|
|
attributes: new AttributeRegistry()
|
|
);
|
|
|
|
$callbackExecutor = new CallbackExecutor($this->container);
|
|
$this->runner = new AttributeRunner(
|
|
discoveryRegistry: $this->discoveryRegistry,
|
|
container: $this->container,
|
|
callbackExecutor: $callbackExecutor
|
|
);
|
|
|
|
$this->extractor = new CallbackMetadataExtractor();
|
|
}
|
|
|
|
public function testPatternAHandlerWorkflow(): void
|
|
{
|
|
// Pattern A: Handler-Klasse
|
|
$metadata = $this->extractor->extract([PermissionGuard::class, [['edit_post']]]);
|
|
|
|
$this->assertEquals(\App\Framework\Attributes\Execution\CallbackType::HANDLER, $metadata->callbackType);
|
|
$this->assertEquals(PermissionGuard::class, $metadata->class);
|
|
$this->assertTrue($metadata->isCacheable());
|
|
|
|
// Test Serialisierung
|
|
$array = $metadata->toArray();
|
|
$restored = \App\Framework\Attributes\Execution\CallbackMetadata::fromArray($array);
|
|
$this->assertEquals($metadata->callbackType, $restored->callbackType);
|
|
}
|
|
|
|
public function testPatternBStaticMethodWorkflow(): void
|
|
{
|
|
// Pattern B: First-Class Callable
|
|
$metadata = $this->extractor->extract([UserPolicies::class, 'isAdmin']);
|
|
|
|
$this->assertEquals(\App\Framework\Attributes\Execution\CallbackType::STATIC_METHOD, $metadata->callbackType);
|
|
$this->assertEquals(UserPolicies::class, $metadata->class);
|
|
$this->assertEquals('isAdmin', $metadata->method);
|
|
$this->assertTrue($metadata->isCacheable());
|
|
|
|
// Test Ausführung
|
|
$context = AttributeExecutionContext::forClass(
|
|
$this->container,
|
|
ClassName::create('TestClass')
|
|
);
|
|
|
|
$executor = new CallbackExecutor($this->container);
|
|
$result = $executor->execute($metadata, $context);
|
|
|
|
$this->assertIsBool($result);
|
|
}
|
|
|
|
public function testPatternCFactoryWorkflow(): void
|
|
{
|
|
// Pattern C: Closure-Factory
|
|
// Für Factory-Pattern müssen wir die Factory-Methode explizit identifizieren
|
|
$metadata = $this->extractor->extractFromFactoryCall(
|
|
Policies::class,
|
|
'requirePermission',
|
|
['edit_post']
|
|
);
|
|
|
|
$this->assertEquals(\App\Framework\Attributes\Execution\CallbackType::FACTORY, $metadata->callbackType);
|
|
$this->assertEquals(Policies::class, $metadata->class);
|
|
$this->assertEquals('requirePermission', $metadata->method);
|
|
$this->assertEquals(['edit_post'], $metadata->args);
|
|
$this->assertTrue($metadata->isCacheable());
|
|
|
|
// Test Ausführung
|
|
$context = AttributeExecutionContext::forClass(
|
|
$this->container,
|
|
ClassName::create('TestClass')
|
|
);
|
|
|
|
$executor = new CallbackExecutor($this->container);
|
|
$closure = $executor->execute($metadata, $context);
|
|
|
|
$this->assertInstanceOf(\Closure::class, $closure);
|
|
|
|
$result = $closure($context);
|
|
$this->assertIsBool($result);
|
|
}
|
|
|
|
public function testDiscoveredAttributeCallbackMetadataExtraction(): void
|
|
{
|
|
$discovered = new DiscoveredAttribute(
|
|
className: ClassName::create('TestClass'),
|
|
attributeClass: Guard::class,
|
|
target: AttributeTarget::TARGET_CLASS,
|
|
arguments: [PermissionGuard::class, [['edit_post']]]
|
|
);
|
|
|
|
$metadata = $discovered->getCallbackMetadata();
|
|
|
|
$this->assertNotNull($metadata);
|
|
$this->assertEquals(\App\Framework\Attributes\Execution\CallbackType::HANDLER, $metadata->callbackType);
|
|
}
|
|
|
|
public function testCacheSerializationRoundTrip(): void
|
|
{
|
|
$discovered = new DiscoveredAttribute(
|
|
className: ClassName::create('TestClass'),
|
|
attributeClass: Guard::class,
|
|
target: AttributeTarget::TARGET_CLASS,
|
|
arguments: [PermissionGuard::class, [['edit_post']]]
|
|
);
|
|
|
|
// Serialisiere
|
|
$array = $discovered->toArray();
|
|
|
|
// Deserialisiere
|
|
$restored = DiscoveredAttribute::fromArray($array);
|
|
|
|
// Prüfe dass Callback-Metadata erhalten bleibt
|
|
$originalMetadata = $discovered->getCallbackMetadata();
|
|
$restoredMetadata = $restored->getCallbackMetadata();
|
|
|
|
$this->assertNotNull($originalMetadata);
|
|
$this->assertNotNull($restoredMetadata);
|
|
$this->assertEquals($originalMetadata->callbackType, $restoredMetadata->callbackType);
|
|
$this->assertEquals($originalMetadata->class, $restoredMetadata->class);
|
|
}
|
|
}
|
|
|