feat: search results
This commit is contained in:
7
.env.dev
7
.env.dev
@@ -1,4 +1,7 @@
|
||||
DATABASE_URL="mysql://root:password@database:3306/app?serverVersion=10.6.19.2-MariaDB&charset=utf8mb4"
|
||||
###> symfony/framework-bundle ###
|
||||
APP_SECRET=70169beadfbc8101c393cbfbba27a313
|
||||
###< symfony/framework-bundle ###
|
||||
|
||||
DOWNLOAD_DIR=./movies
|
||||
MERCURE_URL=http://mercure/.well-known/mercure
|
||||
MERCURE_PUBLIC_URL=https://dev.caldwell.digital/hub/.well-known/mercure
|
||||
MERCURE_JWT_SECRET="!ChangeThisMercureHubJWTSecretKey!"
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
"ext-ctype": "*",
|
||||
"ext-iconv": "*",
|
||||
"1tomany/rich-bundle": "^1.8",
|
||||
"nyholm/psr7": "*",
|
||||
"php-tmdb/api": "^4.1",
|
||||
"symfony/asset": "7.2.*",
|
||||
"symfony/console": "7.2.*",
|
||||
"symfony/dotenv": "7.2.*",
|
||||
|
||||
544
composer.lock
generated
544
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "13701d11cfdac6c3280250a7a031a679",
|
||||
"content-hash": "52ea99b6f072a3dba10316c24060b886",
|
||||
"packages": [
|
||||
{
|
||||
"name": "1tomany/data-uri",
|
||||
@@ -251,6 +251,84 @@
|
||||
},
|
||||
"time": "2025-04-07T20:06:18+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nyholm/psr7",
|
||||
"version": "1.8.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Nyholm/psr7.git",
|
||||
"reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Nyholm/psr7/zipball/a71f2b11690f4b24d099d6b16690a90ae14fc6f3",
|
||||
"reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"psr/http-factory": "^1.0",
|
||||
"psr/http-message": "^1.1 || ^2.0"
|
||||
},
|
||||
"provide": {
|
||||
"php-http/message-factory-implementation": "1.0",
|
||||
"psr/http-factory-implementation": "1.0",
|
||||
"psr/http-message-implementation": "1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"http-interop/http-factory-tests": "^0.9",
|
||||
"php-http/message-factory": "^1.0",
|
||||
"php-http/psr7-integration-tests": "^1.0",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.4",
|
||||
"symfony/error-handler": "^4.4"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.8-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Nyholm\\Psr7\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Tobias Nyholm",
|
||||
"email": "tobias.nyholm@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Martijn van der Ven",
|
||||
"email": "martijn@vanderven.se"
|
||||
}
|
||||
],
|
||||
"description": "A fast PHP7 implementation of PSR-7",
|
||||
"homepage": "https://tnyholm.se",
|
||||
"keywords": [
|
||||
"psr-17",
|
||||
"psr-7"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Nyholm/psr7/issues",
|
||||
"source": "https://github.com/Nyholm/psr7/tree/1.8.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/Zegnat",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nyholm",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-09T07:06:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "opis/json-schema",
|
||||
"version": "2.4.1",
|
||||
@@ -441,6 +519,192 @@
|
||||
},
|
||||
"time": "2021-05-22T15:57:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-http/discovery",
|
||||
"version": "1.20.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-http/discovery.git",
|
||||
"reference": "82fe4c73ef3363caed49ff8dd1539ba06044910d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-http/discovery/zipball/82fe4c73ef3363caed49ff8dd1539ba06044910d",
|
||||
"reference": "82fe4c73ef3363caed49ff8dd1539ba06044910d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"composer-plugin-api": "^1.0|^2.0",
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"nyholm/psr7": "<1.0",
|
||||
"zendframework/zend-diactoros": "*"
|
||||
},
|
||||
"provide": {
|
||||
"php-http/async-client-implementation": "*",
|
||||
"php-http/client-implementation": "*",
|
||||
"psr/http-client-implementation": "*",
|
||||
"psr/http-factory-implementation": "*",
|
||||
"psr/http-message-implementation": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"composer/composer": "^1.0.2|^2.0",
|
||||
"graham-campbell/phpspec-skip-example-extension": "^5.0",
|
||||
"php-http/httplug": "^1.0 || ^2.0",
|
||||
"php-http/message-factory": "^1.0",
|
||||
"phpspec/phpspec": "^5.1 || ^6.1 || ^7.3",
|
||||
"sebastian/comparator": "^3.0.5 || ^4.0.8",
|
||||
"symfony/phpunit-bridge": "^6.4.4 || ^7.0.1"
|
||||
},
|
||||
"type": "composer-plugin",
|
||||
"extra": {
|
||||
"class": "Http\\Discovery\\Composer\\Plugin",
|
||||
"plugin-optional": true
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Http\\Discovery\\": "src/"
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"src/Composer/Plugin.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Márk Sági-Kazár",
|
||||
"email": "mark.sagikazar@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Finds and installs PSR-7, PSR-17, PSR-18 and HTTPlug implementations",
|
||||
"homepage": "http://php-http.org",
|
||||
"keywords": [
|
||||
"adapter",
|
||||
"client",
|
||||
"discovery",
|
||||
"factory",
|
||||
"http",
|
||||
"message",
|
||||
"psr17",
|
||||
"psr7"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-http/discovery/issues",
|
||||
"source": "https://github.com/php-http/discovery/tree/1.20.0"
|
||||
},
|
||||
"time": "2024-10-02T11:20:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-tmdb/api",
|
||||
"version": "4.1.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-tmdb/api.git",
|
||||
"reference": "7f7b3c6317b1346e6bc646ad63edb212a2b55584"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-tmdb/api/zipball/7f7b3c6317b1346e6bc646ad63edb212a2b55584",
|
||||
"reference": "7f7b3c6317b1346e6bc646ad63edb212a2b55584",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"php": "^7.3 || ^7.4 || ^8.0 || ^8.1",
|
||||
"php-http/discovery": "^1.11",
|
||||
"psr/cache": "^1 || ^2 || ^3",
|
||||
"psr/event-dispatcher": "^1",
|
||||
"psr/event-dispatcher-implementation": "^1",
|
||||
"psr/http-client": "^1",
|
||||
"psr/http-client-implementation": "^1",
|
||||
"psr/http-factory": "^1",
|
||||
"psr/http-factory-implementation": "^1",
|
||||
"psr/http-message": "^1",
|
||||
"psr/log": "^1 || ^2 || ^3",
|
||||
"psr/simple-cache": "^1 || ^2 || ^3",
|
||||
"symfony/options-resolver": ">=4.4 || ^5 || ^6"
|
||||
},
|
||||
"require-dev": {
|
||||
"jeroen/psr-log-test-doubles": "^2.1 || ^3",
|
||||
"monolog/monolog": ">=1.11.0",
|
||||
"nyholm/psr7": "^1.2",
|
||||
"php-http/cache-plugin": "^1.7",
|
||||
"php-http/guzzle7-adapter": "^0.1",
|
||||
"php-http/mock-client": "^1.2",
|
||||
"phpstan/phpstan": "^1.8.1",
|
||||
"phpunit/phpunit": ">=8.5.23 || ^9.3",
|
||||
"slevomat/coding-standard": "^6.4",
|
||||
"squizlabs/php_codesniffer": "^3.5.8",
|
||||
"symfony/cache": ">=4.4 || ^5 || ^6",
|
||||
"symfony/event-dispatcher": ">=4.4 || ^5 || ^6",
|
||||
"vimeo/psalm": "^4"
|
||||
},
|
||||
"suggest": {
|
||||
"monolog/monolog": "Great logger to use, but you can pick any PSR-3 logger you wish.",
|
||||
"php-http/cache-plugin": "When making use of cache, you need to install this plugin.",
|
||||
"psr/cache-implementation": "If you wish to enable caching features, provide an PSR-6 cache implementation.",
|
||||
"psr/log-implementation": "If you wish to enable logging features, provide an PSR-3 logger.",
|
||||
"psr/simple-cache-implementation": "If you wish to enable caching features, provide an PSR-16 cache.",
|
||||
"symfony/cache": "Great cache to use, but you can pick any PSR-6 cache you wish."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Tmdb\\": "lib/Tmdb"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michael Roterman",
|
||||
"email": "michael@wtfz.net",
|
||||
"homepage": "http://wtfz.net"
|
||||
}
|
||||
],
|
||||
"description": "PHP wrapper for TMDB (TheMovieDatabase) API v3. Supports two types of approaches, one modelled with repositories, models and factories. And the other by simple array access to RAW data from The Movie Database.",
|
||||
"homepage": "https://github.com/php-tmdb/api",
|
||||
"keywords": [
|
||||
"api",
|
||||
"movie",
|
||||
"php",
|
||||
"tmdb",
|
||||
"tv",
|
||||
"tv show",
|
||||
"tvdb",
|
||||
"wrapper"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-tmdb/api/issues",
|
||||
"source": "https://github.com/php-tmdb/api/tree/4.1.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=SMLZ362KQ8K8W",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/php-tmdb",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/wtfzdotnet",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-11-04T19:25:12+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/reflection-common",
|
||||
"version": "2.2.0",
|
||||
@@ -863,6 +1127,166 @@
|
||||
},
|
||||
"time": "2019-01-08T18:20:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-client",
|
||||
"version": "1.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-client.git",
|
||||
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
|
||||
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.0 || ^8.0",
|
||||
"psr/http-message": "^1.0 || ^2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Client\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for HTTP clients",
|
||||
"homepage": "https://github.com/php-fig/http-client",
|
||||
"keywords": [
|
||||
"http",
|
||||
"http-client",
|
||||
"psr",
|
||||
"psr-18"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/http-client"
|
||||
},
|
||||
"time": "2023-09-23T14:17:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-factory",
|
||||
"version": "1.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-factory.git",
|
||||
"reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
|
||||
"reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1",
|
||||
"psr/http-message": "^1.0 || ^2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Message\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
|
||||
"keywords": [
|
||||
"factory",
|
||||
"http",
|
||||
"message",
|
||||
"psr",
|
||||
"psr-17",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/http-factory"
|
||||
},
|
||||
"time": "2024-04-15T12:06:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-message",
|
||||
"version": "1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-message.git",
|
||||
"reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba",
|
||||
"reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Message\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for HTTP messages",
|
||||
"homepage": "https://github.com/php-fig/http-message",
|
||||
"keywords": [
|
||||
"http",
|
||||
"http-message",
|
||||
"psr",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/http-message/tree/1.1"
|
||||
},
|
||||
"time": "2023-04-04T09:50:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "3.0.2",
|
||||
@@ -913,6 +1337,57 @@
|
||||
},
|
||||
"time": "2024-09-11T13:17:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/simple-cache",
|
||||
"version": "3.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/simple-cache.git",
|
||||
"reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865",
|
||||
"reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\SimpleCache\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interfaces for simple caching",
|
||||
"keywords": [
|
||||
"cache",
|
||||
"caching",
|
||||
"psr",
|
||||
"psr-16",
|
||||
"simple-cache"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/simple-cache/tree/3.0.0"
|
||||
},
|
||||
"time": "2021-10-29T13:26:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/asset",
|
||||
"version": "v7.2.0",
|
||||
@@ -2642,6 +3117,73 @@
|
||||
],
|
||||
"time": "2025-03-28T13:32:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/options-resolver",
|
||||
"version": "v7.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/options-resolver.git",
|
||||
"reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/7da8fbac9dcfef75ffc212235d76b2754ce0cf50",
|
||||
"reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.2",
|
||||
"symfony/deprecation-contracts": "^2.5|^3"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\OptionsResolver\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Provides an improved replacement for the array_replace PHP function",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"config",
|
||||
"configuration",
|
||||
"options"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/options-resolver/tree/v7.2.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-11-20T11:17:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/password-hasher",
|
||||
"version": "v7.2.0",
|
||||
|
||||
10
config/packages/http_discovery.yaml
Normal file
10
config/packages/http_discovery.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
services:
|
||||
Psr\Http\Message\RequestFactoryInterface: '@http_discovery.psr17_factory'
|
||||
Psr\Http\Message\ResponseFactoryInterface: '@http_discovery.psr17_factory'
|
||||
Psr\Http\Message\ServerRequestFactoryInterface: '@http_discovery.psr17_factory'
|
||||
Psr\Http\Message\StreamFactoryInterface: '@http_discovery.psr17_factory'
|
||||
Psr\Http\Message\UploadedFileFactoryInterface: '@http_discovery.psr17_factory'
|
||||
Psr\Http\Message\UriFactoryInterface: '@http_discovery.psr17_factory'
|
||||
|
||||
http_discovery.psr17_factory:
|
||||
class: Http\Discovery\Psr17Factory
|
||||
@@ -3,10 +3,14 @@ controllersIndex:
|
||||
path: ../src/Controller/
|
||||
namespace: App\Controller
|
||||
type: attribute
|
||||
defaults:
|
||||
schemes: [ https ]
|
||||
|
||||
controllersSearch:
|
||||
resource:
|
||||
path: ../src/Search/Framework/Controller
|
||||
namespace: App\Search\Framework\Controller
|
||||
type: attribute
|
||||
defaults:
|
||||
schemes: [ https ]
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
namespace App\Enum;
|
||||
|
||||
enum MediaType
|
||||
enum MediaType: string
|
||||
{
|
||||
|
||||
case Movie = 'movies';
|
||||
case TvShow = 'tvshows';
|
||||
}
|
||||
|
||||
@@ -2,7 +2,15 @@
|
||||
|
||||
namespace App\Search\Action\Command;
|
||||
|
||||
class SearchCommand
|
||||
{
|
||||
use OneToMany\RichBundle\Contract\CommandInterface;
|
||||
|
||||
}
|
||||
class SearchCommand implements CommandInterface
|
||||
{
|
||||
/**
|
||||
* @param string $term
|
||||
* @implements CommandInterface<SearchCommand>
|
||||
*/
|
||||
public function __construct(
|
||||
public string $term
|
||||
) {}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,24 @@
|
||||
|
||||
namespace App\Search\Action\Handler;
|
||||
|
||||
class SearchHandler
|
||||
{
|
||||
use App\Search\Action\Result\SearchResult;
|
||||
use App\Tmdb\Tmdb;
|
||||
use OneToMany\RichBundle\Contract\CommandInterface;
|
||||
use OneToMany\RichBundle\Contract\HandlerInterface;
|
||||
use OneToMany\RichBundle\Contract\ResultInterface;
|
||||
|
||||
}
|
||||
class SearchHandler implements HandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private Tmdb $tmdb,
|
||||
) {}
|
||||
|
||||
/*** @implements HandlerInterface<SearchResult> */
|
||||
public function handle(CommandInterface $command): ResultInterface
|
||||
{
|
||||
return new SearchResult(
|
||||
term: $command->term,
|
||||
results: $this->tmdb->search($command->term)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,25 @@
|
||||
|
||||
namespace App\Search\Action\Input;
|
||||
|
||||
class SearchInput
|
||||
{
|
||||
use App\Search\Action\Command\SearchCommand;
|
||||
use OneToMany\RichBundle\Attribute\SourceQuery;
|
||||
use OneToMany\RichBundle\Attribute\SourceRequest;
|
||||
use OneToMany\RichBundle\Contract\CommandInterface;
|
||||
use OneToMany\RichBundle\Contract\InputInterface;
|
||||
|
||||
}
|
||||
/**
|
||||
* @implements InputInterface<SearchCommand>
|
||||
*/
|
||||
class SearchInput implements InputInterface
|
||||
{
|
||||
public function __construct(
|
||||
#[SourceQuery('term')]
|
||||
#[SourceRequest('term')]
|
||||
public string $term
|
||||
){}
|
||||
|
||||
public function toCommand(): CommandInterface
|
||||
{
|
||||
return new SearchCommand($this->term);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
|
||||
namespace App\Search\Action\Result;
|
||||
|
||||
class SearchResult
|
||||
{
|
||||
use OneToMany\RichBundle\Contract\ResultInterface;
|
||||
|
||||
}
|
||||
class SearchResult implements ResultInterface
|
||||
{
|
||||
public function __construct(
|
||||
public string $term = "",
|
||||
public array $results = []
|
||||
) {}
|
||||
}
|
||||
|
||||
@@ -2,17 +2,27 @@
|
||||
|
||||
namespace App\Search\Framework\Controller;
|
||||
|
||||
use App\Search\Action\Handler\SearchHandler;
|
||||
use App\Search\Action\Input\SearchInput;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
final class SearchController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private SearchHandler $searchHandler,
|
||||
) {}
|
||||
|
||||
#[Route('/search', name: 'app_search', methods: ['GET'])]
|
||||
public function index(): Response
|
||||
public function index(
|
||||
SearchInput $searchInput,
|
||||
): Response
|
||||
{
|
||||
$results = $this->searchHandler->handle($searchInput->toCommand());
|
||||
|
||||
return $this->render('search/results.html.twig', [
|
||||
'controller_name' => 'SearchController',
|
||||
'results' => $results,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
namespace App\Tmdb;
|
||||
|
||||
use App\ValueObject\MediaResult;
|
||||
use App\Enum\MediaType;
|
||||
use App\Tmdb\TmdbResult;
|
||||
use App\ValueObject\ResultFactory;
|
||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
@@ -31,7 +32,7 @@ use Tmdb\Repository\TvSeasonRepository;
|
||||
use Tmdb\Token\Api\ApiToken;
|
||||
use Tmdb\Token\Api\BearerToken;
|
||||
|
||||
class Client
|
||||
class Tmdb
|
||||
{
|
||||
protected Client $client;
|
||||
|
||||
@@ -178,8 +179,8 @@ class Client
|
||||
throw new \Exception("A media type must be set when parsing from an array.");
|
||||
}
|
||||
|
||||
function parseTvShow(array $data, string $posterBasePath): MediaResult {
|
||||
return new MediaResult(
|
||||
function parseTvShow(array $data, string $posterBasePath): TmdbResult {
|
||||
return new TmdbResult(
|
||||
imdbId: $data['external_ids']['imdb_id'],
|
||||
tvdbId: $data['id'],
|
||||
title: $data['name'],
|
||||
@@ -191,8 +192,8 @@ class Client
|
||||
);
|
||||
}
|
||||
|
||||
function parseMovie(array $data, string $posterBasePath): MediaResult {
|
||||
return new MediaResult(
|
||||
function parseMovie(array $data, string $posterBasePath): TmdbResult {
|
||||
return new TmdbResult(
|
||||
imdbId: $data['external_ids']['imdb_id'],
|
||||
tvdbId: $data['id'],
|
||||
title: $data['title'],
|
||||
@@ -209,67 +210,80 @@ class Client
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function parseFromObject($result)
|
||||
private function parseFromObject($result): TmdbResult
|
||||
{
|
||||
$result->mediaType = $result instanceof Movie ? 'movies' : 'tvshows';
|
||||
$mediaType = $result instanceof Movie ? MediaType::Movie->value : MediaType::TvShow->value;
|
||||
$tmdbResult = new TmdbResult();
|
||||
$tmdbResult->mediaType = $mediaType;
|
||||
$tmdbResult->imdbId = $this->getImdbId($result->getId(), $mediaType);
|
||||
$tmdbResult->title = $this->getTitle($result, $mediaType);
|
||||
$tmdbResult->poster = self::POSTER_IMG_PATH . $result->getPosterImage();
|
||||
$tmdbResult->year = $this->getReleaseDate($result, $mediaType);
|
||||
$tmdbResult->description = $result->getOverview();
|
||||
return $tmdbResult;
|
||||
}
|
||||
|
||||
$externalIds = $this->cache->get("tmdb.externalIds.{$result->getId()}", function (ItemInterface $item) use ($result) {
|
||||
if ($result instanceof Movie) {
|
||||
$externalIds = $this->movieRepository->getExternalIds($result->getId());
|
||||
} else {
|
||||
$externalIds = $this->tvRepository->getExternalIds($result->getId());
|
||||
}
|
||||
return $externalIds;
|
||||
public function getImdbId(string $tmdbId, $mediaType)
|
||||
{
|
||||
$externalIds = $this->cache->get("tmdb.externalIds.{$tmdbId}",
|
||||
function (ItemInterface $item) use ($tmdbId, $mediaType) {
|
||||
switch (MediaType::tryFrom($mediaType)->value) {
|
||||
case MediaType::Movie->value:
|
||||
return $this->movieRepository->getExternalIds($tmdbId);
|
||||
case MediaType::TvShow->value:
|
||||
return $this->tvRepository->getExternalIds($tmdbId);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
$images = $this->cache->get("tmdb.images.{$result->getId()}", function (ItemInterface $item) use ($result) {
|
||||
if ($result instanceof Movie) {
|
||||
$images = $this->movieRepository->getImages($result->getId());
|
||||
} else {
|
||||
$images = $this->tvRepository->getImages($result->getId());
|
||||
}
|
||||
return $images;
|
||||
if (null === $externalIds) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $externalIds->getImdbId() !== "" ? $externalIds->getImdbId() : "null";
|
||||
}
|
||||
|
||||
public function getImages($tmdbId, $mediaType)
|
||||
{
|
||||
return $this->cache->get("tmdb.images.{$tmdbId}",
|
||||
function (ItemInterface $item) use ($tmdbId, $mediaType) {
|
||||
switch (MediaType::tryFrom($mediaType)->value) {
|
||||
case MediaType::Movie->value:
|
||||
return $this->movieRepository->getImages($tmdbId);
|
||||
case MediaType::TvShow->value:
|
||||
return $this->tvRepository->getImages($tmdbId);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (null !== $externalIds) {
|
||||
$imdbId = $externalIds->getImdbId() !== "" ? $externalIds->getImdbId() : "null";
|
||||
|
||||
if ("movies" === $result->mediaType) {
|
||||
$result->setImdbId($imdbId);
|
||||
} else {
|
||||
$result->imdbId = $imdbId;
|
||||
$result->title = $result->getName();
|
||||
}
|
||||
} else {
|
||||
if ("movies" === $result->mediaType) {
|
||||
$result->setImdbId("null");
|
||||
} else {
|
||||
$result->imdbId = "null";
|
||||
}
|
||||
private function getReleaseDate($result, $mediaType): string
|
||||
{
|
||||
switch (MediaType::tryFrom($mediaType)->value) {
|
||||
case MediaType::Movie->value:
|
||||
return ($result->getReleaseDate() instanceof \DateTime)
|
||||
? $result->getReleaseDate()->format('Y')
|
||||
: $result->getReleaseDate();
|
||||
case MediaType::TvShow->value:
|
||||
return ($result->getFirstAirDate() instanceof \DateTime)
|
||||
? $result->getFirstAirDate()->format('Y')
|
||||
: $result->getFirstAirDate();
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
if ("movies" === $result->mediaType) {
|
||||
if ($result->getReleaseDate() instanceof \DateTime) {
|
||||
$result->year = $result->getReleaseDate()->format("Y");
|
||||
} else {
|
||||
$result->year = (new \DateTime($result->getReleaseDate()))->format('Y');
|
||||
}
|
||||
} else {
|
||||
if ($result->getFirstAirDate() instanceof \DateTime) {
|
||||
$result->year = $result->getFirstAirDate()->format("Y");
|
||||
} else {
|
||||
$result->year = (new \DateTime($result->getFirstAirDate()))->format('Y');
|
||||
}
|
||||
private function getTitle($result, $mediaType): string
|
||||
{
|
||||
switch (MediaType::tryFrom($mediaType)->value) {
|
||||
case MediaType::Movie->value:
|
||||
return $result->getTitle();
|
||||
case MediaType::TvShow->value:
|
||||
return $result->getName();
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
||||
/** @var Movie $result */
|
||||
$result->setExternalIds($externalIds);
|
||||
|
||||
$result->setImages($images);
|
||||
$result->getPosterImage()->setFilePath(
|
||||
self::POSTER_IMG_PATH . $result->getPosterImage()->getFilePath()
|
||||
);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\ValueObject;
|
||||
namespace App\Tmdb;
|
||||
|
||||
class MediaResult
|
||||
class TmdbResult
|
||||
{
|
||||
public function __construct(
|
||||
public string $imdbId,
|
||||
public string $tvdbId,
|
||||
public string $title,
|
||||
public string $poster,
|
||||
public string $excerpt,
|
||||
public string $year,
|
||||
public string $mediaType,
|
||||
public ?string $imdbId = "",
|
||||
public ?string $tvdbId = "",
|
||||
public ?string $title = "",
|
||||
public ?string $poster = "",
|
||||
public ?string $description = "",
|
||||
public ?string $year = "",
|
||||
public ?string $mediaType = "",
|
||||
public ?array $episodes = null,
|
||||
) {}
|
||||
}
|
||||
|
||||
10
src/Twig/Components/SearchResult.php
Normal file
10
src/Twig/Components/SearchResult.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace App\Twig\Components;
|
||||
|
||||
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
|
||||
|
||||
#[AsTwigComponent]
|
||||
final class SearchResult
|
||||
{
|
||||
}
|
||||
12
symfony.lock
12
symfony.lock
@@ -2,6 +2,18 @@
|
||||
"1tomany/rich-bundle": {
|
||||
"version": "v1.8.3"
|
||||
},
|
||||
"php-http/discovery": {
|
||||
"version": "1.20",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "1.18",
|
||||
"ref": "f45b5dd173a27873ab19f5e3180b2f661c21de02"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/http_discovery.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/asset-mapper": {
|
||||
"version": "7.2",
|
||||
"recipe": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div{{ attributes }}>
|
||||
<div class="flex flex-col bg-white border border-gray-200 border-t-4 border-t-orange-500 shadow-2xs rounded-xl dark:bg-slate-600 dark:border-neutral-700 dark:border-t-orange-500 dark:shadow-neutral-700/70">
|
||||
<div class="p-4 md:p-5">
|
||||
<h3 class="mb-1 text-lg font-bold text-gray-800 dark:text-white">
|
||||
<h3 class="mb-4 text-lg font-bold text-gray-800 dark:text-white">
|
||||
{{ title }}
|
||||
</h3>
|
||||
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
<div {{ attributes }} class="w-full max-w-sm min-w-[200px]">
|
||||
<div class="relative">
|
||||
<input
|
||||
class="w-full bg-orange-500 rounded-md bg-clip-padding backdrop-filter
|
||||
backdrop-blur-md bg-opacity-40 placeholder:text-slate-200 text-gray-50
|
||||
text-sm border border-orange-500 rounded-md pl-3 pr-28 py-2 transition
|
||||
duration-300 ease focus:outline-none focus:border-orange-400 hover:border-orange-300
|
||||
shadow-sm focus:shadow"
|
||||
placeholder="TV Show, Movie..."
|
||||
/>
|
||||
<button
|
||||
class="absolute top-1 right-1 flex items-center rounded bg-green-600 py-1 px-2.5 border border-transparent text-center text-sm text-white transition-all shadow-sm hover:shadow focus:bg-green-700 focus:shadow-none active:bg-green-700 hover:bg-green-700 active:shadow-none disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"
|
||||
type="button"
|
||||
>
|
||||
Search
|
||||
</button>
|
||||
<form action="{{ url('app_search') }}">
|
||||
<input
|
||||
name="term"
|
||||
class="w-full bg-orange-500 rounded-md bg-clip-padding backdrop-filter
|
||||
backdrop-blur-md bg-opacity-40 placeholder:text-slate-200 text-gray-50
|
||||
text-sm border border-orange-500 rounded-md pl-3 pr-28 py-2 transition
|
||||
duration-300 ease focus:outline-none focus:border-orange-400 hover:border-orange-300
|
||||
shadow-sm focus:shadow"
|
||||
placeholder="TV Show, Movie..."
|
||||
/>
|
||||
<button
|
||||
class="absolute top-1 right-1 flex items-center rounded bg-green-600 py-1 px-2.5 border border-transparent text-center text-sm text-white transition-all shadow-sm hover:shadow focus:bg-green-700 focus:shadow-none active:bg-green-700 hover:bg-green-700 active:shadow-none disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"
|
||||
type="button"
|
||||
>
|
||||
Search
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
16
templates/components/SearchResult.html.twig
Normal file
16
templates/components/SearchResult.html.twig
Normal file
@@ -0,0 +1,16 @@
|
||||
<div{{ attributes }}>
|
||||
<div class="p-4 flex flex-row gap-6 bg-orange-500 bg-clip-padding backdrop-filter backdrop-blur-md bg-opacity-60 rounded-md">
|
||||
<img class="w-24" src="{{ poster }}" />
|
||||
<div class="w-full flex flex-col">
|
||||
<h3 class="mb-4 text-xl font-medium leading-tight font-bold text-gray-50">
|
||||
{{ title }} - {{ year }}
|
||||
</h3>
|
||||
<p class="text-gray-50">
|
||||
{{ description }}
|
||||
</p>
|
||||
</div>
|
||||
<a class="h-9 rounded-md py-1 px-2 bg-green-600 text-gray-50"
|
||||
href="/results/{{ mediaType }}/{{ imdbId }}/"
|
||||
>choose</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -3,9 +3,9 @@
|
||||
{% block title %}Dashboard &mdash - Torsearch{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="p-4 flex flex-col grow gap-2">
|
||||
<div class="p-4 flex flex-col grow gap-4">
|
||||
<h2 class="mb-2 text-3xl font-bold text-gray-50">Dashboard</h2>
|
||||
<div class="flex flex-row gap-2">
|
||||
<div class="flex flex-row gap-4">
|
||||
<twig:Card title="Active Downloads" class="w-full">
|
||||
<table class="divide-y divide-gray-200 dark:divide-gray-50 dark:bg-gray-50">
|
||||
<thead>
|
||||
|
||||
@@ -3,16 +3,24 @@
|
||||
{% block title %}Search Results &mdash - Torsearch{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="p-4 flex flex-col grow gap-2">
|
||||
<div class="p-4 flex flex-col grow gap-4">
|
||||
<h2 class="mb-2 text-3xl font-bold text-gray-50">Search Results</h2>
|
||||
<div class="flex flex-row gap-2">
|
||||
<twig:Card title="Popular Movies" contentClass="flex flex-row justify-between w-full">
|
||||
<twig:Poster imdbId="" title="A Working Man" description="" image="https://image.tmdb.org/t/p/w500/xUkUZ8eOnrOnnJAfusZUqKYZiDu.jpg" year="" />
|
||||
<twig:Poster imdbId="" title="In the Lost Lands" description="" image="https://image.tmdb.org/t/p/w500/iHf6bXPghWB6gT8kFkL1zo00x6X.jpg" year="" />
|
||||
<twig:Poster imdbId="" title="A Minecraft Movie" description="" image="https://image.tmdb.org/t/p/w500/yFHHfHcUgGAxziP1C3lLt0q2T4s.jpg" year="" />
|
||||
<twig:Poster imdbId="" title="G20" description="" image="https://image.tmdb.org/t/p/w500/wv6oWAleCJZUk5htrGg413t3GCy.jpg" year="" />
|
||||
<twig:Poster imdbId="" title="Novocaine" description="" image="https://image.tmdb.org/t/p/w500/xmMHGz9dVRaMY6rRAlEX4W0Wdhm.jpg" year="" />
|
||||
<twig:Poster imdbId="" title="Gunslingers" description="" image="https://image.tmdb.org/t/p/w500/O7REXWPANWXvX2jhQydHjAq2DV.jpg" year="" />
|
||||
<div class="flex flex-row w-full gap-2">
|
||||
<twig:Card title="{{ results.results|length }} results for {{ results.term }}" contentClass="flex flex-col gap-4 justify-between w-full">
|
||||
{% for result in results.results %}
|
||||
<ul>
|
||||
<li>
|
||||
<twig:SearchResult
|
||||
mediaType="{{ result.mediaType }}"
|
||||
title="{{ result.title }}"
|
||||
year="{{ result.year }}"
|
||||
description="{{ result.description }}"
|
||||
poster="{{ result.poster }}"
|
||||
imdbId="{{ result.imdbId }}"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
{% endfor %}
|
||||
</twig:Card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user