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

Minor additions #14

Merged
merged 2 commits into from
May 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,26 @@ composer require ericksonreyes/domain-driven-design
## Usage
* [Command Bus](docs/application/COMMAND_BUS.MD)
* [Event Bus](docs/application/EVENT_BUS.MD)
* [Country Factory](docs/common/factory/COUNTRY_FACTORY.MD)
* [Class Composition Validator](docs/common/validation/CLASS_COMPOSITION_VALIDATOR.MD)

## Value Objects
* [Address](src/EricksonReyes/DomainDrivenDesign/Common/ValueObject/Address.php)
* [Country](src/EricksonReyes/DomainDrivenDesign/Common/ValueObject/Country.php)
* [Currency](src/EricksonReyes/DomainDrivenDesign/Common/ValueObject/Currency.php)
* [Email](src/EricksonReyes/DomainDrivenDesign/Common/ValueObject/Email.php)
* [Float](src/EricksonReyes/DomainDrivenDesign/Common/ValueObject/FloatValue.php)
* [Integer](src/EricksonReyes/DomainDrivenDesign/Common/ValueObject/IntegerValue.php)
* [Money](src/EricksonReyes/DomainDrivenDesign/Common/ValueObject/Address.php)
* [Person Name](src/EricksonReyes/DomainDrivenDesign/Common/ValueObject/PersonName.php)
* [String Value](src/EricksonReyes/DomainDrivenDesign/Common/ValueObject/StringValue.php)

## Examples
* [Domain Entity](src/EricksonReyes/DomainDrivenDesign/Example/Domain/DomainEntity.php)
* [Domain Event](src/EricksonReyes/DomainDrivenDesign/Example/Domain/DomainEntityWasDeletedEvent.php)
* [Event Sourced Domain Entity](src/EricksonReyes/DomainDrivenDesign/Example/Domain/EventSourcedDomainEntity.php)

## Shared Interfaces
## Interfaces
* [Command Bus](src/EricksonReyes/DomainDrivenDesign/Infrastructure/CommandBus.php)
* [Event Bus](src/EricksonReyes/DomainDrivenDesign/Infrastructure/EventBus.php)
* [Event Handler](src/EricksonReyes/DomainDrivenDesign/Infrastructure/EventHandler.php)
Expand All @@ -34,7 +47,7 @@ composer require ericksonreyes/domain-driven-design
* [Exception Handler](src/EricksonReyes/DomainDrivenDesign/Infrastructure/ExceptionHandler.php)
* [Identity Generator](src/EricksonReyes/DomainDrivenDesign/Infrastructure/IdentityGenerator.php)

## Common Abstract Exceptions
## Abstract Exceptions
* [AuthenticationFailureException](src/EricksonReyes/DomainDrivenDesign/Common/Exception/AuthenticationFailureException.php) - Authentication/Login failed.
* [PermissionDeniedException](src/EricksonReyes/DomainDrivenDesign/Common/Exception/PermissionDeniedException.php) - Authorization failed. No permission to access a record or execute a command.
* [RecordConflictException](src/EricksonReyes/DomainDrivenDesign/Common/Exception/RecordConflictException.php) - Saving an existing record or overwriting a record with state that has been changed.
Expand All @@ -43,6 +56,6 @@ composer require ericksonreyes/domain-driven-design
* [MissingActionPerformerException](src/EricksonReyes/DomainDrivenDesign/Common/Exception/MissingActionPerformerException.php) - Commands that has no action performer for accountability.
* [EmptyIdentifierException](src/EricksonReyes/DomainDrivenDesign/Common/Exception/EmptyIdentifierException.php) - Entity or aggregate with an empty identifier value.

## Common Exceptions
## Exceptions
* [MissingEventReplayMethodException](src/EricksonReyes/DomainDrivenDesign/Common/Exception/MissingEventReplayMethodException.php) - Event sourced entity or aggregate does not have the required event replay method.
* [DomainEventOwnershipException](src/EricksonReyes/DomainDrivenDesign/Common/Exception/DomainEventOwnershipException.php) - Replaying an event that does not belong to the entity or aggregate.
11 changes: 11 additions & 0 deletions docs/common/factory/COUNTRY_FACTORY.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Country Factory
Creates instances of Country from ISO 2 Country Code

## Usage
```php
$country = EricksonReyes\DomainDrivenDesign\Common\Factory\CountryFactory::create('US');

echo $country->iso2Code(); # Returns "US"
echo $country->iso3Code(); # Returns "USA"
echo $country->name(); # Returns "United States"
```
134 changes: 134 additions & 0 deletions docs/common/validation/CLASS_COMPOSITION_VALIDATOR.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# Class Composition Validator
Let's say you have this class.
```php
class Macbook extends Computer {
// Codes...
}
```
And you want to test if it is an instance of a Laptop. Then you'd simply want to do this:
```php
if ($macbook instanceof Computer) {
// Codes...
}
```
It will work. But what if you have these classes.
```php
class Macbook extends Computer {
// Codes...
}

class Desktop extends Computer {
public function __construct(CPU $cpu) {
// Codes...
}
}

class BoxFullOfComputers {
public function addComputer(Computer $computer) {
// Codes...
}
}
```
And you want to know which instances are composed of CPUs? You want to get the instance that as CPUs?


## Using the HasComposition Interface.
Implement the [EricksonReyes\DomainDrivenDesign\Common\HasComposition](../src/EricksonReyes/DomainDrivenDesign/Common/HasComposition.php) interface to your classes.
```php
class Desktop extends Computer implements EricksonReyes\DomainDrivenDesign\Common\HasComposition {

private $composition = [];
public function __construct(CPU $cpu) {
$this->composition[] = $cpu;
}

public function getComposition() {
return $this->composition;
}

}

class Box implements EricksonReyes\DomainDrivenDesign\Common\HasComposition {
private $composition = [];

public function addItem($item) {
$this->composition[] = $item;
}

public function getComposition() {
return $this->composition;
}
}

class Truck implements EricksonReyes\DomainDrivenDesign\Common\HasComposition {
private $composition = [];

public function addCargo(Box $box) {
$this->composition[] = $box;
}

public function getComposition() {
return $this->composition;
}
}
```

## Using the ComposedClass class.

##### No composition.
```php
$laptop = new Macbook();
$composedClass = new EricksonReyes\DomainDrivenDesign\Common\Validation\ComposedClass($laptop);

print_r( $composedClass->has(CPU:class) ); # Returns false;
print_r( $composedClass->doesntHave(CPU:class) ); # Returns true;
```

##### Has composition.
```php
$desktop = new Desktop();
$composedClass = new EricksonReyes\DomainDrivenDesign\Common\Validation\ComposedClass($desktop);

print_r( $composedClass->has(CPU:class) ); # Returns true;
```

##### Has multiple compositions
```php
$laptop = new Macbook();
$desktop = new Desktop();

$box = new Box();
$box->addItem($laptop);
$box->addItem($desktop);

$composedClass = new EricksonReyes\DomainDrivenDesign\Common\Validation\ComposedClass($box);
print_r( $composedClass->has(CPU:class) ); # Returns true;
```

##### Has nested inner compositions
```php
$truck = new Truck();
$truck->addCargo($box);
$composedClass = new EricksonReyes\DomainDrivenDesign\Common\Validation\ComposedClass($truck);
print_r( $composedClass->has(CPU:class) ); # Returns true;
print_r( $composedClass->has(Box:class) ); # Returns true;
```

#### Extracting a composition
```php
$laptop = new Macbook();
$desktop = new Desktop();

$box = new Box();
$box->addItem($laptop);
$box->addItem($desktop);

$emptyBox = new Box();

$truck = new Truck();
$truck->addCargo($box);
$truck->addCargo($emptyBox);

$composedClass = new EricksonReyes\DomainDrivenDesign\Common\Validation\ComposedClass($truck);
$truck->extract(CPU:class); # Returns $desktop
```
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,28 @@ public function it_can_be_sized()
$this->isEmpty()->shouldReturn(false);
$this->isNotEmpty()->shouldReturn(true);
}

public function it_can_be_lower_cased()
{
$lowerCasedString = strtolower($this->value);
$this->lowercased()->shouldReturn($lowerCasedString);
}

public function it_can_be_upper_cased()
{
$upperCasedString = strtoupper($this->value);
$this->uppercased()->shouldReturn($upperCasedString);
}

public function it_can_be_sentence_cased()
{
$upperCasedString = ucfirst($this->value);
$this->sentenceCased()->shouldReturn($upperCasedString);
}

public function it_can_be_title_cased()
{
$upperCasedString = ucwords($this->value);
$this->titleCased()->shouldReturn($upperCasedString);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ public function doesntHave(string $theClassBeingSearched): bool
}

/**
* @param $theClassBeingSearchedFor
* @return mixed
* @param string $theClassBeingSearchedFor
* @return mixed|null
*/
public function extract($theClassBeingSearchedFor)
public function extract(string $theClassBeingSearchedFor)
{
return ClassExtractor::extract($this->composedClass(), $theClassBeingSearchedFor);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,36 @@ public function lengthIsEqualOrLessThan(int $maximumLength): bool
{
return strlen($this->value()) <= $maximumLength;
}

/**
* @return string
*/
public function lowerCased(): string
{
return strtolower($this->value());
}

/**
* @return string
*/
public function upperCased(): string
{
return strtoupper($this->value());
}

/**
* @return string
*/
public function sentenceCased(): string
{
return ucfirst($this->value());
}

/**
* @return string
*/
public function titleCased(): string
{
return ucwords($this->value());
}
}