From 89dee41d583e57251ea9315402a757f03571d7ad Mon Sep 17 00:00:00 2001 From: Yassine Doghri <yassine@doghri.fr> Date: Thu, 13 Jan 2022 16:02:14 +0000 Subject: [PATCH] feat: add housekeeping task to run after migrations add run housekeeping button in general settings page --- app/Models/MediaModel.php | 15 +++ app/Resources/icons/home-gear.svg | 6 + app/Views/Components/Button.php | 10 +- modules/Admin/Config/Routes.php | 4 + .../Admin/Controllers/SettingsController.php | 106 ++++++++++++++++++ modules/Admin/Language/en/Settings.php | 6 + modules/Admin/Language/fr/Settings.php | 6 + themes/cp_admin/settings/general.php | 14 +++ 8 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 app/Resources/icons/home-gear.svg diff --git a/app/Models/MediaModel.php b/app/Models/MediaModel.php index 85695c410b..bc61689d23 100644 --- a/app/Models/MediaModel.php +++ b/app/Models/MediaModel.php @@ -145,6 +145,21 @@ class MediaModel extends Model return $this->update($media->id, $media); } + /** + * @return array<mixed> + */ + public function getAllOfType(): array + { + $result = $this->where('type', $this->fileType) + ->findAll(); + $mediaClass = $this->returnType; + foreach ($result as $key => $media) { + $result[$key] = new $mediaClass($media->toArray(false, true)); + } + + return $result; + } + public function deleteMedia(object $media): bool { $media->deleteFile(); diff --git a/app/Resources/icons/home-gear.svg b/app/Resources/icons/home-gear.svg new file mode 100644 index 0000000000..2504da6dd9 --- /dev/null +++ b/app/Resources/icons/home-gear.svg @@ -0,0 +1,6 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <g> + <path fill="none" d="M0 0h24v24H0z"/> + <path d="M20 20a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-9H1l10.327-9.388a1 1 0 0 1 1.346 0L23 11h-3v9zM8.592 13.808l-.991.572 1 1.733.993-.573a3.5 3.5 0 0 0 1.405.811v1.145h2.002V16.35a3.5 3.5 0 0 0 1.405-.81l.992.572L16.4 14.38l-.991-.572a3.504 3.504 0 0 0 0-1.62l.991-.573-1-1.733-.993.573A3.5 3.5 0 0 0 13 9.645V8.5h-2.002v1.144a3.5 3.5 0 0 0-1.405.811l-.992-.573L7.6 11.616l.991.572a3.504 3.504 0 0 0 0 1.62zm3.408.69a1.5 1.5 0 1 1-.002-3.001 1.5 1.5 0 0 1 .002 3z"/> + </g> +</svg> diff --git a/app/Views/Components/Button.php b/app/Views/Components/Button.php index 651dcd4882..79c96ac5fd 100644 --- a/app/Views/Components/Button.php +++ b/app/Views/Components/Button.php @@ -46,6 +46,12 @@ class Button extends Component 'large' => 'text-base leading-6', ]; + $iconSize = [ + 'small' => 'text-sm', + 'base' => 'text-lg', + 'large' => 'text-2xl', + ]; + $basePaddings = [ 'small' => 'px-3 py-1', 'base' => 'px-3 py-2', @@ -77,14 +83,14 @@ class Button extends Component if ($this->iconLeft !== '') { $this->slot = (new Icon([ 'glyph' => $this->iconLeft, - 'class' => 'mr-2 opacity-75', + 'class' => 'mr-2 opacity-75' . ' ' . $iconSize[$this->size], ]))->render() . $this->slot; } if ($this->iconRight !== '') { $this->slot .= (new Icon([ 'glyph' => $this->iconRight, - 'class' => 'ml-2 opacity-75', + 'class' => 'ml-2 opacity-75' . ' ' . $iconSize[$this->size], ]))->render(); } diff --git a/modules/Admin/Config/Routes.php b/modules/Admin/Config/Routes.php index c22fba6998..b263686ee7 100644 --- a/modules/Admin/Config/Routes.php +++ b/modules/Admin/Config/Routes.php @@ -40,6 +40,10 @@ $routes->group( 'as' => 'settings-images-regenerate', 'filter' => 'permission:settings-manage', ]); + $routes->post('instance-housekeeping-run', 'SettingsController::runHousekeeping', [ + 'as' => 'settings-housekeeping-run', + 'filter' => 'permission:settings-manage', + ]); $routes->get('theme', 'SettingsController::theme', [ 'as' => 'settings-theme', 'filter' => 'permission:settings-manage', diff --git a/modules/Admin/Controllers/SettingsController.php b/modules/Admin/Controllers/SettingsController.php index 7f91371bbf..879d5d4376 100644 --- a/modules/Admin/Controllers/SettingsController.php +++ b/modules/Admin/Controllers/SettingsController.php @@ -10,8 +10,12 @@ declare(strict_types=1); namespace Modules\Admin\Controllers; +use App\Entities\Media\Image; +use App\Models\ActorModel; +use App\Models\MediaModel; use App\Models\PersonModel; use App\Models\PodcastModel; +use CodeIgniter\Files\File; use CodeIgniter\HTTP\RedirectResponse; use PHP_ICO; @@ -156,6 +160,108 @@ class SettingsController extends BaseController return redirect('settings-general')->with('message', lang('Settings.images.regenerationSuccess')); } + public function runHousekeeping(): RedirectResponse + { + helper('media'); + + // Delete all podcast image sizes to recreate them + $allPodcasts = (new PodcastModel())->findAll(); + foreach ($allPodcasts as $podcast) { + $podcastImages = glob( + ROOTPATH . 'public/' . config('App')->mediaRoot . "/podcasts/{$podcast->handle}/*_*{jpg,png,webp}", + GLOB_BRACE + ); + + if ($podcastImages) { + foreach ($podcastImages as $podcastImage) { + if (is_file($podcastImage)) { + unlink($podcastImage); + } + } + } + } + + // Delete all person image sizes to recreate them + $personsImages = glob( + ROOTPATH . 'public/' . config('App')->mediaRoot . '/persons/*_*{jpg,png,webp}', + GLOB_BRACE + ); + if ($personsImages) { + foreach ($personsImages as $personsImage) { + if (is_file($personsImage)) { + unlink($personsImage); + } + } + } + + $allImages = (new MediaModel('image'))->getAllOfType(); + foreach ($allImages as $image) { + if (str_starts_with($image->file_path, 'podcasts')) { + if (str_ends_with($image->file_path, 'banner.jpg') || str_ends_with($image->file_path, 'banner.png')) { + $image->sizes = config('Images') + ->podcastBannerSizes; + } else { + $image->sizes = config('Images') + ->podcastCoverSizes; + } + } elseif (str_starts_with($image->file_path, 'persons')) { + $image->sizes = config('Images') + ->personAvatarSizes; + } + $image->setFile(new File(media_path($image->file_path))); + + (new MediaModel('image'))->updateMedia($image); + } + + $allAudio = (new MediaModel('audio'))->getAllOfType(); + foreach ($allAudio as $audio) { + $audio->setFile(new File(media_path($audio->file_path))); + + (new MediaModel('audio'))->updateMedia($audio); + } + + $allTranscripts = (new MediaModel('transcript'))->getAllOfType(); + foreach ($allTranscripts as $transcript) { + $transcript->setFile(new File(media_path($transcript->file_path))); + + (new MediaModel('transcript'))->updateMedia($transcript); + } + + $allChapters = (new MediaModel('chapters'))->getAllOfType(); + foreach ($allChapters as $chapters) { + $chapters->setFile(new File(media_path($chapters->file_path))); + + (new MediaModel('chapters'))->updateMedia($chapters); + } + + $allVideos = (new MediaModel('video'))->getAllOfType(); + foreach ($allVideos as $video) { + $video->setFile(new File(media_path($video->file_path))); + + (new MediaModel('video'))->updateMedia($video); + } + + // reset avatar and banner image urls for each podcast actor + foreach ($allPodcasts as $podcast) { + $actorModel = new ActorModel(); + $actor = $actorModel->getActorById($podcast->actor_id); + + if ($actor !== null) { + // update values + $actor->avatar_image_url = $podcast->cover->federation_url; + $actor->avatar_image_mimetype = $podcast->cover->file_mimetype; + $actor->cover_image_url = $podcast->banner->federation_url; + $actor->cover_image_mimetype = $podcast->banner->file_mimetype; + + if ($actor->hasChanged()) { + $actorModel->update($actor->id, $actor); + } + } + } + + return redirect('settings-general')->with('message', lang('Settings.housekeeping.runSuccess')); + } + public function theme(): string { helper('form'); diff --git a/modules/Admin/Language/en/Settings.php b/modules/Admin/Language/en/Settings.php index 48580a5e88..8d0ece529e 100644 --- a/modules/Admin/Language/en/Settings.php +++ b/modules/Admin/Language/en/Settings.php @@ -28,6 +28,12 @@ return [ 'regenerate' => 'Regenerate images', 'regenerationSuccess' => 'All images have been regenerated successfully!', ], + 'housekeeping' => [ + 'title' => 'Housekeeping', + 'subtitle' => 'Runs various housekeeping tasks, such as rewriting media files metadata (images, audio files, transcripts, chapters, …).', + 'run' => 'Run housekeeping', + 'runSuccess' => 'Housekeeping has been run successfully!', + ], 'theme' => [ 'title' => 'Theme', 'accent_section_title' => 'Accent color', diff --git a/modules/Admin/Language/fr/Settings.php b/modules/Admin/Language/fr/Settings.php index 6c7dece2d5..0d0fe8df0f 100644 --- a/modules/Admin/Language/fr/Settings.php +++ b/modules/Admin/Language/fr/Settings.php @@ -28,6 +28,12 @@ return [ 'regenerate' => 'Regénérer les images', 'regenerationSuccess' => 'Toutes les images ont été regénérés avec succès !', ], + 'housekeeping' => [ + 'title' => 'Ménage', + 'subtitle' => 'Exécute un nombre de tâches de nettoyage, comme la réécriture de métadonnées des fichiers media (images, fichiers audio, transcript, chapitres, …).', + 'run' => 'Faire le ménage', + 'runSuccess' => 'Le ménage a été effectué avec succès !', + ], 'theme' => [ 'title' => 'Thème', 'accent_section_title' => 'Couleur d’accentuation', diff --git a/themes/cp_admin/settings/general.php b/themes/cp_admin/settings/general.php index 26c8e86d9b..bd806aa240 100644 --- a/themes/cp_admin/settings/general.php +++ b/themes/cp_admin/settings/general.php @@ -69,6 +69,20 @@ </Forms.Section> </form> + +<form action="<?= route_to('settings-housekeeping-run') ?>" method="POST" class="flex flex-col max-w-xl gap-y-4"> +<?= csrf_field() ?> + +<Forms.Section + title="<?= lang('Settings.housekeeping.title') ?>" + subtitle="<?= lang('Settings.housekeeping.subtitle') ?>" > + + <Button variant="primary" type="submit" iconLeft="home-gear"><?= lang('Settings.housekeeping.run') ?></Button> + +</Forms.Section> + +</form> + </div> <?= $this->endSection() ?> -- GitLab