From 7bc87126c3fb8ca5b51172e9c39eca1c817f8bac Mon Sep 17 00:00:00 2001 From: parker <67624778+xsga@users.noreply.github.com> Date: Thu, 6 Jun 2024 11:11:27 +0000 Subject: [PATCH 01/39] Slim app gets with routes --- config/app/SlimApp.php | 3 +++ public/index.php | 4 +--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/config/app/SlimApp.php b/config/app/SlimApp.php index c03b974..b183c1f 100644 --- a/config/app/SlimApp.php +++ b/config/app/SlimApp.php @@ -24,5 +24,8 @@ function getSlimApp(ContainerInterface $container): App $errorMiddleware = $app->addErrorMiddleware($container->get('getErrorDetail'), true, true); $errorMiddleware->setDefaultErrorHandler(ErrorHandler::class); + // Load routes. + getRoutes($app); + return $app; } \ No newline at end of file diff --git a/public/index.php b/public/index.php index 8dde18c..589d7a3 100644 --- a/public/index.php +++ b/public/index.php @@ -12,10 +12,8 @@ bootstrap(); $container = getDIContainer(); -$logger = $container->get(LoggerInterface::class); $slimApp = getSlimApp($container, filter_var($_ENV['ERROR_DETAIL'], FILTER_VALIDATE_BOOLEAN), $_ENV['URL_PATH']); - -getRoutes($slimApp); +$logger = $container->get(LoggerInterface::class); $requestMethod = $_SERVER['REQUEST_METHOD'] ?? 'METHOD_NOT_FOUND'; $requestUri = $_SERVER['REQUEST_URI'] ?? 'URI_NOT_FOUND'; From 619815a0356eb602ab3ef0ef0c12ff7196512ed8 Mon Sep 17 00:00:00 2001 From: parker <67624778+xsga@users.noreply.github.com> Date: Thu, 6 Jun 2024 14:22:24 +0000 Subject: [PATCH 02/39] Fix error --- .../Repositories/DoctrineUsersRepository.php | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Repositories/DoctrineUsersRepository.php b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Repositories/DoctrineUsersRepository.php index e5a28b5..f3713fb 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Repositories/DoctrineUsersRepository.php +++ b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Repositories/DoctrineUsersRepository.php @@ -82,26 +82,6 @@ public function createUser(User $user): int } } - public function updateUser(User $user): bool - { - try { - $query = $this->em->createQueryBuilder(); - - $query->update(UsersEntity::class, 'u'); - $query->set('u.name', ':userName'); - $query->set('u.updateDate', ':userUpdateDate'); - $query->setParameter(':userName', $user->name()); - $query->setParameter(':userUpdateDate', $user->updateDate()->format('Y-m-d H:i:s')); - $query->where('u.userId = ' . $user->userId()); - $query->getQuery()->execute(); - - return true; - } catch (Throwable $exception) { - $this->logger->error($exception->__toString()); - return false; - } - } - public function updatePassword(User $user): bool { try { From aa71c9f23eb832fac376c66f8f158d10f5661633 Mon Sep 17 00:00:00 2001 From: parker <67624778+xsga@users.noreply.github.com> Date: Thu, 6 Jun 2024 14:22:37 +0000 Subject: [PATCH 03/39] Update readme --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index bd9cfb7..26d7976 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,12 @@ Instructions: ``` docker compose up -d ``` +* Run `composer install` to install the project dependencies: +``` +composer install +``` +* Rename `config/.env.example` to `config/.env` to activates environment settings. +* Setup API settings edditing `config/.env` file. * Create a user using command `app:create-user`: ``` docker exec -it filmaffinityapi-web-server php .bin/console app:create-user From 00aedbe6a680b4220ba5d3aaad93db367c46d6e7 Mon Sep 17 00:00:00 2001 From: parker <67624778+xsga@users.noreply.github.com> Date: Thu, 6 Jun 2024 14:23:05 +0000 Subject: [PATCH 04/39] PSALM error level 6 --- psalm.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/psalm.xml b/psalm.xml index f85ef33..658f996 100644 --- a/psalm.xml +++ b/psalm.xml @@ -1,6 +1,6 @@ Date: Thu, 6 Jun 2024 14:23:19 +0000 Subject: [PATCH 05/39] Fix FilmParser errors --- .../Modules/Films/Domain/Parsers/FilmParser.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php index 8d2f1b1..6f232fc 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php @@ -4,6 +4,8 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers; +use DOMDocument; +use DOMXPath; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Film; final class FilmParser extends AbstractParser @@ -134,7 +136,7 @@ private function getProducers(): string $data = $this->getData(self::QUERY_FILM_GET_PRODUCERS); if (!$this->validateMultipleResult($data, 'film producers')) { - return []; + return ''; } return implode(' ', $data); @@ -232,7 +234,10 @@ private function getCoverUrl(): string return ''; } - return trim($data->item(0)->getAttribute('href')); + $xpath = new DOMXPath(new DOMDocument()); + $href = $xpath->evaluate("string(./a/@href)", $data->item(0)); + + return trim($href); } private function getCoverFile(): string @@ -244,7 +249,10 @@ private function getCoverFile(): string return ''; } - $coverUrl = trim($data->item(0)->getAttribute('href')); + $xpath = new DOMXPath(new DOMDocument()); + $href = $xpath->evaluate("string(./a/@href)", $data->item(0)); + + $coverUrl = trim($href); $coverUrlArray = explode('/', $coverUrl); $coverFile = end($coverUrlArray); From 1ead339b028fd2904cc1a16107ab50a39769d64d Mon Sep 17 00:00:00 2001 From: parker Date: Thu, 6 Jun 2024 16:54:00 +0200 Subject: [PATCH 06/39] Fix parser errors --- .../Films/Domain/Parsers/AdvancedSearchParser.php | 2 +- .../Modules/Films/Domain/Parsers/FilmParser.php | 12 +++--------- .../Films/Domain/Parsers/SimpleSearchParser.php | 9 +++++---- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php index b9bf423..9655f19 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php @@ -61,7 +61,7 @@ private function getFilmTitle(DOMXPath $domXpath): string private function getFilmId(DOMXPath $domXpath): int { $idResult = $domXpath->query(self::QUERY_ADV_SEARCH_GET_ID); - $id = $idResult->item(0)->getAttribute('data-movie-id'); + $id = $idResult->item(0)->attributes->getNamedItem('data-movie-id')->nodeValue; return (int)trim($id); } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php index 6f232fc..9b43d97 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php @@ -233,11 +233,8 @@ private function getCoverUrl(): string $this->logger->warning('Film cover URL not found'); return ''; } - - $xpath = new DOMXPath(new DOMDocument()); - $href = $xpath->evaluate("string(./a/@href)", $data->item(0)); - - return trim($href); + + return trim($data->item(0)->attributes->getNamedItem('href')->nodeValue); } private function getCoverFile(): string @@ -249,10 +246,7 @@ private function getCoverFile(): string return ''; } - $xpath = new DOMXPath(new DOMDocument()); - $href = $xpath->evaluate("string(./a/@href)", $data->item(0)); - - $coverUrl = trim($href); + $coverUrl = trim($data->item(0)->attributes->getNamedItem('href')->nodeValue); $coverUrlArray = explode('/', $coverUrl); $coverFile = end($coverUrlArray); diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php index f2edd34..241fb68 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php @@ -24,7 +24,8 @@ public function getSimpleSearchResults(): SearchResults $queyResults = $this->getData(self::QUERY_RESULTS_TYPE, false); $searchResults = match ( - ($queyResults->length > 0) && ($queyResults->item(0)->getAttribute('content') !== 'FilmAffinity') + ($queyResults->length > 0) && + ($queyResults->item(0)->attributes->getNamedItem('content')->nodeValue !== 'FilmAffinity') ) { true => $this->simpleSearchSingleResult($queyResults), false => $this->simpleSearchMultipleResults() @@ -39,8 +40,8 @@ private function simpleSearchSingleResult(DOMNodeList $data): SearchResults { $idSearch = $this->getData(self::QUERY_SINGLE_RESULT_GET_ID, false); - $idArray = explode('/', $idSearch->item(0)->getAttribute('content')); - $title = $data->item(0)->getAttribute('content'); + $idArray = explode('/', $idSearch->item(0)->attributes->getNamedItem('content')->nodeValue); + $title = $data->item(0)->attributes->getNamedItem('content')->nodeValue; $searchResult = new SingleSearchResult(); $searchResult->id = (int)trim(str_replace('film', '', str_replace('.html', '', end($idArray)))); @@ -102,6 +103,6 @@ private function getId(DOMXPath $domXpath): int { $idResult = $domXpath->query(self::QUERY_MULTIPLE_RESULTS_GET_ID); - return (int)trim($idResult->item(0)->getAttribute('data-movie-id')); + return (int)trim($idResult->item(0)->attributes->getNamedItem('data-movie-id')->nodeValue); } } From ecb13c25e5a6a51afcb873ddbfb124e57d0707d6 Mon Sep 17 00:00:00 2001 From: parker Date: Thu, 6 Jun 2024 17:59:15 +0200 Subject: [PATCH 07/39] Fix parser errors --- .../Modules/Films/Domain/Parsers/AdvancedSearchParser.php | 2 +- .../Modules/Films/Domain/Parsers/FilmParser.php | 4 ++-- .../Modules/Films/Domain/Parsers/SimpleSearchParser.php | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php index 9655f19..64c7370 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php @@ -61,7 +61,7 @@ private function getFilmTitle(DOMXPath $domXpath): string private function getFilmId(DOMXPath $domXpath): int { $idResult = $domXpath->query(self::QUERY_ADV_SEARCH_GET_ID); - $id = $idResult->item(0)->attributes->getNamedItem('data-movie-id')->nodeValue; + $id = $idResult->item(0)?->attributes?->getNamedItem('data-movie-id')?->nodeValue; return (int)trim($id); } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php index 9b43d97..9a57ffe 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php @@ -234,7 +234,7 @@ private function getCoverUrl(): string return ''; } - return trim($data->item(0)->attributes->getNamedItem('href')->nodeValue); + return trim($data->item(0)?->attributes?->getNamedItem('href')?->nodeValue); } private function getCoverFile(): string @@ -246,7 +246,7 @@ private function getCoverFile(): string return ''; } - $coverUrl = trim($data->item(0)->attributes->getNamedItem('href')->nodeValue); + $coverUrl = trim($data->item(0)?->attributes?->getNamedItem('href')?->nodeValue); $coverUrlArray = explode('/', $coverUrl); $coverFile = end($coverUrlArray); diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php index 241fb68..4fb6655 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php @@ -25,7 +25,7 @@ public function getSimpleSearchResults(): SearchResults $searchResults = match ( ($queyResults->length > 0) && - ($queyResults->item(0)->attributes->getNamedItem('content')->nodeValue !== 'FilmAffinity') + ($queyResults->item(0)?->attributes?->getNamedItem('content')?->nodeValue !== 'FilmAffinity') ) { true => $this->simpleSearchSingleResult($queyResults), false => $this->simpleSearchMultipleResults() @@ -40,8 +40,8 @@ private function simpleSearchSingleResult(DOMNodeList $data): SearchResults { $idSearch = $this->getData(self::QUERY_SINGLE_RESULT_GET_ID, false); - $idArray = explode('/', $idSearch->item(0)->attributes->getNamedItem('content')->nodeValue); - $title = $data->item(0)->attributes->getNamedItem('content')->nodeValue; + $idArray = explode('/', $idSearch->item(0)?->attributes?->getNamedItem('content')?->nodeValue); + $title = $data->item(0)?->attributes?->getNamedItem('content')?->nodeValue; $searchResult = new SingleSearchResult(); $searchResult->id = (int)trim(str_replace('film', '', str_replace('.html', '', end($idArray)))); @@ -103,6 +103,6 @@ private function getId(DOMXPath $domXpath): int { $idResult = $domXpath->query(self::QUERY_MULTIPLE_RESULTS_GET_ID); - return (int)trim($idResult->item(0)->attributes->getNamedItem('data-movie-id')->nodeValue); + return (int)trim($idResult->item(0)?->attributes?->getNamedItem('data-movie-id')?->nodeValue); } } From 9213633b92e2505abe536668d0abbcc33faf623a Mon Sep 17 00:00:00 2001 From: parker Date: Thu, 6 Jun 2024 21:03:22 +0200 Subject: [PATCH 08/39] Add lost commands --- bin/console | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bin/console b/bin/console index dc7d772..68d4a50 100644 --- a/bin/console +++ b/bin/console @@ -11,6 +11,8 @@ use Xsga\FilmAffinityApi\Modules\Users\Infrastructure\Console\CreateUserCommand; use Xsga\FilmAffinityApi\Modules\Users\Infrastructure\Console\DeleteUserCommand; use Xsga\FilmAffinityApi\Modules\Users\Infrastructure\Console\DisableUserCommand; use Xsga\FilmAffinityApi\Modules\Users\Infrastructure\Console\EnableUserCommand; +use Xsga\FilmAffinityApi\Modules\Users\Infrastructure\Console\GetHashedPasswordCommand; +use Xsga\FilmAffinityApi\Modules\Users\Infrastructure\Console\GetTokenCommand; chdir(realpath(dirname(__FILE__))); @@ -28,5 +30,7 @@ $console->add($container->get(BackupCountriesCommand::class)); $console->add($container->get(EnableUserCommand::class)); $console->add($container->get(DisableUserCommand::class)); $console->add($container->get(DeleteUserCommand::class)); +$console->add($container->get(GetHashedPasswordCommand::class)); +$console->add($container->get(GetTokenCommand::class)); $console->run(); From 75df39a129277d0f76e4c821f90b1674182e7b93 Mon Sep 17 00:00:00 2001 From: parker Date: Thu, 6 Jun 2024 21:39:43 +0200 Subject: [PATCH 09/39] Include test user on start --- README.md | 2 +- scripts/02_api_user.sql | 9 +++++++++ .../Users/Infrastructure/Console/GetTokenCommand.php | 4 ++-- 3 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 scripts/02_api_user.sql diff --git a/README.md b/README.md index 26d7976..3ab5f4d 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ composer install ``` * Rename `config/.env.example` to `config/.env` to activates environment settings. * Setup API settings edditing `config/.env` file. -* Create a user using command `app:create-user`: +* Use test user (email `test@test.com` and password `Test123!`) or create a user using command `app:create-user`: ``` docker exec -it filmaffinityapi-web-server php .bin/console app:create-user ``` diff --git a/scripts/02_api_user.sql b/scripts/02_api_user.sql new file mode 100644 index 0000000..45bf413 --- /dev/null +++ b/scripts/02_api_user.sql @@ -0,0 +1,9 @@ +-- ---------------------------------------------------------------------------- +-- Insert `app_users` +-- ---------------------------------------------------------------------------- + +-- User: terst@test.com, password: Test123! +INSERT INTO app_users (id, email, password, create_date, update_date, status) +VALUES (NULL, 'test@test.com', '$2y$10$F5E5n6bJrEiLxCLa36OwFee6NtGDgX1miJcJtw.C1Chde.AM4PQ3K', NOW(), NOW(), true); + +COMMIT; diff --git a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/GetTokenCommand.php b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/GetTokenCommand.php index 2b1f90a..94c2f46 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/GetTokenCommand.php +++ b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/GetTokenCommand.php @@ -16,7 +16,7 @@ name: 'app:get-token', description: 'Creates a new token.', hidden: false, - aliases: ['app:get-password'] + aliases: ['app:get-token'] )] final class GetTokenCommand extends Command { @@ -52,7 +52,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $this->display->newLine(); $this->display->text($token); - $this->display->success("Hashed password created successfully"); + $this->display->success("Token created successfully"); return Command::SUCCESS; } From 85362bebcfde0c6a7ccdee302fc7fec66fc699a6 Mon Sep 17 00:00:00 2001 From: parker <67624778+xsga@users.noreply.github.com> Date: Fri, 7 Jun 2024 06:49:56 +0000 Subject: [PATCH 10/39] PSALM error level 5 --- psalm.xml | 2 +- .../Shared/Slim/Middleware/SecurityMiddleware.php | 7 +------ .../Modules/Users/Domain/Services/GetUser.php | 14 ++++++-------- .../Infrastructure/Mappers/UserEntityToUser.php | 5 +---- .../Repositories/DoctrineUsersRepository.php | 7 +------ 5 files changed, 10 insertions(+), 25 deletions(-) diff --git a/psalm.xml b/psalm.xml index 658f996..6d976c0 100644 --- a/psalm.xml +++ b/psalm.xml @@ -1,6 +1,6 @@ getName(); - - return match (is_null($routeName)) { - false => $routeName, - true => '' - }; + return $route->getName() ?? ''; } private function isNonSecuredRequest(string $routeName): bool diff --git a/src/Xsga/FilmAffinityApi/Modules/Users/Domain/Services/GetUser.php b/src/Xsga/FilmAffinityApi/Modules/Users/Domain/Services/GetUser.php index 7dc52c0..014a5e4 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Users/Domain/Services/GetUser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Users/Domain/Services/GetUser.php @@ -21,26 +21,24 @@ public function byId(int $userId): User { $user = $this->usersRepository->getUserById($userId); - $this->validateUserSearch($user, (string)$userId); - - return $user; + return $this->validateUserSearch($user, (string)$userId); } public function byEmail(string $userEmail): User { $user = $this->usersRepository->getUserByEmail($userEmail); - $this->validateUserSearch($user, $userEmail); - - return $user; + return $this->validateUserSearch($user, $userEmail); } - private function validateUserSearch(?User $user, string $criteriaValue): void + private function validateUserSearch(?User $user, string $criteriaValue): User { - if ($user === null) { + if (is_null($user)) { $errorMsg = "User '$criteriaValue' not found"; $this->logger->error($errorMsg); throw new UserNotFoundException($errorMsg, 1005, null, [1 => $criteriaValue]); } + + return $user; } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Mappers/UserEntityToUser.php b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Mappers/UserEntityToUser.php index 2a51fd7..c83d761 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Mappers/UserEntityToUser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Mappers/UserEntityToUser.php @@ -24,10 +24,7 @@ public function convert(UsersEntity $userEntity): User private function getUserId(?int $userId): int { - return match (is_null($userId)) { - true => 0, - false => $userId - }; + return $userId ?? 0; } /** diff --git a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Repositories/DoctrineUsersRepository.php b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Repositories/DoctrineUsersRepository.php index f3713fb..47985ba 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Repositories/DoctrineUsersRepository.php +++ b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Repositories/DoctrineUsersRepository.php @@ -67,12 +67,7 @@ public function createUser(User $user): int $this->em->persist($userEntity); $this->em->flush(); - $userId = $userEntity->getUserId(); - - return match (is_null($userId)) { - true => -1, - false => $userId - }; + return $userEntity->getUserId() ?? -1; } catch (Throwable $exception) { $this->logger->error($exception->__toString()); return match ($exception->getCode()) { From 47596675f9a2d195486fe10042d97268908538c8 Mon Sep 17 00:00:00 2001 From: parker <67624778+xsga@users.noreply.github.com> Date: Fri, 7 Jun 2024 08:03:58 +0000 Subject: [PATCH 11/39] PSALM error level 4 --- composer.json | 2 +- psalm.xml | 2 +- public/index.php | 2 +- .../Modules/Films/Domain/Parsers/AdvancedSearchParser.php | 2 +- .../Modules/Films/Domain/Parsers/SimpleSearchParser.php | 2 +- .../Modules/Films/Domain/Services/UrlService.php | 6 +++--- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 1ce933b..a69edc7 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "squizlabs/php_codesniffer": "^3.7", "php-parallel-lint/php-parallel-lint": "^1.3", "php-parallel-lint/php-console-highlighter": "^1.0", - "vimeo/psalm": "^4.27" + "vimeo/psalm": "^5.24" }, "autoload": { "files": [ diff --git a/psalm.xml b/psalm.xml index 6d976c0..62516f7 100644 --- a/psalm.xml +++ b/psalm.xml @@ -1,6 +1,6 @@ get(LoggerInterface::class); $requestMethod = $_SERVER['REQUEST_METHOD'] ?? 'METHOD_NOT_FOUND'; diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php index 64c7370..48962f7 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php @@ -70,6 +70,6 @@ private function getFilmYear(DOMXPath $domXpath): string { $yearResult = $domXpath->query(self::QUERY_ADV_SEARCH_GET_YEAR); - return $yearResult->item(1)->nodeValue; + return $yearResult->item(1)->nodeValue ?? ''; } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php index 4fb6655..2fa4a9d 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php @@ -96,7 +96,7 @@ private function getYear(DOMXPath $domXpath): string { $yearResult = $domXpath->query(self::QUERY_MULTIPLE_RESULTS_GET_YEAR); - return $yearResult->item(0)->nodeValue; + return $yearResult->item(0)->nodeValue ?? ''; } private function getId(DOMXPath $domXpath): int diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/UrlService.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/UrlService.php index 924bb55..17ff13c 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/UrlService.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/UrlService.php @@ -53,8 +53,8 @@ public function getAdvancedSearchUrl(AdvancedSearch $advancedSearch): string $url = str_replace('{2}', $this->getAdvancedSeartType($advancedSearch), $url); $url = str_replace('{3}', $advancedSearch->searchCountry, $url); $url = str_replace('{4}', $advancedSearch->searchGenre, $url); - $url = str_replace('{5}', $advancedSearch->searchYearFrom === 0 ? '' : $advancedSearch->searchYearFrom, $url); - $url = str_replace('{6}', $advancedSearch->searchYearTo === 0 ? '' : $advancedSearch->searchYearTo, $url); + $url = str_replace('{5}', $advancedSearch->searchYearFrom === 0 ? '' : (string)$advancedSearch->searchYearFrom, $url); + $url = str_replace('{6}', $advancedSearch->searchYearTo === 0 ? '' : (string)$advancedSearch->searchYearTo, $url); $this->logger->debug('Advanced Search URL: ' . $url); @@ -72,7 +72,7 @@ private function getAdvancedSeartType(AdvancedSearch $advancedSearch): string $searchType .= $advancedSearch->searchTypePhotography ? '&stype[]=photo' : ''; $searchType .= $advancedSearch->searchTypeProducer ? '&stype[]=producer' : ''; - if ($searchType === '') { + if (empty($searchType)) { $this->logger->warning('No search type found. Set the default search type: title'); $searchType = '&stype[]=title'; } From 65bf1f2670397acaf7c66164979a1d4b3d3b3104 Mon Sep 17 00:00:00 2001 From: parker <67624778+xsga@users.noreply.github.com> Date: Fri, 7 Jun 2024 08:42:03 +0000 Subject: [PATCH 12/39] Log4PHP PSALM revision --- psalm.xml | 4 +--- src/Log4Php/Appenders/LoggerAppenderMailEvent.php | 2 +- .../Configurators/LoggerConfigurationAdapterPHP.php | 2 +- .../Configurators/LoggerConfigurationAdapterXML.php | 8 ++++---- src/Log4Php/Helpers/LoggerOptionConverter.php | 6 +++--- src/Log4Php/LoggerLevel.php | 2 +- src/Log4Php/LoggerLoggingEvent.php | 2 +- 7 files changed, 12 insertions(+), 14 deletions(-) diff --git a/psalm.xml b/psalm.xml index 62516f7..3e26efb 100644 --- a/psalm.xml +++ b/psalm.xml @@ -9,8 +9,6 @@ - - - + diff --git a/src/Log4Php/Appenders/LoggerAppenderMailEvent.php b/src/Log4Php/Appenders/LoggerAppenderMailEvent.php index d7e360b..2c0eeb8 100644 --- a/src/Log4Php/Appenders/LoggerAppenderMailEvent.php +++ b/src/Log4Php/Appenders/LoggerAppenderMailEvent.php @@ -110,7 +110,7 @@ public function setTo(string $to): void public function getTo(): string { - return $this->to; + return $this->to ?? ''; } public function setDry(bool $dry): void diff --git a/src/Log4Php/Configurators/LoggerConfigurationAdapterPHP.php b/src/Log4Php/Configurators/LoggerConfigurationAdapterPHP.php index aa2830d..15e3c2d 100644 --- a/src/Log4Php/Configurators/LoggerConfigurationAdapterPHP.php +++ b/src/Log4Php/Configurators/LoggerConfigurationAdapterPHP.php @@ -26,7 +26,7 @@ public function convert(string $input): array throw new LoggerException('Error parsing configuration: ' . $error['message']); } - if (empty($config)) { + if ($config === '') { throw new LoggerException('Invalid configuration: empty configuration array.'); } diff --git a/src/Log4Php/Configurators/LoggerConfigurationAdapterXML.php b/src/Log4Php/Configurators/LoggerConfigurationAdapterXML.php index 586ace6..d2af84d 100644 --- a/src/Log4Php/Configurators/LoggerConfigurationAdapterXML.php +++ b/src/Log4Php/Configurators/LoggerConfigurationAdapterXML.php @@ -21,7 +21,7 @@ public function convert(string $input): array $this->parseConfiguration($xml); - if (isset($xml->root)) { + if (!empty($xml->root)) { $this->parseRootLogger($xml->root); } @@ -94,7 +94,7 @@ private function parseAppender(SimpleXMLElement $node): void $appender['threshold'] = $this->getAttributeValue($node, 'threshold'); } - if (isset($node->layout)) { + if (!empty($node->layout)) { $appender['layout'] = $this->parseLayout($node->layout); } @@ -144,7 +144,7 @@ private function parseRootLogger(SimpleXMLElement $node): void { $logger = []; - if (isset($node->level)) { + if (!empty($node->level)) { $logger['level'] = $this->getAttributeValue($node->level, 'value'); } @@ -164,7 +164,7 @@ private function parseLogger(SimpleXMLElement $node): void return; } - if (isset($node->level)) { + if (!empty($node->level)) { $logger['level'] = $this->getAttributeValue($node->level, 'value'); } diff --git a/src/Log4Php/Helpers/LoggerOptionConverter.php b/src/Log4Php/Helpers/LoggerOptionConverter.php index c8a0af9..c953417 100644 --- a/src/Log4Php/Helpers/LoggerOptionConverter.php +++ b/src/Log4Php/Helpers/LoggerOptionConverter.php @@ -54,7 +54,7 @@ public static function toIntegerEx(mixed $value): int return $value; } - if (is_numeric($value) && ($value === (int)$value)) { + if (is_numeric($value)) { return (int)$value; } @@ -67,8 +67,8 @@ public static function toPositiveIntegerEx(mixed $value): int return $value; } - if (is_numeric($value) && ($value === (int)$value) && ($value > 0)) { - return $value; + if (is_numeric($value) && ($value > 0)) { + return (int)$value; } $log = 'Given value [' . var_export($value, true) . '] cannot be converted to a positive integer.'; diff --git a/src/Log4Php/LoggerLevel.php b/src/Log4Php/LoggerLevel.php index b39dde4..5ec8546 100644 --- a/src/Log4Php/LoggerLevel.php +++ b/src/Log4Php/LoggerLevel.php @@ -158,7 +158,7 @@ private static function intLevel(int|string $arg, LoggerLevel $defaultLevel = nu private static function strLevel(int|string $arg, LoggerLevel $defaultLevel = null): ?LoggerLevel { - return match (strtoupper($arg)) { + return match (strtoupper((string)$arg)) { 'ALL' => static::getLevelAll(), 'TRACE' => static::getLevelTrace(), 'DEBUG' => static::getLevelDebug(), diff --git a/src/Log4Php/LoggerLoggingEvent.php b/src/Log4Php/LoggerLoggingEvent.php index 17d2b01..8f5f2cd 100644 --- a/src/Log4Php/LoggerLoggingEvent.php +++ b/src/Log4Php/LoggerLoggingEvent.php @@ -7,7 +7,7 @@ class LoggerLoggingEvent { private static float $startTime = 0.0; - private ?Logger $logger = null; + private ?Logger $logger; private string $categoryName; private ?string $ndc; private bool $ndcLookupRequired = true; From da8fba31ce75b19c014e8545153cc9353b81c904 Mon Sep 17 00:00:00 2001 From: parker Date: Mon, 10 Jun 2024 13:02:44 +0200 Subject: [PATCH 13/39] Fix style --- Dockerfile | 6 ++--- .../Parsers/AdvancedSearchFormParser.php | 4 ++-- .../Domain/Parsers/AdvancedSearchParser.php | 8 +++---- .../Films/Domain/Parsers/FilmParser.php | 22 +++++++++---------- .../Domain/Parsers/SimpleSearchParser.php | 12 +++++----- .../Films/Domain/Services/UrlService.php | 12 +++++----- 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/Dockerfile b/Dockerfile index fd95247..e205a0f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,8 +21,8 @@ RUN curl -L https://phar.phpunit.de/phploc.phar > /usr/local/bin/phploc \ && chmod +x /usr/local/bin/phploc # Setup application folder. -RUN mkdir -p /opt/filmaffinityapi/public -RUN ln -s /opt/filmaffinityapi/public /var/www/html/filmaffinityapi +RUN mkdir -p /opt/app/public +RUN ln -s /opt/app/public /var/www/html/filmaffinityapi # Configure PHP. COPY config/etc/php/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini @@ -31,4 +31,4 @@ COPY config/etc/php/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer # Working directory. -WORKDIR /opt/filmaffinityapi \ No newline at end of file +WORKDIR /opt/app \ No newline at end of file diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchFormParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchFormParser.php index 70969bb..f54ff61 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchFormParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchFormParser.php @@ -9,8 +9,8 @@ final class AdvancedSearchFormParser extends AbstractParser { - private const QUERY_ADV_SEARCH_FORM_GET_GENRES = "//option[not(@data-content)]"; - private const QUERY_ADV_SEARCH_FORM_GET_COUNTRIES = "//option[@data-class = 'flag-wrapper']"; + private const string QUERY_ADV_SEARCH_FORM_GET_GENRES = "//option[not(@data-content)]"; + private const string QUERY_ADV_SEARCH_FORM_GET_COUNTRIES = "//option[@data-class = 'flag-wrapper']"; /** * @return Genre[] diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php index 48962f7..9a5a958 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php @@ -12,10 +12,10 @@ final class AdvancedSearchParser extends AbstractParser { - private const QUERY_ADV_SEARCH_DATA = "//div[contains(@class, 'adv-search-item')]"; - private const QUERY_ADV_SEARCH_GET_TITLE = "//div[@class = 'mc-title']/a"; - private const QUERY_ADV_SEARCH_GET_ID = "//div[contains(@class, 'movie-card')]"; - private const QUERY_ADV_SEARCH_GET_YEAR = "//span[contains(@class, 'mc-year')]"; + private const string QUERY_ADV_SEARCH_DATA = "//div[contains(@class, 'adv-search-item')]"; + private const string QUERY_ADV_SEARCH_GET_TITLE = "//div[@class = 'mc-title']/a"; + private const string QUERY_ADV_SEARCH_GET_ID = "//div[contains(@class, 'movie-card')]"; + private const string QUERY_ADV_SEARCH_GET_YEAR = "//span[contains(@class, 'mc-year')]"; public function getAdvSearchResults(): SearchResults { diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php index 9a57ffe..dba1f47 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php @@ -10,17 +10,17 @@ final class FilmParser extends AbstractParser { - private const QUERY_FILM_GET_VARIOUS = "//dd[not(@class) and not(@itemprop)]"; - private const QUERY_FILM_GET_TITLE = "//h1[@id = 'main-title']/span[@itemprop = 'name']"; - private const QUERY_FILM_GET_RELEASE_DATE = "//dd[@itemprop = 'datePublished']"; - private const QUERY_FILM_GET_DURATION = "//dd[@itemprop = 'duration']"; - private const QUERY_FILM_GET_DIRECTORS = "//span[@itemprop = 'director']//span[@itemprop = 'name']"; - private const QUERY_FILM_GET_ACTORS = "//li[@itemprop = 'actor']"; - private const QUERY_FILM_GET_PRODUCERS = "//dd[@class = 'card-producer']//span"; - private const QUERY_FILM_GET_GENRES = "//dd[@class = 'card-genres']//a"; - private const QUERY_FILM_GET_RATING = "//div[@id = 'movie-rat-avg']"; - private const QUERY_FILM_GET_SYNOPSIS = "//dd[@class = '' and @itemprop = 'description']"; - private const QUERY_FILM_GET_COVER = "//a[@class = 'lightbox']"; + private const string QUERY_FILM_GET_VARIOUS = "//dd[not(@class) and not(@itemprop)]"; + private const string QUERY_FILM_GET_TITLE = "//h1[@id = 'main-title']/span[@itemprop = 'name']"; + private const string QUERY_FILM_GET_RELEASE_DATE = "//dd[@itemprop = 'datePublished']"; + private const string QUERY_FILM_GET_DURATION = "//dd[@itemprop = 'duration']"; + private const string QUERY_FILM_GET_DIRECTORS = "//span[@itemprop = 'director']//span[@itemprop = 'name']"; + private const string QUERY_FILM_GET_ACTORS = "//li[@itemprop = 'actor']"; + private const string QUERY_FILM_GET_PRODUCERS = "//dd[@class = 'card-producer']//span"; + private const string QUERY_FILM_GET_GENRES = "//dd[@class = 'card-genres']//a"; + private const string QUERY_FILM_GET_RATING = "//div[@id = 'movie-rat-avg']"; + private const string QUERY_FILM_GET_SYNOPSIS = "//dd[@class = '' and @itemprop = 'description']"; + private const string QUERY_FILM_GET_COVER = "//a[@class = 'lightbox']"; public function getFilm(int $filmId): Film { diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php index 2fa4a9d..b9d0b36 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php @@ -12,12 +12,12 @@ final class SimpleSearchParser extends AbstractParser { - private const QUERY_RESULTS_TYPE = "//meta[@property = 'og:title']"; - private const QUERY_SINGLE_RESULT_GET_ID = "//meta[@property = 'og:url']"; - private const QUERY_MULTIPLE_RESULTS_DATA = "//div[contains(@class, 'se-it')]"; - private const QUERY_MULTIPLE_RESULTS_GET_TITLE = "//div[@class = 'mc-title']/a"; - private const QUERY_MULTIPLE_RESULTS_GET_YEAR = "//div[contains(@class, 'ye-w')]"; - private const QUERY_MULTIPLE_RESULTS_GET_ID = "//div[contains(@class, 'movie-card')]"; + private const string QUERY_RESULTS_TYPE = "//meta[@property = 'og:title']"; + private const string QUERY_SINGLE_RESULT_GET_ID = "//meta[@property = 'og:url']"; + private const string QUERY_MULTIPLE_RESULTS_DATA = "//div[contains(@class, 'se-it')]"; + private const string QUERY_MULTIPLE_RESULTS_GET_TITLE = "//div[@class = 'mc-title']/a"; + private const string QUERY_MULTIPLE_RESULTS_GET_YEAR = "//div[contains(@class, 'ye-w')]"; + private const string QUERY_MULTIPLE_RESULTS_GET_ID = "//div[contains(@class, 'movie-card')]"; public function getSimpleSearchResults(): SearchResults { diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/UrlService.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/UrlService.php index 17ff13c..eed3487 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/UrlService.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/UrlService.php @@ -22,7 +22,7 @@ public function getFilmUrl(int $filmId): string { $url = str_replace('{1}', (string)$filmId, $this->filmUrl); - $this->logger->debug('Film URL: ' . $url); + $this->logger->debug("Film URL: $url"); return $url; } @@ -31,7 +31,7 @@ public function getSearchUrl(Search $search): string { $url = str_replace('{1}', $this->prepareSearchText($search->searchText), $this->searchUrl); - $this->logger->debug('Search URL: ' . $url); + $this->logger->debug("Search URL: $url"); return $url; } @@ -41,7 +41,7 @@ public function getAdvancedSearchFormUrl(): string $urlArray = explode('?', $this->advancedSearchUrl); $url = $urlArray[0]; - $this->logger->debug('Advanced search form URL: ' . $url); + $this->logger->debug("Advanced search form URL: $url"); return $url; } @@ -50,18 +50,18 @@ public function getAdvancedSearchUrl(AdvancedSearch $advancedSearch): string { $url = $this->advancedSearchUrl; $url = str_replace('{1}', $this->prepareSearchText($advancedSearch->searchText), $url); - $url = str_replace('{2}', $this->getAdvancedSeartType($advancedSearch), $url); + $url = str_replace('{2}', $this->getAdvancedSearchType($advancedSearch), $url); $url = str_replace('{3}', $advancedSearch->searchCountry, $url); $url = str_replace('{4}', $advancedSearch->searchGenre, $url); $url = str_replace('{5}', $advancedSearch->searchYearFrom === 0 ? '' : (string)$advancedSearch->searchYearFrom, $url); $url = str_replace('{6}', $advancedSearch->searchYearTo === 0 ? '' : (string)$advancedSearch->searchYearTo, $url); - $this->logger->debug('Advanced Search URL: ' . $url); + $this->logger->debug("Advanced Search URL: $url"); return $url; } - private function getAdvancedSeartType(AdvancedSearch $advancedSearch): string + private function getAdvancedSearchType(AdvancedSearch $advancedSearch): string { $searchType = ''; $searchType .= $advancedSearch->searchTypeTitle ? '&stype[]=title' : ''; From 611d966a6052aaa5a0e6b7f6c66626ae93d857c8 Mon Sep 17 00:00:00 2001 From: parker Date: Mon, 10 Jun 2024 14:23:38 +0200 Subject: [PATCH 14/39] Genre topics feature --- config/schemas/output/film.schema.json | 17 +++ config/schemas/output/genres.schema.json | 4 +- .../Modules/Films/Application/Dto/FilmDto.php | 1 + .../Films/Application/Dto/GenreDto.php | 2 +- .../Application/Mappers/FilmToFilmDto.php | 33 +++++- .../Modules/Films/Domain/Model/Film.php | 10 ++ .../Modules/Films/Domain/Model/Genre.php | 2 +- .../Modules/Films/Domain/Model/GenreTopic.php | 11 ++ .../Films/Domain/Parsers/FilmParser.php | 100 +++++++++++++----- 9 files changed, 149 insertions(+), 31 deletions(-) create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/GenreTopic.php diff --git a/config/schemas/output/film.schema.json b/config/schemas/output/film.schema.json index 9462a7b..ead5436 100644 --- a/config/schemas/output/film.schema.json +++ b/config/schemas/output/film.schema.json @@ -19,6 +19,7 @@ "cast", "producer", "genres", + "genreTopics", "synopsis" ], "properties": { @@ -135,6 +136,22 @@ ] } }, + "genreTopics": { + "$id": "#/properties/genreTopics", + "type": "array", + "title": "Film genres topics array", + "additionalItems": false, + "items": { + "$id": "#/properties/genreTopics/items", + "anyOf": [ + { + "$id": "#/properties/genreTopics/items/anyOf/0", + "type": "string", + "title": "Film genre topic name" + } + ] + } + }, "synopsis": { "$id": "#/properties/synopsis", "type": "string", diff --git a/config/schemas/output/genres.schema.json b/config/schemas/output/genres.schema.json index 3f549c0..9b56ea2 100644 --- a/config/schemas/output/genres.schema.json +++ b/config/schemas/output/genres.schema.json @@ -20,10 +20,10 @@ "type": "string", "title": "Genre" }, - "description": { + "name": { "$id": "#/items/anyOf/0/properties/description", "type": "string", - "title": "Genre description" + "title": "Genre name" } }, "additionalProperties": false diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Dto/FilmDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Dto/FilmDto.php index c4542f7..ebcb7a1 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Dto/FilmDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Dto/FilmDto.php @@ -22,5 +22,6 @@ class FilmDto public array $cast = []; public string $producer = ''; public array $genres = []; + public array $genreTopics = []; public string $synopsis = ''; } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Dto/GenreDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Dto/GenreDto.php index c084b0d..143e856 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Dto/GenreDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Dto/GenreDto.php @@ -7,5 +7,5 @@ class GenreDto { public string $code = ''; - public string $description = ''; + public string $name = ''; } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php index 29cbcb9..e3cc5de 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php @@ -6,6 +6,8 @@ use Xsga\FilmAffinityApi\Modules\Films\Application\Dto\FilmDto; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Film; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Genre; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\GenreTopic; class FilmToFilmDto { @@ -28,9 +30,38 @@ public function convert(Film $film): FilmDto $filmDto->photography = $film->photography; $filmDto->cast = $film->cast; $filmDto->producer = $film->producer; - $filmDto->genres = $film->genres; + $filmDto->genres = $this->getGenres($film->genres); + $filmDto->genreTopics = $this->getGenreTopics($film->genreTopics); $filmDto->synopsis = $film->synopsis; return $filmDto; } + + /** + * @param Genre[] $genres + */ + private function getGenres(array $genres) : array + { + $out = []; + + foreach ($genres as $genre) { + $out[] = $genre->name; + } + + return $out; + } + + /** + * @param GenreTopic[] $genreTopics + */ + private function getGenreTopics(array $genreTopics) : array + { + $out = []; + + foreach ($genreTopics as $genreTopic) { + $out[] = $genreTopic->name; + } + + return $out; + } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php index 211d908..c808604 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php @@ -21,6 +21,16 @@ class Film public string $photography = ''; public array $cast = []; public string $producer = ''; + + /** + * @var Genre[] + */ public array $genres = []; + + /** + * @var GenreTopic[] + */ + public array $genreTopics = []; + public string $synopsis = ''; } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Genre.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Genre.php index 9d10763..edd725b 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Genre.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Genre.php @@ -7,5 +7,5 @@ class Genre { public string $code = ''; - public string $description = ''; + public string $name = ''; } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/GenreTopic.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/GenreTopic.php new file mode 100644 index 0000000..1320453 --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/GenreTopic.php @@ -0,0 +1,11 @@ +filmAfinityId = $filmId; - $dto->title = $this->getTitle(); - $dto->originalTitle = $this->getOriginalTitle(); - $dto->year = $this->getYear(); - $dto->duration = $this->getDuration(); - $dto->country = $this->getCountry(); - $dto->directors = $this->getDirectors(); - $dto->screenplay = $this->getScreenplay(); - $dto->soundtrack = $this->getSoundtrack(); - $dto->photography = $this->getPhotography(); - $dto->cast = $this->getActors(); - $dto->producer = $this->getProducers(); - $dto->genres = $this->getGenres(); - $dto->rating = $this->getRating(); - $dto->synopsis = $this->getSynopsis(); - $dto->coverUrl = $this->getCoverUrl(); - $dto->coverFile = $this->getCoverFile(); - - return $dto; + $film = new Film(); + + $film->filmAfinityId = $filmId; + $film->title = $this->getTitle(); + $film->originalTitle = $this->getOriginalTitle(); + $film->year = $this->getYear(); + $film->duration = $this->getDuration(); + $film->country = $this->getCountry(); + $film->directors = $this->getDirectors(); + $film->screenplay = $this->getScreenplay(); + $film->soundtrack = $this->getSoundtrack(); + $film->photography = $this->getPhotography(); + $film->cast = $this->getActors(); + $film->producer = $this->getProducers(); + $film->genres = $this->getGenres(); + $film->genreTopics = $this->getGenreTopics(); + $film->rating = $this->getRating(); + $film->synopsis = $this->getSynopsis(); + $film->coverUrl = $this->getCoverUrl(); + $film->coverFile = $this->getCoverFile(); + + return $film; } private function validateOneResult(array $results, string $element): bool @@ -142,15 +147,58 @@ private function getProducers(): string return implode(' ', $data); } + /** + * @return Genre[] + */ private function getGenres(): array { - $data = $this->getData(self::QUERY_FILM_GET_GENRES); + $data = $this->getData(self::QUERY_FILM_GET_GENRES, false); - if (!$this->validateMultipleResult($data, 'film genres')) { - return []; + $out = []; + + foreach ($data as $item) { + $out[] = $this->getGenre($item); } - return array_map('trim', $data); + return $out; + } + + private function getGenre(DOMNode $item): Genre + { + $url = trim($item?->attributes?->getNamedItem('href')?->nodeValue); + + $genre = new Genre(); + $genre->code = substr($url, strpos($url, 'genre=') + 6, strpos($url, '&') - strpos($url, 'genre=') - 6); + $genre->name = trim($item?->nodeValue); + + return $genre; + } + + /** + * @return GenreTopic[] + */ + private function getGenreTopics(): array + { + $data = $this->getData(self::QUERY_FILM_GET_GENRE_TOPICS, false); + + $out = []; + + foreach ($data as $item) { + $out[] = $this->getGenreTopic($item); + } + + return $out; + } + + private function getGenreTopic(DOMNode $item): GenreTopic + { + $url = trim($item?->attributes?->getNamedItem('href')?->nodeValue); + + $genreTopic = new GenreTopic(); + $genreTopic->id = (int)substr($url, strpos($url, 'topic=') + 6, strpos($url, '&') - strpos($url, 'topic=') - 6); + $genreTopic->name = trim($item?->nodeValue); + + return $genreTopic; } private function getOriginalTitle(): string From efd4fa37c0d9629d0a0745aec7cad6c7fc38e97c Mon Sep 17 00:00:00 2001 From: parker Date: Mon, 10 Jun 2024 16:49:55 +0200 Subject: [PATCH 15/39] Genre and country value objects --- .../Mappers/CountryToCountryDto.php | 4 ++-- .../Application/Mappers/FilmToFilmDto.php | 2 +- .../Application/Mappers/GenreToGenreDto.php | 4 ++-- .../Modules/Films/Domain/Model/Country.php | 23 +++++++++++++++++-- .../Modules/Films/Domain/Model/Genre.php | 23 +++++++++++++++++-- .../Parsers/AdvancedSearchFormParser.php | 16 +++++++------ .../Domain/Parsers/AdvancedSearchParser.php | 2 +- .../Films/Domain/Parsers/FilmParser.php | 15 ++++++------ .../Films/Domain/ValueObjects/CountryCode.php | 11 +++++++++ .../Films/Domain/ValueObjects/CountryName.php | 20 ++++++++++++++++ .../Films/Domain/ValueObjects/GenreCode.php | 11 +++++++++ .../Films/Domain/ValueObjects/GenreName.php | 20 ++++++++++++++++ .../Controllers/AdvancedSearchController.php | 2 +- .../Controllers/SimpleSearchController.php | 2 +- .../JsonAdvancedSearchToAdvancedSearchDto.php | 2 +- .../Mappers/JsonSimpleSearchToSearchDto.php | 2 +- .../FilmAffinityCountriesRepository.php | 2 +- .../FilmAffinityGenresRepository.php | 2 +- 18 files changed, 132 insertions(+), 31 deletions(-) create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/CountryCode.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/CountryName.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/GenreCode.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/GenreName.php rename src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/{Controllers => }/Mappers/JsonAdvancedSearchToAdvancedSearchDto.php (94%) rename src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/{Controllers => }/Mappers/JsonSimpleSearchToSearchDto.php (80%) diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/CountryToCountryDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/CountryToCountryDto.php index 053df4d..ef68af5 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/CountryToCountryDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/CountryToCountryDto.php @@ -13,8 +13,8 @@ public function convert(Country $country): CountryDto { $countryDto = new CountryDto(); - $countryDto->code = $country->code; - $countryDto->name = $country->name; + $countryDto->code = $country->code(); + $countryDto->name = $country->name(); return $countryDto; } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php index e3cc5de..8f818f7 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php @@ -45,7 +45,7 @@ private function getGenres(array $genres) : array $out = []; foreach ($genres as $genre) { - $out[] = $genre->name; + $out[] = $genre->name(); } return $out; diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/GenreToGenreDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/GenreToGenreDto.php index b8f9356..91e1d8b 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/GenreToGenreDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/GenreToGenreDto.php @@ -13,8 +13,8 @@ public function convert(Genre $genre): GenreDto { $genreDto = new GenreDto(); - $genreDto->code = $genre->code; - $genreDto->description = $genre->description; + $genreDto->code = $genre->code(); + $genreDto->name = $genre->name(); return $genreDto; } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Country.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Country.php index 9ea334d..ef58951 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Country.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Country.php @@ -4,8 +4,27 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Domain\Model; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\CountryCode; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\CountryName; + class Country { - public string $code = ''; - public string $name = ''; + private CountryCode $code; + private CountryName $name; + + public function __construct(string $code, string $name) + { + $this->code = new CountryCode($code); + $this->name = new CountryName($name); + } + + public function code(): string + { + return $this->code->value(); + } + + public function name(): string + { + return $this->name->value(); + } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Genre.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Genre.php index edd725b..ac70fc4 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Genre.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Genre.php @@ -4,8 +4,27 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Domain\Model; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\GenreCode; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\GenreName; + class Genre { - public string $code = ''; - public string $name = ''; + private GenreCode $code; + private GenreName $name; + + public function __construct(string $code, string $name) + { + $this->code = new GenreCode($code); + $this->name = new GenreName($name); + } + + public function code(): string + { + return $this->code->value(); + } + + public function name(): string + { + return $this->name->value(); + } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchFormParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchFormParser.php index f54ff61..293336d 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchFormParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchFormParser.php @@ -26,9 +26,10 @@ public function getGenres(): array continue; } - $genre = new Genre(); - $genre->code = $element->getAttribute('value'); - $genre->description = trim($element->nodeValue); + $genre = new Genre( + $element->getAttribute('value'), + trim($element->nodeValue) + ); $out[] = $genre; } @@ -46,10 +47,11 @@ public function getCountries(): array $out = []; foreach ($xpathResults as $element) { - $country = new Country(); - $country->code = $element->getAttribute('value'); - $country->name = trim($element->nodeValue); - + $country = new Country( + $element->getAttribute('value'), + trim($element->nodeValue) + ); + $out[] = $country; } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php index 9a5a958..eb23ef6 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php @@ -61,7 +61,7 @@ private function getFilmTitle(DOMXPath $domXpath): string private function getFilmId(DOMXPath $domXpath): int { $idResult = $domXpath->query(self::QUERY_ADV_SEARCH_GET_ID); - $id = $idResult->item(0)?->attributes?->getNamedItem('data-movie-id')?->nodeValue; + $id = $idResult->item(0)->attributes->getNamedItem('data-movie-id')->nodeValue; return (int)trim($id); } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php index 805cce5..c7496ad 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php @@ -4,9 +4,7 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers; -use DOMDocument; use DOMNode; -use DOMXPath; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Film; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Genre; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\GenreTopic; @@ -165,11 +163,12 @@ private function getGenres(): array private function getGenre(DOMNode $item): Genre { - $url = trim($item?->attributes?->getNamedItem('href')?->nodeValue); + $url = trim($item->attributes?->getNamedItem('href')?->nodeValue); - $genre = new Genre(); - $genre->code = substr($url, strpos($url, 'genre=') + 6, strpos($url, '&') - strpos($url, 'genre=') - 6); - $genre->name = trim($item?->nodeValue); + $genre = new Genre( + substr($url, strpos($url, 'genre=') + 6, strpos($url, '&') - strpos($url, 'genre=') - 6), + trim($item->nodeValue) + ); return $genre; } @@ -192,11 +191,11 @@ private function getGenreTopics(): array private function getGenreTopic(DOMNode $item): GenreTopic { - $url = trim($item?->attributes?->getNamedItem('href')?->nodeValue); + $url = trim($item->attributes?->getNamedItem('href')?->nodeValue); $genreTopic = new GenreTopic(); $genreTopic->id = (int)substr($url, strpos($url, 'topic=') + 6, strpos($url, '&') - strpos($url, 'topic=') - 6); - $genreTopic->name = trim($item?->nodeValue); + $genreTopic->name = trim($item->nodeValue); return $genreTopic; } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/CountryCode.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/CountryCode.php new file mode 100644 index 0000000..acfc8d8 --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/CountryCode.php @@ -0,0 +1,11 @@ +value = $name; + } + + public function value(): string + { + return $this->value; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/GenreCode.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/GenreCode.php new file mode 100644 index 0000000..0daf63b --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/GenreCode.php @@ -0,0 +1,11 @@ +value = $name; + } + + public function value(): string + { + return $this->value; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Controllers/AdvancedSearchController.php b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Controllers/AdvancedSearchController.php index d29c6a5..47466e8 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Controllers/AdvancedSearchController.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Controllers/AdvancedSearchController.php @@ -7,7 +7,7 @@ use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use Xsga\FilmAffinityApi\Modules\Films\Application\Services\AdvancedSearchService; -use Xsga\FilmAffinityApi\Modules\Films\Infrastructure\Controllers\Mappers\JsonAdvancedSearchToAdvancedSearchDto; +use Xsga\FilmAffinityApi\Modules\Films\Infrastructure\Mappers\JsonAdvancedSearchToAdvancedSearchDto; use Xsga\FilmAffinityApi\Modules\Shared\Api\Infrastructure\Controllers\AbstractController; final class AdvancedSearchController extends AbstractController diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Controllers/SimpleSearchController.php b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Controllers/SimpleSearchController.php index a10a1ea..054a316 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Controllers/SimpleSearchController.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Controllers/SimpleSearchController.php @@ -7,7 +7,7 @@ use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use Xsga\FilmAffinityApi\Modules\Films\Application\Services\SimpleSearchService; -use Xsga\FilmAffinityApi\Modules\Films\Infrastructure\Controllers\Mappers\JsonSimpleSearchToSearchDto; +use Xsga\FilmAffinityApi\Modules\Films\Infrastructure\Mappers\JsonSimpleSearchToSearchDto; use Xsga\FilmAffinityApi\Modules\Shared\Api\Infrastructure\Controllers\AbstractController; final class SimpleSearchController extends AbstractController diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Controllers/Mappers/JsonAdvancedSearchToAdvancedSearchDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Mappers/JsonAdvancedSearchToAdvancedSearchDto.php similarity index 94% rename from src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Controllers/Mappers/JsonAdvancedSearchToAdvancedSearchDto.php rename to src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Mappers/JsonAdvancedSearchToAdvancedSearchDto.php index 02ff03e..ce2a308 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Controllers/Mappers/JsonAdvancedSearchToAdvancedSearchDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Mappers/JsonAdvancedSearchToAdvancedSearchDto.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Xsga\FilmAffinityApi\Modules\Films\Infrastructure\Controllers\Mappers; +namespace Xsga\FilmAffinityApi\Modules\Films\Infrastructure\Mappers; use Xsga\FilmAffinityApi\Modules\Films\Application\Dto\AdvancedSearchDto; diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Controllers/Mappers/JsonSimpleSearchToSearchDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Mappers/JsonSimpleSearchToSearchDto.php similarity index 80% rename from src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Controllers/Mappers/JsonSimpleSearchToSearchDto.php rename to src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Mappers/JsonSimpleSearchToSearchDto.php index d57a6ba..e9a27ca 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Controllers/Mappers/JsonSimpleSearchToSearchDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Mappers/JsonSimpleSearchToSearchDto.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Xsga\FilmAffinityApi\Modules\Films\Infrastructure\Controllers\Mappers; +namespace Xsga\FilmAffinityApi\Modules\Films\Infrastructure\Mappers; use Xsga\FilmAffinityApi\Modules\Films\Application\Dto\SearchDto; diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinityCountriesRepository.php b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinityCountriesRepository.php index e13932e..be01b73 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinityCountriesRepository.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinityCountriesRepository.php @@ -44,7 +44,7 @@ public function getAll(): array public function get(string $code): ?Country { foreach ($this->getAll() as $country) { - if ($country->code === $code) { + if ($country->code() === $code) { return $country; } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinityGenresRepository.php b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinityGenresRepository.php index 4e829d5..385d4a4 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinityGenresRepository.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinityGenresRepository.php @@ -44,7 +44,7 @@ public function getAll(): array public function get(string $code): ?Genre { foreach ($this->getAll() as $genre) { - if (strtoupper($genre->code) === strtoupper($code)) { + if (strtoupper($genre->code()) === strtoupper($code)) { return $genre; } } From 8b88964e47cebb23fce25988a2a3ba2fff3508c1 Mon Sep 17 00:00:00 2001 From: parker Date: Mon, 10 Jun 2024 17:05:55 +0200 Subject: [PATCH 16/39] Genre topic value objects --- .../Services/BackupCountriesService.php | 12 ++++------ .../Services/BackupGenresService.php | 8 ++----- .../Modules/Films/Domain/Model/GenreTopic.php | 23 +++++++++++++++++-- .../Films/Domain/Parsers/FilmParser.php | 9 ++++---- .../Domain/ValueObjects/GenreTopicId.php | 20 ++++++++++++++++ .../Domain/ValueObjects/GenreTopicName.php | 20 ++++++++++++++++ 6 files changed, 72 insertions(+), 20 deletions(-) create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/GenreTopicId.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/GenreTopicName.php diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Services/BackupCountriesService.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Services/BackupCountriesService.php index 4ea9fd5..45c0705 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Services/BackupCountriesService.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Services/BackupCountriesService.php @@ -4,14 +4,12 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Application\Services; -use Psr\Log\LoggerInterface; use Throwable; use Xsga\FilmAffinityApi\Modules\Films\Infrastructure\Repositories\FilmAffinityCountriesRepository; final class BackupCountriesService { public function __construct( - private LoggerInterface $logger, private FilmAffinityCountriesRepository $repository, private string $language, private string $destinationPath @@ -21,13 +19,11 @@ public function __construct( public function get(): bool { try { - $genres = $this->repository->getAll(); + $countries = $this->repository->getAll(); + $countriesJson = json_encode($countries); + $fileName = "countries_$this->language.json"; - $genresJson = json_encode($genres); - - $fileName = "countries_$this->language.json"; - - file_put_contents($this->destinationPath . $fileName, $genresJson); + file_put_contents($this->destinationPath . $fileName, $countriesJson); } catch (Throwable $th) { return false; } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Services/BackupGenresService.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Services/BackupGenresService.php index f7d89c7..0a6a847 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Services/BackupGenresService.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Services/BackupGenresService.php @@ -4,14 +4,12 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Application\Services; -use Psr\Log\LoggerInterface; use Throwable; use Xsga\FilmAffinityApi\Modules\Films\Infrastructure\Repositories\FilmAffinityGenresRepository; final class BackupGenresService { public function __construct( - private LoggerInterface $logger, private FilmAffinityGenresRepository $repository, private string $language, private string $destinationPath @@ -21,11 +19,9 @@ public function __construct( public function get(): bool { try { - $genres = $this->repository->getAll(); - + $genres = $this->repository->getAll(); $genresJson = json_encode($genres); - - $fileName = "genres_$this->language.json"; + $fileName = "genres_$this->language.json"; file_put_contents($this->destinationPath . $fileName, $genresJson); } catch (Throwable $th) { diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/GenreTopic.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/GenreTopic.php index 1320453..0e1b664 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/GenreTopic.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/GenreTopic.php @@ -4,8 +4,27 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Domain\Model; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\GenreTopicId; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\GenreTopicName; + class GenreTopic { - public int $id = 0; - public string $name = ''; + private GenreTopicId $id; + private GenreTopicName $name; + + public function __construct(int $id, string $name) + { + $this->id = new GenreTopicId($id); + $this->name = new GenreTopicName($name); + } + + public function id(): int + { + return $this->id->value(); + } + + public function name(): string + { + return $this->name->value(); + } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php index c7496ad..e3b0985 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php @@ -193,10 +193,11 @@ private function getGenreTopic(DOMNode $item): GenreTopic { $url = trim($item->attributes?->getNamedItem('href')?->nodeValue); - $genreTopic = new GenreTopic(); - $genreTopic->id = (int)substr($url, strpos($url, 'topic=') + 6, strpos($url, '&') - strpos($url, 'topic=') - 6); - $genreTopic->name = trim($item->nodeValue); - + $genreTopic = new GenreTopic( + (int)substr($url, strpos($url, 'topic=') + 6, strpos($url, '&') - strpos($url, 'topic=') - 6), + trim($item->nodeValue) + ); + return $genreTopic; } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/GenreTopicId.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/GenreTopicId.php new file mode 100644 index 0000000..12df72c --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/GenreTopicId.php @@ -0,0 +1,20 @@ +value = $id; + } + + public function value(): int + { + return $this->value; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/GenreTopicName.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/GenreTopicName.php new file mode 100644 index 0000000..55c8b76 --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/GenreTopicName.php @@ -0,0 +1,20 @@ +value = $name; + } + + public function value(): string + { + return $this->value; + } +} From 2e83095297667f3e309457a7b72502cf7c6fc36c Mon Sep 17 00:00:00 2001 From: parker Date: Mon, 10 Jun 2024 17:49:55 +0200 Subject: [PATCH 17/39] Fix error --- .../Modules/Films/Application/Mappers/FilmToFilmDto.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php index 8f818f7..4a28024 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php @@ -59,7 +59,7 @@ private function getGenreTopics(array $genreTopics) : array $out = []; foreach ($genreTopics as $genreTopic) { - $out[] = $genreTopic->name; + $out[] = $genreTopic->name(); } return $out; From a59d7932bb73dac4f6dfe2fd4d08c37cb9ac4b49 Mon Sep 17 00:00:00 2001 From: parker Date: Mon, 10 Jun 2024 18:19:06 +0200 Subject: [PATCH 18/39] Director model object --- .../Application/Mappers/FilmToFilmDto.php | 17 ++++++++++- .../Modules/Films/Domain/Model/Director.php | 30 +++++++++++++++++++ .../Modules/Films/Domain/Model/Film.php | 9 ++++-- .../Films/Domain/Parsers/FilmParser.php | 29 ++++++++++++++---- .../Films/Domain/ValueObjects/DirectorId.php | 20 +++++++++++++ .../Domain/ValueObjects/DirectorName.php | 20 +++++++++++++ 6 files changed, 116 insertions(+), 9 deletions(-) create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Director.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/DirectorId.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/DirectorName.php diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php index 4a28024..609c5ea 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php @@ -5,6 +5,7 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Application\Mappers; use Xsga\FilmAffinityApi\Modules\Films\Application\Dto\FilmDto; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Director; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Film; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Genre; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\GenreTopic; @@ -24,7 +25,7 @@ public function convert(Film $film): FilmDto $filmDto->coverFile = $film->coverFile; $filmDto->rating = $film->rating; $filmDto->country = $film->country; - $filmDto->directors = $film->directors; + $filmDto->directors = $this->getDirectors($film->directors); $filmDto->screenplay = $film->screenplay; $filmDto->soundtrack = $film->soundtrack; $filmDto->photography = $film->photography; @@ -37,6 +38,20 @@ public function convert(Film $film): FilmDto return $filmDto; } + /** + * @param Director[] $directors + */ + private function getDirectors(array $directors) : array + { + $out = []; + + foreach ($directors as $director) { + $out[] = $director->name(); + } + + return $out; + } + /** * @param Genre[] $genres */ diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Director.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Director.php new file mode 100644 index 0000000..2bf7b27 --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Director.php @@ -0,0 +1,30 @@ +id = new DirectorId($id); + $this->name = new DirectorName($name); + } + + public function id(): int + { + return $this->id->value(); + } + + public function name(): string + { + return $this->name->value(); + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php index c808604..c55e5e1 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php @@ -15,12 +15,17 @@ class Film public string $coverFile = ''; public string $rating = ''; public string $country = ''; - public array $directors = []; public string $screenplay = ''; public string $soundtrack = ''; public string $photography = ''; public array $cast = []; public string $producer = ''; + public string $synopsis = ''; + + /** + * @var Director[] + */ + public array $directors = []; /** * @var Genre[] @@ -31,6 +36,4 @@ class Film * @var GenreTopic[] */ public array $genreTopics = []; - - public string $synopsis = ''; } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php index e3b0985..e9bf95d 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php @@ -4,7 +4,9 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers; +use DOMElement; use DOMNode; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Director; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Film; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Genre; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\GenreTopic; @@ -15,7 +17,7 @@ final class FilmParser extends AbstractParser private const string QUERY_FILM_GET_TITLE = "//h1[@id = 'main-title']/span[@itemprop = 'name']"; private const string QUERY_FILM_GET_RELEASE_DATE = "//dd[@itemprop = 'datePublished']"; private const string QUERY_FILM_GET_DURATION = "//dd[@itemprop = 'duration']"; - private const string QUERY_FILM_GET_DIRECTORS = "//span[@itemprop = 'director']//span[@itemprop = 'name']"; + private const string QUERY_FILM_GET_DIRECTORS = "//span[@itemprop = 'director']/a"; private const string QUERY_FILM_GET_ACTORS = "//li[@itemprop = 'actor']"; private const string QUERY_FILM_GET_PRODUCERS = "//dd[@class = 'card-producer']//span"; private const string QUERY_FILM_GET_GENRES = "//span[@itemprop = 'genre']/a"; @@ -112,15 +114,32 @@ private function getDuration(): string return trim(str_replace('min.', '', $data[0])); } + /** + * @return Director[] + */ private function getDirectors(): array { - $data = $this->getData(self::QUERY_FILM_GET_DIRECTORS); + $data = $this->getData(self::QUERY_FILM_GET_DIRECTORS, false); - if (!$this->validateMultipleResult($data, 'film directors')) { - return []; + $out = []; + + foreach ($data as $item) { + $out[] = $this->getDirector($item); } - return array_map('trim', $data); + return $out; + } + + private function getDirector(DOMElement $item): Director + { + $url = trim($item->getAttribute('href')); + + $director = new Director( + (int)substr($url, strpos($url, 'name-id=') + 8, -1), + trim($item->nodeValue) + ); + + return $director; } private function getActors(): array diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/DirectorId.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/DirectorId.php new file mode 100644 index 0000000..15e0767 --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/DirectorId.php @@ -0,0 +1,20 @@ +value = $id; + } + + public function value(): int + { + return $this->value; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/DirectorName.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/DirectorName.php new file mode 100644 index 0000000..f361242 --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/DirectorName.php @@ -0,0 +1,20 @@ +value = $name; + } + + public function value(): string + { + return $this->value; + } +} From 71618fc77d31827a62cb1a2a59b279031cad014c Mon Sep 17 00:00:00 2001 From: parker Date: Mon, 10 Jun 2024 18:28:02 +0200 Subject: [PATCH 19/39] Actors model --- .../Application/Mappers/FilmToFilmDto.php | 17 ++++++++++- .../Modules/Films/Domain/Model/Actor.php | 30 +++++++++++++++++++ .../Modules/Films/Domain/Model/Film.php | 6 +++- .../Films/Domain/Parsers/FilmParser.php | 28 +++++++++++++---- .../Films/Domain/ValueObjects/ActorId.php | 20 +++++++++++++ .../Films/Domain/ValueObjects/ActorName.php | 20 +++++++++++++ 6 files changed, 114 insertions(+), 7 deletions(-) create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Actor.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/ActorId.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/ActorName.php diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php index 609c5ea..64fdcb1 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php @@ -5,6 +5,7 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Application\Mappers; use Xsga\FilmAffinityApi\Modules\Films\Application\Dto\FilmDto; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Actor; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Director; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Film; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Genre; @@ -29,7 +30,7 @@ public function convert(Film $film): FilmDto $filmDto->screenplay = $film->screenplay; $filmDto->soundtrack = $film->soundtrack; $filmDto->photography = $film->photography; - $filmDto->cast = $film->cast; + $filmDto->cast = $this->getActors($film->cast); $filmDto->producer = $film->producer; $filmDto->genres = $this->getGenres($film->genres); $filmDto->genreTopics = $this->getGenreTopics($film->genreTopics); @@ -52,6 +53,20 @@ private function getDirectors(array $directors) : array return $out; } + /** + * @param Actor[] $actors + */ + private function getActors(array $actors) : array + { + $out = []; + + foreach ($actors as $actor) { + $out[] = $actor->name(); + } + + return $out; + } + /** * @param Genre[] $genres */ diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Actor.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Actor.php new file mode 100644 index 0000000..10ff196 --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Actor.php @@ -0,0 +1,30 @@ +id = new ActorId($id); + $this->name = new ActorName($name); + } + + public function id(): int + { + return $this->id->value(); + } + + public function name(): string + { + return $this->name->value(); + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php index c55e5e1..6a368ca 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php @@ -18,9 +18,13 @@ class Film public string $screenplay = ''; public string $soundtrack = ''; public string $photography = ''; - public array $cast = []; public string $producer = ''; public string $synopsis = ''; + + /** + * @var Actor[] + */ + public array $cast = []; /** * @var Director[] diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php index e9bf95d..a9286e4 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php @@ -6,6 +6,7 @@ use DOMElement; use DOMNode; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Actor; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Director; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Film; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Genre; @@ -18,7 +19,7 @@ final class FilmParser extends AbstractParser private const string QUERY_FILM_GET_RELEASE_DATE = "//dd[@itemprop = 'datePublished']"; private const string QUERY_FILM_GET_DURATION = "//dd[@itemprop = 'duration']"; private const string QUERY_FILM_GET_DIRECTORS = "//span[@itemprop = 'director']/a"; - private const string QUERY_FILM_GET_ACTORS = "//li[@itemprop = 'actor']"; + private const string QUERY_FILM_GET_ACTORS = "//li[@itemprop = 'actor']/a"; private const string QUERY_FILM_GET_PRODUCERS = "//dd[@class = 'card-producer']//span"; private const string QUERY_FILM_GET_GENRES = "//span[@itemprop = 'genre']/a"; private const string QUERY_FILM_GET_GENRE_TOPICS = "//dd[@class = 'card-genres']/a"; @@ -142,15 +143,32 @@ private function getDirector(DOMElement $item): Director return $director; } + /** + * @return Actor[] + */ private function getActors(): array { - $data = $this->getData(self::QUERY_FILM_GET_ACTORS); + $data = $this->getData(self::QUERY_FILM_GET_ACTORS, false); + + $out = []; - if (!$this->validateMultipleResult($data, 'film actors')) { - return []; + foreach ($data as $item) { + $out[] = $this->getActor($item); } - return array_map('trim', $data); + return $out; + } + + private function getActor(DOMElement $item): Actor + { + $url = trim($item->getAttribute('href')); + + $actor = new Actor( + (int)substr($url, strpos($url, 'name-id=') + 8, -1), + trim($item->nodeValue) + ); + + return $actor; } private function getProducers(): string diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/ActorId.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/ActorId.php new file mode 100644 index 0000000..056b9fe --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/ActorId.php @@ -0,0 +1,20 @@ +value = $id; + } + + public function value(): int + { + return $this->value; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/ActorName.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/ActorName.php new file mode 100644 index 0000000..b243264 --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/ActorName.php @@ -0,0 +1,20 @@ +value = $name; + } + + public function value(): string + { + return $this->value; + } +} From 2ef5cff9ddaef3e540401a7ed3a397ce534d5863 Mon Sep 17 00:00:00 2001 From: parker Date: Tue, 11 Jun 2024 09:14:52 +0200 Subject: [PATCH 20/39] Film country --- .../Application/Mappers/FilmToFilmDto.php | 2 +- .../Modules/Films/Domain/Model/Film.php | 2 +- .../Films/Domain/Parsers/FilmParser.php | 34 +++++++++++-------- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php index 64fdcb1..daa3b05 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php @@ -25,7 +25,7 @@ public function convert(Film $film): FilmDto $filmDto->coverUrl = $film->coverUrl; $filmDto->coverFile = $film->coverFile; $filmDto->rating = $film->rating; - $filmDto->country = $film->country; + $filmDto->country = $film->country->name(); $filmDto->directors = $this->getDirectors($film->directors); $filmDto->screenplay = $film->screenplay; $filmDto->soundtrack = $film->soundtrack; diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php index 6a368ca..4e7dc89 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php @@ -14,7 +14,7 @@ class Film public string $coverUrl = ''; public string $coverFile = ''; public string $rating = ''; - public string $country = ''; + public Country $country; public string $screenplay = ''; public string $soundtrack = ''; public string $photography = ''; diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php index a9286e4..ef5031e 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php @@ -7,6 +7,7 @@ use DOMElement; use DOMNode; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Actor; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Country; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Director; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Film; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Genre; @@ -14,10 +15,12 @@ final class FilmParser extends AbstractParser { - private const string QUERY_FILM_GET_VARIOUS = "//dd[not(@class) and not(@itemprop)]"; + private const string QUERY_FILM_GET_VARIOUS = "//dd[not(@class) and not(@itemprop)]/div"; private const string QUERY_FILM_GET_TITLE = "//h1[@id = 'main-title']/span[@itemprop = 'name']"; + private const string QUERY_FILM_GET_ORIGINAL_TITLE = "//dd[not(@class) and not(@itemprop)]"; private const string QUERY_FILM_GET_RELEASE_DATE = "//dd[@itemprop = 'datePublished']"; private const string QUERY_FILM_GET_DURATION = "//dd[@itemprop = 'duration']"; + private const string QUERY_FILM_GET_COUNTRY = "//img[@class = 'nflag']"; private const string QUERY_FILM_GET_DIRECTORS = "//span[@itemprop = 'director']/a"; private const string QUERY_FILM_GET_ACTORS = "//li[@itemprop = 'actor']/a"; private const string QUERY_FILM_GET_PRODUCERS = "//dd[@class = 'card-producer']//span"; @@ -240,7 +243,7 @@ private function getGenreTopic(DOMNode $item): GenreTopic private function getOriginalTitle(): string { - $data = $this->getData(self::QUERY_FILM_GET_VARIOUS); + $data = $this->getData(self::QUERY_FILM_GET_ORIGINAL_TITLE); return match (isset($data[0])) { true => trim(str_replace('aka', '', $data[0])), @@ -248,22 +251,25 @@ private function getOriginalTitle(): string }; } - private function getCountry(): string + private function getCountry(): Country { - $data = $this->getData(self::QUERY_FILM_GET_VARIOUS); + $data = $this->getData(self::QUERY_FILM_GET_COUNTRY, false); - return match (isset($data[1])) { - true => trim(trim($data[1], chr(0xC2) . chr(0xA0))), - false => '' - }; + $url = $data->item(0)->attributes->getNamedItem('src')->nodeValue; + $urlArray = explode('/', $url); + $flagImg = end($urlArray); + $flagImgArray = explode('.', $flagImg); + $countryCode = $flagImgArray[0]; + + return new Country($countryCode, $data->item(0)->attributes->getNamedItem('alt')->nodeValue); } private function getScreenplay(): string { $data = $this->getData(self::QUERY_FILM_GET_VARIOUS); - return match (isset($data[2])) { - true => trim($data[2]), + return match (isset($data[0])) { + true => trim($data[0]), false => '' }; } @@ -272,8 +278,8 @@ private function getSoundtrack(): string { $data = $this->getData(self::QUERY_FILM_GET_VARIOUS); - return match (isset($data[3])) { - true => trim($data[3]), + return match (isset($data[1])) { + true => trim($data[1]), false => '' }; } @@ -282,8 +288,8 @@ private function getPhotography(): string { $data = $this->getData(self::QUERY_FILM_GET_VARIOUS); - return match (isset($data[4])) { - true => trim($data[4]), + return match (isset($data[2])) { + true => trim($data[2]), false => '' }; } From 4a45610f7e8e4b8c574082c049e859e410208717 Mon Sep 17 00:00:00 2001 From: parker Date: Tue, 11 Jun 2024 10:09:05 +0200 Subject: [PATCH 21/39] Parsers refactor --- config/container/Container.php | 10 +- .../Application/Mappers/FilmToFilmDto.php | 4 +- .../Modules/Films/Domain/Model/Cover.php | 30 +++ .../Modules/Films/Domain/Model/Film.php | 4 +- .../Films/Domain/Parsers/FilmCastParser.php | 41 ++++ .../Films/Domain/Parsers/FilmCoverParser.php | 45 ++++ .../Domain/Parsers/FilmDirectorsParser.php | 41 ++++ .../Films/Domain/Parsers/FilmGenresParser.php | 71 ++++++ .../Films/Domain/Parsers/FilmParser.php | 202 ++---------------- .../Domain/ValueObjects/CoverFileName.php | 20 ++ .../Films/Domain/ValueObjects/CoverUrl.php | 20 ++ .../FilmAffinityFilmsRepository.php | 43 +++- 12 files changed, 333 insertions(+), 198 deletions(-) create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Cover.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCastParser.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCoverParser.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmDirectorsParser.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmGenresParser.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/CoverFileName.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/CoverUrl.php diff --git a/config/container/Container.php b/config/container/Container.php index 9d19e0a..b54b527 100644 --- a/config/container/Container.php +++ b/config/container/Container.php @@ -18,6 +18,10 @@ use Xsga\FilmAffinityApi\Modules\Films\Application\Services\BackupGenresService; use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\AdvancedSearchFormParser; use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\AdvancedSearchParser; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmCastParser; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmCoverParser; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmDirectorsParser; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmGenresParser; use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmParser; use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\SimpleSearchParser; use Xsga\FilmAffinityApi\Modules\Films\Domain\Repositories\AdvancedSearchRepository; @@ -200,7 +204,11 @@ FilmsRepository::class => DI\create(FilmAffinityFilmsRepository::class)->constructor( DI\get(UrlService::class), DI\get(HttpClientService::class), - DI\get(FilmParser::class) + DI\get(FilmParser::class), + DI\get(FilmCastParser::class), + DI\get(FilmCoverParser::class), + DI\get(FilmDirectorsParser::class), + DI\get(FilmGenresParser::class) ), GenresRepository::class => DI\create(FilmAffinityGenresRepository::class)->constructor( DI\get(LoggerInterface::class), diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php index daa3b05..fcfff21 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php @@ -22,8 +22,8 @@ public function convert(Film $film): FilmDto $filmDto->originalTitle = $film->originalTitle; $filmDto->year = $film->year; $filmDto->duration = $film->duration; - $filmDto->coverUrl = $film->coverUrl; - $filmDto->coverFile = $film->coverFile; + $filmDto->coverUrl = $film->cover->url(); + $filmDto->coverFile = $film->cover->fileName(); $filmDto->rating = $film->rating; $filmDto->country = $film->country->name(); $filmDto->directors = $this->getDirectors($film->directors); diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Cover.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Cover.php new file mode 100644 index 0000000..4646b0f --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Cover.php @@ -0,0 +1,30 @@ +url = new CoverUrl($url); + $this->fileName = new CoverFileName($fileName); + } + + public function url(): string + { + return $this->url->value(); + } + + public function fileName(): string + { + return $this->fileName->value(); + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php index 4e7dc89..de8554f 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php @@ -11,8 +11,6 @@ class Film public string $originalTitle = ''; public string $year = ''; public string $duration = ''; - public string $coverUrl = ''; - public string $coverFile = ''; public string $rating = ''; public Country $country; public string $screenplay = ''; @@ -21,6 +19,8 @@ class Film public string $producer = ''; public string $synopsis = ''; + public Cover $cover; + /** * @var Actor[] */ diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCastParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCastParser.php new file mode 100644 index 0000000..a84f3bf --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCastParser.php @@ -0,0 +1,41 @@ +getData(self::QUERY_FILM_GET_ACTORS, false); + + $out = []; + + foreach ($data as $item) { + $out[] = $this->getActor($item); + } + + return $out; + } + + private function getActor(DOMElement $item): Actor + { + $url = trim($item->getAttribute('href')); + + $actor = new Actor( + (int)substr($url, strpos($url, 'name-id=') + 8, -1), + trim($item->nodeValue) + ); + + return $actor; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCoverParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCoverParser.php new file mode 100644 index 0000000..59f2b3b --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCoverParser.php @@ -0,0 +1,45 @@ +getCoverUrl(), $this->getCoverFileName()); + } + + private function getCoverUrl(): string + { + $data = $this->getData(self::QUERY_FILM_GET_COVER, false); + + if ($data->length === 0) { + $this->logger->warning('Film cover URL not found'); + return ''; + } + + return trim($data->item(0)?->attributes?->getNamedItem('href')?->nodeValue); + } + + private function getCoverFileName(): string + { + $data = $this->getData(self::QUERY_FILM_GET_COVER, false); + + if ($data->length === 0) { + $this->logger->warning('Film cover file not found'); + return ''; + } + + $coverUrl = trim($data->item(0)?->attributes?->getNamedItem('href')?->nodeValue); + $coverUrlArray = explode('/', $coverUrl); + $coverFile = end($coverUrlArray); + + return $coverFile; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmDirectorsParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmDirectorsParser.php new file mode 100644 index 0000000..0a86b25 --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmDirectorsParser.php @@ -0,0 +1,41 @@ +getData(self::QUERY_FILM_GET_DIRECTORS, false); + + $out = []; + + foreach ($data as $item) { + $out[] = $this->getDirector($item); + } + + return $out; + } + + private function getDirector(DOMElement $item): Director + { + $url = trim($item->getAttribute('href')); + + $director = new Director( + (int)substr($url, strpos($url, 'name-id=') + 8, -1), + trim($item->nodeValue) + ); + + return $director; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmGenresParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmGenresParser.php new file mode 100644 index 0000000..e2f4236 --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmGenresParser.php @@ -0,0 +1,71 @@ +getData(self::QUERY_FILM_GET_GENRES, false); + + $out = []; + + foreach ($data as $item) { + $out[] = $this->getGenre($item); + } + + return $out; + } + + private function getGenre(DOMNode $item): Genre + { + $url = trim($item->attributes?->getNamedItem('href')?->nodeValue); + + $genre = new Genre( + substr($url, strpos($url, 'genre=') + 6, strpos($url, '&') - strpos($url, 'genre=') - 6), + trim($item->nodeValue) + ); + + return $genre; + } + + /** + * @return GenreTopic[] + */ + public function getGenreTopics(): array + { + $data = $this->getData(self::QUERY_FILM_GET_GENRE_TOPICS, false); + + $out = []; + + foreach ($data as $item) { + $out[] = $this->getGenreTopic($item); + } + + return $out; + } + + private function getGenreTopic(DOMNode $item): GenreTopic + { + $url = trim($item->attributes?->getNamedItem('href')?->nodeValue); + + $genreTopic = new GenreTopic( + (int)substr($url, strpos($url, 'topic=') + 6, strpos($url, '&') - strpos($url, 'topic=') - 6), + trim($item->nodeValue) + ); + + return $genreTopic; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php index ef5031e..d5bb14a 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php @@ -4,14 +4,7 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers; -use DOMElement; -use DOMNode; -use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Actor; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Country; -use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Director; -use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Film; -use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Genre; -use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\GenreTopic; final class FilmParser extends AbstractParser { @@ -21,41 +14,10 @@ final class FilmParser extends AbstractParser private const string QUERY_FILM_GET_RELEASE_DATE = "//dd[@itemprop = 'datePublished']"; private const string QUERY_FILM_GET_DURATION = "//dd[@itemprop = 'duration']"; private const string QUERY_FILM_GET_COUNTRY = "//img[@class = 'nflag']"; - private const string QUERY_FILM_GET_DIRECTORS = "//span[@itemprop = 'director']/a"; - private const string QUERY_FILM_GET_ACTORS = "//li[@itemprop = 'actor']/a"; private const string QUERY_FILM_GET_PRODUCERS = "//dd[@class = 'card-producer']//span"; - private const string QUERY_FILM_GET_GENRES = "//span[@itemprop = 'genre']/a"; - private const string QUERY_FILM_GET_GENRE_TOPICS = "//dd[@class = 'card-genres']/a"; private const string QUERY_FILM_GET_RATING = "//div[@id = 'movie-rat-avg']"; private const string QUERY_FILM_GET_SYNOPSIS = "//dd[@class = '' and @itemprop = 'description']"; - private const string QUERY_FILM_GET_COVER = "//a[@class = 'lightbox']"; - - public function getFilm(int $filmId): Film - { - $film = new Film(); - - $film->filmAfinityId = $filmId; - $film->title = $this->getTitle(); - $film->originalTitle = $this->getOriginalTitle(); - $film->year = $this->getYear(); - $film->duration = $this->getDuration(); - $film->country = $this->getCountry(); - $film->directors = $this->getDirectors(); - $film->screenplay = $this->getScreenplay(); - $film->soundtrack = $this->getSoundtrack(); - $film->photography = $this->getPhotography(); - $film->cast = $this->getActors(); - $film->producer = $this->getProducers(); - $film->genres = $this->getGenres(); - $film->genreTopics = $this->getGenreTopics(); - $film->rating = $this->getRating(); - $film->synopsis = $this->getSynopsis(); - $film->coverUrl = $this->getCoverUrl(); - $film->coverFile = $this->getCoverFile(); - - return $film; - } - + private function validateOneResult(array $results, string $element): bool { $resultsCount = count($results); @@ -85,7 +47,7 @@ private function validateMultipleResult(array $results, string $element): bool return true; } - private function getTitle(): string + public function getTitle(): string { $data = $this->getData(self::QUERY_FILM_GET_TITLE); @@ -96,7 +58,7 @@ private function getTitle(): string return trim($data[0]); } - private function getYear(): string + public function getYear(): string { $data = $this->getData(self::QUERY_FILM_GET_RELEASE_DATE); @@ -107,7 +69,7 @@ private function getYear(): string return trim($data[0]); } - private function getDuration(): string + public function getDuration(): string { $data = $this->getData(self::QUERY_FILM_GET_DURATION); @@ -118,63 +80,7 @@ private function getDuration(): string return trim(str_replace('min.', '', $data[0])); } - /** - * @return Director[] - */ - private function getDirectors(): array - { - $data = $this->getData(self::QUERY_FILM_GET_DIRECTORS, false); - - $out = []; - - foreach ($data as $item) { - $out[] = $this->getDirector($item); - } - - return $out; - } - - private function getDirector(DOMElement $item): Director - { - $url = trim($item->getAttribute('href')); - - $director = new Director( - (int)substr($url, strpos($url, 'name-id=') + 8, -1), - trim($item->nodeValue) - ); - - return $director; - } - - /** - * @return Actor[] - */ - private function getActors(): array - { - $data = $this->getData(self::QUERY_FILM_GET_ACTORS, false); - - $out = []; - - foreach ($data as $item) { - $out[] = $this->getActor($item); - } - - return $out; - } - - private function getActor(DOMElement $item): Actor - { - $url = trim($item->getAttribute('href')); - - $actor = new Actor( - (int)substr($url, strpos($url, 'name-id=') + 8, -1), - trim($item->nodeValue) - ); - - return $actor; - } - - private function getProducers(): string + public function getProducers(): string { $data = $this->getData(self::QUERY_FILM_GET_PRODUCERS); @@ -185,63 +91,7 @@ private function getProducers(): string return implode(' ', $data); } - /** - * @return Genre[] - */ - private function getGenres(): array - { - $data = $this->getData(self::QUERY_FILM_GET_GENRES, false); - - $out = []; - - foreach ($data as $item) { - $out[] = $this->getGenre($item); - } - - return $out; - } - - private function getGenre(DOMNode $item): Genre - { - $url = trim($item->attributes?->getNamedItem('href')?->nodeValue); - - $genre = new Genre( - substr($url, strpos($url, 'genre=') + 6, strpos($url, '&') - strpos($url, 'genre=') - 6), - trim($item->nodeValue) - ); - - return $genre; - } - - /** - * @return GenreTopic[] - */ - private function getGenreTopics(): array - { - $data = $this->getData(self::QUERY_FILM_GET_GENRE_TOPICS, false); - - $out = []; - - foreach ($data as $item) { - $out[] = $this->getGenreTopic($item); - } - - return $out; - } - - private function getGenreTopic(DOMNode $item): GenreTopic - { - $url = trim($item->attributes?->getNamedItem('href')?->nodeValue); - - $genreTopic = new GenreTopic( - (int)substr($url, strpos($url, 'topic=') + 6, strpos($url, '&') - strpos($url, 'topic=') - 6), - trim($item->nodeValue) - ); - - return $genreTopic; - } - - private function getOriginalTitle(): string + public function getOriginalTitle(): string { $data = $this->getData(self::QUERY_FILM_GET_ORIGINAL_TITLE); @@ -251,7 +101,7 @@ private function getOriginalTitle(): string }; } - private function getCountry(): Country + public function getCountry(): Country { $data = $this->getData(self::QUERY_FILM_GET_COUNTRY, false); @@ -264,7 +114,7 @@ private function getCountry(): Country return new Country($countryCode, $data->item(0)->attributes->getNamedItem('alt')->nodeValue); } - private function getScreenplay(): string + public function getScreenplay(): string { $data = $this->getData(self::QUERY_FILM_GET_VARIOUS); @@ -274,7 +124,7 @@ private function getScreenplay(): string }; } - private function getSoundtrack(): string + public function getSoundtrack(): string { $data = $this->getData(self::QUERY_FILM_GET_VARIOUS); @@ -284,7 +134,7 @@ private function getSoundtrack(): string }; } - private function getPhotography(): string + public function getPhotography(): string { $data = $this->getData(self::QUERY_FILM_GET_VARIOUS); @@ -294,7 +144,7 @@ private function getPhotography(): string }; } - private function getRating(): string + public function getRating(): string { $data = $this->getData(self::QUERY_FILM_GET_RATING); @@ -305,7 +155,7 @@ private function getRating(): string return trim($data[0]); } - private function getSynopsis(): string + public function getSynopsis(): string { $data = $this->getData(self::QUERY_FILM_GET_SYNOPSIS); @@ -315,32 +165,4 @@ private function getSynopsis(): string return trim(str_replace('(FILMAFFINITY)', '', $data[0])); } - - private function getCoverUrl(): string - { - $data = $this->getData(self::QUERY_FILM_GET_COVER, false); - - if ($data->length === 0) { - $this->logger->warning('Film cover URL not found'); - return ''; - } - - return trim($data->item(0)?->attributes?->getNamedItem('href')?->nodeValue); - } - - private function getCoverFile(): string - { - $data = $this->getData(self::QUERY_FILM_GET_COVER, false); - - if ($data->length === 0) { - $this->logger->warning('Film cover file not found'); - return ''; - } - - $coverUrl = trim($data->item(0)?->attributes?->getNamedItem('href')?->nodeValue); - $coverUrlArray = explode('/', $coverUrl); - $coverFile = end($coverUrlArray); - - return $coverFile; - } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/CoverFileName.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/CoverFileName.php new file mode 100644 index 0000000..57ebe6c --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/CoverFileName.php @@ -0,0 +1,20 @@ +value = $fileName; + } + + public function value(): string + { + return $this->value; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/CoverUrl.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/CoverUrl.php new file mode 100644 index 0000000..fc65930 --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/CoverUrl.php @@ -0,0 +1,20 @@ +value = $url; + } + + public function value(): string + { + return $this->value; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinityFilmsRepository.php b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinityFilmsRepository.php index 315451b..1446597 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinityFilmsRepository.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinityFilmsRepository.php @@ -5,6 +5,10 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Infrastructure\Repositories; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Film; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmCastParser; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmCoverParser; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmDirectorsParser; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmGenresParser; use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmParser; use Xsga\FilmAffinityApi\Modules\Films\Domain\Repositories\FilmsRepository; use Xsga\FilmAffinityApi\Modules\Films\Domain\Services\UrlService; @@ -15,7 +19,11 @@ final class FilmAffinityFilmsRepository implements FilmsRepository public function __construct( private UrlService $urlService, private HttpClientService $httpClientService, - private FilmParser $parser + private FilmParser $filmParser, + private FilmCastParser $castParser, + private FilmCoverParser $coverParser, + private FilmDirectorsParser $directorsParser, + private FilmGenresParser $genresParser ) { } @@ -24,8 +32,37 @@ public function get(int $filmId): Film $filmUrl = $this->urlService->getFilmUrl($filmId); $pageContent = $this->httpClientService->getPageContent($filmUrl); - $this->parser->init($pageContent); + $this->filmParser->init($pageContent); + $this->castParser->init($pageContent); + $this->coverParser->init($pageContent); + $this->directorsParser->init($pageContent); + $this->genresParser->init($pageContent); - return $this->parser->getFilm($filmId); + return $this->getFilm($filmId); + } + + private function getFilm(int $filmId): Film + { + $film = new Film(); + + $film->filmAfinityId = $filmId; + $film->title = $this->filmParser->getTitle(); + $film->originalTitle = $this->filmParser->getOriginalTitle(); + $film->year = $this->filmParser->getYear(); + $film->duration = $this->filmParser->getDuration(); + $film->country = $this->filmParser->getCountry(); + $film->directors = $this->directorsParser->getDirectors(); + $film->screenplay = $this->filmParser->getScreenplay(); + $film->soundtrack = $this->filmParser->getSoundtrack(); + $film->photography = $this->filmParser->getPhotography(); + $film->cast = $this->castParser->getCast(); + $film->producer = $this->filmParser->getProducers(); + $film->genres = $this->genresParser->getGenres(); + $film->genreTopics = $this->genresParser->getGenreTopics(); + $film->rating = $this->filmParser->getRating(); + $film->synopsis = $this->filmParser->getSynopsis(); + $film->cover = $this->coverParser->getCover(); + + return $film; } } From 2fc2f42d98e798794d1d3da95b279469040b7c7c Mon Sep 17 00:00:00 2001 From: parker Date: Tue, 11 Jun 2024 10:56:06 +0200 Subject: [PATCH 22/39] Get film service --- config/container/Container.php | 12 +--- .../Films/Domain/Services/GetFilmService.php | 60 +++++++++++++++++++ .../FilmAffinityFilmsRepository.php | 45 +------------- .../FilmAffinityGenresRepository.php | 6 +- 4 files changed, 68 insertions(+), 55 deletions(-) create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetFilmService.php diff --git a/config/container/Container.php b/config/container/Container.php index b54b527..cf9e1b1 100644 --- a/config/container/Container.php +++ b/config/container/Container.php @@ -18,17 +18,13 @@ use Xsga\FilmAffinityApi\Modules\Films\Application\Services\BackupGenresService; use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\AdvancedSearchFormParser; use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\AdvancedSearchParser; -use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmCastParser; -use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmCoverParser; -use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmDirectorsParser; -use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmGenresParser; -use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmParser; use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\SimpleSearchParser; use Xsga\FilmAffinityApi\Modules\Films\Domain\Repositories\AdvancedSearchRepository; use Xsga\FilmAffinityApi\Modules\Films\Domain\Repositories\CountriesRepository; use Xsga\FilmAffinityApi\Modules\Films\Domain\Repositories\FilmsRepository; use Xsga\FilmAffinityApi\Modules\Films\Domain\Repositories\GenresRepository; use Xsga\FilmAffinityApi\Modules\Films\Domain\Repositories\SearchRepository; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Services\GetFilmService; use Xsga\FilmAffinityApi\Modules\Films\Domain\Services\UrlService; use Xsga\FilmAffinityApi\Modules\Films\Infrastructure\Repositories\FilmAffinityAdvancedSearchRepository; use Xsga\FilmAffinityApi\Modules\Films\Infrastructure\Repositories\FilmAffinityCountriesRepository; @@ -204,11 +200,7 @@ FilmsRepository::class => DI\create(FilmAffinityFilmsRepository::class)->constructor( DI\get(UrlService::class), DI\get(HttpClientService::class), - DI\get(FilmParser::class), - DI\get(FilmCastParser::class), - DI\get(FilmCoverParser::class), - DI\get(FilmDirectorsParser::class), - DI\get(FilmGenresParser::class) + DI\get(GetFilmService::class) ), GenresRepository::class => DI\create(FilmAffinityGenresRepository::class)->constructor( DI\get(LoggerInterface::class), diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetFilmService.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetFilmService.php new file mode 100644 index 0000000..c2cafdc --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetFilmService.php @@ -0,0 +1,60 @@ +filmParser->init($pageContent); + $this->castParser->init($pageContent); + $this->coverParser->init($pageContent); + $this->directorsParser->init($pageContent); + $this->genresParser->init($pageContent); + + return $this->getFilm($filmId); + } + + private function getFilm(int $filmId): Film + { + $film = new Film(); + + $film->filmAfinityId = $filmId; + $film->title = $this->filmParser->getTitle(); + $film->originalTitle = $this->filmParser->getOriginalTitle(); + $film->year = $this->filmParser->getYear(); + $film->duration = $this->filmParser->getDuration(); + $film->country = $this->filmParser->getCountry(); + $film->directors = $this->directorsParser->getDirectors(); + $film->screenplay = $this->filmParser->getScreenplay(); + $film->soundtrack = $this->filmParser->getSoundtrack(); + $film->photography = $this->filmParser->getPhotography(); + $film->cast = $this->castParser->getCast(); + $film->producer = $this->filmParser->getProducers(); + $film->genres = $this->genresParser->getGenres(); + $film->genreTopics = $this->genresParser->getGenreTopics(); + $film->rating = $this->filmParser->getRating(); + $film->synopsis = $this->filmParser->getSynopsis(); + $film->cover = $this->coverParser->getCover(); + + return $film; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinityFilmsRepository.php b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinityFilmsRepository.php index 1446597..6148351 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinityFilmsRepository.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinityFilmsRepository.php @@ -5,12 +5,8 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Infrastructure\Repositories; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Film; -use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmCastParser; -use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmCoverParser; -use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmDirectorsParser; -use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmGenresParser; -use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmParser; use Xsga\FilmAffinityApi\Modules\Films\Domain\Repositories\FilmsRepository; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Services\GetFilmService; use Xsga\FilmAffinityApi\Modules\Films\Domain\Services\UrlService; use Xsga\FilmAffinityApi\Modules\Shared\HttpClient\Application\Services\HttpClientService; @@ -19,11 +15,7 @@ final class FilmAffinityFilmsRepository implements FilmsRepository public function __construct( private UrlService $urlService, private HttpClientService $httpClientService, - private FilmParser $filmParser, - private FilmCastParser $castParser, - private FilmCoverParser $coverParser, - private FilmDirectorsParser $directorsParser, - private FilmGenresParser $genresParser + private GetFilmService $getFilm ) { } @@ -32,37 +24,6 @@ public function get(int $filmId): Film $filmUrl = $this->urlService->getFilmUrl($filmId); $pageContent = $this->httpClientService->getPageContent($filmUrl); - $this->filmParser->init($pageContent); - $this->castParser->init($pageContent); - $this->coverParser->init($pageContent); - $this->directorsParser->init($pageContent); - $this->genresParser->init($pageContent); - - return $this->getFilm($filmId); - } - - private function getFilm(int $filmId): Film - { - $film = new Film(); - - $film->filmAfinityId = $filmId; - $film->title = $this->filmParser->getTitle(); - $film->originalTitle = $this->filmParser->getOriginalTitle(); - $film->year = $this->filmParser->getYear(); - $film->duration = $this->filmParser->getDuration(); - $film->country = $this->filmParser->getCountry(); - $film->directors = $this->directorsParser->getDirectors(); - $film->screenplay = $this->filmParser->getScreenplay(); - $film->soundtrack = $this->filmParser->getSoundtrack(); - $film->photography = $this->filmParser->getPhotography(); - $film->cast = $this->castParser->getCast(); - $film->producer = $this->filmParser->getProducers(); - $film->genres = $this->genresParser->getGenres(); - $film->genreTopics = $this->genresParser->getGenreTopics(); - $film->rating = $this->filmParser->getRating(); - $film->synopsis = $this->filmParser->getSynopsis(); - $film->cover = $this->coverParser->getCover(); - - return $film; + return $this->getFilm->get($filmId, $pageContent); } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinityGenresRepository.php b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinityGenresRepository.php index 385d4a4..6c4a002 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinityGenresRepository.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinityGenresRepository.php @@ -31,14 +31,14 @@ public function getAll(): array $this->parser->init($pageContent); - $countries = $this->parser->getGenres(); + $genres = $this->parser->getGenres(); - if (empty($countries)) { + if (empty($genres)) { $this->logger->error('Error loading genres from FilmAffinity'); return []; } - return $countries; + return $genres; } public function get(string $code): ?Genre From 0b127f9476ba71c3e0d8cceef814e0e876e80146 Mon Sep 17 00:00:00 2001 From: parker <67624778+xsga@users.noreply.github.com> Date: Tue, 11 Jun 2024 16:25:53 +0200 Subject: [PATCH 23/39] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3ab5f4d..6595c96 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Language](https://img.shields.io/github/languages/top/xsga/filmaffinity-api)](https://php.net/) [![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%208.3-8892BF?style=flat)](https://php.net/) -[![Latest version](https://img.shields.io/github/v/release/xsga/filmaffinity-api)](https://github.com/xsga/filmaffinity-api/releases/tag/v6.0.0) +[![Latest version](https://img.shields.io/github/v/release/xsga/filmaffinity-api)](https://github.com/xsga/filmaffinity-api/releases/tag/v6.0.1) [![License](https://img.shields.io/github/license/xsga/filmaffinity-api)](https://opensource.org/licenses/MIT) FilmAffinity-API is a public and non offical API wich allow you to get information about films from [FilmAffinity](http://filmaffinity.com "FilmAffinity Home") website. You can search films and get their complet information, including cast, synopsis and cover. @@ -198,7 +198,8 @@ docker exec -it filmaffinityapi-web-server php .bin/console "photography": "Andrzej Sekula", "cast": ["John Travolta", "Samuel L. Jackson", "Uma Thurman", "Bruce Willis", "Ving Rhames", "Harvey Keitel", "Tim Roth", "Amanda Plummer", "María de Medeiros", "Eric Stoltz", "Rosanna Arquette", "Christopher Walken", "Paul Calderon", "Bronagh Gallagher", "Peter Greene", "Stephen Hibbert", "Angela Jones", "Phil LaMarr", "Robert Ruth", "Julia Sweeney", "Quentin Tarantino", "Frank Whaley", "Duane Whitaker", "Steve Buscemi", "Burr Steers"], "producer": "Miramax, Band Apart, Jersey Films. Lawrence Bender", - "genres": ["Thriller", "Crimen", "Historias cruzadas", "Película de culto", "Comedia negra"], + "genres": ["Thriller"], + "genreTopics": ["Crimen", "Historias cruzadas", "Película de culto", "Comedia negra"], "synopsis": "Jules y Vincent, dos asesinos a sueldo con no demasiadas luces, trabajan para el gángster Marsellus Wallace. Vincent le confiesa a Jules que Marsellus le ha pedido que cuide de Mia, su atractiva mujer. Jules le recomienda prudencia porque es muy peligroso sobrepasarse con la novia del jefe. Cuando llega la hora de trabajar, ambos deben ponerse \"manos a la obra\". Su misión: recuperar un misterioso maletín." } } From 944202019fa97229c209eb5c461a3c2c757ddfe2 Mon Sep 17 00:00:00 2001 From: parker Date: Thu, 13 Jun 2024 08:43:11 +0200 Subject: [PATCH 24/39] Code revision --- .../Mappers/CountryToCountryDto.php | 1 - .../Application/Mappers/GenreToGenreDto.php | 1 - .../SearchResultsToSearchResultsDto.php | 16 ++++++---- .../Services/GetAllCountriesService.php | 2 -- .../Services/GetAllGenresService.php | 2 -- .../Services/GetFilmByIdService.php | 2 -- .../Parsers/AdvancedSearchFormParser.php | 18 ++++------- .../Films/Domain/Parsers/FilmCastParser.php | 10 +++--- .../Domain/Parsers/FilmCountryParser.php | 31 +++++++++++++++++++ .../Domain/Parsers/FilmDirectorsParser.php | 10 +++--- .../Films/Domain/Parsers/FilmGenresParser.php | 29 ++++++++++------- .../Films/Domain/Parsers/FilmParser.php | 16 ---------- .../Films/Domain/Services/GetFilmService.php | 7 +++-- 13 files changed, 80 insertions(+), 65 deletions(-) create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCountryParser.php diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/CountryToCountryDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/CountryToCountryDto.php index ef68af5..b23f52a 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/CountryToCountryDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/CountryToCountryDto.php @@ -12,7 +12,6 @@ class CountryToCountryDto public function convert(Country $country): CountryDto { $countryDto = new CountryDto(); - $countryDto->code = $country->code(); $countryDto->name = $country->name(); diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/GenreToGenreDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/GenreToGenreDto.php index 91e1d8b..bc03378 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/GenreToGenreDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/GenreToGenreDto.php @@ -12,7 +12,6 @@ class GenreToGenreDto public function convert(Genre $genre): GenreDto { $genreDto = new GenreDto(); - $genreDto->code = $genre->code(); $genreDto->name = $genre->name(); diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchResultsToSearchResultsDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchResultsToSearchResultsDto.php index 47d3d24..b0cf291 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchResultsToSearchResultsDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchResultsToSearchResultsDto.php @@ -14,7 +14,6 @@ class SearchResultsToSearchResultsDto public function convert(SearchResults $searchResults): SearchResultsDto { $searchResultsDto = new SearchResultsDto(); - $searchResultsDto->total = $searchResults->total; $searchResultsDto->results = $this->convertSingleSearchResult($searchResults->results); @@ -31,13 +30,18 @@ private function convertSingleSearchResult(array $singleSearchResults): array $out = []; foreach ($singleSearchResults as $singleSearchResult) { - $singleSearchResultDto = new SingleSearchResultDto(); - $singleSearchResultDto->id = $singleSearchResult->id; - $singleSearchResultDto->title = $singleSearchResult->title; - - $out[] = $singleSearchResultDto; + $out[] = $this->getSingleSearchResultDto($singleSearchResult); } return $out; } + + private function getSingleSearchResultDto(SingleSearchResult $singleSearchResult): SingleSearchResultDto + { + $singleSearchResultDto = new SingleSearchResultDto(); + $singleSearchResultDto->id = $singleSearchResult->id; + $singleSearchResultDto->title = $singleSearchResult->title; + + return $singleSearchResultDto; + } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Services/GetAllCountriesService.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Services/GetAllCountriesService.php index 5471850..a692a96 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Services/GetAllCountriesService.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Services/GetAllCountriesService.php @@ -4,7 +4,6 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Application\Services; -use Psr\Log\LoggerInterface; use Xsga\FilmAffinityApi\Modules\Films\Application\Dto\CountryDto; use Xsga\FilmAffinityApi\Modules\Films\Application\Mappers\CountryToCountryDto; use Xsga\FilmAffinityApi\Modules\Films\Domain\Repositories\CountriesRepository; @@ -12,7 +11,6 @@ final class GetAllCountriesService { public function __construct( - private LoggerInterface $logger, private CountriesRepository $countriesRepository, private CountryToCountryDto $mapper ) { diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Services/GetAllGenresService.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Services/GetAllGenresService.php index 9720e48..67a5f0a 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Services/GetAllGenresService.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Services/GetAllGenresService.php @@ -4,7 +4,6 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Application\Services; -use Psr\Log\LoggerInterface; use Xsga\FilmAffinityApi\Modules\Films\Application\Dto\GenreDto; use Xsga\FilmAffinityApi\Modules\Films\Application\Mappers\GenreToGenreDto; use Xsga\FilmAffinityApi\Modules\Films\Domain\Repositories\GenresRepository; @@ -12,7 +11,6 @@ final class GetAllGenresService { public function __construct( - private LoggerInterface $logger, private GenresRepository $genresRepository, private GenreToGenreDto $mapper ) { diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Services/GetFilmByIdService.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Services/GetFilmByIdService.php index 002678b..5a3a01c 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Services/GetFilmByIdService.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Services/GetFilmByIdService.php @@ -7,12 +7,10 @@ use Xsga\FilmAffinityApi\Modules\Films\Application\Dto\FilmDto; use Xsga\FilmAffinityApi\Modules\Films\Application\Mappers\FilmToFilmDto; use Xsga\FilmAffinityApi\Modules\Films\Domain\Repositories\FilmsRepository; -use Xsga\FilmAffinityApi\Modules\Shared\HttpClient\Application\Services\HttpClientService; final class GetFilmByIdService { public function __construct( - private HttpClientService $httpClientService, private FilmsRepository $repository, private FilmToFilmDto $mapper ) { diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchFormParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchFormParser.php index 293336d..9913a44 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchFormParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchFormParser.php @@ -26,13 +26,10 @@ public function getGenres(): array continue; } - $genre = new Genre( - $element->getAttribute('value'), - trim($element->nodeValue) - ); - - $out[] = $genre; + $out[] = new Genre($element->getAttribute('value'), trim($element->nodeValue)); } + + $this->logger->info('FilmAffinity genres: ' . count($out) . ' results found'); return $out; } @@ -47,13 +44,10 @@ public function getCountries(): array $out = []; foreach ($xpathResults as $element) { - $country = new Country( - $element->getAttribute('value'), - trim($element->nodeValue) - ); - - $out[] = $country; + $out[] = new Country($element->getAttribute('value'), trim($element->nodeValue)); } + + $this->logger->info('FilmAffinity countries: ' . count($out) . ' results found'); return $out; } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCastParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCastParser.php index a84f3bf..7ec807e 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCastParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCastParser.php @@ -10,6 +10,8 @@ final class FilmCastParser extends AbstractParser { private const string QUERY_FILM_GET_ACTORS = "//li[@itemprop = 'actor']/a"; + + private string $urlPattern = 'name-id='; /** * @return Actor[] @@ -31,11 +33,9 @@ private function getActor(DOMElement $item): Actor { $url = trim($item->getAttribute('href')); - $actor = new Actor( - (int)substr($url, strpos($url, 'name-id=') + 8, -1), - trim($item->nodeValue) - ); + $actorId = (int)substr($url, strpos($url, $this->urlPattern) + strlen($this->urlPattern), -1); + $actorName = trim($item->nodeValue); - return $actor; + return new Actor($actorId, $actorName); } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCountryParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCountryParser.php new file mode 100644 index 0000000..992846f --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCountryParser.php @@ -0,0 +1,31 @@ +getData(self::QUERY_FILM_GET_COUNTRY, false); + + $countryCode = $this->getCountryCode($data->item(0)->attributes->getNamedItem('src')->nodeValue); + $countryName = $data->item(0)->attributes->getNamedItem('alt')->nodeValue; + + return new Country($countryCode, $countryName); + } + + private function getCountryCode(string $url): string + { + $urlArray = explode('/', $url); + $flagImg = end($urlArray); + $flagImgArray = explode('.', $flagImg); + + return $flagImgArray[0]; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmDirectorsParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmDirectorsParser.php index 0a86b25..81393db 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmDirectorsParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmDirectorsParser.php @@ -10,6 +10,8 @@ final class FilmDirectorsParser extends AbstractParser { private const string QUERY_FILM_GET_DIRECTORS = "//span[@itemprop = 'director']/a"; + + private string $urlPattern = 'name-id='; /** * @return Director[] @@ -31,11 +33,9 @@ private function getDirector(DOMElement $item): Director { $url = trim($item->getAttribute('href')); - $director = new Director( - (int)substr($url, strpos($url, 'name-id=') + 8, -1), - trim($item->nodeValue) - ); + $directorId = (int)substr($url, strpos($url, $this->urlPattern) + strlen($this->urlPattern), -1); + $directorName = trim($item->nodeValue); - return $director; + return new Director($directorId, $directorName); } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmGenresParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmGenresParser.php index e2f4236..4cf6448 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmGenresParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmGenresParser.php @@ -12,6 +12,9 @@ final class FilmGenresParser extends AbstractParser { private const string QUERY_FILM_GET_GENRES = "//span[@itemprop = 'genre']/a"; private const string QUERY_FILM_GET_GENRE_TOPICS = "//dd[@class = 'card-genres']/a"; + + private string $urlGenre = 'genre='; + private string $urlTopic = 'topic='; /** * @return Genre[] @@ -32,13 +35,15 @@ public function getGenres(): array private function getGenre(DOMNode $item): Genre { $url = trim($item->attributes?->getNamedItem('href')?->nodeValue); - - $genre = new Genre( - substr($url, strpos($url, 'genre=') + 6, strpos($url, '&') - strpos($url, 'genre=') - 6), - trim($item->nodeValue) + + $genreCode = substr( + $url, + strpos($url, $this->urlGenre) + strlen($this->urlGenre), + strpos($url, '&') - strpos($url, $this->urlGenre) - strlen($this->urlGenre) ); + $genreName = trim($item->nodeValue); - return $genre; + return new Genre($genreCode, $genreName); } /** @@ -60,12 +65,14 @@ public function getGenreTopics(): array private function getGenreTopic(DOMNode $item): GenreTopic { $url = trim($item->attributes?->getNamedItem('href')?->nodeValue); - - $genreTopic = new GenreTopic( - (int)substr($url, strpos($url, 'topic=') + 6, strpos($url, '&') - strpos($url, 'topic=') - 6), - trim($item->nodeValue) - ); - return $genreTopic; + $genreTopicId = (int)substr( + $url, + strpos($url, $this->urlTopic) + strlen($this->urlTopic), + strpos($url, '&') - strpos($url, $this->urlTopic) - strlen($this->urlTopic) + ); + $genreTopicName = trim($item->nodeValue); + + return new GenreTopic($genreTopicId, $genreTopicName); } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php index d5bb14a..f81fbeb 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php @@ -4,8 +4,6 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers; -use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Country; - final class FilmParser extends AbstractParser { private const string QUERY_FILM_GET_VARIOUS = "//dd[not(@class) and not(@itemprop)]/div"; @@ -13,7 +11,6 @@ final class FilmParser extends AbstractParser private const string QUERY_FILM_GET_ORIGINAL_TITLE = "//dd[not(@class) and not(@itemprop)]"; private const string QUERY_FILM_GET_RELEASE_DATE = "//dd[@itemprop = 'datePublished']"; private const string QUERY_FILM_GET_DURATION = "//dd[@itemprop = 'duration']"; - private const string QUERY_FILM_GET_COUNTRY = "//img[@class = 'nflag']"; private const string QUERY_FILM_GET_PRODUCERS = "//dd[@class = 'card-producer']//span"; private const string QUERY_FILM_GET_RATING = "//div[@id = 'movie-rat-avg']"; private const string QUERY_FILM_GET_SYNOPSIS = "//dd[@class = '' and @itemprop = 'description']"; @@ -101,19 +98,6 @@ public function getOriginalTitle(): string }; } - public function getCountry(): Country - { - $data = $this->getData(self::QUERY_FILM_GET_COUNTRY, false); - - $url = $data->item(0)->attributes->getNamedItem('src')->nodeValue; - $urlArray = explode('/', $url); - $flagImg = end($urlArray); - $flagImgArray = explode('.', $flagImg); - $countryCode = $flagImgArray[0]; - - return new Country($countryCode, $data->item(0)->attributes->getNamedItem('alt')->nodeValue); - } - public function getScreenplay(): string { $data = $this->getData(self::QUERY_FILM_GET_VARIOUS); diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetFilmService.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetFilmService.php index c2cafdc..717d69c 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetFilmService.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetFilmService.php @@ -6,6 +6,7 @@ use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Film; use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmCastParser; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmCountryParser; use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmCoverParser; use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmDirectorsParser; use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmGenresParser; @@ -18,7 +19,8 @@ public function __construct( private FilmCastParser $castParser, private FilmCoverParser $coverParser, private FilmDirectorsParser $directorsParser, - private FilmGenresParser $genresParser + private FilmGenresParser $genresParser, + private FilmCountryParser $countryParser ) { } @@ -29,6 +31,7 @@ public function get(int $filmId, string $pageContent): Film $this->coverParser->init($pageContent); $this->directorsParser->init($pageContent); $this->genresParser->init($pageContent); + $this->countryParser->init($pageContent); return $this->getFilm($filmId); } @@ -42,7 +45,7 @@ private function getFilm(int $filmId): Film $film->originalTitle = $this->filmParser->getOriginalTitle(); $film->year = $this->filmParser->getYear(); $film->duration = $this->filmParser->getDuration(); - $film->country = $this->filmParser->getCountry(); + $film->country = $this->countryParser->getCountry(); $film->directors = $this->directorsParser->getDirectors(); $film->screenplay = $this->filmParser->getScreenplay(); $film->soundtrack = $this->filmParser->getSoundtrack(); From 303bfae2d2cac888f9d46f9a8388065ee60ae1e4 Mon Sep 17 00:00:00 2001 From: parker <67624778+xsga@users.noreply.github.com> Date: Thu, 13 Jun 2024 15:11:27 +0000 Subject: [PATCH 25/39] Simple search parser refactor --- .../Application/Dto/SingleSearchResultDto.php | 2 + .../SearchResultsToSearchResultsDto.php | 21 +++- .../Films/Domain/Model/SingleSearchResult.php | 6 ++ .../Domain/Parsers/SimpleSearchParser.php | 101 +++++++++++------- .../GetSimpleSearchResultsService.php | 64 +++++++++++ .../FilmAffinitySearchRepository.php | 8 +- 6 files changed, 158 insertions(+), 44 deletions(-) create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetSimpleSearchResultsService.php diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Dto/SingleSearchResultDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Dto/SingleSearchResultDto.php index cb60a11..1c5e21c 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Dto/SingleSearchResultDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Dto/SingleSearchResultDto.php @@ -8,4 +8,6 @@ class SingleSearchResultDto { public int $id = 0; public string $title = ''; + public string $year = ''; + public array $directors; } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchResultsToSearchResultsDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchResultsToSearchResultsDto.php index b0cf291..3459bd8 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchResultsToSearchResultsDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchResultsToSearchResultsDto.php @@ -6,6 +6,7 @@ use Xsga\FilmAffinityApi\Modules\Films\Application\Dto\SearchResultsDto; use Xsga\FilmAffinityApi\Modules\Films\Application\Dto\SingleSearchResultDto; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Director; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\SearchResults; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\SingleSearchResult; @@ -39,9 +40,25 @@ private function convertSingleSearchResult(array $singleSearchResults): array private function getSingleSearchResultDto(SingleSearchResult $singleSearchResult): SingleSearchResultDto { $singleSearchResultDto = new SingleSearchResultDto(); - $singleSearchResultDto->id = $singleSearchResult->id; - $singleSearchResultDto->title = $singleSearchResult->title; + $singleSearchResultDto->id = $singleSearchResult->id; + $singleSearchResultDto->title = $singleSearchResult->title; + $singleSearchResultDto->year = $singleSearchResult->year; + $singleSearchResultDto->directors = $this->getDirectors($singleSearchResult->directors); return $singleSearchResultDto; } + + /** + * @param Director[] $directors + */ + private function getDirectors(array $directors): array + { + $out = []; + + foreach ($directors as $director) { + $out[] = $director->name(); + } + + return $out; + } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/SingleSearchResult.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/SingleSearchResult.php index 669de09..b6d824e 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/SingleSearchResult.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/SingleSearchResult.php @@ -8,4 +8,10 @@ class SingleSearchResult { public int $id = 0; public string $title = ''; + public string $year = ''; + + /** + * @return Director[] + */ + public array $directors; } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php index b9d0b36..d1182af 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php @@ -5,8 +5,10 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers; use DOMDocument; +use DOMElement; use DOMNodeList; use DOMXPath; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Director; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\SearchResults; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\SingleSearchResult; @@ -18,51 +20,47 @@ final class SimpleSearchParser extends AbstractParser private const string QUERY_MULTIPLE_RESULTS_GET_TITLE = "//div[@class = 'mc-title']/a"; private const string QUERY_MULTIPLE_RESULTS_GET_YEAR = "//div[contains(@class, 'ye-w')]"; private const string QUERY_MULTIPLE_RESULTS_GET_ID = "//div[contains(@class, 'movie-card')]"; + private const string QUERY_MULTIPLE_RESULTS_GET_DIRECTORS = "//div[contains(@class, 'mc-director')]//a"; - public function getSimpleSearchResults(): SearchResults + private string $urlPattern = 'name-id='; + + public function isSingleResult(): bool { $queyResults = $this->getData(self::QUERY_RESULTS_TYPE, false); - $searchResults = match ( - ($queyResults->length > 0) && - ($queyResults->item(0)?->attributes?->getNamedItem('content')?->nodeValue !== 'FilmAffinity') - ) { - true => $this->simpleSearchSingleResult($queyResults), - false => $this->simpleSearchMultipleResults() - }; - - $this->logger->info("FilmAffinity search: $searchResults->total results found"); + if (($queyResults->length > 0) && ($queyResults->item(0)?->attributes?->getNamedItem('content')?->nodeValue !== 'FilmAffinity')) { + return true; + } - return $searchResults; + return false; } - private function simpleSearchSingleResult(DOMNodeList $data): SearchResults + public function getSingleResultId(): int { $idSearch = $this->getData(self::QUERY_SINGLE_RESULT_GET_ID, false); + $idArray = explode('/', $idSearch->item(0)?->attributes?->getNamedItem('content')?->nodeValue); - $idArray = explode('/', $idSearch->item(0)?->attributes?->getNamedItem('content')?->nodeValue); - $title = $data->item(0)?->attributes?->getNamedItem('content')?->nodeValue; - - $searchResult = new SingleSearchResult(); - $searchResult->id = (int)trim(str_replace('film', '', str_replace('.html', '', end($idArray)))); - $searchResult->title = trim(str_replace(' ', ' ', str_replace(' ', ' ', $title))); + return (int)trim(str_replace('film', '', str_replace('.html', '', end($idArray)))); + } - $out = new SearchResults(); - $out->total = 1; - $out->results[] = $searchResult; + public function getMultiplesResultsTotal(): int + { + $searchResults = $this->getData(self::QUERY_MULTIPLE_RESULTS_DATA, false); - return $out; + return $searchResults->length; } - private function simpleSearchMultipleResults(): SearchResults + /** + * @return SingleSearchResult[] + */ + public function getMultiplesResults(): array { $searchResults = $this->getData(self::QUERY_MULTIPLE_RESULTS_DATA, false); - $out = new SearchResults(); - $out->total = $searchResults->length; + $out = []; - for ($i = 0; $i < $out->total; $i++) { - $out->results[] = $this->getSearchResult($searchResults, $i); + for ($i = 0; $i < $searchResults->length; $i++) { + $out[] = $this->getSearchResult($searchResults, $i); } return $out; @@ -75,34 +73,63 @@ private function getSearchResult(DOMNodeList $searchResults, int $element): Sing $domXpath = new DOMXPath($dom); - $searchResult = new SingleSearchResult(); - $searchResult->id = $this->getId($domXpath); - $searchResult->title = $this->getTitle($domXpath); + $searchResult = new SingleSearchResult(); + $searchResult->id = $this->getId($domXpath); + $searchResult->title = $this->getTitle($domXpath); + $searchResult->year = $this->getYear($domXpath); + $searchResult->directors = $this->getDirectors($domXpath); return $searchResult; } + private function getId(DOMXPath $domXpath): int + { + $idResult = $domXpath->query(self::QUERY_MULTIPLE_RESULTS_GET_ID); + + return (int)trim($idResult->item(0)?->attributes?->getNamedItem('data-movie-id')?->nodeValue); + } + private function getTitle(DOMXPath $domXpath): string { $titleResult = $domXpath->query(self::QUERY_MULTIPLE_RESULTS_GET_TITLE); - $title = $titleResult->item(0)->nodeValue; - $year = $this->getYear($domXpath); + $title = trim(str_replace(' ', ' ', str_replace(' ', ' ', $titleResult->item(0)->nodeValue))); - return trim(str_replace(' ', ' ', str_replace(' ', ' ', $title))) . ' (' . trim($year) . ')'; + return $title; } private function getYear(DOMXPath $domXpath): string { $yearResult = $domXpath->query(self::QUERY_MULTIPLE_RESULTS_GET_YEAR); - return $yearResult->item(0)->nodeValue ?? ''; + $year = $yearResult->item(0)->nodeValue ?? ''; + + return trim($year); } - private function getId(DOMXPath $domXpath): int + /** + * @return Director[] + */ + private function getDirectors(DOMXPath $domXpath): array { - $idResult = $domXpath->query(self::QUERY_MULTIPLE_RESULTS_GET_ID); + $directors = $domXpath->query(self::QUERY_MULTIPLE_RESULTS_GET_DIRECTORS); - return (int)trim($idResult->item(0)?->attributes?->getNamedItem('data-movie-id')?->nodeValue); + $out = []; + + foreach ($directors as $director) { + $out[] = $this->getDirector($director); + } + + return $out; + } + + private function getDirector(DOMElement $item): Director + { + $url = trim($item->getAttribute('href')); + + $directorId = (int)substr($url, strpos($url, $this->urlPattern) + strlen($this->urlPattern), -1); + $directorName = trim($item->nodeValue); + + return new Director($directorId, $directorName); } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetSimpleSearchResultsService.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetSimpleSearchResultsService.php new file mode 100644 index 0000000..779f8ba --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetSimpleSearchResultsService.php @@ -0,0 +1,64 @@ +simpleSearchParser->init($pageContent); + + $searchResults = match ($this->simpleSearchParser->isSingleResult()) { + true => $this->getSingleResult($pageContent), + false => $this->getMultiplesResults() + }; + + $this->logger->info("FilmAffinity search: $searchResults->total results found"); + + return $searchResults; + } + + private function getSingleResult(string $pageContent): SearchResults + { + $this->filmParser->init($pageContent); + $this->filmDirectorsParser->init($pageContent); + + $singleResult = new SingleSearchResult(); + $singleResult->id = $this->simpleSearchParser->getSingleResultId(); + $singleResult->title = $this->filmParser->getTitle(); + $singleResult->year = $this->filmParser->getYear(); + $singleResult->directors = $this->filmDirectorsParser->getDirectors(); + + $searchResults = new SearchResults(); + $searchResults->total = 1; + $searchResults->results = [$singleResult]; + + return $searchResults; + } + + private function getMultiplesResults(): SearchResults + { + $searchResults = new SearchResults(); + $searchResults->total = $this->simpleSearchParser->getMultiplesResultsTotal(); + $searchResults->results = $this->simpleSearchParser->getMultiplesResults(); + + return $searchResults; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinitySearchRepository.php b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinitySearchRepository.php index 170447e..2f8cc41 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinitySearchRepository.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Repositories/FilmAffinitySearchRepository.php @@ -6,8 +6,8 @@ use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Search; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\SearchResults; -use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\SimpleSearchParser; use Xsga\FilmAffinityApi\Modules\Films\Domain\Repositories\SearchRepository; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Services\GetSimpleSearchResultsService; use Xsga\FilmAffinityApi\Modules\Films\Domain\Services\UrlService; use Xsga\FilmAffinityApi\Modules\Shared\HttpClient\Application\Services\HttpClientService; @@ -16,7 +16,7 @@ final class FilmAffinitySearchRepository implements SearchRepository public function __construct( private UrlService $urlService, private HttpClientService $httpClientService, - private SimpleSearchParser $parser + private GetSimpleSearchResultsService $getResultsService ) { } @@ -25,8 +25,6 @@ public function get(Search $search): SearchResults $searchUrl = $this->urlService->getSearchUrl($search); $pageContent = $this->httpClientService->getPageContent($searchUrl); - $this->parser->init($pageContent); - - return $this->parser->getSimpleSearchResults(); + return $this->getResultsService->get($pageContent); } } From e8df2466cb954a728b5b66d2507b324e48808683 Mon Sep 17 00:00:00 2001 From: parker Date: Thu, 13 Jun 2024 17:26:57 +0200 Subject: [PATCH 26/39] Fix error --- config/container/Container.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/container/Container.php b/config/container/Container.php index cf9e1b1..60d748b 100644 --- a/config/container/Container.php +++ b/config/container/Container.php @@ -25,6 +25,7 @@ use Xsga\FilmAffinityApi\Modules\Films\Domain\Repositories\GenresRepository; use Xsga\FilmAffinityApi\Modules\Films\Domain\Repositories\SearchRepository; use Xsga\FilmAffinityApi\Modules\Films\Domain\Services\GetFilmService; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Services\GetSimpleSearchResultsService; use Xsga\FilmAffinityApi\Modules\Films\Domain\Services\UrlService; use Xsga\FilmAffinityApi\Modules\Films\Infrastructure\Repositories\FilmAffinityAdvancedSearchRepository; use Xsga\FilmAffinityApi\Modules\Films\Infrastructure\Repositories\FilmAffinityCountriesRepository; @@ -222,7 +223,7 @@ SearchRepository::class => DI\create(FilmAffinitySearchRepository::class)->constructor( DI\get(UrlService::class), DI\get(HttpClientService::class), - DI\get(SimpleSearchParser::class) + DI\get(GetSimpleSearchResultsService::class) ), // -------------------------------------------------------------------------------------------- From 0530ed60c10a5bca3a58b11b7ba7b4cad876940e Mon Sep 17 00:00:00 2001 From: parker Date: Thu, 13 Jun 2024 17:47:40 +0200 Subject: [PATCH 27/39] Search parsers refactor --- .../schemas/output/search_results.schema.json | 25 ++++++++- .../Domain/Parsers/AdvancedSearchParser.php | 56 +++++++++++++++---- .../Domain/Parsers/SimpleSearchParser.php | 1 - 3 files changed, 68 insertions(+), 14 deletions(-) diff --git a/config/schemas/output/search_results.schema.json b/config/schemas/output/search_results.schema.json index 349ea60..d5c8acd 100644 --- a/config/schemas/output/search_results.schema.json +++ b/config/schemas/output/search_results.schema.json @@ -27,7 +27,9 @@ "title": "Single search result", "required": [ "id", - "title" + "title", + "year", + "directors" ], "properties": { "id": { @@ -39,6 +41,27 @@ "$id": "#/properties/results/items/anyOf/0/properties/title", "type": "string", "title": "The film title" + }, + "year": { + "$id": "#/properties/results/items/anyOf/0/properties/year", + "type": "string", + "title": "The film release year" + }, + "directors": { + "$id": "#/properties/results/items/anyOf/0/properties/directors", + "type": "array", + "title": "Film directors array", + "additionalItems": false, + "items": { + "$id": "/properties/results/items/anyOf/0/properties/directors/items", + "anyOf": [ + { + "$id": "/properties/results/items/anyOf/0/properties/directors/items/anyOf/0", + "type": "string", + "title": "Director name" + } + ] + } } }, "additionalProperties": false diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php index eb23ef6..f7dd49e 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php @@ -5,8 +5,10 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers; use DOMDocument; +use DOMElement; use DOMNodeList; use DOMXPath; +use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Director; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\SearchResults; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\SingleSearchResult; @@ -16,6 +18,9 @@ final class AdvancedSearchParser extends AbstractParser private const string QUERY_ADV_SEARCH_GET_TITLE = "//div[@class = 'mc-title']/a"; private const string QUERY_ADV_SEARCH_GET_ID = "//div[contains(@class, 'movie-card')]"; private const string QUERY_ADV_SEARCH_GET_YEAR = "//span[contains(@class, 'mc-year')]"; + private const string QUERY_ADV_SEARCH_GET_DIRECTORS = "//div[contains(@class, 'mc-director')]//a"; + + private string $urlPattern = 'name-id='; public function getAdvSearchResults(): SearchResults { @@ -42,34 +47,61 @@ private function getResultData(DOMNodeList $node, int $itemNumber): SingleSearch $domXpath = new DOMXPath($dom); $searchResult = new SingleSearchResult(); - $searchResult->id = $this->getFilmId($domXpath); - $searchResult->title = $this->getFilmTitle($domXpath); + $searchResult->id = $this->getFilmId($domXpath); + $searchResult->title = $this->getFilmTitle($domXpath); + $searchResult->year = $this->getFilmYear($domXpath); + $searchResult->directors = $this->getFilmDirectors($domXpath); return $searchResult; } + private function getFilmId(DOMXPath $domXpath): int + { + $idResult = $domXpath->query(self::QUERY_ADV_SEARCH_GET_ID); + $id = $idResult->item(0)->attributes->getNamedItem('data-movie-id')->nodeValue; + + return (int)trim($id); + } + private function getFilmTitle(DOMXPath $domXpath): string { $titleResult = $domXpath->query(self::QUERY_ADV_SEARCH_GET_TITLE); + $title = trim(str_replace(' ', ' ', trim(str_replace(' ', ' ', $titleResult->item(0)->nodeValue)))); - $title = $titleResult->item(0)->nodeValue; - $year = $this->getFilmYear($domXpath); + return $title; + } - return trim(str_replace(' ', ' ', trim(str_replace(' ', ' ', $title))) . ' (' . $year . ')'); + private function getFilmYear(DOMXPath $domXpath): string + { + $yearResult = $domXpath->query(self::QUERY_ADV_SEARCH_GET_YEAR); + $year = $yearResult->item(1)->nodeValue ?? ''; + + return trim($year); } - private function getFilmId(DOMXPath $domXpath): int + /** + * @return Director[] + */ + private function getFilmDirectors(DOMXPath $domXpath): array { - $idResult = $domXpath->query(self::QUERY_ADV_SEARCH_GET_ID); - $id = $idResult->item(0)->attributes->getNamedItem('data-movie-id')->nodeValue; + $directorsResult = $domXpath->query(self::QUERY_ADV_SEARCH_GET_DIRECTORS); + + $out = []; - return (int)trim($id); + foreach ($directorsResult as $director) { + $out[] = $this->getDirector($director); + } + + return $out; } - private function getFilmYear(DOMXPath $domXpath): string + private function getDirector(DOMElement $item): Director { - $yearResult = $domXpath->query(self::QUERY_ADV_SEARCH_GET_YEAR); + $url = trim($item->getAttribute('href')); + + $directorId = (int)substr($url, strpos($url, $this->urlPattern) + strlen($this->urlPattern), -1); + $directorName = trim($item->nodeValue); - return $yearResult->item(1)->nodeValue ?? ''; + return new Director($directorId, $directorName); } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php index d1182af..c7d3cbc 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php @@ -9,7 +9,6 @@ use DOMNodeList; use DOMXPath; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\Director; -use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\SearchResults; use Xsga\FilmAffinityApi\Modules\Films\Domain\Model\SingleSearchResult; final class SimpleSearchParser extends AbstractParser From 66a5b5e5e1e946c173a1ee2788dd6b077f309f1a Mon Sep 17 00:00:00 2001 From: parker Date: Thu, 13 Jun 2024 17:50:27 +0200 Subject: [PATCH 28/39] Fix style --- src/Xsga/FilmAffinityApi/Bootstrap/Bootstrap.php | 2 +- .../Films/Application/Mappers/CountryToCountryDto.php | 2 +- .../Modules/Films/Application/Mappers/FilmToFilmDto.php | 8 ++++---- .../Modules/Films/Application/Mappers/GenreToGenreDto.php | 2 +- .../Mappers/SearchResultsToSearchResultsDto.php | 2 +- .../FilmAffinityApi/Modules/Films/Domain/Model/Film.php | 2 +- .../Modules/Films/Domain/Model/SingleSearchResult.php | 2 +- .../Films/Domain/Parsers/AdvancedSearchFormParser.php | 4 ++-- .../Modules/Films/Domain/Parsers/AdvancedSearchParser.php | 4 ++-- .../Modules/Films/Domain/Parsers/FilmCastParser.php | 2 +- .../Modules/Films/Domain/Parsers/FilmCoverParser.php | 4 ++-- .../Modules/Films/Domain/Parsers/FilmDirectorsParser.php | 2 +- .../Modules/Films/Domain/Parsers/FilmGenresParser.php | 6 +++--- .../Modules/Films/Domain/Parsers/FilmParser.php | 2 +- .../Modules/Films/Domain/Services/GetFilmService.php | 2 +- .../Infrastructure/Controllers/GetFilmByIdController.php | 2 +- .../Users/Infrastructure/Console/DeleteUserCommand.php | 2 +- .../Users/Infrastructure/Console/DisableUserCommand.php | 2 +- .../Users/Infrastructure/Console/EnableUserCommand.php | 2 +- 19 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/Xsga/FilmAffinityApi/Bootstrap/Bootstrap.php b/src/Xsga/FilmAffinityApi/Bootstrap/Bootstrap.php index fd11eb0..55b3fd3 100644 --- a/src/Xsga/FilmAffinityApi/Bootstrap/Bootstrap.php +++ b/src/Xsga/FilmAffinityApi/Bootstrap/Bootstrap.php @@ -7,4 +7,4 @@ function bootstrap(): void $_ENV['APP_ROOT'] = realpath(dirname(__FILE__, 5)) . DIRECTORY_SEPARATOR; loadEnvironmentSettings(); -} \ No newline at end of file +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/CountryToCountryDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/CountryToCountryDto.php index b23f52a..889637e 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/CountryToCountryDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/CountryToCountryDto.php @@ -20,7 +20,7 @@ public function convert(Country $country): CountryDto /** * @param Country[] $countries - * + * * @return CountryDto[] */ public function convertArray(array $countries): array diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php index fcfff21..6c193e0 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php @@ -42,7 +42,7 @@ public function convert(Film $film): FilmDto /** * @param Director[] $directors */ - private function getDirectors(array $directors) : array + private function getDirectors(array $directors): array { $out = []; @@ -56,7 +56,7 @@ private function getDirectors(array $directors) : array /** * @param Actor[] $actors */ - private function getActors(array $actors) : array + private function getActors(array $actors): array { $out = []; @@ -70,7 +70,7 @@ private function getActors(array $actors) : array /** * @param Genre[] $genres */ - private function getGenres(array $genres) : array + private function getGenres(array $genres): array { $out = []; @@ -84,7 +84,7 @@ private function getGenres(array $genres) : array /** * @param GenreTopic[] $genreTopics */ - private function getGenreTopics(array $genreTopics) : array + private function getGenreTopics(array $genreTopics): array { $out = []; diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/GenreToGenreDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/GenreToGenreDto.php index bc03378..641202a 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/GenreToGenreDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/GenreToGenreDto.php @@ -20,7 +20,7 @@ public function convert(Genre $genre): GenreDto /** * @param Genre[] $genres - * + * * @return GenreDto[] */ public function convertArray(array $genres): array diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchResultsToSearchResultsDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchResultsToSearchResultsDto.php index 3459bd8..dcea159 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchResultsToSearchResultsDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchResultsToSearchResultsDto.php @@ -23,7 +23,7 @@ public function convert(SearchResults $searchResults): SearchResultsDto /** * @param SingleSearchResult[] $singleSearchResults - * + * * @return SingleSearchResultDto[] */ private function convertSingleSearchResult(array $singleSearchResults): array diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php index de8554f..3b388fc 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php @@ -25,7 +25,7 @@ class Film * @var Actor[] */ public array $cast = []; - + /** * @var Director[] */ diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/SingleSearchResult.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/SingleSearchResult.php index b6d824e..be3b1c5 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/SingleSearchResult.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/SingleSearchResult.php @@ -9,7 +9,7 @@ class SingleSearchResult public int $id = 0; public string $title = ''; public string $year = ''; - + /** * @return Director[] */ diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchFormParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchFormParser.php index 9913a44..1a3aa4c 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchFormParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchFormParser.php @@ -30,7 +30,7 @@ public function getGenres(): array } $this->logger->info('FilmAffinity genres: ' . count($out) . ' results found'); - + return $out; } @@ -48,7 +48,7 @@ public function getCountries(): array } $this->logger->info('FilmAffinity countries: ' . count($out) . ' results found'); - + return $out; } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php index f7dd49e..9aba59e 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php @@ -67,7 +67,7 @@ private function getFilmTitle(DOMXPath $domXpath): string { $titleResult = $domXpath->query(self::QUERY_ADV_SEARCH_GET_TITLE); $title = trim(str_replace(' ', ' ', trim(str_replace(' ', ' ', $titleResult->item(0)->nodeValue)))); - + return $title; } @@ -85,7 +85,7 @@ private function getFilmYear(DOMXPath $domXpath): string private function getFilmDirectors(DOMXPath $domXpath): array { $directorsResult = $domXpath->query(self::QUERY_ADV_SEARCH_GET_DIRECTORS); - + $out = []; foreach ($directorsResult as $director) { diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCastParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCastParser.php index 7ec807e..6a73d49 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCastParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCastParser.php @@ -12,7 +12,7 @@ final class FilmCastParser extends AbstractParser private const string QUERY_FILM_GET_ACTORS = "//li[@itemprop = 'actor']/a"; private string $urlPattern = 'name-id='; - + /** * @return Actor[] */ diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCoverParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCoverParser.php index 59f2b3b..5e31ee8 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCoverParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmCoverParser.php @@ -9,7 +9,7 @@ final class FilmCoverParser extends AbstractParser { private const string QUERY_FILM_GET_COVER = "//a[@class = 'lightbox']"; - + public function getCover(): Cover { return new Cover($this->getCoverUrl(), $this->getCoverFileName()); @@ -23,7 +23,7 @@ private function getCoverUrl(): string $this->logger->warning('Film cover URL not found'); return ''; } - + return trim($data->item(0)?->attributes?->getNamedItem('href')?->nodeValue); } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmDirectorsParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmDirectorsParser.php index 81393db..cdf1b04 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmDirectorsParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmDirectorsParser.php @@ -12,7 +12,7 @@ final class FilmDirectorsParser extends AbstractParser private const string QUERY_FILM_GET_DIRECTORS = "//span[@itemprop = 'director']/a"; private string $urlPattern = 'name-id='; - + /** * @return Director[] */ diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmGenresParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmGenresParser.php index 4cf6448..c549ba5 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmGenresParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmGenresParser.php @@ -15,7 +15,7 @@ final class FilmGenresParser extends AbstractParser private string $urlGenre = 'genre='; private string $urlTopic = 'topic='; - + /** * @return Genre[] */ @@ -35,7 +35,7 @@ public function getGenres(): array private function getGenre(DOMNode $item): Genre { $url = trim($item->attributes?->getNamedItem('href')?->nodeValue); - + $genreCode = substr( $url, strpos($url, $this->urlGenre) + strlen($this->urlGenre), @@ -65,7 +65,7 @@ public function getGenreTopics(): array private function getGenreTopic(DOMNode $item): GenreTopic { $url = trim($item->attributes?->getNamedItem('href')?->nodeValue); - + $genreTopicId = (int)substr( $url, strpos($url, $this->urlTopic) + strlen($this->urlTopic), diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php index f81fbeb..5576686 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php @@ -14,7 +14,7 @@ final class FilmParser extends AbstractParser private const string QUERY_FILM_GET_PRODUCERS = "//dd[@class = 'card-producer']//span"; private const string QUERY_FILM_GET_RATING = "//div[@id = 'movie-rat-avg']"; private const string QUERY_FILM_GET_SYNOPSIS = "//dd[@class = '' and @itemprop = 'description']"; - + private function validateOneResult(array $results, string $element): bool { $resultsCount = count($results); diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetFilmService.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetFilmService.php index 717d69c..8a21bfd 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetFilmService.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetFilmService.php @@ -59,5 +59,5 @@ private function getFilm(int $filmId): Film $film->cover = $this->coverParser->getCover(); return $film; - } + } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Controllers/GetFilmByIdController.php b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Controllers/GetFilmByIdController.php index e730cc0..0864e32 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Controllers/GetFilmByIdController.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Infrastructure/Controllers/GetFilmByIdController.php @@ -18,7 +18,7 @@ public function __construct(private GetFilmByIdService $getFilmByIdService) public function __invoke(Request $request, Response $response, array $args): Response { $filmId = (int)$args['id']; - + return $this->writeResponse($response, $this->getFilmByIdService->get($filmId)); } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/DeleteUserCommand.php b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/DeleteUserCommand.php index 4904587..90c375f 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/DeleteUserCommand.php +++ b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/DeleteUserCommand.php @@ -67,7 +67,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } $this->deleteUserByEmailService->delete($this->userEmail); - + $this->display->success("User $this->userEmail deleted successfully"); return Command::SUCCESS; diff --git a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/DisableUserCommand.php b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/DisableUserCommand.php index 2d2f4c1..d586631 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/DisableUserCommand.php +++ b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/DisableUserCommand.php @@ -59,7 +59,7 @@ function (?string $email) { protected function execute(InputInterface $input, OutputInterface $output): int { $this->userStatusService->set($this->userEmail, false); - + $this->display->success("User $this->userEmail disabled successfully"); return Command::SUCCESS; diff --git a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/EnableUserCommand.php b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/EnableUserCommand.php index 2473091..20a5478 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/EnableUserCommand.php +++ b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/EnableUserCommand.php @@ -59,7 +59,7 @@ function (?string $email) { protected function execute(InputInterface $input, OutputInterface $output): int { $this->userStatusService->set($this->userEmail, true); - + $this->display->success("User $this->userEmail enabled successfully"); return Command::SUCCESS; From f680fb06f49b485292abbf4ed116fd1de6dbe9ff Mon Sep 17 00:00:00 2001 From: parker Date: Thu, 13 Jun 2024 19:07:55 +0200 Subject: [PATCH 29/39] Object models and value objects --- .../Application/Mappers/FilmToFilmDto.php | 8 ++-- .../SearchResultsToSearchResultsDto.php | 8 ++-- .../Modules/Films/Domain/Model/Film.php | 12 +++-- .../Films/Domain/Model/SingleSearchResult.php | 46 +++++++++++++++++-- .../Domain/Parsers/AdvancedSearchParser.php | 13 +++--- .../Domain/Parsers/SimpleSearchParser.php | 13 +++--- .../Films/Domain/Services/GetFilmService.php | 11 +++-- .../GetSimpleSearchResultsService.php | 11 +++-- .../Films/Domain/ValueObjects/FilmId.php | 20 ++++++++ .../Films/Domain/ValueObjects/FilmTitle.php | 20 ++++++++ .../Films/Domain/ValueObjects/FilmYear.php | 20 ++++++++ 11 files changed, 143 insertions(+), 39 deletions(-) create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmId.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmTitle.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmYear.php diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php index 6c193e0..284cea5 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php @@ -17,10 +17,10 @@ public function convert(Film $film): FilmDto { $filmDto = new FilmDto(); - $filmDto->filmAfinityId = $film->filmAfinityId; - $filmDto->title = $film->title; - $filmDto->originalTitle = $film->originalTitle; - $filmDto->year = $film->year; + $filmDto->filmAfinityId = $film->filmAfinityId->value(); + $filmDto->title = $film->title->value(); + $filmDto->originalTitle = $film->originalTitle->value(); + $filmDto->year = $film->year->value(); $filmDto->duration = $film->duration; $filmDto->coverUrl = $film->cover->url(); $filmDto->coverFile = $film->cover->fileName(); diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchResultsToSearchResultsDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchResultsToSearchResultsDto.php index dcea159..a40f15b 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchResultsToSearchResultsDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchResultsToSearchResultsDto.php @@ -40,10 +40,10 @@ private function convertSingleSearchResult(array $singleSearchResults): array private function getSingleSearchResultDto(SingleSearchResult $singleSearchResult): SingleSearchResultDto { $singleSearchResultDto = new SingleSearchResultDto(); - $singleSearchResultDto->id = $singleSearchResult->id; - $singleSearchResultDto->title = $singleSearchResult->title; - $singleSearchResultDto->year = $singleSearchResult->year; - $singleSearchResultDto->directors = $this->getDirectors($singleSearchResult->directors); + $singleSearchResultDto->id = $singleSearchResult->id(); + $singleSearchResultDto->title = $singleSearchResult->title(); + $singleSearchResultDto->year = $singleSearchResult->year(); + $singleSearchResultDto->directors = $this->getDirectors($singleSearchResult->directors()); return $singleSearchResultDto; } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php index 3b388fc..28c333a 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php @@ -4,12 +4,16 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Domain\Model; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmId; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmTitle; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmYear; + class Film { - public int $filmAfinityId = 0; - public string $title = ''; - public string $originalTitle = ''; - public string $year = ''; + public FilmId $filmAfinityId; + public FilmTitle $title; + public FilmTitle $originalTitle = ''; + public FilmYear $year; public string $duration = ''; public string $rating = ''; public Country $country; diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/SingleSearchResult.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/SingleSearchResult.php index be3b1c5..946d2d4 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/SingleSearchResult.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/SingleSearchResult.php @@ -4,14 +4,52 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Domain\Model; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmId; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmTitle; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmYear; + class SingleSearchResult { - public int $id = 0; - public string $title = ''; - public string $year = ''; + private FilmId $id; + private FilmTitle $title; + private FilmYear $year; + + /** + * @var Director[] + */ + private array $directors; + + /** + * @param Director[] $directors + */ + public function __construct(int $id, string $title, string $year, array $directors) + { + $this->id = new FilmId($id); + $this->title = new FilmTitle($title); + $this->year = new FilmYear($year); + $this->directors = $directors; + } + + public function id(): int + { + return $this->id->value(); + } + + public function title(): string + { + return $this->title->value(); + } + + public function year(): string + { + return $this->year->value(); + } /** * @return Director[] */ - public array $directors; + public function directors(): array + { + return $this->directors; + } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php index 9aba59e..89e6afd 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php @@ -46,13 +46,12 @@ private function getResultData(DOMNodeList $node, int $itemNumber): SingleSearch $dom->appendChild($dom->importNode($node->item($itemNumber), true)); $domXpath = new DOMXPath($dom); - $searchResult = new SingleSearchResult(); - $searchResult->id = $this->getFilmId($domXpath); - $searchResult->title = $this->getFilmTitle($domXpath); - $searchResult->year = $this->getFilmYear($domXpath); - $searchResult->directors = $this->getFilmDirectors($domXpath); - - return $searchResult; + return new SingleSearchResult( + $this->getFilmId($domXpath), + $this->getFilmTitle($domXpath), + $this->getFilmYear($domXpath), + $this->getFilmDirectors($domXpath) + ); } private function getFilmId(DOMXPath $domXpath): int diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php index c7d3cbc..9eb6577 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php @@ -72,13 +72,12 @@ private function getSearchResult(DOMNodeList $searchResults, int $element): Sing $domXpath = new DOMXPath($dom); - $searchResult = new SingleSearchResult(); - $searchResult->id = $this->getId($domXpath); - $searchResult->title = $this->getTitle($domXpath); - $searchResult->year = $this->getYear($domXpath); - $searchResult->directors = $this->getDirectors($domXpath); - - return $searchResult; + return new SingleSearchResult( + $this->getId($domXpath), + $this->getTitle($domXpath), + $this->getYear($domXpath), + $this->getDirectors($domXpath) + ); } private function getId(DOMXPath $domXpath): int diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetFilmService.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetFilmService.php index 8a21bfd..80ce18e 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetFilmService.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetFilmService.php @@ -11,6 +11,9 @@ use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmDirectorsParser; use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmGenresParser; use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmParser; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmId; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmTitle; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmYear; final class GetFilmService { @@ -40,10 +43,10 @@ private function getFilm(int $filmId): Film { $film = new Film(); - $film->filmAfinityId = $filmId; - $film->title = $this->filmParser->getTitle(); - $film->originalTitle = $this->filmParser->getOriginalTitle(); - $film->year = $this->filmParser->getYear(); + $film->filmAfinityId = new FilmId($filmId); + $film->title = new FilmTitle($this->filmParser->getTitle()); + $film->originalTitle = new FilmTitle($this->filmParser->getOriginalTitle()); + $film->year = new FilmYear($this->filmParser->getYear()); $film->duration = $this->filmParser->getDuration(); $film->country = $this->countryParser->getCountry(); $film->directors = $this->directorsParser->getDirectors(); diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetSimpleSearchResultsService.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetSimpleSearchResultsService.php index 779f8ba..a0a16d2 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetSimpleSearchResultsService.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetSimpleSearchResultsService.php @@ -40,11 +40,12 @@ private function getSingleResult(string $pageContent): SearchResults $this->filmParser->init($pageContent); $this->filmDirectorsParser->init($pageContent); - $singleResult = new SingleSearchResult(); - $singleResult->id = $this->simpleSearchParser->getSingleResultId(); - $singleResult->title = $this->filmParser->getTitle(); - $singleResult->year = $this->filmParser->getYear(); - $singleResult->directors = $this->filmDirectorsParser->getDirectors(); + $singleResult = new SingleSearchResult( + $this->simpleSearchParser->getSingleResultId(), + $this->filmParser->getTitle(), + $this->filmParser->getYear(), + $this->filmDirectorsParser->getDirectors() + ); $searchResults = new SearchResults(); $searchResults->total = 1; diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmId.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmId.php new file mode 100644 index 0000000..a723558 --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmId.php @@ -0,0 +1,20 @@ +value = $id; + } + + public function value(): int + { + return $this->value; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmTitle.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmTitle.php new file mode 100644 index 0000000..6259c8b --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmTitle.php @@ -0,0 +1,20 @@ +value = $title; + } + + public function value(): string + { + return $this->value; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmYear.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmYear.php new file mode 100644 index 0000000..a08bef5 --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmYear.php @@ -0,0 +1,20 @@ +value = $year; + } + + public function value(): string + { + return $this->value; + } +} From c1b74dfbfd3aa983c16d712848bf5dd501331f00 Mon Sep 17 00:00:00 2001 From: parker Date: Thu, 13 Jun 2024 23:39:25 +0200 Subject: [PATCH 30/39] Domain objects --- config/schemas/output/film.schema.json | 2 +- .../schemas/output/search_results.schema.json | 2 +- .../Modules/Films/Application/Dto/FilmDto.php | 4 +- .../Application/Dto/SingleSearchResultDto.php | 2 +- .../Mappers/AdvSearchDtoToAdvSearch.php | 30 ++- .../Application/Mappers/FilmToFilmDto.php | 36 ++-- .../Application/Mappers/SearchDtoToSearch.php | 6 +- .../SearchResultsToSearchResultsDto.php | 4 +- .../Films/Domain/Model/AdvancedSearch.php | 118 +++++++++-- .../Modules/Films/Domain/Model/Film.php | 185 ++++++++++++++++-- .../Modules/Films/Domain/Model/Search.php | 14 +- .../Films/Domain/Model/SearchResults.php | 28 ++- .../Films/Domain/Model/SingleSearchResult.php | 4 +- .../Domain/Parsers/AdvancedSearchParser.php | 21 +- .../Films/Domain/Parsers/FilmParser.php | 12 +- .../Domain/Parsers/SimpleSearchParser.php | 4 +- .../Films/Domain/Services/GetFilmService.php | 43 ++-- .../GetSimpleSearchResultsService.php | 17 +- .../Films/Domain/Services/UrlService.php | 26 +-- .../Domain/ValueObjects/FilmDuration.php | 20 ++ .../Domain/ValueObjects/FilmPhotography.php | 20 ++ .../Domain/ValueObjects/FilmProducer.php | 20 ++ .../Films/Domain/ValueObjects/FilmRating.php | 20 ++ .../Domain/ValueObjects/FilmScreenplay.php | 20 ++ .../Domain/ValueObjects/FilmSoundtrack.php | 20 ++ .../Domain/ValueObjects/FilmSynopsis.php | 20 ++ .../Films/Domain/ValueObjects/FilmYear.php | 6 +- .../Domain/ValueObjects/ResultsCount.php | 20 ++ .../Films/Domain/ValueObjects/SearchText.php | 20 ++ .../Films/Domain/ValueObjects/SearchType.php | 20 ++ 30 files changed, 615 insertions(+), 149 deletions(-) create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmDuration.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmPhotography.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmProducer.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmRating.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmScreenplay.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmSoundtrack.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmSynopsis.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/ResultsCount.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/SearchText.php create mode 100644 src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/SearchType.php diff --git a/config/schemas/output/film.schema.json b/config/schemas/output/film.schema.json index ead5436..417b8fa 100644 --- a/config/schemas/output/film.schema.json +++ b/config/schemas/output/film.schema.json @@ -40,7 +40,7 @@ }, "year": { "$id": "#/properties/year", - "type": "string", + "type": "integer", "title": "Film release year" }, "duration": { diff --git a/config/schemas/output/search_results.schema.json b/config/schemas/output/search_results.schema.json index d5c8acd..43334c2 100644 --- a/config/schemas/output/search_results.schema.json +++ b/config/schemas/output/search_results.schema.json @@ -44,7 +44,7 @@ }, "year": { "$id": "#/properties/results/items/anyOf/0/properties/year", - "type": "string", + "type": "integer", "title": "The film release year" }, "directors": { diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Dto/FilmDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Dto/FilmDto.php index ebcb7a1..e805be0 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Dto/FilmDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Dto/FilmDto.php @@ -9,8 +9,8 @@ class FilmDto public int $filmAfinityId = 0; public string $title = ''; public string $originalTitle = ''; - public string $year = ''; - public string $duration = ''; + public int $year = 0; + public int $duration = 0; public string $coverUrl = ''; public string $coverFile = ''; public string $rating = ''; diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Dto/SingleSearchResultDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Dto/SingleSearchResultDto.php index 1c5e21c..0fb14fa 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Dto/SingleSearchResultDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Dto/SingleSearchResultDto.php @@ -8,6 +8,6 @@ class SingleSearchResultDto { public int $id = 0; public string $title = ''; - public string $year = ''; + public int $year = 0; public array $directors; } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/AdvSearchDtoToAdvSearch.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/AdvSearchDtoToAdvSearch.php index 8a4e951..b38bbac 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/AdvSearchDtoToAdvSearch.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/AdvSearchDtoToAdvSearch.php @@ -11,21 +11,19 @@ class AdvSearchDtoToAdvSearch { public function convert(AdvancedSearchDto $advSearchDto): AdvancedSearch { - $advSearch = new AdvancedSearch(); - - $advSearch->searchText = $advSearchDto->searchText; - $advSearch->searchTypeTitle = $advSearchDto->searchTypeTitle; - $advSearch->searchTypeDirector = $advSearchDto->searchTypeDirector; - $advSearch->searchTypeCast = $advSearchDto->searchTypeCast; - $advSearch->searchTypeScreenplay = $advSearchDto->searchTypeScreenplay; - $advSearch->searchTypePhotography = $advSearchDto->searchTypePhotography; - $advSearch->searchTypeSoundtrack = $advSearchDto->searchTypeSoundtrack; - $advSearch->searchTypeProducer = $advSearchDto->searchTypeProducer; - $advSearch->searchCountry = $advSearchDto->searchCountry; - $advSearch->searchGenre = $advSearchDto->searchGenre; - $advSearch->searchYearFrom = $advSearchDto->searchYearFrom; - $advSearch->searchYearTo = $advSearchDto->searchYearTo; - - return $advSearch; + return new AdvancedSearch( + $advSearchDto->searchText, + $advSearchDto->searchTypeTitle, + $advSearchDto->searchTypeDirector, + $advSearchDto->searchTypeCast, + $advSearchDto->searchTypeScreenplay, + $advSearchDto->searchTypePhotography, + $advSearchDto->searchTypeSoundtrack, + $advSearchDto->searchTypeProducer, + $advSearchDto->searchCountry === '' ? null : $advSearchDto->searchCountry, + $advSearchDto->searchGenre === '' ? null : $advSearchDto->searchGenre, + $advSearchDto->searchYearFrom === 0 ? null : $advSearchDto->searchYearFrom, + $advSearchDto->searchYearTo === 0 ? null : $advSearchDto->searchYearTo + ); } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php index 284cea5..8dd1835 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/FilmToFilmDto.php @@ -17,24 +17,24 @@ public function convert(Film $film): FilmDto { $filmDto = new FilmDto(); - $filmDto->filmAfinityId = $film->filmAfinityId->value(); - $filmDto->title = $film->title->value(); - $filmDto->originalTitle = $film->originalTitle->value(); - $filmDto->year = $film->year->value(); - $filmDto->duration = $film->duration; - $filmDto->coverUrl = $film->cover->url(); - $filmDto->coverFile = $film->cover->fileName(); - $filmDto->rating = $film->rating; - $filmDto->country = $film->country->name(); - $filmDto->directors = $this->getDirectors($film->directors); - $filmDto->screenplay = $film->screenplay; - $filmDto->soundtrack = $film->soundtrack; - $filmDto->photography = $film->photography; - $filmDto->cast = $this->getActors($film->cast); - $filmDto->producer = $film->producer; - $filmDto->genres = $this->getGenres($film->genres); - $filmDto->genreTopics = $this->getGenreTopics($film->genreTopics); - $filmDto->synopsis = $film->synopsis; + $filmDto->filmAfinityId = $film->id(); + $filmDto->title = $film->title(); + $filmDto->originalTitle = $film->originalTitle(); + $filmDto->year = $film->year(); + $filmDto->duration = $film->duration(); + $filmDto->coverUrl = $film->cover()->url(); + $filmDto->coverFile = $film->cover()->fileName(); + $filmDto->rating = $film->rating(); + $filmDto->country = $film->country()->name(); + $filmDto->directors = $this->getDirectors($film->directors()); + $filmDto->screenplay = $film->screenplay(); + $filmDto->soundtrack = $film->soundtrack(); + $filmDto->photography = $film->photography(); + $filmDto->cast = $this->getActors($film->cast()); + $filmDto->producer = $film->producer(); + $filmDto->genres = $this->getGenres($film->genres()); + $filmDto->genreTopics = $this->getGenreTopics($film->genreTopics()); + $filmDto->synopsis = $film->synopsis(); return $filmDto; } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchDtoToSearch.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchDtoToSearch.php index bca3f62..87b6e8a 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchDtoToSearch.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchDtoToSearch.php @@ -11,10 +11,6 @@ class SearchDtoToSearch { public function convert(SearchDto $searchDto): Search { - $search = new Search(); - - $search->searchText = $searchDto->searchText; - - return $search; + return new Search($searchDto->searchText); } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchResultsToSearchResultsDto.php b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchResultsToSearchResultsDto.php index a40f15b..7eaa12e 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchResultsToSearchResultsDto.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Application/Mappers/SearchResultsToSearchResultsDto.php @@ -15,8 +15,8 @@ class SearchResultsToSearchResultsDto public function convert(SearchResults $searchResults): SearchResultsDto { $searchResultsDto = new SearchResultsDto(); - $searchResultsDto->total = $searchResults->total; - $searchResultsDto->results = $this->convertSingleSearchResult($searchResults->results); + $searchResultsDto->total = $searchResults->total(); + $searchResultsDto->results = $this->convertSingleSearchResult($searchResults->results()); return $searchResultsDto; } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/AdvancedSearch.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/AdvancedSearch.php index 0bbaae4..02c8caf 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/AdvancedSearch.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/AdvancedSearch.php @@ -4,18 +4,112 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Domain\Model; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\CountryCode; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmYear; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\GenreCode; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\SearchText; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\SearchType; + class AdvancedSearch { - public string $searchText = ''; - public bool $searchTypeTitle = false; - public bool $searchTypeDirector = false; - public bool $searchTypeCast = false; - public bool $searchTypeScreenplay = false; - public bool $searchTypePhotography = false; - public bool $searchTypeSoundtrack = false; - public bool $searchTypeProducer = false; - public string $searchCountry = ''; - public string $searchGenre = ''; - public int $searchYearFrom = 0; - public int $searchYearTo = 0; + private SearchText $text; + private SearchType $typeTitle; + private SearchType $typeDirector; + private SearchType $typeCast; + private SearchType $typeScreenplay; + private SearchType $typePhotography; + private SearchType $typeSoundtrack; + private SearchType $typeProducer; + private ?CountryCode $countryCode; + private ?GenreCode $genreCode; + private ?FilmYear $yearFrom; + private ?FilmYear $yearTo; + + public function __construct( + string $text, + bool $typeTitle, + bool $typeDirector, + bool $typeCast, + bool $typeScreenplay, + bool $typePhotography, + bool $typeSoundtrack, + bool $typeProducer, + ?string $countryCode, + ?string $genreCode, + ?int $yearFrom, + ?int $yearTo + ) { + $this->text = new SearchText($text); + $this->typeTitle = new SearchType($typeTitle); + $this->typeDirector = new SearchType($typeDirector); + $this->typeCast = new SearchType($typeCast); + $this->typeScreenplay = new SearchType($typeScreenplay); + $this->typePhotography = new SearchType($typePhotography); + $this->typeSoundtrack = new SearchType($typeSoundtrack); + $this->typeProducer = new SearchType($typeProducer); + $this->countryCode = isset($countryCode) ? new CountryCode($countryCode) : null; + $this->genreCode = isset($genreCode) ? new GenreCode($genreCode) : null; + $this->yearFrom = isset($yearFrom) ? new FilmYear($yearFrom) : null; + $this->yearTo = isset($yearTo) ? new FilmYear($yearTo) : null; + } + + public function text(): string + { + return $this->text->value(); + } + + public function typeTitle(): bool + { + return $this->typeTitle->value(); + } + + public function typeDirector(): bool + { + return $this->typeDirector->value(); + } + + public function typeCast(): bool + { + return $this->typeCast->value(); + } + + public function typeScreenplay(): bool + { + return $this->typeScreenplay->value(); + } + + public function typePhotography(): bool + { + return $this->typePhotography->value(); + } + + public function typeSoundtrack(): bool + { + return $this->typeSoundtrack->value(); + } + + public function typeProducer(): bool + { + return $this->typeProducer->value(); + } + + public function countryCode(): string + { + return isset($this->countryCode) ? $this->countryCode->value() : ''; + } + + public function genreCode(): string + { + return isset($this->genreCode) ? $this->genreCode->value() : ''; + } + + public function yearFrom(): int + { + return isset($this->yearFrom) ? $this->yearFrom->value() : 0; + } + + public function yearTo(): int + { + return isset($this->yearTo) ? $this->yearTo->value() : 0; + } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php index 28c333a..bc4d197 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Film.php @@ -4,44 +4,193 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Domain\Model; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmDuration; use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmId; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmPhotography; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmProducer; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmRating; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmScreenplay; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmSoundtrack; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmSynopsis; use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmTitle; use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmYear; class Film { - public FilmId $filmAfinityId; - public FilmTitle $title; - public FilmTitle $originalTitle = ''; - public FilmYear $year; - public string $duration = ''; - public string $rating = ''; - public Country $country; - public string $screenplay = ''; - public string $soundtrack = ''; - public string $photography = ''; - public string $producer = ''; - public string $synopsis = ''; - - public Cover $cover; + private FilmId $id; + private FilmTitle $title; + private FilmTitle $originalTitle; + private FilmYear $year; + private FilmDuration $duration; + private FilmRating $rating; + private Country $country; + private FilmScreenplay $screenplay; + private FilmSoundtrack $soundtrack; + private FilmPhotography $photography; + private FilmProducer $producer; + private FilmSynopsis $synopsis; + private Cover $cover; /** * @var Actor[] */ - public array $cast = []; + private array $cast = []; /** * @var Director[] */ - public array $directors = []; + private array $directors = []; /** * @var Genre[] */ - public array $genres = []; + private array $genres = []; /** * @var GenreTopic[] */ - public array $genreTopics = []; + private array $genreTopics = []; + + /** + * @param Actor[] $cast + * @param Director[] $directors + * @param Genre[] $genres + * @param GenreTopic[] $genreTopics + */ + public function __construct( + int $id, + string $title, + string $originalTitle, + int $year, + int $duration, + string $rating, + Country $country, + string $screenplay, + string $soundtrack, + string $photography, + string $producer, + string $synopsis, + Cover $cover, + array $cast, + array $directors, + array $genres, + array $genreTopics + ) + { + $this->id = new FilmId($id); + $this->title = new FilmTitle($title); + $this->originalTitle = new FilmTitle($originalTitle); + $this->year = new FilmYear($year); + $this->duration = new FilmDuration($duration); + $this->rating = new FilmRating($rating); + $this->country = $country; + $this->screenplay = new FilmScreenplay($screenplay); + $this->soundtrack = new FilmSoundtrack($soundtrack); + $this->photography = new FilmPhotography($photography); + $this->producer = new FilmProducer($producer); + $this->synopsis = new FilmSynopsis($synopsis); + $this->cover = $cover; + $this->cast = $cast; + $this->directors = $directors; + $this->genres = $genres; + $this->genreTopics = $genreTopics; + } + + public function id(): int + { + return $this->id->value(); + } + + public function title(): string + { + return $this->title->value(); + } + + public function originalTitle(): string + { + return $this->originalTitle->value(); + } + + public function year(): int + { + return $this->year->value(); + } + + public function duration(): int + { + return $this->duration->value(); + } + + public function rating(): string + { + return $this->rating->value(); + } + + public function country(): Country + { + return $this->country; + } + + public function screenplay(): string + { + return $this->screenplay->value(); + } + + public function soundtrack(): string + { + return $this->soundtrack->value(); + } + + public function photography(): string + { + return $this->photography->value(); + } + + public function producer(): string + { + return $this->producer->value(); + } + + public function synopsis(): string + { + return $this->synopsis->value(); + } + + public function cover(): Cover + { + return $this->cover; + } + + /** + * @return Actor[] + */ + public function cast(): array + { + return $this->cast; + } + + /** + * @return Director[] + */ + public function directors(): array + { + return $this->directors; + } + + /** + * @return Genre[] + */ + public function genres(): array + { + return $this->genres; + } + + /** + * @return GenreTopic[] + */ + public function genreTopics(): array + { + return $this->genreTopics; + } + } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Search.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Search.php index f211443..91dd0f1 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Search.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/Search.php @@ -4,7 +4,19 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Domain\Model; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\SearchText; + class Search { - public string $searchText = ''; + private SearchText $text; + + public function __construct(string $searchText) + { + $this->text = new SearchText($searchText); + } + + public function text(): string + { + return $this->text->value(); + } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/SearchResults.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/SearchResults.php index 0f4fdec..c3c02e3 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/SearchResults.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/SearchResults.php @@ -4,12 +4,36 @@ namespace Xsga\FilmAffinityApi\Modules\Films\Domain\Model; +use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\ResultsCount; + class SearchResults { - public int $total = 0; + private ResultsCount $total; /** * @var SingleSearchResult[] */ - public array $results = []; + private array $results = []; + + /** + * @param SingleSearchResult[] $results + */ + public function __construct(int $total, array $results) + { + $this->total = new ResultsCount($total); + $this->results = $results; + } + + public function total(): int + { + return $this->total->value(); + } + + /** + * @return SingleSearchResult[] + */ + public function results(): array + { + return $this->results; + } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/SingleSearchResult.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/SingleSearchResult.php index 946d2d4..e22bc88 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/SingleSearchResult.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Model/SingleSearchResult.php @@ -22,7 +22,7 @@ class SingleSearchResult /** * @param Director[] $directors */ - public function __construct(int $id, string $title, string $year, array $directors) + public function __construct(int $id, string $title, int $year, array $directors) { $this->id = new FilmId($id); $this->title = new FilmTitle($title); @@ -40,7 +40,7 @@ public function title(): string return $this->title->value(); } - public function year(): string + public function year(): int { return $this->year->value(); } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php index 89e6afd..03223ed 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/AdvancedSearchParser.php @@ -24,18 +24,21 @@ final class AdvancedSearchParser extends AbstractParser public function getAdvSearchResults(): SearchResults { - $out = new SearchResults(); - $xpathResults = $this->getData(self::QUERY_ADV_SEARCH_DATA, false); $totalResults = $xpathResults->length; - $out->total = $totalResults; + $this->logger->info("FilmAffinity search: $totalResults results found"); - for ($i = 0; $i < $totalResults; $i++) { - $out->results[] = $this->getResultData($xpathResults, $i); - } + return new SearchResults($totalResults, $this->getResults($xpathResults)); + } - $this->logger->info("FilmAffinity search: $totalResults results found"); + private function getResults(DOMNodeList $results): array + { + $out = []; + + for ($i = 0; $i < $results->length; $i++) { + $out[] = $this->getResultData($results, $i); + } return $out; } @@ -70,12 +73,12 @@ private function getFilmTitle(DOMXPath $domXpath): string return $title; } - private function getFilmYear(DOMXPath $domXpath): string + private function getFilmYear(DOMXPath $domXpath): int { $yearResult = $domXpath->query(self::QUERY_ADV_SEARCH_GET_YEAR); $year = $yearResult->item(1)->nodeValue ?? ''; - return trim($year); + return (int)trim($year); } /** diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php index 5576686..33358ae 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/FilmParser.php @@ -55,26 +55,26 @@ public function getTitle(): string return trim($data[0]); } - public function getYear(): string + public function getYear(): int { $data = $this->getData(self::QUERY_FILM_GET_RELEASE_DATE); if (!$this->validateOneResult($data, 'film release')) { - return ''; + return 0; } - return trim($data[0]); + return (int)trim($data[0]); } - public function getDuration(): string + public function getDuration(): int { $data = $this->getData(self::QUERY_FILM_GET_DURATION); if (!$this->validateOneResult($data, 'film duration')) { - return ''; + return 0; } - return trim(str_replace('min.', '', $data[0])); + return (int)trim(str_replace('min.', '', $data[0])); } public function getProducers(): string diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php index 9eb6577..3715de3 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Parsers/SimpleSearchParser.php @@ -96,13 +96,13 @@ private function getTitle(DOMXPath $domXpath): string return $title; } - private function getYear(DOMXPath $domXpath): string + private function getYear(DOMXPath $domXpath): int { $yearResult = $domXpath->query(self::QUERY_MULTIPLE_RESULTS_GET_YEAR); $year = $yearResult->item(0)->nodeValue ?? ''; - return trim($year); + return (int)trim($year); } /** diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetFilmService.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetFilmService.php index 80ce18e..43c743f 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetFilmService.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetFilmService.php @@ -11,9 +11,6 @@ use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmDirectorsParser; use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmGenresParser; use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\FilmParser; -use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmId; -use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmTitle; -use Xsga\FilmAffinityApi\Modules\Films\Domain\ValueObjects\FilmYear; final class GetFilmService { @@ -41,26 +38,24 @@ public function get(int $filmId, string $pageContent): Film private function getFilm(int $filmId): Film { - $film = new Film(); - - $film->filmAfinityId = new FilmId($filmId); - $film->title = new FilmTitle($this->filmParser->getTitle()); - $film->originalTitle = new FilmTitle($this->filmParser->getOriginalTitle()); - $film->year = new FilmYear($this->filmParser->getYear()); - $film->duration = $this->filmParser->getDuration(); - $film->country = $this->countryParser->getCountry(); - $film->directors = $this->directorsParser->getDirectors(); - $film->screenplay = $this->filmParser->getScreenplay(); - $film->soundtrack = $this->filmParser->getSoundtrack(); - $film->photography = $this->filmParser->getPhotography(); - $film->cast = $this->castParser->getCast(); - $film->producer = $this->filmParser->getProducers(); - $film->genres = $this->genresParser->getGenres(); - $film->genreTopics = $this->genresParser->getGenreTopics(); - $film->rating = $this->filmParser->getRating(); - $film->synopsis = $this->filmParser->getSynopsis(); - $film->cover = $this->coverParser->getCover(); - - return $film; + return new Film( + $filmId, + $this->filmParser->getTitle(), + $this->filmParser->getOriginalTitle(), + $this->filmParser->getYear(), + $this->filmParser->getDuration(), + $this->filmParser->getRating(), + $this->countryParser->getCountry(), + $this->filmParser->getScreenplay(), + $this->filmParser->getSoundtrack(), + $this->filmParser->getPhotography(), + $this->filmParser->getProducers(), + $this->filmParser->getSynopsis(), + $this->coverParser->getCover(), + $this->castParser->getCast(), + $this->directorsParser->getDirectors(), + $this->genresParser->getGenres(), + $this->genresParser->getGenreTopics() + ); } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetSimpleSearchResultsService.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetSimpleSearchResultsService.php index a0a16d2..52876e7 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetSimpleSearchResultsService.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/GetSimpleSearchResultsService.php @@ -30,7 +30,7 @@ public function get(string $pageContent): SearchResults false => $this->getMultiplesResults() }; - $this->logger->info("FilmAffinity search: $searchResults->total results found"); + $this->logger->info('FilmAffinity search: ' . $searchResults->total() . 'results found'); return $searchResults; } @@ -47,19 +47,14 @@ private function getSingleResult(string $pageContent): SearchResults $this->filmDirectorsParser->getDirectors() ); - $searchResults = new SearchResults(); - $searchResults->total = 1; - $searchResults->results = [$singleResult]; - - return $searchResults; + return new SearchResults(1, [$singleResult]); } private function getMultiplesResults(): SearchResults { - $searchResults = new SearchResults(); - $searchResults->total = $this->simpleSearchParser->getMultiplesResultsTotal(); - $searchResults->results = $this->simpleSearchParser->getMultiplesResults(); - - return $searchResults; + return new SearchResults( + $this->simpleSearchParser->getMultiplesResultsTotal(), + $this->simpleSearchParser->getMultiplesResults() + ); } } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/UrlService.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/UrlService.php index eed3487..3ef38cf 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/UrlService.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/UrlService.php @@ -29,7 +29,7 @@ public function getFilmUrl(int $filmId): string public function getSearchUrl(Search $search): string { - $url = str_replace('{1}', $this->prepareSearchText($search->searchText), $this->searchUrl); + $url = str_replace('{1}', $this->prepareSearchText($search->text()), $this->searchUrl); $this->logger->debug("Search URL: $url"); @@ -49,12 +49,12 @@ public function getAdvancedSearchFormUrl(): string public function getAdvancedSearchUrl(AdvancedSearch $advancedSearch): string { $url = $this->advancedSearchUrl; - $url = str_replace('{1}', $this->prepareSearchText($advancedSearch->searchText), $url); + $url = str_replace('{1}', $this->prepareSearchText($advancedSearch->text()), $url); $url = str_replace('{2}', $this->getAdvancedSearchType($advancedSearch), $url); - $url = str_replace('{3}', $advancedSearch->searchCountry, $url); - $url = str_replace('{4}', $advancedSearch->searchGenre, $url); - $url = str_replace('{5}', $advancedSearch->searchYearFrom === 0 ? '' : (string)$advancedSearch->searchYearFrom, $url); - $url = str_replace('{6}', $advancedSearch->searchYearTo === 0 ? '' : (string)$advancedSearch->searchYearTo, $url); + $url = str_replace('{3}', $advancedSearch->countryCode(), $url); + $url = str_replace('{4}', $advancedSearch->genreCode(), $url); + $url = str_replace('{5}', $advancedSearch->yearFrom() === 0 ? '' : (string)$advancedSearch->yearFrom(), $url); + $url = str_replace('{6}', $advancedSearch->yearTo() === 0 ? '' : (string)$advancedSearch->yearTo(), $url); $this->logger->debug("Advanced Search URL: $url"); @@ -64,13 +64,13 @@ public function getAdvancedSearchUrl(AdvancedSearch $advancedSearch): string private function getAdvancedSearchType(AdvancedSearch $advancedSearch): string { $searchType = ''; - $searchType .= $advancedSearch->searchTypeTitle ? '&stype[]=title' : ''; - $searchType .= $advancedSearch->searchTypeDirector ? '&stype[]=director' : ''; - $searchType .= $advancedSearch->searchTypeCast ? '&stype[]=cast' : ''; - $searchType .= $advancedSearch->searchTypeSoundtrack ? '&stype[]=music' : ''; - $searchType .= $advancedSearch->searchTypeScreenplay ? '&stype[]=script' : ''; - $searchType .= $advancedSearch->searchTypePhotography ? '&stype[]=photo' : ''; - $searchType .= $advancedSearch->searchTypeProducer ? '&stype[]=producer' : ''; + $searchType .= $advancedSearch->typeTitle() ? '&stype[]=title' : ''; + $searchType .= $advancedSearch->typeDirector() ? '&stype[]=director' : ''; + $searchType .= $advancedSearch->typeCast() ? '&stype[]=cast' : ''; + $searchType .= $advancedSearch->typeSoundtrack() ? '&stype[]=music' : ''; + $searchType .= $advancedSearch->typeScreenplay() ? '&stype[]=script' : ''; + $searchType .= $advancedSearch->typePhotography() ? '&stype[]=photo' : ''; + $searchType .= $advancedSearch->typeProducer() ? '&stype[]=producer' : ''; if (empty($searchType)) { $this->logger->warning('No search type found. Set the default search type: title'); diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmDuration.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmDuration.php new file mode 100644 index 0000000..a17aba6 --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmDuration.php @@ -0,0 +1,20 @@ +value = $duration; + } + + public function value(): int + { + return $this->value; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmPhotography.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmPhotography.php new file mode 100644 index 0000000..41a5084 --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmPhotography.php @@ -0,0 +1,20 @@ +value = $photogrphy; + } + + public function value(): string + { + return $this->value; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmProducer.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmProducer.php new file mode 100644 index 0000000..4551ae8 --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmProducer.php @@ -0,0 +1,20 @@ +value = $producer; + } + + public function value(): string + { + return $this->value; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmRating.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmRating.php new file mode 100644 index 0000000..14b5818 --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmRating.php @@ -0,0 +1,20 @@ +value = $rating; + } + + public function value(): string + { + return $this->value; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmScreenplay.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmScreenplay.php new file mode 100644 index 0000000..0e5d571 --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmScreenplay.php @@ -0,0 +1,20 @@ +value = $screenplay; + } + + public function value(): string + { + return $this->value; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmSoundtrack.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmSoundtrack.php new file mode 100644 index 0000000..b950a33 --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmSoundtrack.php @@ -0,0 +1,20 @@ +value = $soundtrack; + } + + public function value(): string + { + return $this->value; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmSynopsis.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmSynopsis.php new file mode 100644 index 0000000..de71bba --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmSynopsis.php @@ -0,0 +1,20 @@ +value = $synopsis; + } + + public function value(): string + { + return $this->value; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmYear.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmYear.php index a08bef5..731496e 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmYear.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/FilmYear.php @@ -6,14 +6,14 @@ final class FilmYear { - private string $value; + private int $value; - public function __construct(string $year) + public function __construct(int $year) { $this->value = $year; } - public function value(): string + public function value(): int { return $this->value; } diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/ResultsCount.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/ResultsCount.php new file mode 100644 index 0000000..66a69cd --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/ResultsCount.php @@ -0,0 +1,20 @@ +value = $count; + } + + public function value(): int + { + return $this->value; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/SearchText.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/SearchText.php new file mode 100644 index 0000000..d3c95c5 --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/SearchText.php @@ -0,0 +1,20 @@ +value = $text; + } + + public function value(): string + { + return $this->value; + } +} diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/SearchType.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/SearchType.php new file mode 100644 index 0000000..bf48c62 --- /dev/null +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/ValueObjects/SearchType.php @@ -0,0 +1,20 @@ +value = $type; + } + + public function value(): bool + { + return $this->value; + } +} From 70057fe0d0be7cadd3ce711d79bcba756ded8885 Mon Sep 17 00:00:00 2001 From: parker <67624778+xsga@users.noreply.github.com> Date: Thu, 13 Jun 2024 23:52:27 +0200 Subject: [PATCH 31/39] Update README.md --- README.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 6595c96..20ecced 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Language](https://img.shields.io/github/languages/top/xsga/filmaffinity-api)](https://php.net/) [![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%208.3-8892BF?style=flat)](https://php.net/) -[![Latest version](https://img.shields.io/github/v/release/xsga/filmaffinity-api)](https://github.com/xsga/filmaffinity-api/releases/tag/v6.0.1) +[![Latest version](https://img.shields.io/github/v/release/xsga/filmaffinity-api)](https://github.com/xsga/filmaffinity-api/releases/tag/v7.0.0) [![License](https://img.shields.io/github/license/xsga/filmaffinity-api)](https://opensource.org/licenses/MIT) FilmAffinity-API is a public and non offical API wich allow you to get information about films from [FilmAffinity](http://filmaffinity.com "FilmAffinity Home") website. You can search films and get their complet information, including cast, synopsis and cover. @@ -128,11 +128,15 @@ docker exec -it filmaffinityapi-web-server php .bin/console "results": [ { "id": 160882, - "title": "Pulp Fiction (1994)" + "title": "Pulp Fiction", + "year": 1994, + "directors": ["Quentin Taratino"] }, { "id": 991349, - "title": "8 Bit Cinema: Pulp Fiction (C) (2014)" + "title": "8 Bit Cinema: Pulp Fiction", + "year": 2014, + "directors": ["David Dutton"] } ] } @@ -164,7 +168,9 @@ docker exec -it filmaffinityapi-web-server php .bin/console "results": [ { "id": 160882, - "title": "Pulp Fiction (1994)" + "title": "Pulp Fiction", + "year": 1994, + "directors": ["Quentin Taratino"] } ] } @@ -186,8 +192,8 @@ docker exec -it filmaffinityapi-web-server php .bin/console "filmAfinityId": "160882", "title": "Pulp Fiction", "originalTitle": "Pulp Fiction", - "year": "1994", - "duration": "153", + "year": 1994, + "duration": 153, "coverUrl": "https://pics.filmaffinity.com/pulp_fiction-210382116-large.jpg", "coverFile": "pulp_fiction-210382116-large.jpg", "rating": "8,6", From de61bdb41669153682350c6a3df1911db417d9e6 Mon Sep 17 00:00:00 2001 From: parker Date: Fri, 14 Jun 2024 21:25:20 +0200 Subject: [PATCH 32/39] Delete environment setting --- config/.env.example | 7 +------ config/container/Container.php | 11 +---------- config/env/Settings.php | 1 - 3 files changed, 2 insertions(+), 17 deletions(-) diff --git a/config/.env.example b/config/.env.example index 605c460..16e2376 100644 --- a/config/.env.example +++ b/config/.env.example @@ -1,11 +1,6 @@ -# ENVIRONMENT - Execution environment. -# -# Accepted values: # -# dev (for development environment) -# pro (for production environment) +# FilmAffinityAPI environtment setting. # -ENVIRONMENT="dev" # URL_PATH - FilmAffinity's API URL path. # Path in URL to access the API without domain or subdomain. diff --git a/config/container/Container.php b/config/container/Container.php index 60d748b..83e9289 100644 --- a/config/container/Container.php +++ b/config/container/Container.php @@ -18,7 +18,6 @@ use Xsga\FilmAffinityApi\Modules\Films\Application\Services\BackupGenresService; use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\AdvancedSearchFormParser; use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\AdvancedSearchParser; -use Xsga\FilmAffinityApi\Modules\Films\Domain\Parsers\SimpleSearchParser; use Xsga\FilmAffinityApi\Modules\Films\Domain\Repositories\AdvancedSearchRepository; use Xsga\FilmAffinityApi\Modules\Films\Domain\Repositories\CountriesRepository; use Xsga\FilmAffinityApi\Modules\Films\Domain\Repositories\FilmsRepository; @@ -69,7 +68,6 @@ // ENVIRONMENT. 'getLanguage' => $_ENV['LANGUAGE'], - 'getEnvironment' => $_ENV['ENVIRONMENT'], 'getErrorDetail' => filter_var($_ENV['ERROR_DETAIL'], FILTER_VALIDATE_BOOLEAN), 'getUrlPath' => $_ENV['URL_PATH'], 'getJwtSecretKey' => $_ENV['JWT_SECRET_KEY'], @@ -80,8 +78,6 @@ 'token' => SecurityTypes::TOKEN }; }, - //'getDateMask' => $_ENV['DATE_MASK'], - //'getDateTimeMask' => $_ENV['DATETIME_MASK'], 'getDateMask' => 'd/m/Y', 'getDateTimeMask' => 'd/m/Y H:i:s', 'database.info' => [ @@ -110,12 +106,7 @@ // ENTITY MANAGER. // -------------------------------------------------------------------------------------------- EntityManagerInterface::class => function (ContainerInterface $container) { - $isDevMode = match ($container->get('getEnvironment')) { - 'dev' => true, - 'pro' => false, - default => true - }; - + $isDevMode = true; $entityPaths = $container->get('entity.folders'); $proxyPath = $container->get('entities.proxy.folder'); $connection = DriverManager::getConnection($container->get('database.info')); diff --git a/config/env/Settings.php b/config/env/Settings.php index 9c0abfc..dc4433a 100644 --- a/config/env/Settings.php +++ b/config/env/Settings.php @@ -9,7 +9,6 @@ function loadEnvironmentSettings(): void $settings = Dotenv::createMutable(getPathTo('config')); $settings->safeLoad(); - $settings->required('ENVIRONMENT')->allowedValues(['dev', 'pro']); $settings->required('URL_PATH'); $settings->required('ERROR_DETAIL')->isBoolean(); $settings->required('LANGUAGE')->allowedValues(['spa', 'en']); From b8d10b4ed7d3baeae5225dfd2ba75edb18a025db Mon Sep 17 00:00:00 2001 From: parker Date: Mon, 17 Jun 2024 08:39:14 +0200 Subject: [PATCH 33/39] Code revision --- README.md | 2 +- config/container/Container.php | 6 +- config/errors/errors.json | 78 +++++++------------ scripts/02_api_user.sql | 4 +- .../Films/Domain/Services/UrlService.php | 9 ++- .../Services/GuzzleHttpClientService.php | 5 +- .../Console/GetHashedPasswordCommand.php | 12 +++ 7 files changed, 50 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index 20ecced..4a0b0b9 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ composer install ``` * Rename `config/.env.example` to `config/.env` to activates environment settings. * Setup API settings edditing `config/.env` file. -* Use test user (email `test@test.com` and password `Test123!`) or create a user using command `app:create-user`: +* Use test user (email `test@test.com` and password `test`) or create a user using command `app:create-user`: ``` docker exec -it filmaffinityapi-web-server php .bin/console app:create-user ``` diff --git a/config/container/Container.php b/config/container/Container.php index 83e9289..c1489ec 100644 --- a/config/container/Container.php +++ b/config/container/Container.php @@ -167,14 +167,12 @@ // Application services. BackupGenresService::class => DI\create(BackupGenresService::class)->constructor( - DI\get(LoggerInterface::class), DI\get(FilmAffinityGenresRepository::class), DI\get('getLanguage'), DI\get('backup.folder') ), BackupCountriesService::class => DI\create(BackupCountriesService::class)->constructor( - DI\get(LoggerInterface::class), DI\get(FilmAffinityCountriesRepository::class), DI\get('getLanguage'), DI\get('backup.folder') @@ -183,6 +181,7 @@ // Domain services. UrlService::class => DI\create(UrlService::class)->constructor( DI\get(LoggerInterface::class), + DI\get('filmaffinity.getBaseURL'), DI\get('filmaffinity.filmURL'), DI\get('filmaffinity.searchURL'), DI\get('filmaffinity.advancedSearchURL') @@ -244,8 +243,7 @@ // HTTP CLIENT application services. HttpClientService::class => DI\create(GuzzleHttpClientService::class)->constructor( DI\get(LoggerInterface::class), - DI\get(Client::class), - DI\get('filmaffinity.getBaseURL') + DI\get(Client::class) ), // SLIM middleware. diff --git a/config/errors/errors.json b/config/errors/errors.json index bc2ba92..c24ebed 100644 --- a/config/errors/errors.json +++ b/config/errors/errors.json @@ -4,8 +4,7 @@ "http": 500, "description": { "en": "Error connecting to FilmAffinity website", - "spa": "Error conectando a la web de FilmAffinity", - "ca": "Error connectant a la web de FilmAffinity" + "spa": "Error conectando a la web de FilmAffinity" } }, { @@ -13,8 +12,7 @@ "http": 500, "description": { "en": "Search text lenght not valid", - "spa": "El texto de búsqueda no tiene una longitud válida", - "ca": "El text de cerca no té una longitud vàlida" + "spa": "El texto de búsqueda no tiene una longitud válida" } }, { @@ -22,8 +20,7 @@ "http": 500, "description": { "en": "Genre code not valid", - "spa": "El codigo de género no es válido", - "ca": "El codi de gènere no és vàlid" + "spa": "El codigo de género no es válido" } }, { @@ -31,8 +28,7 @@ "http": 500, "description": { "en": "Country code not valid", - "spa": "El codigo de país no es válido", - "ca": "El codi de país no és vàlid" + "spa": "El codigo de país no es válido" } }, { @@ -40,8 +36,7 @@ "http": 500, "description": { "en": "Internal system error", - "spa": "Error interno del servidor", - "ca": "Error intern del servidor" + "spa": "Error interno del servidor" } }, { @@ -49,8 +44,7 @@ "http": 400, "description": { "en": "Error validating authorization header, empty header", - "spa": "Error al validar la cabecera de autorización, cabecera vacía", - "ca": "Error al validar la capçalera d'autorització, capçalera buida" + "spa": "Error al validar la cabecera de autorización, cabecera vacía" } }, { @@ -58,8 +52,7 @@ "http": 405, "description": { "en": "HTTP request method not valid", - "spa": "El método de la petición HTTP no es válido", - "ca": "El mètode de la petició HTTP no és vàlid" + "spa": "El método de la petición HTTP no es válido" } }, { @@ -67,8 +60,7 @@ "http": 404, "description": { "en": "API resource not found", - "spa": "Recurso de la API no encontrado", - "ca": "Recurs de la API no trobat" + "spa": "Recurso de la API no encontrado" } }, { @@ -76,8 +68,7 @@ "http": 404, "description": { "en": "User '{1}' doesn't exist in the system", - "spa": "El usuario '{1}' no existe en el sistema", - "ca": "L'usuari '{1}' no existeix en el sistema" + "spa": "El usuario '{1}' no existe en el sistema" } }, { @@ -85,8 +76,7 @@ "http": 500, "description": { "en": "User '{1}' is not active", - "spa": "El usuario '{1}' no está activo", - "ca": "L'usuari '{1}' no està actiu" + "spa": "El usuario '{1}' no está activo" } }, { @@ -94,8 +84,7 @@ "http": 500, "description": { "en": "User name or password incorrects", - "spa": "Nombre de usuario o contrasenya incorrectos", - "ca": "Nom d'usuari o contrassenya incorrectes" + "spa": "Nombre de usuario o contrasenya incorrectos" } }, { @@ -103,8 +92,7 @@ "http": 500, "description": { "en": "Error applying application security", - "spa": "Error aplicando la seguridad de la aplicación", - "ca": "Error aplicant la seguretat de l'aplicació" + "spa": "Error aplicando la seguridad de la aplicación" } }, { @@ -112,8 +100,7 @@ "http": 500, "description": { "en": "The 'getToken' resource is not available. API security type must be 'token'", - "spa": "El recurso 'getToken' no està disponible. El tipo de seguridad de la API debe ser 'token'", - "ca": "El recurs 'getToken' no está disponible. El tipus de seguretat de la API ha de ser 'token'" + "spa": "El recurso 'getToken' no està disponible. El tipo de seguridad de la API debe ser 'token'" } }, { @@ -121,8 +108,7 @@ "http": 400, "description": { "en": "Error validating request body against schema '{1}'", - "spa": "Error validando el cuerpo de la petición contra el esquema '{1}'", - "ca": "Error validant el cos de la petició contra l'esquema '{1}'" + "spa": "Error validando el cuerpo de la petición contra el esquema '{1}'" } }, { @@ -130,8 +116,7 @@ "http": 404, "description": { "en": "JSON schema '{1}' not found or it's empty", - "spa": "Esquema JSON '{1}' no encontrado o está vacío", - "ca": "Esquema JSON '{1}' no trobat o està buit" + "spa": "Esquema JSON '{1}' no encontrado o está vacío" } }, { @@ -139,8 +124,7 @@ "http": 500, "description": { "en": "Error updating user '{1}'", - "spa": "Error actualizando el usuario '{1}'", - "ca": "Error actualitzant l'usuari '{1}'" + "spa": "Error actualizando el usuario '{1}'" } }, { @@ -148,8 +132,7 @@ "http": 500, "description": { "en": "Error creating user '{1}'", - "spa": "Error creando el usuario '{1}'", - "ca": "Error creant l'usuari '{1}'" + "spa": "Error creando el usuario '{1}'" } }, { @@ -157,8 +140,7 @@ "http": 500, "description": { "en": "User password has not a valid format", - "spa": "La contraseña del usuario no tiene un formato válido", - "ca": "La contrasenya de l'usuari no té un format vàlid" + "spa": "La contraseña del usuario no tiene un formato válido" } }, { @@ -166,8 +148,7 @@ "http": 500, "description": { "en": "Email '{1}' has not a valid format", - "spa": "El correo electronico '{1}' no tiene un formato válido", - "ca": "El correu electrònic '{1}' no té un format vàlid" + "spa": "El correo electronico '{1}' no tiene un formato válido" } }, { @@ -175,8 +156,7 @@ "http": 500, "description": { "en": "User name '{1}' has not a valid format", - "spa": "El nombre de usuario '{1}' no tiene un formato válido", - "ca": "El nom d'usuari '{1}' no té un format vàlid" + "spa": "El nombre de usuario '{1}' no tiene un formato válido" } }, { @@ -184,8 +164,7 @@ "http": 500, "description": { "en": "Error getting the route contex on Slim middleware", - "spa": "Error obteniendo el contexto de la ruta en el middleware de Slim", - "ca": "Error obtenint el context de la ruta en el middleware de Slim" + "spa": "Error obteniendo el contexto de la ruta en el middleware de Slim" } }, { @@ -193,8 +172,7 @@ "http": 500, "description": { "en": "User '{1}' already exists", - "spa": "El usuario '{1}' ya existe", - "ca": "L'usuari '{1}' ja existeix" + "spa": "El usuario '{1}' ya existe" } }, { @@ -202,8 +180,7 @@ "http": 404, "description": { "en": "Error with code '{1}' not found", - "spa": "Error con código '{1}' no encontrado", - "ca": "Error amb codi '{1}' no trobat" + "spa": "Error con código '{1}' no encontrado" } }, { @@ -211,8 +188,7 @@ "http": 500, "description": { "en": "Code '{1}' has not a valid length", - "spa": "El código '{1}' no tiene una longitud válida", - "ca": "El codi '{1}' no té una longitud vàlida" + "spa": "El código '{1}' no tiene una longitud válida" } }, { @@ -220,8 +196,7 @@ "http": 500, "description": { "en": "User '{1}' is already disabled", - "spa": "El usuario '{1}' ya está deshabilitado", - "ca": "L'usuari '{1}' ja està deshabilitat" + "spa": "El usuario '{1}' ya está deshabilitado" } }, { @@ -229,8 +204,7 @@ "http": 500, "description": { "en": "User '{1}' is already enabled", - "spa": "El usuario '{1}' ya está habilitado", - "ca": "L'usuari '{1}' ja està habilitat" + "spa": "El usuario '{1}' ya está habilitado" } } ] \ No newline at end of file diff --git a/scripts/02_api_user.sql b/scripts/02_api_user.sql index 45bf413..bf3b2a3 100644 --- a/scripts/02_api_user.sql +++ b/scripts/02_api_user.sql @@ -2,8 +2,8 @@ -- Insert `app_users` -- ---------------------------------------------------------------------------- --- User: terst@test.com, password: Test123! +-- User: terst@test.com, password: test INSERT INTO app_users (id, email, password, create_date, update_date, status) -VALUES (NULL, 'test@test.com', '$2y$10$F5E5n6bJrEiLxCLa36OwFee6NtGDgX1miJcJtw.C1Chde.AM4PQ3K', NOW(), NOW(), true); +VALUES (NULL, 'test@test.com', '$2y$10$1OoDF//gr0a7TQfUTU3fiuKxj9ZH5CJd8OHQrM0jy5dd7s9kgnYVW', NOW(), NOW(), true); COMMIT; diff --git a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/UrlService.php b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/UrlService.php index 3ef38cf..5907e6e 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/UrlService.php +++ b/src/Xsga/FilmAffinityApi/Modules/Films/Domain/Services/UrlService.php @@ -12,6 +12,7 @@ final class UrlService { public function __construct( private LoggerInterface $logger, + private string $baseUrl, private string $filmUrl, private string $searchUrl, private string $advancedSearchUrl @@ -24,7 +25,7 @@ public function getFilmUrl(int $filmId): string $this->logger->debug("Film URL: $url"); - return $url; + return $this->baseUrl . $url; } public function getSearchUrl(Search $search): string @@ -33,7 +34,7 @@ public function getSearchUrl(Search $search): string $this->logger->debug("Search URL: $url"); - return $url; + return $this->baseUrl . $url; } public function getAdvancedSearchFormUrl(): string @@ -43,7 +44,7 @@ public function getAdvancedSearchFormUrl(): string $this->logger->debug("Advanced search form URL: $url"); - return $url; + return $this->baseUrl . $url; } public function getAdvancedSearchUrl(AdvancedSearch $advancedSearch): string @@ -58,7 +59,7 @@ public function getAdvancedSearchUrl(AdvancedSearch $advancedSearch): string $this->logger->debug("Advanced Search URL: $url"); - return $url; + return $this->baseUrl . $url; } private function getAdvancedSearchType(AdvancedSearch $advancedSearch): string diff --git a/src/Xsga/FilmAffinityApi/Modules/Shared/HttpClient/Infrastructure/Services/GuzzleHttpClientService.php b/src/Xsga/FilmAffinityApi/Modules/Shared/HttpClient/Infrastructure/Services/GuzzleHttpClientService.php index df6b493..830b0d7 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Shared/HttpClient/Infrastructure/Services/GuzzleHttpClientService.php +++ b/src/Xsga/FilmAffinityApi/Modules/Shared/HttpClient/Infrastructure/Services/GuzzleHttpClientService.php @@ -14,8 +14,7 @@ final class GuzzleHttpClientService implements HttpClientService { public function __construct( private LoggerInterface $logger, - private Client $client, - private string $baseUrl + private Client $client ) { } @@ -24,7 +23,7 @@ public function getPageContent(string $url): string $statusCode = 0; try { - $response = $this->client->get($this->baseUrl . $url); + $response = $this->client->get($url); $statusCode = $response->getStatusCode(); } catch (Throwable $exception) { $statusCode = $exception->getCode(); diff --git a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/GetHashedPasswordCommand.php b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/GetHashedPasswordCommand.php index c81b589..6a6628c 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/GetHashedPasswordCommand.php +++ b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/GetHashedPasswordCommand.php @@ -6,7 +6,9 @@ use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use Xsga\FilmAffinityApi\Modules\Users\Domain\ValueObjects\UserPassword; @@ -25,6 +27,10 @@ final class GetHashedPasswordCommand extends Command protected function configure(): void { $this->setHelp('This command allows you to create a new hashed password.'); + + $this->setDefinition(new InputDefinition([ + new InputOption('strict', 's', InputOption::VALUE_REQUIRED) + ])); } protected function initialize(InputInterface $input, OutputInterface $output): void @@ -37,6 +43,12 @@ protected function interact(InputInterface $input, OutputInterface $output): voi $this->display->title('GET-HASHED-PASSWORD command'); $this->display->text('Use this command to create a new hashed password.'); + if (!filter_var($input->getOption('strict'), FILTER_VALIDATE_BOOLEAN)) { + $this->hashedPassword = $this->display->askHidden('Enter password'); + $this->hashedPassword = password_hash($this->hashedPassword, PASSWORD_DEFAULT, ['cost' => 10]); + return; + } + $this->hashedPassword = $this->display->askHidden( 'Enter password', function (?string $password) { From b6abe96eb6e4009a3d2c4bbe070a98bccad8c4ce Mon Sep 17 00:00:00 2001 From: parker <67624778+xsga@users.noreply.github.com> Date: Mon, 17 Jun 2024 10:50:27 +0000 Subject: [PATCH 34/39] HTTP Client generic --- config/errors/errors.json | 4 ++-- ...AffinityWebsiteException.php => ConnectionException.php} | 2 +- .../Infrastructure/Services/GuzzleHttpClientService.php | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) rename src/Xsga/FilmAffinityApi/Modules/Shared/HttpClient/Domain/Exceptions/{FilmAffinityWebsiteException.php => ConnectionException.php} (75%) diff --git a/config/errors/errors.json b/config/errors/errors.json index c24ebed..12350ad 100644 --- a/config/errors/errors.json +++ b/config/errors/errors.json @@ -3,8 +3,8 @@ "code": 2000, "http": 500, "description": { - "en": "Error connecting to FilmAffinity website", - "spa": "Error conectando a la web de FilmAffinity" + "en": "Error connecting website", + "spa": "Error conectando a la web" } }, { diff --git a/src/Xsga/FilmAffinityApi/Modules/Shared/HttpClient/Domain/Exceptions/FilmAffinityWebsiteException.php b/src/Xsga/FilmAffinityApi/Modules/Shared/HttpClient/Domain/Exceptions/ConnectionException.php similarity index 75% rename from src/Xsga/FilmAffinityApi/Modules/Shared/HttpClient/Domain/Exceptions/FilmAffinityWebsiteException.php rename to src/Xsga/FilmAffinityApi/Modules/Shared/HttpClient/Domain/Exceptions/ConnectionException.php index e8c0c7f..9e049cd 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Shared/HttpClient/Domain/Exceptions/FilmAffinityWebsiteException.php +++ b/src/Xsga/FilmAffinityApi/Modules/Shared/HttpClient/Domain/Exceptions/ConnectionException.php @@ -6,6 +6,6 @@ use Xsga\FilmAffinityApi\Modules\Shared\Exceptions\GenericException; -class FilmAffinityWebsiteException extends GenericException +class ConnectionException extends GenericException { } diff --git a/src/Xsga/FilmAffinityApi/Modules/Shared/HttpClient/Infrastructure/Services/GuzzleHttpClientService.php b/src/Xsga/FilmAffinityApi/Modules/Shared/HttpClient/Infrastructure/Services/GuzzleHttpClientService.php index 830b0d7..d2a3d4c 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Shared/HttpClient/Infrastructure/Services/GuzzleHttpClientService.php +++ b/src/Xsga/FilmAffinityApi/Modules/Shared/HttpClient/Infrastructure/Services/GuzzleHttpClientService.php @@ -8,7 +8,7 @@ use Psr\Log\LoggerInterface; use Throwable; use Xsga\FilmAffinityApi\Modules\Shared\HttpClient\Application\Services\HttpClientService; -use Xsga\FilmAffinityApi\Modules\Shared\HttpClient\Domain\Exceptions\FilmAffinityWebsiteException; +use Xsga\FilmAffinityApi\Modules\Shared\HttpClient\Domain\Exceptions\ConnectionException; final class GuzzleHttpClientService implements HttpClientService { @@ -30,9 +30,9 @@ public function getPageContent(string $url): string } if ($statusCode !== 200) { - $errorMsg = 'Error connecting to FilmAffinity website'; + $errorMsg = "Error connecting to website: $url"; $this->logger->error($errorMsg); - throw new FilmAffinityWebsiteException($errorMsg, 2000); + throw new ConnectionException($errorMsg, 2000); } return (string)$response->getBody(); From 9d70c82ccc13c1977dc9e3d1e66702eb60233f84 Mon Sep 17 00:00:00 2001 From: parker <67624778+xsga@users.noreply.github.com> Date: Mon, 17 Jun 2024 10:54:12 +0000 Subject: [PATCH 35/39] Unused code --- .../Modules/Users/Infrastructure/Console/CreateUserCommand.php | 1 - .../Modules/Users/Infrastructure/Console/DeleteUserCommand.php | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/CreateUserCommand.php b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/CreateUserCommand.php index c7a72c5..a8a4e55 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/CreateUserCommand.php +++ b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/CreateUserCommand.php @@ -13,7 +13,6 @@ use Symfony\Component\Console\Style\SymfonyStyle; use Xsga\FilmAffinityApi\Modules\Users\Application\Services\CreateUserService; use Xsga\FilmAffinityApi\Modules\Users\Domain\ValueObjects\UserEmail; -use Xsga\FilmAffinityApi\Modules\Users\Domain\ValueObjects\UserName; use Xsga\FilmAffinityApi\Modules\Users\Domain\ValueObjects\UserPassword; use Xsga\FilmAffinityApi\Modules\Users\Infrastructure\Mappers\JsonInputToCreateUserDto; diff --git a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/DeleteUserCommand.php b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/DeleteUserCommand.php index 90c375f..14a1e60 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/DeleteUserCommand.php +++ b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/DeleteUserCommand.php @@ -11,7 +11,6 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use Xsga\FilmAffinityApi\Modules\Users\Application\Services\DeleteUserByEmailService; -use Xsga\FilmAffinityApi\Modules\Users\Application\Services\UpdateUserStatusService; use Xsga\FilmAffinityApi\Modules\Users\Domain\ValueObjects\UserEmail; #[AsCommand( From e0ca92f26afcf7c635f0827c008a4beba5d372c3 Mon Sep 17 00:00:00 2001 From: parker <67624778+xsga@users.noreply.github.com> Date: Mon, 17 Jun 2024 11:05:18 +0000 Subject: [PATCH 36/39] Docker revision --- Dockerfile | 2 +- config/.env.example | 2 +- docker-compose.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index e205a0f..bec8edc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,7 +22,7 @@ RUN curl -L https://phar.phpunit.de/phploc.phar > /usr/local/bin/phploc \ # Setup application folder. RUN mkdir -p /opt/app/public -RUN ln -s /opt/app/public /var/www/html/filmaffinityapi +RUN ln -s /opt/app/public /var/www/html # Configure PHP. COPY config/etc/php/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini diff --git a/config/.env.example b/config/.env.example index 16e2376..d12a38e 100644 --- a/config/.env.example +++ b/config/.env.example @@ -12,7 +12,7 @@ # - http://www.domain.com/api --> url_path = "api" # - http://www.domain.com/api/folder --> url_path = "api/folder" # -URL_PATH="filmaffinityapi" +URL_PATH="" # ERROR_DETAIL - Flag to output error detail on error responses. # diff --git a/docker-compose.yml b/docker-compose.yml index 62a4d93..18976fe 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,7 +28,7 @@ services: ports: - "80:80" volumes: - - .:/opt/filmaffinityapi + - .:/opt/app restart: unless-stopped depends_on: - mysql-server From 4cd3648a40d44d68bdbace67b8694834872512c1 Mon Sep 17 00:00:00 2001 From: parker Date: Mon, 17 Jun 2024 20:51:35 +0200 Subject: [PATCH 37/39] Fix error --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index bec8edc..769fef7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,7 +22,7 @@ RUN curl -L https://phar.phpunit.de/phploc.phar > /usr/local/bin/phploc \ # Setup application folder. RUN mkdir -p /opt/app/public -RUN ln -s /opt/app/public /var/www/html +RUN ln -s /opt/app/public /var/www/html/app # Configure PHP. COPY config/etc/php/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini From e4b24ae0fc502a3a967267643be6403ff3d04d42 Mon Sep 17 00:00:00 2001 From: Parker Date: Tue, 18 Jun 2024 19:25:13 +0200 Subject: [PATCH 38/39] Fix errors --- README.md | 3 ++- config/.env.example | 2 +- .../Console/GetHashedPasswordCommand.php | 11 ++++------- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 4a0b0b9..d3f5231 100644 --- a/README.md +++ b/README.md @@ -28,11 +28,12 @@ docker compose up -d composer install ``` * Rename `config/.env.example` to `config/.env` to activates environment settings. -* Setup API settings edditing `config/.env` file. +* Setup API settings edditing `config/.env` file (don't change `URL_PATH` and database variables). * Use test user (email `test@test.com` and password `test`) or create a user using command `app:create-user`: ``` docker exec -it filmaffinityapi-web-server php .bin/console app:create-user ``` +* FilmAffinityAPI is available at the following URL: `http://localhost/app` ## Manual installation diff --git a/config/.env.example b/config/.env.example index d12a38e..fdcf7cd 100644 --- a/config/.env.example +++ b/config/.env.example @@ -12,7 +12,7 @@ # - http://www.domain.com/api --> url_path = "api" # - http://www.domain.com/api/folder --> url_path = "api/folder" # -URL_PATH="" +URL_PATH="/app" # ERROR_DETAIL - Flag to output error detail on error responses. # diff --git a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/GetHashedPasswordCommand.php b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/GetHashedPasswordCommand.php index 6a6628c..8861797 100644 --- a/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/GetHashedPasswordCommand.php +++ b/src/Xsga/FilmAffinityApi/Modules/Users/Infrastructure/Console/GetHashedPasswordCommand.php @@ -6,9 +6,7 @@ use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use Xsga\FilmAffinityApi\Modules\Users\Domain\ValueObjects\UserPassword; @@ -22,15 +20,12 @@ final class GetHashedPasswordCommand extends Command { private SymfonyStyle $display; + private bool $strictMode = false; private string $hashedPassword = ''; protected function configure(): void { $this->setHelp('This command allows you to create a new hashed password.'); - - $this->setDefinition(new InputDefinition([ - new InputOption('strict', 's', InputOption::VALUE_REQUIRED) - ])); } protected function initialize(InputInterface $input, OutputInterface $output): void @@ -43,7 +38,9 @@ protected function interact(InputInterface $input, OutputInterface $output): voi $this->display->title('GET-HASHED-PASSWORD command'); $this->display->text('Use this command to create a new hashed password.'); - if (!filter_var($input->getOption('strict'), FILTER_VALIDATE_BOOLEAN)) { + $this->strictMode = $this->display->confirm('Do you want to use pattern validation?', false); + + if (!$this->strictMode) { $this->hashedPassword = $this->display->askHidden('Enter password'); $this->hashedPassword = password_hash($this->hashedPassword, PASSWORD_DEFAULT, ['cost' => 10]); return; From 9c572ae77d4311f702c057607bb8b48027f743fe Mon Sep 17 00:00:00 2001 From: parker Date: Thu, 20 Jun 2024 09:15:24 +0200 Subject: [PATCH 39/39] Dockerfile revision --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 769fef7..3421bf2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ ARG DEBIAN_FRONTEND=noninteractive # System dependencies. RUN apt-get update \ - && apt-get install -y sendmail libpng-dev libzip-dev zlib1g-dev libonig-dev gcc make autoconf + && apt-get install -y sendmail libpng-dev libzip-dev zlib1g-dev libonig-dev # PHP libraries. RUN pecl install apcu xdebug