diff --git a/config/routes.yaml b/config/routes.yaml
index 28766ec..29a5f58 100644
--- a/config/routes.yaml
+++ b/config/routes.yaml
@@ -6,6 +6,14 @@ controllersBase:
defaults:
schemes: [ 'https' ]
+controllersLibrary:
+ resource:
+ path: ../src/Library/Framework/Controller/
+ namespace: App\Library\Framework\Controller
+ type: attribute
+ defaults:
+ schemes: [ 'https' ]
+
controllersSearch:
resource:
path: ../src/Search/Framework/Controller/
diff --git a/src/Library/Action/Command/SearchCommand.php b/src/Library/Action/Command/SearchCommand.php
new file mode 100644
index 0000000..00a6728
--- /dev/null
+++ b/src/Library/Action/Command/SearchCommand.php
@@ -0,0 +1,16 @@
+
+ */
+class SearchHandler implements HandlerInterface
+{
+ private array $searchTypes = [
+ 'episode_by_title' => 'episodeByTitle',
+ ];
+
+ public function __construct(
+ private readonly MediaFiles $mediaFiles,
+ ) {}
+
+ public function handle(CommandInterface $command): ResultInterface
+ {
+ $searchType = $this->getSearchType($command);
+ $function = $this->searchTypes[$searchType];
+ return $this->$function($command);
+ }
+
+ private function getSearchType(CommandInterface $command): ?string
+ {
+ if ((!is_null($command->title) || is_null($command->imdbId)) &&
+ !is_null($command->season) &&
+ !is_null($command->episode)
+ ) {
+ return 'episode_by_title';
+ }
+ return null;
+ }
+
+ private function episodeByTitle(CommandInterface $command): ?SearchResult
+ {
+ $result = $this->mediaFiles->episodeExists(
+ $command->title,
+ (int) $command->season,
+ (int) $command->episode,
+ );
+
+ $exists = $result instanceof \SplFileInfo;
+
+ return new SearchResult(
+ input: $command,
+ message: 'Success',
+ code: 200,
+ data: [
+ 'exists' => $exists,
+ 'file' => true === $exists ? ['filename' => $result->getFilename(), 'size' => $result->getSize()] : null,
+ ]
+ );
+ }
+}
diff --git a/src/Library/Action/Input/SearchInput.php b/src/Library/Action/Input/SearchInput.php
new file mode 100644
index 0000000..32cdf0b
--- /dev/null
+++ b/src/Library/Action/Input/SearchInput.php
@@ -0,0 +1,38 @@
+
+ */
+class SearchInput implements InputInterface
+{
+ public function __construct(
+ #[SourceQuery('term', nullify: true)]
+ private ?string $term = null,
+ #[SourceQuery('title', nullify: true)]
+ private ?string $title = null,
+ #[SourceQuery('imdbId', nullify: true)]
+ private ?string $imdbId = null,
+ #[SourceQuery('season', nullify: true)]
+ private ?string $season = null,
+ #[SourceQuery('episode', nullify: true)]
+ private ?string $episode = null,
+ ) {}
+
+ public function toCommand(): CommandInterface
+ {
+ return new SearchCommand(
+ term: $this->term,
+ title: $this->title,
+ imdbId: $this->imdbId,
+ season: $this->season,
+ episode: $this->episode,
+ );
+ }
+}
diff --git a/src/Library/Action/Result/SearchResult.php b/src/Library/Action/Result/SearchResult.php
new file mode 100644
index 0000000..2dce110
--- /dev/null
+++ b/src/Library/Action/Result/SearchResult.php
@@ -0,0 +1,15 @@
+handle($input->toCommand());
+
+ if ($request->headers->get('Turbo-Frame')) {
+ return $this->sendFragmentResponse($result, $request);
+ }
+
+ return $this->json($handler->handle($input->toCommand()));
+ }
+
+ private function sendFragmentResponse(SearchResult $result, Request $request): Response
+ {
+ $request->setRequestFormat(TurboBundle::STREAM_FORMAT);
+ return $this->renderBlock(
+ 'search/fragments.html.twig',
+ $request->query->get('block'),
+ [
+ 'result' => $result,
+ 'target' => $request->query->get('target')
+ ]
+ );
+ }
+}
diff --git a/src/Search/Action/Handler/GetMediaInfoHandler.php b/src/Search/Action/Handler/GetMediaInfoHandler.php
index a514d5e..c4ce8c6 100644
--- a/src/Search/Action/Handler/GetMediaInfoHandler.php
+++ b/src/Search/Action/Handler/GetMediaInfoHandler.php
@@ -15,19 +15,12 @@ class GetMediaInfoHandler implements HandlerInterface
{
public function __construct(
private readonly Tmdb $tmdb,
- private readonly MediaFiles $mediaFiles
) {}
public function handle(CommandInterface $command): ResultInterface
{
$media = $this->tmdb->mediaDetails($command->imdbId, $command->mediaType);
- if ("tvshows" === $command->mediaType) {
- foreach ($media->episodes[$command->season] as $key => $episode) {
- $media->episodes[$command->season][$key]['file'] = $this->mediaFiles->episodeExists($media->title, $command->season, $episode['episode_number']);
- }
- }
-
return new GetMediaInfoResult($media, $command->season);
}
}
diff --git a/src/Twig/Extensions/UtilExtension.php b/src/Twig/Extensions/UtilExtension.php
index 436b67a..a591490 100644
--- a/src/Twig/Extensions/UtilExtension.php
+++ b/src/Twig/Extensions/UtilExtension.php
@@ -47,7 +47,7 @@ class UtilExtension
}
#[AsTwigFilter('episode_id_from_results')]
- public function episodeId($result): ?string
+ public function episodeIdFromResults($result): ?string
{
if (!$result instanceof GetTvShowOptionsResult) {
return null;
@@ -56,4 +56,11 @@ class UtilExtension
return "S". str_pad($result->season, 2, "0", STR_PAD_LEFT) .
"E". str_pad($result->episode, 2, "0", STR_PAD_LEFT);
}
+
+ #[AsTwigFunction('episode_id')]
+ public function episodeId($season, $episode): ?string
+ {
+ return "S". str_pad($season, 2, "0", STR_PAD_LEFT) .
+ "E". str_pad($episode, 2, "0", STR_PAD_LEFT);
+ }
}
diff --git a/templates/components/TvEpisodeList.html.twig b/templates/components/TvEpisodeList.html.twig
index e58fde7..7d1a800 100644
--- a/templates/components/TvEpisodeList.html.twig
+++ b/templates/components/TvEpisodeList.html.twig
@@ -40,30 +40,17 @@
{{ episode['air_date']|date(null, 'UTC') }}
- {% if episode['file'] != false %}
-
-
- Existing file(s) for this episode:
-
-
Existing file(s) for this episode:
+