Loading app/Models/MediaModel.php +15 −0 Original line number Diff line number Diff line Loading @@ -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(); Loading app/Resources/icons/home-gear.svg 0 → 100644 +6 −0 Original line number Diff line number Diff line <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> app/Views/Components/Button.php +8 −2 Original line number Diff line number Diff line Loading @@ -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', Loading Loading @@ -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(); } Loading modules/Admin/Config/Routes.php +4 −0 Original line number Diff line number Diff line Loading @@ -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', Loading modules/Admin/Controllers/SettingsController.php +106 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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'); Loading Loading
app/Models/MediaModel.php +15 −0 Original line number Diff line number Diff line Loading @@ -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(); Loading
app/Resources/icons/home-gear.svg 0 → 100644 +6 −0 Original line number Diff line number Diff line <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>
app/Views/Components/Button.php +8 −2 Original line number Diff line number Diff line Loading @@ -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', Loading Loading @@ -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(); } Loading
modules/Admin/Config/Routes.php +4 −0 Original line number Diff line number Diff line Loading @@ -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', Loading
modules/Admin/Controllers/SettingsController.php +106 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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'); Loading