Skip to content

Commit

Permalink
chore: add value objects
Browse files Browse the repository at this point in the history
  • Loading branch information
mtarld committed Sep 4, 2022
1 parent ab830b7 commit 387a8c3
Show file tree
Hide file tree
Showing 30 changed files with 344 additions and 94 deletions.
10 changes: 8 additions & 2 deletions config/packages/doctrine.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,14 @@
'BookStore' => [
'is_bundle' => false,
'type' => 'attribute',
'dir' => '%kernel.project_dir%/src/BookStore/Domain/Model',
'prefix' => 'App\BookStore\Domain\Model',
'dir' => '%kernel.project_dir%/src/BookStore/Domain',
'prefix' => 'App\BookStore\Domain',
],
'Shared' => [
'is_bundle' => false,
'type' => 'attribute',
'dir' => '%kernel.project_dir%/src/Shared/Domain',
'prefix' => 'App\Shared\Domain',
],
],
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace App\BookStore\Application\Command;

use App\BookStore\Domain\Repository\BookRepositoryInterface;
use App\BookStore\Domain\ValueObject\Author;
use App\Shared\Application\Command\CommandHandlerInterface;

final class AnonymizeBooksCommandHandler implements CommandHandlerInterface
Expand All @@ -18,7 +19,7 @@ public function __invoke(AnonymizeBooksCommand $command): void
$books = $this->bookRepository->withoutPagination();

foreach ($books as $book) {
$book->author = $command->anonymizedName;
$book->author = new Author($command->anonymizedName);

$this->bookRepository->remove($book);
$this->bookRepository->add($book);
Expand Down
13 changes: 12 additions & 1 deletion src/BookStore/Application/Command/CreateBookCommandHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@

use App\BookStore\Domain\Model\Book;
use App\BookStore\Domain\Repository\BookRepositoryInterface;
use App\BookStore\Domain\ValueObject\Author;
use App\BookStore\Domain\ValueObject\BookContent;
use App\BookStore\Domain\ValueObject\BookDescription;
use App\BookStore\Domain\ValueObject\BookName;
use App\BookStore\Domain\ValueObject\Price;
use App\Shared\Application\Command\CommandHandlerInterface;

final class CreateBookCommandHandler implements CommandHandlerInterface
Expand All @@ -16,7 +21,13 @@ public function __construct(private BookRepositoryInterface $bookRepository)

public function __invoke(CreateBookCommand $command): Book
{
$book = new Book($command->name, $command->description, $command->author, $command->content, $command->price);
$book = new Book(
new BookName($command->name),
new BookDescription($command->description),
new Author($command->author),
new BookContent($command->content),
new Price($command->price),
);

$this->bookRepository->add($book);

Expand Down
4 changes: 2 additions & 2 deletions src/BookStore/Application/Command/DeleteBookCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@

namespace App\BookStore\Application\Command;

use App\BookStore\Domain\ValueObject\BookId;
use App\Shared\Application\Command\CommandInterface;
use Symfony\Component\Uid\Uuid;

final class DeleteBookCommand implements CommandInterface
{
public function __construct(
public readonly Uuid $id,
public readonly BookId $id,
) {
}
}
4 changes: 2 additions & 2 deletions src/BookStore/Application/Command/DiscountBookCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@

namespace App\BookStore\Application\Command;

use App\BookStore\Domain\ValueObject\BookId;
use App\Shared\Application\Command\CommandInterface;
use Symfony\Component\Uid\Uuid;
use Webmozart\Assert\Assert;

final class DiscountBookCommand implements CommandInterface
{
public function __construct(
public readonly Uuid $id,
public readonly BookId $id,
public readonly int $discountPercentage,
) {
Assert::range($discountPercentage, 0, 100);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace App\BookStore\Application\Command;

use App\BookStore\Domain\Repository\BookRepositoryInterface;
use App\BookStore\Domain\ValueObject\Price;
use App\Shared\Application\Command\CommandHandlerInterface;

final class DiscountBookCommandHandler implements CommandHandlerInterface
Expand All @@ -17,7 +18,8 @@ public function __invoke(DiscountBookCommand $command): void
{
$book = $this->bookRepository->ofId($command->id);

$book->price = $book->price - ($book->price * $command->discountPercentage / 100);
$amount = $book->price->value - ($book->price->value * $command->discountPercentage / 100);
$book->price = new Price($amount);

$this->bookRepository->remove($book);
$this->bookRepository->add($book);
Expand Down
6 changes: 3 additions & 3 deletions src/BookStore/Application/Command/UpdateBookCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@

namespace App\BookStore\Application\Command;

use App\BookStore\Domain\ValueObject\BookId;
use App\Shared\Application\Command\CommandInterface;
use Symfony\Component\Uid\Uuid;
use Webmozart\Assert\Assert;

final class UpdateBookCommand implements CommandInterface
{
public function __construct(
public readonly Uuid $id,
public readonly ?string $name = null,
public readonly BookId $id,
public readonly ?string $name = null, // TODO VO
public readonly ?string $description = null,
public readonly ?string $author = null,
public readonly ?string $content = null,
Expand Down
15 changes: 10 additions & 5 deletions src/BookStore/Application/Command/UpdateBookCommandHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@

use App\BookStore\Domain\Model\Book;
use App\BookStore\Domain\Repository\BookRepositoryInterface;
use App\BookStore\Domain\ValueObject\Author;
use App\BookStore\Domain\ValueObject\BookContent;
use App\BookStore\Domain\ValueObject\BookDescription;
use App\BookStore\Domain\ValueObject\BookName;
use App\BookStore\Domain\ValueObject\Price;
use App\Shared\Application\Command\CommandHandlerInterface;

final class UpdateBookCommandHandler implements CommandHandlerInterface
Expand All @@ -18,11 +23,11 @@ public function __invoke(UpdateBookCommand $command): Book
{
$book = $this->bookRepository->ofId($command->id);

$book->name = $command->name ?? $book->name;
$book->description = $command->description ?? $book->description;
$book->author = $command->author ?? $book->author;
$book->content = $command->content ?? $book->content;
$book->price = $command->price ?? $book->price;
$book->name = null !== $command->name ? new BookName($command->name) : $book->name;
$book->description = null !== $command->description ? new BookDescription($command->description) : $book->description;
$book->author = null !== $command->author ? new Author($command->author) : $book->author;
$book->content = null !== $command->content ? new BookContent($command->content) : $book->content;
$book->price = null !== $command->price ? new Price($command->price) : $book->price;

$this->bookRepository->remove($book);
$this->bookRepository->add($book);
Expand Down
4 changes: 2 additions & 2 deletions src/BookStore/Application/Query/FindBookQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@

namespace App\BookStore\Application\Query;

use App\BookStore\Domain\ValueObject\BookId;
use App\Shared\Application\Query\QueryInterface;
use Symfony\Component\Uid\Uuid;

final class FindBookQuery implements QueryInterface
{
public function __construct(
public readonly Uuid $id,
public readonly BookId $id,
) {
}
}
3 changes: 2 additions & 1 deletion src/BookStore/Application/Query/FindBooksQueryHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace App\BookStore\Application\Query;

use App\BookStore\Domain\Repository\BookRepositoryInterface;
use App\BookStore\Domain\ValueObject\Author;
use App\Shared\Application\Query\QueryHandlerInterface;

final class FindBooksQueryHandler implements QueryHandlerInterface
Expand All @@ -18,7 +19,7 @@ public function __invoke(FindBooksQuery $query): BookRepositoryInterface
$bookRepository = $this->bookRepository;

if (null !== $query->author) {
$bookRepository = $bookRepository->withAuthor($query->author);
$bookRepository = $bookRepository->withAuthor(new Author($query->author));
}

if (null !== $query->page && null !== $query->itemsPerPage) {
Expand Down
41 changes: 19 additions & 22 deletions src/BookStore/Domain/Model/Book.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,36 @@

namespace App\BookStore\Domain\Model;

use App\BookStore\Domain\ValueObject\Author;
use App\BookStore\Domain\ValueObject\BookContent;
use App\BookStore\Domain\ValueObject\BookDescription;
use App\BookStore\Domain\ValueObject\BookId;
use App\BookStore\Domain\ValueObject\BookName;
use App\BookStore\Domain\ValueObject\Price;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Uid\Uuid;
use Webmozart\Assert\Assert;

#[ORM\Entity]
class Book
{
#[ORM\Id]
#[ORM\Column(type: 'uuid')]
public readonly Uuid $id;
#[ORM\Embedded(columnPrefix: false)]
public BookId $id;

public function __construct(
#[ORM\Column(length: 255)]
public string $name,
#[ORM\Embedded(columnPrefix: false)]
public BookName $name,

#[ORM\Column(length: 1023)]
public string $description,
#[ORM\Embedded(columnPrefix: false)]
public BookDescription $description,

#[ORM\Column(length: 255)]
public string $author,
#[ORM\Embedded(columnPrefix: false)]
public Author $author,

#[ORM\Column(length: 65535)]
public string $content,
#[ORM\Embedded(columnPrefix: false)]
public BookContent $content,

#[ORM\Column(type: 'integer', options: ['unsigned' => true])]
public int $price,
#[ORM\Embedded(columnPrefix: false)]
public Price $price,
) {
$this->id = Uuid::v4();

Assert::lengthBetween($name, 1, 255);
Assert::lengthBetween($description, 1, 1023);
Assert::lengthBetween($author, 1, 255);
Assert::lengthBetween($content, 1, 65535);
Assert::natural($price);
$this->id = new BookId();
}
}
7 changes: 4 additions & 3 deletions src/BookStore/Domain/Repository/BookRepositoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
namespace App\BookStore\Domain\Repository;

use App\BookStore\Domain\Model\Book;
use App\BookStore\Domain\ValueObject\Author;
use App\BookStore\Domain\ValueObject\BookId;
use App\Shared\Domain\Repository\RepositoryInterface;
use Symfony\Component\Uid\Uuid;

/**
* @extends RepositoryInterface<Book>
Expand All @@ -17,9 +18,9 @@ public function add(Book $book): void;

public function remove(Book $book): void;

public function ofId(Uuid $id): ?Book;
public function ofId(BookId $id): ?Book;

public function withAuthor(string $author): static;
public function withAuthor(Author $author): static;

public function withCheapestsFirst(): static;
}
27 changes: 27 additions & 0 deletions src/BookStore/Domain/ValueObject/Author.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace App\BookStore\Domain\ValueObject;

use Doctrine\ORM\Mapping as ORM;
use Webmozart\Assert\Assert;

#[ORM\Embeddable]
final class Author
{
#[ORM\Column(name: 'author', length: 255)]
public readonly string $value;

public function __construct(string $value)
{
Assert::lengthBetween($value, 1, 255);

$this->value = $value;
}

public function isEqualTo(self $author): bool
{
return $author->value === $this->value;
}
}
22 changes: 22 additions & 0 deletions src/BookStore/Domain/ValueObject/BookContent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace App\BookStore\Domain\ValueObject;

use Doctrine\ORM\Mapping as ORM;
use Webmozart\Assert\Assert;

#[ORM\Embeddable]
final class BookContent
{
#[ORM\Column(name: 'content', length: 65535)]
public readonly string $value;

public function __construct(string $value)
{
Assert::lengthBetween($value, 1, 65535);

$this->value = $value;
}
}
22 changes: 22 additions & 0 deletions src/BookStore/Domain/ValueObject/BookDescription.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace App\BookStore\Domain\ValueObject;

use Doctrine\ORM\Mapping as ORM;
use Webmozart\Assert\Assert;

#[ORM\Embeddable]
final class BookDescription
{
#[ORM\Column(name: 'description', length: 1023)]
public readonly string $value;

public function __construct(string $value)
{
Assert::lengthBetween($value, 1, 1023);

$this->value = $value;
}
}
13 changes: 13 additions & 0 deletions src/BookStore/Domain/ValueObject/BookId.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace App\BookStore\Domain\ValueObject;

use App\Shared\Domain\ValueObject\AggregateRootId;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Embeddable]
final class BookId extends AggregateRootId
{
}
22 changes: 22 additions & 0 deletions src/BookStore/Domain/ValueObject/BookName.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace App\BookStore\Domain\ValueObject;

use Doctrine\ORM\Mapping as ORM;
use Webmozart\Assert\Assert;

#[ORM\Embeddable]
final class BookName
{
#[ORM\Column(name: 'name', length: 255)]
public readonly string $value;

public function __construct(string $value)
{
Assert::lengthBetween($value, 1, 255);

$this->value = $value;
}
}
Loading

0 comments on commit 387a8c3

Please sign in to comment.