This commit is contained in:
Flo 2024-02-25 16:02:24 +01:00
parent 544a9480ae
commit 1df97ff326
41 changed files with 546 additions and 86 deletions

View File

@ -94,10 +94,7 @@ class {$stepClassName} implements TaskInterface
) { ) {
} }
public function __invoke( public function __invoke(\$payload, PipelineInterface \$pipeline): void
\$payload,
PipelineInterface \$pipeline
): void
{ {
/** @var {$payloadClassName} \${$payloadVariableName} */ /** @var {$payloadClassName} \${$payloadVariableName} */
\${$payloadVariableName} = \$payload; \${$payloadVariableName} = \$payload;

View File

@ -3,11 +3,13 @@
use MyTube\API\Console\Command\AnalyzeVideoTitlesCommand; use MyTube\API\Console\Command\AnalyzeVideoTitlesCommand;
use MyTube\API\Console\Command\InitializeDataCommand; use MyTube\API\Console\Command\InitializeDataCommand;
use MyTube\API\Console\Command\RbacUpdateCommand; use MyTube\API\Console\Command\RbacUpdateCommand;
use MyTube\API\Console\Command\ReadUntaggedVideosCommand;
return [ return [
'commands' => [ 'commands' => [
InitializeDataCommand::class, InitializeDataCommand::class,
RbacUpdateCommand::class, RbacUpdateCommand::class,
AnalyzeVideoTitlesCommand::class, AnalyzeVideoTitlesCommand::class,
ReadUntaggedVideosCommand::class,
] ]
]; ];

View File

@ -3,6 +3,7 @@
use MyTube\API\Console\Command\AnalyzeVideoTitlesCommand; use MyTube\API\Console\Command\AnalyzeVideoTitlesCommand;
use MyTube\API\Console\Command\InitializeDataCommand; use MyTube\API\Console\Command\InitializeDataCommand;
use MyTube\API\Console\Command\RbacUpdateCommand; use MyTube\API\Console\Command\RbacUpdateCommand;
use MyTube\API\Console\Command\ReadUntaggedVideosCommand;
use Reinfi\DependencyInjection\Factory\AutoWiringFactory; use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
return [ return [
@ -10,5 +11,6 @@ return [
InitializeDataCommand::class => AutoWiringFactory::class, InitializeDataCommand::class => AutoWiringFactory::class,
RbacUpdateCommand::class => AutoWiringFactory::class, RbacUpdateCommand::class => AutoWiringFactory::class,
AnalyzeVideoTitlesCommand::class => AutoWiringFactory::class, AnalyzeVideoTitlesCommand::class => AutoWiringFactory::class,
ReadUntaggedVideosCommand::class => AutoWiringFactory::class,
], ],
]; ];

View File

@ -46,7 +46,7 @@ class AnalyzeVideoTitlesCommand extends Command
/** @var Tag $match */ /** @var Tag $match */
foreach ($matches as $match) { foreach ($matches as $match) {
$io->info(sprintf(" - added Tag '%s'", $match->getDescription())); echo sprintf("Added Tag '%s'", $match->getDescription());
} }
$this->entityManager->persist($video); $this->entityManager->persist($video);

View File

@ -0,0 +1,64 @@
<?php
namespace MyTube\API\Console\Command;
use MyTube\Data\Business\Entity\Tag;
use MyTube\Data\Business\Entity\Video;
use MyTube\Data\Business\Manager\MyTubeEntityManager;
use MyTube\Data\Business\Repository\VideoRepository;
use MyTube\Handling\Video\Analyzer\VideoTitleAnalyzer;
use MyTube\Infrastructure\Logging\Logger\Logger;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
#[AsCommand(name: 'analyze:untagged', description: 'Returns the names of all untagged videos')]
class ReadUntaggedVideosCommand extends Command
{
private readonly VideoRepository $videoRepository;
public function __construct(
private readonly MyTubeEntityManager $entityManager,
private readonly Logger $logger,
) {
parent::__construct($this->getName());
$this->videoRepository = $this->entityManager->getRepository(Video::class);
}
protected function execute(
InputInterface $input,
OutputInterface $output
): int {
$io = new SymfonyStyle($input, $output);
try {
$qb = $this->videoRepository
->createQueryBuilder('v')
->leftJoin('v.tags', 't')
->groupBy('v.id')
->having('COUNT(t.id) = 0')
->orderBy('v.title');
$videos = $qb->getQuery()->execute();
/** @var Video $video */
foreach ($videos as $video) {
echo $video->getTitle() . PHP_EOL;
}
$io->info('total: ' . count($videos));
$io->success('OK!');
} catch (\Throwable $e) {
$io->error($e->getMessage());
$io->error($e->getTraceAsString());
$this->logger->error($e->getMessage(), ['exception' => $e]);
return Command::FAILURE;
}
return Command::SUCCESS;
}
}

View File

@ -7,6 +7,7 @@ namespace MyTube\API\External\Authentication\Handler;
use MyTube\API\External\User\Formatter\UserFormatter; use MyTube\API\External\User\Formatter\UserFormatter;
use MyTube\Handling\Registration\Handler\Command\ConfirmRegistration\ConfirmRegistrationCommandBuilder; use MyTube\Handling\Registration\Handler\Command\ConfirmRegistration\ConfirmRegistrationCommandBuilder;
use MyTube\Handling\Registration\Handler\Command\ConfirmRegistration\ConfirmRegistrationCommandHandler; use MyTube\Handling\Registration\Handler\Command\ConfirmRegistration\ConfirmRegistrationCommandHandler;
use MyTube\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use MyTube\Infrastructure\Session\Middleware\SessionMiddleware; use MyTube\Infrastructure\Session\Middleware\SessionMiddleware;
use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
@ -25,10 +26,7 @@ class ConfirmRegistrationHandler implements RequestHandlerInterface
public function handle(ServerRequestInterface $request): ResponseInterface public function handle(ServerRequestInterface $request): ResponseInterface
{ {
$data = json_decode( $data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
$request->getBody()->getContents(),
true
);
$query = $this->builder->build( $query = $this->builder->build(
Uuid::fromString($data['id']), Uuid::fromString($data['id']),

View File

@ -6,6 +6,7 @@ namespace MyTube\API\External\Authentication\Handler;
use MyTube\Handling\UserSession\Handler\Command\LoginUser\LoginUserCommandBuilder; use MyTube\Handling\UserSession\Handler\Command\LoginUser\LoginUserCommandBuilder;
use MyTube\Handling\UserSession\Handler\Command\LoginUser\LoginUserCommandHandler; use MyTube\Handling\UserSession\Handler\Command\LoginUser\LoginUserCommandHandler;
use MyTube\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use MyTube\Infrastructure\Session\Middleware\SessionMiddleware; use MyTube\Infrastructure\Session\Middleware\SessionMiddleware;
use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
@ -23,10 +24,7 @@ class LoginUserHandler implements RequestHandlerInterface
public function handle(ServerRequestInterface $request): ResponseInterface public function handle(ServerRequestInterface $request): ResponseInterface
{ {
$session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE); $session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE);
$data = json_decode( $data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
$request->getBody()->getContents(),
true
);
$query = $this->builder->build( $query = $this->builder->build(
$session, $session,

View File

@ -8,6 +8,7 @@ use MyTube\Handling\Registration\Handler\Command\RegisterUser\RegisterUserComman
use MyTube\Handling\Registration\Handler\Command\RegisterUser\RegisterUserCommandHandler; use MyTube\Handling\Registration\Handler\Command\RegisterUser\RegisterUserCommandHandler;
use MyTube\Infrastructure\Exception\Middleware\MyTubeExceptionHandlerMiddleware; use MyTube\Infrastructure\Exception\Middleware\MyTubeExceptionHandlerMiddleware;
use MyTube\Infrastructure\Logging\Logger\Logger; use MyTube\Infrastructure\Logging\Logger\Logger;
use MyTube\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use MyTube\Infrastructure\Request\Middleware\AnalyzeHeaderMiddleware; use MyTube\Infrastructure\Request\Middleware\AnalyzeHeaderMiddleware;
use MyTube\Infrastructure\Response\SuccessResponse; use MyTube\Infrastructure\Response\SuccessResponse;
use MyTube\Infrastructure\Session\Middleware\SessionMiddleware; use MyTube\Infrastructure\Session\Middleware\SessionMiddleware;
@ -28,10 +29,7 @@ class RegisterUserHandler implements RequestHandlerInterface
public function handle(ServerRequestInterface $request): ResponseInterface public function handle(ServerRequestInterface $request): ResponseInterface
{ {
$host = $request->getAttribute(AnalyzeHeaderMiddleware::HOST_ATTRIBUTE); $host = $request->getAttribute(AnalyzeHeaderMiddleware::HOST_ATTRIBUTE);
$data = json_decode( $data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
$request->getBody()->getContents(),
true
);
$query = $this->builder->build( $query = $this->builder->build(
$data['username'], $data['username'],

View File

@ -2,6 +2,8 @@
use MyTube\API\External\Tag\Handler\AddAliasHandler; use MyTube\API\External\Tag\Handler\AddAliasHandler;
use MyTube\API\External\Tag\Handler\CreateHandler; use MyTube\API\External\Tag\Handler\CreateHandler;
use MyTube\API\External\Tag\Handler\ReadDetailsHandler;
use MyTube\API\External\Tag\Handler\ReadVideoListHandler;
return [ return [
[ [
@ -20,4 +22,20 @@ return [
AddAliasHandler::class, AddAliasHandler::class,
], ],
], ],
[
'name' => 'tag.read-details',
'path' => '/api/tag/read-details[/]',
'allowed_methods' => ['POST'],
'middleware' => [
ReadDetailsHandler::class,
],
],
[
'name' => 'tag.read-video-list',
'path' => '/api/tag/read-video-list[/]',
'allowed_methods' => ['POST'],
'middleware' => [
ReadVideoListHandler::class,
],
],
]; ];

View File

@ -2,8 +2,12 @@
use MyTube\API\External\Tag\Handler\AddAliasHandler; use MyTube\API\External\Tag\Handler\AddAliasHandler;
use MyTube\API\External\Tag\Handler\CreateHandler; use MyTube\API\External\Tag\Handler\CreateHandler;
use MyTube\API\External\Tag\Handler\ReadDetailsHandler;
use MyTube\API\External\Tag\Handler\ReadVideoListHandler;
use MyTube\API\External\Tag\ResponseFormatter\AddAliasResponseFormatter; use MyTube\API\External\Tag\ResponseFormatter\AddAliasResponseFormatter;
use MyTube\API\External\Tag\ResponseFormatter\CreateResponseFormatter; use MyTube\API\External\Tag\ResponseFormatter\CreateResponseFormatter;
use MyTube\API\External\Tag\ResponseFormatter\ReadDetailsResponseFormatter;
use MyTube\API\External\Tag\ResponseFormatter\ReadVideoListResponseFormatter;
use Reinfi\DependencyInjection\Factory\AutoWiringFactory; use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
return [ return [
@ -11,9 +15,13 @@ return [
// Handler // Handler
AddAliasHandler::class => AutoWiringFactory::class, AddAliasHandler::class => AutoWiringFactory::class,
CreateHandler::class => AutoWiringFactory::class, CreateHandler::class => AutoWiringFactory::class,
ReadDetailsHandler::class => AutoWiringFactory::class,
ReadVideoListHandler::class => AutoWiringFactory::class,
// Response Formatter // Response Formatter
AddAliasResponseFormatter::class => AutoWiringFactory::class, AddAliasResponseFormatter::class => AutoWiringFactory::class,
CreateResponseFormatter::class => AutoWiringFactory::class, CreateResponseFormatter::class => AutoWiringFactory::class,
ReadDetailsResponseFormatter::class => AutoWiringFactory::class,
ReadVideoListResponseFormatter::class => AutoWiringFactory::class,
], ],
]; ];

View File

@ -9,6 +9,7 @@ use MyTube\Handling\Tag\Exception\TagNotFoundByIdException;
use MyTube\Handling\Tag\Handler\Command\AddAlias\AddAliasCommandHandler; use MyTube\Handling\Tag\Handler\Command\AddAlias\AddAliasCommandHandler;
use MyTube\Handling\Tag\Handler\Command\AddAlias\AddAliasCommandBuilder; use MyTube\Handling\Tag\Handler\Command\AddAlias\AddAliasCommandBuilder;
use MyTube\API\External\Tag\ResponseFormatter\AddAliasResponseFormatter; use MyTube\API\External\Tag\ResponseFormatter\AddAliasResponseFormatter;
use MyTube\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface; use Psr\Http\Server\RequestHandlerInterface;
@ -30,10 +31,7 @@ class AddAliasHandler implements RequestHandlerInterface
*/ */
public function handle(ServerRequestInterface $request): ResponseInterface public function handle(ServerRequestInterface $request): ResponseInterface
{ {
$data = json_decode( $data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
$request->getBody()->getContents(),
true
);
$addAliasCommand = $this->addAliasCommandBuilder->build( $addAliasCommand = $this->addAliasCommandBuilder->build(
Uuid::fromString($data['tagId']), Uuid::fromString($data['tagId']),

View File

@ -8,6 +8,7 @@ use MyTube\Handling\Tag\Exception\TagAlreadyExistsException;
use MyTube\Handling\Tag\Handler\Command\Create\CreateCommandHandler; use MyTube\Handling\Tag\Handler\Command\Create\CreateCommandHandler;
use MyTube\Handling\Tag\Handler\Command\Create\CreateCommandBuilder; use MyTube\Handling\Tag\Handler\Command\Create\CreateCommandBuilder;
use MyTube\API\External\Tag\ResponseFormatter\CreateResponseFormatter; use MyTube\API\External\Tag\ResponseFormatter\CreateResponseFormatter;
use MyTube\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface; use Psr\Http\Server\RequestHandlerInterface;
@ -27,10 +28,7 @@ class CreateHandler implements RequestHandlerInterface
*/ */
public function handle(ServerRequestInterface $request): ResponseInterface public function handle(ServerRequestInterface $request): ResponseInterface
{ {
$data = json_decode( $data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
$request->getBody()->getContents(),
true
);
$createCommand = $this->createCommandBuilder->build( $createCommand = $this->createCommandBuilder->build(
$data['description'] $data['description']

View File

@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
namespace MyTube\API\External\Tag\Handler;
use MyTube\Handling\Tag\Exception\TagNotFoundByIdException;
use MyTube\Handling\Tag\Handler\Query\ReadDetails\ReadDetailsQueryHandler;
use MyTube\Handling\Tag\Handler\Query\ReadDetails\ReadDetailsQueryBuilder;
use MyTube\API\External\Tag\ResponseFormatter\ReadDetailsResponseFormatter;
use MyTube\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use MyTube\Infrastructure\Response\SuccessResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Ramsey\Uuid\Uuid;
class ReadDetailsHandler implements RequestHandlerInterface
{
public function __construct(
private readonly ReadDetailsQueryHandler $readDetailsQueryHandler,
private readonly ReadDetailsQueryBuilder $readDetailsQueryBuilder,
private readonly ReadDetailsResponseFormatter $responseFormatter,
) {
}
/**
* @throws TagNotFoundByIdException
*/
public function handle(ServerRequestInterface $request): ResponseInterface
{
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
$readDetailsQuery = $this->readDetailsQueryBuilder->build(
Uuid::fromString($data['tagId']),
);
$result = $this->readDetailsQueryHandler->execute($readDetailsQuery);
return new SuccessResponse($this->responseFormatter->format($result));
}
}

View File

@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
namespace MyTube\API\External\Tag\Handler;
use MyTube\Handling\Tag\Handler\Query\ReadVideoList\ReadVideoListQueryHandler;
use MyTube\Handling\Tag\Handler\Query\ReadVideoList\ReadVideoListQueryBuilder;
use MyTube\API\External\Tag\ResponseFormatter\ReadVideoListResponseFormatter;
use MyTube\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use MyTube\Infrastructure\Response\SuccessResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Ramsey\Uuid\Uuid;
class ReadVideoListHandler implements RequestHandlerInterface
{
public function __construct(
private readonly ReadVideoListQueryHandler $readVideoListQueryHandler,
private readonly ReadVideoListQueryBuilder $readVideoListQueryBuilder,
private readonly ReadVideoListResponseFormatter $responseFormatter,
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
$readVideoListQuery = $this->readVideoListQueryBuilder->build(
Uuid::fromString($data['tagId']),
$data['query'] ?? null,
$data['page'],
$data['perPage'],
);
$result = $this->readVideoListQueryHandler->execute($readVideoListQuery);
return new SuccessResponse($this->responseFormatter->format($result));
}
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace MyTube\API\External\Tag\ResponseFormatter;
use MyTube\Data\Business\Entity\TagAlias;
use MyTube\Handling\Tag\Handler\Query\ReadDetails\ReadDetailsQueryResult;
class ReadDetailsResponseFormatter
{
public function format(ReadDetailsQueryResult $readDetailsQueryResult): array
{
$tag = $readDetailsQueryResult->getTag();
$aliases = [];
/** @var TagAlias $alias */
foreach ($tag->getAliases() as $alias) {
$aliases[] = $alias->getDescription();
}
return [
'id' => $tag->getId()->toString(),
'description' => $tag->getDescription(),
'aliases' => $aliases
];
}
}

View File

@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace MyTube\API\External\Tag\ResponseFormatter;
use MyTube\Data\Business\Entity\Tag;
use MyTube\Data\Business\Entity\Video;
use MyTube\Handling\Tag\Handler\Query\ReadVideoList\ReadVideoListQueryResult;
class ReadVideoListResponseFormatter
{
public function format(ReadVideoListQueryResult $readVideoListQueryResult): array
{
$paginator = $readVideoListQueryResult->getPaginator();
$videos = $paginator->getIterator();
$items = [];
/** @var Video $video */
foreach ($videos as $video) {
$tags = [];
/** @var Tag $tag */
foreach ($video->getTags() as $tag) {
$tags[] = [
'id' => $tag->getId(),
'description' => $tag->getDescription()
];
}
$items[] = [
'title' => $video->getTitle(),
'id' => $video->getId(),
'tags' => $tags
];
}
return [
'total' => $paginator->count(),
'items' => $items,
];
}
}

View File

@ -28,8 +28,6 @@ class ReadListHandler implements RequestHandlerInterface
$readListQuery = $this->readListQueryBuilder->build( $readListQuery = $this->readListQueryBuilder->build(
$data['query'] ?? null, $data['query'] ?? null,
$data['page'],
$data['perPage'],
); );
$result = $this->readListQueryHandler->execute($readListQuery); $result = $this->readListQueryHandler->execute($readListQuery);

View File

@ -11,9 +11,7 @@ class ReadListResponseFormatter
{ {
public function format(ReadListQueryResult $readListQueryResult): array public function format(ReadListQueryResult $readListQueryResult): array
{ {
$paginator = $readListQueryResult->getPaginator(); $tags = $readListQueryResult->getItems();
$tags = $paginator->getIterator();
$items = []; $items = [];
/** @var Tag $tag */ /** @var Tag $tag */
@ -25,7 +23,7 @@ class ReadListResponseFormatter
} }
return [ return [
'total' => $paginator->count(), 'total' => count($items),
'items' => $items, 'items' => $items,
]; ];
} }

View File

@ -26,10 +26,7 @@ class ChangePasswordHandler implements RequestHandlerInterface
/** @var User $user */ /** @var User $user */
$user = $request->getAttribute(LoggedInUserMiddleware::USER_KEY); $user = $request->getAttribute(LoggedInUserMiddleware::USER_KEY);
$data = json_decode( $data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
$request->getBody()->getContents(),
true
);
$query = $this->builder->build( $query = $this->builder->build(
$user, $user,

View File

@ -7,6 +7,7 @@ namespace MyTube\API\External\User\Handler;
use MyTube\Data\Business\Entity\User; use MyTube\Data\Business\Entity\User;
use MyTube\Handling\User\Handler\Command\ChangeUsername\ChangeUsernameCommandBuilder; use MyTube\Handling\User\Handler\Command\ChangeUsername\ChangeUsernameCommandBuilder;
use MyTube\Handling\User\Handler\Command\ChangeUsername\ChangeUsernameCommandHandler; use MyTube\Handling\User\Handler\Command\ChangeUsername\ChangeUsernameCommandHandler;
use MyTube\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use MyTube\Infrastructure\Response\SuccessResponse; use MyTube\Infrastructure\Response\SuccessResponse;
use MyTube\Infrastructure\Session\Middleware\LoggedInUserMiddleware; use MyTube\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
@ -25,11 +26,7 @@ class ChangeUsernameHandler implements RequestHandlerInterface
{ {
/** @var User $user */ /** @var User $user */
$user = $request->getAttribute(LoggedInUserMiddleware::USER_KEY); $user = $request->getAttribute(LoggedInUserMiddleware::USER_KEY);
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
$data = json_decode(
$request->getBody()->getContents(),
true
);
$query = $this->builder->build( $query = $this->builder->build(
$user, $user,

View File

@ -8,6 +8,7 @@ use MyTube\API\External\User\Formatter\UserFormatter;
use MyTube\Handling\User\Handler\Command\CreateUser\CreateUserCommandBuilder; use MyTube\Handling\User\Handler\Command\CreateUser\CreateUserCommandBuilder;
use MyTube\Handling\User\Handler\Command\CreateUser\CreateUserCommandHandler; use MyTube\Handling\User\Handler\Command\CreateUser\CreateUserCommandHandler;
use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\Response\JsonResponse;
use MyTube\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface; use Psr\Http\Server\RequestHandlerInterface;
@ -23,10 +24,7 @@ class CreateUserHandler implements RequestHandlerInterface
public function handle(ServerRequestInterface $request): ResponseInterface public function handle(ServerRequestInterface $request): ResponseInterface
{ {
$data = json_decode( $data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
$request->getBody()->getContents(),
true
);
$query = $this->builder->build( $query = $this->builder->build(
$data['username'], $data['username'],

View File

@ -8,6 +8,7 @@ use MyTube\Handling\Video\Exception\VideoNotFoundByIdException;
use MyTube\Handling\Video\Handler\Query\ReadDetails\ReadDetailsQueryHandler; use MyTube\Handling\Video\Handler\Query\ReadDetails\ReadDetailsQueryHandler;
use MyTube\Handling\Video\Handler\Query\ReadDetails\ReadDetailsQueryBuilder; use MyTube\Handling\Video\Handler\Query\ReadDetails\ReadDetailsQueryBuilder;
use MyTube\API\External\Video\ResponseFormatter\ReadDetailsResponseFormatter; use MyTube\API\External\Video\ResponseFormatter\ReadDetailsResponseFormatter;
use MyTube\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface; use Psr\Http\Server\RequestHandlerInterface;
@ -28,10 +29,7 @@ class ReadDetailsHandler implements RequestHandlerInterface
*/ */
public function handle(ServerRequestInterface $request): ResponseInterface public function handle(ServerRequestInterface $request): ResponseInterface
{ {
$data = json_decode( $data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
$request->getBody()->getContents(),
true
);
$readDetailsQuery = $this->readDetailsQueryBuilder->build( $readDetailsQuery = $this->readDetailsQueryBuilder->build(
Uuid::fromString($data['videoId']) Uuid::fromString($data['videoId'])

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace MyTube\API\External\Video\ResponseFormatter; namespace MyTube\API\External\Video\ResponseFormatter;
use MyTube\Data\Business\Entity\Tag;
use MyTube\Handling\Video\Handler\Query\ReadDetails\ReadDetailsQueryResult; use MyTube\Handling\Video\Handler\Query\ReadDetails\ReadDetailsQueryResult;
class ReadDetailsResponseFormatter class ReadDetailsResponseFormatter
@ -12,9 +13,20 @@ class ReadDetailsResponseFormatter
{ {
$video = $readDetailsQueryResult->getVideo(); $video = $readDetailsQueryResult->getVideo();
$tags = [];
/** @var Tag $tag */
foreach ($video->getTags() as $tag) {
$tags = [
'id' => $tag->getId(),
'description' => $tag->getDescription(),
];
}
return [ return [
'id' => $video->getId(), 'id' => $video->getId(),
'title' => $video->getTitle() 'title' => $video->getTitle(),
'tags' => $tags,
]; ];
} }
} }

View File

@ -23,12 +23,15 @@ class ReadListResponseFormatter
/** @var Tag $tag */ /** @var Tag $tag */
foreach ($video->getTags() as $tag) { foreach ($video->getTags() as $tag) {
$tags[] = $tag->getDescription(); $tags[] = [
'id' => $tag->getId(),
'description' => $tag->getDescription()
];
} }
$items[] = [ $items[] = [
'title' => $video->getTitle(), 'title' => $video->getTitle(),
'id' => $video->getId()->toString(), 'id' => $video->getId(),
'tags' => $tags 'tags' => $tags
]; ];
} }

View File

@ -3,14 +3,11 @@
namespace MyTube\Data\Business\Repository; namespace MyTube\Data\Business\Repository;
use Doctrine\ORM\EntityRepository; use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Tools\Pagination\Paginator;
class TagRepository extends EntityRepository { class TagRepository extends EntityRepository {
public function findByFilter( public function findByFilter(
?string $query, ?string $query,
int $page, ): array
int $perPage,
): Paginator
{ {
$queryBuilder = $this->createQueryBuilder('t'); $queryBuilder = $this->createQueryBuilder('t');
@ -22,9 +19,6 @@ class TagRepository extends EntityRepository {
->setParameter('query', $query); ->setParameter('query', $query);
} }
$queryBuilder->setFirstResult($perPage * ($page - 1)); return $queryBuilder->getQuery()->execute();
$queryBuilder->setMaxResults($perPage);
return new Paginator($queryBuilder->getQuery());
} }
} }

View File

@ -5,12 +5,15 @@ namespace MyTube\Data\Business\Repository;
use Doctrine\ORM\Tools\Pagination\Paginator; use Doctrine\ORM\Tools\Pagination\Paginator;
use MyTube\Data\Business\Entity\Registration; use MyTube\Data\Business\Entity\Registration;
use Doctrine\ORM\EntityRepository; use Doctrine\ORM\EntityRepository;
use MyTube\Data\Business\Entity\Tag;
use Ramsey\Uuid\Doctrine\UuidBinaryOrderedTimeType;
class VideoRepository extends EntityRepository { class VideoRepository extends EntityRepository {
public function findByFilter( public function findByFilter(
?string $query, ?string $query,
int $page, int $page,
int $perPage, int $perPage,
?Tag $tag = null,
): Paginator ): Paginator
{ {
$queryBuilder = $this->createQueryBuilder('v'); $queryBuilder = $this->createQueryBuilder('v');
@ -23,6 +26,13 @@ class VideoRepository extends EntityRepository {
->setParameter('query', $query); ->setParameter('query', $query);
} }
if ($tag !== null) {
$queryBuilder
->join('v.tags', 't')
->andWhere('t.id = :tagId')
->setParameter('tagId', $tag->getId(), UuidBinaryOrderedTimeType::NAME);
}
$queryBuilder->setFirstResult($perPage * ($page - 1)); $queryBuilder->setFirstResult($perPage * ($page - 1));
$queryBuilder->setMaxResults($perPage); $queryBuilder->setMaxResults($perPage);

View File

@ -6,6 +6,10 @@ use MyTube\Handling\Tag\Handler\Command\AddAlias\AddAliasCommandBuilder;
use MyTube\Handling\Tag\Handler\Command\AddAlias\AddAliasCommandHandler; use MyTube\Handling\Tag\Handler\Command\AddAlias\AddAliasCommandHandler;
use MyTube\Handling\Tag\Handler\Command\Create\CreateCommandBuilder; use MyTube\Handling\Tag\Handler\Command\Create\CreateCommandBuilder;
use MyTube\Handling\Tag\Handler\Command\Create\CreateCommandHandler; use MyTube\Handling\Tag\Handler\Command\Create\CreateCommandHandler;
use MyTube\Handling\Tag\Handler\Query\ReadDetails\ReadDetailsQueryBuilder;
use MyTube\Handling\Tag\Handler\Query\ReadDetails\ReadDetailsQueryHandler;
use MyTube\Handling\Tag\Handler\Query\ReadVideoList\ReadVideoListQueryBuilder;
use MyTube\Handling\Tag\Handler\Query\ReadVideoList\ReadVideoListQueryHandler;
use MyTube\Handling\Tag\Rule\TagAliasExistsRule; use MyTube\Handling\Tag\Rule\TagAliasExistsRule;
use MyTube\Handling\Tag\Rule\TagExistsRule; use MyTube\Handling\Tag\Rule\TagExistsRule;
use Reinfi\DependencyInjection\Factory\AutoWiringFactory; use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
@ -30,5 +34,11 @@ return [
// Create // Create
CreateCommandBuilder::class => AutoWiringFactory::class, CreateCommandBuilder::class => AutoWiringFactory::class,
CreateCommandHandler::class => AutoWiringFactory::class, CreateCommandHandler::class => AutoWiringFactory::class,
// Read Details
ReadDetailsQueryBuilder::class => AutoWiringFactory::class,
ReadDetailsQueryHandler::class => InjectionFactory::class,
// Read Video List
ReadVideoListQueryBuilder::class => AutoWiringFactory::class,
ReadVideoListQueryHandler::class => InjectionFactory::class,
], ],
]; ];

View File

@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
namespace MyTube\Handling\Tag\Handler\Query\ReadDetails;
use Ramsey\Uuid\UuidInterface;
class ReadDetailsQuery
{
public function __construct(
private readonly UuidInterface $tagId,
) {
}
public function getTagId(): UuidInterface
{
return $this->tagId;
}
}

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace MyTube\Handling\Tag\Handler\Query\ReadDetails;
use Ramsey\Uuid\UuidInterface;
class ReadDetailsQueryBuilder
{
public function build(
UuidInterface $tagId,
): ReadDetailsQuery {
return new ReadDetailsQuery(
$tagId
);
}
}

View File

@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace MyTube\Handling\Tag\Handler\Query\ReadDetails;
use MyTube\Data\Business\Repository\TagRepository;
use MyTube\Handling\Tag\Exception\TagNotFoundByIdException;
use Reinfi\DependencyInjection\Annotation\InjectDoctrineRepository;
class ReadDetailsQueryHandler
{
/**
* @InjectDoctrineRepository(
* entityManager="MyTube\Data\Business\Manager\MyTubeEntityManager",
* entity="MyTube\Data\Business\Entity\Tag"
* )
*/
public function __construct(
private readonly TagRepository $tagRepository,
) {
}
/**
* @throws TagNotFoundByIdException
*/
public function execute(ReadDetailsQuery $readDetailsQuery): ReadDetailsQueryResult
{
$tagId = $readDetailsQuery->getTagId();
$tag = $this->tagRepository->findOneBy(['id' => $tagId]);
if ($tag === null) {
throw new TagNotFoundByIdException($tagId);
}
return new ReadDetailsQueryResult($tag);
}
}

View File

@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
namespace MyTube\Handling\Tag\Handler\Query\ReadDetails;
use MyTube\Data\Business\Entity\Tag;
class ReadDetailsQueryResult
{
public function __construct(
private readonly Tag $tag,
) {
}
public function getTag(): Tag
{
return $this->tag;
}
}

View File

@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace MyTube\Handling\Tag\Handler\Query\ReadVideoList;
use Ramsey\Uuid\UuidInterface;
class ReadVideoListQuery
{
public function __construct(
private readonly UuidInterface $tagId,
private readonly ?string $query,
private readonly int $page,
private readonly int $perPage,
) {
}
public function getTagId(): UuidInterface
{
return $this->tagId;
}
public function getQuery(): ?string
{
return $this->query;
}
public function getPage(): int
{
return $this->page;
}
public function getPerPage(): int
{
return $this->perPage;
}
}

View File

@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace MyTube\Handling\Tag\Handler\Query\ReadVideoList;
use Ramsey\Uuid\UuidInterface;
class ReadVideoListQueryBuilder
{
public function build(
UuidInterface $tagId,
?string $query,
int $page,
int $perPage,
): ReadVideoListQuery {
return new ReadVideoListQuery(
$tagId,
$query,
$page,
$perPage,
);
}
}

View File

@ -0,0 +1,51 @@
<?php
declare(strict_types=1);
namespace MyTube\Handling\Tag\Handler\Query\ReadVideoList;
use MyTube\Data\Business\Repository\TagRepository;
use MyTube\Data\Business\Repository\VideoRepository;
use MyTube\Handling\Tag\Exception\TagNotFoundByIdException;
use Reinfi\DependencyInjection\Annotation\InjectDoctrineRepository;
class ReadVideoListQueryHandler
{
/**
* @InjectDoctrineRepository(
* entityManager="MyTube\Data\Business\Manager\MyTubeEntityManager",
* entity="MyTube\Data\Business\Entity\Tag"
* )
* @InjectDoctrineRepository(
* entityManager="MyTube\Data\Business\Manager\MyTubeEntityManager",
* entity="MyTube\Data\Business\Entity\Video"
* )
*/
public function __construct(
private readonly TagRepository $tagRepository,
private readonly VideoRepository $videoRepository,
) {
}
/**
* @throws TagNotFoundByIdException
*/
public function execute(ReadVideoListQuery $readVideoListQuery): ReadVideoListQueryResult
{
$tagId = $readVideoListQuery->getTagId();
$tag = $this->tagRepository->findOneBy(['id' => $tagId]);
if ($tag === null) {
throw new TagNotFoundByIdException($tagId);
}
return new ReadVideoListQueryResult(
$this->videoRepository->findByFilter(
query: $readVideoListQuery->getQuery(),
page: $readVideoListQuery->getPage(),
perPage: $readVideoListQuery->getPerPage(),
tag: $tag
)
);
}
}

View File

@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
namespace MyTube\Handling\Tag\Handler\Query\ReadVideoList;
use Doctrine\ORM\Tools\Pagination\Paginator;
class ReadVideoListQueryResult
{
public function __construct(
private readonly Paginator $paginator
) {
}
public function getPaginator(): Paginator
{
return $this->paginator;
}
}

View File

@ -12,6 +12,6 @@ return [
/// CQRS /// CQRS
// ReadList // ReadList
ReadListQueryBuilder::class => AutoWiringFactory::class, ReadListQueryBuilder::class => AutoWiringFactory::class,
ReadListQueryHandler::class => AutoWiringFactory::class, ReadListQueryHandler::class => InjectionFactory::class,
], ],
]; ];

View File

@ -8,8 +8,6 @@ class ReadListQuery
{ {
public function __construct( public function __construct(
private readonly ?string $query, private readonly ?string $query,
private readonly int $page,
private readonly int $perPage,
) { ) {
} }
@ -17,14 +15,4 @@ class ReadListQuery
{ {
return $this->query; return $this->query;
} }
public function getPage(): int
{
return $this->page;
}
public function getPerPage(): int
{
return $this->perPage;
}
} }

View File

@ -8,13 +8,9 @@ class ReadListQueryBuilder
{ {
public function build( public function build(
?string $query, ?string $query,
int $page,
int $perPage,
): ReadListQuery { ): ReadListQuery {
return new ReadListQuery( return new ReadListQuery(
$query, $query,
$page,
$perPage,
); );
} }
} }

View File

@ -25,8 +25,6 @@ class ReadListQueryHandler
return new ReadListQueryResult( return new ReadListQueryResult(
$this->tagRepository->findByFilter( $this->tagRepository->findByFilter(
$readListQuery->getQuery(), $readListQuery->getQuery(),
$readListQuery->getPage(),
$readListQuery->getPerPage()
) )
); );
} }

View File

@ -4,17 +4,15 @@ declare(strict_types=1);
namespace MyTube\Handling\TagList\Handler\Query\ReadList; namespace MyTube\Handling\TagList\Handler\Query\ReadList;
use Doctrine\ORM\Tools\Pagination\Paginator;
class ReadListQueryResult class ReadListQueryResult
{ {
public function __construct( public function __construct(
private readonly Paginator $paginator private readonly array $items
) { ) {
} }
public function getPaginator(): Paginator public function getItems(): array
{ {
return $this->paginator; return $this->items;
} }
} }

View File

@ -24,9 +24,9 @@ class ReadListQueryHandler
{ {
return new ReadListQueryResult( return new ReadListQueryResult(
$this->videoRepository->findByFilter( $this->videoRepository->findByFilter(
$readListQuery->getQuery(), query: $readListQuery->getQuery(),
$readListQuery->getPage(), page: $readListQuery->getPage(),
$readListQuery->getPerPage() perPage: $readListQuery->getPerPage()
) )
); );
} }