paginated list

This commit is contained in:
Flo 2024-02-24 20:16:24 +01:00
parent 3f97413c4e
commit 0201c5c559
11 changed files with 141 additions and 32 deletions

View File

@ -15,19 +15,22 @@ $apiName = $argv[3];
$cqrsType = strtolower($argv[4]) === 'true' ? 'Command' : 'Query'; $cqrsType = strtolower($argv[4]) === 'true' ? 'Command' : 'Query';
$cqrsNamespace = $argv[5]; $cqrsNamespace = $argv[5];
$apiDirectoryPath = $projectSourceDirectory . 'ApiDomain/' . $apiType . '/' . $apiNamespace . '/';
$cqrsDirectoryPath = $projectSourceDirectory . 'HandlingDomain/' . $cqrsNamespace . '/';
# API Handler # API Handler
$apiHandlerName = $apiName . 'Handler'; $apiHandlerName = $apiName . 'Handler';
$apiHandlerNamespace = $projectNamespace . '\\API\\' . $apiType . '\\' . $apiNamespace . '\\Handler'; $apiHandlerNamespace = $projectNamespace . '\\API\\' . $apiType . '\\' . $apiNamespace . '\\Handler';
$apiHandlerFilePath = $projectSourceDirectory . 'ApiDomain/' . $apiType . '/' . $apiNamespace . '/src/Handler/' . $apiHandlerName . '.php'; $apiHandlerFilePath = $apiDirectoryPath . 'src/Handler/' . $apiHandlerName . '.php';
# Response Formatter # Response Formatter
$apiResponseFormatterName = $apiName . 'ResponseFormatter'; $apiResponseFormatterName = $apiName . 'ResponseFormatter';
$apiResponseFormatterNamespace = $projectNamespace . '\\API\\' . $apiType . '\\' . $apiNamespace . '\\ResponseFormatter'; $apiResponseFormatterNamespace = $projectNamespace . '\\API\\' . $apiType . '\\' . $apiNamespace . '\\ResponseFormatter';
$apiResponseFormatterUsingNamespace = $apiResponseFormatterNamespace . '\\' . $apiResponseFormatterName; $apiResponseFormatterUsingNamespace = $apiResponseFormatterNamespace . '\\' . $apiResponseFormatterName;
$apiResponseFormatterFilePath = $projectSourceDirectory . 'ApiDomain/' . $apiType . '/' . $apiNamespace . '/src/ResponseFormatter/' . $apiResponseFormatterName . '.php'; $apiResponseFormatterFilePath = $apiDirectoryPath . 'src/ResponseFormatter/' . $apiResponseFormatterName . '.php';
# CQRS # CQRS
$cqrsFilePath = $projectSourceDirectory . 'HandlingDomain/' . $cqrsNamespace . '/src/Handler/' . $cqrsType . '/' . $apiName . '/'; $cqrsFilePath = $cqrsDirectoryPath . 'src/Handler/' . $cqrsType . '/' . $apiName . '/';
$cqrsName = $apiName . $cqrsType; $cqrsName = $apiName . $cqrsType;
$cqrsVariableName = lcfirst($cqrsName); $cqrsVariableName = lcfirst($cqrsName);
$cqrsNamespace = $projectNamespace . '\\Handling\\' . $cqrsNamespace . '\\Handler\\' . $cqrsType . '\\' . $apiName; $cqrsNamespace = $projectNamespace . '\\Handling\\' . $cqrsNamespace . '\\Handler\\' . $cqrsType . '\\' . $apiName;
@ -70,6 +73,11 @@ function writeToFile($path, $content) {
file_put_contents($path, $content); file_put_contents($path, $content);
} }
if (!file_exists($apiDirectoryPath)) {
$routesFilePath = $apiDirectoryPath . 'config/routes.php';
$serviceManagerFilePath = $apiDirectoryPath . 'config/service_manager.php';
}
$apiHandlerFileContent = "<?php $apiHandlerFileContent = "<?php
declare(strict_types=1); declare(strict_types=1);

View File

@ -3,6 +3,7 @@
declare(strict_types=1); declare(strict_types=1);
use MyTube\Infrastructure\Exception\Middleware\MyTubeExceptionHandlerMiddleware; use MyTube\Infrastructure\Exception\Middleware\MyTubeExceptionHandlerMiddleware;
use MyTube\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use MyTube\Infrastructure\Request\Middleware\AnalyzeHeaderMiddleware; use MyTube\Infrastructure\Request\Middleware\AnalyzeHeaderMiddleware;
use MyTube\Infrastructure\Session\Middleware\SessionMiddleware; use MyTube\Infrastructure\Session\Middleware\SessionMiddleware;
use Laminas\Stratigility\Middleware\ErrorHandler; use Laminas\Stratigility\Middleware\ErrorHandler;
@ -69,6 +70,7 @@ return function (Application $app, MiddlewareFactory $factory, ContainerInterfac
//// Pre MyTube Space //// Pre MyTube Space
$app->pipe(MyTubeExceptionHandlerMiddleware::class); $app->pipe(MyTubeExceptionHandlerMiddleware::class);
$app->pipe(AnalyzeHeaderMiddleware::class); $app->pipe(AnalyzeHeaderMiddleware::class);
$app->pipe(AnalyzeBodyMiddleware::class);
//// MyTube Space //// MyTube Space
$app->pipe(SessionMiddleware::class); $app->pipe(SessionMiddleware::class);

View File

@ -1,4 +1,5 @@
file_uploads = On file_uploads = On
max_file_uploads = 1000
memory_limit = 10000M memory_limit = 10000M
upload_max_filesize = 10000M upload_max_filesize = 10000M
post_max_size = 10000M post_max_size = 10000M

View File

@ -7,6 +7,7 @@ namespace MyTube\API\External\VideoList\Handler;
use MyTube\API\External\VideoList\ResponseFormatter\ReadListResponseFormatter; use MyTube\API\External\VideoList\ResponseFormatter\ReadListResponseFormatter;
use MyTube\Handling\VideoList\Handler\Query\ReadList\ReadListQueryHandler; use MyTube\Handling\VideoList\Handler\Query\ReadList\ReadListQueryHandler;
use MyTube\Handling\VideoList\Handler\Query\ReadList\ReadListQueryBuilder; use MyTube\Handling\VideoList\Handler\Query\ReadList\ReadListQueryBuilder;
use MyTube\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use MyTube\Infrastructure\Response\SuccessResponse; use MyTube\Infrastructure\Response\SuccessResponse;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
@ -23,13 +24,12 @@ class ReadListHandler 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
);
$readListQuery = $this->readListQueryBuilder->build( $readListQuery = $this->readListQueryBuilder->build(
$data $data['query'] ?? null,
$data['page'],
$data['perPage'],
); );
$result = $this->readListQueryHandler->execute($readListQuery); $result = $this->readListQueryHandler->execute($readListQuery);

View File

@ -6,12 +6,16 @@ namespace MyTube\API\External\VideoList\ResponseFormatter;
use MyTube\Data\Business\Entity\Tag; use MyTube\Data\Business\Entity\Tag;
use MyTube\Data\Business\Entity\Video; use MyTube\Data\Business\Entity\Video;
use MyTube\Handling\VideoList\Handler\Query\ReadList\ReadListQueryResult;
class ReadListResponseFormatter class ReadListResponseFormatter
{ {
public function format(array $videos): array public function format(ReadListQueryResult $queryResult): array
{ {
$result = []; $paginator = $queryResult->getPaginator();
$videos = $paginator->getIterator();
$items = [];
/** @var Video $video */ /** @var Video $video */
foreach ($videos as $video) { foreach ($videos as $video) {
@ -22,13 +26,16 @@ class ReadListResponseFormatter
$tags[] = $tag->getDescription(); $tags[] = $tag->getDescription();
} }
$result[] = [ $items[] = [
'title' => $video->getTitle(), 'title' => $video->getTitle(),
'id' => $video->getId()->toString(), 'id' => $video->getId()->toString(),
'tags' => $tags 'tags' => $tags
]; ];
} }
return $result; return [
'total' => $paginator->count(),
'items' => $items,
];
} }
} }

View File

@ -8,21 +8,24 @@ use Doctrine\ORM\EntityRepository;
class VideoRepository extends EntityRepository { class VideoRepository extends EntityRepository {
public function findByFilter( public function findByFilter(
string $identifier ?string $query,
int $page,
int $perPage,
): Paginator ): Paginator
{ {
$queryBuilder = $this->createQueryBuilder('r'); $queryBuilder = $this->createQueryBuilder('v');
$queryBuilder->where(
$queryBuilder->expr()->orX(
$queryBuilder->expr()->eq('r.username', ':identifier'),
$queryBuilder->expr()->eq('r.mail', ':identifier')
)
)
->setParameter('identifier', $identifier);
$query = $queryBuilder->getQuery();
/** @var ?Registration $registration */ if ($query !== null) {
$registration = $query->execute()[0] ?? null; $query = '%'.$query.'%';
return $registration;
$queryBuilder
->where('v.title like :query')
->setParameter('query', $query);
}
$queryBuilder->setFirstResult($perPage * ($page - 1));
$queryBuilder->setMaxResults($perPage);
return new Paginator($queryBuilder->getQuery());
} }
} }

View File

@ -7,9 +7,24 @@ namespace MyTube\Handling\VideoList\Handler\Query\ReadList;
class ReadListQuery class ReadListQuery
{ {
public function __construct( public function __construct(
#TODO private readonly ?string $query,
private readonly int $page,
private readonly int $perPage,
) { ) {
} }
#TODO public function getQuery(): ?string
{
return $this->query;
}
public function getPage(): int
{
return $this->page;
}
public function getPerPage(): int
{
return $this->perPage;
}
} }

View File

@ -7,10 +7,14 @@ namespace MyTube\Handling\VideoList\Handler\Query\ReadList;
class ReadListQueryBuilder class ReadListQueryBuilder
{ {
public function build( public function build(
#TODO ?string $query,
int $page,
int $perPage,
): ReadListQuery { ): ReadListQuery {
return new ReadListQuery( return new ReadListQuery(
#TODO $query,
$page,
$perPage,
); );
} }
} }

View File

@ -20,8 +20,14 @@ class ReadListQueryHandler
) { ) {
} }
public function execute(ReadListQuery $readListQuery): array public function execute(ReadListQuery $readListQuery): ReadListQueryResult
{ {
return $this->videoRepository->findAll(); return new ReadListQueryResult(
$this->videoRepository->findByFilter(
$readListQuery->getQuery(),
$readListQuery->getPage(),
$readListQuery->getPerPage()
)
);
} }
} }

View File

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

View File

@ -0,0 +1,43 @@
<?php
namespace MyTube\Infrastructure\Request\Middleware;
use MyTube\Data\Business\Entity\Permission;
use MyTube\Data\Business\Entity\User;
use MyTube\Infrastructure\Response\ForbiddenResponse;
use MyTube\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
use Laminas\Config\Config;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Reinfi\DependencyInjection\Annotation\InjectConfig;
class AnalyzeBodyMiddleware implements MiddlewareInterface
{
const JSON_DATA = 'json_data_attribute';
private const CONTENT_TYPE_HEADER = 'Content-Type';
private const CONTENT_TYPE_APPLICATION_JSON = 'application/json';
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface
{
$jsonData = [];
$contentType = $request->getHeaderLine(self::CONTENT_TYPE_HEADER);
if (str_contains($contentType, self::CONTENT_TYPE_APPLICATION_JSON)) {
$jsonData = json_decode(
$request->getBody()->getContents(),
true
);
}
return $handler->handle($request->withAttribute(
self::JSON_DATA,
$jsonData
));
}
}