Skip to content

Commit

Permalink
Merge pull request #11 from arcanum-org/conveyor
Browse files Browse the repository at this point in the history
Finished Conveyor implementation.
  • Loading branch information
young-steveo committed Jun 7, 2023
2 parents 841e095 + abeff3a commit 0a721f8
Show file tree
Hide file tree
Showing 30 changed files with 650 additions and 261 deletions.
56 changes: 0 additions & 56 deletions src/Conveyor/DTO.php

This file was deleted.

23 changes: 23 additions & 0 deletions src/Conveyor/Middleware/FinalFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Arcanum\Conveyor\Middleware;

use Arcanum\Flow\Continuum\Progression;

/**
* FinalFilter only allows objects that have been declared final.
*/
final class FinalFilter implements Progression
{
public function __invoke(object $payload, callable $next): void
{
$image = new \ReflectionClass($payload);
if (!$image->isFinal()) {
$name = $image->getName();
throw new InvalidDTO("$name is not final.");
}
$next();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Arcanum\Conveyor;
namespace Arcanum\Conveyor\Middleware;

final class InvalidDTO extends \InvalidArgumentException
{
Expand Down
28 changes: 28 additions & 0 deletions src/Conveyor/Middleware/NonPublicMethodFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Arcanum\Conveyor\Middleware;

use Arcanum\Flow\Continuum\Progression;

/**
* NonPublicMethodFilter only allows objects that have zero public instance methods.
*
* Public static methods are allowed by this filter.
*/
final class NonPublicMethodFilter implements Progression
{
public function __invoke(object $payload, callable $next): void
{
$image = new \ReflectionClass($payload);
$methods = $image->getMethods(\ReflectionMethod::IS_PUBLIC);
foreach ($methods as $method) {
if (!$method->isConstructor() && !$method->isStatic()) {
$name = $image->getName();
throw new InvalidDTO("$name has non-static methods that are public.");
}
}
$next();
}
}
24 changes: 24 additions & 0 deletions src/Conveyor/Middleware/NonStaticPropertyFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Arcanum\Conveyor\Middleware;

use Arcanum\Flow\Continuum\Progression;

/**
* NonStaticPropertyFilter only allows objects that have zero static properties.
*/
final class NonStaticPropertyFilter implements Progression
{
public function __invoke(object $payload, callable $next): void
{
$image = new \ReflectionClass($payload);
$properties = $image->getProperties(\ReflectionProperty::IS_STATIC);
if (!empty($properties)) {
$name = $image->getName();
throw new InvalidDTO("$name has static properties.");
}
$next();
}
}
28 changes: 28 additions & 0 deletions src/Conveyor/Middleware/PublicPropertyFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Arcanum\Conveyor\Middleware;

use Arcanum\Flow\Continuum\Progression;

/**
* PublicPropertyFilter only allows objects that have zero or more public
* properties.
*
* If the object has any private or protected properties, PublicPropertyFilter
* will throw an InvalidDTO exception.
*/
final class PublicPropertyFilter implements Progression
{
public function __invoke(object $payload, callable $next): void
{
$image = new \ReflectionClass($payload);
$properties = $image->getProperties(\ReflectionProperty::IS_PRIVATE | \ReflectionProperty::IS_PROTECTED);
if (!empty($properties)) {
$name = $image->getName();
throw new InvalidDTO("$name has private or protected properties.");
}
$next();
}
}
25 changes: 25 additions & 0 deletions src/Conveyor/Middleware/ReadOnlyPropertyFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Arcanum\Conveyor\Middleware;

use Arcanum\Flow\Continuum\Progression;

/**
* ReadOnlyPropertyFilter only allows objects that have readonly properties.
*/
final class ReadOnlyPropertyFilter implements Progression
{
public function __invoke(object $payload, callable $next): void
{
$image = new \ReflectionClass($payload);
$readonly = $image->getProperties(\ReflectionProperty::IS_READONLY);
$allProperties = $image->getProperties();
if (count($allProperties) > count($readonly)) {
$name = $image->getName();
throw new InvalidDTO("$name has properties that are not readonly.");
}
$next();
}
}
83 changes: 83 additions & 0 deletions src/Conveyor/MiddlewareBus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

declare(strict_types=1);

namespace Arcanum\Conveyor;

use Psr\Container\ContainerInterface;
use Arcanum\Flow\Continuum\Continuum;
use Arcanum\Flow\Continuum\Continuation;
use Arcanum\Flow\Continuum\Progression;
use Arcanum\Flow\Pipeline\Pipeline;

class MiddlewareBus implements Bus
{
/**
* MiddlewareBus
*/
public function __construct(
protected ContainerInterface $container,
protected Continuation $dispatchFlow = new Continuum(),
protected Continuation $responseFlow = new Continuum()
) {
}

/**
* Add dispatch middleware to the bus.
*/
public function before(Progression ...$middleware): void
{
foreach ($middleware as $layer) {
$this->dispatchFlow = $this->dispatchFlow->add($layer);
}
}

/**
* Add response middleware to the bus.
*/
public function after(Progression ...$middleware): void
{
foreach ($middleware as $layer) {
$this->responseFlow = $this->responseFlow->add($layer);
}
}


/**
* Dispatch an object to a handler.
*/
public function dispatch(object $object): object
{
return (new Pipeline())
->pipe($this->dispatchFlow)
->pipe(function (object $object) {
return $this->handlerFor($object)($object) ?? new EmptyDTO();
})
->pipe($this->responseFlow)
->send($object);
}

/**
* Get the handler for an object.
*
* SwiftBus assumes that the handler is a callable.
*/
protected function handlerFor(object $object): callable
{
/** @var callable */
return $this->container->get($this->handlerNameFor($object));
}

/**
* Get the handler name for an object.
*
* This is the class name of the object with the suffix "Handler".
*
* @return class-string
*/
protected function handlerNameFor(object $object): string
{
/** @var class-string */
return get_class($object) . 'Handler';
}
}
51 changes: 0 additions & 51 deletions src/Conveyor/StrictBus.php

This file was deleted.

46 changes: 0 additions & 46 deletions src/Conveyor/SwiftBus.php

This file was deleted.

13 changes: 0 additions & 13 deletions src/Conveyor/Validator.php

This file was deleted.

Loading

0 comments on commit 0a721f8

Please sign in to comment.