Skip to content

Commit

Permalink
add abstract empty command
Browse files Browse the repository at this point in the history
  • Loading branch information
juliangut committed Nov 9, 2018
1 parent 62c350b commit 3dbd887
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 17 deletions.
19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ require './vendor/autoload.php';

Commands are DTOs that carry all the information for an action to happen

You can create your own by implementing `Gears\CQRS\Command` or extend from `Gears\CQRS\AbstractCommand` which ensures command immutability and payload is composed only of **scalar values** which is a very interesting capability. AbstractCommand has a protected constructor forcing you to create a custom static named constructors
You can create your own by implementing `Gears\CQRS\Command` or extend from `Gears\CQRS\AbstractCommand` which ensures command immutability and payload is composed only of **scalar values** which is a very interesting capability. AbstractCommand has a protected constructor forcing you to create custom static named constructors

```php
use Gears\CQRS\AbstractCommand;
Expand All @@ -57,6 +57,19 @@ class CreateUserCommand extends AbstractCommand
}
```

In case of a command without any payload you could extend `Gears\CQRS\AbstractEmptyCommand`

```php
use Gears\CQRS\AbstractCommand;

class CreateUserCommand extends AbstractEmptyCommand
{
public static function instance(): self {
return new self();
}
}
```

#### Async commands

Having command assuring all of its payload is composed only of scalar values proves handy when you want to delegate command handling to a message queue system such as RabbitMQ, Gearman or Apache Kafka, serializing/deserializing scalar values is trivial in any format and language
Expand Down Expand Up @@ -112,15 +125,15 @@ class CreateUserCommandHandler extends AbstractCommandHandler
}
```

Have a look at [phpgears/dto](https://github.com/phpgears/dto) fo a better understanding of how commands and queries are built and how they hold their payload
Have a look at [phpgears/dto](https://github.com/phpgears/dto) fo a better understanding of how commands and queries are built out of DTOs and how they hold their payload

### Buses

Only `Gears\CQRS\CommandBus` and `Gears\CQRS\QueryBus` interfaces are provided, you can easily use any of the good bus libraries available out there by simply adding an adapter layer

#### Implementations

Available CQRS buses implementations
CQRS buses implementations currently available

* [phpgears/cqrs-tactician](https://github.com/phpgears/cqrs-tactician) uses League's Tactician

Expand Down
55 changes: 55 additions & 0 deletions src/AbstractEmptyCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

/*
* cqrs (https://github.com/phpgears/cqrs).
* CQRS base.
*
* @license MIT
* @link https://github.com/phpgears/cqrs
* @author Julián Gutiérrez <juliangut@gmail.com>
*/

declare(strict_types=1);

namespace Gears\CQRS;

use Gears\DTO\ScalarPayloadBehaviour;
use Gears\Immutability\ImmutabilityBehaviour;

/**
* Abstract empty immutable event.
*/
abstract class AbstractEmptyCommand implements Command
{
use ImmutabilityBehaviour, ScalarPayloadBehaviour {
ScalarPayloadBehaviour::__call insteadof ImmutabilityBehaviour;
}

/**
* AbstractEmptyCommand constructor.
*/
final protected function __construct()
{
$this->checkImmutability();
}

/**
* {@inheritdoc}
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
final public static function reconstitute(array $parameters)
{
return new static();
}

/**
* {@inheritdoc}
*
* @return string[]
*/
final protected function getAllowedInterfaces(): array
{
return [Command::class];
}
}
27 changes: 13 additions & 14 deletions tests/CQRS/AbstractCommandHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,43 +13,42 @@

namespace Gears\CQRS\Tests;

use Gears\CQRS\AbstractCommand;
use Gears\CQRS\Tests\Stub\AbstractCommandHandlerStub;
use Gears\CQRS\Tests\Stub\AbstractCommandStub;
use Gears\CQRS\Tests\Stub\AbstractEmptyCommandStub;
use PHPUnit\Framework\TestCase;

/**
* Abstract command handler test.
*/
class AbstractCommandHandlerTest extends TestCase
{
public function testHandling(): void
{
$handler = new AbstractCommandHandlerStub();
$handler->handle(AbstractCommandStub::instance());

$this->assertTrue(true);
}

/**
* @expectedException \Gears\CQRS\Exception\InvalidCommandException
* @expectedExceptionMessageRegExp /Command must be a .+\\AbstractCommandStub, .+ given/
*/
public function testInvalidCommandType(): void
{
/** @var AbstractCommand $command */
$command = $this->getMockBuilder(AbstractCommand::class)
->disableOriginalConstructor()
->getMock();
$handler = new AbstractCommandHandlerStub();
$handler->handle(AbstractEmptyCommandStub::instance());
}

public function testHandling(): void
{
$handler = new AbstractCommandHandlerStub();
$handler->handle($command);
$handler->handle(AbstractCommandStub::instance());

$this->assertTrue(true);
}

public function testReconstitute(): void
{
$command = AbstractCommandStub::reconstitute(['parameter' => 'one']);

$this->assertTrue($command->has('parameter'));

$emptyCommand = AbstractEmptyCommandStub::reconstitute(['parameter' => 'one']);

$this->assertFalse($emptyCommand->has('parameter'));
}
}
38 changes: 38 additions & 0 deletions tests/CQRS/Stub/AbstractEmptyCommandHandlerStub.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

/*
* cqrs (https://github.com/phpgears/cqrs).
* CQRS base.
*
* @license MIT
* @link https://github.com/phpgears/cqrs
* @author Julián Gutiérrez <juliangut@gmail.com>
*/

declare(strict_types=1);

namespace Gears\CQRS\Tests\Stub;

use Gears\CQRS\AbstractCommandHandler;
use Gears\CQRS\Command;

/**
* Abstract command handler stub class.
*/
class AbstractEmptyCommandHandlerStub extends AbstractCommandHandler
{
/**
* {@inheritdoc}
*/
protected function getSupportedCommandType(): string
{
return AbstractEmptyCommandStub::class;
}

/**
* {@inheritdoc}
*/
protected function handleCommand(Command $command): void
{
}
}
32 changes: 32 additions & 0 deletions tests/CQRS/Stub/AbstractEmptyCommandStub.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/*
* cqrs (https://github.com/phpgears/cqrs).
* CQRS base.
*
* @license MIT
* @link https://github.com/phpgears/cqrs
* @author Julián Gutiérrez <juliangut@gmail.com>
*/

declare(strict_types=1);

namespace Gears\CQRS\Tests\Stub;

use Gears\CQRS\AbstractEmptyCommand;

/**
* Abstract empty command stub class.
*/
class AbstractEmptyCommandStub extends AbstractEmptyCommand
{
/**
* Instantiate command.
*
* @return self
*/
public static function instance(): self
{
return new self();
}
}

0 comments on commit 3dbd887

Please sign in to comment.