Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce Flavours #108

Merged
merged 9 commits into from
Nov 16, 2018
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"bookdown/bookdown": "1.x-dev",
"webuni/commonmark-table-extension": "^0.6.1",
"webuni/commonmark-attributes-extension": "^0.5.0",
"prooph/php-cs-fixer-config": "^0.1.1",
"prooph/php-cs-fixer-config": "^0.2",
"satooshi/php-coveralls": "^1.0",
"malukenho/docheader": "^0.1.4"
},
Expand Down
22 changes: 22 additions & 0 deletions examples/CustomMessages/Aggregate/Aggregate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php
/**
* This file is part of the proophsoftware/event-machine.
* (c) 2017-2018 prooph software GmbH <contact@prooph.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ProophExample\CustomMessages\Aggregate;

final class Aggregate
{
const USER = 'User';

private function __construct()
{
//static class only
}
}
96 changes: 96 additions & 0 deletions examples/CustomMessages/Aggregate/UserDescription.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php
/**
* This file is part of the proophsoftware/event-machine.
* (c) 2017-2018 prooph software GmbH <contact@prooph.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ProophExample\CustomMessages\Aggregate;

use Prooph\EventMachine\EventMachine;
use Prooph\EventMachine\EventMachineDescription;
use ProophExample\CustomMessages\Api\Command;
use ProophExample\CustomMessages\Api\Event;
use ProophExample\CustomMessages\Command\ChangeUsername;
use ProophExample\CustomMessages\Command\RegisterUser;
use ProophExample\CustomMessages\Event\UsernameChanged;
use ProophExample\CustomMessages\Event\UserRegistered;

/**
* Class UserDescription
*
* Tell EventMachine how to handle commands with aggregates, which events are yielded by the handle methods
* and how to apply the yielded events to the aggregate state.
*
* Please note:
* UserDescription uses closures. It is the fastest and most readable way of describing
* aggregate behaviour BUT closures cannot be serialized/cached.
* So the closure style is useful for learning and prototyping but if you want to use Event Machine for
* production, you should consider using a cacheable description like illustrated with CacheableUserDescription.
* Also see EventMachine::cacheableConfig() which throws an exception if it detects usage of closure
* The returned array can be used to call EventMachine::fromCachedConfig(). You can json_encode the config and store it
* in a json file.
*
* @package ProophExample\Aggregate
*/
final class UserDescription implements EventMachineDescription
{
public const IDENTIFIER = 'userId';
public const USERNAME = 'username';
public const EMAIL = 'email';

const STATE_CLASS = UserState::class;

public static function describe(EventMachine $eventMachine): void
{
self::describeRegisterUser($eventMachine);
self::describeChangeUsername($eventMachine);
}

private static function describeRegisterUser(EventMachine $eventMachine): void
{
$eventMachine->process(Command::REGISTER_USER)
->withNew(Aggregate::USER)
->identifiedBy(self::IDENTIFIER)
// Note: Our custom command is passed to the function
->handle(function (RegisterUser $registerUser) {
//We can return a custom event
yield new UserRegistered((array) $registerUser);
})
->recordThat(Event::USER_WAS_REGISTERED)
// The custom event is passed to the apply function
->apply(function (UserRegistered $event) {
return new UserState((array) $event);
});
}

private static function describeChangeUsername(EventMachine $eventMachine): void
{
$eventMachine->process(Command::CHANGE_USERNAME)
->withExisting(Aggregate::USER)
// This time we handle command with existing aggregate, hence we get current user state injected
->handle(function (UserState $user, ChangeUsername $changeUsername) {
yield new UsernameChanged([
self::IDENTIFIER => $user->userId,
'oldName' => $user->username,
'newName' => $changeUsername->username,
]);
})
->recordThat(Event::USERNAME_WAS_CHANGED)
// Same here, UsernameChanged is NOT the first event, so current user state is passed
->apply(function (UserState $user, UsernameChanged $event) {
$user->username = $event->newName;

return $user;
});
}

private function __construct()
{
//static class only
}
}
24 changes: 24 additions & 0 deletions examples/CustomMessages/Aggregate/UserState.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php
/**
* This file is part of the proophsoftware/event-machine.
* (c) 2017-2018 prooph software GmbH <contact@prooph.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ProophExample\CustomMessages\Aggregate;

use ProophExample\CustomMessages\Util\ApplyPayload;

class UserState
{
use ApplyPayload;

public $userId;
public $username;
public $email;
public $failed;
}
45 changes: 45 additions & 0 deletions examples/CustomMessages/Api/Command.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php
/**
* This file is part of the proophsoftware/event-machine.
* (c) 2017-2018 prooph software GmbH <contact@prooph.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ProophExample\CustomMessages\Api;

use ProophExample\CustomMessages\Command\ChangeUsername;
use ProophExample\CustomMessages\Command\RegisterUser;

final class Command
{
const REGISTER_USER = 'RegisterUser';
const CHANGE_USERNAME = 'ChangeUsername';

const CLASS_MAP = [
self::REGISTER_USER => RegisterUser::class,
self::CHANGE_USERNAME => ChangeUsername::class,
];

public static function createFromNameAndPayload(string $commandName, array $payload)
{
$class = self::CLASS_MAP[$commandName];

return new $class($payload);
}

public static function nameOf($command): string
{
$map = \array_flip(self::CLASS_MAP);

return $map[\get_class($command)];
}

private function __construct()
{
//static class only
}
}
46 changes: 46 additions & 0 deletions examples/CustomMessages/Api/Event.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php
/**
* This file is part of the proophsoftware/event-machine.
* (c) 2017-2018 prooph software GmbH <contact@prooph.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ProophExample\CustomMessages\Api;

use ProophExample\CustomMessages\Event\UsernameChanged;
use ProophExample\CustomMessages\Event\UserRegistered;

final class Event
{
const USER_WAS_REGISTERED = 'UserWasRegistered';
const USER_REGISTRATION_FAILED = 'UserRegistrationFailed';
const USERNAME_WAS_CHANGED = 'UsernameWasChanged';

const CLASS_MAP = [
self::USER_WAS_REGISTERED => UserRegistered::class,
self::USERNAME_WAS_CHANGED => UsernameChanged::class,
];

public static function createFromNameAndPayload(string $commandName, array $payload)
{
$class = self::CLASS_MAP[$commandName];

return new $class($payload);
}

public static function nameOf($event): string
{
$map = \array_flip(self::CLASS_MAP);

return $map[\get_class($event)];
}

private function __construct()
{
//static class only
}
}
89 changes: 89 additions & 0 deletions examples/CustomMessages/Api/MessageDescription.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php
/**
* This file is part of the proophsoftware/event-machine.
* (c) 2017-2018 prooph software GmbH <contact@prooph.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ProophExample\CustomMessages\Api;

use Prooph\EventMachine\EventMachine;
use Prooph\EventMachine\EventMachineDescription;
use Prooph\EventMachine\JsonSchema\JsonSchema;
use Prooph\EventMachine\JsonSchema\Type\EmailType;
use Prooph\EventMachine\JsonSchema\Type\StringType;
use Prooph\EventMachine\JsonSchema\Type\UuidType;
use ProophExample\Standard\Aggregate\UserDescription;
use ProophExample\Standard\Resolver\GetUserResolver;
use ProophExample\Standard\Resolver\GetUsersResolver;

/**
* You're free to organize EventMachineDescriptions in the way that best fits your personal preferences
*
* We decided to describe all messages of the bounded context in a centralized MessageDescription.
* Another idea would be to register messages within an aggregate description.
*
* You only need to follow one rule:
* Messages need be registered BEFORE they are referenced by handling or listing descriptions
*
* Class MessageDescription
* @package ProophExample\Messaging
*/
final class MessageDescription implements EventMachineDescription
{
public static function describe(EventMachine $eventMachine): void
{
/* Schema Definitions */
$userId = new UuidType();

$username = (new StringType())->withMinLength(1);

$userDataSchema = JsonSchema::object([
UserDescription::IDENTIFIER => $userId,
UserDescription::USERNAME => $username,
UserDescription::EMAIL => new EmailType(),
]);

/* Message Registration */
$eventMachine->registerCommand(Command::REGISTER_USER, $userDataSchema);
$eventMachine->registerCommand(Command::CHANGE_USERNAME, JsonSchema::object([
UserDescription::IDENTIFIER => $userId,
UserDescription::USERNAME => $username,
]));

$eventMachine->registerEvent(Event::USER_WAS_REGISTERED, $userDataSchema);
$eventMachine->registerEvent(Event::USERNAME_WAS_CHANGED, JsonSchema::object([
UserDescription::IDENTIFIER => $userId,
'oldName' => $username,
'newName' => $username,
]));

/*
//Register user state as a Type so that we can reference it as query return type
$eventMachine->registerType('User', $userDataSchema);
$eventMachine->registerQuery(Query::GET_USER, JsonSchema::object([
UserDescription::IDENTIFIER => $userId,
]))
->resolveWith(GetUserResolver::class)
->setReturnType(JsonSchema::typeRef('User'));

$eventMachine->registerQuery(Query::GET_USERS)
->resolveWith(GetUsersResolver::class)
->setReturnType(JsonSchema::array(JsonSchema::typeRef('User')));

$filterInput = JsonSchema::object([
'username' => JsonSchema::nullOr(JsonSchema::string()),
'email' => JsonSchema::nullOr(JsonSchema::email()),
]);
$eventMachine->registerQuery(Query::GET_FILTERED_USERS, JsonSchema::object([], [
'filter' => JsonSchema::nullOr(JsonSchema::typeRef('UserFilterInput')),
]))
->resolveWith(GetUsersResolver::class)
->setReturnType(JsonSchema::array(JsonSchema::typeRef('User')));
*/
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

declare(strict_types=1);

namespace ProophExample\Messaging;
namespace ProophExample\CustomMessages\Api;

final class Query
{
Expand Down
29 changes: 29 additions & 0 deletions examples/CustomMessages/Command/ChangeUsername.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php
/**
* This file is part of the proophsoftware/event-machine.
* (c) 2017-2018 prooph software GmbH <contact@prooph.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ProophExample\CustomMessages\Command;

use ProophExample\CustomMessages\Util\ApplyPayload;

final class ChangeUsername
{
use ApplyPayload;

/**
* @var string
*/
public $userId;

/**
* @var string
*/
public $username;
}
Loading