Skip to content

Commit

Permalink
Merge pull request #1111: [Interceptors] Add PipelineBuilder
Browse files Browse the repository at this point in the history
  • Loading branch information
roxblnfk authored Jun 26, 2024
2 parents 9724731 + 1d22a09 commit aae7791
Show file tree
Hide file tree
Showing 26 changed files with 417 additions and 84 deletions.
7 changes: 4 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@
},
"require-dev": {
"aws/aws-sdk-php": "^3.270",
"buggregator/trap": "^1.10",
"doctrine/annotations": "^2.0",
"google/protobuf": "^3.25",
"guzzlehttp/psr7": "^1.7|^2.0",
"jetbrains/phpstorm-attributes": "^1.0",
"league/flysystem-async-aws-s3": "^2.0 || ^3.0",
Expand All @@ -138,10 +141,8 @@
"spiral/nyholm-bridge": "^1.2",
"spiral/testing": "^2.8",
"spiral/validator": "^1.3",
"google/protobuf": "^3.25",
"symplify/monorepo-builder": "^10.2.7",
"vimeo/psalm": "^5.9",
"doctrine/annotations": "^2.0"
"vimeo/psalm": "^5.9"
},
"autoload-dev": {
"psr-4": {
Expand Down
6 changes: 3 additions & 3 deletions src/Console/src/Attribute/Option.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
final class Option
{
/**
* @param ?non-empty-string $name Option name. Property name by default
* @param non-empty-string|null $name Option name. Property name by default
* @param non-empty-string|array|null $shortcut Option shortcut
* @param ?non-empty-string $description Option description
* @param ?positive-int $mode Option mode, {@see InputOption} constants
* @param non-empty-string|null $description Option description
* @param int<0, 31>|null $mode Option mode, {@see InputOption} constants
* @param \Closure|array $suggestedValues Option suggested values
*/
public function __construct(
Expand Down
9 changes: 4 additions & 5 deletions src/Console/src/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,12 @@
use Spiral\Console\Event\CommandFinished;
use Spiral\Console\Event\CommandStarting;
use Spiral\Console\Traits\HelpersTrait;
use Spiral\Core\ContainerScope;
use Spiral\Core\CoreInterceptorInterface;
use Spiral\Core\CoreInterface;
use Spiral\Core\Exception\ScopeException;
use Spiral\Core\InvokerInterface;
use Spiral\Core\Scope;
use Spiral\Core\ScopeInterface;
use Spiral\Core\InterceptorPipeline;
use Spiral\Events\EventDispatcherAwareInterface;
use Spiral\Interceptors\Context\CallContext;
use Spiral\Interceptors\Context\Target;
Expand Down Expand Up @@ -133,9 +132,9 @@ function () use ($method) {
*/
protected function buildCore(): CoreInterface|HandlerInterface
{
return ContainerScope::getContainer()
->get(CommandCoreFactory::class)
->make($this->interceptors, $this->eventDispatcher);
/** @var InvokerInterface $invoker */
$invoker = $this->container->get(InvokerInterface::class);
return $invoker->invoke([CommandCoreFactory::class, 'make'], [$this->interceptors, $this->eventDispatcher]);
}

protected function prepareInput(InputInterface $input): InputInterface
Expand Down
10 changes: 9 additions & 1 deletion src/Console/src/CommandCore.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
use Spiral\Core\Attribute\Scope as ScopeAttribute;
use Spiral\Core\CoreInterface;
use Spiral\Core\InvokerInterface;
use Spiral\Interceptors\Context\CallContext;
use Spiral\Interceptors\HandlerInterface;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

#[ScopeAttribute('console.command')]
final class CommandCore implements CoreInterface
final class CommandCore implements CoreInterface, HandlerInterface
{
public function __construct(
private readonly InvokerInterface $invoker,
Expand All @@ -27,4 +29,10 @@ public function callAction(string $controller, string $action, array $parameters

return (int)$this->invoker->invoke([$command, $action]);
}

public function handle(CallContext $context): int
{
$callable = $context->getTarget()->getCallable() ?? throw new \RuntimeException('Command action not found');
return (int)$this->invoker->invoke($callable, $context->getArguments());
}
}
17 changes: 11 additions & 6 deletions src/Console/src/CommandCoreFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
use Psr\EventDispatcher\EventDispatcherInterface;
use Spiral\Console\Interceptor\AttributeInterceptor;
use Spiral\Core\Attribute\Scope;
use Spiral\Core\CompatiblePipelineBuilder;
use Spiral\Core\CoreInterceptorInterface;
use Spiral\Core\CoreInterface;
use Spiral\Core\InterceptorPipeline;
use Spiral\Interceptors\HandlerInterface;
use Spiral\Interceptors\InterceptorInterface;
use Spiral\Interceptors\PipelineBuilderInterface;

#[Scope('console.command')]
final class CommandCoreFactory
Expand All @@ -28,17 +29,21 @@ public function __construct(
public function make(
array $interceptors,
?EventDispatcherInterface $eventDispatcher = null,
?PipelineBuilderInterface $pipelineBuilder = null,
): CoreInterface|HandlerInterface {
/** @var CommandCore $core */
$core = $this->container->get(CommandCore::class);
$pipelineBuilder ??= new CompatiblePipelineBuilder($eventDispatcher);

$interceptableCore = (new InterceptorPipeline($eventDispatcher))->withCore($core);

$resolved = [];
foreach ($interceptors as $interceptor) {
$interceptableCore->addInterceptor($this->container->get($interceptor));
$resolved[] = $this->container->get($interceptor);
}
$interceptableCore->addInterceptor($this->container->get(AttributeInterceptor::class));

return $interceptableCore;
$resolved[] = $this->container->get(AttributeInterceptor::class);

return $pipelineBuilder
->withInterceptors(...$resolved)
->build($core);
}
}
2 changes: 1 addition & 1 deletion src/Console/src/Configurator/Attribute/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ private function getPropertyType(\ReflectionProperty $property): \ReflectionName
}

/**
* @return positive-int
* @return int<0, 31>
*/
private function guessOptionMode(\ReflectionNamedType $type, \ReflectionProperty $property): int
{
Expand Down
12 changes: 5 additions & 7 deletions src/Events/src/Bootloader/EventsBootloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
use Spiral\Bootloader\Attributes\AttributesBootloader;
use Spiral\Config\ConfiguratorInterface;
use Spiral\Config\Patch\Append;
use Spiral\Core\CompatiblePipelineBuilder;
use Spiral\Core\Container;
use Spiral\Core\Container\Autowire;
use Spiral\Core\CoreInterceptorInterface;
use Spiral\Core\FactoryInterface;
use Spiral\Core\InterceptorPipeline;
use Spiral\Events\AutowireListenerFactory;
use Spiral\Events\Config\EventsConfig;
use Spiral\Events\EventDispatcher;
Expand Down Expand Up @@ -107,15 +107,13 @@ private function initEventDispatcher(
Container $container,
FactoryInterface $factory
): void {
$pipeline = (new InterceptorPipeline())->withCore($core);

$builder = new CompatiblePipelineBuilder();
$list = [];
foreach ($config->getInterceptors() as $interceptor) {
$interceptor = $this->autowire($interceptor, $container, $factory);

\assert($interceptor instanceof CoreInterceptorInterface || $interceptor instanceof InterceptorInterface);
$pipeline->addInterceptor($interceptor);
$list[] = $this->autowire($interceptor, $container, $factory);
}

$pipeline = $builder->withInterceptors(...$list)->build($core);
$container->removeBinding(EventDispatcherInterface::class);
$container->bindSingleton(EventDispatcherInterface::class, new EventDispatcher($pipeline));
}
Expand Down
6 changes: 3 additions & 3 deletions src/Events/src/EventDispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ final class EventDispatcher implements EventDispatcherInterface
{
private readonly bool $isLegacy;
public function __construct(
private readonly HandlerInterface|CoreInterface $core
private readonly HandlerInterface|CoreInterface $core,
) {
$this->isLegacy = !$core instanceof HandlerInterface;
}

public function dispatch(object $event): object
{
return $this->isLegacy
? $this->core->callAction($event::class, 'dispatch', ['event' => $event])
? $this->core->callAction(EventDispatcherInterface::class, 'dispatch', ['event' => $event])
: $this->core->handle(new CallContext(
Target::fromPair($event, 'dispatch'),
Target::fromPair(EventDispatcherInterface::class, 'dispatch'),
['event' => $event],
));
}
Expand Down
9 changes: 8 additions & 1 deletion src/Events/src/Interceptor/Core.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@

use Psr\EventDispatcher\EventDispatcherInterface;
use Spiral\Core\CoreInterface;
use Spiral\Interceptors\Context\CallContext;
use Spiral\Interceptors\HandlerInterface;

/**
* @psalm-type TParameters = array{event: object}
*/
final class Core implements CoreInterface
final class Core implements CoreInterface, HandlerInterface
{
public function __construct(
private readonly EventDispatcherInterface $dispatcher
Expand All @@ -27,4 +29,9 @@ public function callAction(string $controller, string $action, array $parameters

return $this->dispatcher->dispatch($parameters['event']);
}

public function handle(CallContext $context): mixed
{
return $this->dispatcher->dispatch($context->getArguments()['event']);
}
}
3 changes: 2 additions & 1 deletion src/Events/tests/EventDispatcherTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Mockery as m;
use PHPUnit\Framework\TestCase;
use Psr\EventDispatcher\EventDispatcherInterface;
use Spiral\Core\CoreInterface;
use Spiral\Events\EventDispatcher;

Expand All @@ -19,7 +20,7 @@ public function testDispatch(): void
$core
->shouldReceive('callAction')
->once()
->with($event::class, 'dispatch', ['event' => $event])
->with(EventDispatcherInterface::class, 'dispatch', ['event' => $event])
->andReturn($event);

$dispatcher = new EventDispatcher($core);
Expand Down
17 changes: 9 additions & 8 deletions src/Framework/Bootloader/DomainBootloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
use Psr\Container\ContainerInterface;
use Psr\EventDispatcher\EventDispatcherInterface;
use Spiral\Boot\Bootloader\Bootloader;
use Spiral\Core\CompatiblePipelineBuilder;
use Spiral\Core\Core;
use Spiral\Core\CoreInterceptorInterface;
use Spiral\Core\CoreInterface;
use Spiral\Core\InterceptorPipeline;
use Spiral\Interceptors\HandlerInterface;
use Spiral\Interceptors\InterceptorInterface;

Expand All @@ -29,17 +29,18 @@ protected static function domainCore(
ContainerInterface $container,
?EventDispatcherInterface $dispatcher = null
): CoreInterface&HandlerInterface {
$pipeline = (new InterceptorPipeline($dispatcher))->withCore($core);
$builder = new CompatiblePipelineBuilder($dispatcher);

$list = [];
foreach (static::defineInterceptors() as $interceptor) {
if (!$interceptor instanceof CoreInterceptorInterface && !$interceptor instanceof InterceptorInterface) {
$interceptor = $container->get($interceptor);
}

$pipeline->addInterceptor($interceptor);
$list[] = $interceptor instanceof CoreInterceptorInterface || $interceptor instanceof InterceptorInterface
? $interceptor
: $container->get($interceptor);
}

return $pipeline;
return $builder
->withInterceptors(...$list)
->build($core);
}

/**
Expand Down
15 changes: 11 additions & 4 deletions src/Framework/Bootloader/Security/FiltersBootloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
use Spiral\Config\Patch\Append;
use Spiral\Core\Attribute\Singleton;
use Spiral\Core\BinderInterface;
use Spiral\Core\CompatiblePipelineBuilder;
use Spiral\Core\Config\Proxy;
use Spiral\Core\Container;
use Spiral\Core\CoreInterceptorInterface;
use Spiral\Core\InterceptorPipeline;
use Spiral\Filter\InputScope;
use Spiral\Filters\Config\FiltersConfig;
use Spiral\Filters\Model\FilterBag;
Expand All @@ -32,6 +32,7 @@
use Spiral\Framework\Spiral;
use Spiral\Http\Config\HttpConfig;
use Spiral\Http\Request\InputManager;
use Spiral\Interceptors\PipelineBuilderInterface;

/**
* @implements Container\InjectorInterface<FilterInterface>
Expand Down Expand Up @@ -109,14 +110,20 @@ public function createInjection(\ReflectionClass $class, string $context = null)
private function initFilterProvider(
Container $container,
FiltersConfig $config,
?EventDispatcherInterface $dispatcher = null
?EventDispatcherInterface $dispatcher = null,
?PipelineBuilderInterface $builder = null,
): FilterProvider {
$pipeline = (new InterceptorPipeline($dispatcher))->withHandler(new Core());
$builder ??= new CompatiblePipelineBuilder($dispatcher);

$list = [];
foreach ($config->getInterceptors() as $interceptor) {
$pipeline->addInterceptor($container->get($interceptor));
$list[] = $container->get($interceptor);
}

$pipeline = $builder
->withInterceptors(...$list)
->build(new Core());

return new FilterProvider($container, $container, $pipeline);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Framework/Framework/Spiral.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ enum Spiral: string
case Centrifugo = 'centrifugo';
case CentrifugoRequest = 'centrifugo.request';
case Tcp = 'tcp';
case TcpPacket = 'tcp.packet';
case TcpRequest = 'tcp.request';
case Console = 'console';
case ConsoleCommand = 'console.command';
}
48 changes: 48 additions & 0 deletions src/Hmvc/src/Core/CompatiblePipelineBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

namespace Spiral\Core;

use Psr\EventDispatcher\EventDispatcherInterface;
use Spiral\Interceptors\HandlerInterface;
use Spiral\Interceptors\InterceptorInterface;
use Spiral\Interceptors\PipelineBuilderInterface;

/**
* Accepts {@see InterceptorInterface} and {@see CoreInterface} instances to build a pipeline.
*
* @deprecated Use {@see PipelineBuilder} instead.
*/
class CompatiblePipelineBuilder implements PipelineBuilderInterface
{
private InterceptorPipeline $pipeline;

public function __construct(?EventDispatcherInterface $dispatcher = null)
{
$this->pipeline = new InterceptorPipeline($dispatcher);
}

public function __clone()
{
$this->pipeline = clone $this->pipeline;
}

public function withInterceptors(CoreInterceptorInterface|InterceptorInterface ...$interceptors): static
{
$clone = clone $this;
foreach ($interceptors as $interceptor) {
$clone->pipeline->addInterceptor($interceptor);
}

return $clone;
}

public function build(HandlerInterface|CoreInterface $last): InterceptorPipeline
{
/** @psalm-suppress InvalidArgument */
return $last instanceof HandlerInterface
? $this->pipeline->withHandler($last)
: $this->pipeline->withCore($last);
}
}
6 changes: 6 additions & 0 deletions src/Hmvc/src/Core/InterceptorPipeline.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ public function addInterceptor(CoreInterceptorInterface|InterceptorInterface $in
$this->interceptors[] = $interceptor;
}

/**
* @psalm-immutable
*/
public function withCore(CoreInterface $core): self
{
$pipeline = clone $this;
Expand All @@ -46,6 +49,9 @@ public function withCore(CoreInterface $core): self
return $pipeline;
}

/**
* @psalm-immutable
*/
public function withHandler(HandlerInterface $handler): self
{
$pipeline = clone $this;
Expand Down
Loading

0 comments on commit aae7791

Please sign in to comment.