Skip to content
Open
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
36 changes: 36 additions & 0 deletions config/api_platform/User/Order.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
Acme\Domain\Order\Order:
properties:
uuid:
identifier: true
collectionOperations:
create_order:
method: POST
path: '/orders'
messenger: true
input: Acme\Application\UseCase\Command\Order\CreateOrder\CreateOrderInput
output: Acme\UI\Http\Rest\Presentation\Order\OrderView
normalization_context:
groups: [ order ]
itemOperations:
update_order:
method: PUT
path: '/orders/{uuid}'
status: 202
messenger: true
input: Acme\Application\UseCase\Command\Order\UpdateOrder\UpdateOrderInput
output: false
read: false
openapi_context:
summary: Update order async
parameters:
- in: path
name: uuid
type: string
required: true
responses:
202:
description: Order updating in process
400:
description: Invalid input
409:
description: Conflict
16 changes: 8 additions & 8 deletions config/api_platform/User/User.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ Acme\Domain\User\User:
get:
method: GET
filters: [ 'user.search_filter' ]
output: Acme\UI\Http\Rest\Presentation\User\UserView
normalization_context:
groups: [ profile ]
get_v2:
path: v2/users
method: GET
query: Acme\Application\UseCase\Query\User\GetUsers\GetUsersQuery
filters: [ 'user.search_filter' ]
output: Acme\UI\Http\Rest\Presentation\User\UserView
normalization_context:
groups: [ profile ]
get_v2:
path: v2/users
method: GET
query: Acme\Application\UseCase\Query\User\GetUsers\GetUsersQuery
filters: [ 'user.search_filter' ]
output: Acme\UI\Http\Rest\Presentation\User\UserProfileView
post:
method: POST
Expand Down
9 changes: 9 additions & 0 deletions config/packages/doctrine/orm/mapping/order.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
doctrine:
orm:
mappings:
Order:
is_bundle: false
type: xml
dir: '%kernel.project_dir%/src/Infrastructure/Order/Doctrine/Orm/Mapping'
prefix: 'Acme\Domain\Order'
alias: Order
6 changes: 6 additions & 0 deletions config/packages/security.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ security:
stateless: true
anonymous: true

api_orders:
pattern: ^/api/orders
stateless: true
anonymous: true

api_secured:
pattern: ^/api
provider: users
Expand Down Expand Up @@ -67,4 +72,5 @@ security:
- { path: ^/api/auth, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api/signup, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api/doc, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api/orders, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api/, roles: IS_AUTHENTICATED_FULLY }
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace Acme\Application\UseCase\Command\Order\CreateOrder;

use Acme\Infrastructure\Shared\Bus\Command\CommandInterface;

class CreateOrderCommand implements CommandInterface
{
private string $number;
private string $state;
private int $total;

public function __construct(string $number, string $state, int $total)
{
$this->number = $number;
$this->state = $state;
$this->total = $total;
}

public function getNumber(): string
{
return $this->number;
}

public function getState(): string
{
return $this->state;
}

public function getTotal(): int
{
return $this->total;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Acme\Application\UseCase\Command\Order\CreateOrder;

use Acme\Domain\Order\Order;
use Acme\Domain\Order\Repository\OrderRepositoryInterface;
use Acme\Infrastructure\Shared\Bus\Command\CommandHandlerInterface;
use Acme\UI\Http\Rest\Presentation\Order\OrderView;

class CreateOrderCommandHandler implements CommandHandlerInterface
{
private OrderRepositoryInterface $orderStore;

public function __construct(OrderRepositoryInterface $orderStore)
{
$this->orderStore = $orderStore;
}

public function __invoke(CreateOrderCommand $command)
{
$order = Order::create($command->getNumber(), $command->getState(), $command->getTotal());

$this->orderStore->store($order);

/** @TODO Think about this line because it breaks DDD */
return OrderView::create($order);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace Acme\Application\UseCase\Command\Order\CreateOrder;

use ApiPlatform\Core\DataTransformer\DataTransformerInterface;
use ApiPlatform\Core\Validator\ValidatorInterface;

class CreateOrderDataTransformer implements DataTransformerInterface
{
private ValidatorInterface $validator;

public function __construct(ValidatorInterface $validator)
{
$this->validator = $validator;
}

public function transform($object, string $to, array $context = [])
{
if (!$object instanceof CreateOrderInput) {
throw new \InvalidArgumentException(\sprintf('Object is not an instance of %s', CreateOrderInput::class));
}

$this->validator->validate($object, $context);

return new CreateOrderCommand(
$object->number,
$object->state,
$object->total
);
}

public function supportsTransformation($data, string $to, array $context = []): bool
{
return CreateOrderInput::class === ($context['input']['class'] ?? null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Acme\Application\UseCase\Command\Order\CreateOrder;

use Symfony\Component\Validator\Constraints as Assert;

class CreateOrderInput
{
/**
* @Assert\NotBlank
* @Assert\Type("string")
*/
public string $number;

/**
* @Assert\NotBlank
* @Assert\Type("string")
*/
public string $state;

/**
* @Assert\NotBlank
* @Assert\Type("int")
*/
public int $total;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

declare(strict_types=1);

namespace Acme\Application\UseCase\Command\Order\UpdateOrder;

use Acme\Infrastructure\Shared\Bus\Command\CommandInterface;
use Ramsey\Uuid\UuidInterface;

class UpdateOrderCommand implements CommandInterface
{
private UuidInterface $uuid;

private string $number;

private string $state;

private int $total;

public function getUuid(): UuidInterface
{
return $this->uuid;
}

public function setUuid(UuidInterface $uuid): void
{
$this->uuid = $uuid;
}

public function getNumber(): string
{
return $this->number;
}

public function setNumber(string $number): void
{
$this->number = $number;
}

public function getState(): string
{
return $this->state;
}

public function setState(string $state): void
{
$this->state = $state;
}

public function getTotal(): int
{
return $this->total;
}

public function setTotal(int $total): void
{
$this->total = $total;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace Acme\Application\UseCase\Command\Order\UpdateOrder;

use Acme\Domain\Order\Repository\OrderRepositoryInterface;
use Acme\Domain\Shared\Query\Exception\NotFoundException;
use Acme\Domain\Shared\ValueObject\DateTime;
use Acme\Infrastructure\Shared\Bus\Command\CommandHandlerInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

class UpdateOrderCommandHandler implements CommandHandlerInterface
{
private OrderRepositoryInterface $orderStore;

public function __construct(OrderRepositoryInterface $orderStore)
{
$this->orderStore = $orderStore;
}

public function __invoke(UpdateOrderCommand $command)
{
try {
$order = $this->orderStore->find($command->getUuid());
} catch (NotFoundException $e) {
throw new NotFoundHttpException($e->getMessage());
}

$order->setNumber($command->getNumber());
$order->setState($command->getState());
$order->setTotal($command->getTotal());
$order->setUpdatedAt(DateTime::now());

$this->orderStore->store($order);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace Acme\Application\UseCase\Command\Order\UpdateOrder;

use Acme\Application\UseCase\Command\Order\CreateOrder\CreateOrderInput;
use ApiPlatform\Core\DataTransformer\DataTransformerInterface;
use ApiPlatform\Core\Validator\ValidatorInterface;
use Ramsey\Uuid\UuidInterface;

class UpdateOrderDataTransformer implements DataTransformerInterface
{
private ValidatorInterface $validator;

public function __construct(ValidatorInterface $validator)
{
$this->validator = $validator;
}

public function transform($object, string $to, array $context = [])
{
if (!$object instanceof UpdateOrderInput) {
throw new \InvalidArgumentException(\sprintf('Object is not an instance of %s', UpdateOrderInput::class));
}

if (!isset($context['uuid'])) {
throw new \RuntimeException(\sprintf('Missing uuid value in context'));
}

if (($uuid = $context['uuid']) && !$uuid instanceof UuidInterface) {
throw new \InvalidArgumentException(\sprintf('Given uuid must be an instance of %s', UuidInterface::class));
}

$this->validator->validate($object, $context);

$command = new UpdateOrderCommand();
$command->setUuid($uuid);
$command->setNumber($object->number);
$command->setState($object->state);
$command->setTotal($object->total);

return $command;
}

public function supportsTransformation($data, string $to, array $context = []): bool
{
return UpdateOrderInput::class === ($context['input']['class'] ?? null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace Acme\Application\UseCase\Command\Order\UpdateOrder;

use Acme\Application\UseCase\Command\Order\CreateOrder\CreateOrderInput;

class UpdateOrderInput extends CreateOrderInput
{
}
Loading