wip: adds cache rich functionality
This commit is contained in:
30
assets/controllers/clear_cache_controller.js
Normal file
30
assets/controllers/clear_cache_controller.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { Controller } from '@hotwired/stimulus';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following line makes this controller "lazy": it won't be downloaded until needed
|
||||||
|
* See https://symfony.com/bundles/StimulusBundle/current/index.html#lazy-stimulus-controllers
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* stimulusFetch: 'lazy' */
|
||||||
|
export default class extends Controller {
|
||||||
|
initialize() {}
|
||||||
|
|
||||||
|
connect() {}
|
||||||
|
|
||||||
|
disconnect() {}
|
||||||
|
|
||||||
|
async clearAll() {
|
||||||
|
let response = await fetch('/api/torrentio/cache', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Accept': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
type: 'torrentio',
|
||||||
|
mediaType: 'tvshows',
|
||||||
|
})
|
||||||
|
});
|
||||||
|
response = await response.json()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,6 +25,13 @@
|
|||||||
.alert-warning {
|
.alert-warning {
|
||||||
@apply bg-yellow-500/70 hover:bg-yellow-600 border-yellow-400 text-black
|
@apply bg-yellow-500/70 hover:bg-yellow-600 border-yellow-400 text-black
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.primary-btn {
|
||||||
|
@apply px-1 py-1 rounded-md bg-orange-500 self-end text-white w-16 ml-2 hover:bg-orange-600
|
||||||
|
}
|
||||||
|
.secondary-btn {
|
||||||
|
@apply px-1 py-1 rounded-md self-end w-16 hover:bg-stone-100
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prevent scrolling while dialog is open */
|
/* Prevent scrolling while dialog is open */
|
||||||
|
|||||||
@@ -29,3 +29,12 @@ controllersMonitor:
|
|||||||
type: attribute
|
type: attribute
|
||||||
defaults:
|
defaults:
|
||||||
schemes: ['https']
|
schemes: ['https']
|
||||||
|
|
||||||
|
controllersTorrentio:
|
||||||
|
resource:
|
||||||
|
path: ../src/Torrentio/Framework/Controller
|
||||||
|
namespace: App\Torrentio\Framework\Controller
|
||||||
|
type: attribute
|
||||||
|
defaults:
|
||||||
|
schemes: [ 'https' ]
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ final class TorrentioController extends AbstractController
|
|||||||
try {
|
try {
|
||||||
return $pageCache->get($cacheId, function (ItemInterface $item) use ($input) {
|
return $pageCache->get($cacheId, function (ItemInterface $item) use ($input) {
|
||||||
$item->expiresAt(Carbon::now()->addHour()->setMinute(0)->setSecond(0));
|
$item->expiresAt(Carbon::now()->addHour()->setMinute(0)->setSecond(0));
|
||||||
$item->tag(['page', 'page.torrentio', 'page.torrentio.tvshows', "page.torrentio.tvshows.$input->tmdbId.$input->imdbId", "page.torrentio.tvshows.$input->tmdbId.$input->imdbId.$input->season", "page.torrentio.tvshows.$input->tmdbId.$input->imdbId.$input->season.$input->episode", 'torrentio', 'torrentio.tvshows', "torrentio.tvshows.$input->tmdbId.$input->imdbId", "torrentio.tvshows.$input->tmdbId.$input->imdbId.$input->season", "torrentio.tvshows.$input->tmdbId.$input->imdbId.$input->season.$input->episode"]);
|
$item->tag(['page', 'page.torrentio', 'page.torrentio.tvshows', "page.torrentio.tvshows.$input->tmdbId.$input->imdbId", "page.torrentio.tvshows.$input->tmdbId.$input->imdbId.$input->season", "page.torrentio.tvshows.$input->tmdbId.$input->imdbId.$input->season.$input->episode", 'torrentio', 'torrentio.tvshows', "torrentio.tvshows.$input->tmdbId.$input->imdbId", "torrentio.tvshows.$input->tmdbId.$input->imdbId.$input->season", "torrentio.tvshows.$input->tmdbId.$input->imdbId.$input->season.$input->episode", $input->imdbId, $input->tmdbId]);
|
||||||
$results = $this->getTvShowOptionsHandler->handle($input->toCommand());
|
$results = $this->getTvShowOptionsHandler->handle($input->toCommand());
|
||||||
return $this->render('torrentio/tvshows.html.twig', [
|
return $this->render('torrentio/tvshows.html.twig', [
|
||||||
'results' => $results,
|
'results' => $results,
|
||||||
|
|||||||
18
src/Torrentio/Action/Command/DeleteCacheCommand.php
Normal file
18
src/Torrentio/Action/Command/DeleteCacheCommand.php
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Torrentio\Action\Command;
|
||||||
|
|
||||||
|
use OneToMany\RichBundle\Contract\CommandInterface;
|
||||||
|
|
||||||
|
class DeleteCacheCommand implements CommandInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public ?string $type = null,
|
||||||
|
public ?string $mediaType = null,
|
||||||
|
public ?string $tmdbId = null,
|
||||||
|
public ?string $imdbId = null,
|
||||||
|
public ?int $season = null,
|
||||||
|
public ?int $episode = null,
|
||||||
|
public ?array $tags = null,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
61
src/Torrentio/Action/Handler/DeleteCacheHandler.php
Normal file
61
src/Torrentio/Action/Handler/DeleteCacheHandler.php
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Torrentio\Action\Handler;
|
||||||
|
|
||||||
|
use Aimeos\Map;
|
||||||
|
use App\Torrentio\Action\Command\DeleteCacheCommand;
|
||||||
|
use App\Torrentio\Action\Result\DeleteCacheResult;
|
||||||
|
use OneToMany\RichBundle\Contract\CommandInterface;
|
||||||
|
use OneToMany\RichBundle\Contract\HandlerInterface;
|
||||||
|
use OneToMany\RichBundle\Contract\ResultInterface;
|
||||||
|
use Symfony\Contracts\Cache\TagAwareCacheInterface;
|
||||||
|
|
||||||
|
/** @implements HandlerInterface<DeleteCacheCommand, DeleteCacheResult> */
|
||||||
|
class DeleteCacheHandler implements HandlerInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly TagAwareCacheInterface $torrentioCache
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function handle(CommandInterface $command): ResultInterface
|
||||||
|
{
|
||||||
|
$input = Map::from((array) $command)
|
||||||
|
->filter(fn ($value, $key) => null !== $value && "" !== $value)
|
||||||
|
;
|
||||||
|
|
||||||
|
$cacheKey = null;
|
||||||
|
if ($input->has('type')) {
|
||||||
|
$cacheKey = $input->get('type');
|
||||||
|
|
||||||
|
if ($input->has('mediaType')) {
|
||||||
|
$cacheKey .= ".".$input->get('mediaType');
|
||||||
|
|
||||||
|
if ($input->has('tmdbId')) {
|
||||||
|
$cacheKey .= ".".$input->get('tmdbId');
|
||||||
|
|
||||||
|
if ($input->has('imdbId')) {
|
||||||
|
$cacheKey .= ".".$input->get('imdbId');
|
||||||
|
|
||||||
|
if ($input->has('season')) {
|
||||||
|
$cacheKey .= ".".$input->get('season');
|
||||||
|
|
||||||
|
if ($input->has('episode')) {
|
||||||
|
$cacheKey .= ".".$input->get('episode');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($cacheKey !== null) {
|
||||||
|
$this->torrentioCache->invalidateTags([$cacheKey]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($input->has('tags')) {
|
||||||
|
$this->torrentioCache->invalidateTags($input->get('tags'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DeleteCacheResult($input, $cacheKey, $command->tags);
|
||||||
|
}
|
||||||
|
}
|
||||||
49
src/Torrentio/Action/Input/DeleteCacheInput.php
Normal file
49
src/Torrentio/Action/Input/DeleteCacheInput.php
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Torrentio\Action\Input;
|
||||||
|
|
||||||
|
use App\Torrentio\Action\Command\DeleteCacheCommand;
|
||||||
|
use OneToMany\RichBundle\Attribute\SourceRequest;
|
||||||
|
use OneToMany\RichBundle\Contract\CommandInterface;
|
||||||
|
use OneToMany\RichBundle\Contract\InputInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @implements DeleteCacheInput<DeleteCacheCommand>
|
||||||
|
*/
|
||||||
|
class DeleteCacheInput implements InputInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
#[SourceRequest('type', nullify: true)]
|
||||||
|
public ?string $type,
|
||||||
|
|
||||||
|
#[SourceRequest('mediaType', nullify: true)]
|
||||||
|
public ?string $mediaType,
|
||||||
|
|
||||||
|
#[SourceRequest('tmdbId', nullify: true)]
|
||||||
|
public ?string $tmdbId,
|
||||||
|
|
||||||
|
#[SourceRequest('imdbId', nullify: true)]
|
||||||
|
public ?string $imdbId,
|
||||||
|
|
||||||
|
#[SourceRequest('season', nullify: true)]
|
||||||
|
public ?int $season,
|
||||||
|
|
||||||
|
#[SourceRequest('episode', nullify: true)]
|
||||||
|
public ?int $episode,
|
||||||
|
|
||||||
|
#[SourceRequest('tags', nullify: true)]
|
||||||
|
public ?array $tags,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function toCommand(): CommandInterface
|
||||||
|
{
|
||||||
|
return new DeleteCacheCommand(
|
||||||
|
type: $this->type,
|
||||||
|
mediaType: $this->mediaType,
|
||||||
|
tmdbId: $this->tmdbId,
|
||||||
|
imdbId: $this->imdbId,
|
||||||
|
season: $this->season,
|
||||||
|
episode: $this->episode
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/Torrentio/Action/Result/DeleteCacheResult.php
Normal file
15
src/Torrentio/Action/Result/DeleteCacheResult.php
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Torrentio\Action\Result;
|
||||||
|
|
||||||
|
use Aimeos\Map;
|
||||||
|
use OneToMany\RichBundle\Contract\ResultInterface;
|
||||||
|
|
||||||
|
class DeleteCacheResult implements ResultInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public Map $result,
|
||||||
|
public ?string $cacheKey = null,
|
||||||
|
public ?array $tags = null,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
21
src/Torrentio/Framework/Controller/ApiController.php
Normal file
21
src/Torrentio/Framework/Controller/ApiController.php
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Torrentio\Framework\Controller;
|
||||||
|
|
||||||
|
use App\Torrentio\Action\Handler\DeleteCacheHandler;
|
||||||
|
use App\Torrentio\Action\Input\DeleteCacheInput;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
|
|
||||||
|
class ApiController extends AbstractController
|
||||||
|
{
|
||||||
|
#[Route('/api/torrentio/cache', name: 'api.torrentio.cache', methods: ['POST'])]
|
||||||
|
public function deleteCache(
|
||||||
|
DeleteCacheInput $deleteCacheInput,
|
||||||
|
DeleteCacheHandler $deleteCacheHandler,
|
||||||
|
): Response {
|
||||||
|
$result = $deleteCacheHandler->handle($deleteCacheInput->toCommand());
|
||||||
|
return $this->json($result, Response::HTTP_OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,12 +9,12 @@
|
|||||||
{% if show_cancel is defined or show_submit is defined %}
|
{% if show_cancel is defined or show_submit is defined %}
|
||||||
<div class="flex justify-end">
|
<div class="flex justify-end">
|
||||||
{% if show_cancel is defined %}
|
{% if show_cancel is defined %}
|
||||||
<button type="button" data-action="dialog#close" class="px-1 py-1 rounded-md self-end w-16 hover:bg-stone-100" autofocus>
|
<button type="button" data-action="dialog#close" class="secondary-btn" autofocus>
|
||||||
{{ cancel_text|default('Cancel') }}
|
{{ cancel_text|default('Cancel') }}
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if show_submit is defined %}
|
{% if show_submit is defined %}
|
||||||
<button type="button" {{ submit_action|raw }} class="px-1 py-1 rounded-md bg-orange-500 self-end text-white w-16 ml-2 hover:bg-orange-600" autofocus>
|
<button type="button" {{ submit_action|raw }} class="primary-btn" autofocus>
|
||||||
{{ submit_text|default('Submit') }}
|
{{ submit_text|default('Submit') }}
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -22,5 +22,5 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
||||||
<button type="button" data-action="dialog#open">{{ button_text|raw }}</button>
|
<button type="button" data-action="dialog#open" class="{{ button_class|default('') }}">{{ button_text|raw }}</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -3,11 +3,15 @@
|
|||||||
{% block h2 %}Preferences{% endblock %}
|
{% block h2 %}Preferences{% endblock %}
|
||||||
|
|
||||||
{% block action_buttons %}
|
{% block action_buttons %}
|
||||||
<button
|
<div {{ stimulus_controller('clear_cache') }}>
|
||||||
class="px-1.5 py-1 my-2 text-white text-sm bg-blue-950 hover:bg-black/80 border-2 border-blue-500/90 rounded-md inline-block"
|
<twig:Modal heading="Hold on a sec!" button_text="Clear Cache" cancel_text="Nope" submit_text="Yep" show_cancel show_submit
|
||||||
>
|
button_class="px-1.5 py-1 my-2 text-white text-sm bg-blue-950 hover:bg-black/80 border-2 border-blue-500/90 rounded-md inline-block"
|
||||||
Clear Cache
|
submit_action="{{ stimulus_action('clear_cache', 'clearAll', 'click') }}"
|
||||||
</button>
|
>
|
||||||
|
This will clear the TMDB, Torrentio, and application cache. Clearing the cache is safe, but may lead to
|
||||||
|
slower page loads and rate limits by Torrentio. Would you like to proceed?
|
||||||
|
</twig:Modal>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
|
|||||||
Reference in New Issue
Block a user