refactor: rename controller methods for views and actions to be more consistent

add PermalinkEditor component
This commit is contained in:
Yassine Doghri 2024-12-18 16:05:25 +00:00
parent 8cf9c6dc83
commit 85704bfbe0
48 changed files with 788 additions and 836 deletions

View File

@ -161,7 +161,7 @@ $routes->group('@(:podcastHandle)', static function ($routes): void {
$routes->get('comments/(:uuid)/replies', 'EpisodeCommentController::replies/$1/$2/$3', [ $routes->get('comments/(:uuid)/replies', 'EpisodeCommentController::replies/$1/$2/$3', [
'as' => 'episode-comment-replies', 'as' => 'episode-comment-replies',
]); ]);
$routes->post('comments/(:uuid)/like', 'EpisodeCommentController::attemptLike/$1/$2/$3', [ $routes->post('comments/(:uuid)/like', 'EpisodeCommentController::likeAction/$1/$2/$3', [
'as' => 'episode-comment-attempt-like', 'as' => 'episode-comment-attempt-like',
]); ]);
$routes->get('oembed.json', 'EpisodeController::oembedJSON/$1/$2', [ $routes->get('oembed.json', 'EpisodeController::oembedJSON/$1/$2', [
@ -229,7 +229,7 @@ $routes->get('/pages/(:slug)', 'PageController::index/$1', [
* Overwriting Fediverse routes file * Overwriting Fediverse routes file
*/ */
$routes->group('@(:podcastHandle)', static function ($routes): void { $routes->group('@(:podcastHandle)', static function ($routes): void {
$routes->post('posts/new', 'PostController::attemptCreate/$1', [ $routes->post('posts/new', 'PostController::createAction/$1', [
'as' => 'post-attempt-create', 'as' => 'post-attempt-create',
'filter' => 'permission:podcast$1.manage-publications', 'filter' => 'permission:podcast$1.manage-publications',
]); ]);
@ -266,13 +266,13 @@ $routes->group('@(:podcastHandle)', static function ($routes): void {
'filter' => 'allow-cors', 'filter' => 'allow-cors',
]); ]);
// Actions // Actions
$routes->post('action', 'PostController::attemptAction/$1/$2', [ $routes->post('action', 'PostController::actionAction/$1/$2', [
'as' => 'post-attempt-action', 'as' => 'post-attempt-action',
'filter' => 'permission:podcast$1.interact-as', 'filter' => 'permission:podcast$1.interact-as',
]); ]);
$routes->post( $routes->post(
'block-actor', 'block-actor',
'PostController::attemptBlockActor/$1/$2', 'PostController::blockActorAction/$1/$2',
[ [
'as' => 'post-attempt-block-actor', 'as' => 'post-attempt-block-actor',
'filter' => 'permission:fediverse.manage-blocks', 'filter' => 'permission:fediverse.manage-blocks',
@ -280,13 +280,13 @@ $routes->group('@(:podcastHandle)', static function ($routes): void {
); );
$routes->post( $routes->post(
'block-domain', 'block-domain',
'PostController::attemptBlockDomain/$1/$2', 'PostController::blockDomainAction/$1/$2',
[ [
'as' => 'post-attempt-block-domain', 'as' => 'post-attempt-block-domain',
'filter' => 'permission:fediverse.manage-blocks', 'filter' => 'permission:fediverse.manage-blocks',
], ],
); );
$routes->post('delete', 'PostController::attemptDelete/$1/$2', [ $routes->post('delete', 'PostController::deleteAction/$1/$2', [
'as' => 'post-attempt-delete', 'as' => 'post-attempt-delete',
'filter' => 'permission:podcast$1.manage-publications', 'filter' => 'permission:podcast$1.manage-publications',
]); ]);

View File

@ -22,13 +22,10 @@ class ActorController extends FediverseActorController
*/ */
protected $helpers = ['svg', 'components', 'misc', 'seo']; protected $helpers = ['svg', 'components', 'misc', 'seo'];
public function follow(): string public function followView(): string
{ {
// Prevent analytics hit when authenticated // @phpstan-ignore-next-line
if (! auth()->loggedIn()) { $this->registerPodcastWebpageHit($this->actor->podcast->id);
// @phpstan-ignore-next-line
$this->registerPodcastWebpageHit($this->actor->podcast->id);
}
helper(['form', 'components', 'svg']); helper(['form', 'components', 'svg']);
// @phpstan-ignore-next-line // @phpstan-ignore-next-line

View File

@ -5,9 +5,7 @@ declare(strict_types=1);
namespace App\Controllers; namespace App\Controllers;
use CodeIgniter\Controller; use CodeIgniter\Controller;
use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\Response;
use CodeIgniter\HTTP\ResponseInterface; use CodeIgniter\HTTP\ResponseInterface;
use Override; use Override;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
@ -21,20 +19,6 @@ use ViewThemes\Theme;
*/ */
abstract class BaseController extends Controller abstract class BaseController extends Controller
{ {
/**
* Instance of the main Request object.
*
* @var IncomingRequest
*/
protected $request;
/**
* Instance of the main response object.
*
* @var Response
*/
protected $response;
/** /**
* An array of helpers to be loaded automatically upon * An array of helpers to be loaded automatically upon
* class instantiation. These helpers will be available * class instantiation. These helpers will be available

View File

@ -11,18 +11,11 @@ declare(strict_types=1);
namespace App\Controllers; namespace App\Controllers;
use CodeIgniter\Controller; use CodeIgniter\Controller;
use CodeIgniter\HTTP\Response; use CodeIgniter\HTTP\ResponseInterface;
class ColorsController extends Controller class ColorsController extends Controller
{ {
/** public function index(): ResponseInterface
* Instance of the main response object.
*
* @var Response
*/
protected $response;
public function index(): Response
{ {
$cacheName = 'colors.css'; $cacheName = 'colors.css';
if ( if (

View File

@ -16,7 +16,6 @@ use App\Models\EpisodeModel;
use App\Models\PodcastModel; use App\Models\PodcastModel;
use CodeIgniter\Controller; use CodeIgniter\Controller;
use CodeIgniter\Exceptions\PageNotFoundException; use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface; use CodeIgniter\HTTP\ResponseInterface;
@ -30,13 +29,6 @@ use Psr\Log\LoggerInterface;
class EpisodeAudioController extends Controller class EpisodeAudioController extends Controller
{ {
/**
* Instance of the main Request object.
*
* @var IncomingRequest
*/
protected $request;
/** /**
* An array of helpers to be loaded automatically upon class instantiation. These helpers will be available to all * An array of helpers to be loaded automatically upon class instantiation. These helpers will be available to all
* other controllers that extend Analytics. * other controllers that extend Analytics.

View File

@ -19,7 +19,7 @@ use App\Models\EpisodeModel;
use App\Models\PodcastModel; use App\Models\PodcastModel;
use CodeIgniter\Exceptions\PageNotFoundException; use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\Response; use CodeIgniter\HTTP\ResponseInterface;
use Modules\Analytics\AnalyticsTrait; use Modules\Analytics\AnalyticsTrait;
use Modules\Fediverse\Entities\Actor; use Modules\Fediverse\Entities\Actor;
use Modules\Fediverse\Objects\OrderedCollectionObject; use Modules\Fediverse\Objects\OrderedCollectionObject;
@ -77,10 +77,7 @@ class EpisodeCommentController extends BaseController
public function view(): string public function view(): string
{ {
// Prevent analytics hit when authenticated $this->registerPodcastWebpageHit($this->podcast->id);
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->podcast->id);
}
$cacheName = implode( $cacheName = implode(
'_', '_',
@ -119,7 +116,7 @@ class EpisodeCommentController extends BaseController
return $cachedView; return $cachedView;
} }
public function commentObject(): Response public function commentObject(): ResponseInterface
{ {
$commentObject = new CommentObject($this->comment); $commentObject = new CommentObject($this->comment);
@ -128,7 +125,7 @@ class EpisodeCommentController extends BaseController
->setBody($commentObject->toJSON()); ->setBody($commentObject->toJSON());
} }
public function replies(): Response public function replies(): ResponseInterface
{ {
/** /**
* get comment replies * get comment replies
@ -163,7 +160,7 @@ class EpisodeCommentController extends BaseController
->setBody($collection->toJSON()); ->setBody($collection->toJSON());
} }
public function attemptLike(): RedirectResponse public function likeAction(): RedirectResponse
{ {
if (! ($interactAsActor = interact_as_actor()) instanceof Actor) { if (! ($interactAsActor = interact_as_actor()) instanceof Actor) {
return redirect()->back(); return redirect()->back();
@ -175,7 +172,7 @@ class EpisodeCommentController extends BaseController
return redirect()->back(); return redirect()->back();
} }
public function attemptReply(): RedirectResponse public function replyAction(): RedirectResponse
{ {
if (! ($interactAsActor = interact_as_actor()) instanceof Actor) { if (! ($interactAsActor = interact_as_actor()) instanceof Actor) {
return redirect()->back(); return redirect()->back();

View File

@ -18,7 +18,6 @@ use App\Models\EpisodeModel;
use App\Models\PodcastModel; use App\Models\PodcastModel;
use CodeIgniter\Database\BaseBuilder; use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Exceptions\PageNotFoundException; use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\Response;
use CodeIgniter\HTTP\ResponseInterface; use CodeIgniter\HTTP\ResponseInterface;
use Config\Embed; use Config\Embed;
use Config\Services; use Config\Services;
@ -66,10 +65,7 @@ class EpisodeController extends BaseController
public function index(): string public function index(): string
{ {
// Prevent analytics hit when authenticated $this->registerPodcastWebpageHit($this->episode->podcast_id);
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->episode->podcast_id);
}
$cacheName = implode( $cacheName = implode(
'_', '_',
@ -114,10 +110,7 @@ class EpisodeController extends BaseController
public function activity(): string public function activity(): string
{ {
// Prevent analytics hit when authenticated $this->registerPodcastWebpageHit($this->episode->podcast_id);
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->episode->podcast_id);
}
$cacheName = implode( $cacheName = implode(
'_', '_',
@ -163,10 +156,7 @@ class EpisodeController extends BaseController
public function chapters(): string public function chapters(): string
{ {
// Prevent analytics hit when authenticated $this->registerPodcastWebpageHit($this->episode->podcast_id);
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->episode->podcast_id);
}
$cacheName = implode( $cacheName = implode(
'_', '_',
@ -222,10 +212,7 @@ class EpisodeController extends BaseController
public function transcript(): string public function transcript(): string
{ {
// Prevent analytics hit when authenticated $this->registerPodcastWebpageHit($this->episode->podcast_id);
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->episode->podcast_id);
}
$cacheName = implode( $cacheName = implode(
'_', '_',
@ -288,10 +275,7 @@ class EpisodeController extends BaseController
{ {
header('Content-Security-Policy: frame-ancestors http://*:* https://*:*'); header('Content-Security-Policy: frame-ancestors http://*:* https://*:*');
// Prevent analytics hit when authenticated $this->registerPodcastWebpageHit($this->episode->podcast_id);
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->episode->podcast_id);
}
$session = Services::session(); $session = Services::session();
@ -393,7 +377,7 @@ class EpisodeController extends BaseController
return $this->response->setXML($oembed); return $this->response->setXML($oembed);
} }
public function episodeObject(): Response public function episodeObject(): ResponseInterface
{ {
$podcastObject = new PodcastEpisode($this->episode); $podcastObject = new PodcastEpisode($this->episode);
@ -402,7 +386,7 @@ class EpisodeController extends BaseController
->setBody($podcastObject->toJSON()); ->setBody($podcastObject->toJSON());
} }
public function comments(): Response public function comments(): ResponseInterface
{ {
/** /**
* get comments: aggregated replies from posts referring to the episode * get comments: aggregated replies from posts referring to the episode

View File

@ -17,7 +17,7 @@ use App\Models\EpisodeModel;
use App\Models\PodcastModel; use App\Models\PodcastModel;
use App\Models\PostModel; use App\Models\PostModel;
use CodeIgniter\Exceptions\PageNotFoundException; use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\Response; use CodeIgniter\HTTP\ResponseInterface;
use Modules\Analytics\AnalyticsTrait; use Modules\Analytics\AnalyticsTrait;
use Modules\Fediverse\Objects\OrderedCollectionObject; use Modules\Fediverse\Objects\OrderedCollectionObject;
use Modules\Fediverse\Objects\OrderedCollectionPage; use Modules\Fediverse\Objects\OrderedCollectionPage;
@ -47,7 +47,7 @@ class PodcastController extends BaseController
return $this->{$method}(...$params); return $this->{$method}(...$params);
} }
public function podcastActor(): Response public function podcastActor(): ResponseInterface
{ {
$podcastActor = new PodcastActor($this->podcast); $podcastActor = new PodcastActor($this->podcast);
@ -58,10 +58,7 @@ class PodcastController extends BaseController
public function activity(): string public function activity(): string
{ {
// Prevent analytics hit when authenticated $this->registerPodcastWebpageHit($this->podcast->id);
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->podcast->id);
}
$cacheName = implode( $cacheName = implode(
'_', '_',
@ -106,10 +103,7 @@ class PodcastController extends BaseController
public function about(): string public function about(): string
{ {
// Prevent analytics hit when authenticated $this->registerPodcastWebpageHit($this->podcast->id);
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->podcast->id);
}
$cacheName = implode( $cacheName = implode(
'_', '_',
@ -156,10 +150,7 @@ class PodcastController extends BaseController
public function episodes(): string public function episodes(): string
{ {
// Prevent analytics hit when authenticated $this->registerPodcastWebpageHit($this->podcast->id);
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->podcast->id);
}
$yearQuery = $this->request->getGet('year'); $yearQuery = $this->request->getGet('year');
$seasonQuery = $this->request->getGet('season'); $seasonQuery = $this->request->getGet('season');
@ -274,7 +265,7 @@ class PodcastController extends BaseController
return $cachedView; return $cachedView;
} }
public function episodeCollection(): Response public function episodeCollection(): ResponseInterface
{ {
if ($this->podcast->type === 'serial') { if ($this->podcast->type === 'serial') {
// podcast is serial // podcast is serial

View File

@ -75,10 +75,7 @@ class PostController extends FediversePostController
public function view(): string public function view(): string
{ {
// Prevent analytics hit when authenticated $this->registerPodcastWebpageHit($this->podcast->id);
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->podcast->id);
}
$cacheName = implode( $cacheName = implode(
'_', '_',
@ -115,7 +112,7 @@ class PostController extends FediversePostController
} }
#[Override] #[Override]
public function attemptCreate(): RedirectResponse public function createAction(): RedirectResponse
{ {
$rules = [ $rules = [
'message' => 'required|max_length[500]', 'message' => 'required|max_length[500]',
@ -167,7 +164,7 @@ class PostController extends FediversePostController
} }
#[Override] #[Override]
public function attemptReply(): RedirectResponse public function replyAction(): RedirectResponse
{ {
$rules = [ $rules = [
'message' => 'required|max_length[500]', 'message' => 'required|max_length[500]',
@ -207,7 +204,7 @@ class PostController extends FediversePostController
} }
#[Override] #[Override]
public function attemptFavourite(): RedirectResponse public function favouriteAction(): RedirectResponse
{ {
model('FavouriteModel')->toggleFavourite(interact_as_actor(), $this->post); model('FavouriteModel')->toggleFavourite(interact_as_actor(), $this->post);
@ -215,14 +212,14 @@ class PostController extends FediversePostController
} }
#[Override] #[Override]
public function attemptReblog(): RedirectResponse public function reblogAction(): RedirectResponse
{ {
(new PostModel())->toggleReblog(interact_as_actor(), $this->post); (new PostModel())->toggleReblog(interact_as_actor(), $this->post);
return redirect()->back(); return redirect()->back();
} }
public function attemptAction(): RedirectResponse public function action(): RedirectResponse
{ {
$rules = [ $rules = [
'action' => 'required|in_list[favourite,reblog,reply]', 'action' => 'required|in_list[favourite,reblog,reply]',
@ -239,9 +236,9 @@ class PostController extends FediversePostController
$action = $validData['action']; $action = $validData['action'];
return match ($action) { return match ($action) {
'favourite' => $this->attemptFavourite(), 'favourite' => $this->favouriteAction(),
'reblog' => $this->attemptReblog(), 'reblog' => $this->reblogAction(),
'reply' => $this->attemptReply(), 'reply' => $this->replyAction(),
default => redirect() default => redirect()
->back() ->back()
->withInput() ->withInput()
@ -249,12 +246,9 @@ class PostController extends FediversePostController
}; };
} }
public function remoteAction(string $action): string public function remoteActionView(string $action): string
{ {
// Prevent analytics hit when authenticated $this->registerPodcastWebpageHit($this->podcast->id);
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->podcast->id);
}
set_remote_actions_metatags($this->post, $action); set_remote_actions_metatags($this->post, $action);
$data = [ $data = [

View File

@ -178,9 +178,8 @@ class PersonModel extends Model
foreach ($personsTaxonomy as $group_key => $group) { foreach ($personsTaxonomy as $group_key => $group) {
foreach ($group['roles'] as $role_key => $role) { foreach ($group['roles'] as $role_key => $role) {
$options[] = [ $options[] = [
'value' => "{$group_key}, 'value' => sprintf('%s,%s', $group_key, $role_key),
{$role_key}", 'label' => sprintf('%s %s', $group['label'], $role['label']),
'label' => "{$group['label']} {$role['label']}",
]; ];
} }
} }

View File

@ -72,6 +72,8 @@ export class PermalinkEdit extends LitElement {
} }
firstUpdated(): void { firstUpdated(): void {
console.log(this._slugInput);
this.permalinkBase += this.permalinkBase.endsWith("/") ? "" : "/"; this.permalinkBase += this.permalinkBase.endsWith("/") ? "" : "/";
// set permalink value // set permalink value
@ -145,7 +147,7 @@ export class PermalinkEdit extends LitElement {
border-color: transparent !important; border-color: transparent !important;
padding-left: 0 !important; padding-left: 0 !important;
margin-left: -0.25rem !important; margin-left: -0.25rem !important;
font-weight: 600; font-weight: 600 !important;
} }
::slotted([slot="domain"]) { ::slotted([slot="domain"]) {

View File

@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
namespace App\Views\Components\Forms;
use Override;
class PermalinkEditor extends FormComponent
{
protected array $props = ['label', 'prefix', 'permalinkBase'];
protected string $label = '';
protected string $prefix = '';
protected string $permalinkBase = '';
#[Override]
public function render(): string
{
$this->mergeClass('flex-1 text-xs border-contrast rounded-lg focus:border-contrast border-3 focus-within:ring-accent');
$this->attributes['slot'] = 'slug-input';
$input = form_input($this->attributes, old($this->name, (string) $this->value));
$editLabel = lang('Common.edit');
$copyLabel = lang('Common.copy');
$copiedLabel = lang('Common.copied');
return <<<HTML
<div>
<x-Forms.Label for="{$this->id}">{$this->label}</x-Forms.Label>
<permalink-edit class="inline-flex items-center w-full text-xs" edit-label="{$editLabel}" copy-label="{$copyLabel}" copied-label="{$copiedLabel}" permalink-base="{$this->permalinkBase}">
<span slot="domain">{$this->prefix}</span>
{$input}
</permalink-edit>
</div>
HTML;
}
}

View File

@ -29,41 +29,41 @@ $routes->group(
'as' => 'settings-general', 'as' => 'settings-general',
'filter' => 'permission:admin.settings', 'filter' => 'permission:admin.settings',
]); ]);
$routes->post('instance', 'SettingsController::attemptInstanceEdit', [ $routes->post('instance', 'SettingsController::instanceEditAction', [
'as' => 'settings-instance', 'as' => 'settings-instance',
'filter' => 'permission:admin.settings', 'filter' => 'permission:admin.settings',
]); ]);
$routes->get('instance-delete-icon', 'SettingsController::deleteIcon', [ $routes->get('instance-delete-icon', 'SettingsController::deleteIconAction', [
'as' => 'settings-instance-delete-icon', 'as' => 'settings-instance-delete-icon',
'filter' => 'permission:admin.settings', 'filter' => 'permission:admin.settings',
]); ]);
$routes->post('instance-images-regenerate', 'SettingsController::regenerateImages', [ $routes->post('instance-images-regenerate', 'SettingsController::regenerateImagesAction', [
'as' => 'settings-images-regenerate', 'as' => 'settings-images-regenerate',
'filter' => 'permission:admin.settings', 'filter' => 'permission:admin.settings',
]); ]);
$routes->post('instance-housekeeping-run', 'SettingsController::runHousekeeping', [ $routes->post('instance-housekeeping-run', 'SettingsController::housekeepingAction', [
'as' => 'settings-housekeeping-run', 'as' => 'settings-housekeeping-run',
'filter' => 'permission:admin.settings', 'filter' => 'permission:admin.settings',
]); ]);
$routes->get('theme', 'SettingsController::theme', [ $routes->get('theme', 'SettingsController::themeView', [
'as' => 'settings-theme', 'as' => 'settings-theme',
'filter' => 'permission:admin.settings', 'filter' => 'permission:admin.settings',
]); ]);
$routes->post('theme', 'SettingsController::attemptSetInstanceTheme', [ $routes->post('theme', 'SettingsController::themeAction', [
'as' => 'settings-theme', 'as' => 'settings-theme',
'filter' => 'permission:admin.settings', 'filter' => 'permission:admin.settings',
]); ]);
}); });
$routes->group('persons', static function ($routes): void { $routes->group('persons', static function ($routes): void {
$routes->get('/', 'PersonController', [ $routes->get('/', 'PersonController::list', [
'as' => 'person-list', 'as' => 'person-list',
'filter' => 'permission:persons.manage', 'filter' => 'permission:persons.manage',
]); ]);
$routes->get('new', 'PersonController::create', [ $routes->get('new', 'PersonController::createView', [
'as' => 'person-create', 'as' => 'person-create',
'filter' => 'permission:persons.manage', 'filter' => 'permission:persons.manage',
]); ]);
$routes->post('new', 'PersonController::attemptCreate', [ $routes->post('new', 'PersonController::createAction', [
'filter' => 'permission:persons.manage', 'filter' => 'permission:persons.manage',
]); ]);
$routes->group('(:num)', static function ($routes): void { $routes->group('(:num)', static function ($routes): void {
@ -71,14 +71,14 @@ $routes->group(
'as' => 'person-view', 'as' => 'person-view',
'filter' => 'permission:persons.manage', 'filter' => 'permission:persons.manage',
]); ]);
$routes->get('edit', 'PersonController::edit/$1', [ $routes->get('edit', 'PersonController::editView/$1', [
'as' => 'person-edit', 'as' => 'person-edit',
'filter' => 'permission:persons.manage', 'filter' => 'permission:persons.manage',
]); ]);
$routes->post('edit', 'PersonController::attemptEdit/$1', [ $routes->post('edit', 'PersonController::editAction/$1', [
'filter' => 'permission:persons.manage', 'filter' => 'permission:persons.manage',
]); ]);
$routes->add('delete', 'PersonController::delete/$1', [ $routes->add('delete', 'PersonController::deleteAction/$1', [
'as' => 'person-delete', 'as' => 'person-delete',
'filter' => 'permission:persons.manage', 'filter' => 'permission:persons.manage',
]); ]);
@ -89,11 +89,11 @@ $routes->group(
$routes->get('/', 'PodcastController::list', [ $routes->get('/', 'PodcastController::list', [
'as' => 'podcast-list', 'as' => 'podcast-list',
]); ]);
$routes->get('new', 'PodcastController::create', [ $routes->get('new', 'PodcastController::createView', [
'as' => 'podcast-create', 'as' => 'podcast-create',
'filter' => 'permission:podcasts.create', 'filter' => 'permission:podcasts.create',
]); ]);
$routes->post('new', 'PodcastController::attemptCreate', [ $routes->post('new', 'PodcastController::createAction', [
'filter' => 'permission:podcasts.create', 'filter' => 'permission:podcasts.create',
]); ]);
// Podcast // Podcast
@ -103,16 +103,16 @@ $routes->group(
'as' => 'podcast-view', 'as' => 'podcast-view',
'filter' => 'permission:podcast$1.view', 'filter' => 'permission:podcast$1.view',
]); ]);
$routes->get('edit', 'PodcastController::edit/$1', [ $routes->get('edit', 'PodcastController::editView/$1', [
'as' => 'podcast-edit', 'as' => 'podcast-edit',
'filter' => 'permission:podcast$1.edit', 'filter' => 'permission:podcast$1.edit',
]); ]);
$routes->post('edit', 'PodcastController::attemptEdit/$1', [ $routes->post('edit', 'PodcastController::editAction/$1', [
'filter' => 'permission:podcast$1.edit', 'filter' => 'permission:podcast$1.edit',
]); ]);
$routes->get( $routes->get(
'publish', 'publish',
'PodcastController::publish/$1', 'PodcastController::publishView/$1',
[ [
'as' => 'podcast-publish', 'as' => 'podcast-publish',
'filter' => 'permission:podcast$1.manage-publications', 'filter' => 'permission:podcast$1.manage-publications',
@ -120,14 +120,14 @@ $routes->group(
); );
$routes->post( $routes->post(
'publish', 'publish',
'PodcastController::attemptPublish/$1', 'PodcastController::publishAction/$1',
[ [
'filter' => 'permission:podcast$1.manage-publications', 'filter' => 'permission:podcast$1.manage-publications',
], ],
); );
$routes->get( $routes->get(
'publish-edit', 'publish-edit',
'PodcastController::publishEdit/$1', 'PodcastController::publishEditView/$1',
[ [
'as' => 'podcast-publish_edit', 'as' => 'podcast-publish_edit',
'filter' => 'permission:podcast$1.manage-publications', 'filter' => 'permission:podcast$1.manage-publications',
@ -135,28 +135,28 @@ $routes->group(
); );
$routes->post( $routes->post(
'publish-edit', 'publish-edit',
'PodcastController::attemptPublishEdit/$1', 'PodcastController::publishEditAction/$1',
[ [
'filter' => 'permission:podcast$1.manage-publications', 'filter' => 'permission:podcast$1.manage-publications',
], ],
); );
$routes->get( $routes->get(
'publish-cancel', 'publish-cancel',
'PodcastController::publishCancel/$1', 'PodcastController::publishCancelAction/$1',
[ [
'as' => 'podcast-publish-cancel', 'as' => 'podcast-publish-cancel',
'filter' => 'permission:podcast$1.manage-publications', 'filter' => 'permission:podcast$1.manage-publications',
], ],
); );
$routes->get('edit/delete-banner', 'PodcastController::deleteBanner/$1', [ $routes->get('edit/delete-banner', 'PodcastController::deleteBannerAction/$1', [
'as' => 'podcast-banner-delete', 'as' => 'podcast-banner-delete',
'filter' => 'permission:podcast$1.edit', 'filter' => 'permission:podcast$1.edit',
]); ]);
$routes->get('delete', 'PodcastController::delete/$1', [ $routes->get('delete', 'PodcastController::deleteView/$1', [
'as' => 'podcast-delete', 'as' => 'podcast-delete',
'filter' => 'permission:podcast$1.delete', 'filter' => 'permission:podcast$1.delete',
]); ]);
$routes->post('delete', 'PodcastController::attemptDelete/$1', [ $routes->post('delete', 'PodcastController::deleteAction/$1', [
'filter' => 'permission:podcast$1.delete', 'filter' => 'permission:podcast$1.delete',
]); ]);
$routes->group('persons', static function ($routes): void { $routes->group('persons', static function ($routes): void {
@ -166,14 +166,14 @@ $routes->group(
]); ]);
$routes->post( $routes->post(
'/', '/',
'PodcastPersonController::attemptCreate/$1', 'PodcastPersonController::createAction/$1',
[ [
'filter' => 'permission:podcast$1.manage-persons', 'filter' => 'permission:podcast$1.manage-persons',
], ],
); );
$routes->get( $routes->get(
'(:num)/remove', '(:num)/remove',
'PodcastPersonController::remove/$1/$2', 'PodcastPersonController::deleteAction/$1/$2',
[ [
'as' => 'podcast-person-remove', 'as' => 'podcast-person-remove',
'filter' => 'permission:podcast$1.manage-persons', 'filter' => 'permission:podcast$1.manage-persons',
@ -181,13 +181,13 @@ $routes->group(
); );
}); });
$routes->group('analytics', static function ($routes): void { $routes->group('analytics', static function ($routes): void {
$routes->get('/', 'PodcastController::viewAnalytics/$1', [ $routes->get('/', 'PodcastController::analyticsView/$1', [
'as' => 'podcast-analytics', 'as' => 'podcast-analytics',
'filter' => 'permission:podcast$1.view', 'filter' => 'permission:podcast$1.view',
]); ]);
$routes->get( $routes->get(
'webpages', 'webpages',
'PodcastController::viewAnalyticsWebpages/$1', 'PodcastController::analyticsWebpagesView/$1',
[ [
'as' => 'podcast-analytics-webpages', 'as' => 'podcast-analytics-webpages',
'filter' => 'permission:podcast$1.view', 'filter' => 'permission:podcast$1.view',
@ -195,7 +195,7 @@ $routes->group(
); );
$routes->get( $routes->get(
'locations', 'locations',
'PodcastController::viewAnalyticsLocations/$1', 'PodcastController::analyticsLocationsView/$1',
[ [
'as' => 'podcast-analytics-locations', 'as' => 'podcast-analytics-locations',
'filter' => 'permission:podcast$1.view', 'filter' => 'permission:podcast$1.view',
@ -203,7 +203,7 @@ $routes->group(
); );
$routes->get( $routes->get(
'unique-listeners', 'unique-listeners',
'PodcastController::viewAnalyticsUniqueListeners/$1', 'PodcastController::analyticsUniqueListenersView/$1',
[ [
'as' => 'podcast-analytics-unique-listeners', 'as' => 'podcast-analytics-unique-listeners',
'filter' => 'permission:podcast$1.view', 'filter' => 'permission:podcast$1.view',
@ -211,7 +211,7 @@ $routes->group(
); );
$routes->get( $routes->get(
'listening-time', 'listening-time',
'PodcastController::viewAnalyticsListeningTime/$1', 'PodcastController::analyticsListeningTimeView/$1',
[ [
'as' => 'podcast-analytics-listening-time', 'as' => 'podcast-analytics-listening-time',
'filter' => 'permission:podcast$1.view', 'filter' => 'permission:podcast$1.view',
@ -219,7 +219,7 @@ $routes->group(
); );
$routes->get( $routes->get(
'time-periods', 'time-periods',
'PodcastController::viewAnalyticsTimePeriods/$1', 'PodcastController::analyticsTimePeriodsView/$1',
[ [
'as' => 'podcast-analytics-time-periods', 'as' => 'podcast-analytics-time-periods',
'filter' => 'permission:podcast$1.view', 'filter' => 'permission:podcast$1.view',
@ -227,7 +227,7 @@ $routes->group(
); );
$routes->get( $routes->get(
'players', 'players',
'PodcastController::viewAnalyticsPlayers/$1', 'PodcastController::analyticsPlayersView/$1',
[ [
'as' => 'podcast-analytics-players', 'as' => 'podcast-analytics-players',
'filter' => 'permission:podcast$1.view', 'filter' => 'permission:podcast$1.view',
@ -240,13 +240,13 @@ $routes->group(
'as' => 'episode-list', 'as' => 'episode-list',
'filter' => 'permission:podcast$1.episodes.view', 'filter' => 'permission:podcast$1.episodes.view',
]); ]);
$routes->get('new', 'EpisodeController::create/$1', [ $routes->get('new', 'EpisodeController::createView/$1', [
'as' => 'episode-create', 'as' => 'episode-create',
'filter' => 'permission:podcast$1.episodes.create', 'filter' => 'permission:podcast$1.episodes.create',
]); ]);
$routes->post( $routes->post(
'new', 'new',
'EpisodeController::attemptCreate/$1', 'EpisodeController::createAction/$1',
[ [
'filter' => 'permission:podcast$1.episodes.create', 'filter' => 'permission:podcast$1.episodes.create',
], ],
@ -257,20 +257,20 @@ $routes->group(
'as' => 'episode-view', 'as' => 'episode-view',
'filter' => 'permission:podcast$1.episodes.view', 'filter' => 'permission:podcast$1.episodes.view',
]); ]);
$routes->get('edit', 'EpisodeController::edit/$1/$2', [ $routes->get('edit', 'EpisodeController::editView/$1/$2', [
'as' => 'episode-edit', 'as' => 'episode-edit',
'filter' => 'permission:podcast$1.episodes.edit', 'filter' => 'permission:podcast$1.episodes.edit',
]); ]);
$routes->post( $routes->post(
'edit', 'edit',
'EpisodeController::attemptEdit/$1/$2', 'EpisodeController::editAction/$1/$2',
[ [
'filter' => 'permission:podcast$1.episodes.edit', 'filter' => 'permission:podcast$1.episodes.edit',
], ],
); );
$routes->get( $routes->get(
'publish', 'publish',
'EpisodeController::publish/$1/$2', 'EpisodeController::publishView/$1/$2',
[ [
'as' => 'episode-publish', 'as' => 'episode-publish',
'filter' => 'permission:podcast$1.episodes.manage-publications', 'filter' => 'permission:podcast$1.episodes.manage-publications',
@ -278,14 +278,14 @@ $routes->group(
); );
$routes->post( $routes->post(
'publish', 'publish',
'EpisodeController::attemptPublish/$1/$2', 'EpisodeController::publishAction/$1/$2',
[ [
'filter' => 'permission:podcast$1.episodes.manage-publications', 'filter' => 'permission:podcast$1.episodes.manage-publications',
], ],
); );
$routes->get( $routes->get(
'publish-edit', 'publish-edit',
'EpisodeController::publishEdit/$1/$2', 'EpisodeController::publishEditView/$1/$2',
[ [
'as' => 'episode-publish_edit', 'as' => 'episode-publish_edit',
'filter' => 'permission:podcast$1.episodes.manage-publications', 'filter' => 'permission:podcast$1.episodes.manage-publications',
@ -293,14 +293,14 @@ $routes->group(
); );
$routes->post( $routes->post(
'publish-edit', 'publish-edit',
'EpisodeController::attemptPublishEdit/$1/$2', 'EpisodeController::publishEditAction/$1/$2',
[ [
'filter' => 'permission:podcast$1.episodes.manage-publications', 'filter' => 'permission:podcast$1.episodes.manage-publications',
], ],
); );
$routes->get( $routes->get(
'publish-cancel', 'publish-cancel',
'EpisodeController::publishCancel/$1/$2', 'EpisodeController::publishCancelAction/$1/$2',
[ [
'as' => 'episode-publish-cancel', 'as' => 'episode-publish-cancel',
'filter' => 'permission:podcast$1.episodes.manage-publications', 'filter' => 'permission:podcast$1.episodes.manage-publications',
@ -308,7 +308,7 @@ $routes->group(
); );
$routes->get( $routes->get(
'publish-date-edit', 'publish-date-edit',
'EpisodeController::publishDateEdit/$1/$2', 'EpisodeController::publishDateEditView/$1/$2',
[ [
'as' => 'episode-publish_date_edit', 'as' => 'episode-publish_date_edit',
'filter' => 'permission:podcast$1.episodes.manage-publications', 'filter' => 'permission:podcast$1.episodes.manage-publications',
@ -316,14 +316,14 @@ $routes->group(
); );
$routes->post( $routes->post(
'publish-date-edit', 'publish-date-edit',
'EpisodeController::attemptPublishDateEdit/$1/$2', 'EpisodeController::publishDateEditAction/$1/$2',
[ [
'filter' => 'permission:podcast$1.episodes.manage-publications', 'filter' => 'permission:podcast$1.episodes.manage-publications',
], ],
); );
$routes->get( $routes->get(
'unpublish', 'unpublish',
'EpisodeController::unpublish/$1/$2', 'EpisodeController::unpublishView/$1/$2',
[ [
'as' => 'episode-unpublish', 'as' => 'episode-unpublish',
'filter' => 'permission:podcast$1.episodes.manage-publications', 'filter' => 'permission:podcast$1.episodes.manage-publications',
@ -331,14 +331,14 @@ $routes->group(
); );
$routes->post( $routes->post(
'unpublish', 'unpublish',
'EpisodeController::attemptUnpublish/$1/$2', 'EpisodeController::unpublishAction/$1/$2',
[ [
'filter' => 'permission:podcast$1.episodes.manage-publications', 'filter' => 'permission:podcast$1.episodes.manage-publications',
], ],
); );
$routes->get( $routes->get(
'delete', 'delete',
'EpisodeController::delete/$1/$2', 'EpisodeController::deleteView/$1/$2',
[ [
'as' => 'episode-delete', 'as' => 'episode-delete',
'filter' => 'permission:podcast$1.episodes.delete', 'filter' => 'permission:podcast$1.episodes.delete',
@ -346,7 +346,7 @@ $routes->group(
); );
$routes->post( $routes->post(
'delete', 'delete',
'EpisodeController::attemptDelete/$1/$2', 'EpisodeController::deleteAction/$1/$2',
[ [
'filter' => 'permission:podcast$1.episodes.delete', 'filter' => 'permission:podcast$1.episodes.delete',
], ],
@ -377,7 +377,7 @@ $routes->group(
); );
$routes->get( $routes->get(
'soundbites/new', 'soundbites/new',
'SoundbiteController::create/$1/$2', 'SoundbiteController::createView/$1/$2',
[ [
'as' => 'soundbites-create', 'as' => 'soundbites-create',
'filter' => 'permission:podcast$1.episodes.manage-clips', 'filter' => 'permission:podcast$1.episodes.manage-clips',
@ -385,7 +385,7 @@ $routes->group(
); );
$routes->post( $routes->post(
'soundbites/new', 'soundbites/new',
'SoundbiteController::attemptCreate/$1/$2', 'SoundbiteController::createAction/$1/$2',
[ [
'as' => 'soundbites-create', 'as' => 'soundbites-create',
'filter' => 'permission:podcast$1.episodes.manage-clips', 'filter' => 'permission:podcast$1.episodes.manage-clips',
@ -393,7 +393,7 @@ $routes->group(
); );
$routes->get( $routes->get(
'soundbites/(:num)/delete', 'soundbites/(:num)/delete',
'SoundbiteController::delete/$1/$2/$3', 'SoundbiteController::deleteAction/$1/$2/$3',
[ [
'as' => 'soundbites-delete', 'as' => 'soundbites-delete',
'filter' => 'permission:podcast$1.episodes.manage-clips', 'filter' => 'permission:podcast$1.episodes.manage-clips',
@ -409,7 +409,7 @@ $routes->group(
); );
$routes->get( $routes->get(
'video-clips/new', 'video-clips/new',
'VideoClipsController::create/$1/$2', 'VideoClipsController::createView/$1/$2',
[ [
'as' => 'video-clips-create', 'as' => 'video-clips-create',
'filter' => 'permission:podcast$1.episodes.manage-clips', 'filter' => 'permission:podcast$1.episodes.manage-clips',
@ -417,7 +417,7 @@ $routes->group(
); );
$routes->post( $routes->post(
'video-clips/new', 'video-clips/new',
'VideoClipsController::attemptCreate/$1/$2', 'VideoClipsController::createAction/$1/$2',
[ [
'as' => 'video-clips-create', 'as' => 'video-clips-create',
'filter' => 'permission:podcast$1.episodes.manage-clips', 'filter' => 'permission:podcast$1.episodes.manage-clips',
@ -433,7 +433,7 @@ $routes->group(
); );
$routes->get( $routes->get(
'video-clips/(:num)/retry', 'video-clips/(:num)/retry',
'VideoClipsController::retry/$1/$2/$3', 'VideoClipsController::retryAction/$1/$2/$3',
[ [
'as' => 'video-clip-retry', 'as' => 'video-clip-retry',
'filter' => 'permission:podcast$1.episodes.manage-clips', 'filter' => 'permission:podcast$1.episodes.manage-clips',
@ -441,7 +441,7 @@ $routes->group(
); );
$routes->get( $routes->get(
'video-clips/(:num)/delete', 'video-clips/(:num)/delete',
'VideoClipsController::delete/$1/$2/$3', 'VideoClipsController::deleteAction/$1/$2/$3',
[ [
'as' => 'video-clip-delete', 'as' => 'video-clip-delete',
'filter' => 'permission:podcast$1.episodes.manage-clips', 'filter' => 'permission:podcast$1.episodes.manage-clips',
@ -449,7 +449,7 @@ $routes->group(
); );
$routes->get( $routes->get(
'embed', 'embed',
'EpisodeController::embed/$1/$2', 'EpisodeController::embedView/$1/$2',
[ [
'as' => 'embed-add', 'as' => 'embed-add',
'filter' => 'permission:podcast$1.episodes.edit', 'filter' => 'permission:podcast$1.episodes.edit',
@ -462,14 +462,14 @@ $routes->group(
]); ]);
$routes->post( $routes->post(
'/', '/',
'EpisodePersonController::attemptCreate/$1/$2', 'EpisodePersonController::createAction/$1/$2',
[ [
'filter' => 'permission:podcast$1.episodes.manage-persons', 'filter' => 'permission:podcast$1.episodes.manage-persons',
], ],
); );
$routes->get( $routes->get(
'(:num)/remove', '(:num)/remove',
'EpisodePersonController::remove/$1/$2/$3', 'EpisodePersonController::deleteAction/$1/$2/$3',
[ [
'as' => 'episode-person-remove', 'as' => 'episode-person-remove',
'filter' => 'permission:podcast$1.episodes.manage-persons', 'filter' => 'permission:podcast$1.episodes.manage-persons',
@ -479,7 +479,7 @@ $routes->group(
$routes->group('comments', static function ($routes): void { $routes->group('comments', static function ($routes): void {
$routes->post( $routes->post(
'new', 'new',
'EpisodeController::attemptCommentCreate/$1/$2', 'EpisodeController::commentCreateAction/$1/$2',
[ [
'as' => 'comment-attempt-create', 'as' => 'comment-attempt-create',
'filter' => 'permission:podcast$1.episodes.manage-comments', 'filter' => 'permission:podcast$1.episodes.manage-comments',
@ -487,7 +487,7 @@ $routes->group(
); );
$routes->post( $routes->post(
'(:uuid)/reply', '(:uuid)/reply',
'EpisodeController::attemptCommentReply/$1/$2/$3', 'EpisodeController::commentReplyAction/$1/$2/$3',
[ [
'as' => 'comment-attempt-reply', 'as' => 'comment-attempt-reply',
'filter' => 'permission:podcast$1.episodes.manage-comments', 'filter' => 'permission:podcast$1.episodes.manage-comments',
@ -495,7 +495,7 @@ $routes->group(
); );
$routes->post( $routes->post(
'delete', 'delete',
'EpisodeController::attemptCommentDelete/$1/$2', 'EpisodeController::commentDeleteAction/$1/$2',
[ [
'as' => 'comment-attempt-delete', 'as' => 'comment-attempt-delete',
'filter' => 'permission:podcast$1.episodes.manage-comments', 'filter' => 'permission:podcast$1.episodes.manage-comments',
@ -510,11 +510,11 @@ $routes->group(
'as' => 'notification-list', 'as' => 'notification-list',
'filter' => 'permission:podcast$1.manage-notifications', 'filter' => 'permission:podcast$1.manage-notifications',
]); ]);
$routes->get('(:num)/mark-as-read', 'NotificationController::markAsRead/$1/$2', [ $routes->get('(:num)/mark-as-read', 'NotificationController::markAsReadAction/$1/$2', [
'as' => 'notification-mark-as-read', 'as' => 'notification-mark-as-read',
'filter' => 'permission:podcast$1.manage-notifications', 'filter' => 'permission:podcast$1.manage-notifications',
]); ]);
$routes->get('mark-all-as-read', 'NotificationController::markAllAsRead/$1', [ $routes->get('mark-all-as-read', 'NotificationController::markAllAsReadAction/$1', [
'as' => 'notification-mark-all-as-read', 'as' => 'notification-mark-all-as-read',
'filter' => 'permission:podcast$1.manage-notifications', 'filter' => 'permission:podcast$1.manage-notifications',
]); ]);
@ -528,7 +528,7 @@ $routes->group(
]); ]);
$routes->get( $routes->get(
'blocked-actors', 'blocked-actors',
'FediverseController::blockedActors', 'FediverseController::blockedActorsView',
[ [
'as' => 'fediverse-blocked-actors', 'as' => 'fediverse-blocked-actors',
'filter' => 'permission:fediverse.manage-blocks', 'filter' => 'permission:fediverse.manage-blocks',
@ -536,7 +536,7 @@ $routes->group(
); );
$routes->get( $routes->get(
'blocked-domains', 'blocked-domains',
'FediverseController::blockedDomains', 'FediverseController::blockedDomainsView',
[ [
'as' => 'fediverse-blocked-domains', 'as' => 'fediverse-blocked-domains',
'filter' => 'permission:fediverse.manage-blocks', 'filter' => 'permission:fediverse.manage-blocks',
@ -549,25 +549,25 @@ $routes->group(
'as' => 'page-list', 'as' => 'page-list',
'filter' => 'permission:pages.manage', 'filter' => 'permission:pages.manage',
]); ]);
$routes->get('new', 'PageController::create', [ $routes->get('new', 'PageController::createView', [
'as' => 'page-create', 'as' => 'page-create',
'filter' => 'permission:pages.manage', 'filter' => 'permission:pages.manage',
]); ]);
$routes->post('new', 'PageController::attemptCreate', [ $routes->post('new', 'PageController::createAction', [
'filter' => 'permission:pages.manage', 'filter' => 'permission:pages.manage',
]); ]);
$routes->group('(:num)', static function ($routes): void { $routes->group('(:num)', static function ($routes): void {
$routes->get('/', 'PageController::view/$1', [ $routes->get('/', 'PageController::view/$1', [
'as' => 'page-view', 'as' => 'page-view',
]); ]);
$routes->get('edit', 'PageController::edit/$1', [ $routes->get('edit', 'PageController::editView/$1', [
'as' => 'page-edit', 'as' => 'page-edit',
'filter' => 'permission:pages.manage', 'filter' => 'permission:pages.manage',
]); ]);
$routes->post('edit', 'PageController::attemptEdit/$1', [ $routes->post('edit', 'PageController::editAction/$1', [
'filter' => 'permission:pages.manage', 'filter' => 'permission:pages.manage',
]); ]);
$routes->get('delete', 'PageController::delete/$1', [ $routes->get('delete', 'PageController::deleteAction/$1', [
'as' => 'page-delete', 'as' => 'page-delete',
'filter' => 'permission:pages.manage', 'filter' => 'permission:pages.manage',
]); ]);

View File

@ -35,36 +35,31 @@ class EpisodeController extends BaseController
public function _remap(string $method, string ...$params): mixed public function _remap(string $method, string ...$params): mixed
{ {
if ($params === []) {
throw PageNotFoundException::forPageNotFound();
}
if (count($params) === 1) {
if (! ($podcast = (new PodcastModel())->getPodcastById((int) $params[0])) instanceof Podcast) {
throw PageNotFoundException::forPageNotFound();
}
return $this->{$method}($podcast);
}
if ( if (
! ($podcast = (new PodcastModel())->getPodcastById((int) $params[0])) instanceof Podcast ! ($episode = (new EpisodeModel())->getEpisodeById((int) $params[1]) instanceof Episode)
) { ) {
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
} }
$this->podcast = $podcast; unset($params[0]);
unset($params[1]);
if (count($params) > 1) { return $this->{$method}($episode, ...$params);
if (
! ($episode = (new EpisodeModel())
->where([
'id' => $params[1],
'podcast_id' => $params[0],
])
->first()) instanceof Episode
) {
throw PageNotFoundException::forPageNotFound();
}
$this->episode = $episode;
unset($params[1]);
unset($params[0]);
}
return $this->{$method}(...$params);
} }
public function list(): string public function list(Podcast $podcast): string
{ {
/** @var ?string $query */ /** @var ?string $query */
$query = $this->request->getGet('q'); $query = $this->request->getGet('q');
@ -77,7 +72,7 @@ class EpisodeController extends BaseController
$episodes = $episodeModel $episodes = $episodeModel
->select('episodes.*, IFNULL(SUM(ape.hits),0) as downloads') ->select('episodes.*, IFNULL(SUM(ape.hits),0) as downloads')
->join('analytics_podcasts_by_episode ape', 'episodes.id=ape.episode_id', 'left') ->join('analytics_podcasts_by_episode ape', 'episodes.id=ape.episode_id', 'left')
->where('episodes.podcast_id', $this->podcast->id) ->where('episodes.podcast_id', $podcast->id)
->like('title', $episodeModel->db->escapeLikeString($query)) ->like('title', $episodeModel->db->escapeLikeString($query))
->orLike('description_markdown', $episodeModel->db->escapeLikeString($query)) ->orLike('description_markdown', $episodeModel->db->escapeLikeString($query))
->orLike('slug', $episodeModel->db->escapeLikeString($query)) ->orLike('slug', $episodeModel->db->escapeLikeString($query))
@ -89,7 +84,7 @@ class EpisodeController extends BaseController
$episodes = $episodeModel $episodes = $episodeModel
->select('episodes.*, IFNULL(SUM(ape.hits),0) as downloads') ->select('episodes.*, IFNULL(SUM(ape.hits),0) as downloads')
->join('analytics_podcasts_by_episode ape', 'episodes.id=ape.episode_id', 'left') ->join('analytics_podcasts_by_episode ape', 'episodes.id=ape.episode_id', 'left')
->where('episodes.podcast_id', $this->podcast->id) ->where('episodes.podcast_id', $podcast->id)
->where( ->where(
"MATCH (title, description_markdown, slug, location_name) AGAINST ('{$episodeModel->db->escapeString( "MATCH (title, description_markdown, slug, location_name) AGAINST ('{$episodeModel->db->escapeString(
$query $query
@ -101,7 +96,7 @@ class EpisodeController extends BaseController
$episodes = $episodeModel $episodes = $episodeModel
->select('episodes.*, IFNULL(SUM(ape.hits),0) as downloads') ->select('episodes.*, IFNULL(SUM(ape.hits),0) as downloads')
->join('analytics_podcasts_by_episode ape', 'episodes.id=ape.episode_id', 'left') ->join('analytics_podcasts_by_episode ape', 'episodes.id=ape.episode_id', 'left')
->where('episodes.podcast_id', $this->podcast->id) ->where('episodes.podcast_id', $podcast->id)
->groupBy('episodes.id') ->groupBy('episodes.id')
->orderBy('-`published_at`', '', false) ->orderBy('-`published_at`', '', false)
->orderBy('created_at', 'desc'); ->orderBy('created_at', 'desc');
@ -109,7 +104,7 @@ class EpisodeController extends BaseController
helper('form'); helper('form');
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $podcast,
'episodes' => $episodes->paginate(10), 'episodes' => $episodes->paginate(10),
'pager' => $episodes->pager, 'pager' => $episodes->pager,
'query' => $query, 'query' => $query,
@ -117,48 +112,45 @@ class EpisodeController extends BaseController
$this->setHtmlHead(lang('Episode.all_podcast_episodes')); $this->setHtmlHead(lang('Episode.all_podcast_episodes'));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $podcast->at_handle,
]); ]);
return view('episode/list', $data); return view('episode/list', $data);
} }
public function view(): string public function view(Episode $episode): string
{ {
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $episode->podcast,
'episode' => $this->episode, 'episode' => $episode,
]; ];
$this->setHtmlHead($this->episode->title); $this->setHtmlHead($episode->title);
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $episode->podcast->at_handle,
1 => $this->episode->title, 1 => $episode->title,
]); ]);
return view('episode/view', $data); return view('episode/view', $data);
} }
public function create(): string public function createView(Podcast $podcast): string
{ {
helper(['form']); helper(['form']);
$currentSeasonNumber = (new EpisodeModel())->getCurrentSeasonNumber($this->podcast->id); $currentSeasonNumber = (new EpisodeModel())->getCurrentSeasonNumber($podcast->id);
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $podcast,
'currentSeasonNumber' => $currentSeasonNumber, 'currentSeasonNumber' => $currentSeasonNumber,
'nextEpisodeNumber' => (new EpisodeModel())->getNextEpisodeNumber( 'nextEpisodeNumber' => (new EpisodeModel())->getNextEpisodeNumber($podcast->id, $currentSeasonNumber),
$this->podcast->id,
$currentSeasonNumber
),
]; ];
$this->setHtmlHead(lang('Episode.create')); $this->setHtmlHead(lang('Episode.create'));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $podcast->at_handle,
]); ]);
return view('episode/create', $data); return view('episode/create', $data);
} }
public function attemptCreate(): RedirectResponse public function createAction(Podcast $podcast): RedirectResponse
{ {
$rules = [ $rules = [
'title' => 'required', 'title' => 'required',
@ -169,7 +161,7 @@ class EpisodeController extends BaseController
'chapters_file' => 'ext_in[chapters_file,json]|is_json[chapters_file]', 'chapters_file' => 'ext_in[chapters_file,json]|is_json[chapters_file]',
]; ];
if ($this->podcast->type === 'serial' && $this->request->getPost('type') === 'full') { if ($podcast->type === 'serial' && $this->request->getPost('type') === 'full') {
$rules['episode_number'] = 'required'; $rules['episode_number'] = 'required';
} }
@ -185,7 +177,7 @@ class EpisodeController extends BaseController
if ((new EpisodeModel()) if ((new EpisodeModel())
->where([ ->where([
'slug' => $validData['slug'], 'slug' => $validData['slug'],
'podcast_id' => $this->podcast->id, 'podcast_id' => $podcast->id,
]) ])
->first() instanceof Episode) { ->first() instanceof Episode) {
return redirect() return redirect()
@ -197,7 +189,7 @@ class EpisodeController extends BaseController
$newEpisode = new Episode([ $newEpisode = new Episode([
'created_by' => user_id(), 'created_by' => user_id(),
'updated_by' => user_id(), 'updated_by' => user_id(),
'podcast_id' => $this->podcast->id, 'podcast_id' => $podcast->id,
'title' => $this->request->getPost('title'), 'title' => $this->request->getPost('title'),
'slug' => $this->request->getPost('slug'), 'slug' => $this->request->getPost('slug'),
'guid' => null, 'guid' => null,
@ -250,30 +242,30 @@ class EpisodeController extends BaseController
->with('errors', $episodeModel->errors()); ->with('errors', $episodeModel->errors());
} }
return redirect()->route('episode-view', [$this->podcast->id, $newEpisodeId])->with( return redirect()->route('episode-view', [$podcast->id, $newEpisodeId])->with(
'message', 'message',
lang('Episode.messages.createSuccess') lang('Episode.messages.createSuccess')
); );
} }
public function edit(): string public function editView(Episode $episode): string
{ {
helper(['form']); helper(['form']);
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $episode->podcast,
'episode' => $this->episode, 'episode' => $episode,
]; ];
$this->setHtmlHead(lang('Episode.edit')); $this->setHtmlHead(lang('Episode.edit'));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $episode->podcast->at_handle,
1 => $this->episode->title, 1 => $episode->title,
]); ]);
return view('episode/edit', $data); return view('episode/edit', $data);
} }
public function attemptEdit(): RedirectResponse public function editAction(Episode $episode): RedirectResponse
{ {
$rules = [ $rules = [
'title' => 'required', 'title' => 'required',
@ -284,7 +276,7 @@ class EpisodeController extends BaseController
'chapters_file' => 'ext_in[chapters_file,json]|is_json[chapters_file]', 'chapters_file' => 'ext_in[chapters_file,json]|is_json[chapters_file]',
]; ];
if ($this->podcast->type === 'serial' && $this->request->getPost('type') === 'full') { if ($episode->podcast->type === 'serial' && $this->request->getPost('type') === 'full') {
$rules['episode_number'] = 'required'; $rules['episode_number'] = 'required';
} }
@ -297,87 +289,87 @@ class EpisodeController extends BaseController
$validData = $this->validator->getValidated(); $validData = $this->validator->getValidated();
$this->episode->title = $this->request->getPost('title'); $episode->title = $this->request->getPost('title');
$this->episode->slug = $validData['slug']; $episode->slug = $validData['slug'];
$this->episode->description_markdown = $this->request->getPost('description'); $episode->description_markdown = $this->request->getPost('description');
$this->episode->location = $this->request->getPost('location_name') === '' ? null : new Location( $episode->location = $this->request->getPost('location_name') === '' ? null : new Location(
$this->request->getPost('location_name') $this->request->getPost('location_name')
); );
$this->episode->parental_advisory = $episode->parental_advisory =
$this->request->getPost('parental_advisory') !== 'undefined' $this->request->getPost('parental_advisory') !== 'undefined'
? $this->request->getPost('parental_advisory') ? $this->request->getPost('parental_advisory')
: null; : null;
$this->episode->number = $this->request->getPost('episode_number') ?: null; $episode->number = $this->request->getPost('episode_number') ?: null;
$this->episode->season_number = $this->request->getPost('season_number') ?: null; $episode->season_number = $this->request->getPost('season_number') ?: null;
$this->episode->type = $this->request->getPost('type'); $episode->type = $this->request->getPost('type');
$this->episode->is_blocked = $this->request->getPost('block') === 'yes'; $episode->is_blocked = $this->request->getPost('block') === 'yes';
$this->episode->is_premium = $this->request->getPost('premium') === 'yes'; $episode->is_premium = $this->request->getPost('premium') === 'yes';
$this->episode->updated_by = (int) user_id(); $episode->updated_by = (int) user_id();
$this->episode->setAudio($this->request->getFile('audio_file')); $episode->setAudio($this->request->getFile('audio_file'));
$this->episode->setCover($this->request->getFile('cover')); $episode->setCover($this->request->getFile('cover'));
// republish on websub hubs upon edit // republish on websub hubs upon edit
$this->episode->is_published_on_hubs = false; $episode->is_published_on_hubs = false;
$transcriptChoice = $this->request->getPost('transcript-choice'); $transcriptChoice = $this->request->getPost('transcript-choice');
if ($transcriptChoice === 'upload-file') { if ($transcriptChoice === 'upload-file') {
$transcriptFile = $this->request->getFile('transcript_file'); $transcriptFile = $this->request->getFile('transcript_file');
if ($transcriptFile instanceof UploadedFile && $transcriptFile->isValid()) { if ($transcriptFile instanceof UploadedFile && $transcriptFile->isValid()) {
$this->episode->setTranscript($transcriptFile); $episode->setTranscript($transcriptFile);
$this->episode->transcript_remote_url = null; $episode->transcript_remote_url = null;
} }
} elseif ($transcriptChoice === 'remote-url') { } elseif ($transcriptChoice === 'remote-url') {
if ( if (
($transcriptRemoteUrl = $this->request->getPost('transcript_remote_url')) && ($transcriptRemoteUrl = $this->request->getPost('transcript_remote_url')) &&
(($transcriptFile = $this->episode->transcript_id) !== null) (($transcriptFile = $episode->transcript_id) !== null)
) { ) {
(new MediaModel())->deleteMedia($this->episode->transcript); (new MediaModel())->deleteMedia($episode->transcript);
} }
$this->episode->transcript_remote_url = $transcriptRemoteUrl === '' ? null : $transcriptRemoteUrl; $episode->transcript_remote_url = $transcriptRemoteUrl === '' ? null : $transcriptRemoteUrl;
} }
$chaptersChoice = $this->request->getPost('chapters-choice'); $chaptersChoice = $this->request->getPost('chapters-choice');
if ($chaptersChoice === 'upload-file') { if ($chaptersChoice === 'upload-file') {
$chaptersFile = $this->request->getFile('chapters_file'); $chaptersFile = $this->request->getFile('chapters_file');
if ($chaptersFile instanceof UploadedFile && $chaptersFile->isValid()) { if ($chaptersFile instanceof UploadedFile && $chaptersFile->isValid()) {
$this->episode->setChapters($chaptersFile); $episode->setChapters($chaptersFile);
$this->episode->chapters_remote_url = null; $episode->chapters_remote_url = null;
} }
} elseif ($chaptersChoice === 'remote-url') { } elseif ($chaptersChoice === 'remote-url') {
if ( if (
($chaptersRemoteUrl = $this->request->getPost('chapters_remote_url')) && ($chaptersRemoteUrl = $this->request->getPost('chapters_remote_url')) &&
(($chaptersFile = $this->episode->chapters) instanceof Chapters) (($chaptersFile = $episode->chapters) instanceof Chapters)
) { ) {
(new MediaModel())->deleteMedia($this->episode->chapters); (new MediaModel())->deleteMedia($episode->chapters);
} }
$this->episode->chapters_remote_url = $chaptersRemoteUrl === '' ? null : $chaptersRemoteUrl; $episode->chapters_remote_url = $chaptersRemoteUrl === '' ? null : $chaptersRemoteUrl;
} }
$episodeModel = new EpisodeModel(); $episodeModel = new EpisodeModel();
if (! $episodeModel->update($this->episode->id, $this->episode)) { if (! $episodeModel->update($episode->id, $episode)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
->with('errors', $episodeModel->errors()); ->with('errors', $episodeModel->errors());
} }
return redirect()->route('episode-edit', [$this->podcast->id, $this->episode->id])->with( return redirect()->route('episode-edit', [$episode->podcast_id, $episode->id])->with(
'message', 'message',
lang('Episode.messages.editSuccess') lang('Episode.messages.editSuccess')
); );
} }
public function transcriptDelete(): RedirectResponse public function transcriptDelete(Episode $episode): RedirectResponse
{ {
if (! $this->episode->transcript instanceof Transcript) { if (! $episode->transcript instanceof Transcript) {
return redirect()->back(); return redirect()->back();
} }
$mediaModel = new MediaModel(); $mediaModel = new MediaModel();
if (! $mediaModel->deleteMedia($this->episode->transcript)) { if (! $mediaModel->deleteMedia($episode->transcript)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -387,14 +379,14 @@ class EpisodeController extends BaseController
return redirect()->back(); return redirect()->back();
} }
public function chaptersDelete(): RedirectResponse public function chaptersDelete(Episode $episode): RedirectResponse
{ {
if (! $this->episode->chapters instanceof Chapters) { if (! $episode->chapters instanceof Chapters) {
return redirect()->back(); return redirect()->back();
} }
$mediaModel = new MediaModel(); $mediaModel = new MediaModel();
if (! $mediaModel->deleteMedia($this->episode->chapters)) { if (! $mediaModel->deleteMedia($episode->chapters)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -404,33 +396,33 @@ class EpisodeController extends BaseController
return redirect()->back(); return redirect()->back();
} }
public function publish(): string | RedirectResponse public function publishView(Episode $episode): string | RedirectResponse
{ {
if ($this->episode->publication_status === 'not_published') { if ($episode->publication_status === 'not_published') {
helper(['form']); helper(['form']);
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $episode->podcast,
'episode' => $this->episode, 'episode' => $episode,
]; ];
$this->setHtmlHead(lang('Episode.publish')); $this->setHtmlHead(lang('Episode.publish'));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $episode->podcast->at_handle,
1 => $this->episode->title, 1 => $episode->title,
]); ]);
return view('episode/publish', $data); return view('episode/publish', $data);
} }
return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with( return redirect()->route('episode-view', [$episode->podcast_id, $episode->id])->with(
'error', 'error',
lang('Episode.publish_error') lang('Episode.publish_error')
); );
} }
public function attemptPublish(): RedirectResponse public function publishAction(Episode $episode): RedirectResponse
{ {
if ($this->podcast->publication_status === 'published') { if ($episode->podcast->publication_status === 'published') {
$rules = [ $rules = [
'publication_method' => 'required', 'publication_method' => 'required',
'scheduled_publication_date' => 'valid_date[Y-m-d H:i]|permit_empty', 'scheduled_publication_date' => 'valid_date[Y-m-d H:i]|permit_empty',
@ -448,18 +440,18 @@ class EpisodeController extends BaseController
$db->transStart(); $db->transStart();
$newPost = new Post([ $newPost = new Post([
'actor_id' => $this->podcast->actor_id, 'actor_id' => $episode->podcast->actor_id,
'episode_id' => $this->episode->id, 'episode_id' => $episode->id,
'message' => $this->request->getPost('message'), 'message' => $this->request->getPost('message'),
'created_by' => user_id(), 'created_by' => user_id(),
]); ]);
if ($this->podcast->publication_status === 'published') { if ($episode->podcast->publication_status === 'published') {
$publishMethod = $this->request->getPost('publication_method'); $publishMethod = $this->request->getPost('publication_method');
if ($publishMethod === 'schedule') { if ($publishMethod === 'schedule') {
$scheduledPublicationDate = $this->request->getPost('scheduled_publication_date'); $scheduledPublicationDate = $this->request->getPost('scheduled_publication_date');
if ($scheduledPublicationDate) { if ($scheduledPublicationDate) {
$this->episode->published_at = Time::createFromFormat( $episode->published_at = Time::createFromFormat(
'Y-m-d H:i', 'Y-m-d H:i',
$scheduledPublicationDate, $scheduledPublicationDate,
$this->request->getPost('client_timezone'), $this->request->getPost('client_timezone'),
@ -472,16 +464,16 @@ class EpisodeController extends BaseController
->with('error', lang('Episode.messages.scheduleDateError')); ->with('error', lang('Episode.messages.scheduleDateError'));
} }
} else { } else {
$this->episode->published_at = Time::now(); $episode->published_at = Time::now();
} }
} elseif ($this->podcast->publication_status === 'scheduled') { } elseif ($episode->podcast->publication_status === 'scheduled') {
// podcast publication date has already been set // podcast publication date has already been set
$this->episode->published_at = $this->podcast->published_at->addSeconds(1); $episode->published_at = $episode->podcast->published_at->addSeconds(1);
} else { } else {
$this->episode->published_at = Time::now(); $episode->published_at = Time::now();
} }
$newPost->published_at = $this->episode->published_at; $newPost->published_at = $episode->published_at;
$postModel = new PostModel(); $postModel = new PostModel();
if (! $postModel->addPost($newPost)) { if (! $postModel->addPost($newPost)) {
@ -493,7 +485,7 @@ class EpisodeController extends BaseController
} }
$episodeModel = new EpisodeModel(); $episodeModel = new EpisodeModel();
if (! $episodeModel->update($this->episode->id, $this->episode)) { if (! $episodeModel->update($episode->id, $episode)) {
$db->transRollback(); $db->transRollback();
return redirect() return redirect()
->back() ->back()
@ -503,47 +495,47 @@ class EpisodeController extends BaseController
$db->transComplete(); $db->transComplete();
return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with( return redirect()->route('episode-view', [$episode->podcast_id, $episode->id])->with(
'message', 'message',
lang('Episode.messages.publishSuccess', [ lang('Episode.messages.publishSuccess', [
'publication_status' => $this->episode->publication_status, 'publication_status' => $episode->publication_status,
]) ])
); );
} }
public function publishEdit(): string | RedirectResponse public function publishEditView(Episode $episode): string | RedirectResponse
{ {
if (in_array($this->episode->publication_status, ['scheduled', 'with_podcast'], true)) { if (in_array($episode->publication_status, ['scheduled', 'with_podcast'], true)) {
helper(['form']); helper(['form']);
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $episode->podcast,
'episode' => $this->episode, 'episode' => $episode,
'post' => (new PostModel()) 'post' => (new PostModel())
->where([ ->where([
'actor_id' => $this->podcast->actor_id, 'actor_id' => $episode->podcast->actor_id,
'episode_id' => $this->episode->id, 'episode_id' => $episode->id,
]) ])
->first(), ->first(),
]; ];
$this->setHtmlHead(lang('Episode.publish_edit')); $this->setHtmlHead(lang('Episode.publish_edit'));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $episode->podcast->at_handle,
1 => $this->episode->title, 1 => $episode->title,
]); ]);
return view('episode/publish_edit', $data); return view('episode/publish_edit', $data);
} }
return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with( return redirect()->route('episode-view', [$episode->podcast_id, $episode->id])->with(
'error', 'error',
lang('Episode.publish_edit_error') lang('Episode.publish_edit_error')
); );
} }
public function attemptPublishEdit(): RedirectResponse public function publishEditAction(Episode $episode): RedirectResponse
{ {
if ($this->podcast->publication_status === 'published') { if ($episode->podcast->publication_status === 'published') {
$rules = [ $rules = [
'post_id' => 'required', 'post_id' => 'required',
'publication_method' => 'required', 'publication_method' => 'required',
@ -561,12 +553,12 @@ class EpisodeController extends BaseController
$db = db_connect(); $db = db_connect();
$db->transStart(); $db->transStart();
if ($this->podcast->publication_status === 'published') { if ($episode->podcast->publication_status === 'published') {
$publishMethod = $this->request->getPost('publication_method'); $publishMethod = $this->request->getPost('publication_method');
if ($publishMethod === 'schedule') { if ($publishMethod === 'schedule') {
$scheduledPublicationDate = $this->request->getPost('scheduled_publication_date'); $scheduledPublicationDate = $this->request->getPost('scheduled_publication_date');
if ($scheduledPublicationDate) { if ($scheduledPublicationDate) {
$this->episode->published_at = Time::createFromFormat( $episode->published_at = Time::createFromFormat(
'Y-m-d H:i', 'Y-m-d H:i',
$scheduledPublicationDate, $scheduledPublicationDate,
$this->request->getPost('client_timezone'), $this->request->getPost('client_timezone'),
@ -579,20 +571,20 @@ class EpisodeController extends BaseController
->with('error', lang('Episode.messages.scheduleDateError')); ->with('error', lang('Episode.messages.scheduleDateError'));
} }
} else { } else {
$this->episode->published_at = Time::now(); $episode->published_at = Time::now();
} }
} elseif ($this->podcast->publication_status === 'scheduled') { } elseif ($episode->podcast->publication_status === 'scheduled') {
// podcast publication date has already been set // podcast publication date has already been set
$this->episode->published_at = $this->podcast->published_at->addSeconds(1); $episode->published_at = $episode->podcast->published_at->addSeconds(1);
} else { } else {
$this->episode->published_at = Time::now(); $episode->published_at = Time::now();
} }
$post = (new PostModel())->getPostById($this->request->getPost('post_id')); $post = (new PostModel())->getPostById($this->request->getPost('post_id'));
if ($post instanceof Post) { if ($post instanceof Post) {
$post->message = $this->request->getPost('message'); $post->message = $this->request->getPost('message');
$post->published_at = $this->episode->published_at; $post->published_at = $episode->published_at;
$postModel = new PostModel(); $postModel = new PostModel();
if (! $postModel->editPost($post)) { if (! $postModel->editPost($post)) {
@ -605,7 +597,7 @@ class EpisodeController extends BaseController
} }
$episodeModel = new EpisodeModel(); $episodeModel = new EpisodeModel();
if (! $episodeModel->update($this->episode->id, $this->episode)) { if (! $episodeModel->update($episode->id, $episode)) {
$db->transRollback(); $db->transRollback();
return redirect() return redirect()
->back() ->back()
@ -615,33 +607,33 @@ class EpisodeController extends BaseController
$db->transComplete(); $db->transComplete();
return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with( return redirect()->route('episode-view', [$episode->podcast_id, $episode->id])->with(
'message', 'message',
lang('Episode.messages.publishSuccess', [ lang('Episode.messages.publishSuccess', [
'publication_status' => $this->episode->publication_status, 'publication_status' => $episode->publication_status,
]) ])
); );
} }
public function publishCancel(): RedirectResponse public function publishCancelAction(Episode $episode): RedirectResponse
{ {
if (in_array($this->episode->publication_status, ['scheduled', 'with_podcast'], true)) { if (in_array($episode->publication_status, ['scheduled', 'with_podcast'], true)) {
$db = db_connect(); $db = db_connect();
$db->transStart(); $db->transStart();
$postModel = new PostModel(); $postModel = new PostModel();
$post = $postModel $post = $postModel
->where([ ->where([
'actor_id' => $this->podcast->actor_id, 'actor_id' => $episode->podcast->actor_id,
'episode_id' => $this->episode->id, 'episode_id' => $episode->id,
]) ])
->first(); ->first();
$postModel->removePost($post); $postModel->removePost($post);
$this->episode->published_at = null; $episode->published_at = null;
$episodeModel = new EpisodeModel(); $episodeModel = new EpisodeModel();
if (! $episodeModel->update($this->episode->id, $this->episode)) { if (! $episodeModel->update($episode->id, $episode)) {
$db->transRollback(); $db->transRollback();
return redirect() return redirect()
->back() ->back()
@ -651,20 +643,20 @@ class EpisodeController extends BaseController
$db->transComplete(); $db->transComplete();
return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with( return redirect()->route('episode-view', [$episode->podcast_id, $episode->id])->with(
'message', 'message',
lang('Episode.messages.publishCancelSuccess') lang('Episode.messages.publishCancelSuccess')
); );
} }
return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id]); return redirect()->route('episode-view', [$episode->podcast_id, $episode->id]);
} }
public function publishDateEdit(): string|RedirectResponse public function publishDateEditView(Episode $episode): string|RedirectResponse
{ {
// only accessible if episode is already published // only accessible if episode is already published
if ($this->episode->publication_status !== 'published') { if ($episode->publication_status !== 'published') {
return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with( return redirect()->route('episode-view', [$episode->podcast_id, $episode->id])->with(
'error', 'error',
lang('Episode.publish_date_edit_error') lang('Episode.publish_date_edit_error')
); );
@ -673,14 +665,14 @@ class EpisodeController extends BaseController
helper('form'); helper('form');
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $episode->podcast,
'episode' => $this->episode, 'episode' => $episode,
]; ];
$this->setHtmlHead(lang('Episode.publish_date_edit')); $this->setHtmlHead(lang('Episode.publish_date_edit'));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->title, 0 => $episode->podcast->title,
1 => $this->episode->title, 1 => $episode->title,
]); ]);
return view('episode/publish_date_edit', $data); return view('episode/publish_date_edit', $data);
} }
@ -691,7 +683,7 @@ class EpisodeController extends BaseController
* Prevents setting a future date as it does not make sense to set a future published date to an already published * Prevents setting a future date as it does not make sense to set a future published date to an already published
* episode. This also prevents any side-effects from occurring. * episode. This also prevents any side-effects from occurring.
*/ */
public function attemptPublishDateEdit(): RedirectResponse public function publishDateEditAction(Episode $episode): RedirectResponse
{ {
$rules = [ $rules = [
'new_publication_date' => 'valid_date[Y-m-d H:i]', 'new_publication_date' => 'valid_date[Y-m-d H:i]',
@ -721,26 +713,26 @@ class EpisodeController extends BaseController
->with('error', lang('Episode.publish_date_edit_future_error')); ->with('error', lang('Episode.publish_date_edit_future_error'));
} }
$this->episode->published_at = $newPublicationDate; $episode->published_at = $newPublicationDate;
$episodeModel = new EpisodeModel(); $episodeModel = new EpisodeModel();
if (! $episodeModel->update($this->episode->id, $this->episode)) { if (! $episodeModel->update($episode->id, $episode)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
->with('errors', $episodeModel->errors()); ->with('errors', $episodeModel->errors());
} }
return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with( return redirect()->route('episode-view', [$episode->podcast_id, $episode->id])->with(
'message', 'message',
lang('Episode.publish_date_edit_success') lang('Episode.publish_date_edit_success')
); );
} }
public function unpublish(): string | RedirectResponse public function unpublishView(Episode $episode): string | RedirectResponse
{ {
if ($this->episode->publication_status !== 'published') { if ($episode->publication_status !== 'published') {
return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with( return redirect()->route('episode-view', [$episode->podcast_id, $episode->id])->with(
'error', 'error',
lang('Episode.unpublish_error') lang('Episode.unpublish_error')
); );
@ -749,19 +741,19 @@ class EpisodeController extends BaseController
helper(['form']); helper(['form']);
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $episode->podcast,
'episode' => $this->episode, 'episode' => $episode,
]; ];
$this->setHtmlHead(lang('Episode.unpublish')); $this->setHtmlHead(lang('Episode.unpublish'));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->title, 0 => $episode->podcast->title,
1 => $this->episode->title, 1 => $episode->title,
]); ]);
return view('episode/unpublish', $data); return view('episode/unpublish', $data);
} }
public function attemptUnpublish(): RedirectResponse public function unpublishAction(Episode $episode): RedirectResponse
{ {
$rules = [ $rules = [
'understand' => 'required', 'understand' => 'required',
@ -780,7 +772,7 @@ class EpisodeController extends BaseController
$allPostsLinkedToEpisode = (new PostModel()) $allPostsLinkedToEpisode = (new PostModel())
->where([ ->where([
'episode_id' => $this->episode->id, 'episode_id' => $episode->id,
'in_reply_to_id' => null, 'in_reply_to_id' => null,
'reblog_of_id' => null, 'reblog_of_id' => null,
]) ])
@ -791,7 +783,7 @@ class EpisodeController extends BaseController
$allCommentsLinkedToEpisode = (new EpisodeCommentModel()) $allCommentsLinkedToEpisode = (new EpisodeCommentModel())
->where([ ->where([
'episode_id' => $this->episode->id, 'episode_id' => $episode->id,
'in_reply_to_id' => null, 'in_reply_to_id' => null,
]) ])
->findAll(); ->findAll();
@ -800,10 +792,10 @@ class EpisodeController extends BaseController
} }
// set episode published_at to null to unpublish // set episode published_at to null to unpublish
$this->episode->published_at = null; $episode->published_at = null;
$episodeModel = new EpisodeModel(); $episodeModel = new EpisodeModel();
if (! $episodeModel->update($this->episode->id, $this->episode)) { if (! $episodeModel->update($episode->id, $episode)) {
$db->transRollback(); $db->transRollback();
return redirect() return redirect()
->back() ->back()
@ -812,33 +804,33 @@ class EpisodeController extends BaseController
} }
// set podcast is_published_on_hubs to false to trigger websub push // set podcast is_published_on_hubs to false to trigger websub push
(new PodcastModel())->update($this->episode->podcast->id, [ (new PodcastModel())->update($episode->podcast_id, [
'is_published_on_hubs' => 0, 'is_published_on_hubs' => 0,
]); ]);
$db->transComplete(); $db->transComplete();
return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id]); return redirect()->route('episode-view', [$episode->podcast_id, $episode->id]);
} }
public function delete(): string public function deleteView(Episode $episode): string
{ {
helper(['form']); helper(['form']);
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $episode->podcast,
'episode' => $this->episode, 'episode' => $episode,
]; ];
$this->setHtmlHead(lang('Episode.delete')); $this->setHtmlHead(lang('Episode.delete'));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $episode->podcast->at_handle,
1 => $this->episode->title, 1 => $episode->title,
]); ]);
return view('episode/delete', $data); return view('episode/delete', $data);
} }
public function attemptDelete(): RedirectResponse public function deleteAction(Episode $episode): RedirectResponse
{ {
$rules = [ $rules = [
'understand' => 'required', 'understand' => 'required',
@ -851,7 +843,7 @@ class EpisodeController extends BaseController
->with('errors', $this->validator->getErrors()); ->with('errors', $this->validator->getErrors());
} }
if ($this->episode->published_at instanceof Time) { if ($episode->published_at instanceof Time) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -864,7 +856,7 @@ class EpisodeController extends BaseController
$episodeModel = new EpisodeModel(); $episodeModel = new EpisodeModel();
if (! $episodeModel->delete($this->episode->id)) { if (! $episodeModel->delete($episode->id)) {
$db->transRollback(); $db->transRollback();
return redirect() return redirect()
->back() ->back()
@ -872,11 +864,11 @@ class EpisodeController extends BaseController
->with('errors', $episodeModel->errors()); ->with('errors', $episodeModel->errors());
} }
$episodeMediaList = [$this->episode->transcript, $this->episode->chapters, $this->episode->audio]; $episodeMediaList = [$episode->transcript, $episode->chapters, $episode->audio];
//only delete episode cover if different from podcast's //only delete episode cover if different from podcast's
if ($this->episode->cover_id !== null) { if ($episode->cover_id !== null) {
$episodeMediaList[] = $this->episode->cover; $episodeMediaList[] = $episode->cover;
} }
$mediaModel = new MediaModel(); $mediaModel = new MediaModel();
@ -916,36 +908,36 @@ class EpisodeController extends BaseController
if ($warnings !== []) { if ($warnings !== []) {
return redirect() return redirect()
->route('episode-list', [$this->podcast->id]) ->route('episode-list', [$episode->podcast_id])
->with('message', lang('Episode.messages.deleteSuccess')) ->with('message', lang('Episode.messages.deleteSuccess'))
->with('warnings', $warnings); ->with('warnings', $warnings);
} }
return redirect()->route('episode-list', [$this->podcast->id])->with( return redirect()->route('episode-list', [$episode->podcast_id])->with(
'message', 'message',
lang('Episode.messages.deleteSuccess') lang('Episode.messages.deleteSuccess')
); );
} }
public function embed(): string public function embedView(Episode $episode): string
{ {
helper(['form']); helper(['form']);
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $episode->podcast,
'episode' => $this->episode, 'episode' => $episode,
'themes' => EpisodeModel::$themes, 'themes' => EpisodeModel::$themes,
]; ];
$this->setHtmlHead(lang('Episode.embed.title')); $this->setHtmlHead(lang('Episode.embed.title'));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $episode->podcast->at_handle,
1 => $this->episode->title, 1 => $episode->title,
]); ]);
return view('episode/embed', $data); return view('episode/embed', $data);
} }
public function attemptCommentCreate(): RedirectResponse public function commentCreateAction(Episode $episode): RedirectResponse
{ {
$rules = [ $rules = [
'message' => 'required|max_length[500]', 'message' => 'required|max_length[500]',
@ -962,7 +954,7 @@ class EpisodeController extends BaseController
$newComment = new EpisodeComment([ $newComment = new EpisodeComment([
'actor_id' => interact_as_actor_id(), 'actor_id' => interact_as_actor_id(),
'episode_id' => $this->episode->id, 'episode_id' => $episode->id,
'message' => $validData['message'], 'message' => $validData['message'],
'created_at' => new Time('now'), 'created_at' => new Time('now'),
'created_by' => user_id(), 'created_by' => user_id(),
@ -982,7 +974,7 @@ class EpisodeController extends BaseController
return redirect()->back(); return redirect()->back();
} }
public function attemptCommentReply(string $commentId): RedirectResponse public function commentReplyAction(Episode $episode, string $commentId): RedirectResponse
{ {
$rules = [ $rules = [
'message' => 'required|max_length[500]', 'message' => 'required|max_length[500]',
@ -999,7 +991,7 @@ class EpisodeController extends BaseController
$newReply = new EpisodeComment([ $newReply = new EpisodeComment([
'actor_id' => interact_as_actor_id(), 'actor_id' => interact_as_actor_id(),
'episode_id' => $this->episode->id, 'episode_id' => $episode->id,
'message' => $validData['message'], 'message' => $validData['message'],
'in_reply_to_id' => $commentId, 'in_reply_to_id' => $commentId,
'created_at' => new Time('now'), 'created_at' => new Time('now'),

View File

@ -20,54 +20,52 @@ use CodeIgniter\HTTP\RedirectResponse;
class EpisodePersonController extends BaseController class EpisodePersonController extends BaseController
{ {
protected Podcast $podcast;
protected Episode $episode;
public function _remap(string $method, string ...$params): mixed public function _remap(string $method, string ...$params): mixed
{ {
if (count($params) < 2) { if ($params === []) {
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
} }
if ( if (count($params) === 1) {
($this->podcast = (new PodcastModel())->getPodcastById((int) $params[0])) && if (! ($podcast = (new PodcastModel())->getPodcastById((int) $params[0])) instanceof Podcast) {
($this->episode = (new EpisodeModel()) throw PageNotFoundException::forPageNotFound();
->where([ }
'id' => $params[1],
'podcast_id' => $params[0],
])
->first())
) {
unset($params[1]);
unset($params[0]);
return $this->{$method}(...$params); return $this->{$method}($podcast);
} }
throw PageNotFoundException::forPageNotFound(); if (
! ($episode = (new EpisodeModel())->getEpisodeById((int) $params[1]) instanceof Episode)
) {
throw PageNotFoundException::forPageNotFound();
}
unset($params[0]);
unset($params[1]);
return $this->{$method}($episode, ...$params);
} }
public function index(): string public function index(Episode $episode): string
{ {
helper('form'); helper('form');
$data = [ $data = [
'episode' => $this->episode, 'episode' => $episode,
'podcast' => $this->podcast, 'podcast' => $episode->podcast,
'personOptions' => (new PersonModel())->getPersonOptions(), 'personOptions' => (new PersonModel())->getPersonOptions(),
'taxonomyOptions' => (new PersonModel())->getTaxonomyOptions(), 'taxonomyOptions' => (new PersonModel())->getTaxonomyOptions(),
]; ];
$this->setHtmlHead(lang('Person.episode_form.title')); $this->setHtmlHead(lang('Person.episode_form.title'));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $episode->podcast->at_handle,
1 => $this->episode->title, 1 => $episode->title,
]); ]);
return view('episode/persons', $data); return view('episode/persons', $data);
} }
public function attemptCreate(): RedirectResponse public function createAction(Episode $episode): RedirectResponse
{ {
$rules = [ $rules = [
'persons' => 'required', 'persons' => 'required',
@ -83,8 +81,8 @@ class EpisodePersonController extends BaseController
$validData = $this->validator->getValidated(); $validData = $this->validator->getValidated();
(new PersonModel())->addEpisodePersons( (new PersonModel())->addEpisodePersons(
$this->podcast->id, $episode->podcast_id,
$this->episode->id, $episode->id,
$validData['persons'], $validData['persons'],
$this->request->getPost('roles') ?? [], $this->request->getPost('roles') ?? [],
); );
@ -92,9 +90,9 @@ class EpisodePersonController extends BaseController
return redirect()->back(); return redirect()->back();
} }
public function remove(string $personId): RedirectResponse public function deleteAction(Episode $episode, string $personId): RedirectResponse
{ {
(new PersonModel())->removePersonFromEpisode($this->podcast->id, $this->episode->id, (int) $personId); (new PersonModel())->removePersonFromEpisode($episode->podcast_id, $episode->id, (int) $personId);
return redirect()->back(); return redirect()->back();
} }

View File

@ -19,7 +19,7 @@ class FediverseController extends BaseController
return redirect()->route('fediverse-blocked-actors'); return redirect()->route('fediverse-blocked-actors');
} }
public function blockedActors(): string public function blockedActorsView(): string
{ {
helper(['form']); helper(['form']);
@ -32,7 +32,7 @@ class FediverseController extends BaseController
]); ]);
} }
public function blockedDomains(): string public function blockedDomainsView(): string
{ {
helper(['form']); helper(['form']);

View File

@ -27,70 +27,52 @@ class NotificationController extends BaseController
public function _remap(string $method, string ...$params): mixed public function _remap(string $method, string ...$params): mixed
{ {
if ($params === []) {
throw PageNotFoundException::forPageNotFound();
}
if ( if (
! ($podcast = (new PodcastModel())->getPodcastById((int) $params[0])) instanceof Podcast ! ($podcast = (new PodcastModel())->getPodcastById((int) $params[0])) instanceof Podcast
) { ) {
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
} }
$this->podcast = $podcast; $params[0] = $podcast;
if (count($params) > 1) { if (count($params) > 1) {
if ( if (
! ($notification = (new NotificationModel()) ! ($notification = (new NotificationModel())->find($params[1])) instanceof Notification
->where([
'id' => $params[1],
])
->first()) instanceof Notification
) { ) {
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
} }
$this->notification = $notification; $params[1] = $notification;
unset($params[1]);
unset($params[0]);
} }
return $this->{$method}(...$params); return $this->{$method}(...$params);
} }
public function list(): string public function list(Podcast $podcast): string
{ {
$notifications = (new NotificationModel())->where('target_actor_id', $this->podcast->actor_id) $notifications = (new NotificationModel())->where('target_actor_id', $podcast->actor_id)
->orderBy('created_at', 'desc'); ->orderBy('created_at', 'desc');
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $podcast,
'notifications' => $notifications->paginate(10), 'notifications' => $notifications->paginate(10),
'pager' => $notifications->pager, 'pager' => $notifications->pager,
]; ];
$this->setHtmlHead(lang('Notifications.title')); $this->setHtmlHead(lang('Notifications.title'));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $podcast->at_handle,
]); ]);
return view('podcast/notifications', $data); return view('podcast/notifications', $data);
} }
public function markAsRead(): RedirectResponse public function markAllAsReadAction(Podcast $podcast): RedirectResponse
{ {
$this->notification->read_at = new Time('now'); $notifications = (new NotificationModel())->where('target_actor_id', $podcast->actor_id)
$notificationModel = new NotificationModel();
$notificationModel->update($this->notification->id, $this->notification);
if ($this->notification->post_id === null) {
return redirect()->route('podcast-activity', [esc($this->podcast->handle)]);
}
$post = (new PostModel())->getPostById($this->notification->post_id);
return redirect()->route('post', [$this->podcast->handle, $post->id]);
}
public function markAllAsRead(): RedirectResponse
{
$notifications = (new NotificationModel())->where('target_actor_id', $this->podcast->actor_id)
->where('read_at', null) ->where('read_at', null)
->findAll(); ->findAll();
@ -101,4 +83,19 @@ class NotificationController extends BaseController
return redirect()->back(); return redirect()->back();
} }
public function markAsReadAction(Podcast $podcast, Notification $notification): RedirectResponse
{
$notification->read_at = new Time('now');
$notificationModel = new NotificationModel();
$notificationModel->update($notification->id, $notification);
if ($notification->post_id === null) {
return redirect()->route('podcast-activity', [esc($podcast->handle)]);
}
$post = (new PostModel())->getPostById($notification->post_id);
return redirect()->route('post', [$podcast->handle, $post->id]);
}
} }

View File

@ -17,16 +17,14 @@ use CodeIgniter\HTTP\RedirectResponse;
class PageController extends BaseController class PageController extends BaseController
{ {
protected ?Page $page = null;
public function _remap(string $method, string ...$params): mixed public function _remap(string $method, string ...$params): mixed
{ {
if ($params === []) { if ($params === []) {
return $this->{$method}(); return $this->{$method}();
} }
if (($this->page = (new PageModel())->find($params[0])) instanceof Page) { if (($page = (new PageModel())->find($params[0])) instanceof Page) {
return $this->{$method}(); return $this->{$method}($page);
} }
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
@ -42,15 +40,15 @@ class PageController extends BaseController
return view('page/list', $data); return view('page/list', $data);
} }
public function view(): string public function view(Page $page): string
{ {
$this->setHtmlHead($this->page->title); $this->setHtmlHead($page->title);
return view('page/view', [ return view('page/view', [
'page' => $this->page, 'page' => $page,
]); ]);
} }
public function create(): string public function createView(): string
{ {
helper('form'); helper('form');
@ -58,7 +56,7 @@ class PageController extends BaseController
return view('page/create'); return view('page/create');
} }
public function attemptCreate(): RedirectResponse public function createAction(): RedirectResponse
{ {
$page = new Page([ $page = new Page([
'title' => $this->request->getPost('title'), 'title' => $this->request->getPost('title'),
@ -82,40 +80,40 @@ class PageController extends BaseController
])); ]));
} }
public function edit(): string public function editView(Page $page): string
{ {
helper('form'); helper('form');
$this->setHtmlHead(lang('Page.edit')); $this->setHtmlHead(lang('Page.edit'));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->page->title, 0 => $page->title,
]); ]);
return view('page/edit', [ return view('page/edit', [
'page' => $this->page, 'page' => $page,
]); ]);
} }
public function attemptEdit(): RedirectResponse public function editAction(Page $page): RedirectResponse
{ {
$this->page->title = $this->request->getPost('title'); $page->title = $this->request->getPost('title');
$this->page->slug = $this->request->getPost('slug'); $page->slug = $this->request->getPost('slug');
$this->page->content_markdown = $this->request->getPost('content'); $page->content_markdown = $this->request->getPost('content');
$pageModel = new PageModel(); $pageModel = new PageModel();
if (! $pageModel->update($this->page->id, $this->page)) { if (! $pageModel->update($page->id, $page)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
->with('errors', $pageModel->errors()); ->with('errors', $pageModel->errors());
} }
return redirect()->route('page-edit', [$this->page->id])->with('message', lang('Page.messages.editSuccess')); return redirect()->route('page-edit', [$page->id])->with('message', lang('Page.messages.editSuccess'));
} }
public function delete(): RedirectResponse public function deleteAction(Page $page): RedirectResponse
{ {
(new PageModel())->delete($this->page->id); (new PageModel())->delete($page->id);
return redirect()->route('page-list'); return redirect()->route('page-list');
} }

View File

@ -18,8 +18,6 @@ use Modules\Media\Models\MediaModel;
class PersonController extends BaseController class PersonController extends BaseController
{ {
protected ?Person $person = null;
public function _remap(string $method, string ...$params): mixed public function _remap(string $method, string ...$params): mixed
{ {
if ($params === []) { if ($params === []) {
@ -27,15 +25,15 @@ class PersonController extends BaseController
} }
if ( if (
($this->person = (new PersonModel())->getPersonById((int) $params[0])) instanceof Person ($person = (new PersonModel())->getPersonById((int) $params[0])) instanceof Person
) { ) {
return $this->{$method}(); return $this->{$method}($person);
} }
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
} }
public function index(): string public function list(): string
{ {
$data = [ $data = [
'persons' => (new PersonModel())->orderBy('full_name') 'persons' => (new PersonModel())->orderBy('full_name')
@ -46,20 +44,20 @@ class PersonController extends BaseController
return view('person/list', $data); return view('person/list', $data);
} }
public function view(): string public function view(Person $person): string
{ {
$data = [ $data = [
'person' => $this->person, 'person' => $person,
]; ];
$this->setHtmlHead($this->person->full_name); $this->setHtmlHead($person->full_name);
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->person->full_name, 0 => $person->full_name,
]); ]);
return view('person/view', $data); return view('person/view', $data);
} }
public function create(): string public function createView(): string
{ {
helper(['form']); helper(['form']);
@ -67,7 +65,7 @@ class PersonController extends BaseController
return view('person/create'); return view('person/create');
} }
public function attemptCreate(): RedirectResponse public function createAction(): RedirectResponse
{ {
$rules = [ $rules = [
'avatar' => 'is_image[avatar]|ext_in[avatar,jpg,jpeg,png]|min_dims[avatar,400,400]|is_image_ratio[avatar,1,1]', 'avatar' => 'is_image[avatar]|ext_in[avatar,jpg,jpeg,png]|min_dims[avatar,400,400]|is_image_ratio[avatar,1,1]',
@ -107,22 +105,22 @@ class PersonController extends BaseController
->with('message', lang('Person.messages.createSuccess')); ->with('message', lang('Person.messages.createSuccess'));
} }
public function edit(): string public function editView(Person $person): string
{ {
helper('form'); helper('form');
$data = [ $data = [
'person' => $this->person, 'person' => $person,
]; ];
$this->setHtmlHead(lang('Person.edit')); $this->setHtmlHead(lang('Person.edit'));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->person->full_name, 0 => $person->full_name,
]); ]);
return view('person/edit', $data); return view('person/edit', $data);
} }
public function attemptEdit(): RedirectResponse public function editAction(Person $person): RedirectResponse
{ {
$rules = [ $rules = [
'avatar' => 'is_image[avatar]|ext_in[avatar,jpg,jpeg,png]|min_dims[avatar,400,400]|is_image_ratio[avatar,1,1]', 'avatar' => 'is_image[avatar]|ext_in[avatar,jpg,jpeg,png]|min_dims[avatar,400,400]|is_image_ratio[avatar,1,1]',
@ -135,34 +133,34 @@ class PersonController extends BaseController
->with('errors', $this->validator->getErrors()); ->with('errors', $this->validator->getErrors());
} }
$this->person->updated_by = user_id(); $person->updated_by = user_id();
$this->person->full_name = $this->request->getPost('full_name'); $person->full_name = $this->request->getPost('full_name');
$this->person->unique_name = $this->request->getPost('unique_name'); $person->unique_name = $this->request->getPost('unique_name');
$this->person->information_url = $this->request->getPost('information_url'); $person->information_url = $this->request->getPost('information_url');
$this->person->setAvatar($this->request->getFile('avatar')); $person->setAvatar($this->request->getFile('avatar'));
$personModel = new PersonModel(); $personModel = new PersonModel();
if (! $personModel->update($this->person->id, $this->person)) { if (! $personModel->update($person->id, $person)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
->with('errors', $personModel->errors()); ->with('errors', $personModel->errors());
} }
return redirect()->route('person-edit', [$this->person->id])->with( return redirect()->route('person-edit', [$person->id])->with(
'message', 'message',
lang('Person.messages.editSuccess') lang('Person.messages.editSuccess')
); );
} }
public function delete(): RedirectResponse public function deleteAction(Person $person): RedirectResponse
{ {
if ($this->person->avatar_id !== null) { if ($person->avatar_id !== null) {
// delete avatar to prevent collision if recreating person // delete avatar to prevent collision if recreating person
(new MediaModel())->deleteMedia($this->person->avatar); (new MediaModel())->deleteMedia($person->avatar);
} }
(new PersonModel())->delete($this->person->id); (new PersonModel())->delete($person->id);
return redirect()->route('person-list') return redirect()->route('person-list')
->with('message', lang('Person.messages.deleteSuccess')); ->with('message', lang('Person.messages.deleteSuccess'));

View File

@ -38,8 +38,6 @@ use Modules\Media\Models\MediaModel;
class PodcastController extends BaseController class PodcastController extends BaseController
{ {
protected Podcast $podcast;
public function _remap(string $method, string ...$params): mixed public function _remap(string $method, string ...$params): mixed
{ {
if ($params === []) { if ($params === []) {
@ -49,8 +47,7 @@ class PodcastController extends BaseController
if ( if (
($podcast = (new PodcastModel())->getPodcastById((int) $params[0])) instanceof Podcast ($podcast = (new PodcastModel())->getPodcastById((int) $params[0])) instanceof Podcast
) { ) {
$this->podcast = $podcast; return $this->{$method}($podcast);
return $this->{$method}();
} }
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
@ -72,111 +69,111 @@ class PodcastController extends BaseController
return view('podcast/list', $data); return view('podcast/list', $data);
} }
public function view(): string public function view(Podcast $podcast): string
{ {
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $podcast,
]; ];
$this->setHtmlHead($this->podcast->title); $this->setHtmlHead($podcast->title);
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $podcast->at_handle,
]); ]);
return view('podcast/view', $data); return view('podcast/view', $data);
} }
public function viewAnalytics(): string public function analyticsView(Podcast $podcast): string
{ {
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $podcast,
]; ];
$this->setHtmlHead($this->podcast->title); $this->setHtmlHead($podcast->title);
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $podcast->at_handle,
]); ]);
return view('podcast/analytics/index', $data); return view('podcast/analytics/index', $data);
} }
public function viewAnalyticsWebpages(): string public function analyticsWebpagesView(Podcast $podcast): string
{ {
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $podcast,
]; ];
$this->setHtmlHead($this->podcast->title); $this->setHtmlHead($podcast->title);
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $podcast->at_handle,
]); ]);
return view('podcast/analytics/webpages', $data); return view('podcast/analytics/webpages', $data);
} }
public function viewAnalyticsLocations(): string public function analyticsLocationsView(Podcast $podcast): string
{ {
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $podcast,
]; ];
$this->setHtmlHead($this->podcast->title); $this->setHtmlHead($podcast->title);
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $podcast->at_handle,
]); ]);
return view('podcast/analytics/locations', $data); return view('podcast/analytics/locations', $data);
} }
public function viewAnalyticsUniqueListeners(): string public function analyticsUniqueListenersView(Podcast $podcast): string
{ {
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $podcast,
]; ];
$this->setHtmlHead($this->podcast->title); $this->setHtmlHead($podcast->title);
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $podcast->at_handle,
]); ]);
return view('podcast/analytics/unique_listeners', $data); return view('podcast/analytics/unique_listeners', $data);
} }
public function viewAnalyticsListeningTime(): string public function analyticsListeningTimeView(Podcast $podcast): string
{ {
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $podcast,
]; ];
$this->setHtmlHead($this->podcast->title); $this->setHtmlHead($podcast->title);
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $podcast->at_handle,
]); ]);
return view('podcast/analytics/listening_time', $data); return view('podcast/analytics/listening_time', $data);
} }
public function viewAnalyticsTimePeriods(): string public function analyticsTimePeriodsView(Podcast $podcast): string
{ {
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $podcast,
]; ];
$this->setHtmlHead($this->podcast->title); $this->setHtmlHead($podcast->title);
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $podcast->at_handle,
]); ]);
return view('podcast/analytics/time_periods', $data); return view('podcast/analytics/time_periods', $data);
} }
public function viewAnalyticsPlayers(): string public function analyticsPlayersView(Podcast $podcast): string
{ {
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $podcast,
]; ];
$this->setHtmlHead($this->podcast->title); $this->setHtmlHead($podcast->title);
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $podcast->at_handle,
]); ]);
return view('podcast/analytics/players', $data); return view('podcast/analytics/players', $data);
} }
public function create(): string public function createView(): string
{ {
helper(['form', 'misc']); helper(['form', 'misc']);
@ -193,7 +190,7 @@ class PodcastController extends BaseController
return view('podcast/create', $data); return view('podcast/create', $data);
} }
public function attemptCreate(): RedirectResponse public function createAction(): RedirectResponse
{ {
$rules = [ $rules = [
'cover' => 'uploaded[cover]|is_image[cover]|ext_in[cover,jpg,jpeg,png]|min_dims[cover,1400,1400]|is_image_ratio[cover,1,1]', 'cover' => 'uploaded[cover]|is_image[cover]|ext_in[cover,jpg,jpeg,png]|min_dims[cover,1400,1400]|is_image_ratio[cover,1,1]',
@ -267,7 +264,7 @@ class PodcastController extends BaseController
); );
} }
public function edit(): string public function editView(Podcast $podcast): string
{ {
helper('form'); helper('form');
@ -275,19 +272,19 @@ class PodcastController extends BaseController
$categoryOptions = (new CategoryModel())->getCategoryOptions(); $categoryOptions = (new CategoryModel())->getCategoryOptions();
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $podcast,
'languageOptions' => $languageOptions, 'languageOptions' => $languageOptions,
'categoryOptions' => $categoryOptions, 'categoryOptions' => $categoryOptions,
]; ];
$this->setHtmlHead(lang('Podcast.edit')); $this->setHtmlHead(lang('Podcast.edit'));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $podcast->at_handle,
]); ]);
return view('podcast/edit', $data); return view('podcast/edit', $data);
} }
public function attemptEdit(): RedirectResponse public function editAction(Podcast $podcast): RedirectResponse
{ {
$rules = [ $rules = [
'cover' => 'is_image[cover]|ext_in[cover,jpg,jpeg,png]|min_dims[cover,1400,1400]|is_image_ratio[cover,1,1]', 'cover' => 'is_image[cover]|ext_in[cover,jpg,jpeg,png]|min_dims[cover,1400,1400]|is_image_ratio[cover,1,1]',
@ -301,46 +298,46 @@ class PodcastController extends BaseController
->with('errors', $this->validator->getErrors()); ->with('errors', $this->validator->getErrors());
} }
$this->podcast->updated_by = (int) user_id(); $podcast->updated_by = (int) user_id();
$this->podcast->title = $this->request->getPost('title'); $podcast->title = $this->request->getPost('title');
$this->podcast->description_markdown = $this->request->getPost('description'); $podcast->description_markdown = $this->request->getPost('description');
$this->podcast->setCover($this->request->getFile('cover')); $podcast->setCover($this->request->getFile('cover'));
$this->podcast->setBanner($this->request->getFile('banner')); $podcast->setBanner($this->request->getFile('banner'));
$this->podcast->language_code = $this->request->getPost('language'); $podcast->language_code = $this->request->getPost('language');
$this->podcast->category_id = $this->request->getPost('category'); $podcast->category_id = $this->request->getPost('category');
$this->podcast->parental_advisory = $podcast->parental_advisory =
$this->request->getPost('parental_advisory') !== 'undefined' $this->request->getPost('parental_advisory') !== 'undefined'
? $this->request->getPost('parental_advisory') ? $this->request->getPost('parental_advisory')
: null; : null;
$this->podcast->publisher = $this->request->getPost('publisher'); $podcast->publisher = $this->request->getPost('publisher');
$this->podcast->owner_name = $this->request->getPost('owner_name'); $podcast->owner_name = $this->request->getPost('owner_name');
$this->podcast->owner_email = $this->request->getPost('owner_email'); $podcast->owner_email = $this->request->getPost('owner_email');
$this->podcast->type = $this->request->getPost('type'); $podcast->type = $this->request->getPost('type');
$this->podcast->copyright = $this->request->getPost('copyright'); $podcast->copyright = $this->request->getPost('copyright');
$this->podcast->location = $this->request->getPost('location_name') === '' ? null : new Location( $podcast->location = $this->request->getPost('location_name') === '' ? null : new Location(
$this->request->getPost('location_name') $this->request->getPost('location_name')
); );
$this->podcast->new_feed_url = $this->request->getPost('new_feed_url') === '' ? null : $this->request->getPost( $podcast->new_feed_url = $this->request->getPost('new_feed_url') === '' ? null : $this->request->getPost(
'new_feed_url' 'new_feed_url'
); );
$this->podcast->is_blocked = $this->request->getPost('block') === 'yes'; $podcast->is_blocked = $this->request->getPost('block') === 'yes';
$this->podcast->is_completed = $podcast->is_completed =
$this->request->getPost('complete') === 'yes'; $this->request->getPost('complete') === 'yes';
$this->podcast->is_locked = $this->request->getPost('lock') === 'yes'; $podcast->is_locked = $this->request->getPost('lock') === 'yes';
$this->podcast->is_premium_by_default = $this->request->getPost('premium_by_default') === 'yes'; $podcast->is_premium_by_default = $this->request->getPost('premium_by_default') === 'yes';
// republish on websub hubs upon edit // republish on websub hubs upon edit
$this->podcast->is_published_on_hubs = false; $podcast->is_published_on_hubs = false;
$db = db_connect(); $db = db_connect();
$db->transStart(); $db->transStart();
$podcastModel = new PodcastModel(); $podcastModel = new PodcastModel();
if (! $podcastModel->update($this->podcast->id, $this->podcast)) { if (! $podcastModel->update($podcast->id, $podcast)) {
$db->transRollback(); $db->transRollback();
return redirect() return redirect()
->back() ->back()
@ -350,21 +347,21 @@ class PodcastController extends BaseController
// set Podcast categories // set Podcast categories
(new CategoryModel())->setPodcastCategories( (new CategoryModel())->setPodcastCategories(
$this->podcast->id, $podcast->id,
$this->request->getPost('other_categories') ?? [], $this->request->getPost('other_categories') ?? [],
); );
$db->transComplete(); $db->transComplete();
return redirect()->route('podcast-edit', [$this->podcast->id])->with( return redirect()->route('podcast-edit', [$podcast->id])->with(
'message', 'message',
lang('Podcast.messages.editSuccess') lang('Podcast.messages.editSuccess')
); );
} }
public function deleteBanner(): RedirectResponse public function deleteBannerAction(Podcast $podcast): RedirectResponse
{ {
if (! $this->podcast->banner instanceof Image) { if (! $podcast->banner instanceof Image) {
return redirect()->back(); return redirect()->back();
} }
@ -373,7 +370,7 @@ class PodcastController extends BaseController
$db->transStart(); $db->transStart();
$mediaModel = new MediaModel(); $mediaModel = new MediaModel();
if (! $mediaModel->deleteMedia($this->podcast->banner)) { if (! $mediaModel->deleteMedia($podcast->banner)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -381,11 +378,11 @@ class PodcastController extends BaseController
} }
(new PodcastModel())->clearCache([ (new PodcastModel())->clearCache([
'id' => $this->podcast->id, 'id' => $podcast->id,
]); ]);
// remove banner url from actor // remove banner url from actor
$actor = (new ActorModel())->getActorById($this->podcast->actor_id); $actor = (new ActorModel())->getActorById($podcast->actor_id);
if ($actor instanceof Actor) { if ($actor instanceof Actor) {
$actor->cover_image_url = null; $actor->cover_image_url = null;
@ -399,7 +396,7 @@ class PodcastController extends BaseController
return redirect()->back(); return redirect()->back();
} }
public function latestEpisodes(int $limit, int $podcastId): string public function latestEpisodesView(int $limit, int $podcastId): string
{ {
$episodes = (new EpisodeModel()) $episodes = (new EpisodeModel())
->where('podcast_id', $podcastId) ->where('podcast_id', $podcastId)
@ -413,22 +410,22 @@ class PodcastController extends BaseController
]); ]);
} }
public function delete(): string public function deleteView(Podcast $podcast): string
{ {
helper(['form']); helper(['form']);
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $podcast,
]; ];
$this->setHtmlHead(lang('Podcast.delete')); $this->setHtmlHead(lang('Podcast.delete'));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $podcast->at_handle,
]); ]);
return view('podcast/delete', $data); return view('podcast/delete', $data);
} }
public function attemptDelete(): RedirectResponse public function deleteAction(Podcast $podcast): RedirectResponse
{ {
$rules = [ $rules = [
'understand' => 'required', 'understand' => 'required',
@ -446,7 +443,7 @@ class PodcastController extends BaseController
$db->transStart(); $db->transStart();
//delete podcast episodes //delete podcast episodes
$podcastEpisodes = (new EpisodeModel())->where('podcast_id', $this->podcast->id) $podcastEpisodes = (new EpisodeModel())->where('podcast_id', $podcast->id)
->findAll(); ->findAll();
foreach ($podcastEpisodes as $podcastEpisode) { foreach ($podcastEpisodes as $podcastEpisode) {
@ -486,7 +483,7 @@ class PodcastController extends BaseController
//delete podcast //delete podcast
$podcastModel = new PodcastModel(); $podcastModel = new PodcastModel();
if (! $podcastModel->delete($this->podcast->id)) { if (! $podcastModel->delete($podcast->id)) {
$db->transRollback(); $db->transRollback();
return redirect() return redirect()
->back() ->back()
@ -498,15 +495,15 @@ class PodcastController extends BaseController
$podcastMediaList = [ $podcastMediaList = [
[ [
'type' => 'cover', 'type' => 'cover',
'file' => $this->podcast->cover, 'file' => $podcast->cover,
], ],
]; ];
if ($this->podcast->banner_id !== null) { if ($podcast->banner_id !== null) {
$podcastMediaList[] = $podcastMediaList[] =
[ [
'type' => 'banner', 'type' => 'banner',
'file' => $this->podcast->banner, 'file' => $podcast->banner,
]; ];
} }
@ -527,7 +524,7 @@ class PodcastController extends BaseController
//delete podcast actor //delete podcast actor
$actorModel = new ActorModel(); $actorModel = new ActorModel();
if (! $actorModel->delete($this->podcast->actor_id)) { if (! $actorModel->delete($podcast->actor_id)) {
$db->transRollback(); $db->transRollback();
return redirect() return redirect()
->back() ->back()
@ -549,7 +546,7 @@ class PodcastController extends BaseController
]; ];
foreach ($analyticsModels as $analyticsModel) { foreach ($analyticsModels as $analyticsModel) {
if (! $analyticsModel->where([ if (! $analyticsModel->where([
'podcast_id' => $this->podcast->id, 'podcast_id' => $podcast->id,
])->delete()) { ])->delete()) {
$db->transRollback(); $db->transRollback();
return redirect() return redirect()
@ -565,11 +562,11 @@ class PodcastController extends BaseController
$fileManager = service('file_manager'); $fileManager = service('file_manager');
//delete podcast media files and folder //delete podcast media files and folder
$folder = 'podcasts/' . $this->podcast->handle; $folder = 'podcasts/' . $podcast->handle;
if (! $fileManager->deleteAll($folder)) { if (! $fileManager->deleteAll($folder)) {
return redirect()->route('podcast-list') return redirect()->route('podcast-list')
->with('message', lang('Podcast.messages.deleteSuccess', [ ->with('message', lang('Podcast.messages.deleteSuccess', [
'podcast_handle' => $this->podcast->handle, 'podcast_handle' => $podcast->handle,
])) ]))
->with('warning', lang('Podcast.messages.deletePodcastMediaFolderError', [ ->with('warning', lang('Podcast.messages.deletePodcastMediaFolderError', [
'folder_path' => $folder, 'folder_path' => $folder,
@ -578,29 +575,29 @@ class PodcastController extends BaseController
return redirect()->route('podcast-list') return redirect()->route('podcast-list')
->with('message', lang('Podcast.messages.deleteSuccess', [ ->with('message', lang('Podcast.messages.deleteSuccess', [
'podcast_handle' => $this->podcast->handle, 'podcast_handle' => $podcast->handle,
])); ]));
} }
public function publish(): string | RedirectResponse public function publishView(Podcast $podcast): string | RedirectResponse
{ {
helper(['form']); helper(['form']);
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $podcast,
]; ];
$this->setHtmlHead(lang('Podcast.publish')); $this->setHtmlHead(lang('Podcast.publish'));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $podcast->at_handle,
]); ]);
return view('podcast/publish', $data); return view('podcast/publish', $data);
} }
public function attemptPublish(): RedirectResponse public function publishAction(Podcast $podcast): RedirectResponse
{ {
if ($this->podcast->publication_status !== 'not_published') { if ($podcast->publication_status !== 'not_published') {
return redirect()->route('podcast-view', [$this->podcast->id])->with( return redirect()->route('podcast-view', [$podcast->id])->with(
'error', 'error',
lang('Podcast.messages.publishError') lang('Podcast.messages.publishError')
); );
@ -627,7 +624,7 @@ class PodcastController extends BaseController
if ($publishMethod === 'schedule') { if ($publishMethod === 'schedule') {
$scheduledPublicationDate = $validData['scheduled_publication_date']; $scheduledPublicationDate = $validData['scheduled_publication_date'];
if ($scheduledPublicationDate) { if ($scheduledPublicationDate) {
$this->podcast->published_at = Time::createFromFormat( $podcast->published_at = Time::createFromFormat(
'Y-m-d H:i', 'Y-m-d H:i',
$scheduledPublicationDate, $scheduledPublicationDate,
$this->request->getPost('client_timezone'), $this->request->getPost('client_timezone'),
@ -640,19 +637,19 @@ class PodcastController extends BaseController
->with('error', lang('Podcast.messages.scheduleDateError')); ->with('error', lang('Podcast.messages.scheduleDateError'));
} }
} else { } else {
$this->podcast->published_at = Time::now(); $podcast->published_at = Time::now();
} }
$message = $this->request->getPost('message'); $message = $this->request->getPost('message');
// only create post if message is not empty // only create post if message is not empty
if ($message !== '') { if ($message !== '') {
$newPost = new Post([ $newPost = new Post([
'actor_id' => $this->podcast->actor_id, 'actor_id' => $podcast->actor_id,
'message' => $message, 'message' => $message,
'created_by' => user_id(), 'created_by' => user_id(),
]); ]);
$newPost->published_at = $this->podcast->published_at; $newPost->published_at = $podcast->published_at;
$postModel = new PostModel(); $postModel = new PostModel();
if (! $postModel->addPost($newPost)) { if (! $postModel->addPost($newPost)) {
@ -665,12 +662,12 @@ class PodcastController extends BaseController
} }
$episodes = (new EpisodeModel()) $episodes = (new EpisodeModel())
->where('podcast_id', $this->podcast->id) ->where('podcast_id', $podcast->id)
->where('published_at !=', null) ->where('published_at !=', null)
->findAll(); ->findAll();
foreach ($episodes as $episode) { foreach ($episodes as $episode) {
$episode->published_at = $this->podcast->published_at->addSeconds(1); $episode->published_at = $podcast->published_at->addSeconds(1);
$episodeModel = new EpisodeModel(); $episodeModel = new EpisodeModel();
if (! $episodeModel->update($episode->id, $episode)) { if (! $episodeModel->update($episode->id, $episode)) {
@ -698,7 +695,7 @@ class PodcastController extends BaseController
} }
$podcastModel = new PodcastModel(); $podcastModel = new PodcastModel();
if (! $podcastModel->update($this->podcast->id, $this->podcast)) { if (! $podcastModel->update($podcast->id, $podcast)) {
$db->transRollback(); $db->transRollback();
return redirect() return redirect()
->back() ->back()
@ -708,18 +705,18 @@ class PodcastController extends BaseController
$db->transComplete(); $db->transComplete();
return redirect()->route('podcast-view', [$this->podcast->id]); return redirect()->route('podcast-view', [$podcast->id]);
} }
public function publishEdit(): string | RedirectResponse public function publishEditView(Podcast $podcast): string | RedirectResponse
{ {
helper(['form']); helper(['form']);
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $podcast,
'post' => (new PostModel()) 'post' => (new PostModel())
->where([ ->where([
'actor_id' => $this->podcast->actor_id, 'actor_id' => $podcast->actor_id,
'episode_id' => null, 'episode_id' => null,
]) ])
->first(), ->first(),
@ -727,15 +724,15 @@ class PodcastController extends BaseController
$this->setHtmlHead(lang('Podcast.publish_edit')); $this->setHtmlHead(lang('Podcast.publish_edit'));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $podcast->at_handle,
]); ]);
return view('podcast/publish_edit', $data); return view('podcast/publish_edit', $data);
} }
public function attemptPublishEdit(): RedirectResponse public function publishEditAction(Podcast $podcast): RedirectResponse
{ {
if ($this->podcast->publication_status !== 'scheduled') { if ($podcast->publication_status !== 'scheduled') {
return redirect()->route('podcast-view', [$this->podcast->id])->with( return redirect()->route('podcast-view', [$podcast->id])->with(
'error', 'error',
lang('Podcast.messages.publishEditError') lang('Podcast.messages.publishEditError')
); );
@ -762,7 +759,7 @@ class PodcastController extends BaseController
if ($publishMethod === 'schedule') { if ($publishMethod === 'schedule') {
$scheduledPublicationDate = $validData['scheduled_publication_date']; $scheduledPublicationDate = $validData['scheduled_publication_date'];
if ($scheduledPublicationDate) { if ($scheduledPublicationDate) {
$this->podcast->published_at = Time::createFromFormat( $podcast->published_at = Time::createFromFormat(
'Y-m-d H:i', 'Y-m-d H:i',
$scheduledPublicationDate, $scheduledPublicationDate,
$this->request->getPost('client_timezone'), $this->request->getPost('client_timezone'),
@ -775,12 +772,12 @@ class PodcastController extends BaseController
->with('error', lang('Podcast.messages.scheduleDateError')); ->with('error', lang('Podcast.messages.scheduleDateError'));
} }
} else { } else {
$this->podcast->published_at = Time::now(); $podcast->published_at = Time::now();
} }
$post = (new PostModel()) $post = (new PostModel())
->where([ ->where([
'actor_id' => $this->podcast->actor_id, 'actor_id' => $podcast->actor_id,
'episode_id' => null, 'episode_id' => null,
]) ])
->first(); ->first();
@ -791,7 +788,7 @@ class PodcastController extends BaseController
if ($newPostMessage !== '') { if ($newPostMessage !== '') {
// edit post if post exists and message is not empty // edit post if post exists and message is not empty
$post->message = $newPostMessage; $post->message = $newPostMessage;
$post->published_at = $this->podcast->published_at; $post->published_at = $podcast->published_at;
$postModel = new PostModel(); $postModel = new PostModel();
if (! $postModel->editPost($post)) { if (! $postModel->editPost($post)) {
@ -806,7 +803,7 @@ class PodcastController extends BaseController
$postModel = new PostModel(); $postModel = new PostModel();
$post = $postModel $post = $postModel
->where([ ->where([
'actor_id' => $this->podcast->actor_id, 'actor_id' => $podcast->actor_id,
'episode_id' => null, 'episode_id' => null,
]) ])
->first(); ->first();
@ -815,12 +812,12 @@ class PodcastController extends BaseController
} elseif ($newPostMessage !== '') { } elseif ($newPostMessage !== '') {
// create post if there is no post and message is not empty // create post if there is no post and message is not empty
$newPost = new Post([ $newPost = new Post([
'actor_id' => $this->podcast->actor_id, 'actor_id' => $podcast->actor_id,
'message' => $newPostMessage, 'message' => $newPostMessage,
'created_by' => user_id(), 'created_by' => user_id(),
]); ]);
$newPost->published_at = $this->podcast->published_at; $newPost->published_at = $podcast->published_at;
$postModel = new PostModel(); $postModel = new PostModel();
if (! $postModel->addPost($newPost)) { if (! $postModel->addPost($newPost)) {
@ -833,12 +830,12 @@ class PodcastController extends BaseController
} }
$episodes = (new EpisodeModel()) $episodes = (new EpisodeModel())
->where('podcast_id', $this->podcast->id) ->where('podcast_id', $podcast->id)
->where('published_at !=', null) ->where('published_at !=', null)
->findAll(); ->findAll();
foreach ($episodes as $episode) { foreach ($episodes as $episode) {
$episode->published_at = $this->podcast->published_at->addSeconds(1); $episode->published_at = $podcast->published_at->addSeconds(1);
$episodeModel = new EpisodeModel(); $episodeModel = new EpisodeModel();
if (! $episodeModel->update($episode->id, $episode)) { if (! $episodeModel->update($episode->id, $episode)) {
@ -866,7 +863,7 @@ class PodcastController extends BaseController
} }
$podcastModel = new PodcastModel(); $podcastModel = new PodcastModel();
if (! $podcastModel->update($this->podcast->id, $this->podcast)) { if (! $podcastModel->update($podcast->id, $podcast)) {
$db->transRollback(); $db->transRollback();
return redirect() return redirect()
->back() ->back()
@ -876,13 +873,13 @@ class PodcastController extends BaseController
$db->transComplete(); $db->transComplete();
return redirect()->route('podcast-view', [$this->podcast->id]); return redirect()->route('podcast-view', [$podcast->id]);
} }
public function publishCancel(): RedirectResponse public function publishCancelAction(Podcast $podcast): RedirectResponse
{ {
if ($this->podcast->publication_status !== 'scheduled') { if ($podcast->publication_status !== 'scheduled') {
return redirect()->route('podcast-view', [$this->podcast->id]); return redirect()->route('podcast-view', [$podcast->id]);
} }
$db = db_connect(); $db = db_connect();
@ -891,7 +888,7 @@ class PodcastController extends BaseController
$postModel = new PostModel(); $postModel = new PostModel();
$post = $postModel $post = $postModel
->where([ ->where([
'actor_id' => $this->podcast->actor_id, 'actor_id' => $podcast->actor_id,
'episode_id' => null, 'episode_id' => null,
]) ])
->first(); ->first();
@ -900,7 +897,7 @@ class PodcastController extends BaseController
} }
$episodes = (new EpisodeModel()) $episodes = (new EpisodeModel())
->where('podcast_id', $this->podcast->id) ->where('podcast_id', $podcast->id)
->where('published_at !=', null) ->where('published_at !=', null)
->findAll(); ->findAll();
@ -922,10 +919,10 @@ class PodcastController extends BaseController
$postModel->removePost($post); $postModel->removePost($post);
} }
$this->podcast->published_at = null; $podcast->published_at = null;
$podcastModel = new PodcastModel(); $podcastModel = new PodcastModel();
if (! $podcastModel->update($this->podcast->id, $this->podcast)) { if (! $podcastModel->update($podcast->id, $podcast)) {
$db->transRollback(); $db->transRollback();
return redirect() return redirect()
->back() ->back()
@ -935,7 +932,7 @@ class PodcastController extends BaseController
$db->transComplete(); $db->transComplete();
return redirect()->route('podcast-view', [$this->podcast->id])->with( return redirect()->route('podcast-view', [$podcast->id])->with(
'message', 'message',
lang('Podcast.messages.publishCancelSuccess') lang('Podcast.messages.publishCancelSuccess')
); );

View File

@ -27,34 +27,34 @@ class PodcastPersonController extends BaseController
} }
if ( if (
($this->podcast = (new PodcastModel())->getPodcastById((int) $params[0])) instanceof Podcast ($podcast = (new PodcastModel())->getPodcastById((int) $params[0])) instanceof Podcast
) { ) {
unset($params[0]); unset($params[0]);
return $this->{$method}(...$params); return $this->{$method}($podcast, ...$params);
} }
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
} }
public function index(): string public function index(Podcast $podcast): string
{ {
helper('form'); helper('form');
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $podcast,
'podcastPersons' => (new PersonModel())->getPodcastPersons($this->podcast->id), 'podcastPersons' => (new PersonModel())->getPodcastPersons($podcast->id),
'personOptions' => (new PersonModel())->getPersonOptions(), 'personOptions' => (new PersonModel())->getPersonOptions(),
'taxonomyOptions' => (new PersonModel())->getTaxonomyOptions(), 'taxonomyOptions' => (new PersonModel())->getTaxonomyOptions(),
]; ];
$this->setHtmlHead(lang('Person.podcast_form.title')); $this->setHtmlHead(lang('Person.podcast_form.title'));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $podcast->at_handle,
]); ]);
return view('podcast/persons', $data); return view('podcast/persons', $data);
} }
public function attemptCreate(): RedirectResponse public function createAction(Podcast $podcast): RedirectResponse
{ {
$rules = [ $rules = [
'persons' => 'required', 'persons' => 'required',
@ -70,7 +70,7 @@ class PodcastPersonController extends BaseController
$validData = $this->validator->getValidated(); $validData = $this->validator->getValidated();
(new PersonModel())->addPodcastPersons( (new PersonModel())->addPodcastPersons(
$this->podcast->id, $podcast->id,
$validData['persons'], $validData['persons'],
$this->request->getPost('roles') ?? [], $this->request->getPost('roles') ?? [],
); );
@ -78,9 +78,9 @@ class PodcastPersonController extends BaseController
return redirect()->back(); return redirect()->back();
} }
public function remove(string $personId): RedirectResponse public function deleteAction(Podcast $podcast, string $personId): RedirectResponse
{ {
(new PersonModel())->removePersonFromPodcast($this->podcast->id, (int) $personId); (new PersonModel())->removePersonFromPodcast($podcast->id, (int) $personId);
return redirect()->back(); return redirect()->back();
} }

View File

@ -34,7 +34,7 @@ class SettingsController extends BaseController
return view('settings/general'); return view('settings/general');
} }
public function attemptInstanceEdit(): RedirectResponse public function instanceEditAction(): RedirectResponse
{ {
$rules = [ $rules = [
'site_icon' => 'is_image[site_icon]|ext_in[site_icon,png,jpeg]|is_image_ratio[site_icon,1,1]|min_dims[image,512,512]|permit_empty', 'site_icon' => 'is_image[site_icon]|ext_in[site_icon,png,jpeg]|is_image_ratio[site_icon,1,1]|min_dims[image,512,512]|permit_empty',
@ -119,7 +119,7 @@ class SettingsController extends BaseController
return redirect('settings-general')->with('message', lang('Settings.instance.editSuccess')); return redirect('settings-general')->with('message', lang('Settings.instance.editSuccess'));
} }
public function deleteIcon(): RedirectResponse public function deleteIconAction(): RedirectResponse
{ {
/** @var FileManagerInterface $fileManager */ /** @var FileManagerInterface $fileManager */
$fileManager = service('file_manager'); $fileManager = service('file_manager');
@ -133,7 +133,7 @@ class SettingsController extends BaseController
return redirect('settings-general')->with('message', lang('Settings.instance.deleteIconSuccess')); return redirect('settings-general')->with('message', lang('Settings.instance.deleteIconSuccess'));
} }
public function regenerateImages(): RedirectResponse public function regenerateImagesAction(): RedirectResponse
{ {
/** @var Podcast[] $allPodcasts */ /** @var Podcast[] $allPodcasts */
$allPodcasts = (new PodcastModel())->findAll(); $allPodcasts = (new PodcastModel())->findAll();
@ -168,7 +168,7 @@ class SettingsController extends BaseController
return redirect('settings-general')->with('message', lang('Settings.images.regenerationSuccess')); return redirect('settings-general')->with('message', lang('Settings.images.regenerationSuccess'));
} }
public function runHousekeeping(): RedirectResponse public function housekeepingAction(): RedirectResponse
{ {
if ($this->request->getPost('reset_counts') === 'yes') { if ($this->request->getPost('reset_counts') === 'yes') {
// recalculate fediverse counts // recalculate fediverse counts
@ -200,14 +200,14 @@ class SettingsController extends BaseController
return redirect('settings-general')->with('message', lang('Settings.housekeeping.runSuccess')); return redirect('settings-general')->with('message', lang('Settings.housekeeping.runSuccess'));
} }
public function theme(): string public function themeView(): string
{ {
helper('form'); helper('form');
$this->setHtmlHead(lang('Settings.theme.title')); $this->setHtmlHead(lang('Settings.theme.title'));
return view('settings/theme'); return view('settings/theme');
} }
public function attemptSetInstanceTheme(): RedirectResponse public function themeAction(): RedirectResponse
{ {
$theme = $this->request->getPost('theme'); $theme = $this->request->getPost('theme');
service('settings') service('settings')

View File

@ -22,47 +22,38 @@ use Modules\Media\Models\MediaModel;
class SoundbiteController extends BaseController class SoundbiteController extends BaseController
{ {
protected Podcast $podcast;
protected Episode $episode;
public function _remap(string $method, string ...$params): mixed public function _remap(string $method, string ...$params): mixed
{ {
if ($params === []) {
throw PageNotFoundException::forPageNotFound();
}
if (count($params) === 1) {
if (! ($podcast = (new PodcastModel())->getPodcastById((int) $params[0])) instanceof Podcast) {
throw PageNotFoundException::forPageNotFound();
}
return $this->{$method}($podcast);
}
if ( if (
! ($podcast = (new PodcastModel())->getPodcastById((int) $params[0])) instanceof Podcast ! ($episode = (new EpisodeModel())->getEpisodeById((int) $params[1]) instanceof Episode)
) { ) {
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
} }
$this->podcast = $podcast; unset($params[0]);
unset($params[1]);
if (count($params) > 1) { return $this->{$method}($episode, ...$params);
if (
! ($episode = (new EpisodeModel())
->where([
'id' => $params[1],
'podcast_id' => $params[0],
])
->first()) instanceof Episode
) {
throw PageNotFoundException::forPageNotFound();
}
$this->episode = $episode;
unset($params[1]);
unset($params[0]);
}
return $this->{$method}(...$params);
} }
public function list(): string public function list(Episode $episode): string
{ {
$soundbitesBuilder = (new ClipModel('audio')) $soundbitesBuilder = (new ClipModel('audio'))
->where([ ->where([
'podcast_id' => $this->podcast->id, 'podcast_id' => $episode->podcast_id,
'episode_id' => $this->episode->id, 'episode_id' => $episode->id,
'type' => 'audio', 'type' => 'audio',
]) ])
->orderBy('created_at', 'desc'); ->orderBy('created_at', 'desc');
@ -70,38 +61,38 @@ class SoundbiteController extends BaseController
$soundbites = $soundbitesBuilder->paginate(10); $soundbites = $soundbitesBuilder->paginate(10);
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $episode->podcast,
'episode' => $this->episode, 'episode' => $episode,
'soundbites' => $soundbites, 'soundbites' => $soundbites,
'pager' => $soundbitesBuilder->pager, 'pager' => $soundbitesBuilder->pager,
]; ];
$this->setHtmlHead(lang('Soundbite.list.title')); $this->setHtmlHead(lang('Soundbite.list.title'));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $episode->podcast->at_handle,
1 => $this->episode->title, 1 => $episode->title,
]); ]);
return view('episode/soundbites_list', $data); return view('episode/soundbites_list', $data);
} }
public function create(): string public function createView(Episode $episode): string
{ {
helper(['form']); helper(['form']);
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $episode->podcast,
'episode' => $this->episode, 'episode' => $episode,
]; ];
$this->setHtmlHead(lang('Soundbite.form.title')); $this->setHtmlHead(lang('Soundbite.form.title'));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $episode->podcast->at_handle,
1 => $this->episode->title, 1 => $episode->title,
]); ]);
return view('episode/soundbites_new', $data); return view('episode/soundbites_new', $data);
} }
public function attemptCreate(): RedirectResponse public function createAction(Episode $episode): RedirectResponse
{ {
$rules = [ $rules = [
'title' => 'required', 'title' => 'required',
@ -124,8 +115,8 @@ class SoundbiteController extends BaseController
'duration' => (float) $validData['duration'], 'duration' => (float) $validData['duration'],
'type' => 'audio', 'type' => 'audio',
'status' => '', 'status' => '',
'podcast_id' => $this->podcast->id, 'podcast_id' => $episode->podcast_id,
'episode_id' => $this->episode->id, 'episode_id' => $episode->id,
'created_by' => user_id(), 'created_by' => user_id(),
'updated_by' => user_id(), 'updated_by' => user_id(),
]); ]);
@ -138,13 +129,13 @@ class SoundbiteController extends BaseController
->with('errors', $clipModel->errors()); ->with('errors', $clipModel->errors());
} }
return redirect()->route('soundbites-list', [$this->podcast->id, $this->episode->id])->with( return redirect()->route('soundbites-list', [$episode->podcast_id, $episode->id])->with(
'message', 'message',
lang('Soundbite.messages.createSuccess') lang('Soundbite.messages.createSuccess')
); );
} }
public function delete(string $soundbiteId): RedirectResponse public function deleteAction(Episode $episode, string $soundbiteId): RedirectResponse
{ {
$soundbite = (new ClipModel())->getSoundbiteById((int) $soundbiteId); $soundbite = (new ClipModel())->getSoundbiteById((int) $soundbiteId);
@ -154,9 +145,9 @@ class SoundbiteController extends BaseController
if ($soundbite->media === null) { if ($soundbite->media === null) {
// delete Clip directly // delete Clip directly
(new ClipModel())->deleteSoundbite($this->podcast->id, $this->episode->id, $soundbite->id); (new ClipModel())->deleteSoundbite($episode->podcast_id, $episode->id, $soundbite->id);
} else { } else {
(new ClipModel())->clearSoundbiteCache($this->podcast->id, $this->episode->id, $soundbite->id); (new ClipModel())->clearSoundbiteCache($episode->podcast_id, $episode->id, $soundbite->id);
$mediaModel = new MediaModel(); $mediaModel = new MediaModel();
// delete the soundbite file, the clip will be deleted on cascade // delete the soundbite file, the clip will be deleted on cascade
@ -168,7 +159,7 @@ class SoundbiteController extends BaseController
} }
} }
return redirect()->route('soundbites-list', [$this->podcast->id, $this->episode->id])->with( return redirect()->route('soundbites-list', [$episode->podcast_id, $episode->id])->with(
'message', 'message',
lang('Soundbite.messages.deleteSuccess') lang('Soundbite.messages.deleteSuccess')
); );

View File

@ -23,47 +23,38 @@ use Modules\Media\Models\MediaModel;
class VideoClipsController extends BaseController class VideoClipsController extends BaseController
{ {
protected Podcast $podcast;
protected Episode $episode;
public function _remap(string $method, string ...$params): mixed public function _remap(string $method, string ...$params): mixed
{ {
if ($params === []) {
throw PageNotFoundException::forPageNotFound();
}
if (count($params) === 1) {
if (! ($podcast = (new PodcastModel())->getPodcastById((int) $params[0])) instanceof Podcast) {
throw PageNotFoundException::forPageNotFound();
}
return $this->{$method}($podcast);
}
if ( if (
! ($podcast = (new PodcastModel())->getPodcastById((int) $params[0])) instanceof Podcast ! ($episode = (new EpisodeModel())->getEpisodeById((int) $params[1]) instanceof Episode)
) { ) {
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
} }
$this->podcast = $podcast; unset($params[0]);
unset($params[1]);
if (count($params) > 1) { return $this->{$method}($episode, ...$params);
if (
! ($episode = (new EpisodeModel())
->where([
'id' => $params[1],
'podcast_id' => $params[0],
])
->first()) instanceof Episode
) {
throw PageNotFoundException::forPageNotFound();
}
$this->episode = $episode;
unset($params[1]);
unset($params[0]);
}
return $this->{$method}(...$params);
} }
public function list(): string public function list(Episode $episode): string
{ {
$videoClipsBuilder = (new ClipModel('video')) $videoClipsBuilder = (new ClipModel('video'))
->where([ ->where([
'podcast_id' => $this->podcast->id, 'podcast_id' => $episode->podcast_id,
'episode_id' => $this->episode->id, 'episode_id' => $episode->id,
'type' => 'video', 'type' => 'video',
]) ])
->orderBy('created_at', 'desc'); ->orderBy('created_at', 'desc');
@ -76,27 +67,27 @@ class VideoClipsController extends BaseController
} }
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $episode->podcast,
'episode' => $this->episode, 'episode' => $episode,
'videoClips' => $videoClips, 'videoClips' => $videoClips,
'pager' => $videoClipsBuilder->pager, 'pager' => $videoClipsBuilder->pager,
]; ];
$this->setHtmlHead(lang('VideoClip.list.title')); $this->setHtmlHead(lang('VideoClip.list.title'));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $episode->podcast->at_handle,
1 => $this->episode->title, 1 => $episode->title,
]); ]);
return view('episode/video_clips_list', $data); return view('episode/video_clips_list', $data);
} }
public function view(string $videoClipId): string public function view(Episode $episode, string $videoClipId): string
{ {
$videoClip = (new ClipModel())->getVideoClipById((int) $videoClipId); $videoClip = (new ClipModel())->getVideoClipById((int) $videoClipId);
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $episode->podcast,
'episode' => $this->episode, 'episode' => $episode,
'videoClip' => $videoClip, 'videoClip' => $videoClip,
]; ];
@ -104,23 +95,23 @@ class VideoClipsController extends BaseController
'videoClipLabel' => esc($videoClip->title), 'videoClipLabel' => esc($videoClip->title),
])); ]));
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $episode->podcast->at_handle,
1 => $this->episode->title, 1 => $episode->title,
2 => $videoClip->title, 2 => $videoClip->title,
]); ]);
return view('episode/video_clip', $data); return view('episode/video_clip', $data);
} }
public function create(): string public function createView(Episode $episode): string
{ {
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $episode->podcast,
'episode' => $this->episode, 'episode' => $episode,
]; ];
replace_breadcrumb_params([ replace_breadcrumb_params([
0 => $this->podcast->at_handle, 0 => $episode->podcast->at_handle,
1 => $this->episode->title, 1 => $episode->title,
]); ]);
// First, check that requirements to create a video clip are met // First, check that requirements to create a video clip are met
@ -129,7 +120,7 @@ class VideoClipsController extends BaseController
'ffmpeg' => $ffmpeg !== null, 'ffmpeg' => $ffmpeg !== null,
'gd' => extension_loaded('gd'), 'gd' => extension_loaded('gd'),
'freetype' => extension_loaded('gd') && gd_info()['FreeType Support'], 'freetype' => extension_loaded('gd') && gd_info()['FreeType Support'],
'transcript' => $this->episode->transcript instanceof Transcript, 'transcript' => $episode->transcript instanceof Transcript,
]; ];
$this->setHtmlHead(lang('VideoClip.form.title')); $this->setHtmlHead(lang('VideoClip.form.title'));
@ -143,7 +134,7 @@ class VideoClipsController extends BaseController
return view('episode/video_clips_new', $data); return view('episode/video_clips_new', $data);
} }
public function attemptCreate(): RedirectResponse public function createAction(Episode $episode): RedirectResponse
{ {
$rules = [ $rules = [
'title' => 'required', 'title' => 'required',
@ -178,8 +169,8 @@ class VideoClipsController extends BaseController
'format' => $validData['format'], 'format' => $validData['format'],
'type' => 'video', 'type' => 'video',
'status' => 'queued', 'status' => 'queued',
'podcast_id' => $this->podcast->id, 'podcast_id' => $episode->podcast_id,
'episode_id' => $this->episode->id, 'episode_id' => $episode->id,
'created_by' => user_id(), 'created_by' => user_id(),
'updated_by' => user_id(), 'updated_by' => user_id(),
]); ]);
@ -195,13 +186,13 @@ class VideoClipsController extends BaseController
(new ClipModel())->insert($videoClip); (new ClipModel())->insert($videoClip);
return redirect()->route('video-clips-list', [$this->podcast->id, $this->episode->id])->with( return redirect()->route('video-clips-list', [$episode->podcast_id, $episode->id])->with(
'message', 'message',
lang('VideoClip.messages.addToQueueSuccess') lang('VideoClip.messages.addToQueueSuccess')
); );
} }
public function retry(string $videoClipId): RedirectResponse public function retryAction(Episode $episode, string $videoClipId): RedirectResponse
{ {
$videoClip = (new ClipModel())->getVideoClipById((int) $videoClipId); $videoClip = (new ClipModel())->getVideoClipById((int) $videoClipId);
@ -218,7 +209,7 @@ class VideoClipsController extends BaseController
return redirect()->back(); return redirect()->back();
} }
public function delete(string $videoClipId): RedirectResponse public function deleteAction(Episode $episode, string $videoClipId): RedirectResponse
{ {
$videoClip = (new ClipModel())->getVideoClipById((int) $videoClipId); $videoClip = (new ClipModel())->getVideoClipById((int) $videoClipId);
@ -228,7 +219,7 @@ class VideoClipsController extends BaseController
if ($videoClip->media === null) { if ($videoClip->media === null) {
// delete Clip directly // delete Clip directly
(new ClipModel())->deleteVideoClip($this->podcast->id, $this->episode->id, $videoClip->id); (new ClipModel())->deleteVideoClip($episode->podcast_id, $episode->id, $videoClip->id);
} else { } else {
(new ClipModel())->clearVideoClipCache($videoClip->id); (new ClipModel())->clearVideoClipCache($videoClip->id);

View File

@ -16,6 +16,11 @@ trait AnalyticsTrait
{ {
protected function registerPodcastWebpageHit(int $podcastId): void protected function registerPodcastWebpageHit(int $podcastId): void
{ {
// Prevent analytics hit when authenticated
if (auth()->loggedIn()) {
return;
}
helper('analytics'); helper('analytics');
set_user_session_deny_list_ip(); set_user_session_deny_list_ip();

View File

@ -26,7 +26,7 @@ $routes->group(
]); ]);
$routes->post('magic-link-set-password', 'MagicLinkController::setPasswordAction'); $routes->post('magic-link-set-password', 'MagicLinkController::setPasswordAction');
$routes->post('interact-as-actor', 'InteractController::attemptInteractAsActor', [ $routes->post('interact-as-actor', 'InteractController::interactAsActorAction', [
'as' => 'interact-as-actor', 'as' => 'interact-as-actor',
]); ]);
@ -36,11 +36,11 @@ $routes->group(
'as' => 'user-list', 'as' => 'user-list',
'filter' => 'permission:users.manage', 'filter' => 'permission:users.manage',
]); ]);
$routes->get('new', 'UserController::create', [ $routes->get('new', 'UserController::createView', [
'as' => 'user-create', 'as' => 'user-create',
'filter' => 'permission:users.manage', 'filter' => 'permission:users.manage',
]); ]);
$routes->post('new', 'UserController::attemptCreate', [ $routes->post('new', 'UserController::createAction', [
'filter' => 'permission:users.manage', 'filter' => 'permission:users.manage',
]); ]);
// User // User
@ -49,18 +49,18 @@ $routes->group(
'as' => 'user-view', 'as' => 'user-view',
'filter' => 'permission:users.manage', 'filter' => 'permission:users.manage',
]); ]);
$routes->get('edit', 'UserController::edit/$1', [ $routes->get('edit', 'UserController::editView/$1', [
'as' => 'user-edit', 'as' => 'user-edit',
'filter' => 'permission:users.manage', 'filter' => 'permission:users.manage',
]); ]);
$routes->post('edit', 'UserController::attemptEdit/$1', [ $routes->post('edit', 'UserController::editAction/$1', [
'filter' => 'permission:users.manage', 'filter' => 'permission:users.manage',
]); ]);
$routes->get('delete', 'UserController::delete/$1', [ $routes->get('delete', 'UserController::delete/$1', [
'as' => 'user-delete', 'as' => 'user-delete',
'filter' => 'permission:users.manage', 'filter' => 'permission:users.manage',
]); ]);
$routes->post('delete', 'UserController::attemptDelete/$1', [ $routes->post('delete', 'UserController::deleteAction/$1', [
'as' => 'user-delete', 'as' => 'user-delete',
'filter' => 'permission:users.manage', 'filter' => 'permission:users.manage',
]); ]);
@ -74,7 +74,7 @@ $routes->group(
$routes->get('change-password', 'MyAccountController::changePassword', [ $routes->get('change-password', 'MyAccountController::changePassword', [
'as' => 'change-password', 'as' => 'change-password',
],); ],);
$routes->post('change-password', 'MyAccountController::attemptChange'); $routes->post('change-password', 'MyAccountController::changeAction');
}); });
// Podcast contributors // Podcast contributors
@ -83,13 +83,13 @@ $routes->group(
'as' => 'contributor-list', 'as' => 'contributor-list',
'filter' => 'permission:podcast$1.manage-contributors', 'filter' => 'permission:podcast$1.manage-contributors',
]); ]);
$routes->get('add', 'ContributorController::create/$1', [ $routes->get('add', 'ContributorController::createView/$1', [
'as' => 'contributor-add', 'as' => 'contributor-add',
'filter' => 'permission:podcast$1.manage-contributors', 'filter' => 'permission:podcast$1.manage-contributors',
]); ]);
$routes->post( $routes->post(
'add', 'add',
'ContributorController::attemptCreate/$1', 'ContributorController::createAction/$1',
[ [
'filter' => 'permission:podcast$1.manage-contributors', 'filter' => 'permission:podcast$1.manage-contributors',
], ],
@ -102,7 +102,7 @@ $routes->group(
]); ]);
$routes->get( $routes->get(
'edit', 'edit',
'ContributorController::edit/$1/$2', 'ContributorController::editView/$1/$2',
[ [
'as' => 'contributor-edit', 'as' => 'contributor-edit',
'filter' => 'permission:podcast$1.manage-contributors', 'filter' => 'permission:podcast$1.manage-contributors',
@ -110,7 +110,7 @@ $routes->group(
); );
$routes->post( $routes->post(
'edit', 'edit',
'ContributorController::attemptEdit/$1/$2', 'ContributorController::editAction/$1/$2',
[ [
'filter' => 'permission:podcast$1.manage-contributors', 'filter' => 'permission:podcast$1.manage-contributors',
], ],
@ -125,7 +125,7 @@ $routes->group(
); );
$routes->post( $routes->post(
'remove', 'remove',
'ContributorController::attemptRemove/$1/$2', 'ContributorController::removeAction/$1/$2',
[ [
'filter' => 'permission:podcast$1.manage-contributors', 'filter' => 'permission:podcast$1.manage-contributors',
], ],

View File

@ -81,7 +81,7 @@ class ContributorController extends BaseController
return view('contributor/view', $data); return view('contributor/view', $data);
} }
public function create(): string public function createView(): string
{ {
helper('form'); helper('form');
@ -125,7 +125,7 @@ class ContributorController extends BaseController
return view('contributor/create', $data); return view('contributor/create', $data);
} }
public function attemptCreate(): RedirectResponse public function createAction(): RedirectResponse
{ {
/** @var User $user */ /** @var User $user */
$user = (new UserModel())->find((int) $this->request->getPost('user')); $user = (new UserModel())->find((int) $this->request->getPost('user'));
@ -142,7 +142,7 @@ class ContributorController extends BaseController
return redirect()->route('contributor-list', [$this->podcast->id]); return redirect()->route('contributor-list', [$this->podcast->id]);
} }
public function edit(): string|RedirectResponse public function editView(): string|RedirectResponse
{ {
helper('form'); helper('form');
@ -184,7 +184,7 @@ class ContributorController extends BaseController
return view('contributor/edit', $data); return view('contributor/edit', $data);
} }
public function attemptEdit(): RedirectResponse public function editAction(): RedirectResponse
{ {
// forbid updating a podcast owner // forbid updating a podcast owner
if ($this->podcast->created_by === $this->contributor->id) { if ($this->podcast->created_by === $this->contributor->id) {
@ -206,7 +206,7 @@ class ContributorController extends BaseController
); );
} }
public function remove(): string public function deleteView(): string
{ {
helper('form'); helper('form');
@ -225,7 +225,7 @@ class ContributorController extends BaseController
return view('contributor/delete', $data); return view('contributor/delete', $data);
} }
public function attemptRemove(): RedirectResponse public function deleteAction(): RedirectResponse
{ {
if ($this->podcast->created_by === $this->contributor->id) { if ($this->podcast->created_by === $this->contributor->id) {
return redirect() return redirect()

View File

@ -12,7 +12,7 @@ use CodeIgniter\HTTP\RedirectResponse;
*/ */
class InteractController extends Controller class InteractController extends Controller
{ {
public function attemptInteractAsActor(): RedirectResponse public function interactAsActorAction(): RedirectResponse
{ {
$rules = [ $rules = [
'actor_id' => 'required|numeric', 'actor_id' => 'required|numeric',

View File

@ -30,7 +30,7 @@ class MyAccountController extends BaseController
return view('my_account/change_password'); return view('my_account/change_password');
} }
public function attemptChange(): RedirectResponse public function changeAction(): RedirectResponse
{ {
$rules = [ $rules = [
'password' => 'required', 'password' => 'required',

View File

@ -61,7 +61,7 @@ class UserController extends BaseController
return view('user/view', $data); return view('user/view', $data);
} }
public function create(): string public function createView(): string
{ {
helper('form'); helper('form');
@ -70,7 +70,10 @@ class UserController extends BaseController
array_walk( array_walk(
$roles, $roles,
static function (array $role, $key) use (&$roleOptions): array { static function (array $role, $key) use (&$roleOptions): array {
$roleOptions[$key] = $role['title']; $roleOptions[] = [
'value' => $key,
'label' => $role['title'],
];
return $roleOptions; return $roleOptions;
}, },
[], [],
@ -88,7 +91,7 @@ class UserController extends BaseController
* Create the user with the provided username and email. The password is set as a random string and a magic link is * Create the user with the provided username and email. The password is set as a random string and a magic link is
* sent to the user to allow them setting their password. * sent to the user to allow them setting their password.
*/ */
public function attemptCreate(): RedirectResponse public function createAction(): RedirectResponse
{ {
helper(['text', 'email']); helper(['text', 'email']);
@ -167,7 +170,7 @@ class UserController extends BaseController
])); ]));
} }
public function edit(): string public function editView(): string
{ {
helper('form'); helper('form');
@ -176,7 +179,10 @@ class UserController extends BaseController
array_walk( array_walk(
$roles, $roles,
static function (array $role, $key) use (&$roleOptions): array { static function (array $role, $key) use (&$roleOptions): array {
$roleOptions[$key] = $role['title']; $roleOptions[] = [
'value' => $key,
'label' => $role['title'],
];
return $roleOptions; return $roleOptions;
}, },
[], [],
@ -196,7 +202,7 @@ class UserController extends BaseController
return view('user/edit', $data); return view('user/edit', $data);
} }
public function attemptEdit(): RedirectResponse public function editAction(): RedirectResponse
{ {
// The instance owner is a superadmin and the only user that cannot be demoted. // The instance owner is a superadmin and the only user that cannot be demoted.
if ((bool) $this->user->is_owner) { if ((bool) $this->user->is_owner) {
@ -221,7 +227,7 @@ class UserController extends BaseController
])); ]));
} }
public function delete(): string public function deleteView(): string
{ {
helper(['form']); helper(['form']);
@ -238,7 +244,7 @@ class UserController extends BaseController
return view('user/delete', $data); return view('user/delete', $data);
} }
public function attemptDelete(): RedirectResponse public function deleteAction(): RedirectResponse
{ {
// You cannot delete the instance owner. // You cannot delete the instance owner.
if ((bool) $this->user->is_owner) { if ((bool) $this->user->is_owner) {

View File

@ -52,7 +52,7 @@ $routes->group('', [
'as' => 'followers', 'as' => 'followers',
'filter' => 'fediverse::activity-stream', 'filter' => 'fediverse::activity-stream',
]); ]);
$routes->post('follow', 'ActorController::attemptFollow/$1', [ $routes->post('follow', 'ActorController::followAction/$1', [
'as' => 'attempt-follow', 'as' => 'attempt-follow',
]); ]);
$routes->get('activities/(:uuid)', 'ActorController::activity/$1/$2', [ $routes->get('activities/(:uuid)', 'ActorController::activity/$1/$2', [
@ -60,7 +60,7 @@ $routes->group('', [
]); ]);
}); });
// Post // Post
$routes->post('posts/create', 'PostController::attemptCreate/$1', [ $routes->post('posts/create', 'PostController::createAction/$1', [
'as' => 'post-attempt-create', 'as' => 'post-attempt-create',
]); ]);
$routes->get('posts/(:uuid)', 'PostController::index/$1', [ $routes->get('posts/(:uuid)', 'PostController::index/$1', [
@ -71,7 +71,7 @@ $routes->group('', [
]); ]);
$routes->post( $routes->post(
'posts/(:uuid)/remote/(:postAction)', 'posts/(:uuid)/remote/(:postAction)',
'PostController::attemptRemoteAction/$1/$2/$3', 'PostController::remoteActionAction/$1/$2/$3',
[ [
'as' => 'post-attempt-remote-action', 'as' => 'post-attempt-remote-action',
], ],
@ -79,28 +79,28 @@ $routes->group('', [
// Blocking actors and domains // Blocking actors and domains
$routes->post( $routes->post(
'fediverse-block-actor', 'fediverse-block-actor',
'BlockController::attemptBlockActor', 'BlockController::blockActorAction',
[ [
'as' => 'fediverse-attempt-block-actor', 'as' => 'fediverse-attempt-block-actor',
], ],
); );
$routes->post( $routes->post(
'fediverse-block-domain', 'fediverse-block-domain',
'BlockController::attemptBlockDomain', 'BlockController::blockDomainAction',
[ [
'as' => 'fediverse-attempt-block-domain', 'as' => 'fediverse-attempt-block-domain',
], ],
); );
$routes->post( $routes->post(
'fediverse-unblock-actor', 'fediverse-unblock-actor',
'BlockController::attemptUnblockActor', 'BlockController::unblockActorAction',
[ [
'as' => 'fediverse-attempt-unblock-actor', 'as' => 'fediverse-attempt-unblock-actor',
], ],
); );
$routes->post( $routes->post(
'fediverse-unblock-domain', 'fediverse-unblock-domain',
'BlockController::attemptUnblockDomain', 'BlockController::unblockDomainAction',
[ [
'as' => 'fediverse-attempt-unblock-domain', 'as' => 'fediverse-attempt-unblock-domain',
], ],

View File

@ -319,7 +319,7 @@ class ActorController extends Controller
->setBody($followersCollection->toJSON()); ->setBody($followersCollection->toJSON());
} }
public function attemptFollow(): RedirectResponse public function followAction(): RedirectResponse
{ {
$rules = [ $rules = [
'handle' => 'regex_match[/^@?(?P<username>[\w\.\-]+)@(?P<host>[\w\.\-]+)(?P<port>:[\d]+)?$/]', 'handle' => 'regex_match[/^@?(?P<username>[\w\.\-]+)@(?P<host>[\w\.\-]+)(?P<port>:[\d]+)?$/]',

View File

@ -21,7 +21,7 @@ class BlockController extends Controller
*/ */
protected $helpers = ['fediverse']; protected $helpers = ['fediverse'];
public function attemptBlockActor(): RedirectResponse public function blockActorAction(): RedirectResponse
{ {
$rules = [ $rules = [
'handle' => 'required|regex_match[/^@?([\w\.\-]+)@([\w\.\-]+)(:[\d]+)?$/]', 'handle' => 'required|regex_match[/^@?([\w\.\-]+)@([\w\.\-]+)(:[\d]+)?$/]',
@ -58,7 +58,7 @@ class BlockController extends Controller
])); ]));
} }
public function attemptUnblockActor(): RedirectResponse public function unblockActorAction(): RedirectResponse
{ {
$rules = [ $rules = [
'actor_id' => 'required', 'actor_id' => 'required',
@ -80,7 +80,7 @@ class BlockController extends Controller
->with('message', lang('Fediverse.messages.unblockActorSuccess')); ->with('message', lang('Fediverse.messages.unblockActorSuccess'));
} }
public function attemptBlockDomain(): RedirectResponse public function blockDomainAction(): RedirectResponse
{ {
$rules = [ $rules = [
'domain' => 'required|regex_match[/^[\w\-\.]+[\w]+(:[\d]+)?/]', 'domain' => 'required|regex_match[/^[\w\-\.]+[\w]+(:[\d]+)?/]',
@ -105,7 +105,7 @@ class BlockController extends Controller
])); ]));
} }
public function attemptUnblockDomain(): RedirectResponse public function unblockDomainAction(): RedirectResponse
{ {
$rules = [ $rules = [
'domain' => 'required', 'domain' => 'required',

View File

@ -112,7 +112,7 @@ class PostController extends Controller
->setBody($collection->toJSON()); ->setBody($collection->toJSON());
} }
public function attemptCreate(): RedirectResponse public function createAction(): RedirectResponse
{ {
$rules = [ $rules = [
'actor_id' => 'required|is_natural_no_zero', 'actor_id' => 'required|is_natural_no_zero',
@ -147,7 +147,7 @@ class PostController extends Controller
return redirect()->back(); return redirect()->back();
} }
public function attemptFavourite(): RedirectResponse public function favouriteAction(): RedirectResponse
{ {
$rules = [ $rules = [
'actor_id' => 'required|is_natural_no_zero', 'actor_id' => 'required|is_natural_no_zero',
@ -171,7 +171,7 @@ class PostController extends Controller
return redirect()->back(); return redirect()->back();
} }
public function attemptReblog(): RedirectResponse public function reblogAction(): RedirectResponse
{ {
$rules = [ $rules = [
'actor_id' => 'required|is_natural_no_zero', 'actor_id' => 'required|is_natural_no_zero',
@ -195,7 +195,7 @@ class PostController extends Controller
return redirect()->back(); return redirect()->back();
} }
public function attemptReply(): RedirectResponse public function replyAction(): RedirectResponse
{ {
$rules = [ $rules = [
'actor_id' => 'required|is_natural_no_zero', 'actor_id' => 'required|is_natural_no_zero',
@ -230,7 +230,7 @@ class PostController extends Controller
return redirect()->back(); return redirect()->back();
} }
public function attemptRemoteAction(string $action): RedirectResponse | ResponseInterface public function remoteActionAction(string $action): RedirectResponse | ResponseInterface
{ {
$rules = [ $rules = [
'handle' => 'regex_match[/^@?(?P<username>[\w\.\-]+)@(?P<host>[\w\.\-]+)(?P<port>:[\d]+)?$/]', 'handle' => 'regex_match[/^@?(?P<username>[\w\.\-]+)@(?P<host>[\w\.\-]+)(?P<port>:[\d]+)?$/]',
@ -277,21 +277,21 @@ class PostController extends Controller
); );
} }
public function attemptBlockActor(): RedirectResponse public function blockActorAction(): RedirectResponse
{ {
model('ActorModel', false)->blockActor($this->post->actor->id); model('ActorModel', false)->blockActor($this->post->actor->id);
return redirect()->back(); return redirect()->back();
} }
public function attemptBlockDomain(): RedirectResponse public function blockDomainAction(): RedirectResponse
{ {
model('BlockedDomainModel', false)->blockDomain($this->post->actor->domain); model('BlockedDomainModel', false)->blockDomain($this->post->actor->domain);
return redirect()->back(); return redirect()->back();
} }
public function attemptDelete(): RedirectResponse public function deleteAction(): RedirectResponse
{ {
model('PostModel', false)->removePost($this->post); model('PostModel', false)->removePost($this->post);

View File

@ -19,18 +19,18 @@ $routes->group(
$routes->get('/', 'InstallController', [ $routes->get('/', 'InstallController', [
'as' => 'install', 'as' => 'install',
]); ]);
$routes->post('instance-config', 'InstallController::attemptInstanceConfig', [ $routes->post('instance-config', 'InstallController::instanceConfigAction', [
'as' => 'instance-config', 'as' => 'instance-config',
]); ]);
$routes->post('database-config', 'InstallController::attemptDatabaseConfig', [ $routes->post('database-config', 'InstallController::databaseConfigAction', [
'as' => 'database-config', 'as' => 'database-config',
]); ]);
$routes->post('cache-config', 'InstallController::attemptCacheConfig', [ $routes->post('cache-config', 'InstallController::cacheConfigAction', [
'as' => 'cache-config', 'as' => 'cache-config',
]); ]);
$routes->post( $routes->post(
'create-superadmin', 'create-superadmin',
'InstallController::attemptCreateSuperAdmin', 'InstallController::createSuperAdminAction',
[ [
'as' => 'create-superadmin', 'as' => 'create-superadmin',
], ],

View File

@ -75,7 +75,7 @@ class InstallController extends Controller
$dotenv->required(['app.baseURL', 'analytics.salt', 'admin.gateway', 'auth.gateway']); $dotenv->required(['app.baseURL', 'analytics.salt', 'admin.gateway', 'auth.gateway']);
} catch (ValidationException) { } catch (ValidationException) {
// form to input instance configuration // form to input instance configuration
return $this->instanceConfig(); return $this->instanceConfigView();
} }
try { try {
@ -87,13 +87,13 @@ class InstallController extends Controller
'database.default.DBPrefix', 'database.default.DBPrefix',
]); ]);
} catch (ValidationException) { } catch (ValidationException) {
return $this->databaseConfig(); return $this->databaseConfigView();
} }
try { try {
$dotenv->required('cache.handler'); $dotenv->required('cache.handler');
} catch (ValidationException) { } catch (ValidationException) {
return $this->cacheConfig(); return $this->cacheConfigView();
} }
} else { } else {
try { try {
@ -130,7 +130,7 @@ class InstallController extends Controller
session() session()
->setFlashdata('error', lang('Install.messages.databaseConnectError')); ->setFlashdata('error', lang('Install.messages.databaseConnectError'));
return $this->databaseConfig(); return $this->databaseConfigView();
} }
// migrate if no user has been created // migrate if no user has been created
@ -139,15 +139,15 @@ class InstallController extends Controller
// Check if all seeds have succeeded // Check if all seeds have succeeded
$this->seed(); $this->seed();
return $this->createSuperAdmin(); return $this->createSuperAdminView();
} }
public function instanceConfig(): string public function instanceConfigView(): string
{ {
return view('instance_config'); return view('instance_config');
} }
public function attemptInstanceConfig(): RedirectResponse public function instanceConfigAction(): RedirectResponse
{ {
$rules = [ $rules = [
'hostname' => 'required|valid_url_strict', 'hostname' => 'required|valid_url_strict',
@ -181,12 +181,12 @@ class InstallController extends Controller
return redirect()->to(reduce_double_slashes($baseUrl . '/' . config('Install')->gateway)); return redirect()->to(reduce_double_slashes($baseUrl . '/' . config('Install')->gateway));
} }
public function databaseConfig(): string public function databaseConfigView(): string
{ {
return view('database_config'); return view('database_config');
} }
public function attemptDatabaseConfig(): RedirectResponse public function databaseConfigAction(): RedirectResponse
{ {
$rules = [ $rules = [
'db_hostname' => 'required', 'db_hostname' => 'required',
@ -215,12 +215,12 @@ class InstallController extends Controller
return redirect()->back(); return redirect()->back();
} }
public function cacheConfig(): string public function cacheConfigView(): string
{ {
return view('cache_config'); return view('cache_config');
} }
public function attemptCacheConfig(): RedirectResponse public function cacheConfigAction(): RedirectResponse
{ {
$rules = [ $rules = [
'cache_handler' => 'required', 'cache_handler' => 'required',
@ -267,7 +267,7 @@ class InstallController extends Controller
/** /**
* Returns the form to create a the first superadmin user for the instance. * Returns the form to create a the first superadmin user for the instance.
*/ */
public function createSuperAdmin(): string public function createSuperAdminView(): string
{ {
return view('create_superadmin'); return view('create_superadmin');
} }
@ -277,7 +277,7 @@ class InstallController extends Controller
* *
* After creation, user is redirected to login page to input its credentials. * After creation, user is redirected to login page to input its credentials.
*/ */
public function attemptCreateSuperAdmin(): RedirectResponse public function createSuperAdminAction(): RedirectResponse
{ {
// validate user password // validate user password
$rules = [ $rules = [

View File

@ -21,7 +21,7 @@ $routes->group(
$routes->group('podcasts/(:num)/platforms', static function ($routes): void { $routes->group('podcasts/(:num)/platforms', static function ($routes): void {
$routes->get( $routes->get(
'/', '/',
'PlatformController::platforms/$1/podcasting', 'PlatformController::list/$1/podcasting',
[ [
'as' => 'platforms-podcasting', 'as' => 'platforms-podcasting',
'filter' => 'permission:podcast$1.manage-platforms', 'filter' => 'permission:podcast$1.manage-platforms',
@ -29,7 +29,7 @@ $routes->group(
); );
$routes->get( $routes->get(
'social', 'social',
'PlatformController::platforms/$1/social', 'PlatformController::list/$1/social',
[ [
'as' => 'platforms-social', 'as' => 'platforms-social',
'filter' => 'permission:podcast$1.manage-platforms', 'filter' => 'permission:podcast$1.manage-platforms',
@ -37,7 +37,7 @@ $routes->group(
); );
$routes->get( $routes->get(
'funding', 'funding',
'PlatformController::platforms/$1/funding', 'PlatformController::list/$1/funding',
[ [
'as' => 'platforms-funding', 'as' => 'platforms-funding',
'filter' => 'permission:podcast$1.manage-platforms', 'filter' => 'permission:podcast$1.manage-platforms',
@ -45,7 +45,7 @@ $routes->group(
); );
$routes->post( $routes->post(
'save/(:platformType)', 'save/(:platformType)',
'PlatformController::attemptPlatformsUpdate/$1/$2', 'PlatformController::updateAction/$1/$2',
[ [
'as' => 'platforms-save', 'as' => 'platforms-save',
'filter' => 'permission:podcast$1.manage-platforms', 'filter' => 'permission:podcast$1.manage-platforms',
@ -53,7 +53,7 @@ $routes->group(
); );
$routes->get( $routes->get(
'(:platformType)/(:slug)/podcast-platform-remove', '(:platformType)/(:slug)/podcast-platform-remove',
'PlatformController::removePlatform/$1/$2/$3', 'PlatformController::removeAction/$1/$2/$3',
[ [
'as' => 'podcast-platform-remove', 'as' => 'podcast-platform-remove',
'filter' => 'permission:podcast$1.manage-platforms', 'filter' => 'permission:podcast$1.manage-platforms',

View File

@ -45,7 +45,7 @@ class PlatformController extends BaseController
return view('podcast/platforms/dashboard'); return view('podcast/platforms/dashboard');
} }
public function platforms(string $platformType): string public function list(string $platformType): string
{ {
helper('form'); helper('form');
@ -62,7 +62,7 @@ class PlatformController extends BaseController
return view('podcast/platforms', $data); return view('podcast/platforms', $data);
} }
public function attemptPlatformsUpdate(string $platformType): RedirectResponse public function updateAction(string $platformType): RedirectResponse
{ {
$platformModel = new PlatformModel(); $platformModel = new PlatformModel();
$validation = Services::validation(); $validation = Services::validation();
@ -99,7 +99,7 @@ class PlatformController extends BaseController
->with('message', lang('Platforms.messages.updateSuccess')); ->with('message', lang('Platforms.messages.updateSuccess'));
} }
public function removePlatform(string $platformType, string $platformSlug): RedirectResponse public function removeAction(string $platformType, string $platformSlug): RedirectResponse
{ {
(new PlatformModel())->removePlatform($this->podcast->id, $platformType, $platformSlug); (new PlatformModel())->removePlatform($this->podcast->id, $platformType, $platformSlug);

View File

@ -23,18 +23,18 @@ $routes->group(
'as' => 'subscription-list', 'as' => 'subscription-list',
'filter' => 'permission:podcast$1.manage-subscriptions', 'filter' => 'permission:podcast$1.manage-subscriptions',
]); ]);
$routes->get('new', 'SubscriptionController::create/$1', [ $routes->get('new', 'SubscriptionController::createView/$1', [
'as' => 'subscription-create', 'as' => 'subscription-create',
'filter' => 'permission:podcast$1.manage-subscriptions', 'filter' => 'permission:podcast$1.manage-subscriptions',
]); ]);
$routes->post( $routes->post(
'new', 'new',
'SubscriptionController::attemptCreate/$1', 'SubscriptionController::createAction/$1',
[ [
'filter' => 'permission:podcast$1.manage-subscriptions', 'filter' => 'permission:podcast$1.manage-subscriptions',
], ],
); );
$routes->post('save-link', 'SubscriptionController::attemptLinkSave/$1', [ $routes->post('save-link', 'SubscriptionController::linkSaveAction/$1', [
'as' => 'subscription-link-save', 'as' => 'subscription-link-save',
'filter' => 'permission:podcast$1.manage-subscriptions', 'filter' => 'permission:podcast$1.manage-subscriptions',
]); ]);
@ -46,7 +46,7 @@ $routes->group(
]); ]);
$routes->get( $routes->get(
'edit', 'edit',
'SubscriptionController::edit/$1/$2', 'SubscriptionController::editView/$1/$2',
[ [
'as' => 'subscription-edit', 'as' => 'subscription-edit',
'filter' => 'permission:podcast$1.manage-subscriptions', 'filter' => 'permission:podcast$1.manage-subscriptions',
@ -54,7 +54,7 @@ $routes->group(
); );
$routes->post( $routes->post(
'edit', 'edit',
'SubscriptionController::attemptEdit/$1/$2', 'SubscriptionController::editAction/$1/$2',
[ [
'as' => 'subscription-edit', 'as' => 'subscription-edit',
'filter' => 'permission:podcast$1.manage-subscriptions', 'filter' => 'permission:podcast$1.manage-subscriptions',
@ -78,7 +78,7 @@ $routes->group(
); );
$routes->post( $routes->post(
'suspend', 'suspend',
'SubscriptionController::attemptSuspend/$1/$2', 'SubscriptionController::suspendAction/$1/$2',
[ [
'filter' => 'permission:podcast$1.manage-subscriptions', 'filter' => 'permission:podcast$1.manage-subscriptions',
], ],
@ -101,7 +101,7 @@ $routes->group(
); );
$routes->post( $routes->post(
'delete', 'delete',
'SubscriptionController::attemptDelete/$1/$2', 'SubscriptionController::deleteAction/$1/$2',
[ [
'filter' => 'permission:podcast$1.manage-subscriptions', 'filter' => 'permission:podcast$1.manage-subscriptions',
], ],
@ -120,10 +120,10 @@ $routes->group(
$routes->get('unlock', 'LockController::index/$1', [ $routes->get('unlock', 'LockController::index/$1', [
'as' => 'premium-podcast-unlock', 'as' => 'premium-podcast-unlock',
]); ]);
$routes->post('unlock', 'LockController::attemptUnlock/$1', [ $routes->post('unlock', 'LockController::unlockAction/$1', [
'as' => 'premium-podcast-unlock', 'as' => 'premium-podcast-unlock',
]); ]);
$routes->get('lock', 'LockController::attemptLock/$1', [ $routes->get('lock', 'LockController::lockAction/$1', [
'as' => 'premium-podcast-lock', 'as' => 'premium-podcast-lock',
]); ]);
} }

View File

@ -58,7 +58,7 @@ class LockController extends BaseController
return view('podcast/unlock', $data); return view('podcast/unlock', $data);
} }
public function attemptUnlock(): RedirectResponse public function unlockAction(): RedirectResponse
{ {
$rules = [ $rules = [
'token' => 'required', 'token' => 'required',
@ -91,7 +91,7 @@ class LockController extends BaseController
->with('message', lang('PremiumPodcasts.messages.unlockSuccess')); ->with('message', lang('PremiumPodcasts.messages.unlockSuccess'));
} }
public function attemptLock(): RedirectResponse public function lockAction(): RedirectResponse
{ {
$this->premiumPodcasts->lock($this->podcast->handle); $this->premiumPodcasts->lock($this->podcast->handle);

View File

@ -66,7 +66,7 @@ class SubscriptionController extends BaseController
return view('subscription/list', $data); return view('subscription/list', $data);
} }
public function attemptLinkSave(): RedirectResponse public function linkSaveAction(): RedirectResponse
{ {
$rules = [ $rules = [
'subscription_link' => 'valid_url_strict|permit_empty', 'subscription_link' => 'valid_url_strict|permit_empty',
@ -118,7 +118,7 @@ class SubscriptionController extends BaseController
return view('subscription/view', $data); return view('subscription/view', $data);
} }
public function create(): string public function createView(): string
{ {
helper('form'); helper('form');
@ -133,7 +133,7 @@ class SubscriptionController extends BaseController
return view('subscription/create', $data); return view('subscription/create', $data);
} }
public function attemptCreate(): RedirectResponse public function createAction(): RedirectResponse
{ {
helper('text'); helper('text');
@ -244,7 +244,7 @@ class SubscriptionController extends BaseController
); );
} }
public function edit(): string public function editView(): string
{ {
helper('form'); helper('form');
@ -261,7 +261,7 @@ class SubscriptionController extends BaseController
return view('subscription/edit', $data); return view('subscription/edit', $data);
} }
public function attemptEdit(): RedirectResponse public function editAction(): RedirectResponse
{ {
$expiresAt = null; $expiresAt = null;
$expirationDate = $this->request->getPost('expiration_date'); $expirationDate = $this->request->getPost('expiration_date');
@ -330,7 +330,7 @@ class SubscriptionController extends BaseController
return view('subscription/suspend', $data); return view('subscription/suspend', $data);
} }
public function attemptSuspend(): RedirectResponse public function suspendAction(): RedirectResponse
{ {
$db = db_connect(); $db = db_connect();
$db->transStart(); $db->transStart();
@ -426,7 +426,7 @@ class SubscriptionController extends BaseController
return view('subscription/delete', $data); return view('subscription/delete', $data);
} }
public function attemptDelete(): RedirectResponse public function deleteAction(): RedirectResponse
{ {
$db = db_connect(); $db = db_connect();
$db->transStart(); $db->transStart();

View File

@ -117,7 +117,11 @@ final class PluginsTest extends CIUnitTestCase
$this->assertEquals( $this->assertEquals(
(string) $head, (string) $head,
'<head> <title >foo</title> <meta charset="UTF-8"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <link rel="icon" type="image/x-icon" href="http://localhost:8080/favicon.ico"/> <link rel="apple-touch-icon" href="http://localhost:8080/icon-180.png"/> <link rel="manifest" href="/manifest.webmanifest"/> <meta name="theme-color" content="#009486"/> <link rel="stylesheet" type="text/css" href="/themes/colors"/> <title >foo</title> <script> '<head> <title >foo</title> <meta charset="UTF-8"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <link rel="icon" type="image/x-icon" href="' . base_url(
'favicon.ico'
) . '"/> <link rel="apple-touch-icon" href="' . base_url(
'icon-180.png'
) . '"/> <link rel="manifest" href="/manifest.webmanifest"/> <meta name="theme-color" content="#009486"/> <link rel="stylesheet" type="text/css" href="/themes/colors"/> <title >foo</title> <script>
// Check that service workers are supported // Check that service workers are supported
if (\'serviceWorker\' in navigator) { if (\'serviceWorker\' in navigator) {
// Use the window load event to keep the page load performant // Use the window load event to keep the page load performant

View File

@ -39,13 +39,13 @@
isRequired="true" isRequired="true"
data-slugify="title" /> data-slugify="title" />
<div> <x-Forms.PermalinkEditor
<x-Forms.Label for="slug"><?= lang('Episode.form.permalink') ?></x-Forms.Label> name="slug"
<permalink-edit class="inline-flex items-center w-full text-xs" edit-label="<?= lang('Common.edit') ?>" copy-label="<?= lang('Common.copy') ?>" copied-label="<?= lang('Common.copied') ?>" permalink-base="<?= url_to('podcast-episodes', $podcast->handle) ?>"> label="<?= lang('Episode.form.permalink') ?>"
<span slot="domain"><?= '…/' . esc($podcast->at_handle) . '/' ?></span> prefix="<?= '…/' . esc($podcast->at_handle) . '/' ?>"
<x-Forms.Input name="slug" isRequired="true" data-slugify="slug" slot="slug-input" class="flex-1 text-xs" /> data-slugify="slug"
</permalink-edit> permalinkBase="<?= url_to('podcast-episodes', $podcast->handle) ?>"
</div> />
<div class="flex flex-col gap-x-2 gap-y-4 md:flex-row"> <div class="flex flex-col gap-x-2 gap-y-4 md:flex-row">
<x-Forms.Field <x-Forms.Field

View File

@ -41,14 +41,20 @@
hint="<?= esc(lang('Episode.form.title_hint')) ?>" hint="<?= esc(lang('Episode.form.title_hint')) ?>"
value="<?= esc($episode->title) ?>" value="<?= esc($episode->title) ?>"
isRequired="true" /> isRequired="true" />
<x-Forms.PermalinkEditor
name="slug"
label="<?= lang('Episode.form.permalink') ?>"
prefix="<?= '…/' . esc($podcast->handle) . '/' ?>"
data-slugify="slug" />
<div> <x-Forms.PermalinkEditor
<x-Forms.Label for="slug"><?= lang('Episode.form.permalink') ?></x-Forms.Label> name="slug"
<permalink-edit class="inline-flex items-center w-full text-xs" edit-label="<?= lang('Common.edit') ?>" copy-label="<?= lang('Common.copy') ?>" copied-label="<?= lang('Common.copied') ?>" permalink-base="<?= url_to('podcast-episodes', esc($podcast->handle)) ?>"> label="<?= lang('Episode.form.permalink') ?>"
<span slot="domain"><?= '…/' . esc($podcast->handle) . '/' ?></span> prefix="<?= '…/' . esc($podcast->at_handle) . '/' ?>"
<x-Forms.Input name="slug" value="<?= esc($episode->slug) ?>" isRequired="true" data-slugify="slug" slot="slug-input" class="flex-1 text-xs" /> data-slugify="slug"
</permalink-edit> permalinkBase="<?= url_to('podcast-episodes', $podcast->handle) ?>"
</div> value="<?= $episode->slug ?>"
/>
<div class="flex flex-col gap-x-2 gap-y-4 md:flex-row"> <div class="flex flex-col gap-x-2 gap-y-4 md:flex-row">
<x-Forms.Field <x-Forms.Field

View File

@ -17,13 +17,13 @@
data-slugify="title" data-slugify="title"
class="max-w-sm" /> class="max-w-sm" />
<div class="flex flex-col max-w-sm"> <x-Forms.PermalinkEditor
<x-Forms.Label for="slug"><?= lang('Page.form.permalink') ?></x-Forms.Label> name="slug"
<permalink-edit class="inline-flex items-center w-full text-xs" edit-label="<?= lang('Common.edit') ?>" copy-label="<?= lang('Common.copy') ?>" copied-label="<?= lang('Common.copied') ?>" permalink-base="<?= base_url('pages') ?>"> label="<?= lang('Page.form.permalink') ?>"
<span slot="domain" class="flex-shrink-0">/pages/</span> prefix="…/pages/"
<x-Forms.Input name="slug" isRequired="true" data-slugify="slug" slot="slug-input" class="flex-1 text-xs" /> data-slugify="slug"
</permalink-edit> permalinkBase="<?= base_url('pages') ?>"
</div> />
<x-Forms.Field <x-Forms.Field
as="MarkdownEditor" as="MarkdownEditor"

View File

@ -19,13 +19,14 @@
slot="slug-input" slot="slug-input"
class="max-w-sm" /> class="max-w-sm" />
<div class="flex flex-col max-w-sm"> <x-Forms.PermalinkEditor
<x-Forms.Label for="slug"><?= lang('Page.form.permalink') ?></x-Forms.Label> name="slug"
<permalink-edit class="inline-flex items-center text-xs" edit-label="<?= lang('Common.edit') ?>" copy-label="<?= lang('Common.copy') ?>" copied-label="<?= lang('Common.copied') ?>" permalink-base="<?= base_url('pages') ?>"> label="<?= lang('Page.form.permalink') ?>"
<span slot="domain" class="flex-shrink-0">/pages/<span> prefix="…/pages/"
<x-Forms.Input name="slug" value="<?= esc($page->slug) ?>" isRequired="true" data-slugify="slug" slot="slug-input" class="flex-1 text-xs" value="<?= esc($page->slug) ?>"/> data-slugify="slug"
</permalink-edit> permalinkBase="<?= base_url('pages') ?>"
</div> value="<?= $page->slug ?>"
/>
<x-Forms.Field <x-Forms.Field
as="MarkdownEditor" as="MarkdownEditor"

View File

@ -15,7 +15,7 @@
<?= $this->section('content') ?> <?= $this->section('content') ?>
<?= view_cell('Modules\Admin\Controllers\PodcastController::latestEpisodes', [ <?= view_cell('Modules\Admin\Controllers\PodcastController::latestEpisodesView', [
'limit' => 5, 'limit' => 5,
'podcastId' => $podcast->id, 'podcastId' => $podcast->id,
]) ?> ]) ?>

View File

@ -29,13 +29,7 @@
<p class="text-xs text-skin-muted"><?= implode( <p class="text-xs text-skin-muted"><?= implode(
', ', ', ',
array_map(function ($role) { array_map(function ($role) {
return lang( return lang(sprintf('PersonsTaxonomy.persons.%s.roles.%s.label', $role->group, $role->role));
'PersonsTaxonomy.persons.' .
$role->group .
'.roles.' .
$role->role .
'.label',
);
}, $person->roles), }, $person->roles),
) ?></p> ) ?></p>
</div> </div>