first nice version
This commit is contained in:
parent
fa5375e04d
commit
7c6bd31a6c
@ -20,6 +20,12 @@ $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 = $projectSourceDirectory . 'ApiDomain/' . $apiType . '/' . $apiNamespace . '/src/Handler/' . $apiHandlerName . '.php';
|
||||||
|
|
||||||
|
# Response Formatter
|
||||||
|
$apiResponseFormatterName = $apiName . 'ResponseFormatter';
|
||||||
|
$apiResponseFormatterNamespace = $projectNamespace . '\\API\\' . $apiType . '\\' . $apiNamespace . '\\ResponseFormatter';
|
||||||
|
$apiResponseFormatterUsingNamespace = $apiResponseFormatterNamespace . '\\' . $apiResponseFormatterName;
|
||||||
|
$apiResponseFormatterFilePath = $projectSourceDirectory . 'ApiDomain/' . $apiType . '/' . $apiNamespace . '/src/ResponseFormatter/' . $apiResponseFormatterName . '.php';
|
||||||
|
|
||||||
# CQRS
|
# CQRS
|
||||||
$cqrsFilePath = $projectSourceDirectory . 'HandlingDomain/' . $cqrsNamespace . '/src/Handler/' . $cqrsType . '/' . $apiName . '/';
|
$cqrsFilePath = $projectSourceDirectory . 'HandlingDomain/' . $cqrsNamespace . '/src/Handler/' . $cqrsType . '/' . $apiName . '/';
|
||||||
$cqrsName = $apiName . $cqrsType;
|
$cqrsName = $apiName . $cqrsType;
|
||||||
@ -30,6 +36,12 @@ $cqrsNamespace = $projectNamespace . '\\Handling\\' . $cqrsNamespace . '\\Handle
|
|||||||
$cqrsPath = $cqrsFilePath . $cqrsName . '.php';
|
$cqrsPath = $cqrsFilePath . $cqrsName . '.php';
|
||||||
$cqrsUsingNamespace = $cqrsNamespace . '\\' . $cqrsName;
|
$cqrsUsingNamespace = $cqrsNamespace . '\\' . $cqrsName;
|
||||||
|
|
||||||
|
# Result
|
||||||
|
$cqrsResultName = $cqrsName . 'Result';
|
||||||
|
$cqrsResultVariableName = lcfirst($cqrsResultName);
|
||||||
|
$cqrsResultPath = $cqrsFilePath . $cqrsResultName . '.php';
|
||||||
|
$cqrsResultUsingNamespace = $cqrsNamespace . '\\' . $cqrsResultName;
|
||||||
|
|
||||||
# Handler
|
# Handler
|
||||||
$cqrsHandlerName = $cqrsName . 'Handler';
|
$cqrsHandlerName = $cqrsName . 'Handler';
|
||||||
$cqrsHandlerVariableName = lcfirst($cqrsHandlerName);
|
$cqrsHandlerVariableName = lcfirst($cqrsHandlerName);
|
||||||
@ -66,16 +78,18 @@ namespace {$apiHandlerNamespace};
|
|||||||
|
|
||||||
use {$cqrsHandlerUsingNamespace};
|
use {$cqrsHandlerUsingNamespace};
|
||||||
use {$cqrsBuilderUsingNamespace};
|
use {$cqrsBuilderUsingNamespace};
|
||||||
|
use {$apiResponseFormatterUsingNamespace};
|
||||||
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;
|
||||||
use Bee\\Infrastructure\\Response\\SuccessResponse;
|
use {$projectNamespace}\\Infrastructure\\Response\\SuccessResponse;
|
||||||
|
|
||||||
class {$apiHandlerName} implements RequestHandlerInterface
|
class {$apiHandlerName} implements RequestHandlerInterface
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly {$cqrsHandlerName} \${$cqrsHandlerVariableName},
|
private readonly {$cqrsHandlerName} \${$cqrsHandlerVariableName},
|
||||||
private readonly {$cqrsBuilderName} \${$cqrsBuilderVariableName},
|
private readonly {$cqrsBuilderName} \${$cqrsBuilderVariableName},
|
||||||
|
private readonly {$apiResponseFormatterName} \$responseFormatter,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,12 +105,30 @@ class {$apiHandlerName} implements RequestHandlerInterface
|
|||||||
);
|
);
|
||||||
\$result = \$this->{$cqrsHandlerVariableName}->execute(\${$cqrsVariableName});
|
\$result = \$this->{$cqrsHandlerVariableName}->execute(\${$cqrsVariableName});
|
||||||
|
|
||||||
return new SuccessResponse('OK');
|
return new SuccessResponse(\$this->responseFormatter->format(\$result));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
";
|
";
|
||||||
writeToFile($apiHandlerFilePath, $apiHandlerFileContent);
|
writeToFile($apiHandlerFilePath, $apiHandlerFileContent);
|
||||||
|
|
||||||
|
$apiResponseFormatterFileContent = "<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace {$apiResponseFormatterNamespace};
|
||||||
|
|
||||||
|
use {$cqrsResultUsingNamespace};
|
||||||
|
|
||||||
|
class {$apiResponseFormatterName}
|
||||||
|
{
|
||||||
|
public function format({$cqrsResultName} \${$cqrsResultVariableName}): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
";
|
||||||
|
writeToFile($apiResponseFormatterFilePath, $apiResponseFormatterFileContent);
|
||||||
|
|
||||||
$cqrsFileContent = "<?php
|
$cqrsFileContent = "<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
@ -109,12 +141,26 @@ class {$cqrsName}
|
|||||||
#TODO
|
#TODO
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#TODO
|
|
||||||
}
|
}
|
||||||
";
|
";
|
||||||
writeToFile($cqrsPath, $cqrsFileContent);
|
writeToFile($cqrsPath, $cqrsFileContent);
|
||||||
|
|
||||||
|
$cqrsResultFileContent = "<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace {$cqrsNamespace};
|
||||||
|
|
||||||
|
class {$cqrsResultName}
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
#TODO
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
";
|
||||||
|
writeToFile($cqrsResultPath, $cqrsResultFileContent);
|
||||||
|
|
||||||
$cqrsHandlerFileContent = "<?php
|
$cqrsHandlerFileContent = "<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
@ -128,8 +174,9 @@ class {$cqrsHandlerName}
|
|||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function execute({$cqrsName} \${$cqrsVariableName}): void
|
public function execute({$cqrsName} \${$cqrsVariableName}): {$cqrsResultName}
|
||||||
{
|
{
|
||||||
|
return new {$cqrsResultName}();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
";
|
";
|
||||||
|
|||||||
@ -58,6 +58,7 @@ $aggregator = new ConfigAggregator([
|
|||||||
\MyTube\Handling\UserSession\ConfigProvider::class,
|
\MyTube\Handling\UserSession\ConfigProvider::class,
|
||||||
\MyTube\Handling\Registration\ConfigProvider::class,
|
\MyTube\Handling\Registration\ConfigProvider::class,
|
||||||
\MyTube\Handling\Video\ConfigProvider::class,
|
\MyTube\Handling\Video\ConfigProvider::class,
|
||||||
|
\MyTube\Handling\VideoList\ConfigProvider::class,
|
||||||
|
|
||||||
// API
|
// API
|
||||||
/// Command
|
/// Command
|
||||||
@ -68,6 +69,7 @@ $aggregator = new ConfigAggregator([
|
|||||||
\MyTube\API\External\User\ConfigProvider::class,
|
\MyTube\API\External\User\ConfigProvider::class,
|
||||||
\MyTube\API\External\Authentication\ConfigProvider::class,
|
\MyTube\API\External\Authentication\ConfigProvider::class,
|
||||||
\MyTube\API\External\Video\ConfigProvider::class,
|
\MyTube\API\External\Video\ConfigProvider::class,
|
||||||
|
\MyTube\API\External\VideoList\ConfigProvider::class,
|
||||||
|
|
||||||
/// Internal
|
/// Internal
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,7 @@ final class Version20240214194156 extends AbstractMigration
|
|||||||
$sql = "CREATE TABLE video (
|
$sql = "CREATE TABLE video (
|
||||||
id binary(16) NOT NULL,
|
id binary(16) NOT NULL,
|
||||||
title varchar(255) NOT NULL,
|
title varchar(255) NOT NULL,
|
||||||
file_path varchar(255) NOT NULL,
|
directory_path varchar(255) NOT NULL,
|
||||||
created_at datetime NOT NULL,
|
created_at datetime NOT NULL,
|
||||||
updated_at datetime NOT NULL,
|
updated_at datetime NOT NULL,
|
||||||
PRIMARY KEY (id)
|
PRIMARY KEY (id)
|
||||||
|
|||||||
31
data/migrations/myTube/Version20240223130626.php
Normal file
31
data/migrations/myTube/Version20240223130626.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MyTube\Migrations\MyTube;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20240223130626 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,6 +5,8 @@ upstream host-backend-app {
|
|||||||
server {
|
server {
|
||||||
listen 80 default_server;
|
listen 80 default_server;
|
||||||
|
|
||||||
|
client_max_body_size 1000M;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
fastcgi_pass host-backend-app;
|
fastcgi_pass host-backend-app;
|
||||||
fastcgi_index index.php;
|
fastcgi_index index.php;
|
||||||
|
|||||||
5
docker/php/config/uploads.ini
Normal file
5
docker/php/config/uploads.ini
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
file_uploads = On
|
||||||
|
memory_limit = 1000M
|
||||||
|
upload_max_filesize = 1000M
|
||||||
|
post_max_size = 1000M
|
||||||
|
max_execution_time = 600
|
||||||
@ -2,6 +2,7 @@ FROM php:8.1-fpm
|
|||||||
|
|
||||||
RUN apt-get -y update
|
RUN apt-get -y update
|
||||||
RUN apt-get -y install git
|
RUN apt-get -y install git
|
||||||
|
RUN apt-get install -y ffmpeg
|
||||||
|
|
||||||
RUN chown -R www-data:www-data /var/www/html
|
RUN chown -R www-data:www-data /var/www/html
|
||||||
WORKDIR /var/www/html
|
WORKDIR /var/www/html
|
||||||
@ -12,4 +13,6 @@ RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local
|
|||||||
RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo
|
RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo
|
||||||
USER docker
|
USER docker
|
||||||
|
|
||||||
|
COPY docker/php/config/uploads.ini /usr/local/etc/php/conf.d
|
||||||
|
|
||||||
CMD ["php-fpm"]
|
CMD ["php-fpm"]
|
||||||
23
src/ApiDomain/External/Video/config/routes.php
vendored
23
src/ApiDomain/External/Video/config/routes.php
vendored
@ -1,22 +1,41 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use MyTube\API\External\Video\Handler\ReadDetailsHandler;
|
||||||
use MyTube\API\External\Video\Handler\StreamHandler;
|
use MyTube\API\External\Video\Handler\StreamHandler;
|
||||||
|
use MyTube\API\External\Video\Handler\ThumbnailHandler;
|
||||||
|
use MyTube\API\External\Video\Handler\UploadHandler;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
[
|
[
|
||||||
'name' => 'video.stream',
|
'name' => 'video.stream',
|
||||||
'path' => '/api/video/stream[/]',
|
'path' => '/api/video/stream/:videoUuid[/]',
|
||||||
'allowed_methods' => ['GET'],
|
'allowed_methods' => ['GET'],
|
||||||
'middleware' => [
|
'middleware' => [
|
||||||
StreamHandler::class
|
StreamHandler::class
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'name' => 'video.thumbnail',
|
||||||
|
'path' => '/api/video/thumbnail/:videoUuid[/]',
|
||||||
|
'allowed_methods' => ['GET'],
|
||||||
|
'middleware' => [
|
||||||
|
ThumbnailHandler::class
|
||||||
|
],
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'name' => 'video.upload',
|
'name' => 'video.upload',
|
||||||
'path' => '/api/video/upload[/]',
|
'path' => '/api/video/upload[/]',
|
||||||
'allowed_methods' => ['POST'],
|
'allowed_methods' => ['POST'],
|
||||||
'middleware' => [
|
'middleware' => [
|
||||||
StreamHandler::class
|
UploadHandler::class
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'video.read-details',
|
||||||
|
'path' => '/api/video/read-details[/]',
|
||||||
|
'allowed_methods' => ['POST'],
|
||||||
|
'middleware' => [
|
||||||
|
ReadDetailsHandler::class
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
@ -1,10 +1,19 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use MyTube\API\External\Video\Handler\ReadDetailsHandler;
|
||||||
use MyTube\API\External\Video\Handler\StreamHandler;
|
use MyTube\API\External\Video\Handler\StreamHandler;
|
||||||
|
use MyTube\API\External\Video\Handler\ThumbnailHandler;
|
||||||
|
use MyTube\API\External\Video\Handler\UploadHandler;
|
||||||
|
use MyTube\API\External\Video\ResponseFormatter\ReadDetailsResponseFormatter;
|
||||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'factories' => [
|
'factories' => [
|
||||||
StreamHandler::class => AutoWiringFactory::class
|
ThumbnailHandler::class => AutoWiringFactory::class,
|
||||||
|
StreamHandler::class => AutoWiringFactory::class,
|
||||||
|
UploadHandler::class => AutoWiringFactory::class,
|
||||||
|
ReadDetailsHandler::class => AutoWiringFactory::class,
|
||||||
|
|
||||||
|
ReadDetailsResponseFormatter::class => AutoWiringFactory::class,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
43
src/ApiDomain/External/Video/src/Handler/ReadDetailsHandler.php
vendored
Normal file
43
src/ApiDomain/External/Video/src/Handler/ReadDetailsHandler.php
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MyTube\API\External\Video\Handler;
|
||||||
|
|
||||||
|
use MyTube\Handling\Video\Exception\VideoNotFoundByIdException;
|
||||||
|
use MyTube\Handling\Video\Handler\Query\ReadDetails\ReadDetailsQueryHandler;
|
||||||
|
use MyTube\Handling\Video\Handler\Query\ReadDetails\ReadDetailsQueryBuilder;
|
||||||
|
use MyTube\API\External\Video\ResponseFormatter\ReadDetailsResponseFormatter;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
use MyTube\Infrastructure\Response\SuccessResponse;
|
||||||
|
use Ramsey\Uuid\Uuid;
|
||||||
|
|
||||||
|
class ReadDetailsHandler implements RequestHandlerInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly ReadDetailsQueryHandler $readDetailsQueryHandler,
|
||||||
|
private readonly ReadDetailsQueryBuilder $readDetailsQueryBuilder,
|
||||||
|
private readonly ReadDetailsResponseFormatter $responseFormatter,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws VideoNotFoundByIdException
|
||||||
|
*/
|
||||||
|
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
$data = json_decode(
|
||||||
|
$request->getBody()->getContents(),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
$readDetailsQuery = $this->readDetailsQueryBuilder->build(
|
||||||
|
Uuid::fromString($data['videoId'])
|
||||||
|
);
|
||||||
|
$result = $this->readDetailsQueryHandler->execute($readDetailsQuery);
|
||||||
|
|
||||||
|
return new SuccessResponse($this->responseFormatter->format($result));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,6 +12,7 @@ use MyTube\Handling\Video\Handler\Query\Stream\StreamQueryHandler;
|
|||||||
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;
|
||||||
|
use Ramsey\Uuid\Uuid;
|
||||||
|
|
||||||
class StreamHandler implements RequestHandlerInterface
|
class StreamHandler implements RequestHandlerInterface
|
||||||
{
|
{
|
||||||
@ -23,19 +24,24 @@ class StreamHandler implements RequestHandlerInterface
|
|||||||
|
|
||||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||||
{
|
{
|
||||||
$videoPath = APP_ROOT . '/var/filestore/video.mp4';
|
$videoUuid = $request->getAttribute('videoUuid') ?? null;
|
||||||
|
|
||||||
|
if ($videoUuid === null) {
|
||||||
|
return new JsonResponse('No videoId provided');
|
||||||
|
}
|
||||||
|
|
||||||
|
$streamQuery = $this->streamQueryBuilder->build(
|
||||||
|
Uuid::fromString($videoUuid)
|
||||||
|
);
|
||||||
|
$video = $this->streamQueryHandler->execute($streamQuery);
|
||||||
|
|
||||||
if (file_exists($videoPath)) {
|
|
||||||
$stream = new VideoStream();
|
$stream = new VideoStream();
|
||||||
return $stream->streamVideo(
|
return $stream->streamVideo(
|
||||||
$videoPath,
|
$video->getDirectoryPath() . 'video.mp4',
|
||||||
[
|
[
|
||||||
'is_localPath' => true,
|
'is_localPath' => true,
|
||||||
'content_type' => 'video/mp4'
|
'content_type' => 'video/mp4'
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
return new JsonResponse("Video not found", Response::STATUS_CODE_404);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
47
src/ApiDomain/External/Video/src/Handler/ThumbnailHandler.php
vendored
Normal file
47
src/ApiDomain/External/Video/src/Handler/ThumbnailHandler.php
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MyTube\API\External\Video\Handler;
|
||||||
|
|
||||||
|
use Laminas\Diactoros\Response\JsonResponse;
|
||||||
|
use Laminas\Diactoros\Response\TextResponse;
|
||||||
|
use MyTube\Handling\Video\Handler\Query\Thumbnail\ThumbnailQueryHandler;
|
||||||
|
use MyTube\Handling\Video\Handler\Query\Thumbnail\ThumbnailQueryBuilder;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
use Ramsey\Uuid\Uuid;
|
||||||
|
|
||||||
|
class ThumbnailHandler implements RequestHandlerInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly ThumbnailQueryHandler $thumbnailQueryHandler,
|
||||||
|
private readonly ThumbnailQueryBuilder $thumbnailQueryBuilder,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
$videoUuid = $request->getAttribute('videoUuid') ?? null;
|
||||||
|
|
||||||
|
if ($videoUuid === null) {
|
||||||
|
return new JsonResponse('No videoId provided');
|
||||||
|
}
|
||||||
|
|
||||||
|
$thumbnailQuery = $this->thumbnailQueryBuilder->build(
|
||||||
|
Uuid::fromString($videoUuid)
|
||||||
|
);
|
||||||
|
$result = $this->thumbnailQueryHandler->execute($thumbnailQuery);
|
||||||
|
|
||||||
|
$filePath = $result->getVideo()->getDirectoryPath() . 'thumbnail.png';
|
||||||
|
|
||||||
|
if (!file_exists($filePath)) {
|
||||||
|
return new JsonResponse('Not Found', 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$fileContent = file_get_contents($filePath);
|
||||||
|
$response = new TextResponse($fileContent);
|
||||||
|
return $response->withHeader('Content-Type', 'image/png');
|
||||||
|
}
|
||||||
|
}
|
||||||
41
src/ApiDomain/External/Video/src/Handler/UploadHandler.php
vendored
Normal file
41
src/ApiDomain/External/Video/src/Handler/UploadHandler.php
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MyTube\API\External\Video\Handler;
|
||||||
|
|
||||||
|
use Laminas\Diactoros\Response\JsonResponse;
|
||||||
|
use Laminas\Http\Response;
|
||||||
|
use MyTube\Handling\Video\Handler\Command\Upload\UploadCommandHandler;
|
||||||
|
use MyTube\Handling\Video\Handler\Command\Upload\UploadCommandBuilder;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
use MyTube\Infrastructure\Response\SuccessResponse;
|
||||||
|
|
||||||
|
class UploadHandler implements RequestHandlerInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly UploadCommandHandler $uploadCommandHandler,
|
||||||
|
private readonly UploadCommandBuilder $uploadCommandBuilder,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
$uploadedFiles = $request->getUploadedFiles();
|
||||||
|
|
||||||
|
if (count($uploadedFiles) !== 1) {
|
||||||
|
return new JsonResponse('Uploaded more than one file', Response::STATUS_CODE_400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$uploadCommand = $this->uploadCommandBuilder->build(
|
||||||
|
$request->getUploadedFiles()['file']
|
||||||
|
);
|
||||||
|
$result = $this->uploadCommandHandler->execute($uploadCommand);
|
||||||
|
|
||||||
|
return new SuccessResponse([
|
||||||
|
'id' => $result->getId()->toString()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
20
src/ApiDomain/External/Video/src/ResponseFormatter/ReadDetailsResponseFormatter.php
vendored
Normal file
20
src/ApiDomain/External/Video/src/ResponseFormatter/ReadDetailsResponseFormatter.php
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MyTube\API\External\Video\ResponseFormatter;
|
||||||
|
|
||||||
|
use MyTube\Handling\Video\Handler\Query\ReadDetails\ReadDetailsQueryResult;
|
||||||
|
|
||||||
|
class ReadDetailsResponseFormatter
|
||||||
|
{
|
||||||
|
public function format(ReadDetailsQueryResult $readDetailsQueryResult): array
|
||||||
|
{
|
||||||
|
$video = $readDetailsQueryResult->getVideo();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'id' => $video->getId(),
|
||||||
|
'title' => $video->getTitle()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/ApiDomain/External/Video/src/ResponseFormatter/ThumbnailResponseFormatter.php
vendored
Normal file
15
src/ApiDomain/External/Video/src/ResponseFormatter/ThumbnailResponseFormatter.php
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MyTube\API\External\Video\ResponseFormatter;
|
||||||
|
|
||||||
|
use MyTube\Handling\Video\Handler\Query\Thumbnail\ThumbnailQueryResult;
|
||||||
|
|
||||||
|
class ThumbnailResponseFormatter
|
||||||
|
{
|
||||||
|
public function format(ThumbnailQueryResult $thumbnailQueryResult): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/ApiDomain/External/VideoList/config/routes.php
vendored
Normal file
14
src/ApiDomain/External/VideoList/config/routes.php
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use MyTube\API\External\VideoList\Handler\ReadListHandler;
|
||||||
|
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'name' => 'video-list.read-list',
|
||||||
|
'path' => '/api/video-list/read-list[/]',
|
||||||
|
'allowed_methods' => ['POST'],
|
||||||
|
'middleware' => [
|
||||||
|
ReadListHandler::class
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
15
src/ApiDomain/External/VideoList/config/service_manager.php
vendored
Normal file
15
src/ApiDomain/External/VideoList/config/service_manager.php
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use MyTube\API\External\Video\Handler\StreamHandler;
|
||||||
|
use MyTube\API\External\Video\Handler\UploadHandler;
|
||||||
|
use MyTube\API\External\VideoList\Handler\ReadListHandler;
|
||||||
|
use MyTube\API\External\VideoList\ResponseFormatter\ReadListResponseFormatter;
|
||||||
|
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||||
|
|
||||||
|
return [
|
||||||
|
'factories' => [
|
||||||
|
ReadListHandler::class => AutoWiringFactory::class,
|
||||||
|
|
||||||
|
ReadListResponseFormatter::class => AutoWiringFactory::class,
|
||||||
|
],
|
||||||
|
];
|
||||||
16
src/ApiDomain/External/VideoList/src/ConfigProvider.php
vendored
Normal file
16
src/ApiDomain/External/VideoList/src/ConfigProvider.php
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MyTube\API\External\VideoList;
|
||||||
|
|
||||||
|
class ConfigProvider
|
||||||
|
{
|
||||||
|
public function __invoke(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'dependencies' => require __DIR__ . './../config/service_manager.php',
|
||||||
|
'routes' => require __DIR__ . '/./../config/routes.php',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,18 +4,20 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace MyTube\API\External\VideoList\Handler;
|
namespace MyTube\API\External\VideoList\Handler;
|
||||||
|
|
||||||
|
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\Response\SuccessResponse;
|
||||||
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;
|
||||||
use Bee\Infrastructure\Response\SuccessResponse;
|
|
||||||
|
|
||||||
class ReadListHandler implements RequestHandlerInterface
|
class ReadListHandler implements RequestHandlerInterface
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly ReadListQueryHandler $readListQueryHandler,
|
private readonly ReadListQueryHandler $readListQueryHandler,
|
||||||
private readonly ReadListQueryBuilder $readListQueryBuilder,
|
private readonly ReadListQueryBuilder $readListQueryBuilder,
|
||||||
|
private readonly ReadListResponseFormatter $readListResponseFormatter,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,6 +33,6 @@ class ReadListHandler implements RequestHandlerInterface
|
|||||||
);
|
);
|
||||||
$result = $this->readListQueryHandler->execute($readListQuery);
|
$result = $this->readListQueryHandler->execute($readListQuery);
|
||||||
|
|
||||||
return new SuccessResponse('OK');
|
return new SuccessResponse($this->readListResponseFormatter->format($result));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
25
src/ApiDomain/External/VideoList/src/ResponseFormatter/ReadListResponseFormatter.php
vendored
Normal file
25
src/ApiDomain/External/VideoList/src/ResponseFormatter/ReadListResponseFormatter.php
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MyTube\API\External\VideoList\ResponseFormatter;
|
||||||
|
|
||||||
|
use MyTube\Data\Business\Entity\Video;
|
||||||
|
|
||||||
|
class ReadListResponseFormatter
|
||||||
|
{
|
||||||
|
public function format(array $videos): array
|
||||||
|
{
|
||||||
|
$result = [];
|
||||||
|
|
||||||
|
/** @var Video $video */
|
||||||
|
foreach ($videos as $video) {
|
||||||
|
$result[] = [
|
||||||
|
'title' => $video->getTitle(),
|
||||||
|
'id' => $video->getId()->toString(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -21,8 +21,8 @@ class Video {
|
|||||||
/** @ORM\Column(name="title", type="string") */
|
/** @ORM\Column(name="title", type="string") */
|
||||||
private string $title;
|
private string $title;
|
||||||
|
|
||||||
/** @ORM\Column(name="file_path", type="string") */
|
/** @ORM\Column(name="directory_path", type="string") */
|
||||||
private string $filePath;
|
private ?string $directoryPath;
|
||||||
|
|
||||||
/** @ORM\Column(name="created_at", type="datetime") */
|
/** @ORM\Column(name="created_at", type="datetime") */
|
||||||
private DateTime $createdAt;
|
private DateTime $createdAt;
|
||||||
@ -36,6 +36,7 @@ class Video {
|
|||||||
|
|
||||||
$now = new DateTime();
|
$now = new DateTime();
|
||||||
$this->setCreatedAt($now);
|
$this->setCreatedAt($now);
|
||||||
|
$this->setUpdatedAt($now);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -51,12 +52,12 @@ class Video {
|
|||||||
$this->title = $title;
|
$this->title = $title;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFilePath(): ?string {
|
public function getDirectoryPath(): ?string {
|
||||||
return $this->filePath;
|
return $this->directoryPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setFilePath(?string $filePath): void {
|
public function setDirectoryPath(?string $directoryPath): void {
|
||||||
$this->filePath = $filePath;
|
$this->directoryPath = $directoryPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCreatedAt(): DateTime {
|
public function getCreatedAt(): DateTime {
|
||||||
|
|||||||
@ -1,16 +1,41 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use MyTube\Handling\Video\Builder\VideoBuilder;
|
||||||
|
use MyTube\Handling\Video\Builder\VideoImageBuilder;
|
||||||
|
use MyTube\Handling\Video\Handler\Command\Upload\UploadCommandBuilder;
|
||||||
|
use MyTube\Handling\Video\Handler\Command\Upload\UploadCommandHandler;
|
||||||
|
use MyTube\Handling\Video\Handler\Query\ReadDetails\ReadDetailsQueryBuilder;
|
||||||
|
use MyTube\Handling\Video\Handler\Query\ReadDetails\ReadDetailsQueryHandler;
|
||||||
use MyTube\Handling\Video\Handler\Query\Stream\StreamQueryBuilder;
|
use MyTube\Handling\Video\Handler\Query\Stream\StreamQueryBuilder;
|
||||||
use MyTube\Handling\Video\Handler\Query\Stream\StreamQueryHandler;
|
use MyTube\Handling\Video\Handler\Query\Stream\StreamQueryHandler;
|
||||||
|
use MyTube\Handling\Video\Handler\Query\Thumbnail\ThumbnailQueryBuilder;
|
||||||
|
use MyTube\Handling\Video\Handler\Query\Thumbnail\ThumbnailQueryHandler;
|
||||||
|
use MyTube\Handling\Video\Uploader\VideoUploader;
|
||||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||||
use Reinfi\DependencyInjection\Factory\InjectionFactory;
|
use Reinfi\DependencyInjection\Factory\InjectionFactory;
|
||||||
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'factories' => [
|
'factories' => [
|
||||||
|
/// Uploader
|
||||||
|
VideoUploader::class => AutoWiringFactory::class,
|
||||||
|
|
||||||
|
/// Builder
|
||||||
|
VideoBuilder::class => AutoWiringFactory::class,
|
||||||
|
VideoImageBuilder::class => AutoWiringFactory::class,
|
||||||
|
|
||||||
/// CQRS
|
/// CQRS
|
||||||
// Stream Query
|
// Stream Query
|
||||||
StreamQueryHandler::class => InjectionFactory::class,
|
StreamQueryHandler::class => InjectionFactory::class,
|
||||||
StreamQueryBuilder::class => AutoWiringFactory::class,
|
StreamQueryBuilder::class => AutoWiringFactory::class,
|
||||||
|
// Thumbnail Query
|
||||||
|
ThumbnailQueryHandler::class => InjectionFactory::class,
|
||||||
|
ThumbnailQueryBuilder::class => AutoWiringFactory::class,
|
||||||
|
// Upload Command
|
||||||
|
UploadCommandHandler::class => AutoWiringFactory::class,
|
||||||
|
UploadCommandBuilder::class => AutoWiringFactory::class,
|
||||||
|
// Read Details
|
||||||
|
ReadDetailsQueryHandler::class => InjectionFactory::class,
|
||||||
|
ReadDetailsQueryBuilder::class => AutoWiringFactory::class,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
20
src/HandlingDomain/Video/src/Builder/VideoBuilder.php
Normal file
20
src/HandlingDomain/Video/src/Builder/VideoBuilder.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MyTube\Handling\Video\Builder;
|
||||||
|
|
||||||
|
use MyTube\Data\Business\Entity\Video;
|
||||||
|
|
||||||
|
class VideoBuilder
|
||||||
|
{
|
||||||
|
public function build(
|
||||||
|
string $title,
|
||||||
|
?string $directoryPath = null,
|
||||||
|
): Video
|
||||||
|
{
|
||||||
|
$video = new Video();
|
||||||
|
$video->setTitle($title);
|
||||||
|
$video->setDirectoryPath($directoryPath);
|
||||||
|
|
||||||
|
return $video;
|
||||||
|
}
|
||||||
|
}
|
||||||
38
src/HandlingDomain/Video/src/Builder/VideoImageBuilder.php
Normal file
38
src/HandlingDomain/Video/src/Builder/VideoImageBuilder.php
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MyTube\Handling\Video\Builder;
|
||||||
|
|
||||||
|
use MyTube\Data\Business\Entity\Video;
|
||||||
|
|
||||||
|
class VideoImageBuilder
|
||||||
|
{
|
||||||
|
private const FILE_NAME = 'thumbnail.png';
|
||||||
|
|
||||||
|
public function build(
|
||||||
|
Video $video,
|
||||||
|
string $timestamp = '00:00:10'
|
||||||
|
): string|null
|
||||||
|
{
|
||||||
|
$videoId = $video->getId()->toString();
|
||||||
|
|
||||||
|
$targetPath = sprintf(
|
||||||
|
'%s/%s/%s/%s',
|
||||||
|
APP_ROOT,
|
||||||
|
'var/filestore',
|
||||||
|
$videoId,
|
||||||
|
self::FILE_NAME
|
||||||
|
);
|
||||||
|
|
||||||
|
if (file_exists($targetPath)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$command = "cd /var/www/html/var/filestore/" . $videoId . "/" .
|
||||||
|
" && " .
|
||||||
|
"ffmpeg -i video.mp4 -ss " . $timestamp . " -vframes 1 " . self::FILE_NAME;
|
||||||
|
|
||||||
|
$output = shell_exec($command);
|
||||||
|
|
||||||
|
return $targetPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MyTube\Handling\Video\Exception;
|
||||||
|
|
||||||
|
use MyTube\Infrastructure\Exception\ErrorCode;
|
||||||
|
use MyTube\Infrastructure\Exception\ErrorDomain;
|
||||||
|
use MyTube\Infrastructure\Exception\Exception\MyTubeException;
|
||||||
|
use Ramsey\Uuid\UuidInterface;
|
||||||
|
|
||||||
|
class VideoNotFoundByIdException extends MyTubeException {
|
||||||
|
|
||||||
|
private const MESSAGE = 'The user with the Id %s was not found!';
|
||||||
|
|
||||||
|
public function __construct(UuidInterface $id)
|
||||||
|
{
|
||||||
|
parent::__construct(
|
||||||
|
sprintf(
|
||||||
|
self::MESSAGE,
|
||||||
|
$id->toString()
|
||||||
|
),
|
||||||
|
ErrorDomain::Video,
|
||||||
|
ErrorCode::NotFound
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MyTube\Handling\Video\Handler\Command\Upload;
|
||||||
|
|
||||||
|
use Psr\Http\Message\UploadedFileInterface;
|
||||||
|
|
||||||
|
class UploadCommand
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly UploadedFileInterface $uploadedFile,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUploadedFile(): UploadedFileInterface
|
||||||
|
{
|
||||||
|
return $this->uploadedFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MyTube\Handling\Video\Handler\Command\Upload;
|
||||||
|
|
||||||
|
use Psr\Http\Message\UploadedFileInterface;
|
||||||
|
|
||||||
|
class UploadCommandBuilder
|
||||||
|
{
|
||||||
|
public function build(
|
||||||
|
UploadedFileInterface $uploadedFile,
|
||||||
|
): UploadCommand {
|
||||||
|
return new UploadCommand(
|
||||||
|
$uploadedFile,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MyTube\Handling\Video\Handler\Command\Upload;
|
||||||
|
|
||||||
|
use MyTube\Data\Business\Entity\Video;
|
||||||
|
use MyTube\Data\Business\Manager\MyTubeEntityManager;
|
||||||
|
use MyTube\Handling\Video\Builder\VideoBuilder;
|
||||||
|
use MyTube\Handling\Video\Builder\VideoImageBuilder;
|
||||||
|
use MyTube\Handling\Video\Uploader\VideoUploader;
|
||||||
|
use Psr\Http\Message\UploadedFileInterface;
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class UploadCommandHandler
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly VideoBuilder $videoBuilder,
|
||||||
|
private readonly MyTubeEntityManager $entityManager,
|
||||||
|
private readonly VideoUploader $uploader,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function execute(UploadCommand $uploadCommand): Video
|
||||||
|
{
|
||||||
|
$uploadedFile = $uploadCommand->getUploadedFile();
|
||||||
|
|
||||||
|
$video = $this->videoBuilder->build(
|
||||||
|
$uploadedFile->getClientFilename()
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->uploader->upload(
|
||||||
|
$uploadedFile,
|
||||||
|
$video
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->entityManager->persist($video);
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
return $video;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MyTube\Handling\Video\Handler\Query\ReadDetails;
|
||||||
|
|
||||||
|
use Ramsey\Uuid\UuidInterface;
|
||||||
|
|
||||||
|
class ReadDetailsQuery
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly UuidInterface $videoId
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getVideoId(): UuidInterface
|
||||||
|
{
|
||||||
|
return $this->videoId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MyTube\Handling\Video\Handler\Query\ReadDetails;
|
||||||
|
|
||||||
|
use Ramsey\Uuid\UuidInterface;
|
||||||
|
|
||||||
|
class ReadDetailsQueryBuilder
|
||||||
|
{
|
||||||
|
public function build(
|
||||||
|
UuidInterface $videoId
|
||||||
|
): ReadDetailsQuery {
|
||||||
|
return new ReadDetailsQuery(
|
||||||
|
$videoId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MyTube\Handling\Video\Handler\Query\ReadDetails;
|
||||||
|
|
||||||
|
use MyTube\Data\Business\Entity\Video;
|
||||||
|
use MyTube\Data\Business\Repository\VideoRepository;
|
||||||
|
use MyTube\Handling\Video\Builder\VideoImageBuilder;
|
||||||
|
use MyTube\Handling\Video\Exception\VideoNotFoundByIdException;
|
||||||
|
use Reinfi\DependencyInjection\Annotation\Inject;
|
||||||
|
use Reinfi\DependencyInjection\Annotation\InjectDoctrineRepository;
|
||||||
|
|
||||||
|
class ReadDetailsQueryHandler
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @InjectDoctrineRepository(
|
||||||
|
* entityManager="MyTube\Data\Business\Manager\MyTubeEntityManager",
|
||||||
|
* entity="MyTube\Data\Business\Entity\Video"
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
private readonly VideoRepository $videoRepository,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws VideoNotFoundByIdException
|
||||||
|
*/
|
||||||
|
public function execute(ReadDetailsQuery $readDetailsQuery): ReadDetailsQueryResult
|
||||||
|
{
|
||||||
|
$videoId = $readDetailsQuery->getVideoId();
|
||||||
|
|
||||||
|
/** @var Video $video */
|
||||||
|
$video = $this->videoRepository->findOneBy(['id' => $videoId]);
|
||||||
|
|
||||||
|
if ($video === null) {
|
||||||
|
throw new VideoNotFoundByIdException($videoId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ReadDetailsQueryResult($video);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MyTube\Handling\Video\Handler\Query\ReadDetails;
|
||||||
|
|
||||||
|
use MyTube\Data\Business\Entity\Video;
|
||||||
|
|
||||||
|
class ReadDetailsQueryResult
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly Video $video
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getVideo(): Video
|
||||||
|
{
|
||||||
|
return $this->video;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,12 +4,17 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace MyTube\Handling\Video\Handler\Query\Stream;
|
namespace MyTube\Handling\Video\Handler\Query\Stream;
|
||||||
|
|
||||||
|
use Ramsey\Uuid\UuidInterface;
|
||||||
|
|
||||||
class StreamQuery
|
class StreamQuery
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
#TODO
|
private readonly UuidInterface $videoUuid,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#TODO
|
public function getVideoUuid(): UuidInterface
|
||||||
|
{
|
||||||
|
return $this->videoUuid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,13 +4,15 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace MyTube\Handling\Video\Handler\Query\Stream;
|
namespace MyTube\Handling\Video\Handler\Query\Stream;
|
||||||
|
|
||||||
|
use Ramsey\Uuid\UuidInterface;
|
||||||
|
|
||||||
class StreamQueryBuilder
|
class StreamQueryBuilder
|
||||||
{
|
{
|
||||||
public function build(
|
public function build(
|
||||||
#TODO
|
UuidInterface $videoUuid,
|
||||||
): StreamQuery {
|
): StreamQuery {
|
||||||
return new StreamQuery(
|
return new StreamQuery(
|
||||||
#TODO
|
$videoUuid,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,14 +4,34 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace MyTube\Handling\Video\Handler\Query\Stream;
|
namespace MyTube\Handling\Video\Handler\Query\Stream;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use MyTube\Data\Business\Entity\Video;
|
||||||
|
use MyTube\Data\Business\Repository\VideoRepository;
|
||||||
|
use Reinfi\DependencyInjection\Annotation\InjectDoctrineRepository;
|
||||||
|
|
||||||
class StreamQueryHandler
|
class StreamQueryHandler
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @InjectDoctrineRepository(
|
||||||
|
* entityManager="MyTube\Data\Business\Manager\MyTubeEntityManager",
|
||||||
|
* entity="MyTube\Data\Business\Entity\Video"
|
||||||
|
* )
|
||||||
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
#TODO
|
private readonly VideoRepository $videoRepository,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function execute(StreamQuery $streamQuery): void
|
public function execute(StreamQuery $streamQuery): Video
|
||||||
{
|
{
|
||||||
|
$video = $this->videoRepository->findOneBy([
|
||||||
|
'id' => $streamQuery->getVideoUuid()
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($video === null) {
|
||||||
|
throw new Exception('Video not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $video;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MyTube\Handling\Video\Handler\Query\Thumbnail;
|
||||||
|
|
||||||
|
use Ramsey\Uuid\UuidInterface;
|
||||||
|
|
||||||
|
class ThumbnailQuery
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly UuidInterface $videoUuid,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getVideoUuid(): UuidInterface
|
||||||
|
{
|
||||||
|
return $this->videoUuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MyTube\Handling\Video\Handler\Query\Thumbnail;
|
||||||
|
|
||||||
|
use Ramsey\Uuid\UuidInterface;
|
||||||
|
|
||||||
|
class ThumbnailQueryBuilder
|
||||||
|
{
|
||||||
|
public function build(
|
||||||
|
UuidInterface $videoUuid,
|
||||||
|
): ThumbnailQuery {
|
||||||
|
return new ThumbnailQuery(
|
||||||
|
$videoUuid,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MyTube\Handling\Video\Handler\Query\Thumbnail;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use MyTube\Data\Business\Entity\Video;
|
||||||
|
use MyTube\Data\Business\Repository\VideoRepository;
|
||||||
|
use Reinfi\DependencyInjection\Annotation\InjectDoctrineRepository;
|
||||||
|
|
||||||
|
class ThumbnailQueryHandler
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @InjectDoctrineRepository(
|
||||||
|
* entityManager="MyTube\Data\Business\Manager\MyTubeEntityManager",
|
||||||
|
* entity="MyTube\Data\Business\Entity\Video"
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
private readonly VideoRepository $videoRepository,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(ThumbnailQuery $streamQuery): ThumbnailQueryResult
|
||||||
|
{
|
||||||
|
/** @var Video $video */
|
||||||
|
$video = $this->videoRepository->findOneBy([
|
||||||
|
'id' => $streamQuery->getVideoUuid()
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($video === null) {
|
||||||
|
throw new Exception('Video not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ThumbnailQueryResult($video);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MyTube\Handling\Video\Handler\Query\Thumbnail;
|
||||||
|
|
||||||
|
use MyTube\Data\Business\Entity\Video;
|
||||||
|
|
||||||
|
class ThumbnailQueryResult
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly Video $video
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getVideo(): Video
|
||||||
|
{
|
||||||
|
return $this->video;
|
||||||
|
}
|
||||||
|
}
|
||||||
40
src/HandlingDomain/Video/src/Uploader/VideoUploader.php
Normal file
40
src/HandlingDomain/Video/src/Uploader/VideoUploader.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MyTube\Handling\Video\Uploader;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use MyTube\Data\Business\Entity\Video;
|
||||||
|
use MyTube\Handling\Video\Builder\VideoImageBuilder;
|
||||||
|
use Psr\Http\Message\UploadedFileInterface;
|
||||||
|
|
||||||
|
class VideoUploader
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly VideoImageBuilder $imageBuilder,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function upload(
|
||||||
|
UploadedFileInterface $file,
|
||||||
|
Video $video,
|
||||||
|
): void {
|
||||||
|
$targetPath = sprintf(
|
||||||
|
'%s/%s/%s/',
|
||||||
|
APP_ROOT,
|
||||||
|
'var/filestore',
|
||||||
|
$video->getId()->toString(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (file_exists($targetPath)) {
|
||||||
|
throw new Exception('File already exists');
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir($targetPath, 0777, true);
|
||||||
|
$video->setDirectoryPath($targetPath);
|
||||||
|
|
||||||
|
$targetPath = $targetPath . 'video.' . substr(strrchr($file->getClientFilename(),'.'),1);
|
||||||
|
$file->moveTo($targetPath);
|
||||||
|
|
||||||
|
$this->imageBuilder->build($video);
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/HandlingDomain/VideoList/config/service_manager.php
Normal file
21
src/HandlingDomain/VideoList/config/service_manager.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use MyTube\Handling\Video\Builder\VideoBuilder;
|
||||||
|
use MyTube\Handling\Video\Handler\Command\Upload\UploadCommandBuilder;
|
||||||
|
use MyTube\Handling\Video\Handler\Command\Upload\UploadCommandHandler;
|
||||||
|
use MyTube\Handling\Video\Handler\Query\Stream\StreamQueryBuilder;
|
||||||
|
use MyTube\Handling\Video\Handler\Query\Stream\StreamQueryHandler;
|
||||||
|
use MyTube\Handling\VideoList\Handler\Query\ReadList\ReadListQueryBuilder;
|
||||||
|
use MyTube\Handling\VideoList\Handler\Query\ReadList\ReadListQueryHandler;
|
||||||
|
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||||
|
use Reinfi\DependencyInjection\Factory\InjectionFactory;
|
||||||
|
|
||||||
|
|
||||||
|
return [
|
||||||
|
'factories' => [
|
||||||
|
/// CQRS
|
||||||
|
// Read List
|
||||||
|
ReadListQueryHandler::class => InjectionFactory::class,
|
||||||
|
ReadListQueryBuilder::class => AutoWiringFactory::class,
|
||||||
|
],
|
||||||
|
];
|
||||||
15
src/HandlingDomain/VideoList/src/ConfigProvider.php
Normal file
15
src/HandlingDomain/VideoList/src/ConfigProvider.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MyTube\Handling\VideoList;
|
||||||
|
|
||||||
|
class ConfigProvider
|
||||||
|
{
|
||||||
|
public function __invoke(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'dependencies' => require __DIR__ . '/./../config/service_manager.php',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,14 +4,24 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace MyTube\Handling\VideoList\Handler\Query\ReadList;
|
namespace MyTube\Handling\VideoList\Handler\Query\ReadList;
|
||||||
|
|
||||||
|
use MyTube\Data\Business\Repository\VideoRepository;
|
||||||
|
use Reinfi\DependencyInjection\Annotation\InjectDoctrineRepository;
|
||||||
|
|
||||||
class ReadListQueryHandler
|
class ReadListQueryHandler
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @InjectDoctrineRepository(
|
||||||
|
* entityManager="MyTube\Data\Business\Manager\MyTubeEntityManager",
|
||||||
|
* entity="MyTube\Data\Business\Entity\Video"
|
||||||
|
* )
|
||||||
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
#TODO
|
private readonly VideoRepository $videoRepository
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function execute(ReadListQuery $readListQuery): void
|
public function execute(ReadListQuery $readListQuery): array
|
||||||
{
|
{
|
||||||
|
return $this->videoRepository->findAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,4 +10,5 @@ enum ErrorDomain : string {
|
|||||||
case UserPassword = 'UserPassword';
|
case UserPassword = 'UserPassword';
|
||||||
case Registration = 'Registration';
|
case Registration = 'Registration';
|
||||||
case Product = 'Product';
|
case Product = 'Product';
|
||||||
|
case Video = 'Video';
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user