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', [
'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',
]);
$routes->get('oembed.json', 'EpisodeController::oembedJSON/$1/$2', [
@ -229,7 +229,7 @@ $routes->get('/pages/(:slug)', 'PageController::index/$1', [
* Overwriting Fediverse routes file
*/
$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',
'filter' => 'permission:podcast$1.manage-publications',
]);
@ -266,13 +266,13 @@ $routes->group('@(:podcastHandle)', static function ($routes): void {
'filter' => 'allow-cors',
]);
// Actions
$routes->post('action', 'PostController::attemptAction/$1/$2', [
$routes->post('action', 'PostController::actionAction/$1/$2', [
'as' => 'post-attempt-action',
'filter' => 'permission:podcast$1.interact-as',
]);
$routes->post(
'block-actor',
'PostController::attemptBlockActor/$1/$2',
'PostController::blockActorAction/$1/$2',
[
'as' => 'post-attempt-block-actor',
'filter' => 'permission:fediverse.manage-blocks',
@ -280,13 +280,13 @@ $routes->group('@(:podcastHandle)', static function ($routes): void {
);
$routes->post(
'block-domain',
'PostController::attemptBlockDomain/$1/$2',
'PostController::blockDomainAction/$1/$2',
[
'as' => 'post-attempt-block-domain',
'filter' => 'permission:fediverse.manage-blocks',
],
);
$routes->post('delete', 'PostController::attemptDelete/$1/$2', [
$routes->post('delete', 'PostController::deleteAction/$1/$2', [
'as' => 'post-attempt-delete',
'filter' => 'permission:podcast$1.manage-publications',
]);

View File

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

View File

@ -5,9 +5,7 @@ declare(strict_types=1);
namespace App\Controllers;
use CodeIgniter\Controller;
use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\Response;
use CodeIgniter\HTTP\ResponseInterface;
use Override;
use Psr\Log\LoggerInterface;
@ -21,20 +19,6 @@ use ViewThemes\Theme;
*/
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
* class instantiation. These helpers will be available

View File

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

View File

@ -16,7 +16,6 @@ use App\Models\EpisodeModel;
use App\Models\PodcastModel;
use CodeIgniter\Controller;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
@ -30,13 +29,6 @@ use Psr\Log\LoggerInterface;
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
* other controllers that extend Analytics.

View File

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

View File

@ -18,7 +18,6 @@ use App\Models\EpisodeModel;
use App\Models\PodcastModel;
use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\Response;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Embed;
use Config\Services;
@ -66,10 +65,7 @@ class EpisodeController extends BaseController
public function index(): string
{
// Prevent analytics hit when authenticated
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->episode->podcast_id);
}
$this->registerPodcastWebpageHit($this->episode->podcast_id);
$cacheName = implode(
'_',
@ -114,10 +110,7 @@ class EpisodeController extends BaseController
public function activity(): string
{
// Prevent analytics hit when authenticated
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->episode->podcast_id);
}
$this->registerPodcastWebpageHit($this->episode->podcast_id);
$cacheName = implode(
'_',
@ -163,10 +156,7 @@ class EpisodeController extends BaseController
public function chapters(): string
{
// Prevent analytics hit when authenticated
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->episode->podcast_id);
}
$this->registerPodcastWebpageHit($this->episode->podcast_id);
$cacheName = implode(
'_',
@ -222,10 +212,7 @@ class EpisodeController extends BaseController
public function transcript(): string
{
// Prevent analytics hit when authenticated
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->episode->podcast_id);
}
$this->registerPodcastWebpageHit($this->episode->podcast_id);
$cacheName = implode(
'_',
@ -288,10 +275,7 @@ class EpisodeController extends BaseController
{
header('Content-Security-Policy: frame-ancestors http://*:* https://*:*');
// Prevent analytics hit when authenticated
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->episode->podcast_id);
}
$this->registerPodcastWebpageHit($this->episode->podcast_id);
$session = Services::session();
@ -393,7 +377,7 @@ class EpisodeController extends BaseController
return $this->response->setXML($oembed);
}
public function episodeObject(): Response
public function episodeObject(): ResponseInterface
{
$podcastObject = new PodcastEpisode($this->episode);
@ -402,7 +386,7 @@ class EpisodeController extends BaseController
->setBody($podcastObject->toJSON());
}
public function comments(): Response
public function comments(): ResponseInterface
{
/**
* 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\PostModel;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\Response;
use CodeIgniter\HTTP\ResponseInterface;
use Modules\Analytics\AnalyticsTrait;
use Modules\Fediverse\Objects\OrderedCollectionObject;
use Modules\Fediverse\Objects\OrderedCollectionPage;
@ -47,7 +47,7 @@ class PodcastController extends BaseController
return $this->{$method}(...$params);
}
public function podcastActor(): Response
public function podcastActor(): ResponseInterface
{
$podcastActor = new PodcastActor($this->podcast);
@ -58,10 +58,7 @@ class PodcastController extends BaseController
public function activity(): string
{
// Prevent analytics hit when authenticated
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->podcast->id);
}
$this->registerPodcastWebpageHit($this->podcast->id);
$cacheName = implode(
'_',
@ -106,10 +103,7 @@ class PodcastController extends BaseController
public function about(): string
{
// Prevent analytics hit when authenticated
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->podcast->id);
}
$this->registerPodcastWebpageHit($this->podcast->id);
$cacheName = implode(
'_',
@ -156,10 +150,7 @@ class PodcastController extends BaseController
public function episodes(): string
{
// Prevent analytics hit when authenticated
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->podcast->id);
}
$this->registerPodcastWebpageHit($this->podcast->id);
$yearQuery = $this->request->getGet('year');
$seasonQuery = $this->request->getGet('season');
@ -274,7 +265,7 @@ class PodcastController extends BaseController
return $cachedView;
}
public function episodeCollection(): Response
public function episodeCollection(): ResponseInterface
{
if ($this->podcast->type === 'serial') {
// podcast is serial

View File

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

View File

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

View File

@ -72,6 +72,8 @@ export class PermalinkEdit extends LitElement {
}
firstUpdated(): void {
console.log(this._slugInput);
this.permalinkBase += this.permalinkBase.endsWith("/") ? "" : "/";
// set permalink value
@ -145,7 +147,7 @@ export class PermalinkEdit extends LitElement {
border-color: transparent !important;
padding-left: 0 !important;
margin-left: -0.25rem !important;
font-weight: 600;
font-weight: 600 !important;
}
::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',
'filter' => 'permission:admin.settings',
]);
$routes->post('instance', 'SettingsController::attemptInstanceEdit', [
$routes->post('instance', 'SettingsController::instanceEditAction', [
'as' => 'settings-instance',
'filter' => 'permission:admin.settings',
]);
$routes->get('instance-delete-icon', 'SettingsController::deleteIcon', [
$routes->get('instance-delete-icon', 'SettingsController::deleteIconAction', [
'as' => 'settings-instance-delete-icon',
'filter' => 'permission:admin.settings',
]);
$routes->post('instance-images-regenerate', 'SettingsController::regenerateImages', [
$routes->post('instance-images-regenerate', 'SettingsController::regenerateImagesAction', [
'as' => 'settings-images-regenerate',
'filter' => 'permission:admin.settings',
]);
$routes->post('instance-housekeeping-run', 'SettingsController::runHousekeeping', [
$routes->post('instance-housekeeping-run', 'SettingsController::housekeepingAction', [
'as' => 'settings-housekeeping-run',
'filter' => 'permission:admin.settings',
]);
$routes->get('theme', 'SettingsController::theme', [
$routes->get('theme', 'SettingsController::themeView', [
'as' => 'settings-theme',
'filter' => 'permission:admin.settings',
]);
$routes->post('theme', 'SettingsController::attemptSetInstanceTheme', [
$routes->post('theme', 'SettingsController::themeAction', [
'as' => 'settings-theme',
'filter' => 'permission:admin.settings',
]);
});
$routes->group('persons', static function ($routes): void {
$routes->get('/', 'PersonController', [
$routes->get('/', 'PersonController::list', [
'as' => 'person-list',
'filter' => 'permission:persons.manage',
]);
$routes->get('new', 'PersonController::create', [
$routes->get('new', 'PersonController::createView', [
'as' => 'person-create',
'filter' => 'permission:persons.manage',
]);
$routes->post('new', 'PersonController::attemptCreate', [
$routes->post('new', 'PersonController::createAction', [
'filter' => 'permission:persons.manage',
]);
$routes->group('(:num)', static function ($routes): void {
@ -71,14 +71,14 @@ $routes->group(
'as' => 'person-view',
'filter' => 'permission:persons.manage',
]);
$routes->get('edit', 'PersonController::edit/$1', [
$routes->get('edit', 'PersonController::editView/$1', [
'as' => 'person-edit',
'filter' => 'permission:persons.manage',
]);
$routes->post('edit', 'PersonController::attemptEdit/$1', [
$routes->post('edit', 'PersonController::editAction/$1', [
'filter' => 'permission:persons.manage',
]);
$routes->add('delete', 'PersonController::delete/$1', [
$routes->add('delete', 'PersonController::deleteAction/$1', [
'as' => 'person-delete',
'filter' => 'permission:persons.manage',
]);
@ -89,11 +89,11 @@ $routes->group(
$routes->get('/', 'PodcastController::list', [
'as' => 'podcast-list',
]);
$routes->get('new', 'PodcastController::create', [
$routes->get('new', 'PodcastController::createView', [
'as' => 'podcast-create',
'filter' => 'permission:podcasts.create',
]);
$routes->post('new', 'PodcastController::attemptCreate', [
$routes->post('new', 'PodcastController::createAction', [
'filter' => 'permission:podcasts.create',
]);
// Podcast
@ -103,16 +103,16 @@ $routes->group(
'as' => 'podcast-view',
'filter' => 'permission:podcast$1.view',
]);
$routes->get('edit', 'PodcastController::edit/$1', [
$routes->get('edit', 'PodcastController::editView/$1', [
'as' => 'podcast-edit',
'filter' => 'permission:podcast$1.edit',
]);
$routes->post('edit', 'PodcastController::attemptEdit/$1', [
$routes->post('edit', 'PodcastController::editAction/$1', [
'filter' => 'permission:podcast$1.edit',
]);
$routes->get(
'publish',
'PodcastController::publish/$1',
'PodcastController::publishView/$1',
[
'as' => 'podcast-publish',
'filter' => 'permission:podcast$1.manage-publications',
@ -120,14 +120,14 @@ $routes->group(
);
$routes->post(
'publish',
'PodcastController::attemptPublish/$1',
'PodcastController::publishAction/$1',
[
'filter' => 'permission:podcast$1.manage-publications',
],
);
$routes->get(
'publish-edit',
'PodcastController::publishEdit/$1',
'PodcastController::publishEditView/$1',
[
'as' => 'podcast-publish_edit',
'filter' => 'permission:podcast$1.manage-publications',
@ -135,28 +135,28 @@ $routes->group(
);
$routes->post(
'publish-edit',
'PodcastController::attemptPublishEdit/$1',
'PodcastController::publishEditAction/$1',
[
'filter' => 'permission:podcast$1.manage-publications',
],
);
$routes->get(
'publish-cancel',
'PodcastController::publishCancel/$1',
'PodcastController::publishCancelAction/$1',
[
'as' => 'podcast-publish-cancel',
'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',
'filter' => 'permission:podcast$1.edit',
]);
$routes->get('delete', 'PodcastController::delete/$1', [
$routes->get('delete', 'PodcastController::deleteView/$1', [
'as' => 'podcast-delete',
'filter' => 'permission:podcast$1.delete',
]);
$routes->post('delete', 'PodcastController::attemptDelete/$1', [
$routes->post('delete', 'PodcastController::deleteAction/$1', [
'filter' => 'permission:podcast$1.delete',
]);
$routes->group('persons', static function ($routes): void {
@ -166,14 +166,14 @@ $routes->group(
]);
$routes->post(
'/',
'PodcastPersonController::attemptCreate/$1',
'PodcastPersonController::createAction/$1',
[
'filter' => 'permission:podcast$1.manage-persons',
],
);
$routes->get(
'(:num)/remove',
'PodcastPersonController::remove/$1/$2',
'PodcastPersonController::deleteAction/$1/$2',
[
'as' => 'podcast-person-remove',
'filter' => 'permission:podcast$1.manage-persons',
@ -181,13 +181,13 @@ $routes->group(
);
});
$routes->group('analytics', static function ($routes): void {
$routes->get('/', 'PodcastController::viewAnalytics/$1', [
$routes->get('/', 'PodcastController::analyticsView/$1', [
'as' => 'podcast-analytics',
'filter' => 'permission:podcast$1.view',
]);
$routes->get(
'webpages',
'PodcastController::viewAnalyticsWebpages/$1',
'PodcastController::analyticsWebpagesView/$1',
[
'as' => 'podcast-analytics-webpages',
'filter' => 'permission:podcast$1.view',
@ -195,7 +195,7 @@ $routes->group(
);
$routes->get(
'locations',
'PodcastController::viewAnalyticsLocations/$1',
'PodcastController::analyticsLocationsView/$1',
[
'as' => 'podcast-analytics-locations',
'filter' => 'permission:podcast$1.view',
@ -203,7 +203,7 @@ $routes->group(
);
$routes->get(
'unique-listeners',
'PodcastController::viewAnalyticsUniqueListeners/$1',
'PodcastController::analyticsUniqueListenersView/$1',
[
'as' => 'podcast-analytics-unique-listeners',
'filter' => 'permission:podcast$1.view',
@ -211,7 +211,7 @@ $routes->group(
);
$routes->get(
'listening-time',
'PodcastController::viewAnalyticsListeningTime/$1',
'PodcastController::analyticsListeningTimeView/$1',
[
'as' => 'podcast-analytics-listening-time',
'filter' => 'permission:podcast$1.view',
@ -219,7 +219,7 @@ $routes->group(
);
$routes->get(
'time-periods',
'PodcastController::viewAnalyticsTimePeriods/$1',
'PodcastController::analyticsTimePeriodsView/$1',
[
'as' => 'podcast-analytics-time-periods',
'filter' => 'permission:podcast$1.view',
@ -227,7 +227,7 @@ $routes->group(
);
$routes->get(
'players',
'PodcastController::viewAnalyticsPlayers/$1',
'PodcastController::analyticsPlayersView/$1',
[
'as' => 'podcast-analytics-players',
'filter' => 'permission:podcast$1.view',
@ -240,13 +240,13 @@ $routes->group(
'as' => 'episode-list',
'filter' => 'permission:podcast$1.episodes.view',
]);
$routes->get('new', 'EpisodeController::create/$1', [
$routes->get('new', 'EpisodeController::createView/$1', [
'as' => 'episode-create',
'filter' => 'permission:podcast$1.episodes.create',
]);
$routes->post(
'new',
'EpisodeController::attemptCreate/$1',
'EpisodeController::createAction/$1',
[
'filter' => 'permission:podcast$1.episodes.create',
],
@ -257,20 +257,20 @@ $routes->group(
'as' => 'episode-view',
'filter' => 'permission:podcast$1.episodes.view',
]);
$routes->get('edit', 'EpisodeController::edit/$1/$2', [
$routes->get('edit', 'EpisodeController::editView/$1/$2', [
'as' => 'episode-edit',
'filter' => 'permission:podcast$1.episodes.edit',
]);
$routes->post(
'edit',
'EpisodeController::attemptEdit/$1/$2',
'EpisodeController::editAction/$1/$2',
[
'filter' => 'permission:podcast$1.episodes.edit',
],
);
$routes->get(
'publish',
'EpisodeController::publish/$1/$2',
'EpisodeController::publishView/$1/$2',
[
'as' => 'episode-publish',
'filter' => 'permission:podcast$1.episodes.manage-publications',
@ -278,14 +278,14 @@ $routes->group(
);
$routes->post(
'publish',
'EpisodeController::attemptPublish/$1/$2',
'EpisodeController::publishAction/$1/$2',
[
'filter' => 'permission:podcast$1.episodes.manage-publications',
],
);
$routes->get(
'publish-edit',
'EpisodeController::publishEdit/$1/$2',
'EpisodeController::publishEditView/$1/$2',
[
'as' => 'episode-publish_edit',
'filter' => 'permission:podcast$1.episodes.manage-publications',
@ -293,14 +293,14 @@ $routes->group(
);
$routes->post(
'publish-edit',
'EpisodeController::attemptPublishEdit/$1/$2',
'EpisodeController::publishEditAction/$1/$2',
[
'filter' => 'permission:podcast$1.episodes.manage-publications',
],
);
$routes->get(
'publish-cancel',
'EpisodeController::publishCancel/$1/$2',
'EpisodeController::publishCancelAction/$1/$2',
[
'as' => 'episode-publish-cancel',
'filter' => 'permission:podcast$1.episodes.manage-publications',
@ -308,7 +308,7 @@ $routes->group(
);
$routes->get(
'publish-date-edit',
'EpisodeController::publishDateEdit/$1/$2',
'EpisodeController::publishDateEditView/$1/$2',
[
'as' => 'episode-publish_date_edit',
'filter' => 'permission:podcast$1.episodes.manage-publications',
@ -316,14 +316,14 @@ $routes->group(
);
$routes->post(
'publish-date-edit',
'EpisodeController::attemptPublishDateEdit/$1/$2',
'EpisodeController::publishDateEditAction/$1/$2',
[
'filter' => 'permission:podcast$1.episodes.manage-publications',
],
);
$routes->get(
'unpublish',
'EpisodeController::unpublish/$1/$2',
'EpisodeController::unpublishView/$1/$2',
[
'as' => 'episode-unpublish',
'filter' => 'permission:podcast$1.episodes.manage-publications',
@ -331,14 +331,14 @@ $routes->group(
);
$routes->post(
'unpublish',
'EpisodeController::attemptUnpublish/$1/$2',
'EpisodeController::unpublishAction/$1/$2',
[
'filter' => 'permission:podcast$1.episodes.manage-publications',
],
);
$routes->get(
'delete',
'EpisodeController::delete/$1/$2',
'EpisodeController::deleteView/$1/$2',
[
'as' => 'episode-delete',
'filter' => 'permission:podcast$1.episodes.delete',
@ -346,7 +346,7 @@ $routes->group(
);
$routes->post(
'delete',
'EpisodeController::attemptDelete/$1/$2',
'EpisodeController::deleteAction/$1/$2',
[
'filter' => 'permission:podcast$1.episodes.delete',
],
@ -377,7 +377,7 @@ $routes->group(
);
$routes->get(
'soundbites/new',
'SoundbiteController::create/$1/$2',
'SoundbiteController::createView/$1/$2',
[
'as' => 'soundbites-create',
'filter' => 'permission:podcast$1.episodes.manage-clips',
@ -385,7 +385,7 @@ $routes->group(
);
$routes->post(
'soundbites/new',
'SoundbiteController::attemptCreate/$1/$2',
'SoundbiteController::createAction/$1/$2',
[
'as' => 'soundbites-create',
'filter' => 'permission:podcast$1.episodes.manage-clips',
@ -393,7 +393,7 @@ $routes->group(
);
$routes->get(
'soundbites/(:num)/delete',
'SoundbiteController::delete/$1/$2/$3',
'SoundbiteController::deleteAction/$1/$2/$3',
[
'as' => 'soundbites-delete',
'filter' => 'permission:podcast$1.episodes.manage-clips',
@ -409,7 +409,7 @@ $routes->group(
);
$routes->get(
'video-clips/new',
'VideoClipsController::create/$1/$2',
'VideoClipsController::createView/$1/$2',
[
'as' => 'video-clips-create',
'filter' => 'permission:podcast$1.episodes.manage-clips',
@ -417,7 +417,7 @@ $routes->group(
);
$routes->post(
'video-clips/new',
'VideoClipsController::attemptCreate/$1/$2',
'VideoClipsController::createAction/$1/$2',
[
'as' => 'video-clips-create',
'filter' => 'permission:podcast$1.episodes.manage-clips',
@ -433,7 +433,7 @@ $routes->group(
);
$routes->get(
'video-clips/(:num)/retry',
'VideoClipsController::retry/$1/$2/$3',
'VideoClipsController::retryAction/$1/$2/$3',
[
'as' => 'video-clip-retry',
'filter' => 'permission:podcast$1.episodes.manage-clips',
@ -441,7 +441,7 @@ $routes->group(
);
$routes->get(
'video-clips/(:num)/delete',
'VideoClipsController::delete/$1/$2/$3',
'VideoClipsController::deleteAction/$1/$2/$3',
[
'as' => 'video-clip-delete',
'filter' => 'permission:podcast$1.episodes.manage-clips',
@ -449,7 +449,7 @@ $routes->group(
);
$routes->get(
'embed',
'EpisodeController::embed/$1/$2',
'EpisodeController::embedView/$1/$2',
[
'as' => 'embed-add',
'filter' => 'permission:podcast$1.episodes.edit',
@ -462,14 +462,14 @@ $routes->group(
]);
$routes->post(
'/',
'EpisodePersonController::attemptCreate/$1/$2',
'EpisodePersonController::createAction/$1/$2',
[
'filter' => 'permission:podcast$1.episodes.manage-persons',
],
);
$routes->get(
'(:num)/remove',
'EpisodePersonController::remove/$1/$2/$3',
'EpisodePersonController::deleteAction/$1/$2/$3',
[
'as' => 'episode-person-remove',
'filter' => 'permission:podcast$1.episodes.manage-persons',
@ -479,7 +479,7 @@ $routes->group(
$routes->group('comments', static function ($routes): void {
$routes->post(
'new',
'EpisodeController::attemptCommentCreate/$1/$2',
'EpisodeController::commentCreateAction/$1/$2',
[
'as' => 'comment-attempt-create',
'filter' => 'permission:podcast$1.episodes.manage-comments',
@ -487,7 +487,7 @@ $routes->group(
);
$routes->post(
'(:uuid)/reply',
'EpisodeController::attemptCommentReply/$1/$2/$3',
'EpisodeController::commentReplyAction/$1/$2/$3',
[
'as' => 'comment-attempt-reply',
'filter' => 'permission:podcast$1.episodes.manage-comments',
@ -495,7 +495,7 @@ $routes->group(
);
$routes->post(
'delete',
'EpisodeController::attemptCommentDelete/$1/$2',
'EpisodeController::commentDeleteAction/$1/$2',
[
'as' => 'comment-attempt-delete',
'filter' => 'permission:podcast$1.episodes.manage-comments',
@ -510,11 +510,11 @@ $routes->group(
'as' => 'notification-list',
'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',
'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',
'filter' => 'permission:podcast$1.manage-notifications',
]);
@ -528,7 +528,7 @@ $routes->group(
]);
$routes->get(
'blocked-actors',
'FediverseController::blockedActors',
'FediverseController::blockedActorsView',
[
'as' => 'fediverse-blocked-actors',
'filter' => 'permission:fediverse.manage-blocks',
@ -536,7 +536,7 @@ $routes->group(
);
$routes->get(
'blocked-domains',
'FediverseController::blockedDomains',
'FediverseController::blockedDomainsView',
[
'as' => 'fediverse-blocked-domains',
'filter' => 'permission:fediverse.manage-blocks',
@ -549,25 +549,25 @@ $routes->group(
'as' => 'page-list',
'filter' => 'permission:pages.manage',
]);
$routes->get('new', 'PageController::create', [
$routes->get('new', 'PageController::createView', [
'as' => 'page-create',
'filter' => 'permission:pages.manage',
]);
$routes->post('new', 'PageController::attemptCreate', [
$routes->post('new', 'PageController::createAction', [
'filter' => 'permission:pages.manage',
]);
$routes->group('(:num)', static function ($routes): void {
$routes->get('/', 'PageController::view/$1', [
'as' => 'page-view',
]);
$routes->get('edit', 'PageController::edit/$1', [
$routes->get('edit', 'PageController::editView/$1', [
'as' => 'page-edit',
'filter' => 'permission:pages.manage',
]);
$routes->post('edit', 'PageController::attemptEdit/$1', [
$routes->post('edit', 'PageController::editAction/$1', [
'filter' => 'permission:pages.manage',
]);
$routes->get('delete', 'PageController::delete/$1', [
$routes->get('delete', 'PageController::deleteAction/$1', [
'as' => 'page-delete',
'filter' => 'permission:pages.manage',
]);

View File

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

View File

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

View File

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

View File

@ -27,70 +27,52 @@ class NotificationController extends BaseController
public function _remap(string $method, string ...$params): mixed
{
if ($params === []) {
throw PageNotFoundException::forPageNotFound();
}
if (
! ($podcast = (new PodcastModel())->getPodcastById((int) $params[0])) instanceof Podcast
) {
throw PageNotFoundException::forPageNotFound();
}
$this->podcast = $podcast;
$params[0] = $podcast;
if (count($params) > 1) {
if (
! ($notification = (new NotificationModel())
->where([
'id' => $params[1],
])
->first()) instanceof Notification
! ($notification = (new NotificationModel())->find($params[1])) instanceof Notification
) {
throw PageNotFoundException::forPageNotFound();
}
$this->notification = $notification;
unset($params[1]);
unset($params[0]);
$params[1] = $notification;
}
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');
$data = [
'podcast' => $this->podcast,
'podcast' => $podcast,
'notifications' => $notifications->paginate(10),
'pager' => $notifications->pager,
];
$this->setHtmlHead(lang('Notifications.title'));
replace_breadcrumb_params([
0 => $this->podcast->at_handle,
0 => $podcast->at_handle,
]);
return view('podcast/notifications', $data);
}
public function markAsRead(): RedirectResponse
public function markAllAsReadAction(Podcast $podcast): RedirectResponse
{
$this->notification->read_at = new Time('now');
$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)
$notifications = (new NotificationModel())->where('target_actor_id', $podcast->actor_id)
->where('read_at', null)
->findAll();
@ -101,4 +83,19 @@ class NotificationController extends BaseController
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
{
protected ?Page $page = null;
public function _remap(string $method, string ...$params): mixed
{
if ($params === []) {
return $this->{$method}();
}
if (($this->page = (new PageModel())->find($params[0])) instanceof Page) {
return $this->{$method}();
if (($page = (new PageModel())->find($params[0])) instanceof Page) {
return $this->{$method}($page);
}
throw PageNotFoundException::forPageNotFound();
@ -42,15 +40,15 @@ class PageController extends BaseController
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', [
'page' => $this->page,
'page' => $page,
]);
}
public function create(): string
public function createView(): string
{
helper('form');
@ -58,7 +56,7 @@ class PageController extends BaseController
return view('page/create');
}
public function attemptCreate(): RedirectResponse
public function createAction(): RedirectResponse
{
$page = new Page([
'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');
$this->setHtmlHead(lang('Page.edit'));
replace_breadcrumb_params([
0 => $this->page->title,
0 => $page->title,
]);
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');
$this->page->slug = $this->request->getPost('slug');
$this->page->content_markdown = $this->request->getPost('content');
$page->title = $this->request->getPost('title');
$page->slug = $this->request->getPost('slug');
$page->content_markdown = $this->request->getPost('content');
$pageModel = new PageModel();
if (! $pageModel->update($this->page->id, $this->page)) {
if (! $pageModel->update($page->id, $page)) {
return redirect()
->back()
->withInput()
->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');
}

View File

@ -18,8 +18,6 @@ use Modules\Media\Models\MediaModel;
class PersonController extends BaseController
{
protected ?Person $person = null;
public function _remap(string $method, string ...$params): mixed
{
if ($params === []) {
@ -27,15 +25,15 @@ class PersonController extends BaseController
}
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();
}
public function index(): string
public function list(): string
{
$data = [
'persons' => (new PersonModel())->orderBy('full_name')
@ -46,20 +44,20 @@ class PersonController extends BaseController
return view('person/list', $data);
}
public function view(): string
public function view(Person $person): string
{
$data = [
'person' => $this->person,
'person' => $person,
];
$this->setHtmlHead($this->person->full_name);
$this->setHtmlHead($person->full_name);
replace_breadcrumb_params([
0 => $this->person->full_name,
0 => $person->full_name,
]);
return view('person/view', $data);
}
public function create(): string
public function createView(): string
{
helper(['form']);
@ -67,7 +65,7 @@ class PersonController extends BaseController
return view('person/create');
}
public function attemptCreate(): RedirectResponse
public function createAction(): RedirectResponse
{
$rules = [
'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'));
}
public function edit(): string
public function editView(Person $person): string
{
helper('form');
$data = [
'person' => $this->person,
'person' => $person,
];
$this->setHtmlHead(lang('Person.edit'));
replace_breadcrumb_params([
0 => $this->person->full_name,
0 => $person->full_name,
]);
return view('person/edit', $data);
}
public function attemptEdit(): RedirectResponse
public function editAction(Person $person): RedirectResponse
{
$rules = [
'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());
}
$this->person->updated_by = user_id();
$this->person->full_name = $this->request->getPost('full_name');
$this->person->unique_name = $this->request->getPost('unique_name');
$this->person->information_url = $this->request->getPost('information_url');
$this->person->setAvatar($this->request->getFile('avatar'));
$person->updated_by = user_id();
$person->full_name = $this->request->getPost('full_name');
$person->unique_name = $this->request->getPost('unique_name');
$person->information_url = $this->request->getPost('information_url');
$person->setAvatar($this->request->getFile('avatar'));
$personModel = new PersonModel();
if (! $personModel->update($this->person->id, $this->person)) {
if (! $personModel->update($person->id, $person)) {
return redirect()
->back()
->withInput()
->with('errors', $personModel->errors());
}
return redirect()->route('person-edit', [$this->person->id])->with(
return redirect()->route('person-edit', [$person->id])->with(
'message',
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
(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')
->with('message', lang('Person.messages.deleteSuccess'));

View File

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

View File

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

View File

@ -34,7 +34,7 @@ class SettingsController extends BaseController
return view('settings/general');
}
public function attemptInstanceEdit(): RedirectResponse
public function instanceEditAction(): RedirectResponse
{
$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',
@ -119,7 +119,7 @@ class SettingsController extends BaseController
return redirect('settings-general')->with('message', lang('Settings.instance.editSuccess'));
}
public function deleteIcon(): RedirectResponse
public function deleteIconAction(): RedirectResponse
{
/** @var FileManagerInterface $fileManager */
$fileManager = service('file_manager');
@ -133,7 +133,7 @@ class SettingsController extends BaseController
return redirect('settings-general')->with('message', lang('Settings.instance.deleteIconSuccess'));
}
public function regenerateImages(): RedirectResponse
public function regenerateImagesAction(): RedirectResponse
{
/** @var Podcast[] $allPodcasts */
$allPodcasts = (new PodcastModel())->findAll();
@ -168,7 +168,7 @@ class SettingsController extends BaseController
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') {
// recalculate fediverse counts
@ -200,14 +200,14 @@ class SettingsController extends BaseController
return redirect('settings-general')->with('message', lang('Settings.housekeeping.runSuccess'));
}
public function theme(): string
public function themeView(): string
{
helper('form');
$this->setHtmlHead(lang('Settings.theme.title'));
return view('settings/theme');
}
public function attemptSetInstanceTheme(): RedirectResponse
public function themeAction(): RedirectResponse
{
$theme = $this->request->getPost('theme');
service('settings')

View File

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

View File

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

View File

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

View File

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

View File

@ -81,7 +81,7 @@ class ContributorController extends BaseController
return view('contributor/view', $data);
}
public function create(): string
public function createView(): string
{
helper('form');
@ -125,7 +125,7 @@ class ContributorController extends BaseController
return view('contributor/create', $data);
}
public function attemptCreate(): RedirectResponse
public function createAction(): RedirectResponse
{
/** @var User $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]);
}
public function edit(): string|RedirectResponse
public function editView(): string|RedirectResponse
{
helper('form');
@ -184,7 +184,7 @@ class ContributorController extends BaseController
return view('contributor/edit', $data);
}
public function attemptEdit(): RedirectResponse
public function editAction(): RedirectResponse
{
// forbid updating a podcast owner
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');
@ -225,7 +225,7 @@ class ContributorController extends BaseController
return view('contributor/delete', $data);
}
public function attemptRemove(): RedirectResponse
public function deleteAction(): RedirectResponse
{
if ($this->podcast->created_by === $this->contributor->id) {
return redirect()

View File

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

View File

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

View File

@ -61,7 +61,7 @@ class UserController extends BaseController
return view('user/view', $data);
}
public function create(): string
public function createView(): string
{
helper('form');
@ -70,7 +70,10 @@ class UserController extends BaseController
array_walk(
$roles,
static function (array $role, $key) use (&$roleOptions): array {
$roleOptions[$key] = $role['title'];
$roleOptions[] = [
'value' => $key,
'label' => $role['title'],
];
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
* sent to the user to allow them setting their password.
*/
public function attemptCreate(): RedirectResponse
public function createAction(): RedirectResponse
{
helper(['text', 'email']);
@ -167,7 +170,7 @@ class UserController extends BaseController
]));
}
public function edit(): string
public function editView(): string
{
helper('form');
@ -176,7 +179,10 @@ class UserController extends BaseController
array_walk(
$roles,
static function (array $role, $key) use (&$roleOptions): array {
$roleOptions[$key] = $role['title'];
$roleOptions[] = [
'value' => $key,
'label' => $role['title'],
];
return $roleOptions;
},
[],
@ -196,7 +202,7 @@ class UserController extends BaseController
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.
if ((bool) $this->user->is_owner) {
@ -221,7 +227,7 @@ class UserController extends BaseController
]));
}
public function delete(): string
public function deleteView(): string
{
helper(['form']);
@ -238,7 +244,7 @@ class UserController extends BaseController
return view('user/delete', $data);
}
public function attemptDelete(): RedirectResponse
public function deleteAction(): RedirectResponse
{
// You cannot delete the instance owner.
if ((bool) $this->user->is_owner) {

View File

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

View File

@ -319,7 +319,7 @@ class ActorController extends Controller
->setBody($followersCollection->toJSON());
}
public function attemptFollow(): RedirectResponse
public function followAction(): RedirectResponse
{
$rules = [
'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'];
public function attemptBlockActor(): RedirectResponse
public function blockActorAction(): RedirectResponse
{
$rules = [
'handle' => 'required|regex_match[/^@?([\w\.\-]+)@([\w\.\-]+)(:[\d]+)?$/]',
@ -58,7 +58,7 @@ class BlockController extends Controller
]));
}
public function attemptUnblockActor(): RedirectResponse
public function unblockActorAction(): RedirectResponse
{
$rules = [
'actor_id' => 'required',
@ -80,7 +80,7 @@ class BlockController extends Controller
->with('message', lang('Fediverse.messages.unblockActorSuccess'));
}
public function attemptBlockDomain(): RedirectResponse
public function blockDomainAction(): RedirectResponse
{
$rules = [
'domain' => 'required|regex_match[/^[\w\-\.]+[\w]+(:[\d]+)?/]',
@ -105,7 +105,7 @@ class BlockController extends Controller
]));
}
public function attemptUnblockDomain(): RedirectResponse
public function unblockDomainAction(): RedirectResponse
{
$rules = [
'domain' => 'required',

View File

@ -112,7 +112,7 @@ class PostController extends Controller
->setBody($collection->toJSON());
}
public function attemptCreate(): RedirectResponse
public function createAction(): RedirectResponse
{
$rules = [
'actor_id' => 'required|is_natural_no_zero',
@ -147,7 +147,7 @@ class PostController extends Controller
return redirect()->back();
}
public function attemptFavourite(): RedirectResponse
public function favouriteAction(): RedirectResponse
{
$rules = [
'actor_id' => 'required|is_natural_no_zero',
@ -171,7 +171,7 @@ class PostController extends Controller
return redirect()->back();
}
public function attemptReblog(): RedirectResponse
public function reblogAction(): RedirectResponse
{
$rules = [
'actor_id' => 'required|is_natural_no_zero',
@ -195,7 +195,7 @@ class PostController extends Controller
return redirect()->back();
}
public function attemptReply(): RedirectResponse
public function replyAction(): RedirectResponse
{
$rules = [
'actor_id' => 'required|is_natural_no_zero',
@ -230,7 +230,7 @@ class PostController extends Controller
return redirect()->back();
}
public function attemptRemoteAction(string $action): RedirectResponse | ResponseInterface
public function remoteActionAction(string $action): RedirectResponse | ResponseInterface
{
$rules = [
'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);
return redirect()->back();
}
public function attemptBlockDomain(): RedirectResponse
public function blockDomainAction(): RedirectResponse
{
model('BlockedDomainModel', false)->blockDomain($this->post->actor->domain);
return redirect()->back();
}
public function attemptDelete(): RedirectResponse
public function deleteAction(): RedirectResponse
{
model('PostModel', false)->removePost($this->post);

View File

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

View File

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

View File

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

View File

@ -45,7 +45,7 @@ class PlatformController extends BaseController
return view('podcast/platforms/dashboard');
}
public function platforms(string $platformType): string
public function list(string $platformType): string
{
helper('form');
@ -62,7 +62,7 @@ class PlatformController extends BaseController
return view('podcast/platforms', $data);
}
public function attemptPlatformsUpdate(string $platformType): RedirectResponse
public function updateAction(string $platformType): RedirectResponse
{
$platformModel = new PlatformModel();
$validation = Services::validation();
@ -99,7 +99,7 @@ class PlatformController extends BaseController
->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);

View File

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

View File

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

View File

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

View File

@ -117,7 +117,11 @@ final class PluginsTest extends CIUnitTestCase
$this->assertEquals(
(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
if (\'serviceWorker\' in navigator) {
// Use the window load event to keep the page load performant

View File

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

View File

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

View File

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

View File

@ -19,13 +19,14 @@
slot="slug-input"
class="max-w-sm" />
<div class="flex flex-col max-w-sm">
<x-Forms.Label for="slug"><?= lang('Page.form.permalink') ?></x-Forms.Label>
<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') ?>">
<span slot="domain" class="flex-shrink-0">/pages/<span>
<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) ?>"/>
</permalink-edit>
</div>
<x-Forms.PermalinkEditor
name="slug"
label="<?= lang('Page.form.permalink') ?>"
prefix="…/pages/"
data-slugify="slug"
permalinkBase="<?= base_url('pages') ?>"
value="<?= $page->slug ?>"
/>
<x-Forms.Field
as="MarkdownEditor"

View File

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

View File

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