style(ecs): add easy-coding-standard to enforce coding style rules for php

- update .devcontainer settings: remove auto-formatting
for php + set intelephense as default formatter
- remove prettier php plugin as it lacks php 8 support
- add captain hook action for checking style pre-commit
- fix style with ecs on all files except views
This commit is contained in:
Yassine Doghri 2021-05-19 16:35:13 +00:00
parent fb3593f828
commit aa1612342e
No known key found for this signature in database
GPG Key ID: 3E7F89498B960C9F
230 changed files with 3341 additions and 5805 deletions

View File

@ -10,9 +10,9 @@
"terminal.integrated.defaultProfile.linux": "/bin/bash", "terminal.integrated.defaultProfile.linux": "/bin/bash",
"editor.formatOnSave": true, "editor.formatOnSave": true,
"[php]": { "[php]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "bmewburn.vscode-intelephense-client",
"editor.formatOnSave": false
}, },
"phpSniffer.autoDetect": true,
"color-highlight.markerType": "dot-before", "color-highlight.markerType": "dot-before",
"files.associations": { "files.associations": {
"*.xml.dist": "xml", "*.xml.dist": "xml",
@ -31,7 +31,6 @@
"jamesbirtles.svelte-vscode", "jamesbirtles.svelte-vscode",
"dbaeumer.vscode-eslint", "dbaeumer.vscode-eslint",
"stylelint.vscode-stylelint", "stylelint.vscode-stylelint",
"wongjn.php-sniffer",
"eamodio.gitlens", "eamodio.gitlens",
"breezelin.phpstan", "breezelin.phpstan",
"kasik96.latte" "kasik96.latte"

View File

@ -1,7 +0,0 @@
<?xml version="1.0"?>
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Castopod">
<description>Castopod Host's coding standard based on the PSR-1 standard.</description>
<!-- Include the whole PSR-1 standard -->
<rule ref="PSR1"/>
</ruleset>

View File

@ -1,13 +1,6 @@
{ {
"trailingComma": "es5", "trailingComma": "es5",
"overrides": [ "overrides": [
{
"files": "*.php",
"options": {
"phpVersion": "7.4",
"singleQuote": true
}
},
{ {
"files": "*.md", "files": "*.md",
"options": { "options": {

View File

@ -7,9 +7,8 @@ use Myth\Auth\Authorization\FlatAuthorization as MythAuthFlatAuthorization;
class FlatAuthorization extends MythAuthFlatAuthorization class FlatAuthorization extends MythAuthFlatAuthorization
{ {
/** /**
* The group model to use. Usually the class noted * The group model to use. Usually the class noted below (or an extension thereof) but can be any compatible
* below (or an extension thereof) but can be any * CodeIgniter Model.
* compatible CodeIgniter Model.
* *
* @var PermissionModel * @var PermissionModel
*/ */
@ -18,19 +17,16 @@ class FlatAuthorization extends MythAuthFlatAuthorization
/** /**
* Checks a group to see if they have the specified permission. * Checks a group to see if they have the specified permission.
*/ */
public function groupHasPermission(int|string $permission, int $groupId): bool public function groupHasPermission(int | string $permission, int $groupId): bool
{ {
// Get the Permission ID // Get the Permission ID
$permissionId = $this->getPermissionID($permission); $permissionId = $this->getPermissionID($permission);
if (!is_numeric($permissionId)) { if (! is_numeric($permissionId)) {
return false; return false;
} }
return $this->permissionModel->doesGroupHavePermission( return $this->permissionModel->doesGroupHavePermission($groupId, $permissionId,);
$groupId,
$permissionId,
);
} }
/** /**

View File

@ -7,13 +7,10 @@ use Myth\Auth\Authorization\PermissionModel as MythAuthPermissionModel;
class PermissionModel extends MythAuthPermissionModel class PermissionModel extends MythAuthPermissionModel
{ {
/** /**
* Checks to see if a user, or one of their groups, * Checks to see if a user, or one of their groups, has a specific permission.
* has a specific permission.
*/ */
public function doesGroupHavePermission( public function doesGroupHavePermission(int $groupId, int $permissionId): bool
int $groupId, {
int $permissionId
): bool {
// Check group permissions and take advantage of caching // Check group permissions and take advantage of caching
$groupPerms = $this->getPermissionsForGroup($groupId); $groupPerms = $this->getPermissionsForGroup($groupId);
@ -22,28 +19,20 @@ class PermissionModel extends MythAuthPermissionModel
} }
/** /**
* Gets all permissions for a group in a way that can be * Gets all permissions for a group in a way that can be easily used to check against:
* easily used to check against:
* *
* [ * [ id => name, id => name ]
* id => name,
* id => name
* ]
* *
* @return array<int, string> * @return array<int, string>
*/ */
public function getPermissionsForGroup(int $groupId): array public function getPermissionsForGroup(int $groupId): array
{ {
$cacheName = "group{$groupId}_permissions"; $cacheName = "group{$groupId}_permissions";
if (!($found = cache($cacheName))) { if (! ($found = cache($cacheName))) {
$groupPermissions = $this->db $groupPermissions = $this->db
->table('auth_groups_permissions') ->table('auth_groups_permissions')
->select('id, auth_permissions.name') ->select('id, auth_permissions.name')
->join( ->join('auth_permissions', 'auth_permissions.id = permission_id', 'inner',)
'auth_permissions',
'auth_permissions.id = permission_id',
'inner',
)
->where('group_id', $groupId) ->where('group_id', $groupId)
->get() ->get()
->getResultObject(); ->getResultObject();
@ -53,7 +42,8 @@ class PermissionModel extends MythAuthPermissionModel
$found[$row->id] = strtolower($row->name); $found[$row->id] = strtolower($row->name);
} }
cache()->save($cacheName, $found, 300); cache()
->save($cacheName, $found, 300);
} }
return $found; return $found;

View File

@ -1,14 +1,11 @@
<?php <?php
/** /**
* The goal of this file is to allow developers a location * The goal of this file is to allow developers a location where they can overwrite core procedural functions and
* where they can overwrite core procedural functions and * replace them with their own. This file is loaded during the bootstrap process and is called during the frameworks
* replace them with their own. This file is loaded during
* the bootstrap process and is called during the frameworks
* execution. * execution.
* *
* This can be looked at as a `master helper` file that is * This can be looked at as a `master helper` file that is loaded early on, and may also contain additional functions
* loaded early on, and may also contain additional functions
* that you'd like to use throughout your entire application * that you'd like to use throughout your entire application
* *
* @link: https://codeigniter4.github.io/CodeIgniter4/ * @link: https://codeigniter4.github.io/CodeIgniter4/

View File

@ -1,8 +1,10 @@
<?php namespace Config; <?php
namespace Config;
use App\Libraries\PodcastActor;
use App\Libraries\NoteObject;
use ActivityPub\Config\ActivityPub as ActivityPubBase; use ActivityPub\Config\ActivityPub as ActivityPubBase;
use App\Libraries\NoteObject;
use App\Libraries\PodcastActor;
class ActivityPub extends ActivityPubBase class ActivityPub extends ActivityPubBase
{ {

View File

@ -23,7 +23,8 @@ class Analytics extends AnalyticsBase
// set the analytics gateway behind the admin gateway. // set the analytics gateway behind the admin gateway.
// Only logged in users should be able to view analytics // Only logged in users should be able to view analytics
$this->gateway = config('App')->adminGateway . '/analytics'; $this->gateway = config('App')
->adminGateway . '/analytics';
} }
/** /**

View File

@ -2,8 +2,8 @@
namespace Config; namespace Config;
use CodeIgniter\Session\Handlers\FileHandler;
use CodeIgniter\Config\BaseConfig; use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Session\Handlers\FileHandler;
class App extends BaseConfig class App extends BaseConfig
{ {
@ -21,7 +21,6 @@ class App extends BaseConfig
* and path to your installation. However, you should always configure this * and path to your installation. However, you should always configure this
* explicitly and never rely on auto-guessing, especially in production * explicitly and never rely on auto-guessing, especially in production
* environments. * environments.
*
*/ */
public string $baseURL = 'http://localhost:8080/'; public string $baseURL = 'http://localhost:8080/';
@ -34,7 +33,6 @@ class App extends BaseConfig
* WITH a trailing slash: * WITH a trailing slash:
* *
* http://cdn.example.com/ * http://cdn.example.com/
*
*/ */
public string $mediaBaseURL = 'http://127.0.0.2:8080/'; public string $mediaBaseURL = 'http://127.0.0.2:8080/';
@ -46,7 +44,6 @@ class App extends BaseConfig
* Typically this will be your index.php file, unless you've renamed it to * Typically this will be your index.php file, unless you've renamed it to
* something else. If you are using mod_rewrite to remove the page set this * something else. If you are using mod_rewrite to remove the page set this
* variable so that it is blank. * variable so that it is blank.
*
*/ */
public string $indexPage = ''; public string $indexPage = '';
@ -64,7 +61,6 @@ class App extends BaseConfig
* 'PATH_INFO' Uses $_SERVER['PATH_INFO'] * 'PATH_INFO' Uses $_SERVER['PATH_INFO']
* *
* WARNING: If you set this to 'PATH_INFO', URIs will always be URL-decoded! * WARNING: If you set this to 'PATH_INFO', URIs will always be URL-decoded!
*
*/ */
public string $uriProtocol = 'REQUEST_URI'; public string $uriProtocol = 'REQUEST_URI';
@ -77,7 +73,6 @@ class App extends BaseConfig
* is viewing the site from. It affects the language strings and other * is viewing the site from. It affects the language strings and other
* strings (like currency markers, numbers, etc), that your program * strings (like currency markers, numbers, etc), that your program
* should run under for this request. * should run under for this request.
*
*/ */
public string $defaultLocale = 'en'; public string $defaultLocale = 'en';
@ -113,7 +108,6 @@ class App extends BaseConfig
* *
* The default timezone that will be used in your application to display * The default timezone that will be used in your application to display
* dates with the date helper, and can be retrieved through app_timezone() * dates with the date helper, and can be retrieved through app_timezone()
*
*/ */
public string $appTimezone = 'UTC'; public string $appTimezone = 'UTC';
@ -126,7 +120,6 @@ class App extends BaseConfig
* that require a character set to be provided. * that require a character set to be provided.
* *
* @see http://php.net/htmlspecialchars for a list of supported charsets. * @see http://php.net/htmlspecialchars for a list of supported charsets.
*
*/ */
public string $charset = 'UTF-8'; public string $charset = 'UTF-8';
@ -139,7 +132,6 @@ class App extends BaseConfig
* made via a secure connection (HTTPS). If the incoming request is not * made via a secure connection (HTTPS). If the incoming request is not
* secure, the user will be redirected to a secure version of the page * secure, the user will be redirected to a secure version of the page
* and the HTTP Strict Transport Security header will be set. * and the HTTP Strict Transport Security header will be set.
*
*/ */
public bool $forceGlobalSecureRequests = true; public bool $forceGlobalSecureRequests = true;
@ -153,7 +145,6 @@ class App extends BaseConfig
* - `CodeIgniter\Session\Handlers\DatabaseHandler` * - `CodeIgniter\Session\Handlers\DatabaseHandler`
* - `CodeIgniter\Session\Handlers\MemcachedHandler` * - `CodeIgniter\Session\Handlers\MemcachedHandler`
* - `CodeIgniter\Session\Handlers\RedisHandler` * - `CodeIgniter\Session\Handlers\RedisHandler`
*
*/ */
public string $sessionDriver = FileHandler::class; public string $sessionDriver = FileHandler::class;
@ -163,7 +154,6 @@ class App extends BaseConfig
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* *
* The session cookie name, must contain only [0-9a-z_-] characters * The session cookie name, must contain only [0-9a-z_-] characters
*
*/ */
public string $sessionCookieName = 'ci_session'; public string $sessionCookieName = 'ci_session';
@ -174,7 +164,6 @@ class App extends BaseConfig
* *
* The number of SECONDS you want the session to last. * The number of SECONDS you want the session to last.
* Setting to 0 (zero) means expire when the browser is closed. * Setting to 0 (zero) means expire when the browser is closed.
*
*/ */
public int $sessionExpiration = 7200; public int $sessionExpiration = 7200;
@ -192,7 +181,6 @@ class App extends BaseConfig
* Please read up the manual for the format with other session drivers. * Please read up the manual for the format with other session drivers.
* *
* IMPORTANT: You are REQUIRED to set a valid save path! * IMPORTANT: You are REQUIRED to set a valid save path!
*
*/ */
public string $sessionSavePath = WRITEPATH . 'session'; public string $sessionSavePath = WRITEPATH . 'session';
@ -205,7 +193,6 @@ class App extends BaseConfig
* *
* WARNING: If you're using the database driver, don't forget to update * WARNING: If you're using the database driver, don't forget to update
* your session table's PRIMARY KEY when changing this setting. * your session table's PRIMARY KEY when changing this setting.
*
*/ */
public bool $sessionMatchIP = false; public bool $sessionMatchIP = false;
@ -215,7 +202,6 @@ class App extends BaseConfig
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* *
* How many seconds between CI regenerating the session ID. * How many seconds between CI regenerating the session ID.
*
*/ */
public int $sessionTimeToUpdate = 300; public int $sessionTimeToUpdate = 300;
@ -227,7 +213,6 @@ class App extends BaseConfig
* Whether to destroy session data associated with the old session ID * Whether to destroy session data associated with the old session ID
* when auto-regenerating the session ID. When set to FALSE, the data * when auto-regenerating the session ID. When set to FALSE, the data
* will be later deleted by the garbage collector. * will be later deleted by the garbage collector.
*
*/ */
public bool $sessionRegenerateDestroy = false; public bool $sessionRegenerateDestroy = false;
@ -238,8 +223,6 @@ class App extends BaseConfig
* *
* Set a cookie name prefix if you need to avoid collisions. * Set a cookie name prefix if you need to avoid collisions.
* *
* @var string
*
* @deprecated use Config\Cookie::$prefix property instead. * @deprecated use Config\Cookie::$prefix property instead.
*/ */
public string $cookiePrefix = ''; public string $cookiePrefix = '';
@ -251,8 +234,6 @@ class App extends BaseConfig
* *
* Set to `.your-domain.com` for site-wide cookies. * Set to `.your-domain.com` for site-wide cookies.
* *
* @var string
*
* @deprecated use Config\Cookie::$domain property instead. * @deprecated use Config\Cookie::$domain property instead.
*/ */
public string $cookieDomain = ''; public string $cookieDomain = '';
@ -264,8 +245,6 @@ class App extends BaseConfig
* *
* Typically will be a forward slash. * Typically will be a forward slash.
* *
* @var string
*
* @deprecated use Config\Cookie::$path property instead. * @deprecated use Config\Cookie::$path property instead.
*/ */
public string $cookiePath = '/'; public string $cookiePath = '/';
@ -277,8 +256,6 @@ class App extends BaseConfig
* *
* Cookie will only be set if a secure HTTPS connection exists. * Cookie will only be set if a secure HTTPS connection exists.
* *
* @var bool
*
* @deprecated use Config\Cookie::$secure property instead. * @deprecated use Config\Cookie::$secure property instead.
*/ */
public bool $cookieSecure = false; public bool $cookieSecure = false;
@ -316,8 +293,6 @@ class App extends BaseConfig
* (empty string) means default SameSite attribute set by browsers (`Lax`) * (empty string) means default SameSite attribute set by browsers (`Lax`)
* will be set on cookies. If set to `None`, `$cookieSecure` must also be set. * will be set on cookies. If set to `None`, `$cookieSecure` must also be set.
* *
* @var string
*
* @deprecated use Config\Cookie::$samesite property instead. * @deprecated use Config\Cookie::$samesite property instead.
*/ */
public string $cookieSameSite = 'Lax'; public string $cookieSameSite = 'Lax';
@ -340,7 +315,7 @@ class App extends BaseConfig
* *
* @var string|string[] * @var string|string[]
*/ */
public string|array $proxyIPs = ''; public string | array $proxyIPs = '';
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------

View File

@ -40,7 +40,7 @@ class Autoload extends AutoloadConfig
* @var array<string, string> * @var array<string, string>
*/ */
public $psr4 = [ public $psr4 = [
APP_NAMESPACE => APPPATH, // For custom app namespace APP_NAMESPACE => APPPATH,
'Config' => APPPATH . 'Config', 'Config' => APPPATH . 'Config',
'ActivityPub' => APPPATH . 'Libraries/ActivityPub', 'ActivityPub' => APPPATH . 'Libraries/ActivityPub',
'Analytics' => APPPATH . 'Libraries/Analytics', 'Analytics' => APPPATH . 'Libraries/Analytics',

View File

@ -8,14 +8,7 @@
* it and display a generic error message. * it and display a generic error message.
*/ */
ini_set('display_errors', '0'); ini_set('display_errors', '0');
error_reporting( error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT & ~E_USER_NOTICE & ~E_USER_DEPRECATED,);
E_ALL &
~E_NOTICE &
~E_DEPRECATED &
~E_STRICT &
~E_USER_NOTICE &
~E_USER_DEPRECATED,
);
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------

View File

@ -19,7 +19,6 @@ class Cache extends BaseConfig
* *
* The name of the preferred handler that should be used. If for some reason * The name of the preferred handler that should be used. If for some reason
* it is not available, the $backupHandler will be used in its place. * it is not available, the $backupHandler will be used in its place.
*
*/ */
public string $handler = 'file'; public string $handler = 'file';
@ -31,7 +30,6 @@ class Cache extends BaseConfig
* The name of the handler that will be used in case the first one is * The name of the handler that will be used in case the first one is
* unreachable. Often, 'file' is used here since the filesystem is * unreachable. Often, 'file' is used here since the filesystem is
* always available, though that's not always practical for the app. * always available, though that's not always practical for the app.
*
*/ */
public string $backupHandler = 'dummy'; public string $backupHandler = 'dummy';
@ -64,7 +62,7 @@ class Cache extends BaseConfig
* *
* @var boolean|string[] * @var boolean|string[]
*/ */
public bool|array $cacheQueryString = false; public bool | array $cacheQueryString = false;
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
@ -73,7 +71,6 @@ class Cache extends BaseConfig
* *
* This string is added to all cache item names to help avoid collisions * This string is added to all cache item names to help avoid collisions
* if you run multiple applications with the same cache engine. * if you run multiple applications with the same cache engine.
*
*/ */
public string $prefix = ''; public string $prefix = '';

View File

@ -5,9 +5,8 @@ namespace Config;
use CodeIgniter\Config\BaseConfig; use CodeIgniter\Config\BaseConfig;
/** /**
* Stores the default settings for the ContentSecurityPolicy, if you * Stores the default settings for the ContentSecurityPolicy, if you choose to use it. The values here will be read in
* choose to use it. The values here will be read in and set as defaults * and set as defaults for the site. If needed, they can be overridden on a page-by-page basis.
* for the site. If needed, they can be overridden on a page-by-page basis.
* *
* Suggested reference for explanations: * Suggested reference for explanations:
* *
@ -15,64 +14,49 @@ use CodeIgniter\Config\BaseConfig;
*/ */
class ContentSecurityPolicy extends BaseConfig class ContentSecurityPolicy extends BaseConfig
{ {
//-------------------------------------------------------------------------
// Broadbrush CSP management
//-------------------------------------------------------------------------
/** /**
* Default CSP report context * Default CSP report context
*
*/ */
public bool $reportOnly = false; public bool $reportOnly = false;
/** /**
* Specifies a URL where a browser will send reports * Specifies a URL where a browser will send reports when a content security policy is violated.
* when a content security policy is violated.
*
* @var string|null
*/ */
public ?string $reportURI = null; public ?string $reportURI = null;
/** /**
* Instructs user agents to rewrite URL schemes, changing * Instructs user agents to rewrite URL schemes, changing HTTP to HTTPS. This directive is for websites with large
* HTTP to HTTPS. This directive is for websites with * numbers of old URLs that need to be rewritten.
* large numbers of old URLs that need to be rewritten.
*
*/ */
public bool $upgradeInsecureRequests = false; public bool $upgradeInsecureRequests = false;
//-------------------------------------------------------------------------
// Sources allowed
// Note: once you set a policy to 'none', it cannot be further restricted
//-------------------------------------------------------------------------
/** /**
* Will default to self if not overridden * Will default to self if not overridden
* *
* @var string|string[]|null * @var string|string[]|null
*/ */
public string|array|null $defaultSrc; public string | array | null $defaultSrc;
/** /**
* Lists allowed scripts' URLs. * Lists allowed scripts' URLs.
* *
* @var string|string[] * @var string|string[]
*/ */
public string|array $scriptSrc = 'self'; public string | array $scriptSrc = 'self';
/** /**
* Lists allowed stylesheets' URLs. * Lists allowed stylesheets' URLs.
* *
* @var string|string[] * @var string|string[]
*/ */
public string|array $styleSrc = 'self'; public string | array $styleSrc = 'self';
/** /**
* Defines the origins from which images can be loaded. * Defines the origins from which images can be loaded.
* *
* @var string|string[] * @var string|string[]
*/ */
public string|array $imageSrc = 'self'; public string | array $imageSrc = 'self';
/** /**
* Restricts the URLs that can appear in a page's `<base>` element. * Restricts the URLs that can appear in a page's `<base>` element.
@ -81,77 +65,75 @@ class ContentSecurityPolicy extends BaseConfig
* *
* @var string|string[]|null * @var string|string[]|null
*/ */
public string|array|null $baseURI; public string | array | null $baseURI;
/** /**
* Lists the URLs for workers and embedded frame contents * Lists the URLs for workers and embedded frame contents
* *
* @var string|string[] * @var string|string[]
*/ */
public string|array $childSrc = 'self'; public string | array $childSrc = 'self';
/** /**
* Limits the origins that you can connect to (via XHR, * Limits the origins that you can connect to (via XHR, WebSockets, and EventSource).
* WebSockets, and EventSource).
* *
* @var string|string[] * @var string|string[]
*/ */
public string|array $connectSrc = 'self'; public string | array $connectSrc = 'self';
/** /**
* Specifies the origins that can serve web fonts. * Specifies the origins that can serve web fonts.
* *
* @var string|string[] * @var string|string[]
*/ */
public string|array $fontSrc; public string | array $fontSrc;
/** /**
* Lists valid endpoints for submission from `<form>` tags. * Lists valid endpoints for submission from `<form>` tags.
* *
* @var string|string[] * @var string|string[]
*/ */
public string|array $formAction = 'self'; public string | array $formAction = 'self';
/** /**
* Specifies the sources that can embed the current page. * Specifies the sources that can embed the current page. This directive applies to `<frame>`, `<iframe>`,
* This directive applies to `<frame>`, `<iframe>`, `<embed>`, * `<embed>`, and `<applet>` tags. This directive can't be used in `<meta>` tags and applies only to non-HTML
* and `<applet>` tags. This directive can't be used in * resources.
* `<meta>` tags and applies only to non-HTML resources.
* *
* @var string|string[]|null * @var string|string[]|null
*/ */
public string|array|null $frameAncestors; public string | array | null $frameAncestors;
/** /**
* Restricts the origins allowed to deliver video and audio. * Restricts the origins allowed to deliver video and audio.
* *
* @var string|string[]|null * @var string|string[]|null
*/ */
public string|array|null $mediaSrc; public string | array | null $mediaSrc;
/** /**
* Allows control over Flash and other plugins. * Allows control over Flash and other plugins.
* *
* @var string|string[] * @var string|string[]
*/ */
public string|array $objectSrc = 'self'; public string | array $objectSrc = 'self';
/** /**
* @var string|string[]|null * @var string|string[]|null
*/ */
public string|array|null $manifestSrc; public string | array | null $manifestSrc;
/** /**
* Limits the kinds of plugins a page may invoke. * Limits the kinds of plugins a page may invoke.
* *
* @var string|string[]|null * @var string|string[]|null
*/ */
public string|array|null $pluginTypes; public string | array | null $pluginTypes;
/** /**
* List of actions allowed. * List of actions allowed.
* *
* @var string|string[]|null * @var string|string[]|null
*/ */
public string|array|null $sandbox; public string | array | null $sandbox;
} }

View File

@ -13,7 +13,6 @@ class Cookie extends BaseConfig
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* *
* Set a cookie name prefix if you need to avoid collisions. * Set a cookie name prefix if you need to avoid collisions.
*
*/ */
public string $prefix = ''; public string $prefix = '';
@ -25,9 +24,8 @@ class Cookie extends BaseConfig
* Default expires timestamp for cookies. Setting this to `0` will mean the * Default expires timestamp for cookies. Setting this to `0` will mean the
* cookie will not have the `Expires` attribute and will behave as a session * cookie will not have the `Expires` attribute and will behave as a session
* cookie. * cookie.
*
*/ */
public DateTimeInterface|int|string $expires = 0; public DateTimeInterface | int | string $expires = 0;
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
@ -35,7 +33,6 @@ class Cookie extends BaseConfig
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* *
* Typically will be a forward slash. * Typically will be a forward slash.
*
*/ */
public string $path = '/'; public string $path = '/';
@ -45,7 +42,6 @@ class Cookie extends BaseConfig
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* *
* Set to `.your-domain.com` for site-wide cookies. * Set to `.your-domain.com` for site-wide cookies.
*
*/ */
public string $domain = ''; public string $domain = '';
@ -55,7 +51,6 @@ class Cookie extends BaseConfig
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* *
* Cookie will only be set if a secure HTTPS connection exists. * Cookie will only be set if a secure HTTPS connection exists.
*
*/ */
public bool $secure = false; public bool $secure = false;
@ -65,7 +60,6 @@ class Cookie extends BaseConfig
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* *
* Cookie will only be accessible via HTTP(S) (no JavaScript). * Cookie will only be accessible via HTTP(S) (no JavaScript).
*
*/ */
public bool $httponly = true; public bool $httponly = true;
@ -88,7 +82,6 @@ class Cookie extends BaseConfig
* Defaults to `Lax` for compatibility with modern browsers. Setting `''` * Defaults to `Lax` for compatibility with modern browsers. Setting `''`
* (empty string) means default SameSite attribute set by browsers (`Lax`) * (empty string) means default SameSite attribute set by browsers (`Lax`)
* will be set on cookies. If set to `None`, `$secure` must also be set. * will be set on cookies. If set to `None`, `$secure` must also be set.
*
*/ */
public string $samesite = 'Lax'; public string $samesite = 'Lax';

View File

@ -10,14 +10,12 @@ use CodeIgniter\Database\Config;
class Database extends Config class Database extends Config
{ {
/** /**
* The directory that holds the Migrations * The directory that holds the Migrations and Seeds directories.
* and Seeds directories.
*/ */
public string $filesPath = APPPATH . 'Database' . DIRECTORY_SEPARATOR; public string $filesPath = APPPATH . 'Database' . DIRECTORY_SEPARATOR;
/** /**
* Lets you choose which connection group to * Lets you choose which connection group to use if no other is specified.
* use if no other is specified.
*/ */
public string $defaultGroup = 'default'; public string $defaultGroup = 'default';
@ -47,8 +45,7 @@ class Database extends Config
]; ];
/** /**
* This database connection is used when * This database connection is used when running PHPUnit database tests.
* running PHPUnit database tests.
* *
* @noRector StringClassNameToClassConstantRector * @noRector StringClassNameToClassConstantRector
* *
@ -61,7 +58,7 @@ class Database extends Config
'password' => '', 'password' => '',
'database' => ':memory:', 'database' => ':memory:',
'DBDriver' => 'SQLite3', 'DBDriver' => 'SQLite3',
'DBPrefix' => 'db_', // Needed to ensure we're working correctly with prefixes live. DO NOT REMOVE FOR CI DEVS 'DBPrefix' => 'db_',
'pConnect' => false, 'pConnect' => false,
'DBDebug' => ENVIRONMENT !== 'production', 'DBDebug' => ENVIRONMENT !== 'production',
'charset' => 'utf8', 'charset' => 'utf8',

View File

@ -14,127 +14,106 @@ class Email extends BaseConfig
/** /**
* The "user agent" * The "user agent"
*
*/ */
public string $userAgent = 'CodeIgniter'; public string $userAgent = 'CodeIgniter';
/** /**
* The mail sending protocol: mail, sendmail, smtp * The mail sending protocol: mail, sendmail, smtp
*
*/ */
public string $protocol = 'mail'; public string $protocol = 'mail';
/** /**
* The server path to Sendmail. * The server path to Sendmail.
*
*/ */
public string $mailPath = '/usr/sbin/sendmail'; public string $mailPath = '/usr/sbin/sendmail';
/** /**
* SMTP Server Address * SMTP Server Address
*
*/ */
public string $SMTPHost; public string $SMTPHost;
/** /**
* SMTP Username * SMTP Username
*
*/ */
public string $SMTPUser; public string $SMTPUser;
/** /**
* SMTP Password * SMTP Password
*
*/ */
public string $SMTPPass; public string $SMTPPass;
/** /**
* SMTP Port * SMTP Port
*
*/ */
public int $SMTPPort = 25; public int $SMTPPort = 25;
/** /**
* SMTP Timeout (in seconds) * SMTP Timeout (in seconds)
*
*/ */
public int $SMTPTimeout = 5; public int $SMTPTimeout = 5;
/** /**
* Enable persistent SMTP connections * Enable persistent SMTP connections
*
*/ */
public bool $SMTPKeepAlive = false; public bool $SMTPKeepAlive = false;
/** /**
* SMTP Encryption. Either tls or ssl * SMTP Encryption. Either tls or ssl
*
*/ */
public string $SMTPCrypto = 'tls'; public string $SMTPCrypto = 'tls';
/** /**
* Enable word-wrap * Enable word-wrap
*
*/ */
public bool $wordWrap = true; public bool $wordWrap = true;
/** /**
* Character count to wrap at * Character count to wrap at
*
*/ */
public int $wrapChars = 76; public int $wrapChars = 76;
/** /**
* Type of mail, either 'text' or 'html' * Type of mail, either 'text' or 'html'
*
*/ */
public string $mailType = 'text'; public string $mailType = 'text';
/** /**
* Character set (utf-8, iso-8859-1, etc.) * Character set (utf-8, iso-8859-1, etc.)
*
*/ */
public string $charset = 'UTF-8'; public string $charset = 'UTF-8';
/** /**
* Whether to validate the email address * Whether to validate the email address
*
*/ */
public bool $validate = false; public bool $validate = false;
/** /**
* Email Priority. 1 = highest. 5 = lowest. 3 = normal * Email Priority. 1 = highest. 5 = lowest. 3 = normal
*
*/ */
public int $priority = 3; public int $priority = 3;
/** /**
* Newline character. (Use “\r\n” to comply with RFC 822) * Newline character. (Use “\r\n” to comply with RFC 822)
*
*/ */
public string $CRLF = "\r\n"; public string $CRLF = "\r\n";
/** /**
* Newline character. (Use “\r\n” to comply with RFC 822) * Newline character. (Use “\r\n” to comply with RFC 822)
*
*/ */
public string $newline = "\r\n"; public string $newline = "\r\n";
/** /**
* Enable BCC Batch Mode. * Enable BCC Batch Mode.
*
*/ */
public bool $BCCBatchMode = false; public bool $BCCBatchMode = false;
/** /**
* Number of emails in each BCC batch * Number of emails in each BCC batch
*
*/ */
public int $BCCBatchSize = 200; public int $BCCBatchSize = 200;
/** /**
* Enable notify message from server * Enable notify message from server
*
*/ */
public bool $DSN = false; public bool $DSN = false;
} }

View File

@ -7,8 +7,8 @@ use CodeIgniter\Config\BaseConfig;
/** /**
* Encryption configuration. * Encryption configuration.
* *
* These are the settings used for encryption, if you don't pass a parameter * These are the settings used for encryption, if you don't pass a parameter array to the encrypter for
* array to the encrypter for creation/initialization. * creation/initialization.
*/ */
class Encryption extends BaseConfig class Encryption extends BaseConfig
{ {
@ -20,7 +20,6 @@ class Encryption extends BaseConfig
* If you use the Encryption class you must set an encryption key (seed). * If you use the Encryption class you must set an encryption key (seed).
* You need to ensure it is long enough for the cipher and mode you plan to use. * You need to ensure it is long enough for the cipher and mode you plan to use.
* See the user guide for more info. * See the user guide for more info.
*
*/ */
public string $key = ''; public string $key = '';
@ -34,7 +33,6 @@ class Encryption extends BaseConfig
* Available drivers: * Available drivers:
* - OpenSSL * - OpenSSL
* - Sodium * - Sodium
*
*/ */
public string $driver = 'OpenSSL'; public string $driver = 'OpenSSL';
@ -47,7 +45,6 @@ class Encryption extends BaseConfig
* before it is encrypted. This value should be greater than zero. * before it is encrypted. This value should be greater than zero.
* *
* See the user guide for more information on padding. * See the user guide for more information on padding.
*
*/ */
public int $blockSize = 16; public int $blockSize = 16;
@ -57,7 +54,6 @@ class Encryption extends BaseConfig
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* *
* HMAC digest to use, e.g. 'SHA512' or 'SHA256'. Default value is 'SHA512'. * HMAC digest to use, e.g. 'SHA512' or 'SHA256'. Default value is 'SHA512'.
*
*/ */
public string $digest = 'SHA512'; public string $digest = 'SHA512';
} }

View File

@ -50,10 +50,7 @@ Events::on('pre_system', function () {
* @phpstan-ignore-next-line * @phpstan-ignore-next-line
*/ */
if (CI_DEBUG) { if (CI_DEBUG) {
Events::on( Events::on('DBQuery', 'CodeIgniter\Debug\Toolbar\Collectors\Database::collect',);
'DBQuery',
'CodeIgniter\Debug\Toolbar\Collectors\Database::collect',
);
Services::toolbar()->respond(); Services::toolbar()->respond();
} }
}); });
@ -90,7 +87,8 @@ Events::on('on_note_add', function (Note $note): void {
// Removing all of the podcast pages is a bit overkill, but works perfectly // Removing all of the podcast pages is a bit overkill, but works perfectly
// same for other events below // same for other events below
cache()->deleteMatching("page_podcast#{$note->actor->podcast->id}*"); cache()
->deleteMatching("page_podcast#{$note->actor->podcast->id}*");
}); });
Events::on('on_note_remove', function (Note $note): void { Events::on('on_note_remove', function (Note $note): void {
@ -108,8 +106,10 @@ Events::on('on_note_remove', function (Note $note): void {
->decrement('favourites_total', $note->favourites_count); ->decrement('favourites_total', $note->favourites_count);
} }
cache()->deleteMatching("page_podcast#{$note->actor->podcast->id}*"); cache()
cache()->deleteMatching("page_note#{$note->id}*"); ->deleteMatching("page_podcast#{$note->actor->podcast->id}*");
cache()
->deleteMatching("page_note#{$note->id}*");
}); });
Events::on('on_note_reblog', function (Actor $actor, Note $note): void { Events::on('on_note_reblog', function (Actor $actor, Note $note): void {
@ -123,8 +123,10 @@ Events::on('on_note_reblog', function (Actor $actor, Note $note): void {
->increment('notes_total'); ->increment('notes_total');
} }
cache()->deleteMatching("page_podcast#{$note->actor->podcast->id}*"); cache()
cache()->deleteMatching("page_note#{$note->id}*"); ->deleteMatching("page_podcast#{$note->actor->podcast->id}*");
cache()
->deleteMatching("page_note#{$note->id}*");
if ($actor->is_podcast) { if ($actor->is_podcast) {
cache()->deleteMatching("page_podcast#{$actor->podcast->id}*"); cache()->deleteMatching("page_podcast#{$actor->podcast->id}*");
@ -143,28 +145,32 @@ Events::on('on_note_undo_reblog', function (Note $reblogNote): void {
->decrement('notes_total'); ->decrement('notes_total');
} }
cache()->deleteMatching("page_podcast#{$note->actor->podcast->id}*"); cache()
cache()->deleteMatching("page_note#{$note->id}*"); ->deleteMatching("page_podcast#{$note->actor->podcast->id}*");
cache()
->deleteMatching("page_note#{$note->id}*");
if ($reblogNote->actor->is_podcast) { if ($reblogNote->actor->is_podcast) {
cache()->deleteMatching( cache()->deleteMatching("page_podcast#{$reblogNote->actor->podcast->id}*",);
"page_podcast#{$reblogNote->actor->podcast->id}*",
);
} }
}); });
Events::on('on_note_reply', function (Note $reply): void { Events::on('on_note_reply', function (Note $reply): void {
$note = $reply->reply_to_note; $note = $reply->reply_to_note;
cache()->deleteMatching("page_podcast#{$note->actor->podcast->id}*"); cache()
cache()->deleteMatching("page_note#{$note->id}*"); ->deleteMatching("page_podcast#{$note->actor->podcast->id}*");
cache()
->deleteMatching("page_note#{$note->id}*");
}); });
Events::on('on_reply_remove', function (Note $reply): void { Events::on('on_reply_remove', function (Note $reply): void {
$note = $reply->reply_to_note; $note = $reply->reply_to_note;
cache()->deleteMatching("page_podcast#{$note->actor->podcast->id}*"); cache()
cache()->deleteMatching("page_note#{$note->id}*"); ->deleteMatching("page_podcast#{$note->actor->podcast->id}*");
cache()
->deleteMatching("page_note#{$note->id}*");
}); });
Events::on('on_note_favourite', function (Actor $actor, Note $note): void { Events::on('on_note_favourite', function (Actor $actor, Note $note): void {
@ -174,8 +180,10 @@ Events::on('on_note_favourite', function (Actor $actor, Note $note): void {
->increment('favourites_total'); ->increment('favourites_total');
} }
cache()->deleteMatching("page_podcast#{$actor->podcast->id}*"); cache()
cache()->deleteMatching("page_note#{$note->id}*"); ->deleteMatching("page_podcast#{$actor->podcast->id}*");
cache()
->deleteMatching("page_note#{$note->id}*");
if ($note->in_reply_to_id) { if ($note->in_reply_to_id) {
cache()->deleteMatching("page_note#{$note->in_reply_to_id}*"); cache()->deleteMatching("page_note#{$note->in_reply_to_id}*");
@ -189,8 +197,10 @@ Events::on('on_note_undo_favourite', function (Actor $actor, Note $note): void {
->decrement('favourites_total'); ->decrement('favourites_total');
} }
cache()->deleteMatching("page_podcast#{$actor->podcast->id}*"); cache()
cache()->deleteMatching("page_note#{$note->id}*"); ->deleteMatching("page_podcast#{$actor->podcast->id}*");
cache()
->deleteMatching("page_note#{$note->id}*");
if ($note->in_reply_to_id) { if ($note->in_reply_to_id) {
cache()->deleteMatching("page_note#{$note->in_reply_to_id}*"); cache()->deleteMatching("page_note#{$note->in_reply_to_id}*");
@ -199,20 +209,24 @@ Events::on('on_note_undo_favourite', function (Actor $actor, Note $note): void {
Events::on('on_block_actor', function (int $actorId): void { Events::on('on_block_actor', function (int $actorId): void {
cache()->deleteMatching('page_podcast*'); cache()->deleteMatching('page_podcast*');
cache()->deleteMatching('page_note*'); cache()
->deleteMatching('page_note*');
}); });
Events::on('on_unblock_actor', function (int $actorId): void { Events::on('on_unblock_actor', function (int $actorId): void {
cache()->deleteMatching('page_podcast*'); cache()->deleteMatching('page_podcast*');
cache()->deleteMatching('page_note*'); cache()
->deleteMatching('page_note*');
}); });
Events::on('on_block_domain', function (string $domainName): void { Events::on('on_block_domain', function (string $domainName): void {
cache()->deleteMatching('page_podcast*'); cache()->deleteMatching('page_podcast*');
cache()->deleteMatching('page_note*'); cache()
->deleteMatching('page_note*');
}); });
Events::on('on_unblock_domain', function (string $domainName): void { Events::on('on_unblock_domain', function (string $domainName): void {
cache()->deleteMatching('page_podcast*'); cache()->deleteMatching('page_podcast*');
cache()->deleteMatching('page_note*'); cache()
->deleteMatching('page_note*');
}); });

View File

@ -17,7 +17,6 @@ class Exceptions extends BaseConfig
* through Services::Log. * through Services::Log.
* *
* Default: true * Default: true
*
*/ */
public bool $log = true; public bool $log = true;
@ -40,7 +39,6 @@ class Exceptions extends BaseConfig
* directories that hold the views used to generate errors. * directories that hold the views used to generate errors.
* *
* Default: APPPATH.'Views/errors' * Default: APPPATH.'Views/errors'
*
*/ */
public string $errorViewPath = APPPATH . 'Views/errors'; public string $errorViewPath = APPPATH . 'Views/errors';
} }

View File

@ -2,20 +2,19 @@
namespace Config; namespace Config;
use Myth\Auth\Filters\LoginFilter;
use Myth\Auth\Filters\RoleFilter;
use App\Filters\PermissionFilter;
use ActivityPub\Filters\ActivityPubFilter; use ActivityPub\Filters\ActivityPubFilter;
use App\Filters\PermissionFilter;
use CodeIgniter\Config\BaseConfig; use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Filters\CSRF; use CodeIgniter\Filters\CSRF;
use CodeIgniter\Filters\DebugToolbar; use CodeIgniter\Filters\DebugToolbar;
use CodeIgniter\Filters\Honeypot; use CodeIgniter\Filters\Honeypot;
use Myth\Auth\Filters\LoginFilter;
use Myth\Auth\Filters\RoleFilter;
class Filters extends BaseConfig class Filters extends BaseConfig
{ {
/** /**
* Configures aliases for Filter classes to * Configures aliases for Filter classes to make reading things nicer and simpler.
* make reading things nicer and simpler.
* *
* @var array<string, string> * @var array<string, string>
*/ */
@ -30,8 +29,7 @@ class Filters extends BaseConfig
]; ];
/** /**
* List of filter aliases that are always * List of filter aliases that are always applied before and after every request.
* applied before and after every request.
* *
* @var array<string, string[]> * @var array<string, string[]>
*/ */
@ -47,22 +45,18 @@ class Filters extends BaseConfig
]; ];
/** /**
* List of filter aliases that works on a * List of filter aliases that works on a particular HTTP method (GET, POST, etc.).
* particular HTTP method (GET, POST, etc.).
* *
* Example: * Example: 'post' => ['csrf', 'throttle']
* 'post' => ['csrf', 'throttle']
* *
* @var array<string, string[]> * @var array<string, string[]>
*/ */
public array $methods = []; public array $methods = [];
/** /**
* List of filter aliases that should run on any * List of filter aliases that should run on any before or after URI patterns.
* before or after URI patterns.
* *
* Example: * Example: 'isLoggedIn' => ['before' => ['account/*', 'profiles/*']]
* 'isLoggedIn' => ['before' => ['account/*', 'profiles/*']]
* *
* @var array<string, array<string, string[]>> * @var array<string, array<string, string[]>>
*/ */
@ -73,7 +67,9 @@ class Filters extends BaseConfig
parent::__construct(); parent::__construct();
$this->filters = [ $this->filters = [
'login' => ['before' => [config('App')->adminGateway . '*']], 'login' => [
'before' => [config('App')->adminGateway . '*'],
],
]; ];
} }
} }

View File

@ -2,10 +2,10 @@
namespace Config; namespace Config;
use CodeIgniter\Format\JSONFormatter;
use CodeIgniter\Format\XMLFormatter;
use CodeIgniter\Config\BaseConfig; use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Format\FormatterInterface; use CodeIgniter\Format\FormatterInterface;
use CodeIgniter\Format\JSONFormatter;
use CodeIgniter\Format\XMLFormatter;
class Format extends BaseConfig class Format extends BaseConfig
{ {
@ -64,6 +64,7 @@ class Format extends BaseConfig
]; ];
//-------------------------------------------------------------------- //--------------------------------------------------------------------
/** /**
* A Factory method to return the appropriate formatter for the given mime type. * A Factory method to return the appropriate formatter for the given mime type.
* *

View File

@ -8,31 +8,26 @@ class Honeypot extends BaseConfig
{ {
/** /**
* Makes Honeypot visible or not to human * Makes Honeypot visible or not to human
*
*/ */
public bool $hidden = true; public bool $hidden = true;
/** /**
* Honeypot Label Content * Honeypot Label Content
*
*/ */
public string $label = 'Fill This Field'; public string $label = 'Fill This Field';
/** /**
* Honeypot Field Name * Honeypot Field Name
*
*/ */
public string $name = 'honeypot'; public string $name = 'honeypot';
/** /**
* Honeypot HTML Template * Honeypot HTML Template
*
*/ */
public string $template = '<label>{label}</label><input type="text" name="{name}" value=""/>'; public string $template = '<label>{label}</label><input type="text" name="{name}" value=""/>';
/** /**
* Honeypot container * Honeypot container
*
*/ */
public string $container = '<div style="display:none">{template}</div>'; public string $container = '<div style="display:none">{template}</div>';
} }

View File

@ -10,14 +10,11 @@ class Images extends BaseConfig
{ {
/** /**
* Default handler used if no other handler is specified. * Default handler used if no other handler is specified.
*
*/ */
public string $defaultHandler = 'gd'; public string $defaultHandler = 'gd';
/** /**
* The path to the image library. * The path to the image library. Required for ImageMagick, GraphicsMagick, or NetPBM.
* Required for ImageMagick, GraphicsMagick, or NetPBM.
*
*/ */
public string $libraryPath = '/usr/local/bin/convert'; public string $libraryPath = '/usr/local/bin/convert';
@ -32,15 +29,17 @@ class Images extends BaseConfig
]; ];
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Uploaded images resizing sizes (in px) | Uploaded images resizing sizes (in px)
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| The sizes listed below determine the resizing of images when uploaded. | The sizes listed below determine the resizing of images when uploaded.
| All uploaded images are of 1:1 ratio (width and height are the same). | All uploaded images are of 1:1 ratio (width and height are the same).
*/ */
public int $thumbnailSize = 150; public int $thumbnailSize = 150;
public int $mediumSize = 320; public int $mediumSize = 320;
public int $largeSize = 1024; public int $largeSize = 1024;
/** /**
@ -54,11 +53,11 @@ class Images extends BaseConfig
public int $id3Size = 500; public int $id3Size = 500;
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Uploaded images naming extensions | Uploaded images naming extensions
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| The properties listed below set the name extensions for the resized images | The properties listed below set the name extensions for the resized images
*/ */
public string $thumbnailSuffix = '_thumbnail'; public string $thumbnailSuffix = '_thumbnail';

View File

@ -18,10 +18,10 @@ use Kint\Renderer\Renderer;
class Kint extends BaseConfig class Kint extends BaseConfig
{ {
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Global Settings | Global Settings
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
*/ */
/** /**
* @var string[] * @var string[]

View File

@ -2,8 +2,8 @@
namespace Config; namespace Config;
use CodeIgniter\Log\Handlers\FileHandler;
use CodeIgniter\Config\BaseConfig; use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Log\Handlers\FileHandler;
class Logger extends BaseConfig class Logger extends BaseConfig
{ {
@ -38,7 +38,7 @@ class Logger extends BaseConfig
* *
* @var int|int[] * @var int|int[]
*/ */
public int|array $threshold = 4; public int | array $threshold = 4;
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
@ -47,8 +47,6 @@ class Logger extends BaseConfig
* *
* Each item that is logged has an associated date. You can use PHP date * Each item that is logged has an associated date. You can use PHP date
* codes to set your own date formatting * codes to set your own date formatting
*
* @var string
*/ */
public string $dateFormat = 'Y-m-d H:i:s'; public string $dateFormat = 'Y-m-d H:i:s';
@ -87,16 +85,7 @@ class Logger extends BaseConfig
/* /*
* The log levels that this handler will handle. * The log levels that this handler will handle.
*/ */
'handles' => [ 'handles' => ['critical', 'alert', 'emergency', 'debug', 'error', 'info', 'notice', 'warning'],
'critical',
'alert',
'emergency',
'debug',
'error',
'info',
'notice',
'warning',
],
/* /*
* The default filename extension for log files. * The default filename extension for log files.

View File

@ -15,7 +15,6 @@ class Migrations extends BaseConfig
* *
* You should enable migrations whenever you intend to do a schema migration * You should enable migrations whenever you intend to do a schema migration
* and disable it back when you're done. * and disable it back when you're done.
*
*/ */
public bool $enabled = true; public bool $enabled = true;
@ -29,7 +28,6 @@ class Migrations extends BaseConfig
* level the system is at. It then compares the migration level in this * level the system is at. It then compares the migration level in this
* table to the $config['migration_version'] if they are not the same it * table to the $config['migration_version'] if they are not the same it
* will migrate up. This must be set. * will migrate up. This must be set.
*
*/ */
public string $table = 'migrations'; public string $table = 'migrations';
@ -46,7 +44,6 @@ class Migrations extends BaseConfig
* - YmdHis_ * - YmdHis_
* - Y-m-d-His_ * - Y-m-d-His_
* - Y_m_d_His_ * - Y_m_d_His_
*
*/ */
public string $timestampFormat = 'Y-m-d-His_'; public string $timestampFormat = 'Y-m-d-His_';
} }

View File

@ -5,16 +5,13 @@ namespace Config;
/** /**
* Mimes * Mimes
* *
* This file contains an array of mime types. It is used by the * This file contains an array of mime types. It is used by the Upload class to help identify allowed file types.
* Upload class to help identify allowed file types.
* *
* When more than one variation for an extension exist (like jpg, jpeg, etc) * When more than one variation for an extension exist (like jpg, jpeg, etc) the most common one should be first in the
* the most common one should be first in the array to aid the guess* * array to aid the guess* methods. The same applies when more than one mime-type exists for a single extension.
* methods. The same applies when more than one mime-type exists for a
* single extension.
* *
* When working with mime types, please make sure you have the ´fileinfo´ * When working with mime types, please make sure you have the ´fileinfo´ extension enabled to reliably detect the
* extension enabled to reliably detect the media types. * media types.
*/ */
class Mimes class Mimes
@ -61,11 +58,7 @@ class Mimes
'sea' => 'application/octet-stream', 'sea' => 'application/octet-stream',
'dll' => 'application/octet-stream', 'dll' => 'application/octet-stream',
'oda' => 'application/oda', 'oda' => 'application/oda',
'pdf' => [ 'pdf' => ['application/pdf', 'application/force-download', 'application/x-download'],
'application/pdf',
'application/force-download',
'application/x-download',
],
'ai' => ['application/pdf', 'application/postscript'], 'ai' => ['application/pdf', 'application/postscript'],
'eps' => 'application/postscript', 'eps' => 'application/postscript',
'ps' => 'application/postscript', 'ps' => 'application/postscript',
@ -133,12 +126,7 @@ class Mimes
'application/s-compressed', 'application/s-compressed',
'multipart/x-zip', 'multipart/x-zip',
], ],
'rar' => [ 'rar' => ['application/vnd.rar', 'application/x-rar', 'application/rar', 'application/x-rar-compressed'],
'application/vnd.rar',
'application/x-rar',
'application/rar',
'application/x-rar-compressed',
],
'mid' => 'audio/midi', 'mid' => 'audio/midi',
'midi' => 'audio/midi', 'midi' => 'audio/midi',
'mpga' => 'audio/mpeg', 'mpga' => 'audio/mpeg',
@ -197,12 +185,7 @@ class Mimes
'mpe' => 'video/mpeg', 'mpe' => 'video/mpeg',
'qt' => 'video/quicktime', 'qt' => 'video/quicktime',
'mov' => 'video/quicktime', 'mov' => 'video/quicktime',
'avi' => [ 'avi' => ['video/x-msvideo', 'video/msvideo', 'video/avi', 'application/x-troff-msvideo'],
'video/x-msvideo',
'video/msvideo',
'video/avi',
'application/x-troff-msvideo',
],
'movie' => 'video/x-sgi-movie', 'movie' => 'video/x-sgi-movie',
'doc' => ['application/msword', 'application/vnd.ms-office'], 'doc' => ['application/msword', 'application/vnd.ms-office'],
'docx' => [ 'docx' => [
@ -228,11 +211,7 @@ class Mimes
'xl' => 'application/excel', 'xl' => 'application/excel',
'eml' => 'message/rfc822', 'eml' => 'message/rfc822',
'json' => ['application/json', 'text/json'], 'json' => ['application/json', 'text/json'],
'pem' => [ 'pem' => ['application/x-x509-user-cert', 'application/x-pem-file', 'application/octet-stream'],
'application/x-x509-user-cert',
'application/x-pem-file',
'application/octet-stream',
],
'p10' => ['application/x-pkcs10', 'application/pkcs10'], 'p10' => ['application/x-pkcs10', 'application/pkcs10'],
'p12' => 'application/x-pkcs12', 'p12' => 'application/x-pkcs12',
'p7a' => 'application/x-pkcs7-signature', 'p7a' => 'application/x-pkcs7-signature',
@ -240,11 +219,7 @@ class Mimes
'p7m' => ['application/pkcs7-mime', 'application/x-pkcs7-mime'], 'p7m' => ['application/pkcs7-mime', 'application/x-pkcs7-mime'],
'p7r' => 'application/x-pkcs7-certreqresp', 'p7r' => 'application/x-pkcs7-certreqresp',
'p7s' => 'application/pkcs7-signature', 'p7s' => 'application/pkcs7-signature',
'crt' => [ 'crt' => ['application/x-x509-ca-cert', 'application/x-x509-user-cert', 'application/pkix-cert'],
'application/x-x509-ca-cert',
'application/x-x509-user-cert',
'application/pkix-cert',
],
'crl' => ['application/pkix-crl', 'application/pkcs-crl'], 'crl' => ['application/pkix-crl', 'application/pkcs-crl'],
'der' => 'application/x-x509-ca-cert', 'der' => 'application/x-x509-ca-cert',
'kdb' => 'application/octet-stream', 'kdb' => 'application/octet-stream',
@ -271,16 +246,8 @@ class Mimes
'ac3' => 'audio/ac3', 'ac3' => 'audio/ac3',
'flac' => 'audio/x-flac', 'flac' => 'audio/x-flac',
'ogg' => ['audio/ogg', 'video/ogg', 'application/ogg'], 'ogg' => ['audio/ogg', 'video/ogg', 'application/ogg'],
'kmz' => [ 'kmz' => ['application/vnd.google-earth.kmz', 'application/zip', 'application/x-zip'],
'application/vnd.google-earth.kmz', 'kml' => ['application/vnd.google-earth.kml+xml', 'application/xml', 'text/xml'],
'application/zip',
'application/x-zip',
],
'kml' => [
'application/vnd.google-earth.kml+xml',
'application/xml',
'text/xml',
],
'ics' => 'text/calendar', 'ics' => 'text/calendar',
'ical' => 'text/calendar', 'ical' => 'text/calendar',
'zsh' => 'text/x-scriptzsh', 'zsh' => 'text/x-scriptzsh',
@ -311,11 +278,7 @@ class Mimes
'srt' => ['text/srt', 'text/plain', 'application/octet-stream'], 'srt' => ['text/srt', 'text/plain', 'application/octet-stream'],
'vtt' => ['text/vtt', 'text/plain'], 'vtt' => ['text/vtt', 'text/plain'],
'ico' => ['image/x-icon', 'image/x-ico', 'image/vnd.microsoft.icon'], 'ico' => ['image/x-icon', 'image/x-ico', 'image/vnd.microsoft.icon'],
'stl' => [ 'stl' => ['application/sla', 'application/vnd.ms-pki.stl', 'application/x-navistyle'],
'application/sla',
'application/vnd.ms-pki.stl',
'application/x-navistyle',
],
]; ];
/** /**
@ -327,7 +290,7 @@ class Mimes
{ {
$extension = trim(strtolower($extension), '. '); $extension = trim(strtolower($extension), '. ');
if (!array_key_exists($extension, static::$mimes)) { if (! array_key_exists($extension, static::$mimes)) {
return null; return null;
} }
@ -342,10 +305,8 @@ class Mimes
* @param string|null $proposedExtension - default extension (in case there is more than one with the same mime type) * @param string|null $proposedExtension - default extension (in case there is more than one with the same mime type)
* @return string|null The extension determined, or null if unable to match. * @return string|null The extension determined, or null if unable to match.
*/ */
public static function guessExtensionFromType( public static function guessExtensionFromType(string $type, string $proposedExtension = null): ?string
string $type, {
string $proposedExtension = null
): ?string {
$type = trim(strtolower($type), '. '); $type = trim(strtolower($type), '. ');
$proposedExtension = trim(strtolower($proposedExtension)); $proposedExtension = trim(strtolower($proposedExtension));

View File

@ -32,7 +32,6 @@ class Pager extends BaseConfig
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* *
* The default number of results shown in a single page. * The default number of results shown in a single page.
*
*/ */
public int $perPage = 20; public int $perPage = 20;
} }

View File

@ -5,11 +5,10 @@ namespace Config;
/** /**
* Paths * Paths
* *
* Holds the paths that are used by the system to * Holds the paths that are used by the system to locate the main directories, app, system, etc.
* locate the main directories, app, system, etc.
* *
* Modifying these allows you to restructure your application, * Modifying these allows you to restructure your application, share a system folder between multiple applications, and
* share a system folder between multiple applications, and more. * more.
* *
* All paths are relative to the project's root folder. * All paths are relative to the project's root folder.
*/ */
@ -23,10 +22,10 @@ class Paths
* *
* This must contain the name of your "system" folder. Include * This must contain the name of your "system" folder. Include
* the path if the folder is not in the same directory as this file. * the path if the folder is not in the same directory as this file.
*
*/ */
public string $systemDirectory = public string $systemDirectory =
__DIR__ . '/../../vendor/codeigniter4/codeigniter4/system'; __DIR__ . '/../../vendor/codeigniter4/codeigniter4/system';
/** /**
* --------------------------------------------------------------- * ---------------------------------------------------------------
* APPLICATION FOLDER NAME * APPLICATION FOLDER NAME
@ -38,7 +37,6 @@ class Paths
* you do, use a full getServer path. * you do, use a full getServer path.
* *
* @see http://codeigniter.com/user_guide/general/managing_apps.html * @see http://codeigniter.com/user_guide/general/managing_apps.html
*
*/ */
public string $appDirectory = __DIR__ . '/..'; public string $appDirectory = __DIR__ . '/..';
@ -52,7 +50,6 @@ class Paths
* need write permission to a single place that can be tucked away * need write permission to a single place that can be tucked away
* for maximum security, keeping it out of the app and/or * for maximum security, keeping it out of the app and/or
* system directories. * system directories.
*
*/ */
public string $writableDirectory = __DIR__ . '/../../writable'; public string $writableDirectory = __DIR__ . '/../../writable';
@ -62,7 +59,6 @@ class Paths
* --------------------------------------------------------------- * ---------------------------------------------------------------
* *
* This variable must contain the name of your "tests" directory. * This variable must contain the name of your "tests" directory.
*
*/ */
public string $testsDirectory = __DIR__ . '/../../tests'; public string $testsDirectory = __DIR__ . '/../../tests';
@ -75,7 +71,6 @@ class Paths
* contains the view files used by your application. By * contains the view files used by your application. By
* default this is in `app/Views`. This value * default this is in `app/Views`. This value
* is used when no value is provided to `Services::renderer()`. * is used when no value is provided to `Services::renderer()`.
*
*/ */
public string $viewDirectory = __DIR__ . '/../Views'; public string $viewDirectory = __DIR__ . '/../Views';
} }

View File

@ -34,10 +34,7 @@ $routes->addPlaceholder('slug', '[a-zA-Z0-9\-]{1,191}');
$routes->addPlaceholder('base64', '[A-Za-z0-9\.\_]+\-{0,2}'); $routes->addPlaceholder('base64', '[A-Za-z0-9\.\_]+\-{0,2}');
$routes->addPlaceholder('platformType', '\bpodcasting|\bsocial|\bfunding'); $routes->addPlaceholder('platformType', '\bpodcasting|\bsocial|\bfunding');
$routes->addPlaceholder('noteAction', '\bfavourite|\breblog|\breply'); $routes->addPlaceholder('noteAction', '\bfavourite|\breblog|\breply');
$routes->addPlaceholder( $routes->addPlaceholder('embeddablePlayerTheme', '\blight|\bdark|\blight-transparent|\bdark-transparent',);
'embeddablePlayerTheme',
'\blight|\bdark|\blight-transparent|\bdark-transparent',
);
$routes->addPlaceholder( $routes->addPlaceholder(
'uuid', 'uuid',
'[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}', '[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}',
@ -51,25 +48,21 @@ $routes->addPlaceholder(
// We get a performance increase by specifying the default // We get a performance increase by specifying the default
// route since we don't have to scan directories. // route since we don't have to scan directories.
$routes->get('/', 'HomeController::index', ['as' => 'home']); $routes->get('/', 'HomeController::index', [
'as' => 'home',
]);
// Install Wizard route // Install Wizard route
$routes->group(config('App')->installGateway, function ($routes): void { $routes->group(config('App')->installGateway, function ($routes): void {
$routes->get('/', 'InstallController', ['as' => 'install']); $routes->get('/', 'InstallController', [
$routes->post( 'as' => 'install',
'instance-config', ]);
'InstallController::attemptInstanceConfig', $routes->post('instance-config', 'InstallController::attemptInstanceConfig', [
[ 'as' => 'instance-config',
'as' => 'instance-config', ],);
], $routes->post('database-config', 'InstallController::attemptDatabaseConfig', [
); 'as' => 'database-config',
$routes->post( ],);
'database-config',
'InstallController::attemptDatabaseConfig',
[
'as' => 'database-config',
],
);
$routes->post('cache-config', 'InstallController::attemptCacheConfig', [ $routes->post('cache-config', 'InstallController::attemptCacheConfig', [
'as' => 'cache-config', 'as' => 'cache-config',
]); ]);
@ -86,8 +79,11 @@ $routes->get('.well-known/platforms', 'Platform');
// Admin area // Admin area
$routes->group( $routes->group(
config('App')->adminGateway, config('App')
['namespace' => 'App\Controllers\Admin'], ->adminGateway,
[
'namespace' => 'App\Controllers\Admin',
],
function ($routes): void { function ($routes): void {
$routes->get('/', 'HomeController', [ $routes->get('/', 'HomeController', [
'as' => 'admin', 'as' => 'admin',
@ -538,7 +534,9 @@ $routes->group(
// Pages // Pages
$routes->group('pages', function ($routes): void { $routes->group('pages', function ($routes): void {
$routes->get('/', 'PageController::list', ['as' => 'page-list']); $routes->get('/', 'PageController::list', [
'as' => 'page-list',
]);
$routes->get('new', 'PageController::create', [ $routes->get('new', 'PageController::create', [
'as' => 'page-create', 'as' => 'page-create',
'filter' => 'permission:pages-manage', 'filter' => 'permission:pages-manage',
@ -628,10 +626,7 @@ $routes->group(
'as' => 'change-password', 'as' => 'change-password',
], ],
); );
$routes->post( $routes->post('change-password', 'MyAccountController::attemptChange/$1',);
'change-password',
'MyAccountController::attemptChange/$1',
);
}); });
}, },
); );
@ -641,7 +636,9 @@ $routes->group(
*/ */
$routes->group(config('App')->authGateway, function ($routes): void { $routes->group(config('App')->authGateway, function ($routes): void {
// Login/out // Login/out
$routes->get('login', 'AuthController::login', ['as' => 'login']); $routes->get('login', 'AuthController::login', [
'as' => 'login',
]);
$routes->post('login', 'AuthController::attemptLogin'); $routes->post('login', 'AuthController::attemptLogin');
$routes->get('logout', 'AuthController::logout', [ $routes->get('logout', 'AuthController::logout', [
'as' => 'logout', 'as' => 'logout',
@ -722,13 +719,21 @@ $routes->group('@(:podcastName)', function ($routes): void {
}); });
}); });
$routes->head('feed.xml', 'FeedController/$1', ['as' => 'podcast_feed']); $routes->head('feed.xml', 'FeedController/$1', [
$routes->get('feed.xml', 'FeedController/$1', ['as' => 'podcast_feed']); 'as' => 'podcast_feed',
]);
$routes->get('feed.xml', 'FeedController/$1', [
'as' => 'podcast_feed',
]);
}); });
// Other pages // Other pages
$routes->get('/credits', 'PageController::credits', ['as' => 'credits']); $routes->get('/credits', 'CreditsController', [
$routes->get('/pages/(:slug)', 'Page/$1', ['as' => 'page']); 'as' => 'credits',
]);
$routes->get('/pages/(:slug)', 'PageController/$1', [
'as' => 'page',
]);
// interacting as an actor // interacting as an actor
$routes->post('interact-as-actor', 'AuthController::attemptInteractAsActor', [ $routes->post('interact-as-actor', 'AuthController::attemptInteractAsActor', [

View File

@ -12,7 +12,6 @@ class Security extends BaseConfig
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* *
* Token name for Cross Site Request Forgery protection cookie. * Token name for Cross Site Request Forgery protection cookie.
*
*/ */
public string $tokenName = 'csrf_test_name'; public string $tokenName = 'csrf_test_name';
@ -22,7 +21,6 @@ class Security extends BaseConfig
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* *
* Token name for Cross Site Request Forgery protection cookie. * Token name for Cross Site Request Forgery protection cookie.
*
*/ */
public string $headerName = 'X-CSRF-TOKEN'; public string $headerName = 'X-CSRF-TOKEN';
@ -32,7 +30,6 @@ class Security extends BaseConfig
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* *
* Cookie name for Cross Site Request Forgery protection cookie. * Cookie name for Cross Site Request Forgery protection cookie.
*
*/ */
public string $cookieName = 'csrf_cookie_name'; public string $cookieName = 'csrf_cookie_name';
@ -44,7 +41,6 @@ class Security extends BaseConfig
* Expiration time for Cross Site Request Forgery protection cookie. * Expiration time for Cross Site Request Forgery protection cookie.
* *
* Defaults to two hours (in seconds). * Defaults to two hours (in seconds).
*
*/ */
public int $expires = 7200; public int $expires = 7200;
@ -54,7 +50,6 @@ class Security extends BaseConfig
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* *
* Regenerate CSRF Token on every request. * Regenerate CSRF Token on every request.
*
*/ */
public bool $regenerate = true; public bool $regenerate = true;
@ -64,7 +59,6 @@ class Security extends BaseConfig
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* *
* Redirect to previous page with error on failure. * Redirect to previous page with error on failure.
*
*/ */
public bool $redirect = true; public bool $redirect = true;

View File

@ -2,38 +2,35 @@
namespace Config; namespace Config;
use CodeIgniter\Config\BaseService;
use CodeIgniter\Model;
use App\Authorization\FlatAuthorization; use App\Authorization\FlatAuthorization;
use App\Authorization\PermissionModel;
use App\Authorization\GroupModel; use App\Authorization\GroupModel;
use App\Authorization\PermissionModel;
use App\Libraries\Breadcrumb; use App\Libraries\Breadcrumb;
use App\Libraries\Negotiate; use App\Libraries\Negotiate;
use App\Libraries\Router; use App\Libraries\Router;
use App\Models\UserModel; use App\Models\UserModel;
use CodeIgniter\Config\BaseService;
use CodeIgniter\HTTP\Request; use CodeIgniter\HTTP\Request;
use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\Model;
use CodeIgniter\Router\RouteCollectionInterface; use CodeIgniter\Router\RouteCollectionInterface;
use Myth\Auth\Models\LoginModel; use Myth\Auth\Models\LoginModel;
/** /**
* Services Configuration file. * Services Configuration file.
* *
* Services are simply other classes/libraries that the system uses * Services are simply other classes/libraries that the system uses to do its job. This is used by CodeIgniter to allow
* to do its job. This is used by CodeIgniter to allow the core of the * the core of the framework to be swapped out easily without affecting the usage within the rest of your application.
* framework to be swapped out easily without affecting the usage within
* the rest of your application.
* *
* This file holds any application-specific services, or service overrides * This file holds any application-specific services, or service overrides that you might need. An example has been
* that you might need. An example has been included with the general * included with the general method format you should use for your service methods. For more examples, see the core
* method format you should use for your service methods. For more examples, * Services file at system/Config/Services.php.
* see the core Services file at system/Config/Services.php.
*/ */
class Services extends BaseService class Services extends BaseService
{ {
/** /**
* The Router class uses a RouteCollection's array of routes, and determines * The Router class uses a RouteCollection's array of routes, and determines the correct Controller and Method to
* the correct Controller and Method to execute. * execute.
*/ */
public static function router( public static function router(
?RouteCollectionInterface $routes = null, ?RouteCollectionInterface $routes = null,
@ -51,14 +48,11 @@ class Services extends BaseService
} }
/** /**
* The Negotiate class provides the content negotiation features for * The Negotiate class provides the content negotiation features for working the request to determine correct
* working the request to determine correct language, encoding, charset, * language, encoding, charset, and more.
* and more.
*/ */
public static function negotiator( public static function negotiator(?RequestInterface $request = null, bool $getShared = true): Negotiate
?RequestInterface $request = null, {
bool $getShared = true
): Negotiate {
if ($getShared) { if ($getShared) {
return static::getSharedInstance('negotiator', $request); return static::getSharedInstance('negotiator', $request);
} }
@ -78,12 +72,7 @@ class Services extends BaseService
bool $getShared = true bool $getShared = true
) { ) {
if ($getShared) { if ($getShared) {
return self::getSharedInstance( return self::getSharedInstance('authentication', $lib, $userModel, $loginModel,);
'authentication',
$lib,
$userModel,
$loginModel,
);
} }
// config() checks first in app/Config // config() checks first in app/Config
@ -101,7 +90,8 @@ class Services extends BaseService
$loginModel = new LoginModel(); $loginModel = new LoginModel();
} }
return $instance->setUserModel($userModel)->setLoginModel($loginModel); return $instance->setUserModel($userModel)
->setLoginModel($loginModel);
} }
/** /**
@ -114,25 +104,20 @@ class Services extends BaseService
bool $getShared = true bool $getShared = true
) { ) {
if ($getShared) { if ($getShared) {
return self::getSharedInstance( return self::getSharedInstance('authorization', $groupModel, $permissionModel, $userModel,);
'authorization',
$groupModel,
$permissionModel,
$userModel,
);
} }
if (is_null($groupModel)) { if ($groupModel === null) {
$groupModel = new GroupModel(); $groupModel = new GroupModel();
} }
if (is_null($permissionModel)) { if ($permissionModel === null) {
$permissionModel = new PermissionModel(); $permissionModel = new PermissionModel();
} }
$instance = new FlatAuthorization($groupModel, $permissionModel); $instance = new FlatAuthorization($groupModel, $permissionModel);
if (is_null($userModel)) { if ($userModel === null) {
$userModel = new UserModel(); $userModel = new UserModel();
} }

View File

@ -52,7 +52,6 @@ class Toolbar extends BaseConfig
* `$maxHistory` sets a limit on the number of past requests that are stored, * `$maxHistory` sets a limit on the number of past requests that are stored,
* helping to conserve file space used to store them. You can set it to * helping to conserve file space used to store them. You can set it to
* 0 (zero) to not have any history stored, or -1 for unlimited history. * 0 (zero) to not have any history stored, or -1 for unlimited history.
*
*/ */
public int $maxHistory = 20; public int $maxHistory = 20;
@ -63,7 +62,6 @@ class Toolbar extends BaseConfig
* *
* The full path to the the views that are used by the toolbar. * The full path to the the views that are used by the toolbar.
* This MUST have a trailing slash. * This MUST have a trailing slash.
*
*/ */
public string $viewsPath = SYSTEMPATH . 'Debug/Toolbar/Views/'; public string $viewsPath = SYSTEMPATH . 'Debug/Toolbar/Views/';
@ -78,7 +76,6 @@ class Toolbar extends BaseConfig
* with hundreds of queries. * with hundreds of queries.
* *
* `$maxQueries` defines the maximum amount of queries that will be stored. * `$maxQueries` defines the maximum amount of queries that will be stored.
*
*/ */
public int $maxQueries = 100; public int $maxQueries = 100;
} }

View File

@ -1,4 +1,5 @@
<?php <?php
namespace Config; namespace Config;
use CodeIgniter\Config\BaseConfig; use CodeIgniter\Config\BaseConfig;

View File

@ -12,13 +12,8 @@ use Myth\Auth\Authentication\Passwords\ValidationRules as PasswordRules;
class Validation class Validation
{ {
//--------------------------------------------------------------------
// Setup
//--------------------------------------------------------------------
/** /**
* Stores the classes that contain the * Stores the classes that contain the rules that are available.
* rules that are available.
* *
* @var string[] * @var string[]
*/ */
@ -33,8 +28,7 @@ class Validation
]; ];
/** /**
* Specifies the views that are used to display the * Specifies the views that are used to display the errors.
* errors.
* *
* @var array<string, string> * @var array<string, string>
*/ */
@ -42,8 +36,4 @@ class Validation
'list' => 'CodeIgniter\Validation\Views\list', 'list' => 'CodeIgniter\Validation\Views\list',
'single' => 'CodeIgniter\Validation\Views\single', 'single' => 'CodeIgniter\Validation\Views\single',
]; ];
//--------------------------------------------------------------------
// Rules
//--------------------------------------------------------------------
} }

View File

@ -7,36 +7,29 @@ use CodeIgniter\Config\View as BaseView;
class View extends BaseView class View extends BaseView
{ {
/** /**
* When false, the view method will clear the data between each * When false, the view method will clear the data between each call. This keeps your data safe and ensures there is
* call. This keeps your data safe and ensures there is no accidental * no accidental leaking between calls, so you would need to explicitly pass the data to each view. You might prefer
* leaking between calls, so you would need to explicitly pass the data * to have the data stick around between calls so that it is available to all views. If that is the case, set
* to each view. You might prefer to have the data stick around between * $saveData to true.
* calls so that it is available to all views. If that is the case,
* set $saveData to true.
* *
* @var boolean * @var boolean
*/ */
public $saveData = true; public $saveData = true;
/** /**
* Parser Filters map a filter name with any PHP callable. When the * Parser Filters map a filter name with any PHP callable. When the Parser prepares a variable for display, it will
* Parser prepares a variable for display, it will chain it * chain it through the filters in the order defined, inserting any parameters. To prevent potential abuse, all
* through the filters in the order defined, inserting any parameters. * filters MUST be defined here in order for them to be available for use within the Parser.
* To prevent potential abuse, all filters MUST be defined here
* in order for them to be available for use within the Parser.
* *
* Examples: * Examples: { title|esc(js) } { created_on|date(Y-m-d)|esc(attr) }
* { title|esc(js) }
* { created_on|date(Y-m-d)|esc(attr) }
* *
* @var string[] * @var string[]
*/ */
public $filters = []; public $filters = [];
/** /**
* Parser Plugins provide a way to extend the functionality provided * Parser Plugins provide a way to extend the functionality provided by the core Parser by creating aliases that
* by the core Parser by creating aliases that will be replaced with * will be replaced with any callable. Can be single or tag pair.
* any callable. Can be single or tag pair.
* *
* @var string[] * @var string[]
*/ */

View File

@ -23,12 +23,12 @@ class ActorController extends ActivityPubActorController
public function follow(): string public function follow(): string
{ {
// Prevent analytics hit when authenticated // Prevent analytics hit when authenticated
if (!can_user_interact()) { if (! can_user_interact()) {
$this->registerPodcastWebpageHit($this->actor->podcast->id); $this->registerPodcastWebpageHit($this->actor->podcast->id);
} }
$cacheName = "page_podcast-{$this->actor->username}_follow"; $cacheName = "page_podcast-{$this->actor->username}_follow";
if (!($cachedView = cache($cacheName))) { if (! ($cachedView = cache($cacheName))) {
helper(['form', 'components', 'svg']); helper(['form', 'components', 'svg']);
$data = [ $data = [
'actor' => $this->actor, 'actor' => $this->actor,

View File

@ -10,10 +10,8 @@ use Psr\Log\LoggerInterface;
/** /**
* Class BaseController * Class BaseController
* *
* BaseController provides a convenient place for loading components * BaseController provides a convenient place for loading components and performing functions that are needed by all
* and performing functions that are needed by all your controllers. * your controllers. Extend this class in any new controllers: class Home extends BaseController
* Extend this class in any new controllers:
* class Home extends BaseController
* *
* For security be sure to declare any new methods as protected or private. * For security be sure to declare any new methods as protected or private.
*/ */
@ -21,9 +19,8 @@ use Psr\Log\LoggerInterface;
class BaseController extends Controller class BaseController extends Controller
{ {
/** /**
* An array of helpers to be loaded automatically upon * An array of helpers to be loaded automatically upon class instantiation. These helpers will be available to all
* class instantiation. These helpers will be available * other controllers that extend BaseController.
* to all other controllers that extend BaseController.
* *
* @var string[] * @var string[]
*/ */
@ -39,10 +36,5 @@ class BaseController extends Controller
): void { ): void {
// Do Not Edit This Line // Do Not Edit This Line
parent::initController($request, $response, $logger); parent::initController($request, $response, $logger);
//--------------------------------------------------------------------
// Preload any models, libraries, etc, here.
//--------------------------------------------------------------------
// E.g.: $this->session = \Config\Services::session();
} }
} }

View File

@ -8,18 +8,19 @@
namespace App\Controllers\Admin; namespace App\Controllers\Admin;
use App\Authorization\GroupModel;
use App\Entities\Podcast; use App\Entities\Podcast;
use App\Entities\User; use App\Entities\User;
use CodeIgniter\Exceptions\PageNotFoundException;
use Exception;
use App\Authorization\GroupModel;
use App\Models\PodcastModel; use App\Models\PodcastModel;
use App\Models\UserModel; use App\Models\UserModel;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\RedirectResponse;
use Exception;
class ContributorController extends BaseController class ContributorController extends BaseController
{ {
protected Podcast $podcast; protected Podcast $podcast;
protected ?User $user; protected ?User $user;
public function _remap(string $method, string ...$params): mixed public function _remap(string $method, string ...$params): mixed
@ -27,16 +28,13 @@ class ContributorController extends BaseController
$this->podcast = (new PodcastModel())->getPodcastById((int) $params[0]); $this->podcast = (new PodcastModel())->getPodcastById((int) $params[0]);
if (count($params) <= 1) { if (count($params) <= 1) {
return $this->$method(); return $this->{$method}();
} }
if ( if (
$this->user = (new UserModel())->getPodcastContributor( $this->user = (new UserModel())->getPodcastContributor((int) $params[1], (int) $params[0],)
(int) $params[1],
(int) $params[0],
)
) { ) {
return $this->$method(); return $this->{$method}();
} }
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
@ -48,17 +46,16 @@ class ContributorController extends BaseController
'podcast' => $this->podcast, 'podcast' => $this->podcast,
]; ];
replace_breadcrumb_params([0 => $this->podcast->title]); replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/contributor/list', $data); return view('admin/contributor/list', $data);
} }
public function view(): string public function view(): string
{ {
$data = [ $data = [
'contributor' => (new UserModel())->getPodcastContributor( 'contributor' => (new UserModel())->getPodcastContributor($this->user->id, $this->podcast->id,),
$this->user->id,
$this->podcast->id,
),
]; ];
replace_breadcrumb_params([ replace_breadcrumb_params([
@ -98,7 +95,9 @@ class ContributorController extends BaseController
'roleOptions' => $roleOptions, 'roleOptions' => $roleOptions,
]; ];
replace_breadcrumb_params([0 => $this->podcast->title]); replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/contributor/add', $data); return view('admin/contributor/add', $data);
} }
@ -114,9 +113,7 @@ class ContributorController extends BaseController
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
->with('errors', [ ->with('errors', [lang('Contributor.messages.alreadyAddedError')]);
lang('Contributor.messages.alreadyAddedError'),
]);
} }
return redirect()->route('contributor-list', [$this->podcast->id]); return redirect()->route('contributor-list', [$this->podcast->id]);
@ -169,17 +166,12 @@ class ContributorController extends BaseController
if ($this->podcast->created_by === $this->user->id) { if ($this->podcast->created_by === $this->user->id) {
return redirect() return redirect()
->back() ->back()
->with('errors', [ ->with('errors', [lang('Contributor.messages.removeOwnerContributorError')]);
lang('Contributor.messages.removeOwnerContributorError'),
]);
} }
$podcastModel = new PodcastModel(); $podcastModel = new PodcastModel();
if ( if (
!$podcastModel->removePodcastContributor( ! $podcastModel->removePodcastContributor($this->user->id, $this->podcast->id,)
$this->user->id,
$this->podcast->id,
)
) { ) {
return redirect() return redirect()
->back() ->back()

View File

@ -8,9 +8,6 @@
namespace App\Controllers\Admin; namespace App\Controllers\Admin;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\RedirectResponse;
use Config\Database;
use App\Entities\Episode; use App\Entities\Episode;
use App\Entities\Location; use App\Entities\Location;
use App\Entities\Note; use App\Entities\Note;
@ -19,26 +16,28 @@ use App\Models\EpisodeModel;
use App\Models\NoteModel; use App\Models\NoteModel;
use App\Models\PodcastModel; use App\Models\PodcastModel;
use App\Models\SoundbiteModel; use App\Models\SoundbiteModel;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\I18n\Time; use CodeIgniter\I18n\Time;
use Config\Database;
class EpisodeController extends BaseController class EpisodeController extends BaseController
{ {
protected Podcast $podcast; protected Podcast $podcast;
protected ?Episode $episode; protected ?Episode $episode;
public function _remap(string $method, string ...$params): mixed public function _remap(string $method, string ...$params): mixed
{ {
if ( if (
($this->podcast = (new PodcastModel())->getPodcastById( ($this->podcast = (new PodcastModel())->getPodcastById((int) $params[0],)) === null
(int) $params[0],
)) === null
) { ) {
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
} }
if (count($params) > 1) { if (count($params) > 1) {
if ( if (
!($this->episode = (new EpisodeModel()) ! ($this->episode = (new EpisodeModel())
->where([ ->where([
'id' => $params[1], 'id' => $params[1],
'podcast_id' => $params[0], 'podcast_id' => $params[0],
@ -52,7 +51,7 @@ class EpisodeController extends BaseController
unset($params[0]); unset($params[0]);
} }
return $this->$method(...$params); return $this->{$method}(...$params);
} }
public function list(): string public function list(): string
@ -112,7 +111,7 @@ class EpisodeController extends BaseController
'chapters_file' => 'ext_in[chapters,json]|permit_empty', 'chapters_file' => 'ext_in[chapters,json]|permit_empty',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -127,9 +126,7 @@ class EpisodeController extends BaseController
'audio_file' => $this->request->getFile('audio_file'), 'audio_file' => $this->request->getFile('audio_file'),
'description_markdown' => $this->request->getPost('description'), 'description_markdown' => $this->request->getPost('description'),
'image' => $this->request->getFile('image'), 'image' => $this->request->getFile('image'),
'location' => new Location( 'location' => new Location($this->request->getPost('location_name'),),
$this->request->getPost('location_name'),
),
'transcript' => $this->request->getFile('transcript'), 'transcript' => $this->request->getFile('transcript'),
'chapters' => $this->request->getFile('chapters'), 'chapters' => $this->request->getFile('chapters'),
'parental_advisory' => 'parental_advisory' =>
@ -143,7 +140,7 @@ class EpisodeController extends BaseController
? $this->request->getPost('season_number') ? $this->request->getPost('season_number')
: null, : null,
'type' => $this->request->getPost('type'), 'type' => $this->request->getPost('type'),
'is_blocked' => $this->request->getPost('block') == 'yes', 'is_blocked' => $this->request->getPost('block') === 'yes',
'custom_rss_string' => $this->request->getPost('custom_rss'), 'custom_rss_string' => $this->request->getPost('custom_rss'),
'created_by' => user_id(), 'created_by' => user_id(),
'updated_by' => user_id(), 'updated_by' => user_id(),
@ -157,9 +154,7 @@ class EpisodeController extends BaseController
) { ) {
$newEpisode->transcript_file = $transcriptFile; $newEpisode->transcript_file = $transcriptFile;
} elseif ($transcriptChoice === 'remote-url') { } elseif ($transcriptChoice === 'remote-url') {
$newEpisode->transcript_file_remote_url = $this->request->getPost( $newEpisode->transcript_file_remote_url = $this->request->getPost('transcript_file_remote_url',);
'transcript_file_remote_url',
);
} }
$chaptersChoice = $this->request->getPost('chapters-choice'); $chaptersChoice = $this->request->getPost('chapters-choice');
@ -169,14 +164,12 @@ class EpisodeController extends BaseController
) { ) {
$newEpisode->chapters_file = $chaptersFile; $newEpisode->chapters_file = $chaptersFile;
} elseif ($chaptersChoice === 'remote-url') { } elseif ($chaptersChoice === 'remote-url') {
$newEpisode->chapters_file_remote_url = $this->request->getPost( $newEpisode->chapters_file_remote_url = $this->request->getPost('chapters_file_remote_url',);
'chapters_file_remote_url',
);
} }
$episodeModel = new EpisodeModel(); $episodeModel = new EpisodeModel();
if (!($newEpisodeId = $episodeModel->insert($newEpisode, true))) { if (! ($newEpisodeId = $episodeModel->insert($newEpisode, true))) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -187,11 +180,9 @@ class EpisodeController extends BaseController
$podcastModel = new PodcastModel(); $podcastModel = new PodcastModel();
if ($this->podcast->hasChanged('episode_description_footer_markdown')) { if ($this->podcast->hasChanged('episode_description_footer_markdown')) {
$this->podcast->episode_description_footer_markdown = $this->request->getPost( $this->podcast->episode_description_footer_markdown = $this->request->getPost('description_footer',);
'description_footer',
);
if (!$podcastModel->update($this->podcast->id, $this->podcast)) { if (! $podcastModel->update($this->podcast->id, $this->podcast)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -199,10 +190,7 @@ class EpisodeController extends BaseController
} }
} }
return redirect()->route('episode-view', [ return redirect()->route('episode-view', [$this->podcast->id, $newEpisodeId]);
$this->podcast->id,
$newEpisodeId,
]);
} }
public function edit(): string public function edit(): string
@ -233,7 +221,7 @@ class EpisodeController extends BaseController
'chapters_file' => 'ext_in[chapters_file,json]|permit_empty', 'chapters_file' => 'ext_in[chapters_file,json]|permit_empty',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -242,12 +230,8 @@ class EpisodeController extends BaseController
$this->episode->title = $this->request->getPost('title'); $this->episode->title = $this->request->getPost('title');
$this->episode->slug = $this->request->getPost('slug'); $this->episode->slug = $this->request->getPost('slug');
$this->episode->description_markdown = $this->request->getPost( $this->episode->description_markdown = $this->request->getPost('description',);
'description', $this->episode->location = new Location($this->request->getPost('location_name'),);
);
$this->episode->location = new Location(
$this->request->getPost('location_name'),
);
$this->episode->parental_advisory = $this->episode->parental_advisory =
$this->request->getPost('parental_advisory') !== 'undefined' $this->request->getPost('parental_advisory') !== 'undefined'
? $this->request->getPost('parental_advisory') ? $this->request->getPost('parental_advisory')
@ -259,10 +243,8 @@ class EpisodeController extends BaseController
? $this->request->getPost('season_number') ? $this->request->getPost('season_number')
: null; : null;
$this->episode->type = $this->request->getPost('type'); $this->episode->type = $this->request->getPost('type');
$this->episode->is_blocked = $this->request->getPost('block') == 'yes'; $this->episode->is_blocked = $this->request->getPost('block') === 'yes';
$this->episode->custom_rss_string = $this->request->getPost( $this->episode->custom_rss_string = $this->request->getPost('custom_rss',);
'custom_rss',
);
$this->episode->updated_by = user_id(); $this->episode->updated_by = user_id();
@ -285,9 +267,7 @@ class EpisodeController extends BaseController
} }
} elseif ($transcriptChoice === 'remote-url') { } elseif ($transcriptChoice === 'remote-url') {
if ( if (
($transcriptFileRemoteUrl = $this->request->getPost( ($transcriptFileRemoteUrl = $this->request->getPost('transcript_file_remote_url',)) &&
'transcript_file_remote_url',
)) &&
(($transcriptFile = $this->episode->transcript_file) && (($transcriptFile = $this->episode->transcript_file) &&
$transcriptFile !== null) $transcriptFile !== null)
) { ) {
@ -306,9 +286,7 @@ class EpisodeController extends BaseController
} }
} elseif ($chaptersChoice === 'remote-url') { } elseif ($chaptersChoice === 'remote-url') {
if ( if (
($chaptersFileRemoteUrl = $this->request->getPost( ($chaptersFileRemoteUrl = $this->request->getPost('chapters_file_remote_url',)) &&
'chapters_file_remote_url',
)) &&
(($chaptersFile = $this->episode->chapters_file) && (($chaptersFile = $this->episode->chapters_file) &&
$chaptersFile !== null) $chaptersFile !== null)
) { ) {
@ -320,7 +298,7 @@ class EpisodeController extends BaseController
$episodeModel = new EpisodeModel(); $episodeModel = new EpisodeModel();
if (!$episodeModel->update($this->episode->id, $this->episode)) { if (! $episodeModel->update($this->episode->id, $this->episode)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -328,13 +306,11 @@ class EpisodeController extends BaseController
} }
// update podcast's episode_description_footer_markdown if changed // update podcast's episode_description_footer_markdown if changed
$this->podcast->episode_description_footer_markdown = $this->request->getPost( $this->podcast->episode_description_footer_markdown = $this->request->getPost('description_footer',);
'description_footer',
);
if ($this->podcast->hasChanged('episode_description_footer_markdown')) { if ($this->podcast->hasChanged('episode_description_footer_markdown')) {
$podcastModel = new PodcastModel(); $podcastModel = new PodcastModel();
if (!$podcastModel->update($this->podcast->id, $this->podcast)) { if (! $podcastModel->update($this->podcast->id, $this->podcast)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -342,10 +318,7 @@ class EpisodeController extends BaseController
} }
} }
return redirect()->route('episode-view', [ return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id]);
$this->podcast->id,
$this->episode->id,
]);
} }
public function transcriptDelete(): RedirectResponse public function transcriptDelete(): RedirectResponse
@ -355,7 +328,7 @@ class EpisodeController extends BaseController
$episodeModel = new EpisodeModel(); $episodeModel = new EpisodeModel();
if (!$episodeModel->update($this->episode->id, $this->episode)) { if (! $episodeModel->update($this->episode->id, $this->episode)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -372,7 +345,7 @@ class EpisodeController extends BaseController
$episodeModel = new EpisodeModel(); $episodeModel = new EpisodeModel();
if (!$episodeModel->update($this->episode->id, $this->episode)) { if (! $episodeModel->update($this->episode->id, $this->episode)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -410,7 +383,7 @@ class EpisodeController extends BaseController
'valid_date[Y-m-d H:i]|permit_empty', 'valid_date[Y-m-d H:i]|permit_empty',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -429,9 +402,7 @@ class EpisodeController extends BaseController
$publishMethod = $this->request->getPost('publication_method'); $publishMethod = $this->request->getPost('publication_method');
if ($publishMethod === 'schedule') { if ($publishMethod === 'schedule') {
$scheduledPublicationDate = $this->request->getPost( $scheduledPublicationDate = $this->request->getPost('scheduled_publication_date',);
'scheduled_publication_date',
);
if ($scheduledPublicationDate) { if ($scheduledPublicationDate) {
$scheduledDateUTC = Time::createFromFormat( $scheduledDateUTC = Time::createFromFormat(
'Y-m-d H:i', 'Y-m-d H:i',
@ -454,7 +425,7 @@ class EpisodeController extends BaseController
} }
$noteModel = new NoteModel(); $noteModel = new NoteModel();
if (!$noteModel->addNote($newNote)) { if (! $noteModel->addNote($newNote)) {
$db->transRollback(); $db->transRollback();
return redirect() return redirect()
->back() ->back()
@ -463,7 +434,7 @@ class EpisodeController extends BaseController
} }
$episodeModel = new EpisodeModel(); $episodeModel = new EpisodeModel();
if (!$episodeModel->update($this->episode->id, $this->episode)) { if (! $episodeModel->update($this->episode->id, $this->episode)) {
$db->transRollback(); $db->transRollback();
return redirect() return redirect()
->back() ->back()
@ -473,10 +444,7 @@ class EpisodeController extends BaseController
$db->transComplete(); $db->transComplete();
return redirect()->route('episode-view', [ return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id]);
$this->podcast->id,
$this->episode->id,
]);
} }
public function publishEdit(): string public function publishEdit(): string
@ -513,7 +481,7 @@ class EpisodeController extends BaseController
'valid_date[Y-m-d H:i]|permit_empty', 'valid_date[Y-m-d H:i]|permit_empty',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -523,16 +491,12 @@ class EpisodeController extends BaseController
$db = Database::connect(); $db = Database::connect();
$db->transStart(); $db->transStart();
$note = (new NoteModel())->getNoteById( $note = (new NoteModel())->getNoteById($this->request->getPost('note_id'),);
$this->request->getPost('note_id'),
);
$note->message = $this->request->getPost('message'); $note->message = $this->request->getPost('message');
$publishMethod = $this->request->getPost('publication_method'); $publishMethod = $this->request->getPost('publication_method');
if ($publishMethod === 'schedule') { if ($publishMethod === 'schedule') {
$scheduledPublicationDate = $this->request->getPost( $scheduledPublicationDate = $this->request->getPost('scheduled_publication_date',);
'scheduled_publication_date',
);
if ($scheduledPublicationDate) { if ($scheduledPublicationDate) {
$scheduledDateUTC = Time::createFromFormat( $scheduledDateUTC = Time::createFromFormat(
'Y-m-d H:i', 'Y-m-d H:i',
@ -555,7 +519,7 @@ class EpisodeController extends BaseController
} }
$noteModel = new NoteModel(); $noteModel = new NoteModel();
if (!$noteModel->editNote($note)) { if (! $noteModel->editNote($note)) {
$db->transRollback(); $db->transRollback();
return redirect() return redirect()
->back() ->back()
@ -564,7 +528,7 @@ class EpisodeController extends BaseController
} }
$episodeModel = new EpisodeModel(); $episodeModel = new EpisodeModel();
if (!$episodeModel->update($this->episode->id, $this->episode)) { if (! $episodeModel->update($this->episode->id, $this->episode)) {
$db->transRollback(); $db->transRollback();
return redirect() return redirect()
->back() ->back()
@ -574,10 +538,7 @@ class EpisodeController extends BaseController
$db->transComplete(); $db->transComplete();
return redirect()->route('episode-view', [ return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id]);
$this->podcast->id,
$this->episode->id,
]);
} }
public function unpublish(): string public function unpublish(): string
@ -606,7 +567,7 @@ class EpisodeController extends BaseController
'understand' => 'required', 'understand' => 'required',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -630,7 +591,7 @@ class EpisodeController extends BaseController
$this->episode->published_at = null; $this->episode->published_at = null;
$episodeModel = new EpisodeModel(); $episodeModel = new EpisodeModel();
if (!$episodeModel->update($this->episode->id, $this->episode)) { if (! $episodeModel->update($this->episode->id, $this->episode)) {
$db->transRollback(); $db->transRollback();
return redirect() return redirect()
->back() ->back()
@ -640,10 +601,7 @@ class EpisodeController extends BaseController
$db->transComplete(); $db->transComplete();
return redirect()->route('episode-view', [ return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id]);
$this->podcast->id,
$this->episode->id,
]);
} }
public function delete(): RedirectResponse public function delete(): RedirectResponse
@ -684,7 +642,7 @@ class EpisodeController extends BaseController
"soundbites.{$soundbite_id}.duration" => 'required|decimal|greater_than_equal_to[0]', "soundbites.{$soundbite_id}.duration" => 'required|decimal|greater_than_equal_to[0]',
]; ];
} }
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -701,14 +659,18 @@ class EpisodeController extends BaseController
'label' => $soundbite['label'], 'label' => $soundbite['label'],
'updated_by' => user_id(), 'updated_by' => user_id(),
]; ];
if ($soundbite_id == 0) { if ($soundbite_id === 0) {
$data += ['created_by' => user_id()]; $data += [
'created_by' => user_id(),
];
} else { } else {
$data += ['id' => $soundbite_id]; $data += [
'id' => $soundbite_id,
];
} }
$soundbiteModel = new SoundbiteModel(); $soundbiteModel = new SoundbiteModel();
if (!$soundbiteModel->save($data)) { if (! $soundbiteModel->save($data)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -716,24 +678,14 @@ class EpisodeController extends BaseController
} }
} }
} }
return redirect()->route('soundbites-edit', [ return redirect()->route('soundbites-edit', [$this->podcast->id, $this->episode->id]);
$this->podcast->id,
$this->episode->id,
]);
} }
public function soundbiteDelete(int $soundbiteId): RedirectResponse public function soundbiteDelete(int $soundbiteId): RedirectResponse
{ {
(new SoundbiteModel())->deleteSoundbite( (new SoundbiteModel())->deleteSoundbite($this->podcast->id, $this->episode->id, $soundbiteId,);
$this->podcast->id,
$this->episode->id,
$soundbiteId,
);
return redirect()->route('soundbites-edit', [ return redirect()->route('soundbites-edit', [$this->podcast->id, $this->episode->id]);
$this->podcast->id,
$this->episode->id,
]);
} }
public function embeddablePlayer(): string public function embeddablePlayer(): string

View File

@ -8,17 +8,18 @@
namespace App\Controllers\Admin; namespace App\Controllers\Admin;
use CodeIgniter\HTTP\RedirectResponse;
use App\Entities\Podcast;
use App\Entities\Episode; use App\Entities\Episode;
use CodeIgniter\Exceptions\PageNotFoundException; use App\Entities\Podcast;
use App\Models\PodcastModel;
use App\Models\EpisodeModel; use App\Models\EpisodeModel;
use App\Models\PersonModel; use App\Models\PersonModel;
use App\Models\PodcastModel;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\RedirectResponse;
class EpisodePersonController extends BaseController class EpisodePersonController extends BaseController
{ {
protected Podcast $podcast; protected Podcast $podcast;
protected Episode $episode; protected Episode $episode;
public function _remap(string $method, string ...$params): mixed public function _remap(string $method, string ...$params): mixed
@ -28,9 +29,7 @@ class EpisodePersonController extends BaseController
} }
if ( if (
($this->podcast = (new PodcastModel())->getPodcastById( ($this->podcast = (new PodcastModel())->getPodcastById((int) $params[0],)) &&
(int) $params[0],
)) &&
($this->episode = (new EpisodeModel()) ($this->episode = (new EpisodeModel())
->where([ ->where([
'id' => $params[1], 'id' => $params[1],
@ -41,7 +40,7 @@ class EpisodePersonController extends BaseController
unset($params[1]); unset($params[1]);
unset($params[0]); unset($params[0]);
return $this->$method(...$params); return $this->{$method}(...$params);
} }
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
@ -70,7 +69,7 @@ class EpisodePersonController extends BaseController
'person' => 'required', 'person' => 'required',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -89,11 +88,7 @@ class EpisodePersonController extends BaseController
public function remove(int $personId): RedirectResponse public function remove(int $personId): RedirectResponse
{ {
(new PersonModel())->removePersonFromEpisode( (new PersonModel())->removePersonFromEpisode($this->podcast->id, $this->episode->id, $personId,);
$this->podcast->id,
$this->episode->id,
$personId,
);
return redirect()->back(); return redirect()->back();
} }

View File

@ -19,7 +19,8 @@ class FediverseController extends BaseController
{ {
helper(['form']); helper(['form']);
$blockedActors = model('ActorModel')->getBlockedActors(); $blockedActors = model('ActorModel')
->getBlockedActors();
return view('admin/fediverse/blocked_actors', [ return view('admin/fediverse/blocked_actors', [
'blockedActors' => $blockedActors, 'blockedActors' => $blockedActors,
@ -30,7 +31,8 @@ class FediverseController extends BaseController
{ {
helper(['form']); helper(['form']);
$blockedDomains = model('BlockedDomainModel')->getBlockedDomains(); $blockedDomains = model('BlockedDomainModel')
->getBlockedDomains();
return view('admin/fediverse/blocked_domains', [ return view('admin/fediverse/blocked_domains', [
'blockedDomains' => $blockedDomains, 'blockedDomains' => $blockedDomains,

View File

@ -9,6 +9,7 @@
namespace App\Controllers\Admin; namespace App\Controllers\Admin;
use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\RedirectResponse;
class HomeController extends BaseController class HomeController extends BaseController
{ {
public function index(): RedirectResponse public function index(): RedirectResponse

View File

@ -8,9 +8,9 @@
namespace App\Controllers\Admin; namespace App\Controllers\Admin;
use App\Models\UserModel;
use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\RedirectResponse;
use Config\Services; use Config\Services;
use App\Models\UserModel;
class MyAccountController extends BaseController class MyAccountController extends BaseController
{ {
@ -38,7 +38,7 @@ class MyAccountController extends BaseController
'new_password' => 'required|strong_password|differs[password]', 'new_password' => 'required|strong_password|differs[password]',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -46,20 +46,22 @@ class MyAccountController extends BaseController
} }
$credentials = [ $credentials = [
'email' => user()->email, 'email' => user()
->email,
'password' => $this->request->getPost('password'), 'password' => $this->request->getPost('password'),
]; ];
if (!$auth->validate($credentials)) { if (! $auth->validate($credentials)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
->with('error', lang('MyAccount.messages.wrongPasswordError')); ->with('error', lang('MyAccount.messages.wrongPasswordError'));
} }
user()->password = $this->request->getPost('new_password'); user()
->password = $this->request->getPost('new_password');
if (!$userModel->update(user_id(), user())) { if (! $userModel->update(user_id(), user())) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()

View File

@ -8,10 +8,10 @@
namespace App\Controllers\Admin; namespace App\Controllers\Admin;
use CodeIgniter\HTTP\RedirectResponse;
use App\Entities\Page; use App\Entities\Page;
use CodeIgniter\Exceptions\PageNotFoundException;
use App\Models\PageModel; use App\Models\PageModel;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\RedirectResponse;
class PageController extends BaseController class PageController extends BaseController
{ {
@ -20,17 +20,17 @@ class PageController extends BaseController
public function _remap(string $method, string ...$params): mixed public function _remap(string $method, string ...$params): mixed
{ {
if (count($params) === 0) { if (count($params) === 0) {
return $this->$method(); return $this->{$method}();
} }
if ($this->page = (new PageModel())->find($params[0])) { if ($this->page = (new PageModel())->find($params[0])) {
return $this->$method(); return $this->{$method}();
} }
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
} }
function list(): string public function list(): string
{ {
$data = [ $data = [
'pages' => (new PageModel())->findAll(), 'pages' => (new PageModel())->findAll(),
@ -39,19 +39,21 @@ class PageController extends BaseController
return view('admin/page/list', $data); return view('admin/page/list', $data);
} }
function view(): string public function view(): string
{ {
return view('admin/page/view', ['page' => $this->page]); return view('admin/page/view', [
'page' => $this->page,
]);
} }
function create(): string public function create(): string
{ {
helper('form'); helper('form');
return view('admin/page/create'); return view('admin/page/create');
} }
function attemptCreate(): RedirectResponse public function attemptCreate(): RedirectResponse
{ {
$page = new Page([ $page = new Page([
'title' => $this->request->getPost('title'), 'title' => $this->request->getPost('title'),
@ -61,7 +63,7 @@ class PageController extends BaseController
$pageModel = new PageModel(); $pageModel = new PageModel();
if (!$pageModel->insert($page)) { if (! $pageModel->insert($page)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -70,23 +72,24 @@ class PageController extends BaseController
return redirect() return redirect()
->route('page-list') ->route('page-list')
->with( ->with('message', lang('Page.messages.createSuccess', [
'message', 'pageTitle' => $page->title,
lang('Page.messages.createSuccess', [ ]),);
'pageTitle' => $page->title,
]),
);
} }
function edit(): string public function edit(): string
{ {
helper('form'); helper('form');
replace_breadcrumb_params([0 => $this->page->title]); replace_breadcrumb_params([
return view('admin/page/edit', ['page' => $this->page]); 0 => $this->page->title,
]);
return view('admin/page/edit', [
'page' => $this->page,
]);
} }
function attemptEdit(): RedirectResponse public function attemptEdit(): RedirectResponse
{ {
$this->page->title = $this->request->getPost('title'); $this->page->title = $this->request->getPost('title');
$this->page->slug = $this->request->getPost('slug'); $this->page->slug = $this->request->getPost('slug');
@ -94,7 +97,7 @@ class PageController extends BaseController
$pageModel = new PageModel(); $pageModel = new PageModel();
if (!$pageModel->update($this->page->id, $this->page)) { if (! $pageModel->update($this->page->id, $this->page)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()

View File

@ -9,10 +9,10 @@
namespace App\Controllers\Admin; namespace App\Controllers\Admin;
use App\Entities\Image; use App\Entities\Image;
use CodeIgniter\HTTP\RedirectResponse;
use App\Entities\Person; use App\Entities\Person;
use CodeIgniter\Exceptions\PageNotFoundException;
use App\Models\PersonModel; use App\Models\PersonModel;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\RedirectResponse;
class PersonController extends BaseController class PersonController extends BaseController
{ {
@ -21,15 +21,13 @@ class PersonController extends BaseController
public function _remap(string $method, string ...$params): mixed public function _remap(string $method, string ...$params): mixed
{ {
if (count($params) === 0) { if (count($params) === 0) {
return $this->$method(); return $this->{$method}();
} }
if ( if (
($this->person = (new PersonModel())->getPersonById( ($this->person = (new PersonModel())->getPersonById((int) $params[0],)) !== null
(int) $params[0],
)) !== null
) { ) {
return $this->$method(); return $this->{$method}();
} }
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
@ -37,16 +35,22 @@ class PersonController extends BaseController
public function index(): string public function index(): string
{ {
$data = ['persons' => (new PersonModel())->findAll()]; $data = [
'persons' => (new PersonModel())->findAll(),
];
return view('admin/person/list', $data); return view('admin/person/list', $data);
} }
public function view(): string public function view(): string
{ {
$data = ['person' => $this->person]; $data = [
'person' => $this->person,
];
replace_breadcrumb_params([0 => $this->person->full_name]); replace_breadcrumb_params([
0 => $this->person->full_name,
]);
return view('admin/person/view', $data); return view('admin/person/view', $data);
} }
@ -64,7 +68,7 @@ class PersonController extends BaseController
'is_image[image]|ext_in[image,jpg,jpeg,png]|min_dims[image,400,400]|is_image_squared[image]', 'is_image[image]|ext_in[image,jpg,jpeg,png]|min_dims[image,400,400]|is_image_squared[image]',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -82,7 +86,7 @@ class PersonController extends BaseController
$personModel = new PersonModel(); $personModel = new PersonModel();
if (!$personModel->insert($person)) { if (! $personModel->insert($person)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -100,7 +104,9 @@ class PersonController extends BaseController
'person' => $this->person, 'person' => $this->person,
]; ];
replace_breadcrumb_params([0 => $this->person->full_name]); replace_breadcrumb_params([
0 => $this->person->full_name,
]);
return view('admin/person/edit', $data); return view('admin/person/edit', $data);
} }
@ -111,7 +117,7 @@ class PersonController extends BaseController
'is_image[image]|ext_in[image,jpg,jpeg,png]|min_dims[image,400,400]|is_image_squared[image]', 'is_image[image]|ext_in[image,jpg,jpeg,png]|min_dims[image,400,400]|is_image_squared[image]',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -120,9 +126,7 @@ class PersonController extends BaseController
$this->person->full_name = $this->request->getPost('full_name'); $this->person->full_name = $this->request->getPost('full_name');
$this->person->unique_name = $this->request->getPost('unique_name'); $this->person->unique_name = $this->request->getPost('unique_name');
$this->person->information_url = $this->request->getPost( $this->person->information_url = $this->request->getPost('information_url',);
'information_url',
);
$imageFile = $this->request->getFile('image'); $imageFile = $this->request->getFile('image');
if ($imageFile !== null && $imageFile->isValid()) { if ($imageFile !== null && $imageFile->isValid()) {
$this->person->image = new Image($imageFile); $this->person->image = new Image($imageFile);
@ -131,7 +135,7 @@ class PersonController extends BaseController
$this->person->updated_by = user_id(); $this->person->updated_by = user_id();
$personModel = new PersonModel(); $personModel = new PersonModel();
if (!$personModel->update($this->person->id, $this->person)) { if (! $personModel->update($this->person->id, $this->person)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()

View File

@ -11,34 +11,29 @@ namespace App\Controllers\Admin;
use App\Entities\Image; use App\Entities\Image;
use App\Entities\Location; use App\Entities\Location;
use App\Entities\Podcast; use App\Entities\Podcast;
use CodeIgniter\Exceptions\PageNotFoundException;
use Config\Database;
use App\Models\CategoryModel; use App\Models\CategoryModel;
use App\Models\EpisodeModel;
use App\Models\LanguageModel; use App\Models\LanguageModel;
use App\Models\PodcastModel; use App\Models\PodcastModel;
use App\Models\EpisodeModel; use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\RedirectResponse;
use Config\Database;
use Config\Services; use Config\Services;
class PodcastController extends BaseController class PodcastController extends BaseController
{ {
/**
* @var Podcast
*/
protected Podcast $podcast; protected Podcast $podcast;
public function _remap(string $method, string ...$params): mixed public function _remap(string $method, string ...$params): mixed
{ {
if (count($params) === 0) { if (count($params) === 0) {
return $this->$method(); return $this->{$method}();
} }
if ( if (
($this->podcast = (new PodcastModel())->getPodcastById( ($this->podcast = (new PodcastModel())->getPodcastById((int) $params[0],)) !== null
(int) $params[0],
)) !== null
) { ) {
return $this->$method(); return $this->{$method}();
} }
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
@ -46,14 +41,14 @@ class PodcastController extends BaseController
public function list(): string public function list(): string
{ {
if (!has_permission('podcasts-list')) { if (! has_permission('podcasts-list')) {
$data = [ $data = [
'podcasts' => (new PodcastModel())->getUserPodcasts( 'podcasts' => (new PodcastModel())->getUserPodcasts((int) user_id(),),
(int) user_id(),
),
]; ];
} else { } else {
$data = ['podcasts' => (new PodcastModel())->findAll()]; $data = [
'podcasts' => (new PodcastModel())->findAll(),
];
} }
return view('admin/podcast/list', $data); return view('admin/podcast/list', $data);
@ -61,65 +56,97 @@ class PodcastController extends BaseController
public function view(): string public function view(): string
{ {
$data = ['podcast' => $this->podcast]; $data = [
'podcast' => $this->podcast,
];
replace_breadcrumb_params([0 => $this->podcast->title]); replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/podcast/view', $data); return view('admin/podcast/view', $data);
} }
public function viewAnalytics(): string public function viewAnalytics(): string
{ {
$data = ['podcast' => $this->podcast]; $data = [
'podcast' => $this->podcast,
];
replace_breadcrumb_params([0 => $this->podcast->title]); replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/podcast/analytics/index', $data); return view('admin/podcast/analytics/index', $data);
} }
public function viewAnalyticsWebpages(): string public function viewAnalyticsWebpages(): string
{ {
$data = ['podcast' => $this->podcast]; $data = [
'podcast' => $this->podcast,
];
replace_breadcrumb_params([0 => $this->podcast->title]); replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/podcast/analytics/webpages', $data); return view('admin/podcast/analytics/webpages', $data);
} }
public function viewAnalyticsLocations(): string public function viewAnalyticsLocations(): string
{ {
$data = ['podcast' => $this->podcast]; $data = [
'podcast' => $this->podcast,
];
replace_breadcrumb_params([0 => $this->podcast->title]); replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/podcast/analytics/locations', $data); return view('admin/podcast/analytics/locations', $data);
} }
public function viewAnalyticsUniqueListeners(): string public function viewAnalyticsUniqueListeners(): string
{ {
$data = ['podcast' => $this->podcast]; $data = [
'podcast' => $this->podcast,
];
replace_breadcrumb_params([0 => $this->podcast->title]); replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/podcast/analytics/unique_listeners', $data); return view('admin/podcast/analytics/unique_listeners', $data);
} }
public function viewAnalyticsListeningTime(): string public function viewAnalyticsListeningTime(): string
{ {
$data = ['podcast' => $this->podcast]; $data = [
'podcast' => $this->podcast,
];
replace_breadcrumb_params([0 => $this->podcast->title]); replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/podcast/analytics/listening_time', $data); return view('admin/podcast/analytics/listening_time', $data);
} }
public function viewAnalyticsTimePeriods(): string public function viewAnalyticsTimePeriods(): string
{ {
$data = ['podcast' => $this->podcast]; $data = [
'podcast' => $this->podcast,
];
replace_breadcrumb_params([0 => $this->podcast->title]); replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/podcast/analytics/time_periods', $data); return view('admin/podcast/analytics/time_periods', $data);
} }
public function viewAnalyticsPlayers(): string public function viewAnalyticsPlayers(): string
{ {
$data = ['podcast' => $this->podcast]; $data = [
'podcast' => $this->podcast,
];
replace_breadcrumb_params([0 => $this->podcast->title]); replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/podcast/analytics/players', $data); return view('admin/podcast/analytics/players', $data);
} }
@ -133,9 +160,7 @@ class PodcastController extends BaseController
$data = [ $data = [
'languageOptions' => $languageOptions, 'languageOptions' => $languageOptions,
'categoryOptions' => $categoryOptions, 'categoryOptions' => $categoryOptions,
'browserLang' => get_browser_language( 'browserLang' => get_browser_language($this->request->getServer('HTTP_ACCEPT_LANGUAGE'),),
$this->request->getServer('HTTP_ACCEPT_LANGUAGE'),
),
]; ];
return view('admin/podcast/create', $data); return view('admin/podcast/create', $data);
@ -148,7 +173,7 @@ class PodcastController extends BaseController
'uploaded[image]|is_image[image]|ext_in[image,jpg,png]|min_dims[image,1400,1400]|is_image_squared[image]', 'uploaded[image]|is_image[image]|ext_in[image,jpg,png]|min_dims[image,1400,1400]|is_image_squared[image]',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -171,9 +196,7 @@ class PodcastController extends BaseController
'publisher' => $this->request->getPost('publisher'), 'publisher' => $this->request->getPost('publisher'),
'type' => $this->request->getPost('type'), 'type' => $this->request->getPost('type'),
'copyright' => $this->request->getPost('copyright'), 'copyright' => $this->request->getPost('copyright'),
'location' => new Location( 'location' => new Location($this->request->getPost('location_name'),),
$this->request->getPost('location_name'),
),
'payment_pointer' => $this->request->getPost('payment_pointer'), 'payment_pointer' => $this->request->getPost('payment_pointer'),
'custom_rss_string' => $this->request->getPost('custom_rss'), 'custom_rss_string' => $this->request->getPost('custom_rss'),
'partner_id' => $this->request->getPost('partner_id'), 'partner_id' => $this->request->getPost('partner_id'),
@ -191,7 +214,7 @@ class PodcastController extends BaseController
$db->transStart(); $db->transStart();
if (!($newPodcastId = $podcastModel->insert($podcast, true))) { if (! ($newPodcastId = $podcastModel->insert($podcast, true))) {
$db->transRollback(); $db->transRollback();
return redirect() return redirect()
->back() ->back()
@ -202,11 +225,7 @@ class PodcastController extends BaseController
$authorize = Services::authorization(); $authorize = Services::authorization();
$podcastAdminGroup = $authorize->group('podcast_admin'); $podcastAdminGroup = $authorize->group('podcast_admin');
$podcastModel->addPodcastContributor( $podcastModel->addPodcastContributor(user_id(), $newPodcastId, $podcastAdminGroup->id,);
user_id(),
$newPodcastId,
$podcastAdminGroup->id,
);
// set Podcast categories // set Podcast categories
(new CategoryModel())->setPodcastCategories( (new CategoryModel())->setPodcastCategories(
@ -236,7 +255,9 @@ class PodcastController extends BaseController
'categoryOptions' => $categoryOptions, 'categoryOptions' => $categoryOptions,
]; ];
replace_breadcrumb_params([0 => $this->podcast->title]); replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/podcast/edit', $data); return view('admin/podcast/edit', $data);
} }
@ -247,7 +268,7 @@ class PodcastController extends BaseController
'is_image[image]|ext_in[image,jpg,png]|min_dims[image,1400,1400]|is_image_squared[image]', 'is_image[image]|ext_in[image,jpg,png]|min_dims[image,1400,1400]|is_image_squared[image]',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -255,9 +276,7 @@ class PodcastController extends BaseController
} }
$this->podcast->title = $this->request->getPost('title'); $this->podcast->title = $this->request->getPost('title');
$this->podcast->description_markdown = $this->request->getPost( $this->podcast->description_markdown = $this->request->getPost('description',);
'description',
);
$image = $this->request->getFile('image'); $image = $this->request->getFile('image');
if ($image !== null && $image->isValid()) { if ($image !== null && $image->isValid()) {
@ -274,22 +293,12 @@ class PodcastController extends BaseController
$this->podcast->owner_email = $this->request->getPost('owner_email'); $this->podcast->owner_email = $this->request->getPost('owner_email');
$this->podcast->type = $this->request->getPost('type'); $this->podcast->type = $this->request->getPost('type');
$this->podcast->copyright = $this->request->getPost('copyright'); $this->podcast->copyright = $this->request->getPost('copyright');
$this->podcast->location = new Location( $this->podcast->location = new Location($this->request->getPost('location_name'),);
$this->request->getPost('location_name'), $this->podcast->payment_pointer = $this->request->getPost('payment_pointer',);
); $this->podcast->custom_rss_string = $this->request->getPost('custom_rss',);
$this->podcast->payment_pointer = $this->request->getPost(
'payment_pointer',
);
$this->podcast->custom_rss_string = $this->request->getPost(
'custom_rss',
);
$this->podcast->partner_id = $this->request->getPost('partner_id'); $this->podcast->partner_id = $this->request->getPost('partner_id');
$this->podcast->partner_link_url = $this->request->getPost( $this->podcast->partner_link_url = $this->request->getPost('partner_link_url',);
'partner_link_url', $this->podcast->partner_image_url = $this->request->getPost('partner_image_url',);
);
$this->podcast->partner_image_url = $this->request->getPost(
'partner_image_url',
);
$this->podcast->is_blocked = $this->request->getPost('block') === 'yes'; $this->podcast->is_blocked = $this->request->getPost('block') === 'yes';
$this->podcast->is_completed = $this->podcast->is_completed =
$this->request->getPost('complete') === 'yes'; $this->request->getPost('complete') === 'yes';
@ -300,7 +309,7 @@ class PodcastController extends BaseController
$db->transStart(); $db->transStart();
$podcastModel = new PodcastModel(); $podcastModel = new PodcastModel();
if (!$podcastModel->update($this->podcast->id, $this->podcast)) { if (! $podcastModel->update($this->podcast->id, $this->podcast)) {
$db->transRollback(); $db->transRollback();
return redirect() return redirect()
->back() ->back()
@ -326,7 +335,9 @@ class PodcastController extends BaseController
->orderBy('created_at', 'desc') ->orderBy('created_at', 'desc')
->findAll($limit); ->findAll($limit);
return view('admin/podcast/latest_episodes', ['episodes' => $episodes]); return view('admin/podcast/latest_episodes', [
'episodes' => $episodes,
]);
} }
public function delete(): RedirectResponse public function delete(): RedirectResponse

View File

@ -8,40 +8,37 @@
namespace App\Controllers\Admin; namespace App\Controllers\Admin;
use CodeIgniter\HTTP\RedirectResponse;
use App\Entities\Podcast;
use CodeIgniter\Exceptions\PageNotFoundException;
use ErrorException;
use Config\Database;
use Podlibre\PodcastNamespace\ReversedTaxonomy;
use App\Entities\Episode; use App\Entities\Episode;
use App\Entities\Image; use App\Entities\Image;
use App\Entities\Location; use App\Entities\Location;
use App\Entities\Person; use App\Entities\Person;
use App\Entities\Podcast;
use App\Models\CategoryModel; use App\Models\CategoryModel;
use App\Models\LanguageModel;
use App\Models\PodcastModel;
use App\Models\EpisodeModel; use App\Models\EpisodeModel;
use App\Models\PlatformModel; use App\Models\LanguageModel;
use App\Models\PersonModel; use App\Models\PersonModel;
use App\Models\PlatformModel;
use App\Models\PodcastModel;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\RedirectResponse;
use Config\Database;
use Config\Services; use Config\Services;
use ErrorException;
use League\HTMLToMarkdown\HtmlConverter; use League\HTMLToMarkdown\HtmlConverter;
use Podlibre\PodcastNamespace\ReversedTaxonomy;
class PodcastImportController extends BaseController class PodcastImportController extends BaseController
{ {
/**
* @var Podcast|null
*/
protected ?Podcast $podcast; protected ?Podcast $podcast;
public function _remap(string $method, string ...$params): mixed public function _remap(string $method, string ...$params): mixed
{ {
if (count($params) === 0) { if (count($params) === 0) {
return $this->$method(); return $this->{$method}();
} }
if (($this->podcast = (new PodcastModel())->getPodcastById((int) $params[0])) !== null) { if (($this->podcast = (new PodcastModel())->getPodcastById((int) $params[0])) !== null) {
return $this->$method(); return $this->{$method}();
} }
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
@ -57,9 +54,7 @@ class PodcastImportController extends BaseController
$data = [ $data = [
'languageOptions' => $languageOptions, 'languageOptions' => $languageOptions,
'categoryOptions' => $categoryOptions, 'categoryOptions' => $categoryOptions,
'browserLang' => get_browser_language( 'browserLang' => get_browser_language($this->request->getServer('HTTP_ACCEPT_LANGUAGE'),),
$this->request->getServer('HTTP_ACCEPT_LANGUAGE'),
),
]; ];
return view('admin/podcast/import', $data); return view('admin/podcast/import', $data);
@ -75,7 +70,7 @@ class PodcastImportController extends BaseController
'max_episodes' => 'is_natural_no_zero|permit_empty', 'max_episodes' => 'is_natural_no_zero|permit_empty',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -83,9 +78,7 @@ class PodcastImportController extends BaseController
} }
try { try {
ini_set('user_agent', 'Castopod/' . CP_VERSION); ini_set('user_agent', 'Castopod/' . CP_VERSION);
$feed = simplexml_load_file( $feed = simplexml_load_file($this->request->getPost('imported_feed_url'),);
$this->request->getPost('imported_feed_url'),
);
} catch (ErrorException $errorException) { } catch (ErrorException $errorException) {
return redirect() return redirect()
->back() ->back()
@ -99,15 +92,11 @@ class PodcastImportController extends BaseController
' ⎋</a>', ' ⎋</a>',
]); ]);
} }
$nsItunes = $feed->channel[0]->children( $nsItunes = $feed->channel[0]->children('http://www.itunes.com/dtds/podcast-1.0.dtd',);
'http://www.itunes.com/dtds/podcast-1.0.dtd',
);
$nsPodcast = $feed->channel[0]->children( $nsPodcast = $feed->channel[0]->children(
'https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md', 'https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md',
); );
$nsContent = $feed->channel[0]->children( $nsContent = $feed->channel[0]->children('http://purl.org/rss/1.0/modules/content/',);
'http://purl.org/rss/1.0/modules/content/',
);
if ((string) $nsPodcast->locked === 'yes') { if ((string) $nsPodcast->locked === 'yes') {
return redirect() return redirect()
@ -125,13 +114,9 @@ class PodcastImportController extends BaseController
property_exists($nsItunes, 'image') && $nsItunes->image !== null && property_exists($nsItunes, 'image') && $nsItunes->image !== null &&
$nsItunes->image->attributes()['href'] !== null $nsItunes->image->attributes()['href'] !== null
) { ) {
$imageFile = download_file( $imageFile = download_file((string) $nsItunes->image->attributes()['href'],);
(string) $nsItunes->image->attributes()['href'],
);
} else { } else {
$imageFile = download_file( $imageFile = download_file((string) $feed->channel[0]->image->url,);
(string) $feed->channel[0]->image->url,
);
} }
$location = null; $location = null;
@ -145,37 +130,37 @@ class PodcastImportController extends BaseController
$podcast = new Podcast([ $podcast = new Podcast([
'name' => $this->request->getPost('name'), 'name' => $this->request->getPost('name'),
'imported_feed_url' => $this->request->getPost( 'imported_feed_url' => $this->request->getPost('imported_feed_url',),
'imported_feed_url', 'new_feed_url' => base_url(route_to('podcast_feed', $this->request->getPost('name')),),
),
'new_feed_url' => base_url(
route_to('podcast_feed', $this->request->getPost('name')),
),
'title' => (string) $feed->channel[0]->title, 'title' => (string) $feed->channel[0]->title,
'description_markdown' => $converter->convert( 'description_markdown' => $converter->convert($channelDescriptionHtml,),
$channelDescriptionHtml,
),
'description_html' => $channelDescriptionHtml, 'description_html' => $channelDescriptionHtml,
'image' => new Image($imageFile), 'image' => new Image($imageFile),
'language_code' => $this->request->getPost('language'), 'language_code' => $this->request->getPost('language'),
'category_id' => $this->request->getPost('category'), 'category_id' => $this->request->getPost('category'),
'parental_advisory' => 'parental_advisory' =>
property_exists($nsItunes, 'explicit') && $nsItunes->explicit !== null property_exists($nsItunes, 'explicit') && $nsItunes->explicit !== null
? (in_array((string) $nsItunes->explicit, ['yes', 'true']) ? (in_array((string) $nsItunes->explicit, ['yes', 'true'], true)
? 'explicit' ? 'explicit'
: (in_array((string) $nsItunes->explicit, ['no', 'false']) : (in_array((string) $nsItunes->explicit, ['no', 'false'], true)
? 'clean' ? 'clean'
: null)) : null))
: null, : null,
'owner_name' => (string) $nsItunes->owner->name, 'owner_name' => (string) $nsItunes->owner->name,
'owner_email' => (string) $nsItunes->owner->email, 'owner_email' => (string) $nsItunes->owner->email,
'publisher' => (string) $nsItunes->author, 'publisher' => (string) $nsItunes->author,
'type' => property_exists($nsItunes, 'type') && $nsItunes->type !== null ? (string) $nsItunes->type : 'episodic', 'type' => property_exists(
$nsItunes,
'type'
) && $nsItunes->type !== null ? (string) $nsItunes->type : 'episodic',
'copyright' => (string) $feed->channel[0]->copyright, 'copyright' => (string) $feed->channel[0]->copyright,
'is_blocked' => 'is_blocked' =>
property_exists($nsItunes, 'block') && $nsItunes->block !== null && (string) $nsItunes->block === 'yes', property_exists($nsItunes, 'block') && $nsItunes->block !== null && (string) $nsItunes->block === 'yes',
'is_completed' => 'is_completed' =>
property_exists($nsItunes, 'complete') && $nsItunes->complete !== null && (string) $nsItunes->complete === 'yes', property_exists(
$nsItunes,
'complete'
) && $nsItunes->complete !== null && (string) $nsItunes->complete === 'yes',
'location' => $location, 'location' => $location,
'created_by' => user_id(), 'created_by' => user_id(),
'updated_by' => user_id(), 'updated_by' => user_id(),
@ -199,7 +184,7 @@ class PodcastImportController extends BaseController
$db->transStart(); $db->transStart();
if (!($newPodcastId = $podcastModel->insert($podcast, true))) { if (! ($newPodcastId = $podcastModel->insert($podcast, true))) {
$db->transRollback(); $db->transRollback();
return redirect() return redirect()
->back() ->back()
@ -210,17 +195,22 @@ class PodcastImportController extends BaseController
$authorize = Services::authorization(); $authorize = Services::authorization();
$podcastAdminGroup = $authorize->group('podcast_admin'); $podcastAdminGroup = $authorize->group('podcast_admin');
$podcastModel->addPodcastContributor( $podcastModel->addPodcastContributor(user_id(), $newPodcastId, $podcastAdminGroup->id,);
user_id(),
$newPodcastId,
$podcastAdminGroup->id,
);
$podcastsPlatformsData = []; $podcastsPlatformsData = [];
$platformTypes = [ $platformTypes = [
['name' => 'podcasting', 'elements' => $nsPodcast->id], [
['name' => 'social', 'elements' => $nsPodcast->social], 'name' => 'podcasting',
['name' => 'funding', 'elements' => $nsPodcast->funding], 'elements' => $nsPodcast->id,
],
[
'name' => 'social',
'elements' => $nsPodcast->social,
],
[
'name' => 'funding',
'elements' => $nsPodcast->funding,
],
]; ];
$platformModel = new PlatformModel(); $platformModel = new PlatformModel();
foreach ($platformTypes as $platformType) { foreach ($platformTypes as $platformType) {
@ -240,10 +230,7 @@ class PodcastImportController extends BaseController
} }
if (count($podcastsPlatformsData) > 1) { if (count($podcastsPlatformsData) > 1) {
$platformModel->createPodcastPlatforms( $platformModel->createPodcastPlatforms($newPodcastId, $podcastsPlatformsData,);
$newPodcastId,
$podcastsPlatformsData,
);
} }
foreach ($nsPodcast->person as $podcastPerson) { foreach ($nsPodcast->person as $podcastPerson) {
@ -262,7 +249,7 @@ class PodcastImportController extends BaseController
'updated_by' => user_id(), 'updated_by' => user_id(),
]); ]);
if (!$newPersonId = $personModel->insert($newPodcastPerson)) { if (! $newPersonId = $personModel->insert($newPodcastPerson)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -271,8 +258,8 @@ class PodcastImportController extends BaseController
} }
// TODO: these checks should be in the taxonomy as default values // TODO: these checks should be in the taxonomy as default values
$podcastPersonGroup = $podcastPerson->attributes()['group'] ?? "Cast"; $podcastPersonGroup = $podcastPerson->attributes()['group'] ?? 'Cast';
$podcastPersonRole = $podcastPerson->attributes()['role'] ?? "Host"; $podcastPersonRole = $podcastPerson->attributes()['role'] ?? 'Host';
$personGroup = ReversedTaxonomy::$taxonomy[(string) $podcastPersonGroup]; $personGroup = ReversedTaxonomy::$taxonomy[(string) $podcastPersonGroup];
@ -280,7 +267,12 @@ class PodcastImportController extends BaseController
$personRoleSlug = $personGroup['roles'][(string) $podcastPersonRole]['slug']; $personRoleSlug = $personGroup['roles'][(string) $podcastPersonRole]['slug'];
$podcastPersonModel = new PersonModel(); $podcastPersonModel = new PersonModel();
if (!$podcastPersonModel->addPodcastPerson($newPodcastId, $newPersonId, $personGroupSlug, $personRoleSlug)) { if (! $podcastPersonModel->addPodcastPerson(
$newPodcastId,
$newPersonId,
$personGroupSlug,
$personRoleSlug
)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -296,30 +288,23 @@ class PodcastImportController extends BaseController
: $numberItems; : $numberItems;
$slugs = []; $slugs = [];
//////////////////////////////////////////////////////////////////
// For each Episode:
for ($itemNumber = 1; $itemNumber <= $lastItem; ++$itemNumber) { for ($itemNumber = 1; $itemNumber <= $lastItem; ++$itemNumber) {
$item = $feed->channel[0]->item[$numberItems - $itemNumber]; $item = $feed->channel[0]->item[$numberItems - $itemNumber];
$nsItunes = $item->children( $nsItunes = $item->children('http://www.itunes.com/dtds/podcast-1.0.dtd',);
'http://www.itunes.com/dtds/podcast-1.0.dtd',
);
$nsPodcast = $item->children( $nsPodcast = $item->children(
'https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md', 'https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md',
); );
$nsContent = $item->children( $nsContent = $item->children('http://purl.org/rss/1.0/modules/content/',);
'http://purl.org/rss/1.0/modules/content/',
);
$slug = slugify( $slug = slugify(
$this->request->getPost('slug_field') === 'title' $this->request->getPost('slug_field') === 'title'
? $item->title ? $item->title
: basename($item->link), : basename($item->link),
); );
if (in_array($slug, $slugs)) { if (in_array($slug, $slugs, true)) {
$slugNumber = 2; $slugNumber = 2;
while (in_array($slug . '-' . $slugNumber, $slugs)) { while (in_array($slug . '-' . $slugNumber, $slugs, true)) {
++$slugNumber; ++$slugNumber;
} }
$slug = $slug . '-' . $slugNumber; $slug = $slug . '-' . $slugNumber;
@ -336,11 +321,7 @@ class PodcastImportController extends BaseController
property_exists($nsItunes, 'image') && $nsItunes->image !== null && property_exists($nsItunes, 'image') && $nsItunes->image !== null &&
$nsItunes->image->attributes()['href'] !== null $nsItunes->image->attributes()['href'] !== null
) { ) {
$episodeImage = new Image( $episodeImage = new Image(download_file((string) $nsItunes->image->attributes()['href'],),);
download_file(
(string) $nsItunes->image->attributes()['href'],
),
);
} else { } else {
$episodeImage = null; $episodeImage = null;
} }
@ -359,19 +340,15 @@ class PodcastImportController extends BaseController
'guid' => $item->guid ?? null, 'guid' => $item->guid ?? null,
'title' => $item->title, 'title' => $item->title,
'slug' => $slug, 'slug' => $slug,
'audio_file' => download_file( 'audio_file' => download_file($item->enclosure->attributes()['url'],),
$item->enclosure->attributes()['url'], 'description_markdown' => $converter->convert($itemDescriptionHtml,),
),
'description_markdown' => $converter->convert(
$itemDescriptionHtml,
),
'description_html' => $itemDescriptionHtml, 'description_html' => $itemDescriptionHtml,
'image' => $episodeImage, 'image' => $episodeImage,
'parental_advisory' => 'parental_advisory' =>
property_exists($nsItunes, 'explicit') && $nsItunes->explicit !== null property_exists($nsItunes, 'explicit') && $nsItunes->explicit !== null
? (in_array((string) $nsItunes->explicit, ['yes', 'true']) ? (in_array((string) $nsItunes->explicit, ['yes', 'true'], true)
? 'explicit' ? 'explicit'
: (in_array((string) $nsItunes->explicit, ['no', 'false']) : (in_array((string) $nsItunes->explicit, ['no', 'false'], true)
? 'clean' ? 'clean'
: null)) : null))
: null, : null,
@ -386,7 +363,10 @@ class PodcastImportController extends BaseController
'type' => property_exists($nsItunes, 'episodeType') && $nsItunes->episodeType !== null 'type' => property_exists($nsItunes, 'episodeType') && $nsItunes->episodeType !== null
? (string) $nsItunes->episodeType ? (string) $nsItunes->episodeType
: 'full', : 'full',
'is_blocked' => property_exists($nsItunes, 'block') && $nsItunes->block !== null && (string) $nsItunes->block === 'yes', 'is_blocked' => property_exists(
$nsItunes,
'block'
) && $nsItunes->block !== null && (string) $nsItunes->block === 'yes',
'location' => $location, 'location' => $location,
'created_by' => user_id(), 'created_by' => user_id(),
'updated_by' => user_id(), 'updated_by' => user_id(),
@ -395,7 +375,7 @@ class PodcastImportController extends BaseController
$episodeModel = new EpisodeModel(); $episodeModel = new EpisodeModel();
if (!($newEpisodeId = $episodeModel->insert($newEpisode, true))) { if (! ($newEpisodeId = $episodeModel->insert($newEpisode, true))) {
// FIXME: What shall we do? // FIXME: What shall we do?
return redirect() return redirect()
->back() ->back()
@ -419,7 +399,7 @@ class PodcastImportController extends BaseController
'updated_by' => user_id(), 'updated_by' => user_id(),
]); ]);
if (!($newPersonId = $personModel->insert($newPerson))) { if (! ($newPersonId = $personModel->insert($newPerson))) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -428,8 +408,8 @@ class PodcastImportController extends BaseController
} }
// TODO: these checks should be in the taxonomy as default values // TODO: these checks should be in the taxonomy as default values
$episodePersonGroup = $episodePerson->attributes()['group'] ?? "Cast"; $episodePersonGroup = $episodePerson->attributes()['group'] ?? 'Cast';
$episodePersonRole = $episodePerson->attributes()['role'] ?? "Host"; $episodePersonRole = $episodePerson->attributes()['role'] ?? 'Host';
$personGroup = ReversedTaxonomy::$taxonomy[(string) $episodePersonGroup]; $personGroup = ReversedTaxonomy::$taxonomy[(string) $episodePersonGroup];
@ -437,7 +417,13 @@ class PodcastImportController extends BaseController
$personRoleSlug = $personGroup['roles'][(string) $episodePersonRole]['slug']; $personRoleSlug = $personGroup['roles'][(string) $episodePersonRole]['slug'];
$episodePersonModel = new PersonModel(); $episodePersonModel = new PersonModel();
if (!$episodePersonModel->addEpisodePerson($newPodcastId, $newEpisodeId, $newPersonId, $personGroupSlug, $personRoleSlug)) { if (! $episodePersonModel->addEpisodePerson(
$newPodcastId,
$newEpisodeId,
$newPersonId,
$personGroupSlug,
$personRoleSlug
)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()

View File

@ -8,17 +8,14 @@
namespace App\Controllers\Admin; namespace App\Controllers\Admin;
use CodeIgniter\HTTP\RedirectResponse;
use App\Entities\Podcast; use App\Entities\Podcast;
use CodeIgniter\Exceptions\PageNotFoundException;
use App\Models\PodcastModel;
use App\Models\PersonModel; use App\Models\PersonModel;
use App\Models\PodcastModel;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\RedirectResponse;
class PodcastPersonController extends BaseController class PodcastPersonController extends BaseController
{ {
/**
* @var Podcast
*/
protected Podcast $podcast; protected Podcast $podcast;
public function _remap(string $method, string ...$params): mixed public function _remap(string $method, string ...$params): mixed
@ -28,12 +25,10 @@ class PodcastPersonController extends BaseController
} }
if ( if (
($this->podcast = (new PodcastModel())->getPodcastById( ($this->podcast = (new PodcastModel())->getPodcastById((int) $params[0],)) !== null
(int) $params[0],
)) !== null
) { ) {
unset($params[0]); unset($params[0]);
return $this->$method(...$params); return $this->{$method}(...$params);
} }
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
@ -45,9 +40,7 @@ class PodcastPersonController extends BaseController
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $this->podcast,
'podcastPersons' => (new PersonModel())->getPodcastPersons( 'podcastPersons' => (new PersonModel())->getPodcastPersons($this->podcast->id,),
$this->podcast->id,
),
'personOptions' => (new PersonModel())->getPersonOptions(), 'personOptions' => (new PersonModel())->getPersonOptions(),
'taxonomyOptions' => (new PersonModel())->getTaxonomyOptions(), 'taxonomyOptions' => (new PersonModel())->getTaxonomyOptions(),
]; ];
@ -63,7 +56,7 @@ class PodcastPersonController extends BaseController
'persons' => 'required', 'persons' => 'required',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -81,10 +74,7 @@ class PodcastPersonController extends BaseController
public function remove(int $personId): RedirectResponse public function remove(int $personId): RedirectResponse
{ {
(new PersonModel())->removePersonFromPodcast( (new PersonModel())->removePersonFromPodcast($this->podcast->id, $personId,);
$this->podcast->id,
$personId,
);
return redirect()->back(); return redirect()->back();
} }

View File

@ -8,33 +8,28 @@
namespace App\Controllers\Admin; namespace App\Controllers\Admin;
use CodeIgniter\HTTP\RedirectResponse;
use App\Entities\Podcast; use App\Entities\Podcast;
use CodeIgniter\Exceptions\PageNotFoundException;
use App\Models\PlatformModel; use App\Models\PlatformModel;
use App\Models\PodcastModel; use App\Models\PodcastModel;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\RedirectResponse;
use Config\Services; use Config\Services;
class PodcastPlatformController extends BaseController class PodcastPlatformController extends BaseController
{ {
/**
* @var Podcast|null
*/
protected ?Podcast $podcast; protected ?Podcast $podcast;
public function _remap(string $method, string ...$params): mixed public function _remap(string $method, string ...$params): mixed
{ {
if (count($params) === 0) { if (count($params) === 0) {
return $this->$method(); return $this->{$method}();
} }
if ( if (
($this->podcast = (new PodcastModel())->getPodcastById( ($this->podcast = (new PodcastModel())->getPodcastById((int) $params[0],)) !== null
(int) $params[0],
)) !== null
) { ) {
unset($params[0]); unset($params[0]);
return $this->$method(...$params); return $this->{$method}(...$params);
} }
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
@ -52,19 +47,17 @@ class PodcastPlatformController extends BaseController
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $this->podcast,
'platformType' => $platformType, 'platformType' => $platformType,
'platforms' => (new PlatformModel())->getPlatformsWithLinks( 'platforms' => (new PlatformModel())->getPlatformsWithLinks($this->podcast->id, $platformType,),
$this->podcast->id,
$platformType,
),
]; ];
replace_breadcrumb_params([0 => $this->podcast->title]); replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/podcast/platforms', $data); return view('admin/podcast/platforms', $data);
} }
public function attemptPlatformsUpdate( public function attemptPlatformsUpdate(string $platformType): RedirectResponse
string $platformType {
): RedirectResponse {
$platformModel = new PlatformModel(); $platformModel = new PlatformModel();
$validation = Services::validation(); $validation = Services::validation();
@ -78,7 +71,7 @@ class PodcastPlatformController extends BaseController
if ($podcastPlatformUrl === null) { if ($podcastPlatformUrl === null) {
continue; continue;
} }
if (!$validation->check($podcastPlatformUrl, 'validate_url')) { if (! $validation->check($podcastPlatformUrl, 'validate_url')) {
continue; continue;
} }
$podcastsPlatformsData[] = [ $podcastsPlatformsData[] = [
@ -88,36 +81,28 @@ class PodcastPlatformController extends BaseController
'link_content' => $podcastPlatform['content'], 'link_content' => $podcastPlatform['content'],
'is_visible' => 'is_visible' =>
array_key_exists('visible', $podcastPlatform) && array_key_exists('visible', $podcastPlatform) &&
$podcastPlatform['visible'] == 'yes', $podcastPlatform['visible'] === 'yes',
'is_on_embeddable_player' => 'is_on_embeddable_player' =>
array_key_exists( array_key_exists(
'on_embeddable_player', 'on_embeddable_player',
$podcastPlatform, $podcastPlatform,
) && $podcastPlatform['on_embeddable_player'] == 'yes', ) && $podcastPlatform['on_embeddable_player'] === 'yes',
]; ];
return redirect() return redirect()
->back() ->back()
->with('message', lang('Platforms.messages.updateSuccess')); ->with('message', lang('Platforms.messages.updateSuccess'));
} }
$platformModel->savePodcastPlatforms( $platformModel->savePodcastPlatforms($this->podcast->id, $platformType, $podcastsPlatformsData,);
$this->podcast->id,
$platformType,
$podcastsPlatformsData,
);
return redirect() return redirect()
->back() ->back()
->with('message', lang('Platforms.messages.updateSuccess')); ->with('message', lang('Platforms.messages.updateSuccess'));
} }
public function removePodcastPlatform( public function removePodcastPlatform(string $platformSlug): RedirectResponse
string $platformSlug {
): RedirectResponse { (new PlatformModel())->removePodcastPlatform($this->podcast->id, $platformSlug,);
(new PlatformModel())->removePodcastPlatform(
$this->podcast->id,
$platformSlug,
);
return redirect() return redirect()
->back() ->back()

View File

@ -8,10 +8,10 @@
namespace App\Controllers\Admin; namespace App\Controllers\Admin;
use CodeIgniter\Exceptions\PageNotFoundException;
use App\Authorization\GroupModel; use App\Authorization\GroupModel;
use App\Entities\User; use App\Entities\User;
use App\Models\UserModel; use App\Models\UserModel;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\RedirectResponse;
use Config\Services; use Config\Services;
@ -22,11 +22,11 @@ class UserController extends BaseController
public function _remap(string $method, string ...$params): mixed public function _remap(string $method, string ...$params): mixed
{ {
if (count($params) === 0) { if (count($params) === 0) {
return $this->$method(); return $this->{$method}();
} }
if ($this->user = (new UserModel())->find($params[0])) { if ($this->user = (new UserModel())->find($params[0])) {
return $this->$method(); return $this->{$method}();
} }
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
@ -34,16 +34,22 @@ class UserController extends BaseController
public function list(): string public function list(): string
{ {
$data = ['users' => (new UserModel())->findAll()]; $data = [
'users' => (new UserModel())->findAll(),
];
return view('admin/user/list', $data); return view('admin/user/list', $data);
} }
public function view(): string public function view(): string
{ {
$data = ['user' => $this->user]; $data = [
'user' => $this->user,
];
replace_breadcrumb_params([0 => $this->user->username]); replace_breadcrumb_params([
0 => $this->user->username,
]);
return view('admin/user/view', $data); return view('admin/user/view', $data);
} }
@ -65,14 +71,16 @@ class UserController extends BaseController
// Validate here first, since some things, // Validate here first, since some things,
// like the password, can only be validated properly here. // like the password, can only be validated properly here.
$rules = array_merge( $rules = array_merge(
$userModel->getValidationRules(['only' => ['username']]), $userModel->getValidationRules([
'only' => ['username'],
]),
[ [
'email' => 'required|valid_email|is_unique[users.email]', 'email' => 'required|valid_email|is_unique[users.email]',
'password' => 'required|strong_password', 'password' => 'required|strong_password',
], ],
); );
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -88,7 +96,7 @@ class UserController extends BaseController
// Force user to reset his password on first connection // Force user to reset his password on first connection
$user->forcePasswordReset(); $user->forcePasswordReset();
if (!$userModel->insert($user)) { if (! $userModel->insert($user)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -98,12 +106,9 @@ class UserController extends BaseController
// Success! // Success!
return redirect() return redirect()
->route('user-list') ->route('user-list')
->with( ->with('message', lang('User.messages.createSuccess', [
'message', 'username' => $user->username,
lang('User.messages.createSuccess', [ ]),);
'username' => $user->username,
]),
);
} }
public function edit(): string public function edit(): string
@ -125,7 +130,9 @@ class UserController extends BaseController
'roleOptions' => $roleOptions, 'roleOptions' => $roleOptions,
]; ];
replace_breadcrumb_params([0 => $this->user->username]); replace_breadcrumb_params([
0 => $this->user->username,
]);
return view('admin/user/edit', $data); return view('admin/user/edit', $data);
} }
@ -139,12 +146,9 @@ class UserController extends BaseController
// Success! // Success!
return redirect() return redirect()
->route('user-list') ->route('user-list')
->with( ->with('message', lang('User.messages.rolesEditSuccess', [
'message', 'username' => $this->user->username,
lang('User.messages.rolesEditSuccess', [ ]),);
'username' => $this->user->username,
]),
);
} }
public function forcePassReset(): RedirectResponse public function forcePassReset(): RedirectResponse
@ -152,7 +156,7 @@ class UserController extends BaseController
$userModel = new UserModel(); $userModel = new UserModel();
$this->user->forcePasswordReset(); $this->user->forcePasswordReset();
if (!$userModel->update($this->user->id, $this->user)) { if (! $userModel->update($this->user->id, $this->user)) {
return redirect() return redirect()
->back() ->back()
->with('errors', $userModel->errors()); ->with('errors', $userModel->errors());
@ -186,7 +190,7 @@ class UserController extends BaseController
// TODO: add ban reason? // TODO: add ban reason?
$this->user->ban(''); $this->user->ban('');
if (!$userModel->update($this->user->id, $this->user)) { if (! $userModel->update($this->user->id, $this->user)) {
return redirect() return redirect()
->back() ->back()
->with('errors', $userModel->errors()); ->with('errors', $userModel->errors());
@ -194,12 +198,9 @@ class UserController extends BaseController
return redirect() return redirect()
->route('user-list') ->route('user-list')
->with( ->with('message', lang('User.messages.banSuccess', [
'message', 'username' => $this->user->username,
lang('User.messages.banSuccess', [ ]),);
'username' => $this->user->username,
]),
);
} }
public function unBan(): RedirectResponse public function unBan(): RedirectResponse
@ -207,7 +208,7 @@ class UserController extends BaseController
$userModel = new UserModel(); $userModel = new UserModel();
$this->user->unBan(); $this->user->unBan();
if (!$userModel->update($this->user->id, $this->user)) { if (! $userModel->update($this->user->id, $this->user)) {
return redirect() return redirect()
->back() ->back()
->with('errors', $userModel->errors()); ->with('errors', $userModel->errors());
@ -215,12 +216,9 @@ class UserController extends BaseController
return redirect() return redirect()
->route('user-list') ->route('user-list')
->with( ->with('message', lang('User.messages.unbanSuccess', [
'message', 'username' => $this->user->username,
lang('User.messages.unbanSuccess', [ ]),);
'username' => $this->user->username,
]),
);
} }
public function delete(): RedirectResponse public function delete(): RedirectResponse
@ -240,11 +238,8 @@ class UserController extends BaseController
return redirect() return redirect()
->back() ->back()
->with( ->with('message', lang('User.messages.deleteSuccess', [
'message', 'username' => $this->user->username,
lang('User.messages.deleteSuccess', [ ]),);
'username' => $this->user->username,
]),
);
} }
} }

View File

@ -8,15 +8,14 @@
namespace App\Controllers; namespace App\Controllers;
use Myth\Auth\Controllers\AuthController as MythAuthController;
use App\Entities\User; use App\Entities\User;
use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\RedirectResponse;
use Myth\Auth\Controllers\AuthController as MythAuthController;
class AuthController extends MythAuthController class AuthController extends MythAuthController
{ {
/** /**
* An array of helpers to be automatically loaded * An array of helpers to be automatically loaded upon class instantiation.
* upon class instantiation.
* *
* @var string[] * @var string[]
*/ */
@ -28,7 +27,7 @@ class AuthController extends MythAuthController
public function attemptRegister(): RedirectResponse public function attemptRegister(): RedirectResponse
{ {
// Check if registration is allowed // Check if registration is allowed
if (!$this->config->allowRegistration) { if (! $this->config->allowRegistration) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -46,7 +45,7 @@ class AuthController extends MythAuthController
'password' => 'required|strong_password', 'password' => 'required|strong_password',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -54,11 +53,7 @@ class AuthController extends MythAuthController
} }
// Save the user // Save the user
$allowedPostFields = array_merge( $allowedPostFields = array_merge(['password'], $this->config->validFields, $this->config->personalFields,);
['password'],
$this->config->validFields,
$this->config->personalFields,
);
$user = new User($this->request->getPost($allowedPostFields)); $user = new User($this->request->getPost($allowedPostFields));
$this->config->requireActivation === null $this->config->requireActivation === null
@ -70,7 +65,7 @@ class AuthController extends MythAuthController
$users = $users->withGroup($this->config->defaultUserGroup); $users = $users->withGroup($this->config->defaultUserGroup);
} }
if (!$users->save($user)) { if (! $users->save($user)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -81,14 +76,11 @@ class AuthController extends MythAuthController
$activator = service('activator'); $activator = service('activator');
$sent = $activator->send($user); $sent = $activator->send($user);
if (!$sent) { if (! $sent) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
->with( ->with('error', $activator->error() ?? lang('Auth.unknownError'),);
'error',
$activator->error() ?? lang('Auth.unknownError'),
);
} }
// Success! // Success!
@ -104,8 +96,7 @@ class AuthController extends MythAuthController
} }
/** /**
* Verifies the code with the email and saves the new password, * Verifies the code with the email and saves the new password, if they all pass validation.
* if they all pass validation.
*/ */
public function attemptReset(): RedirectResponse public function attemptReset(): RedirectResponse
{ {
@ -131,7 +122,7 @@ class AuthController extends MythAuthController
'password' => 'required|strong_password', 'password' => 'required|strong_password',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -143,7 +134,7 @@ class AuthController extends MythAuthController
->where('reset_hash', $this->request->getPost('token')) ->where('reset_hash', $this->request->getPost('token'))
->first(); ->first();
if (is_null($user)) { if ($user === null) {
return redirect() return redirect()
->back() ->back()
->with('error', lang('Auth.forgotNoUser')); ->with('error', lang('Auth.forgotNoUser'));
@ -179,7 +170,7 @@ class AuthController extends MythAuthController
'actor_id' => 'required|numeric', 'actor_id' => 'required|numeric',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()

View File

@ -10,19 +10,16 @@ use Psr\Log\LoggerInterface;
/** /**
* Class BaseController * Class BaseController
* *
* BaseController provides a convenient place for loading components * BaseController provides a convenient place for loading components and performing functions that are needed by all
* and performing functions that are needed by all your controllers. * your controllers. Extend this class in any new controllers: class Home extends BaseController
* Extend this class in any new controllers:
* class Home extends BaseController
* *
* For security be sure to declare any new methods as protected or private. * For security be sure to declare any new methods as protected or private.
*/ */
class BaseController extends Controller class BaseController extends Controller
{ {
/** /**
* An array of helpers to be loaded automatically upon * An array of helpers to be loaded automatically upon class instantiation. These helpers will be available to all
* class instantiation. These helpers will be available * other controllers that extend BaseController.
* to all other controllers that extend BaseController.
* *
* @var string[] * @var string[]
*/ */
@ -38,10 +35,5 @@ class BaseController extends Controller
): void { ): void {
// Do Not Edit This Line // Do Not Edit This Line
parent::initController($request, $response, $logger); parent::initController($request, $response, $logger);
//--------------------------------------------------------------------
// Preload any models, libraries, etc, here.
//--------------------------------------------------------------------
// E.g.: $this->session = \Config\Services::session();
} }
} }

View File

@ -0,0 +1,178 @@
<?php
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
namespace App\Controllers;
use App\Entities\Page;
use App\Models\CreditModel;
use App\Models\PodcastModel;
class CreditsController extends BaseController
{
public function index(): string
{
$locale = service('request')
->getLocale();
$allPodcasts = (new PodcastModel())->findAll();
$cacheName = "page_credits_{$locale}";
if (! ($found = cache($cacheName))) {
$page = new Page([
'title' => lang('Person.credits', [], $locale),
'slug' => 'credits',
'content_markdown' => '',
]);
$allCredits = (new CreditModel())->findAll();
// Unlike the carpenter, we make a tree from a table:
$personGroup = null;
$personId = null;
$personRole = null;
$credits = [];
foreach ($allCredits as $credit) {
if ($personGroup !== $credit->person_group) {
$personGroup = $credit->person_group;
$personId = $credit->person_id;
$personRole = $credit->person_role;
$credits[$personGroup] = [
'group_label' => $credit->group_label,
'persons' => [
$personId => [
'full_name' => $credit->person->full_name,
'thumbnail_url' =>
$credit->person->image->thumbnail_url,
'information_url' =>
$credit->person->information_url,
'roles' => [
$personRole => [
'role_label' => $credit->role_label,
'is_in' => [
[
'link' => $credit->episode_id
? $credit->episode->link
: $credit->podcast->link,
'title' => $credit->episode_id
? (count($allPodcasts) > 1
? "{$credit->podcast->title} "
: '') .
$credit->episode
->title .
episode_numbering(
$credit->episode
->number,
$credit->episode
->season_number,
'text-xs ml-2',
true,
)
: $credit->podcast->title,
],
],
],
],
],
],
];
} elseif ($personId !== $credit->person_id) {
$personId = $credit->person_id;
$personRole = $credit->person_role;
$credits[$personGroup]['persons'][$personId] = [
'full_name' => $credit->person->full_name,
'thumbnail_url' =>
$credit->person->image->thumbnail_url,
'information_url' => $credit->person->information_url,
'roles' => [
$personRole => [
'role_label' => $credit->role_label,
'is_in' => [
[
'link' => $credit->episode_id
? $credit->episode->link
: $credit->podcast->link,
'title' => $credit->episode_id
? (count($allPodcasts) > 1
? "{$credit->podcast->title} "
: '') .
$credit->episode->title .
episode_numbering(
$credit->episode->number,
$credit->episode
->season_number,
'text-xs ml-2',
true,
)
: $credit->podcast->title,
],
],
],
],
];
} elseif ($personRole !== $credit->person_role) {
$personRole = $credit->person_role;
$credits[$personGroup]['persons'][$personId]['roles'][
$personRole
] = [
'role_label' => $credit->role_label,
'is_in' => [
[
'link' => $credit->episode_id
? $credit->episode->link
: $credit->podcast->link,
'title' => $credit->episode_id
? (count($allPodcasts) > 1
? "{$credit->podcast->title} "
: '') .
$credit->episode->title .
episode_numbering(
$credit->episode->number,
$credit->episode->season_number,
'text-xs ml-2',
true,
)
: $credit->podcast->title,
],
],
];
} else {
$credits[$personGroup]['persons'][$personId]['roles'][
$personRole
]['is_in'][] = [
'link' => $credit->episode_id
? $credit->episode->link
: $credit->podcast->link,
'title' => $credit->episode_id
? (count($allPodcasts) > 1
? "{$credit->podcast->title} "
: '') .
$credit->episode->title .
episode_numbering(
$credit->episode->number,
$credit->episode->season_number,
'text-xs ml-2',
true,
)
: $credit->podcast->title,
];
}
}
$data = [
'page' => $page,
'credits' => $credits,
];
$found = view('credits', $data);
cache()
->save($cacheName, $found, DECADE);
}
return $found;
}
}

View File

@ -8,14 +8,14 @@
namespace App\Controllers; namespace App\Controllers;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;
use Analytics\AnalyticsTrait; use Analytics\AnalyticsTrait;
use App\Entities\Episode; use App\Entities\Episode;
use App\Entities\Podcast; use App\Entities\Podcast;
use App\Models\EpisodeModel; use App\Models\EpisodeModel;
use App\Models\PodcastModel; use App\Models\PodcastModel;
use CodeIgniter\Exceptions\PageNotFoundException; use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;
use SimpleXMLElement; use SimpleXMLElement;
class EpisodeController extends BaseController class EpisodeController extends BaseController
@ -33,22 +33,17 @@ class EpisodeController extends BaseController
} }
if ( if (
($this->podcast = (new PodcastModel())->getPodcastByName( ($this->podcast = (new PodcastModel())->getPodcastByName($params[0],)) === null
$params[0],
)) === null
) { ) {
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
} }
if ( if (
($this->episode = (new EpisodeModel())->getEpisodeBySlug( ($this->episode = (new EpisodeModel())->getEpisodeBySlug($this->podcast->id, $params[1],)) !== null
$this->podcast->id,
$params[1],
)) !== null
) { ) {
unset($params[1]); unset($params[1]);
unset($params[0]); unset($params[0]);
return $this->$method(...$params); return $this->{$method}(...$params);
} }
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
@ -57,16 +52,17 @@ class EpisodeController extends BaseController
public function index(): string public function index(): string
{ {
// Prevent analytics hit when authenticated // Prevent analytics hit when authenticated
if (!can_user_interact()) { if (! can_user_interact()) {
$this->registerPodcastWebpageHit($this->episode->podcast_id); $this->registerPodcastWebpageHit($this->episode->podcast_id);
} }
$locale = service('request')->getLocale(); $locale = service('request')
->getLocale();
$cacheName = $cacheName =
"page_podcast#{$this->podcast->id}_episode#{$this->episode->id}_{$locale}" . "page_podcast#{$this->podcast->id}_episode#{$this->episode->id}_{$locale}" .
(can_user_interact() ? '_authenticated' : ''); (can_user_interact() ? '_authenticated' : '');
if (!($cachedView = cache($cacheName))) { if (! ($cachedView = cache($cacheName))) {
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $this->podcast,
'episode' => $this->episode, 'episode' => $this->episode,
@ -92,30 +88,27 @@ class EpisodeController extends BaseController
return $cachedView; return $cachedView;
} }
public function embeddablePlayer( public function embeddablePlayer(string $theme = 'light-transparent'): string
string $theme = 'light-transparent' {
): string {
header('Content-Security-Policy: frame-ancestors https://* http://*'); header('Content-Security-Policy: frame-ancestors https://* http://*');
// Prevent analytics hit when authenticated // Prevent analytics hit when authenticated
if (!can_user_interact()) { if (! can_user_interact()) {
$this->registerPodcastWebpageHit($this->episode->podcast_id); $this->registerPodcastWebpageHit($this->episode->podcast_id);
} }
$session = Services::session(); $session = Services::session();
$session->start(); $session->start();
if (isset($_SERVER['HTTP_REFERER'])) { if (isset($_SERVER['HTTP_REFERER'])) {
$session->set( $session->set('embeddable_player_domain', parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST),);
'embeddable_player_domain',
parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST),
);
} }
$locale = service('request')->getLocale(); $locale = service('request')
->getLocale();
$cacheName = "page_podcast#{$this->podcast->id}_episode#{$this->episode->id}_embeddable_player_{$theme}_{$locale}"; $cacheName = "page_podcast#{$this->podcast->id}_episode#{$this->episode->id}_embeddable_player_{$theme}_{$locale}";
if (!($cachedView = cache($cacheName))) { if (! ($cachedView = cache($cacheName))) {
$theme = EpisodeModel::$themes[$theme]; $theme = EpisodeModel::$themes[$theme];
$data = [ $data = [
@ -157,16 +150,16 @@ class EpisodeController extends BaseController
'width' => 600, 'width' => 600,
'height' => 200, 'height' => 200,
'thumbnail_url' => $this->episode->image->large_url, 'thumbnail_url' => $this->episode->image->large_url,
'thumbnail_width' => config('Images')->largeSize, 'thumbnail_width' => config('Images')
'thumbnail_height' => config('Images')->largeSize, ->largeSize,
'thumbnail_height' => config('Images')
->largeSize,
]); ]);
} }
public function oembedXML(): ResponseInterface public function oembedXML(): ResponseInterface
{ {
$oembed = new SimpleXMLElement( $oembed = new SimpleXMLElement("<?xml version='1.0' encoding='utf-8' standalone='yes'?><oembed></oembed>",);
"<?xml version='1.0' encoding='utf-8' standalone='yes'?><oembed></oembed>",
);
$oembed->addChild('type', 'rich'); $oembed->addChild('type', 'rich');
$oembed->addChild('version', '1.0'); $oembed->addChild('version', '1.0');

View File

@ -8,13 +8,13 @@
namespace App\Controllers; namespace App\Controllers;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Exceptions\PageNotFoundException;
use Opawg\UserAgentsPhp\UserAgentsRSS;
use Exception;
use App\Models\EpisodeModel; use App\Models\EpisodeModel;
use App\Models\PodcastModel; use App\Models\PodcastModel;
use CodeIgniter\Controller; use CodeIgniter\Controller;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\ResponseInterface;
use Exception;
use Opawg\UserAgentsPhp\UserAgentsRSS;
class FeedController extends Controller class FeedController extends Controller
{ {
@ -22,8 +22,9 @@ class FeedController extends Controller
{ {
helper('rss'); helper('rss');
$podcast = (new PodcastModel())->where('name', $podcastName)->first(); $podcast = (new PodcastModel())->where('name', $podcastName)
if (!$podcast) { ->first();
if (! $podcast) {
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
} }
@ -43,7 +44,7 @@ class FeedController extends Controller
$cacheName = $cacheName =
"podcast#{$podcast->id}_feed" . ($service ? "_{$serviceSlug}" : ''); "podcast#{$podcast->id}_feed" . ($service ? "_{$serviceSlug}" : '');
if (!($found = cache($cacheName))) { if (! ($found = cache($cacheName))) {
$found = get_rss_feed($podcast, $serviceSlug); $found = get_rss_feed($podcast, $serviceSlug);
// The page cache is set to expire after next episode publication or a decade by default so it is deleted manually upon podcast update // The page cache is set to expire after next episode publication or a decade by default so it is deleted manually upon podcast update
@ -51,13 +52,14 @@ class FeedController extends Controller
$podcast->id, $podcast->id,
); );
cache()->save( cache()
$cacheName, ->save(
$found, $cacheName,
$secondsToNextUnpublishedEpisode $found,
$secondsToNextUnpublishedEpisode
? $secondsToNextUnpublishedEpisode ? $secondsToNextUnpublishedEpisode
: DECADE, : DECADE,
); );
} }
return $this->response->setXML($found); return $this->response->setXML($found);

View File

@ -13,7 +13,7 @@ use CodeIgniter\HTTP\RedirectResponse;
class HomeController extends BaseController class HomeController extends BaseController
{ {
public function index(): RedirectResponse|string public function index(): RedirectResponse | string
{ {
$model = new PodcastModel(); $model = new PodcastModel();
@ -21,13 +21,13 @@ class HomeController extends BaseController
// check if there's only one podcast to redirect user to it // check if there's only one podcast to redirect user to it
if (count($allPodcasts) === 1) { if (count($allPodcasts) === 1) {
return redirect()->route('podcast-activity', [ return redirect()->route('podcast-activity', [$allPodcasts[0]->name]);
$allPodcasts[0]->name,
]);
} }
// default behavior: list all podcasts on home page // default behavior: list all podcasts on home page
$data = ['podcasts' => $allPodcasts]; $data = [
'podcasts' => $allPodcasts,
];
return view('home', $data); return view('home', $data);
} }
} }

View File

@ -8,20 +8,20 @@
namespace App\Controllers; namespace App\Controllers;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Psr\Log\LoggerInterface;
use Throwable;
use Dotenv\Exception\ValidationException;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\Database\Exceptions\DatabaseException;
use Config\Database;
use App\Entities\User; use App\Entities\User;
use App\Models\UserModel; use App\Models\UserModel;
use CodeIgniter\Controller; use CodeIgniter\Controller;
use CodeIgniter\Database\Exceptions\DatabaseException;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Database;
use Config\Services; use Config\Services;
use Dotenv\Dotenv; use Dotenv\Dotenv;
use Dotenv\Exception\ValidationException;
use Psr\Log\LoggerInterface;
use Throwable;
class InstallController extends Controller class InstallController extends Controller
{ {
@ -43,15 +43,13 @@ class InstallController extends Controller
} }
/** /**
* Every operation goes through this method to handle * Every operation goes through this method to handle the install logic.
* the install logic.
* *
* If all required actions have already been performed, * If all required actions have already been performed, the install route will show a 404 page.
* the install route will show a 404 page.
*/ */
public function index(): string public function index(): string
{ {
if (!file_exists(ROOTPATH . '.env')) { if (! file_exists(ROOTPATH . '.env')) {
// create empty .env file // create empty .env file
try { try {
$envFile = fopen(ROOTPATH . '.env', 'w'); $envFile = fopen(ROOTPATH . '.env', 'w');
@ -69,11 +67,7 @@ class InstallController extends Controller
// Check if the created .env file is writable to continue install process // Check if the created .env file is writable to continue install process
if (is_really_writable(ROOTPATH . '.env')) { if (is_really_writable(ROOTPATH . '.env')) {
try { try {
$dotenv->required([ $dotenv->required(['app.baseURL', 'app.adminGateway', 'app.authGateway']);
'app.baseURL',
'app.adminGateway',
'app.authGateway',
]);
} catch (ValidationException $e) { } catch (ValidationException $e) {
// form to input instance configuration // form to input instance configuration
return $this->instanceConfig(); return $this->instanceConfig();
@ -128,10 +122,8 @@ class InstallController extends Controller
} catch (DatabaseException) { } catch (DatabaseException) {
// Could not connect to the database // Could not connect to the database
// show database config view to fix value // show database config view to fix value
session()->setFlashdata( session()
'error', ->setFlashdata('error', lang('Install.messages.databaseConnectError'),);
lang('Install.messages.databaseConnectError'),
);
return view('install/database_config'); return view('install/database_config');
} }
@ -159,13 +151,9 @@ class InstallController extends Controller
'auth_gateway' => 'required|differs[admin_gateway]', 'auth_gateway' => 'required|differs[admin_gateway]',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->to( ->to((host_url() === null ? config('App') ->baseURL : host_url()) . config('App')->installGateway,)
(host_url() === null
? config('App')->baseURL
: host_url()) . config('App')->installGateway,
)
->withInput() ->withInput()
->with('errors', $this->validator->getErrors()); ->with('errors', $this->validator->getErrors());
} }
@ -183,11 +171,7 @@ class InstallController extends Controller
helper('text'); helper('text');
// redirect to full install url with new baseUrl input // redirect to full install url with new baseUrl input
return redirect()->to( return redirect()->to(reduce_double_slashes($baseUrl . '/' . config('App')->installGateway,),);
reduce_double_slashes(
$baseUrl . '/' . config('App')->installGateway,
),
);
} }
public function databaseConfig(): string public function databaseConfig(): string
@ -204,7 +188,7 @@ class InstallController extends Controller
'db_password' => 'required', 'db_password' => 'required',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -212,16 +196,10 @@ class InstallController extends Controller
} }
self::writeEnv([ self::writeEnv([
'database.default.hostname' => $this->request->getPost( 'database.default.hostname' => $this->request->getPost('db_hostname',),
'db_hostname',
),
'database.default.database' => $this->request->getPost('db_name'), 'database.default.database' => $this->request->getPost('db_name'),
'database.default.username' => $this->request->getPost( 'database.default.username' => $this->request->getPost('db_username',),
'db_username', 'database.default.password' => $this->request->getPost('db_password',),
),
'database.default.password' => $this->request->getPost(
'db_password',
),
'database.default.DBPrefix' => $this->request->getPost('db_prefix'), 'database.default.DBPrefix' => $this->request->getPost('db_prefix'),
]); ]);
@ -239,7 +217,7 @@ class InstallController extends Controller
'cache_handler' => 'required', 'cache_handler' => 'required',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -260,10 +238,14 @@ class InstallController extends Controller
{ {
$migrations = Services::migrations(); $migrations = Services::migrations();
$migrations->setNamespace('Myth\Auth')->latest(); $migrations->setNamespace('Myth\Auth')
$migrations->setNamespace('ActivityPub')->latest(); ->latest();
$migrations->setNamespace('Analytics')->latest(); $migrations->setNamespace('ActivityPub')
$migrations->setNamespace(APP_NAMESPACE)->latest(); ->latest();
$migrations->setNamespace('Analytics')
->latest();
$migrations->setNamespace(APP_NAMESPACE)
->latest();
} }
/** /**
@ -297,14 +279,16 @@ class InstallController extends Controller
// Validate here first, since some things, // Validate here first, since some things,
// like the password, can only be validated properly here. // like the password, can only be validated properly here.
$rules = array_merge( $rules = array_merge(
$userModel->getValidationRules(['only' => ['username']]), $userModel->getValidationRules([
'only' => ['username'],
]),
[ [
'email' => 'required|valid_email|is_unique[users.email]', 'email' => 'required|valid_email|is_unique[users.email]',
'password' => 'required|strong_password', 'password' => 'required|strong_password',
], ],
); );
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -320,7 +304,7 @@ class InstallController extends Controller
$db = Database::connect(); $db = Database::connect();
$db->transStart(); $db->transStart();
if (!($userId = $userModel->insert($user, true))) { if (! ($userId = $userModel->insert($user, true))) {
$db->transRollback(); $db->transRollback();
return redirect() return redirect()
@ -337,7 +321,8 @@ class InstallController extends Controller
// Success! // Success!
// set redirect_url session as admin area to go to after login // set redirect_url session as admin area to go to after login
session()->set('redirect_url', route_to('admin')); session()
->set('redirect_url', route_to('admin'));
return redirect() return redirect()
->route('login') ->route('login')
@ -345,8 +330,7 @@ class InstallController extends Controller
} }
/** /**
* writes config values in .env file * writes config values in .env file overwrites any existing key and appends new ones
* overwrites any existing key and appends new ones
* *
* @param array<string, string> $configData key/value config pairs * @param array<string, string> $configData key/value config pairs
*/ */
@ -357,20 +341,18 @@ class InstallController extends Controller
foreach ($configData as $key => $value) { foreach ($configData as $key => $value) {
$replaced = false; $replaced = false;
$keyVal = $key . '="' . $value . '"' . PHP_EOL; $keyVal = $key . '="' . $value . '"' . PHP_EOL;
$envData = array_map(function ($line) use ( $envData = array_map(
$key, function ($line) use ($key, $keyVal, &$replaced) {
$keyVal, if (str_starts_with($line, (string) $key)) {
&$replaced $replaced = true;
) { return $keyVal;
if (str_starts_with($line, (string) $key)) { }
$replaced = true; return $line;
return $keyVal; },
} $envData
return $line; );
},
$envData);
if (!$replaced) { if (! $replaced) {
$envData[] = $keyVal; $envData[] = $keyVal;
} }
} }

View File

@ -8,7 +8,6 @@
namespace App\Controllers; namespace App\Controllers;
use CodeIgniter\Exceptions\PageNotFoundException;
use ActivityPub\Controllers\NoteController as ActivityPubNoteController; use ActivityPub\Controllers\NoteController as ActivityPubNoteController;
use ActivityPub\Entities\Note as ActivityPubNote; use ActivityPub\Entities\Note as ActivityPubNote;
use Analytics\AnalyticsTrait; use Analytics\AnalyticsTrait;
@ -17,6 +16,7 @@ use App\Entities\Note as CastopodNote;
use App\Entities\Podcast; use App\Entities\Podcast;
use App\Models\EpisodeModel; use App\Models\EpisodeModel;
use App\Models\PodcastModel; use App\Models\PodcastModel;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\URI; use CodeIgniter\HTTP\URI;
use CodeIgniter\I18n\Time; use CodeIgniter\I18n\Time;
@ -26,6 +26,7 @@ class NoteController extends ActivityPubNoteController
use AnalyticsTrait; use AnalyticsTrait;
protected Podcast $podcast; protected Podcast $podcast;
protected Actor $actor; protected Actor $actor;
/** /**
@ -36,9 +37,7 @@ class NoteController extends ActivityPubNoteController
public function _remap(string $method, string ...$params): mixed public function _remap(string $method, string ...$params): mixed
{ {
if ( if (
($this->podcast = (new PodcastModel())->getPodcastByName( ($this->podcast = (new PodcastModel())->getPodcastByName($params[0],)) === null
$params[0],
)) === null
) { ) {
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
} }
@ -47,20 +46,20 @@ class NoteController extends ActivityPubNoteController
if ( if (
count($params) > 1 && count($params) > 1 &&
!($this->note = model('NoteModel')->getNoteById($params[1])) ! ($this->note = model('NoteModel')->getNoteById($params[1]))
) { ) {
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
} }
unset($params[0]); unset($params[0]);
unset($params[1]); unset($params[1]);
return $this->$method(...$params); return $this->{$method}(...$params);
} }
public function view(): string public function view(): string
{ {
// Prevent analytics hit when authenticated // Prevent analytics hit when authenticated
if (!can_user_interact()) { if (! can_user_interact()) {
$this->registerPodcastWebpageHit($this->podcast->id); $this->registerPodcastWebpageHit($this->podcast->id);
} }
@ -69,12 +68,13 @@ class NoteController extends ActivityPubNoteController
array_filter([ array_filter([
'page', 'page',
"note#{$this->note->id}", "note#{$this->note->id}",
service('request')->getLocale(), service('request')
->getLocale(),
can_user_interact() ? '_authenticated' : null, can_user_interact() ? '_authenticated' : null,
]), ]),
); );
if (!($cachedView = cache($cacheName))) { if (! ($cachedView = cache($cacheName))) {
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $this->podcast,
'actor' => $this->actor, 'actor' => $this->actor,
@ -102,7 +102,7 @@ class NoteController extends ActivityPubNoteController
'episode_url' => 'valid_url|permit_empty', 'episode_url' => 'valid_url|permit_empty',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -122,10 +122,7 @@ class NoteController extends ActivityPubNoteController
if ( if (
$episodeUri && $episodeUri &&
($params = extract_params_from_episode_uri(new URI($episodeUri))) && ($params = extract_params_from_episode_uri(new URI($episodeUri))) &&
($episode = (new EpisodeModel())->getEpisodeBySlug( ($episode = (new EpisodeModel())->getEpisodeBySlug($params['podcastName'], $params['episodeSlug'],))
$params['podcastName'],
$params['episodeSlug'],
))
) { ) {
$newNote->episode_id = $episode->id; $newNote->episode_id = $episode->id;
} }
@ -133,11 +130,8 @@ class NoteController extends ActivityPubNoteController
$newNote->message = $message; $newNote->message = $message;
if ( if (
!model('NoteModel')->addNote( ! model('NoteModel')
$newNote, ->addNote($newNote, ! (bool) $newNote->episode_id, true,)
!(bool) $newNote->episode_id,
true,
)
) { ) {
return redirect() return redirect()
->back() ->back()
@ -155,7 +149,7 @@ class NoteController extends ActivityPubNoteController
'message' => 'required|max_length[500]', 'message' => 'required|max_length[500]',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -170,7 +164,7 @@ class NoteController extends ActivityPubNoteController
'created_by' => user_id(), 'created_by' => user_id(),
]); ]);
if (!model('NoteModel')->addReply($newNote)) { if (! model('NoteModel')->addReply($newNote)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -183,10 +177,7 @@ class NoteController extends ActivityPubNoteController
public function attemptFavourite(): RedirectResponse public function attemptFavourite(): RedirectResponse
{ {
model('FavouriteModel')->toggleFavourite( model('FavouriteModel')->toggleFavourite(interact_as_actor(), $this->note,);
interact_as_actor(),
$this->note,
);
return redirect()->back(); return redirect()->back();
} }
@ -204,7 +195,7 @@ class NoteController extends ActivityPubNoteController
'action' => 'required|in_list[favourite,reblog,reply]', 'action' => 'required|in_list[favourite,reblog,reply]',
]; ];
if (!$this->validate($rules)) { if (! $this->validate($rules)) {
return redirect() return redirect()
->back() ->back()
->withInput() ->withInput()
@ -231,21 +222,16 @@ class NoteController extends ActivityPubNoteController
public function remoteAction(string $action): string public function remoteAction(string $action): string
{ {
// Prevent analytics hit when authenticated // Prevent analytics hit when authenticated
if (!can_user_interact()) { if (! can_user_interact()) {
$this->registerPodcastWebpageHit($this->podcast->id); $this->registerPodcastWebpageHit($this->podcast->id);
} }
$cacheName = implode( $cacheName = implode(
'_', '_',
array_filter([ array_filter(['page', "note#{$this->note->id}", "remote_{$action}", service('request') ->getLocale()]),
'page',
"note#{$this->note->id}",
"remote_{$action}",
service('request')->getLocale(),
]),
); );
if (!($cachedView = cache($cacheName))) { if (! ($cachedView = cache($cacheName))) {
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $this->podcast,
'actor' => $this->actor, 'actor' => $this->actor,

View File

@ -9,25 +9,23 @@
namespace App\Controllers; namespace App\Controllers;
use App\Entities\Page; use App\Entities\Page;
use CodeIgniter\Exceptions\PageNotFoundException;
use App\Models\PageModel; use App\Models\PageModel;
use App\Models\CreditModel; use CodeIgniter\Exceptions\PageNotFoundException;
use App\Models\PodcastModel;
class PageController extends BaseController class PageController extends BaseController
{ {
protected ?Page $page; protected Page $page;
public function _remap(string $method, string ...$params): mixed public function _remap(string $method, string ...$params): mixed
{ {
if (count($params) === 0) { if (count($params) === 0) {
return $this->$method(); throw PageNotFoundException::forPageNotFound();
} }
if ( if (
$this->page = (new PageModel())->where('slug', $params[0])->first() $this->page = (new PageModel())->where('slug', $params[0])->first()
) { ) {
return $this->$method(); return $this->{$method}();
} }
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
@ -36,7 +34,7 @@ class PageController extends BaseController
public function index(): string public function index(): string
{ {
$cacheName = "page-{$this->page->slug}"; $cacheName = "page-{$this->page->slug}";
if (!($found = cache($cacheName))) { if (! ($found = cache($cacheName))) {
$data = [ $data = [
'page' => $this->page, 'page' => $this->page,
]; ];
@ -44,167 +42,8 @@ class PageController extends BaseController
$found = view('page', $data); $found = view('page', $data);
// The page cache is set to a decade so it is deleted manually upon page update // The page cache is set to a decade so it is deleted manually upon page update
cache()->save($cacheName, $found, DECADE); cache()
} ->save($cacheName, $found, DECADE);
return $found;
}
public function credits(): string
{
$locale = service('request')->getLocale();
$allPodcasts = (new PodcastModel())->findAll();
$cacheName = "page_credits_{$locale}";
if (!($found = cache($cacheName))) {
$page = new Page([
'title' => lang('Person.credits', [], $locale),
'slug' => 'credits',
'content_markdown' => '',
]);
$allCredits = (new CreditModel())->findAll();
// Unlike the carpenter, we make a tree from a table:
$personGroup = null;
$personId = null;
$personRole = null;
$credits = [];
foreach ($allCredits as $credit) {
if ($personGroup !== $credit->person_group) {
$personGroup = $credit->person_group;
$personId = $credit->person_id;
$personRole = $credit->person_role;
$credits[$personGroup] = [
'group_label' => $credit->group_label,
'persons' => [
$personId => [
'full_name' => $credit->person->full_name,
'thumbnail_url' =>
$credit->person->image->thumbnail_url,
'information_url' =>
$credit->person->information_url,
'roles' => [
$personRole => [
'role_label' => $credit->role_label,
'is_in' => [
[
'link' => $credit->episode_id
? $credit->episode->link
: $credit->podcast->link,
'title' => $credit->episode_id
? (count($allPodcasts) > 1
? "{$credit->podcast->title} "
: '') .
$credit->episode
->title .
episode_numbering(
$credit->episode
->number,
$credit->episode
->season_number,
'text-xs ml-2',
true,
)
: $credit->podcast->title,
],
],
],
],
],
],
];
} elseif ($personId !== $credit->person_id) {
$personId = $credit->person_id;
$personRole = $credit->person_role;
$credits[$personGroup]['persons'][$personId] = [
'full_name' => $credit->person->full_name,
'thumbnail_url' =>
$credit->person->image->thumbnail_url,
'information_url' => $credit->person->information_url,
'roles' => [
$personRole => [
'role_label' => $credit->role_label,
'is_in' => [
[
'link' => $credit->episode_id
? $credit->episode->link
: $credit->podcast->link,
'title' => $credit->episode_id
? (count($allPodcasts) > 1
? "{$credit->podcast->title} "
: '') .
$credit->episode->title .
episode_numbering(
$credit->episode->number,
$credit->episode
->season_number,
'text-xs ml-2',
true,
)
: $credit->podcast->title,
],
],
],
],
];
} elseif ($personRole !== $credit->person_role) {
$personRole = $credit->person_role;
$credits[$personGroup]['persons'][$personId]['roles'][
$personRole
] = [
'role_label' => $credit->role_label,
'is_in' => [
[
'link' => $credit->episode_id
? $credit->episode->link
: $credit->podcast->link,
'title' => $credit->episode_id
? (count($allPodcasts) > 1
? "{$credit->podcast->title} "
: '') .
$credit->episode->title .
episode_numbering(
$credit->episode->number,
$credit->episode->season_number,
'text-xs ml-2',
true,
)
: $credit->podcast->title,
],
],
];
} else {
$credits[$personGroup]['persons'][$personId]['roles'][
$personRole
]['is_in'][] = [
'link' => $credit->episode_id
? $credit->episode->link
: $credit->podcast->link,
'title' => $credit->episode_id
? (count($allPodcasts) > 1
? "{$credit->podcast->title} "
: '') .
$credit->episode->title .
episode_numbering(
$credit->episode->number,
$credit->episode->season_number,
'text-xs ml-2',
true,
)
: $credit->podcast->title,
];
}
}
$data = [
'page' => $page,
'credits' => $credits,
];
$found = view('credits', $data);
cache()->save($cacheName, $found, DECADE);
} }
return $found; return $found;

View File

@ -8,9 +8,9 @@
namespace App\Controllers; namespace App\Controllers;
use CodeIgniter\HTTP\ResponseInterface;
use App\Models\PlatformModel; use App\Models\PlatformModel;
use CodeIgniter\Controller; use CodeIgniter\Controller;
use CodeIgniter\HTTP\ResponseInterface;
/* /*
* Provide public access to all platforms so that they can be exported * Provide public access to all platforms so that they can be exported

View File

@ -8,20 +8,17 @@
namespace App\Controllers; namespace App\Controllers;
use CodeIgniter\Exceptions\PageNotFoundException;
use Analytics\AnalyticsTrait; use Analytics\AnalyticsTrait;
use App\Entities\Podcast; use App\Entities\Podcast;
use App\Models\EpisodeModel; use App\Models\EpisodeModel;
use App\Models\PodcastModel;
use App\Models\NoteModel; use App\Models\NoteModel;
use App\Models\PodcastModel;
use CodeIgniter\Exceptions\PageNotFoundException;
class PodcastController extends BaseController class PodcastController extends BaseController
{ {
use AnalyticsTrait; use AnalyticsTrait;
/**
* @var Podcast
*/
protected Podcast $podcast; protected Podcast $podcast;
public function _remap(string $method, string ...$params): mixed public function _remap(string $method, string ...$params): mixed
@ -31,12 +28,10 @@ class PodcastController extends BaseController
} }
if ( if (
($this->podcast = (new PodcastModel())->getPodcastByName( ($this->podcast = (new PodcastModel())->getPodcastByName($params[0],)) !== null
$params[0],
)) !== null
) { ) {
unset($params[0]); unset($params[0]);
return $this->$method(...$params); return $this->{$method}(...$params);
} }
throw PageNotFoundException::forPageNotFound(); throw PageNotFoundException::forPageNotFound();
@ -45,7 +40,7 @@ class PodcastController extends BaseController
public function activity(): string public function activity(): string
{ {
// Prevent analytics hit when authenticated // Prevent analytics hit when authenticated
if (!can_user_interact()) { if (! can_user_interact()) {
$this->registerPodcastWebpageHit($this->podcast->id); $this->registerPodcastWebpageHit($this->podcast->id);
} }
@ -55,17 +50,16 @@ class PodcastController extends BaseController
'page', 'page',
"podcast#{$this->podcast->id}", "podcast#{$this->podcast->id}",
'activity', 'activity',
service('request')->getLocale(), service('request')
->getLocale(),
can_user_interact() ? '_authenticated' : null, can_user_interact() ? '_authenticated' : null,
]), ]),
); );
if (!($cachedView = cache($cacheName))) { if (! ($cachedView = cache($cacheName))) {
$data = [ $data = [
'podcast' => $this->podcast, 'podcast' => $this->podcast,
'notes' => (new NoteModel())->getActorPublishedNotes( 'notes' => (new NoteModel())->getActorPublishedNotes($this->podcast->actor_id,),
$this->podcast->actor_id,
),
]; ];
// if user is logged in then send to the authenticated activity view // if user is logged in then send to the authenticated activity view
@ -85,21 +79,19 @@ class PodcastController extends BaseController
public function episodes(): string public function episodes(): string
{ {
// Prevent analytics hit when authenticated // Prevent analytics hit when authenticated
if (!can_user_interact()) { if (! can_user_interact()) {
$this->registerPodcastWebpageHit($this->podcast->id); $this->registerPodcastWebpageHit($this->podcast->id);
} }
$yearQuery = $this->request->getGet('year'); $yearQuery = $this->request->getGet('year');
$seasonQuery = $this->request->getGet('season'); $seasonQuery = $this->request->getGet('season');
if (!$yearQuery && !$seasonQuery) { if (! $yearQuery && ! $seasonQuery) {
$defaultQuery = (new PodcastModel())->getDefaultQuery( $defaultQuery = (new PodcastModel())->getDefaultQuery($this->podcast->id,);
$this->podcast->id,
);
if ($defaultQuery) { if ($defaultQuery) {
if ($defaultQuery['type'] == 'season') { if ($defaultQuery['type'] === 'season') {
$seasonQuery = $defaultQuery['data']['season_number']; $seasonQuery = $defaultQuery['data']['season_number'];
} elseif ($defaultQuery['type'] == 'year') { } elseif ($defaultQuery['type'] === 'year') {
$yearQuery = $defaultQuery['data']['year']; $yearQuery = $defaultQuery['data']['year'];
} }
} }
@ -113,12 +105,13 @@ class PodcastController extends BaseController
'episodes', 'episodes',
$yearQuery ? 'year' . $yearQuery : null, $yearQuery ? 'year' . $yearQuery : null,
$seasonQuery ? 'season' . $seasonQuery : null, $seasonQuery ? 'season' . $seasonQuery : null,
service('request')->getLocale(), service('request')
->getLocale(),
can_user_interact() ? '_authenticated' : null, can_user_interact() ? '_authenticated' : null,
]), ]),
); );
if (!($cachedView = cache($cacheName))) { if (! ($cachedView = cache($cacheName))) {
// Build navigation array // Build navigation array
$podcastModel = new PodcastModel(); $podcastModel = new PodcastModel();
$years = $podcastModel->getYears($this->podcast->id); $years = $podcastModel->getYears($this->podcast->id);

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class AddAddPodcastsPlatforms * Class AddAddPodcastsPlatforms Creates podcasts_platforms table in database
* Creates podcasts_platforms table in database
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class AddCategories * Class AddCategories Creates categories table in database
* Creates categories table in database
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class AddLanguages * Class AddLanguages Creates languages table in database
* Creates languages table in database
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class AddPodcasts * Class AddPodcasts Creates podcasts table in database
* Creates podcasts table in database
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -190,13 +189,7 @@ class AddPodcasts extends Migration
// TODO: remove name in favor of username from actor // TODO: remove name in favor of username from actor
$this->forge->addUniqueKey('name'); $this->forge->addUniqueKey('name');
$this->forge->addUniqueKey('actor_id'); $this->forge->addUniqueKey('actor_id');
$this->forge->addForeignKey( $this->forge->addForeignKey('actor_id', 'activitypub_actors', 'id', '', 'CASCADE',);
'actor_id',
'activitypub_actors',
'id',
'',
'CASCADE',
);
$this->forge->addForeignKey('category_id', 'categories', 'id'); $this->forge->addForeignKey('category_id', 'categories', 'id');
$this->forge->addForeignKey('language_code', 'languages', 'code'); $this->forge->addForeignKey('language_code', 'languages', 'code');
$this->forge->addForeignKey('created_by', 'users', 'id'); $this->forge->addForeignKey('created_by', 'users', 'id');

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class AddEpisodes * Class AddEpisodes Creates episodes table in database
* Creates episodes table in database
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -186,13 +185,7 @@ class AddEpisodes extends Migration
]); ]);
$this->forge->addPrimaryKey('id'); $this->forge->addPrimaryKey('id');
$this->forge->addUniqueKey(['podcast_id', 'slug']); $this->forge->addUniqueKey(['podcast_id', 'slug']);
$this->forge->addForeignKey( $this->forge->addForeignKey('podcast_id', 'podcasts', 'id', '', 'CASCADE',);
'podcast_id',
'podcasts',
'id',
'',
'CASCADE',
);
$this->forge->addForeignKey('created_by', 'users', 'id'); $this->forge->addForeignKey('created_by', 'users', 'id');
$this->forge->addForeignKey('updated_by', 'users', 'id'); $this->forge->addForeignKey('updated_by', 'users', 'id');
$this->forge->createTable('episodes'); $this->forge->createTable('episodes');

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class AddSoundbites * Class AddSoundbites Creates soundbites table in database
* Creates soundbites table in database
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -64,20 +63,8 @@ class AddSoundbites extends Migration
]); ]);
$this->forge->addKey('id', true); $this->forge->addKey('id', true);
$this->forge->addUniqueKey(['episode_id', 'start_time', 'duration']); $this->forge->addUniqueKey(['episode_id', 'start_time', 'duration']);
$this->forge->addForeignKey( $this->forge->addForeignKey('podcast_id', 'podcasts', 'id', '', 'CASCADE',);
'podcast_id', $this->forge->addForeignKey('episode_id', 'episodes', 'id', '', 'CASCADE',);
'podcasts',
'id',
'',
'CASCADE',
);
$this->forge->addForeignKey(
'episode_id',
'episodes',
'id',
'',
'CASCADE',
);
$this->forge->addForeignKey('created_by', 'users', 'id'); $this->forge->addForeignKey('created_by', 'users', 'id');
$this->forge->addForeignKey('updated_by', 'users', 'id'); $this->forge->addForeignKey('updated_by', 'users', 'id');
$this->forge->createTable('soundbites'); $this->forge->createTable('soundbites');

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class AddPlatforms * Class AddPlatforms Creates platforms table in database
* Creates platforms table in database
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -42,9 +41,7 @@ class AddPlatforms extends Migration
], ],
]); ]);
$this->forge->addField('`created_at` timestamp NOT NULL DEFAULT NOW()'); $this->forge->addField('`created_at` timestamp NOT NULL DEFAULT NOW()');
$this->forge->addField( $this->forge->addField('`updated_at` timestamp NOT NULL DEFAULT NOW() ON UPDATE NOW()',);
'`updated_at` timestamp NOT NULL DEFAULT NOW() ON UPDATE NOW()',
);
$this->forge->addPrimaryKey('slug'); $this->forge->addPrimaryKey('slug');
$this->forge->createTable('platforms'); $this->forge->createTable('platforms');
} }

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class AddPodcastUsers * Class AddPodcastUsers Creates podcast_users table in database
* Creates podcast_users table in database
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -33,20 +32,8 @@ class AddPodcastsUsers extends Migration
]); ]);
$this->forge->addPrimaryKey(['user_id', 'podcast_id']); $this->forge->addPrimaryKey(['user_id', 'podcast_id']);
$this->forge->addForeignKey('user_id', 'users', 'id', '', 'CASCADE'); $this->forge->addForeignKey('user_id', 'users', 'id', '', 'CASCADE');
$this->forge->addForeignKey( $this->forge->addForeignKey('podcast_id', 'podcasts', 'id', '', 'CASCADE',);
'podcast_id', $this->forge->addForeignKey('group_id', 'auth_groups', 'id', '', 'CASCADE',);
'podcasts',
'id',
'',
'CASCADE',
);
$this->forge->addForeignKey(
'group_id',
'auth_groups',
'id',
'',
'CASCADE',
);
$this->forge->createTable('podcasts_users'); $this->forge->createTable('podcasts_users');
} }

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class AddPages * Class AddPages Creates pages table in database
* Creates pages table in database
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class AddPodcastsCategories * Class AddPodcastsCategories Creates podcasts_categories table in database
* Creates podcasts_categories table in database
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -28,20 +27,8 @@ class AddPodcastsCategories extends Migration
], ],
]); ]);
$this->forge->addPrimaryKey(['podcast_id', 'category_id']); $this->forge->addPrimaryKey(['podcast_id', 'category_id']);
$this->forge->addForeignKey( $this->forge->addForeignKey('podcast_id', 'podcasts', 'id', '', 'CASCADE',);
'podcast_id', $this->forge->addForeignKey('category_id', 'categories', 'id', '', 'CASCADE',);
'podcasts',
'id',
'',
'CASCADE',
);
$this->forge->addForeignKey(
'category_id',
'categories',
'id',
'',
'CASCADE',
);
$this->forge->createTable('podcasts_categories'); $this->forge->createTable('podcasts_categories');
} }

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class Persons * Class Persons Creates persons table in database
* Creates persons table in database
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class AddPodcastsPersons * Class AddPodcastsPersons Creates podcasts_persons table in database
* Creates podcasts_persons table in database
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -41,26 +40,9 @@ class AddPodcastsPersons extends Migration
], ],
]); ]);
$this->forge->addKey('id', true); $this->forge->addKey('id', true);
$this->forge->addUniqueKey([ $this->forge->addUniqueKey(['podcast_id', 'person_id', 'person_group', 'person_role']);
'podcast_id', $this->forge->addForeignKey('podcast_id', 'podcasts', 'id', '', 'CASCADE',);
'person_id', $this->forge->addForeignKey('person_id', 'persons', 'id', '', 'CASCADE',);
'person_group',
'person_role',
]);
$this->forge->addForeignKey(
'podcast_id',
'podcasts',
'id',
'',
'CASCADE',
);
$this->forge->addForeignKey(
'person_id',
'persons',
'id',
'',
'CASCADE',
);
$this->forge->createTable('podcasts_persons'); $this->forge->createTable('podcasts_persons');
} }

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class AddEpisodesPersons * Class AddEpisodesPersons Creates episodes_persons table in database
* Creates episodes_persons table in database
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -45,34 +44,10 @@ class AddEpisodesPersons extends Migration
], ],
]); ]);
$this->forge->addPrimaryKey('id'); $this->forge->addPrimaryKey('id');
$this->forge->addUniqueKey([ $this->forge->addUniqueKey(['podcast_id', 'episode_id', 'person_id', 'person_group', 'person_role']);
'podcast_id', $this->forge->addForeignKey('podcast_id', 'podcasts', 'id', '', 'CASCADE',);
'episode_id', $this->forge->addForeignKey('episode_id', 'episodes', 'id', '', 'CASCADE',);
'person_id', $this->forge->addForeignKey('person_id', 'persons', 'id', '', 'CASCADE',);
'person_group',
'person_role',
]);
$this->forge->addForeignKey(
'podcast_id',
'podcasts',
'id',
'',
'CASCADE',
);
$this->forge->addForeignKey(
'episode_id',
'episodes',
'id',
'',
'CASCADE',
);
$this->forge->addForeignKey(
'person_id',
'persons',
'id',
'',
'CASCADE',
);
$this->forge->createTable('episodes_persons'); $this->forge->createTable('episodes_persons');
} }

View File

@ -1,8 +1,8 @@
<?php <?php
/** /**
* Class AddCreditView * Class AddCreditView Creates Credit View in database
* Creates Credit View in database *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/ * @link https://castopod.org/
@ -22,7 +22,7 @@ class AddCreditView extends Migration
$podcastPersonsTable = $this->db->prefixTable('podcasts_persons'); $podcastPersonsTable = $this->db->prefixTable('podcasts_persons');
$episodePersonsTable = $this->db->prefixTable('episodes_persons'); $episodePersonsTable = $this->db->prefixTable('episodes_persons');
$episodesTable = $this->db->prefixTable('episodes'); $episodesTable = $this->db->prefixTable('episodes');
$createQuery = <<<EOD $createQuery = <<<CODE_SAMPLE
CREATE VIEW `{$viewName}` AS CREATE VIEW `{$viewName}` AS
SELECT `person_group`, `person_id`, `full_name`, `person_role`, `podcast_id`, NULL AS `episode_id` FROM `{$podcastPersonsTable}` SELECT `person_group`, `person_id`, `full_name`, `person_role`, `podcast_id`, NULL AS `episode_id` FROM `{$podcastPersonsTable}`
INNER JOIN `{$personsTable}` INNER JOIN `{$personsTable}`
@ -35,7 +35,7 @@ class AddCreditView extends Migration
ON (`episode_id`=`{$episodesTable}`.`id`) ON (`episode_id`=`{$episodesTable}`.`id`)
WHERE `{$episodesTable}`.published_at <= NOW() WHERE `{$episodesTable}`.published_at <= NOW()
ORDER BY `person_group`, `full_name`, `person_role`, `podcast_id`, `episode_id`; ORDER BY `person_group`, `full_name`, `person_role`, `podcast_id`, `episode_id`;
EOD; CODE_SAMPLE;
$this->db->query($createQuery); $this->db->query($createQuery);
} }

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class AddEpisodeIdToNotes * Class AddEpisodeIdToNotes Adds episode_id field to activitypub_notes table in database
* Adds episode_id field to activitypub_notes table in database
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -19,20 +18,17 @@ class AddEpisodeIdToNotes extends Migration
{ {
$prefix = $this->db->getPrefix(); $prefix = $this->db->getPrefix();
$createQuery = <<<SQL $createQuery = <<<CODE_SAMPLE
ALTER TABLE {$prefix}activitypub_notes ALTER TABLE {$prefix}activitypub_notes
ADD COLUMN `episode_id` INT UNSIGNED NULL AFTER `replies_count`, ADD COLUMN `episode_id` INT UNSIGNED NULL AFTER `replies_count`,
ADD FOREIGN KEY {$prefix}activitypub_notes_episode_id_foreign(episode_id) REFERENCES {$prefix}episodes(id) ON DELETE CASCADE; ADD FOREIGN KEY {$prefix}activitypub_notes_episode_id_foreign(episode_id) REFERENCES {$prefix}episodes(id) ON DELETE CASCADE;
SQL; CODE_SAMPLE;
$this->db->query($createQuery); $this->db->query($createQuery);
} }
public function down(): void public function down(): void
{ {
$this->forge->dropForeignKey( $this->forge->dropForeignKey('activitypub_notes', 'activitypub_notes_episode_id_foreign',);
'activitypub_notes',
'activitypub_notes_episode_id_foreign',
);
$this->forge->dropColumn('activitypub_notes', 'episode_id'); $this->forge->dropColumn('activitypub_notes', 'episode_id');
} }
} }

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class AddCreatedByToNotes * Class AddCreatedByToNotes Adds created_by field to activitypub_notes table in database
* Adds created_by field to activitypub_notes table in database
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -19,20 +18,17 @@ class AddCreatedByToNotes extends Migration
{ {
$prefix = $this->db->getPrefix(); $prefix = $this->db->getPrefix();
$createQuery = <<<SQL $createQuery = <<<CODE_SAMPLE
ALTER TABLE {$prefix}activitypub_notes ALTER TABLE {$prefix}activitypub_notes
ADD COLUMN `created_by` INT UNSIGNED AFTER `episode_id`, ADD COLUMN `created_by` INT UNSIGNED AFTER `episode_id`,
ADD FOREIGN KEY {$prefix}activitypub_notes_created_by_foreign(created_by) REFERENCES {$prefix}users(id) ON DELETE CASCADE; ADD FOREIGN KEY {$prefix}activitypub_notes_created_by_foreign(created_by) REFERENCES {$prefix}users(id) ON DELETE CASCADE;
SQL; CODE_SAMPLE;
$this->db->query($createQuery); $this->db->query($createQuery);
} }
public function down(): void public function down(): void
{ {
$this->forge->dropForeignKey( $this->forge->dropForeignKey('activitypub_notes', 'activitypub_notes_created_by_foreign',);
'activitypub_notes',
'activitypub_notes_created_by_foreign',
);
$this->forge->dropColumn('activitypub_notes', 'created_by'); $this->forge->dropColumn('activitypub_notes', 'created_by');
} }
} }

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class AppSeeder * Class AppSeeder Calls all required seeders for castopod to work properly
* Calls all required seeders for castopod to work properly
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class PermissionSeeder * Class PermissionSeeder Inserts permissions
* Inserts permissions
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -31,15 +30,10 @@ class AuthSeeder extends Seeder
], ],
]; ];
/** Build permissions array as a list of: /**
* Build permissions array as a list of:
* *
* ``` * ``` context => [ [action, description], [action, description], ... ] ```
* context => [
* [action, description],
* [action, description],
* ...
* ]
* ```
* *
* @var array<string, array<string, string|array>[]> * @var array<string, array<string, string|array>[]>
*/ */
@ -281,10 +275,7 @@ class AuthSeeder extends Seeder
foreach ($action['has_permission'] as $role) { foreach ($action['has_permission'] as $role) {
// link permission to specified groups // link permission to specified groups
$dataGroupsPermissions[] = [ $dataGroupsPermissions[] = [
'group_id' => $this->getGroupIdByName( 'group_id' => $this->getGroupIdByName($role, $dataGroups,),
$role,
$dataGroups,
),
'permission_id' => $permissionId, 'permission_id' => $permissionId,
]; ];
} }
@ -304,10 +295,11 @@ class AuthSeeder extends Seeder
->ignore(true) ->ignore(true)
->insertBatch($dataGroupsPermissions); ->insertBatch($dataGroupsPermissions);
} }
/** /**
* @param array<string, string|int>[] $dataGroups * @param array<string, string|int>[] $dataGroups
*/ */
static function getGroupIdByName(string $name, array $dataGroups): ?int public static function getGroupIdByName(string $name, array $dataGroups): ?int
{ {
foreach ($dataGroups as $group) { foreach ($dataGroups as $group) {
if ($group['name'] === $name) { if ($group['name'] === $name) {

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class CategorySeeder * Class CategorySeeder Inserts values in categories table in database
* Inserts values in categories table in database
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class FakePodcastsAnalyticsSeeder * Class FakePodcastsAnalyticsSeeder Inserts Fake Analytics in the database
* Inserts Fake Analytics in the database
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -11,12 +10,12 @@
namespace App\Database\Seeds; namespace App\Database\Seeds;
use GeoIp2\Database\Reader;
use GeoIp2\Exception\AddressNotFoundException;
use App\Models\PodcastModel;
use App\Models\EpisodeModel; use App\Models\EpisodeModel;
use App\Models\PodcastModel;
use CodeIgniter\Database\Seeder; use CodeIgniter\Database\Seeder;
use GeoIp2\Database\Reader;
use GeoIp2\Exception\AddressNotFoundException;
class FakePodcastsAnalyticsSeeder extends Seeder class FakePodcastsAnalyticsSeeder extends Seeder
{ {
@ -25,9 +24,7 @@ class FakePodcastsAnalyticsSeeder extends Seeder
$podcast = (new PodcastModel())->first(); $podcast = (new PodcastModel())->first();
$jsonUserAgents = json_decode( $jsonUserAgents = json_decode(
file_get_contents( file_get_contents('https://raw.githubusercontent.com/opawg/user-agents/master/src/user-agents.json',),
'https://raw.githubusercontent.com/opawg/user-agents/master/src/user-agents.json',
),
true, true,
512, 512,
JSON_THROW_ON_ERROR, JSON_THROW_ON_ERROR,
@ -66,9 +63,7 @@ class FakePodcastsAnalyticsSeeder extends Seeder
]) ])
->findAll(); ->findAll();
foreach ($episodes as $episode) { foreach ($episodes as $episode) {
$age = floor( $age = floor(($date - strtotime($episode->published_at)) / 86400,);
($date - strtotime($episode->published_at)) / 86400,
);
$probability1 = (int) floor(exp(3 - $age / 40)) + 1; $probability1 = (int) floor(exp(3 - $age / 40)) + 1;
for ( for (
@ -102,10 +97,7 @@ class FakePodcastsAnalyticsSeeder extends Seeder
'.' . '.' .
rand(0, 255); rand(0, 255);
$cityReader = new Reader( $cityReader = new Reader(WRITEPATH . 'uploads/GeoLite2-City/GeoLite2-City.mmdb',);
WRITEPATH .
'uploads/GeoLite2-City/GeoLite2-City.mmdb',
);
$countryCode = 'N/A'; $countryCode = 'N/A';
$regionCode = 'N/A'; $regionCode = 'N/A';

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class FakeWebsiteAnalyticsSeeder * Class FakeWebsiteAnalyticsSeeder Inserts Fake Analytics in the database
* Inserts Fake Analytics in the database
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -11,8 +10,8 @@
namespace App\Database\Seeds; namespace App\Database\Seeds;
use App\Models\PodcastModel;
use App\Models\EpisodeModel; use App\Models\EpisodeModel;
use App\Models\PodcastModel;
use CodeIgniter\Database\Seeder; use CodeIgniter\Database\Seeder;
@ -203,9 +202,7 @@ class FakeWebsiteAnalyticsSeeder extends Seeder
]) ])
->findAll(); ->findAll();
foreach ($episodes as $episode) { foreach ($episodes as $episode) {
$age = floor( $age = floor(($date - strtotime($episode->published_at)) / 86400,);
($date - strtotime($episode->published_at)) / 86400,
);
$probability1 = (int) floor(exp(3 - $age / 40)) + 1; $probability1 = (int) floor(exp(3 - $age / 40)) + 1;
for ( for (

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class LanguageSeeder * Class LanguageSeeder Inserts values in languages table in database
* Inserts values in languages table in database
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,8 +9,7 @@
*/ */
/** /**
* From https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes * From https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes (cc) Creative Commons Attribution-ShareAlike 3.0
* (cc) Creative Commons Attribution-ShareAlike 3.0
* 2020-06-07 * 2020-06-07
*/ */
@ -24,29 +22,50 @@ class LanguageSeeder extends Seeder
public function run(): void public function run(): void
{ {
$data = [ $data = [
['code' => 'aa', 'native_name' => 'Afaraf'], [
'code' => 'aa',
'native_name' => 'Afaraf',
],
[ [
'code' => 'ab', 'code' => 'ab',
'native_name' => 'аҧсуа бызшәа, аҧсшәа', 'native_name' => 'аҧсуа бызшәа, аҧсшәа',
], ],
['code' => 'ae', 'native_name' => 'avesta'], [
'code' => 'ae',
'native_name' => 'avesta',
],
[ [
'code' => 'af', 'code' => 'af',
'native_name' => 'Afrikaans', 'native_name' => 'Afrikaans',
], ],
['code' => 'ak', 'native_name' => 'Akan'], [
['code' => 'am', 'native_name' => 'አማርኛ'], 'code' => 'ak',
'native_name' => 'Akan',
],
[
'code' => 'am',
'native_name' => 'አማርኛ',
],
[ [
'code' => 'an', 'code' => 'an',
'native_name' => 'aragonés', 'native_name' => 'aragonés',
], ],
['code' => 'ar', 'native_name' => 'العربية'], [
['code' => 'as', 'native_name' => 'অসমীয়া'], 'code' => 'ar',
'native_name' => 'العربية',
],
[
'code' => 'as',
'native_name' => 'অসমীয়া',
],
[ [
'code' => 'av', 'code' => 'av',
'native_name' => 'авар мацӀ, магӀарул мацӀ', 'native_name' => 'авар мацӀ, магӀарул мацӀ',
], ],
['code' => 'ay', 'native_name' => 'aymar aru'], [
'code' => 'ay',
'native_name' => 'aymar aru',
],
[ [
'code' => 'az', 'code' => 'az',
'native_name' => 'azərbaycan dili', 'native_name' => 'azərbaycan dili',
@ -67,14 +86,26 @@ class LanguageSeeder extends Seeder
'code' => 'bh', 'code' => 'bh',
'native_name' => 'भोजपुरी', 'native_name' => 'भोजपुरी',
], ],
['code' => 'bi', 'native_name' => 'Bislama'], [
'code' => 'bi',
'native_name' => 'Bislama',
],
[ [
'code' => 'bm', 'code' => 'bm',
'native_name' => 'bamanankan', 'native_name' => 'bamanankan',
], ],
['code' => 'bn', 'native_name' => 'বাংলা'], [
['code' => 'bo', 'native_name' => 'བོད་ཡིག'], 'code' => 'bn',
['code' => 'br', 'native_name' => 'brezhoneg'], 'native_name' => 'বাংলা',
],
[
'code' => 'bo',
'native_name' => 'བོད་ཡིག',
],
[
'code' => 'br',
'native_name' => 'brezhoneg',
],
[ [
'code' => 'bs', 'code' => 'bs',
'native_name' => 'bosanski jezik', 'native_name' => 'bosanski jezik',
@ -87,12 +118,18 @@ class LanguageSeeder extends Seeder
'code' => 'ce', 'code' => 'ce',
'native_name' => 'нохчийн мотт', 'native_name' => 'нохчийн мотт',
], ],
['code' => 'ch', 'native_name' => 'Chamoru'], [
'code' => 'ch',
'native_name' => 'Chamoru',
],
[ [
'code' => 'co', 'code' => 'co',
'native_name' => 'corsu, lingua corsa', 'native_name' => 'corsu, lingua corsa',
], ],
['code' => 'cr', 'native_name' => 'ᓀᐦᐃᔭᐍᐏᐣ'], [
'code' => 'cr',
'native_name' => 'ᓀᐦᐃᔭᐍᐏᐣ',
],
[ [
'code' => 'cs', 'code' => 'cs',
'native_name' => 'čeština, český jazyk', 'native_name' => 'čeština, český jazyk',
@ -105,20 +142,38 @@ class LanguageSeeder extends Seeder
'code' => 'cv', 'code' => 'cv',
'native_name' => 'чӑваш чӗлхи', 'native_name' => 'чӑваш чӗлхи',
], ],
['code' => 'cy', 'native_name' => 'Cymraeg'], [
['code' => 'da', 'native_name' => 'dansk'], 'code' => 'cy',
['code' => 'de', 'native_name' => 'Deutsch'], 'native_name' => 'Cymraeg',
],
[
'code' => 'da',
'native_name' => 'dansk',
],
[
'code' => 'de',
'native_name' => 'Deutsch',
],
[ [
'code' => 'dv', 'code' => 'dv',
'native_name' => 'ދިވެހި', 'native_name' => 'ދިވެހި',
], ],
['code' => 'dz', 'native_name' => 'རྫོང་ཁ'], [
['code' => 'ee', 'native_name' => 'Eʋegbe'], 'code' => 'dz',
'native_name' => 'རྫོང་ཁ',
],
[
'code' => 'ee',
'native_name' => 'Eʋegbe',
],
[ [
'code' => 'el', 'code' => 'el',
'native_name' => 'ελληνικά', 'native_name' => 'ελληνικά',
], ],
['code' => 'en', 'native_name' => 'English'], [
'code' => 'en',
'native_name' => 'English',
],
[ [
'code' => 'eo', 'code' => 'eo',
'native_name' => 'Esperanto', 'native_name' => 'Esperanto',
@ -135,7 +190,10 @@ class LanguageSeeder extends Seeder
'code' => 'eu', 'code' => 'eu',
'native_name' => 'euskara, euskera', 'native_name' => 'euskara, euskera',
], ],
['code' => 'fa', 'native_name' => 'فارسی'], [
'code' => 'fa',
'native_name' => 'فارسی',
],
[ [
'code' => 'ff', 'code' => 'ff',
'native_name' => 'Fulfulde, Pulaar, Pular', 'native_name' => 'Fulfulde, Pulaar, Pular',
@ -148,7 +206,10 @@ class LanguageSeeder extends Seeder
'code' => 'fj', 'code' => 'fj',
'native_name' => 'vosa Vakaviti', 'native_name' => 'vosa Vakaviti',
], ],
['code' => 'fo', 'native_name' => 'føroyskt'], [
'code' => 'fo',
'native_name' => 'føroyskt',
],
[ [
'code' => 'fr', 'code' => 'fr',
'native_name' => 'français, langue française', 'native_name' => 'français, langue française',
@ -157,14 +218,26 @@ class LanguageSeeder extends Seeder
'code' => 'fy', 'code' => 'fy',
'native_name' => 'Frysk', 'native_name' => 'Frysk',
], ],
['code' => 'ga', 'native_name' => 'Gaeilge'], [
'code' => 'ga',
'native_name' => 'Gaeilge',
],
[ [
'code' => 'gd', 'code' => 'gd',
'native_name' => 'Gàidhlig', 'native_name' => 'Gàidhlig',
], ],
['code' => 'gl', 'native_name' => 'Galego'], [
['code' => 'gn', 'native_name' => "Avañe'ẽ"], 'code' => 'gl',
['code' => 'gu', 'native_name' => 'ગુજરાતી'], 'native_name' => 'Galego',
],
[
'code' => 'gn',
'native_name' => "Avañe'ẽ",
],
[
'code' => 'gu',
'native_name' => 'ગુજરાતી',
],
[ [
'code' => 'gv', 'code' => 'gv',
'native_name' => 'Gaelg, Gailck', 'native_name' => 'Gaelg, Gailck',
@ -173,7 +246,10 @@ class LanguageSeeder extends Seeder
'code' => 'ha', 'code' => 'ha',
'native_name' => '(Hausa) هَوُسَ', 'native_name' => '(Hausa) هَوُسَ',
], ],
['code' => 'he', 'native_name' => 'עברית'], [
'code' => 'he',
'native_name' => 'עברית',
],
[ [
'code' => 'hi', 'code' => 'hi',
'native_name' => 'हिन्दी, हिंदी', 'native_name' => 'हिन्दी, हिंदी',
@ -190,9 +266,18 @@ class LanguageSeeder extends Seeder
'code' => 'ht', 'code' => 'ht',
'native_name' => 'Kreyòl ayisyen', 'native_name' => 'Kreyòl ayisyen',
], ],
['code' => 'hu', 'native_name' => 'magyar'], [
['code' => 'hy', 'native_name' => 'Հայերեն'], 'code' => 'hu',
['code' => 'hz', 'native_name' => 'Otjiherero'], 'native_name' => 'magyar',
],
[
'code' => 'hy',
'native_name' => 'Հայերեն',
],
[
'code' => 'hz',
'native_name' => 'Otjiherero',
],
[ [
'code' => 'ia', 'code' => 'ia',
'native_name' => 'Interlingua', 'native_name' => 'Interlingua',
@ -206,7 +291,10 @@ class LanguageSeeder extends Seeder
'native_name' => 'native_name' =>
'(originally:) Occidental, (after WWII:) Interlingue', '(originally:) Occidental, (after WWII:) Interlingue',
], ],
['code' => 'ig', 'native_name' => 'Asụsụ Igbo'], [
'code' => 'ig',
'native_name' => 'Asụsụ Igbo',
],
[ [
'code' => 'ii', 'code' => 'ii',
'native_name' => 'ꆈꌠ꒿ Nuosuhxop', 'native_name' => 'ꆈꌠ꒿ Nuosuhxop',
@ -215,13 +303,22 @@ class LanguageSeeder extends Seeder
'code' => 'ik', 'code' => 'ik',
'native_name' => 'Iñupiaq, Iñupiatun', 'native_name' => 'Iñupiaq, Iñupiatun',
], ],
['code' => 'io', 'native_name' => 'Ido'], [
'code' => 'io',
'native_name' => 'Ido',
],
[ [
'code' => 'is', 'code' => 'is',
'native_name' => 'Íslenska', 'native_name' => 'Íslenska',
], ],
['code' => 'it', 'native_name' => 'Italiano'], [
['code' => 'iu', 'native_name' => 'ᐃᓄᒃᑎᑐᑦ'], 'code' => 'it',
'native_name' => 'Italiano',
],
[
'code' => 'iu',
'native_name' => 'ᐃᓄᒃᑎᑐᑦ',
],
[ [
'code' => 'ja', 'code' => 'ja',
'native_name' => '日本語 (にほんご)', 'native_name' => '日本語 (にほんご)',
@ -230,8 +327,14 @@ class LanguageSeeder extends Seeder
'code' => 'jv', 'code' => 'jv',
'native_name' => 'ꦧꦱꦗꦮ, Basa Jawa', 'native_name' => 'ꦧꦱꦗꦮ, Basa Jawa',
], ],
['code' => 'ka', 'native_name' => 'ქართული'], [
['code' => 'kg', 'native_name' => 'Kikongo'], 'code' => 'ka',
'native_name' => 'ქართული',
],
[
'code' => 'kg',
'native_name' => 'Kikongo',
],
[ [
'code' => 'ki', 'code' => 'ki',
'native_name' => 'Gĩkũyũ', 'native_name' => 'Gĩkũyũ',
@ -240,7 +343,10 @@ class LanguageSeeder extends Seeder
'code' => 'kj', 'code' => 'kj',
'native_name' => 'Kuanyama', 'native_name' => 'Kuanyama',
], ],
['code' => 'kk', 'native_name' => 'қазақ тілі'], [
'code' => 'kk',
'native_name' => 'қазақ тілі',
],
[ [
'code' => 'kl', 'code' => 'kl',
'native_name' => 'kalaallisut, kalaallit oqaasii', 'native_name' => 'kalaallisut, kalaallit oqaasii',
@ -249,9 +355,18 @@ class LanguageSeeder extends Seeder
'code' => 'km', 'code' => 'km',
'native_name' => 'ខ្មែរ, ខេមរភាសា, ភាសាខ្មែរ', 'native_name' => 'ខ្មែរ, ខេមរភាសា, ភាសាខ្មែរ',
], ],
['code' => 'kn', 'native_name' => 'ಕನ್ನಡ'], [
['code' => 'ko', 'native_name' => '한국어'], 'code' => 'kn',
['code' => 'kr', 'native_name' => 'Kanuri'], 'native_name' => 'ಕನ್ನಡ',
],
[
'code' => 'ko',
'native_name' => '한국어',
],
[
'code' => 'kr',
'native_name' => 'Kanuri',
],
[ [
'code' => 'ks', 'code' => 'ks',
'native_name' => 'कश्मीरी, كشميري‎', 'native_name' => 'कश्मीरी, كشميري‎',
@ -260,8 +375,14 @@ class LanguageSeeder extends Seeder
'code' => 'ku', 'code' => 'ku',
'native_name' => 'Kurdî, کوردی‎', 'native_name' => 'Kurdî, کوردی‎',
], ],
['code' => 'kv', 'native_name' => 'коми кыв'], [
['code' => 'kw', 'native_name' => 'Kernewek'], 'code' => 'kv',
'native_name' => 'коми кыв',
],
[
'code' => 'kw',
'native_name' => 'Kernewek',
],
[ [
'code' => 'ky', 'code' => 'ky',
'native_name' => 'Кыргызча, Кыргыз тили', 'native_name' => 'Кыргызча, Кыргыз тили',
@ -274,13 +395,22 @@ class LanguageSeeder extends Seeder
'code' => 'lb', 'code' => 'lb',
'native_name' => 'Lëtzebuergesch', 'native_name' => 'Lëtzebuergesch',
], ],
['code' => 'lg', 'native_name' => 'Luganda'], [
'code' => 'lg',
'native_name' => 'Luganda',
],
[ [
'code' => 'li', 'code' => 'li',
'native_name' => 'Limburgs', 'native_name' => 'Limburgs',
], ],
['code' => 'ln', 'native_name' => 'Lingála'], [
['code' => 'lo', 'native_name' => 'ພາສາລາວ'], 'code' => 'ln',
'native_name' => 'Lingála',
],
[
'code' => 'lo',
'native_name' => 'ພາສາລາວ',
],
[ [
'code' => 'lt', 'code' => 'lt',
'native_name' => 'lietuvių kalba', 'native_name' => 'lietuvių kalba',
@ -309,18 +439,30 @@ class LanguageSeeder extends Seeder
'code' => 'mk', 'code' => 'mk',
'native_name' => 'македонски јазик', 'native_name' => 'македонски јазик',
], ],
['code' => 'ml', 'native_name' => 'മലയാളം'], [
'code' => 'ml',
'native_name' => 'മലയാളം',
],
[ [
'code' => 'mn', 'code' => 'mn',
'native_name' => 'Монгол хэл', 'native_name' => 'Монгол хэл',
], ],
['code' => 'mr', 'native_name' => 'मराठी'], [
'code' => 'mr',
'native_name' => 'मराठी',
],
[ [
'code' => 'ms', 'code' => 'ms',
'native_name' => 'Bahasa Melayu, بهاس ملايو‎', 'native_name' => 'Bahasa Melayu, بهاس ملايو‎',
], ],
['code' => 'mt', 'native_name' => 'Malti'], [
['code' => 'my', 'native_name' => 'ဗမာစာ'], 'code' => 'mt',
'native_name' => 'Malti',
],
[
'code' => 'my',
'native_name' => 'ဗမာစာ',
],
[ [
'code' => 'na', 'code' => 'na',
'native_name' => 'Dorerin Naoero', 'native_name' => 'Dorerin Naoero',
@ -333,8 +475,14 @@ class LanguageSeeder extends Seeder
'code' => 'nd', 'code' => 'nd',
'native_name' => 'isiNdebele', 'native_name' => 'isiNdebele',
], ],
['code' => 'ne', 'native_name' => 'नेपाली'], [
['code' => 'ng', 'native_name' => 'Owambo'], 'code' => 'ne',
'native_name' => 'नेपाली',
],
[
'code' => 'ng',
'native_name' => 'Owambo',
],
[ [
'code' => 'nl', 'code' => 'nl',
'native_name' => 'Nederlands, Vlaams', 'native_name' => 'Nederlands, Vlaams',
@ -343,7 +491,10 @@ class LanguageSeeder extends Seeder
'code' => 'nn', 'code' => 'nn',
'native_name' => 'Norsk Nynorsk', 'native_name' => 'Norsk Nynorsk',
], ],
['code' => 'no', 'native_name' => 'Norsk'], [
'code' => 'no',
'native_name' => 'Norsk',
],
[ [
'code' => 'nr', 'code' => 'nr',
'native_name' => 'isiNdebele', 'native_name' => 'isiNdebele',
@ -360,12 +511,18 @@ class LanguageSeeder extends Seeder
'code' => 'oc', 'code' => 'oc',
'native_name' => 'occitan, lenga dòc', 'native_name' => 'occitan, lenga dòc',
], ],
['code' => 'oj', 'native_name' => 'ᐊᓂᔑᓈᐯᒧᐎᓐ'], [
'code' => 'oj',
'native_name' => 'ᐊᓂᔑᓈᐯᒧᐎᓐ',
],
[ [
'code' => 'om', 'code' => 'om',
'native_name' => 'Afaan Oromoo', 'native_name' => 'Afaan Oromoo',
], ],
['code' => 'or', 'native_name' => 'ଓଡ଼ିଆ'], [
'code' => 'or',
'native_name' => 'ଓଡ଼ିଆ',
],
[ [
'code' => 'os', 'code' => 'os',
'native_name' => 'ирон æвзаг', 'native_name' => 'ирон æвзаг',
@ -374,7 +531,10 @@ class LanguageSeeder extends Seeder
'code' => 'pa', 'code' => 'pa',
'native_name' => 'ਪੰਜਾਬੀ, پنجابی‎', 'native_name' => 'ਪੰਜਾਬੀ, پنجابی‎',
], ],
['code' => 'pi', 'native_name' => 'पालि, पाळि'], [
'code' => 'pi',
'native_name' => 'पालि, पाळि',
],
[ [
'code' => 'pl', 'code' => 'pl',
'native_name' => 'język polski, polszczyzna', 'native_name' => 'język polski, polszczyzna',
@ -395,12 +555,18 @@ class LanguageSeeder extends Seeder
'code' => 'rm', 'code' => 'rm',
'native_name' => 'Rumantsch Grischun', 'native_name' => 'Rumantsch Grischun',
], ],
['code' => 'rn', 'native_name' => 'Ikirundi'], [
'code' => 'rn',
'native_name' => 'Ikirundi',
],
[ [
'code' => 'ro', 'code' => 'ro',
'native_name' => 'Română', 'native_name' => 'Română',
], ],
['code' => 'ru', 'native_name' => 'русский'], [
'code' => 'ru',
'native_name' => 'русский',
],
[ [
'code' => 'rw', 'code' => 'rw',
'native_name' => 'Ikinyarwanda', 'native_name' => 'Ikinyarwanda',
@ -409,7 +575,10 @@ class LanguageSeeder extends Seeder
'code' => 'sa', 'code' => 'sa',
'native_name' => 'संस्कृतम्', 'native_name' => 'संस्कृतम्',
], ],
['code' => 'sc', 'native_name' => 'sardu'], [
'code' => 'sc',
'native_name' => 'sardu',
],
[ [
'code' => 'sd', 'code' => 'sd',
'native_name' => 'सिन्धी, سنڌي، سندھی‎', 'native_name' => 'सिन्धी, سنڌي، سندھی‎',
@ -438,17 +607,26 @@ class LanguageSeeder extends Seeder
'code' => 'sm', 'code' => 'sm',
'native_name' => "gagana fa'a Samoa", 'native_name' => "gagana fa'a Samoa",
], ],
['code' => 'sn', 'native_name' => 'chiShona'], [
'code' => 'sn',
'native_name' => 'chiShona',
],
[ [
'code' => 'so', 'code' => 'so',
'native_name' => 'Soomaaliga, af Soomaali', 'native_name' => 'Soomaaliga, af Soomaali',
], ],
['code' => 'sq', 'native_name' => 'Shqip'], [
'code' => 'sq',
'native_name' => 'Shqip',
],
[ [
'code' => 'sr', 'code' => 'sr',
'native_name' => 'српски језик', 'native_name' => 'српски језик',
], ],
['code' => 'ss', 'native_name' => 'SiSwati'], [
'code' => 'ss',
'native_name' => 'SiSwati',
],
[ [
'code' => 'st', 'code' => 'st',
'native_name' => 'Sesotho', 'native_name' => 'Sesotho',
@ -457,16 +635,34 @@ class LanguageSeeder extends Seeder
'code' => 'su', 'code' => 'su',
'native_name' => 'Basa Sunda', 'native_name' => 'Basa Sunda',
], ],
['code' => 'sv', 'native_name' => 'Svenska'], [
['code' => 'sw', 'native_name' => 'Kiswahili'], 'code' => 'sv',
['code' => 'ta', 'native_name' => 'தமிழ்'], 'native_name' => 'Svenska',
['code' => 'te', 'native_name' => 'తెలుగు'], ],
[
'code' => 'sw',
'native_name' => 'Kiswahili',
],
[
'code' => 'ta',
'native_name' => 'தமிழ்',
],
[
'code' => 'te',
'native_name' => 'తెలుగు',
],
[ [
'code' => 'tg', 'code' => 'tg',
'native_name' => 'тоҷикӣ, toçikī, تاجیکی‎', 'native_name' => 'тоҷикӣ, toçikī, تاجیکی‎',
], ],
['code' => 'th', 'native_name' => 'ไทย'], [
['code' => 'ti', 'native_name' => 'ትግርኛ'], 'code' => 'th',
'native_name' => 'ไทย',
],
[
'code' => 'ti',
'native_name' => 'ትግርኛ',
],
[ [
'code' => 'tk', 'code' => 'tk',
'native_name' => 'Türkmen, Түркмен', 'native_name' => 'Türkmen, Түркмен',
@ -475,18 +671,30 @@ class LanguageSeeder extends Seeder
'code' => 'tl', 'code' => 'tl',
'native_name' => 'Wikang Tagalog', 'native_name' => 'Wikang Tagalog',
], ],
['code' => 'tn', 'native_name' => 'Setswana'], [
'code' => 'tn',
'native_name' => 'Setswana',
],
[ [
'code' => 'to', 'code' => 'to',
'native_name' => 'Faka Tonga', 'native_name' => 'Faka Tonga',
], ],
['code' => 'tr', 'native_name' => 'Türkçe'], [
['code' => 'ts', 'native_name' => 'Xitsonga'], 'code' => 'tr',
'native_name' => 'Türkçe',
],
[
'code' => 'ts',
'native_name' => 'Xitsonga',
],
[ [
'code' => 'tt', 'code' => 'tt',
'native_name' => 'татар теле, tatar tele', 'native_name' => 'татар теле, tatar tele',
], ],
['code' => 'tw', 'native_name' => 'Twi'], [
'code' => 'tw',
'native_name' => 'Twi',
],
[ [
'code' => 'ty', 'code' => 'ty',
'native_name' => 'Reo Tahiti', 'native_name' => 'Reo Tahiti',
@ -499,22 +707,46 @@ class LanguageSeeder extends Seeder
'code' => 'uk', 'code' => 'uk',
'native_name' => 'Українська', 'native_name' => 'Українська',
], ],
['code' => 'ur', 'native_name' => 'اردو'], [
'code' => 'ur',
'native_name' => 'اردو',
],
[ [
'code' => 'uz', 'code' => 'uz',
'native_name' => 'Oʻzbek, Ўзбек, أۇزبېك‎', 'native_name' => 'Oʻzbek, Ўзбек, أۇزبېك‎',
], ],
['code' => 've', 'native_name' => 'Tshivenḓa'], [
'code' => 've',
'native_name' => 'Tshivenḓa',
],
[ [
'code' => 'vi', 'code' => 'vi',
'native_name' => 'Tiếng Việt', 'native_name' => 'Tiếng Việt',
], ],
['code' => 'vo', 'native_name' => 'Volapük'], [
['code' => 'wa', 'native_name' => 'Walon'], 'code' => 'vo',
['code' => 'wo', 'native_name' => 'Wollof'], 'native_name' => 'Volapük',
['code' => 'xh', 'native_name' => 'isiXhosa'], ],
['code' => 'yi', 'native_name' => 'ייִדיש'], [
['code' => 'yo', 'native_name' => 'Yorùbá'], 'code' => 'wa',
'native_name' => 'Walon',
],
[
'code' => 'wo',
'native_name' => 'Wollof',
],
[
'code' => 'xh',
'native_name' => 'isiXhosa',
],
[
'code' => 'yi',
'native_name' => 'ייִדיש',
],
[
'code' => 'yo',
'native_name' => 'Yorùbá',
],
[ [
'code' => 'za', 'code' => 'za',
'native_name' => 'Saɯ cueŋƅ, Saw cuengh', 'native_name' => 'Saɯ cueŋƅ, Saw cuengh',
@ -523,7 +755,10 @@ class LanguageSeeder extends Seeder
'code' => 'zh', 'code' => 'zh',
'native_name' => '中文 (Zhōngwén), 汉语, 漢語', 'native_name' => '中文 (Zhōngwén), 汉语, 漢語',
], ],
['code' => 'zu', 'native_name' => 'isiZulu'], [
'code' => 'zu',
'native_name' => 'isiZulu',
],
]; ];
$this->db $this->db

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class PlatformsSeeder * Class PlatformsSeeder Inserts values in platforms table in database
* Inserts values in platforms table in database
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3

View File

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Class TestSeeder * Class TestSeeder Inserts a superadmin user in the database
* Inserts a superadmin user in the database
* *
* @copyright 2020 Podlibre * @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -17,21 +16,24 @@ class TestSeeder extends Seeder
{ {
public function run(): void public function run(): void
{ {
/** Inserts an active user with the following credentials: /**
* username: admin * Inserts an active user with the following credentials: username: admin password: AGUehL3P
* password: AGUehL3P
*/ */
$this->db->table('users')->insert([ $this->db->table('users')
'id' => 1, ->insert([
'username' => 'admin', 'id' => 1,
'email' => 'admin@example.com', 'username' => 'admin',
'password_hash' => 'email' => 'admin@example.com',
'$2y$10$TXJEHX/djW8jtzgpDVf7dOOCGo5rv1uqtAYWdwwwkttQcDkAeB2.6', 'password_hash' =>
'active' => 1, '$2y$10$TXJEHX/djW8jtzgpDVf7dOOCGo5rv1uqtAYWdwwwkttQcDkAeB2.6',
]); 'active' => 1,
]);
$this->db $this->db
->table('auth_groups_users') ->table('auth_groups_users')
->insert(['group_id' => 1, 'user_id' => 1]); ->insert([
'group_id' => 1,
'user_id' => 1,
]);
} }
} }

View File

@ -19,6 +19,7 @@ use RuntimeException;
class Actor extends ActivityPubActor class Actor extends ActivityPubActor
{ {
protected ?Podcast $podcast = null; protected ?Podcast $podcast = null;
protected bool $is_podcast; protected bool $is_podcast;
public function getIsPodcast(): bool public function getIsPodcast(): bool
@ -29,15 +30,11 @@ class Actor extends ActivityPubActor
public function getPodcast(): ?Podcast public function getPodcast(): ?Podcast
{ {
if ($this->id === null) { if ($this->id === null) {
throw new RuntimeException( throw new RuntimeException('Podcast id must be set before getting associated podcast.',);
'Podcast id must be set before getting associated podcast.',
);
} }
if ($this->podcast === null) { if ($this->podcast === null) {
$this->podcast = (new PodcastModel())->getPodcastByActorId( $this->podcast = (new PodcastModel())->getPodcastByActorId($this->id,);
$this->id,
);
} }
return $this->podcast; return $this->podcast;

View File

@ -34,7 +34,7 @@ class Category extends Entity
'google_category' => 'string', 'google_category' => 'string',
]; ];
public function getParent(): ?Category public function getParent(): ?self
{ {
if ($this->parent_id === null) { if ($this->parent_id === null) {
return null; return null;

View File

@ -8,11 +8,11 @@
namespace App\Entities; namespace App\Entities;
use RuntimeException; use App\Models\EpisodeModel;
use App\Models\PersonModel; use App\Models\PersonModel;
use App\Models\PodcastModel; use App\Models\PodcastModel;
use App\Models\EpisodeModel;
use CodeIgniter\Entity\Entity; use CodeIgniter\Entity\Entity;
use RuntimeException;
/** /**
* @property int $podcast_id * @property int $podcast_id
@ -30,9 +30,13 @@ use CodeIgniter\Entity\Entity;
class Credit extends Entity class Credit extends Entity
{ {
protected ?Person $person = null; protected ?Person $person = null;
protected ?Podcast $podcast = null; protected ?Podcast $podcast = null;
protected ?Episode $episode = null; protected ?Episode $episode = null;
protected string $group_label; protected string $group_label;
protected string $role_label; protected string $role_label;
/** /**
@ -50,15 +54,11 @@ class Credit extends Entity
public function getPerson(): ?Person public function getPerson(): ?Person
{ {
if ($this->person_id === null) { if ($this->person_id === null) {
throw new RuntimeException( throw new RuntimeException('Credit must have person_id before getting person.',);
'Credit must have person_id before getting person.',
);
} }
if ($this->person === null) { if ($this->person === null) {
$this->person = (new PersonModel())->getPersonById( $this->person = (new PersonModel())->getPersonById($this->person_id,);
$this->person_id,
);
} }
return $this->person; return $this->person;
@ -67,15 +67,11 @@ class Credit extends Entity
public function getPodcast(): ?Podcast public function getPodcast(): ?Podcast
{ {
if ($this->podcast_id === null) { if ($this->podcast_id === null) {
throw new RuntimeException( throw new RuntimeException('Credit must have podcast_id before getting podcast.',);
'Credit must have podcast_id before getting podcast.',
);
} }
if ($this->podcast === null) { if ($this->podcast === null) {
$this->podcast = (new PodcastModel())->getPodcastById( $this->podcast = (new PodcastModel())->getPodcastById($this->podcast_id,);
$this->podcast_id,
);
} }
return $this->podcast; return $this->podcast;
@ -84,16 +80,11 @@ class Credit extends Entity
public function getEpisode(): ?Episode public function getEpisode(): ?Episode
{ {
if ($this->episode_id === null) { if ($this->episode_id === null) {
throw new RuntimeException( throw new RuntimeException('Credit must have episode_id before getting episode.',);
'Credit must have episode_id before getting episode.',
);
} }
if ($this->episode === null) { if ($this->episode === null) {
$this->episode = (new EpisodeModel())->getPublishedEpisodeById( $this->episode = (new EpisodeModel())->getPublishedEpisodeById($this->podcast_id, $this->episode_id,);
$this->podcast_id,
$this->episode_id,
);
} }
return $this->episode; return $this->episode;
@ -118,8 +109,6 @@ class Credit extends Entity
return ''; return '';
} }
return lang( return lang("PersonsTaxonomy.persons.{$this->person_group}.roles.{$this->person_role}.label",);
"PersonsTaxonomy.persons.{$this->person_group}.roles.{$this->person_role}.label",
);
} }
} }

View File

@ -8,12 +8,11 @@
namespace App\Entities; namespace App\Entities;
use App\Entities\Location;
use App\Libraries\SimpleRSSElement; use App\Libraries\SimpleRSSElement;
use App\Models\PodcastModel;
use App\Models\SoundbiteModel;
use App\Models\NoteModel; use App\Models\NoteModel;
use App\Models\PersonModel; use App\Models\PersonModel;
use App\Models\PodcastModel;
use App\Models\SoundbiteModel;
use CodeIgniter\Entity\Entity; use CodeIgniter\Entity\Entity;
use CodeIgniter\Files\File; use CodeIgniter\Files\File;
use CodeIgniter\HTTP\Files\UploadedFile; use CodeIgniter\HTTP\Files\UploadedFile;
@ -82,16 +81,27 @@ use RuntimeException;
class Episode extends Entity class Episode extends Entity
{ {
protected Podcast $podcast; protected Podcast $podcast;
protected string $link; protected string $link;
protected File $audio_file; protected File $audio_file;
protected string $audio_file_url; protected string $audio_file_url;
protected string $audio_file_analytics_url; protected string $audio_file_analytics_url;
protected string $audio_file_web_url; protected string $audio_file_web_url;
protected string $audio_file_opengraph_url; protected string $audio_file_opengraph_url;
protected string $embeddable_player_url; protected string $embeddable_player_url;
protected Image $image; protected Image $image;
protected ?string $description = null; protected ?string $description = null;
protected File $transcript_file; protected File $transcript_file;
protected File $chapters_file; protected File $chapters_file;
/** /**
@ -110,18 +120,15 @@ class Episode extends Entity
protected ?array $notes = null; protected ?array $notes = null;
protected ?Location $location = null; protected ?Location $location = null;
protected string $custom_rss_string; protected string $custom_rss_string;
protected ?string $publication_status = null; protected ?string $publication_status = null;
/** /**
* @var string[] * @var string[]
*/ */
protected $dates = [ protected $dates = ['published_at', 'created_at', 'updated_at', 'deleted_at'];
'published_at',
'created_at',
'updated_at',
'deleted_at',
];
/** /**
* @var array<string, string> * @var array<string, string>
@ -171,10 +178,7 @@ class Episode extends Entity
} }
// Save image // Save image
$image->saveImage( $image->saveImage('podcasts/' . $this->getPodcast()->name, $this->attributes['slug'],);
'podcasts/' . $this->getPodcast()->name,
$this->attributes['slug'],
);
$this->attributes['image_mimetype'] = $image->mimetype; $this->attributes['image_mimetype'] = $image->mimetype;
$this->attributes['image_path'] = $image->path; $this->attributes['image_path'] = $image->path;
@ -185,11 +189,7 @@ class Episode extends Entity
public function getImage(): Image public function getImage(): Image
{ {
if ($imagePath = $this->attributes['image_path']) { if ($imagePath = $this->attributes['image_path']) {
return new Image( return new Image(null, $imagePath, $this->attributes['image_mimetype'],);
null,
$imagePath,
$this->attributes['image_mimetype'],
);
} }
return $this->podcast->image; return $this->podcast->image;
@ -198,7 +198,7 @@ class Episode extends Entity
/** /**
* Saves an audio file * Saves an audio file
*/ */
public function setAudioFile(UploadedFile|File $audioFile): static public function setAudioFile(UploadedFile | File $audioFile): static
{ {
helper(['media', 'id3']); helper(['media', 'id3']);
@ -222,13 +222,14 @@ class Episode extends Entity
/** /**
* Saves an episode transcript file * Saves an episode transcript file
*/ */
public function setTranscriptFile(UploadedFile|File $transcriptFile): static public function setTranscriptFile(UploadedFile | File $transcriptFile): static
{ {
helper('media'); helper('media');
$this->attributes['transcript_file_path'] = save_media( $this->attributes['transcript_file_path'] = save_media(
$transcriptFile, $transcriptFile,
$this->getPodcast()->name, $this->getPodcast()
->name,
$this->attributes['slug'] . '-transcript', $this->attributes['slug'] . '-transcript',
); );
@ -238,13 +239,14 @@ class Episode extends Entity
/** /**
* Saves an episode chapters file * Saves an episode chapters file
*/ */
public function setChaptersFile(UploadedFile|File $chaptersFile): static public function setChaptersFile(UploadedFile | File $chaptersFile): static
{ {
helper('media'); helper('media');
$this->attributes['chapters_file_path'] = save_media( $this->attributes['chapters_file_path'] = save_media(
$chaptersFile, $chaptersFile,
$this->getPodcast()->name, $this->getPodcast()
->name,
$this->attributes['slug'] . '-chapters', $this->attributes['slug'] . '-chapters',
); );
@ -263,9 +265,7 @@ class Episode extends Entity
if ($this->attributes['transcript_file_path']) { if ($this->attributes['transcript_file_path']) {
helper('media'); helper('media');
return new File( return new File(media_path($this->attributes['transcript_file_path']),);
media_path($this->attributes['transcript_file_path']),
);
} }
return null; return null;
@ -276,9 +276,7 @@ class Episode extends Entity
if ($this->attributes['chapters_file_path']) { if ($this->attributes['chapters_file_path']) {
helper('media'); helper('media');
return new File( return new File(media_path($this->attributes['chapters_file_path']),);
media_path($this->attributes['chapters_file_path']),
);
} }
return null; return null;
@ -317,8 +315,8 @@ class Episode extends Entity
} }
/** /**
* Gets transcript url from transcript file uri if it exists * Gets transcript url from transcript file uri if it exists or returns the transcript_file_remote_url which can be
* or returns the transcript_file_remote_url which can be null. * null.
*/ */
public function getTranscriptFileUrl(): ?string public function getTranscriptFileUrl(): ?string
{ {
@ -329,8 +327,8 @@ class Episode extends Entity
} }
/** /**
* Gets chapters file url from chapters file uri if it exists * Gets chapters file url from chapters file uri if it exists or returns the chapters_file_remote_url which can be
* or returns the chapters_file_remote_url which can be null. * null.
*/ */
public function getChaptersFileUrl(): ?string public function getChaptersFileUrl(): ?string
{ {
@ -349,16 +347,11 @@ class Episode extends Entity
public function getPersons(): array public function getPersons(): array
{ {
if ($this->id === null) { if ($this->id === null) {
throw new RuntimeException( throw new RuntimeException('Episode must be created before getting persons.',);
'Episode must be created before getting persons.',
);
} }
if ($this->persons === null) { if ($this->persons === null) {
$this->persons = (new PersonModel())->getEpisodePersons( $this->persons = (new PersonModel())->getEpisodePersons($this->podcast_id, $this->id,);
$this->podcast_id,
$this->id,
);
} }
return $this->persons; return $this->persons;
@ -372,16 +365,11 @@ class Episode extends Entity
public function getSoundbites(): array public function getSoundbites(): array
{ {
if ($this->id === null) { if ($this->id === null) {
throw new RuntimeException( throw new RuntimeException('Episode must be created before getting soundbites.',);
'Episode must be created before getting soundbites.',
);
} }
if ($this->soundbites === null) { if ($this->soundbites === null) {
$this->soundbites = (new SoundbiteModel())->getEpisodeSoundbites( $this->soundbites = (new SoundbiteModel())->getEpisodeSoundbites($this->getPodcast() ->id, $this->id,);
$this->getPodcast()->id,
$this->id,
);
} }
return $this->soundbites; return $this->soundbites;
@ -393,9 +381,7 @@ class Episode extends Entity
public function getNotes(): array public function getNotes(): array
{ {
if ($this->id === null) { if ($this->id === null) {
throw new RuntimeException( throw new RuntimeException('Episode must be created before getting soundbites.',);
'Episode must be created before getting soundbites.',
);
} }
if ($this->notes === null) { if ($this->notes === null) {
@ -407,13 +393,7 @@ class Episode extends Entity
public function getLink(): string public function getLink(): string
{ {
return base_url( return base_url(route_to('episode', $this->getPodcast() ->name, $this->attributes['slug'],),);
route_to(
'episode',
$this->getPodcast()->name,
$this->attributes['slug'],
),
);
} }
public function getEmbeddablePlayerUrl(string $theme = null): string public function getEmbeddablePlayerUrl(string $theme = null): string
@ -422,15 +402,12 @@ class Episode extends Entity
$theme $theme
? route_to( ? route_to(
'embeddable-player-theme', 'embeddable-player-theme',
$this->getPodcast()->name, $this->getPodcast()
->name,
$this->attributes['slug'], $this->attributes['slug'],
$theme, $theme,
) )
: route_to( : route_to('embeddable-player', $this->getPodcast() ->name, $this->attributes['slug'],),
'embeddable-player',
$this->getPodcast()->name,
$this->attributes['slug'],
),
); );
} }
@ -443,9 +420,7 @@ class Episode extends Entity
public function getPodcast(): ?Podcast public function getPodcast(): ?Podcast
{ {
return (new PodcastModel())->getPodcastById( return (new PodcastModel())->getPodcastById($this->attributes['podcast_id'],);
$this->attributes['podcast_id'],
);
} }
public function setDescriptionMarkdown(string $descriptionMarkdown): static public function setDescriptionMarkdown(string $descriptionMarkdown): static
@ -456,9 +431,7 @@ class Episode extends Entity
]); ]);
$this->attributes['description_markdown'] = $descriptionMarkdown; $this->attributes['description_markdown'] = $descriptionMarkdown;
$this->attributes['description_html'] = $converter->convertToHtml( $this->attributes['description_html'] = $converter->convertToHtml($descriptionMarkdown,);
$descriptionMarkdown,
);
return $this; return $this;
} }
@ -467,19 +440,25 @@ class Episode extends Entity
{ {
$descriptionHtml = ''; $descriptionHtml = '';
if ( if (
$this->getPodcast()->partner_id !== null && $this->getPodcast()
$this->getPodcast()->partner_link_url !== null && ->partner_id !== null &&
$this->getPodcast()->partner_image_url !== null $this->getPodcast()
->partner_link_url !== null &&
$this->getPodcast()
->partner_image_url !== null
) { ) {
$descriptionHtml .= "<div><a href=\"{$this->getPartnerLink($serviceSlug, $descriptionHtml .= "<div><a href=\"{$this->getPartnerLink(
)}\" rel=\"sponsored noopener noreferrer\" target=\"_blank\"><img src=\"{$this->getPartnerImageUrl($serviceSlug, $serviceSlug,
)}\" rel=\"sponsored noopener noreferrer\" target=\"_blank\"><img src=\"{$this->getPartnerImageUrl(
$serviceSlug,
)}\" alt=\"Partner image\" /></a></div>"; )}\" alt=\"Partner image\" /></a></div>";
} }
$descriptionHtml .= $this->attributes['description_html']; $descriptionHtml .= $this->attributes['description_html'];
if ($this->getPodcast()->episode_description_footer_html) { if ($this->getPodcast()->episode_description_footer_html) {
$descriptionHtml .= "<footer>{$this->getPodcast()->episode_description_footer_html}</footer>"; $descriptionHtml .= "<footer>{$this->getPodcast()
->episode_description_footer_html}</footer>";
} }
return $descriptionHtml; return $descriptionHtml;
@ -489,11 +468,7 @@ class Episode extends Entity
{ {
if ($this->description === null) { if ($this->description === null) {
$this->description = trim( $this->description = trim(
preg_replace( preg_replace('~\s+~', ' ', strip_tags($this->attributes['description_html']),),
'~\s+~',
' ',
strip_tags($this->attributes['description_html']),
),
); );
} }
@ -529,7 +504,7 @@ class Episode extends Entity
} }
if ( if (
!isset($this->attributes['location_name']) || ! isset($this->attributes['location_name']) ||
$this->attributes['location_name'] !== $location->name $this->attributes['location_name'] !== $location->name
) { ) {
$location->fetchOsmLocation(); $location->fetchOsmLocation();
@ -549,11 +524,7 @@ class Episode extends Entity
} }
if ($this->location === null) { if ($this->location === null) {
$this->location = new Location( $this->location = new Location($this->location_name, $this->location_geo, $this->location_osm,);
$this->location_name,
$this->location_geo,
$this->location_osm,
);
} }
return $this->location; return $this->location;
@ -562,7 +533,7 @@ class Episode extends Entity
/** /**
* Get custom rss tag as XML String * Get custom rss tag as XML String
*/ */
function getCustomRssString(): string public function getCustomRssString(): string
{ {
if ($this->custom_rss === null) { if ($this->custom_rss === null) {
return ''; return '';
@ -575,12 +546,9 @@ class Episode extends Entity
)) ))
->addChild('channel') ->addChild('channel')
->addChild('item'); ->addChild('item');
array_to_rss( array_to_rss([
[ 'elements' => $this->custom_rss,
'elements' => $this->custom_rss, ], $xmlNode,);
],
$xmlNode,
);
return str_replace(['<item>', '</item>'], '', $xmlNode->asXML()); return str_replace(['<item>', '</item>'], '', $xmlNode->asXML());
} }
@ -588,7 +556,7 @@ class Episode extends Entity
/** /**
* Saves custom rss tag into json * Saves custom rss tag into json
*/ */
function setCustomRssString(?string $customRssString = null): static public function setCustomRssString(?string $customRssString = null): static
{ {
if ($customRssString === null) { if ($customRssString === null) {
return $this; return $this;
@ -604,9 +572,7 @@ class Episode extends Entity
)['elements'][0]['elements'][0]; )['elements'][0]['elements'][0];
if (array_key_exists('elements', $customRssArray)) { if (array_key_exists('elements', $customRssArray)) {
$this->attributes['custom_rss'] = json_encode( $this->attributes['custom_rss'] = json_encode($customRssArray['elements'],);
$customRssArray['elements'],
);
} else { } else {
$this->attributes['custom_rss'] = null; $this->attributes['custom_rss'] = null;
} }
@ -614,12 +580,13 @@ class Episode extends Entity
return $this; return $this;
} }
function getPartnerLink(?string $serviceSlug = null): string public function getPartnerLink(?string $serviceSlug = null): string
{ {
$partnerLink = $partnerLink =
rtrim($this->getPodcast()->partner_link_url, '/') . rtrim($this->getPodcast()->partner_link_url, '/') .
'?pid=' . '?pid=' .
$this->getPodcast()->partner_id . $this->getPodcast()
->partner_id .
'&guid=' . '&guid=' .
urlencode($this->attributes['guid']); urlencode($this->attributes['guid']);
@ -630,7 +597,7 @@ class Episode extends Entity
return $partnerLink; return $partnerLink;
} }
function getPartnerImageUrl(string $serviceSlug = null): string public function getPartnerImageUrl(string $serviceSlug = null): string
{ {
if ($serviceSlug !== null) { if ($serviceSlug !== null) {
return '&_from=' . $serviceSlug; return '&_from=' . $serviceSlug;
@ -638,7 +605,8 @@ class Episode extends Entity
return rtrim($this->getPodcast()->partner_image_url, '/') . return rtrim($this->getPodcast()->partner_image_url, '/') .
'?pid=' . '?pid=' .
$this->getPodcast()->partner_id . $this->getPodcast()
->partner_id .
'&guid=' . '&guid=' .
urlencode($this->attributes['guid']); urlencode($this->attributes['guid']);
} }

View File

@ -36,20 +36,19 @@ use RuntimeException;
class Image extends Entity class Image extends Entity
{ {
protected Images $config; protected Images $config;
protected ?File $file = null; protected ?File $file = null;
protected string $dirname; protected string $dirname;
protected string $filename; protected string $filename;
protected string $extension; protected string $extension;
public function __construct( public function __construct(?File $file, string $path = '', string $mimetype = '')
?File $file, {
string $path = '',
string $mimetype = ''
) {
if ($file === null && $path === '') { if ($file === null && $path === '') {
throw new RuntimeException( throw new RuntimeException('File or path must be set to create an Image.',);
'File or path must be set to create an Image.',
);
} }
$this->config = config('Images'); $this->config = config('Images');
@ -80,7 +79,7 @@ class Image extends Entity
$this->mimetype = $mimetype; $this->mimetype = $mimetype;
} }
function getFile(): File public function getFile(): File
{ {
if ($this->file === null) { if ($this->file === null) {
$this->file = new File($this->path); $this->file = new File($this->path);
@ -89,19 +88,19 @@ class Image extends Entity
return $this->file; return $this->file;
} }
function getPath(): string public function getPath(): string
{ {
return $this->dirname . '/' . $this->filename . '.' . $this->extension; return $this->dirname . '/' . $this->filename . '.' . $this->extension;
} }
function getUrl(): string public function getUrl(): string
{ {
helper('media'); helper('media');
return media_base_url($this->path); return media_base_url($this->path);
} }
function getThumbnailPath(): string public function getThumbnailPath(): string
{ {
return $this->dirname . return $this->dirname .
'/' . '/' .
@ -111,14 +110,14 @@ class Image extends Entity
$this->extension; $this->extension;
} }
function getThumbnailUrl(): string public function getThumbnailUrl(): string
{ {
helper('media'); helper('media');
return media_base_url($this->thumbnail_path); return media_base_url($this->thumbnail_path);
} }
function getMediumPath(): string public function getMediumPath(): string
{ {
return $this->dirname . return $this->dirname .
'/' . '/' .
@ -128,14 +127,14 @@ class Image extends Entity
$this->extension; $this->extension;
} }
function getMediumUrl(): string public function getMediumUrl(): string
{ {
helper('media'); helper('media');
return media_base_url($this->medium_path); return media_base_url($this->medium_path);
} }
function getLargePath(): string public function getLargePath(): string
{ {
return $this->dirname . return $this->dirname .
'/' . '/' .
@ -145,14 +144,14 @@ class Image extends Entity
$this->extension; $this->extension;
} }
function getLargeUrl(): string public function getLargeUrl(): string
{ {
helper('media'); helper('media');
return media_base_url($this->large_path); return media_base_url($this->large_path);
} }
function getFeedPath(): string public function getFeedPath(): string
{ {
return $this->dirname . return $this->dirname .
'/' . '/' .
@ -162,14 +161,14 @@ class Image extends Entity
$this->extension; $this->extension;
} }
function getFeedUrl(): string public function getFeedUrl(): string
{ {
helper('media'); helper('media');
return media_base_url($this->feed_path); return media_base_url($this->feed_path);
} }
function getId3Path(): string public function getId3Path(): string
{ {
return $this->dirname . return $this->dirname .
'/' . '/' .
@ -179,7 +178,7 @@ class Image extends Entity
$this->extension; $this->extension;
} }
function getId3Url(): string public function getId3Url(): string
{ {
helper('media'); helper('media');

View File

@ -22,12 +22,12 @@ class Location extends Entity
/** /**
* @var string * @var string
*/ */
const OSM_URL = 'https://www.openstreetmap.org/'; private const OSM_URL = 'https://www.openstreetmap.org/';
/** /**
* @var string * @var string
*/ */
const NOMINATIM_URL = 'https://nominatim.openstreetmap.org/'; private const NOMINATIM_URL = 'https://nominatim.openstreetmap.org/';
public function __construct( public function __construct(
protected string $name, protected string $name,
@ -37,7 +37,7 @@ class Location extends Entity
parent::__construct([ parent::__construct([
'name' => $name, 'name' => $name,
'geo' => $geo, 'geo' => $geo,
'osm' => $osm 'osm' => $osm,
]); ]);
} }
@ -45,7 +45,11 @@ class Location extends Entity
{ {
if ($this->osm !== null) { if ($this->osm !== null) {
return self::OSM_URL . return self::OSM_URL .
['N' => 'node', 'W' => 'way', 'R' => 'relation'][substr($this->osm, 0, 1)] . [
'N' => 'node',
'W' => 'way',
'R' => 'relation',
][substr($this->osm, 0, 1)] .
'/' . '/' .
substr($this->osm, 1); substr($this->osm, 1);
} }
@ -80,22 +84,23 @@ class Location extends Entity
], ],
); );
$places = json_decode( $places = json_decode($response->getBody(), false, 512, JSON_THROW_ON_ERROR,);
$response->getBody(),
false,
512,
JSON_THROW_ON_ERROR,
);
if ($places === []) { if ($places === []) {
return $this; return $this;
} }
if (property_exists($places[0], 'lat') && $places[0]->lat !== null && (property_exists($places[0], 'lon') && $places[0]->lon !== null)) { if (property_exists($places[0], 'lat') && $places[0]->lat !== null && (property_exists(
$places[0],
'lon'
) && $places[0]->lon !== null)) {
$this->attributes['geo'] = "geo:{$places[0]->lat},{$places[0]->lon}"; $this->attributes['geo'] = "geo:{$places[0]->lat},{$places[0]->lon}";
} }
if (property_exists($places[0], 'osm_type') && $places[0]->osm_type !== null && (property_exists($places[0], 'osm_id') && $places[0]->osm_id !== null)) { if (property_exists($places[0], 'osm_type') && $places[0]->osm_type !== null && (property_exists(
$places[0],
'osm_id'
) && $places[0]->osm_id !== null)) {
$this->attributes['osm'] = strtoupper(substr($places[0]->osm_type, 0, 1)) . $places[0]->osm_id; $this->attributes['osm'] = strtoupper(substr($places[0]->osm_type, 0, 1)) . $places[0]->osm_id;
} }

View File

@ -47,15 +47,11 @@ class Note extends ActivityPubNote
public function getEpisode(): ?Episode public function getEpisode(): ?Episode
{ {
if ($this->episode_id === null) { if ($this->episode_id === null) {
throw new RuntimeException( throw new RuntimeException('Note must have an episode_id before getting episode.',);
'Note must have an episode_id before getting episode.',
);
} }
if ($this->episode === null) { if ($this->episode === null) {
$this->episode = (new EpisodeModel())->getEpisodeById( $this->episode = (new EpisodeModel())->getEpisodeById($this->episode_id,);
$this->episode_id,
);
} }
return $this->episode; return $this->episode;

View File

@ -26,6 +26,7 @@ use League\CommonMark\CommonMarkConverter;
class Page extends Entity class Page extends Entity
{ {
protected string $link; protected string $link;
protected string $content_html; protected string $content_html;
/** /**
@ -52,9 +53,7 @@ class Page extends Entity
]); ]);
$this->attributes['content_markdown'] = $contentMarkdown; $this->attributes['content_markdown'] = $contentMarkdown;
$this->attributes['content_html'] = $converter->convertToHtml( $this->attributes['content_html'] = $converter->convertToHtml($contentMarkdown,);
$contentMarkdown,
);
return $this; return $this;
} }

View File

@ -27,7 +27,9 @@ use RuntimeException;
class Person extends Entity class Person extends Entity
{ {
protected Image $image; protected Image $image;
protected ?int $podcast_id = null; protected ?int $podcast_id = null;
protected ?int $episode_id = null; protected ?int $episode_id = null;
/** /**
@ -69,25 +71,24 @@ class Person extends Entity
public function getImage(): Image public function getImage(): Image
{ {
return new Image( return new Image(null, $this->attributes['image_path'], $this->attributes['image_mimetype'],);
null,
$this->attributes['image_path'],
$this->attributes['image_mimetype'],
);
} }
/** /**
* @return object[] * @return object[]
*/ */
public function getRoles(): array { public function getRoles(): array
{
if ($this->attributes['podcast_id'] === null) { if ($this->attributes['podcast_id'] === null) {
throw new RuntimeException( throw new RuntimeException('Person must have a podcast_id before getting roles.',);
'Person must have a podcast_id before getting roles.',
);
} }
if ($this->roles === null) { if ($this->roles === null) {
$this->roles = (new PersonModel())->getPersonRoles($this->id, $this->attributes['podcast_id'], $this->episode_id); $this->roles = (new PersonModel())->getPersonRoles(
$this->id,
$this->attributes['podcast_id'],
$this->episode_id
);
} }
return $this->roles; return $this->roles;

View File

@ -13,8 +13,8 @@ use App\Models\CategoryModel;
use App\Models\EpisodeModel; use App\Models\EpisodeModel;
use App\Models\PersonModel; use App\Models\PersonModel;
use App\Models\PlatformModel; use App\Models\PlatformModel;
use CodeIgniter\Entity\Entity;
use App\Models\UserModel; use App\Models\UserModel;
use CodeIgniter\Entity\Entity;
use CodeIgniter\I18n\Time; use CodeIgniter\I18n\Time;
use League\CommonMark\CommonMarkConverter; use League\CommonMark\CommonMarkConverter;
use RuntimeException; use RuntimeException;
@ -73,14 +73,17 @@ use RuntimeException;
* @property Platform[] $podcasting_platforms * @property Platform[] $podcasting_platforms
* @property Platform[] $social_platforms * @property Platform[] $social_platforms
* @property Platform[] $funding_platforms * @property Platform[] $funding_platforms
*
*/ */
class Podcast extends Entity class Podcast extends Entity
{ {
protected string $link; protected string $link;
protected ?Actor $actor = null; protected ?Actor $actor = null;
protected Image $image; protected Image $image;
protected ?string $description = null; protected ?string $description = null;
protected ?Category $category = null; protected ?Category $category = null;
/** /**
@ -124,6 +127,7 @@ class Podcast extends Entity
protected ?array $funding_platforms = null; protected ?array $funding_platforms = null;
protected ?Location $location = null; protected ?Location $location = null;
protected string $custom_rss_string; protected string $custom_rss_string;
/** /**
@ -168,13 +172,12 @@ class Podcast extends Entity
public function getActor(): Actor public function getActor(): Actor
{ {
if ($this->actor_id === 0) { if ($this->actor_id === 0) {
throw new RuntimeException( throw new RuntimeException('Podcast must have an actor_id before getting actor.',);
'Podcast must have an actor_id before getting actor.',
);
} }
if ($this->actor === null) { if ($this->actor === null) {
$this->actor = model('ActorModel')->getActorById($this->actor_id); $this->actor = model('ActorModel')
->getActorById($this->actor_id);
} }
return $this->actor; return $this->actor;
@ -217,16 +220,11 @@ class Podcast extends Entity
public function getEpisodes(): array public function getEpisodes(): array
{ {
if ($this->id === null) { if ($this->id === null) {
throw new RuntimeException( throw new RuntimeException('Podcast must be created before getting episodes.',);
'Podcast must be created before getting episodes.',
);
} }
if ($this->episodes === null) { if ($this->episodes === null) {
$this->episodes = (new EpisodeModel())->getPodcastEpisodes( $this->episodes = (new EpisodeModel())->getPodcastEpisodes($this->id, $this->type,);
$this->id,
$this->type,
);
} }
return $this->episodes; return $this->episodes;
@ -240,9 +238,7 @@ class Podcast extends Entity
public function getPersons(): array public function getPersons(): array
{ {
if ($this->id === null) { if ($this->id === null) {
throw new RuntimeException( throw new RuntimeException('Podcast must be created before getting persons.',);
'Podcast must be created before getting persons.',
);
} }
if ($this->persons === null) { if ($this->persons === null) {
@ -258,15 +254,11 @@ class Podcast extends Entity
public function getCategory(): ?Category public function getCategory(): ?Category
{ {
if ($this->id === null) { if ($this->id === null) {
throw new RuntimeException( throw new RuntimeException('Podcast must be created before getting category.',);
'Podcast must be created before getting category.',
);
} }
if ($this->category === null) { if ($this->category === null) {
$this->category = (new CategoryModel())->getCategoryById( $this->category = (new CategoryModel())->getCategoryById($this->category_id,);
$this->category_id,
);
} }
return $this->category; return $this->category;
@ -280,15 +272,11 @@ class Podcast extends Entity
public function getContributors(): array public function getContributors(): array
{ {
if ($this->id === null) { if ($this->id === null) {
throw new RuntimeException( throw new RuntimeException('Podcasts must be created before getting contributors.',);
'Podcasts must be created before getting contributors.',
);
} }
if ($this->contributors === null) { if ($this->contributors === null) {
$this->contributors = (new UserModel())->getPodcastContributors( $this->contributors = (new UserModel())->getPodcastContributors($this->id,);
$this->id,
);
} }
return $this->contributors; return $this->contributors;
@ -302,16 +290,13 @@ class Podcast extends Entity
]); ]);
$this->attributes['description_markdown'] = $descriptionMarkdown; $this->attributes['description_markdown'] = $descriptionMarkdown;
$this->attributes['description_html'] = $converter->convertToHtml( $this->attributes['description_html'] = $converter->convertToHtml($descriptionMarkdown,);
$descriptionMarkdown,
);
return $this; return $this;
} }
public function setEpisodeDescriptionFooterMarkdown( public function setEpisodeDescriptionFooterMarkdown(?string $episodeDescriptionFooterMarkdown = null): static
?string $episodeDescriptionFooterMarkdown = null {
): static {
if ($episodeDescriptionFooterMarkdown) { if ($episodeDescriptionFooterMarkdown) {
$converter = new CommonMarkConverter([ $converter = new CommonMarkConverter([
'html_input' => 'strip', 'html_input' => 'strip',
@ -333,11 +318,7 @@ class Podcast extends Entity
{ {
if ($this->description === null) { if ($this->description === null) {
$this->description = trim( $this->description = trim(
(string) preg_replace( (string) preg_replace('~\s+~', ' ', strip_tags($this->attributes['description_html']),),
'~\s+~',
' ',
strip_tags($this->attributes['description_html']),
),
); );
} }
@ -352,16 +333,11 @@ class Podcast extends Entity
public function getPodcastingPlatforms(): array public function getPodcastingPlatforms(): array
{ {
if ($this->id === null) { if ($this->id === null) {
throw new RuntimeException( throw new RuntimeException('Podcast must be created before getting podcasting platform links.',);
'Podcast must be created before getting podcasting platform links.',
);
} }
if ($this->podcasting_platforms === null) { if ($this->podcasting_platforms === null) {
$this->podcasting_platforms = (new PlatformModel())->getPodcastPlatforms( $this->podcasting_platforms = (new PlatformModel())->getPodcastPlatforms($this->id, 'podcasting',);
$this->id,
'podcasting',
);
} }
return $this->podcasting_platforms; return $this->podcasting_platforms;
@ -375,16 +351,11 @@ class Podcast extends Entity
public function getSocialPlatforms(): array public function getSocialPlatforms(): array
{ {
if ($this->id === null) { if ($this->id === null) {
throw new RuntimeException( throw new RuntimeException('Podcast must be created before getting social platform links.',);
'Podcast must be created before getting social platform links.',
);
} }
if ($this->social_platforms === null) { if ($this->social_platforms === null) {
$this->social_platforms = (new PlatformModel())->getPodcastPlatforms( $this->social_platforms = (new PlatformModel())->getPodcastPlatforms($this->id, 'social',);
$this->id,
'social',
);
} }
return $this->social_platforms; return $this->social_platforms;
@ -398,16 +369,11 @@ class Podcast extends Entity
public function getFundingPlatforms(): array public function getFundingPlatforms(): array
{ {
if ($this->id === null) { if ($this->id === null) {
throw new RuntimeException( throw new RuntimeException('Podcast must be created before getting funding platform links.',);
'Podcast must be created before getting funding platform links.',
);
} }
if ($this->funding_platforms === null) { if ($this->funding_platforms === null) {
$this->funding_platforms = (new PlatformModel())->getPodcastPlatforms( $this->funding_platforms = (new PlatformModel())->getPodcastPlatforms($this->id, 'funding',);
$this->id,
'funding',
);
} }
return $this->funding_platforms; return $this->funding_platforms;
@ -419,15 +385,11 @@ class Podcast extends Entity
public function getOtherCategories(): array public function getOtherCategories(): array
{ {
if ($this->id === null) { if ($this->id === null) {
throw new RuntimeException( throw new RuntimeException('Podcast must be created before getting other categories.',);
'Podcast must be created before getting other categories.',
);
} }
if ($this->other_categories === null) { if ($this->other_categories === null) {
$this->other_categories = (new CategoryModel())->getPodcastCategories( $this->other_categories = (new CategoryModel())->getPodcastCategories($this->id,);
$this->id,
);
} }
return $this->other_categories; return $this->other_categories;
@ -439,10 +401,7 @@ class Podcast extends Entity
public function getOtherCategoriesIds(): array public function getOtherCategoriesIds(): array
{ {
if ($this->other_categories_ids === null) { if ($this->other_categories_ids === null) {
$this->other_categories_ids = array_column( $this->other_categories_ids = array_column($this->getOtherCategories(), 'id',);
$this->getOtherCategories(),
'id',
);
} }
return $this->other_categories_ids; return $this->other_categories_ids;
@ -462,7 +421,7 @@ class Podcast extends Entity
} }
if ( if (
!isset($this->attributes['location_name']) || ! isset($this->attributes['location_name']) ||
$this->attributes['location_name'] !== $location->name $this->attributes['location_name'] !== $location->name
) { ) {
$location->fetchOsmLocation(); $location->fetchOsmLocation();
@ -482,11 +441,7 @@ class Podcast extends Entity
} }
if ($this->location === null) { if ($this->location === null) {
$this->location = new Location( $this->location = new Location($this->location_name, $this->location_geo, $this->location_osm,);
$this->location_name,
$this->location_geo,
$this->location_osm,
);
} }
return $this->location; return $this->location;
@ -495,7 +450,7 @@ class Podcast extends Entity
/** /**
* Get custom rss tag as XML String * Get custom rss tag as XML String
*/ */
function getCustomRssString(): string public function getCustomRssString(): string
{ {
if ($this->attributes['custom_rss'] === null) { if ($this->attributes['custom_rss'] === null) {
return ''; return '';
@ -506,12 +461,9 @@ class Podcast extends Entity
$xmlNode = (new SimpleRSSElement( $xmlNode = (new SimpleRSSElement(
'<?xml version="1.0" encoding="utf-8"?><rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:podcast="https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0"/>', '<?xml version="1.0" encoding="utf-8"?><rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:podcast="https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0"/>',
))->addChild('channel'); ))->addChild('channel');
array_to_rss( array_to_rss([
[ 'elements' => $this->custom_rss,
'elements' => $this->custom_rss, ], $xmlNode,);
],
$xmlNode,
);
return str_replace(['<channel>', '</channel>'], '', $xmlNode->asXML()); return str_replace(['<channel>', '</channel>'], '', $xmlNode->asXML());
} }
@ -519,7 +471,7 @@ class Podcast extends Entity
/** /**
* Saves custom rss tag into json * Saves custom rss tag into json
*/ */
function setCustomRssString(string $customRssString): static public function setCustomRssString(string $customRssString): static
{ {
if ($customRssString === '') { if ($customRssString === '') {
return $this; return $this;
@ -535,9 +487,7 @@ class Podcast extends Entity
)['elements'][0]; )['elements'][0];
if (array_key_exists('elements', $customRssArray)) { if (array_key_exists('elements', $customRssArray)) {
$this->attributes['custom_rss'] = json_encode( $this->attributes['custom_rss'] = json_encode($customRssArray['elements'],);
$customRssArray['elements'],
);
} else { } else {
$this->attributes['custom_rss'] = null; $this->attributes['custom_rss'] = null;
} }

View File

@ -8,9 +8,9 @@
namespace App\Entities; namespace App\Entities;
use RuntimeException;
use App\Models\PodcastModel; use App\Models\PodcastModel;
use Myth\Auth\Entities\User as MythAuthUser; use Myth\Auth\Entities\User as MythAuthUser;
use RuntimeException;
/** /**
* @property int $id * @property int $id
@ -32,8 +32,7 @@ class User extends MythAuthUser
protected ?array $podcasts = null; protected ?array $podcasts = null;
/** /**
* Array of field names and the type of value to cast them as * Array of field names and the type of value to cast them as when they are accessed.
* when they are accessed.
* *
* @var array<string, string> * @var array<string, string>
*/ */
@ -53,9 +52,7 @@ class User extends MythAuthUser
public function getPodcasts(): array public function getPodcasts(): array
{ {
if ($this->id === null) { if ($this->id === null) {
throw new RuntimeException( throw new RuntimeException('Users must be created before getting podcasts.',);
'Users must be created before getting podcasts.',
);
} }
if ($this->podcasts === null) { if ($this->podcasts === null) {

View File

@ -3,23 +3,19 @@
namespace App\Filters; namespace App\Filters;
use App\Models\PodcastModel; use App\Models\PodcastModel;
use Config\Services; use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface; use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface; use Config\Services;
use Myth\Auth\Exceptions\PermissionException; use Myth\Auth\Exceptions\PermissionException;
class PermissionFilter implements FilterInterface class PermissionFilter implements FilterInterface
{ {
/** /**
* Do whatever processing this filter needs to do. * Do whatever processing this filter needs to do. By default it should not return anything during normal execution.
* By default it should not return anything during * However, when an abnormal state is found, it should return an instance of CodeIgniter\HTTP\Response. If it does,
* normal execution. However, when an abnormal state * script execution will end and that Response will be sent back to the client, allowing for error pages, redirects,
* is found, it should return an instance of * etc.
* CodeIgniter\HTTP\Response. If it does, script
* execution will end and that Response will be
* sent back to the client, allowing for error pages,
* redirects, etc.
* *
* @param string[]|null $params * @param string[]|null $params
* @return void|mixed * @return void|mixed
@ -35,7 +31,7 @@ class PermissionFilter implements FilterInterface
$authenticate = Services::authentication(); $authenticate = Services::authentication();
// if no user is logged in then send to the login form // if no user is logged in then send to the login form
if (!$authenticate->check()) { if (! $authenticate->check()) {
session()->set('redirect_url', current_url()); session()->set('redirect_url', current_url());
return redirect('login'); return redirect('login');
} }
@ -72,7 +68,7 @@ class PermissionFilter implements FilterInterface
} }
} }
if (!$result) { if (! $result) {
if ($authenticate->silent()) { if ($authenticate->silent()) {
$redirectURL = session('redirect_url') ?? '/'; $redirectURL = session('redirect_url') ?? '/';
unset($_SESSION['redirect_url']); unset($_SESSION['redirect_url']);
@ -85,19 +81,15 @@ class PermissionFilter implements FilterInterface
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
/** /**
* Allows After filters to inspect and modify the response * Allows After filters to inspect and modify the response object as needed. This method does not allow any way to
* object as needed. This method does not allow any way * stop execution of other after filters, short of throwing an Exception or Error.
* to stop execution of other after filters, short of
* throwing an Exception or Error.
* *
* @param string[]|null $arguments * @param string[]|null $arguments
*/ */
public function after( public function after(RequestInterface $request, ResponseInterface $response, $arguments = null): void
RequestInterface $request, {
ResponseInterface $response,
$arguments = null
): void {
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------

View File

@ -11,7 +11,7 @@ use App\Entities\User;
use CodeIgniter\Database\Exceptions\DataException; use CodeIgniter\Database\Exceptions\DataException;
use Config\Services; use Config\Services;
if (!function_exists('user')) { if (! function_exists('user')) {
/** /**
* Returns the User instance for the current logged in user. * Returns the User instance for the current logged in user.
*/ */
@ -23,7 +23,7 @@ if (!function_exists('user')) {
} }
} }
if (!function_exists('set_interact_as_actor')) { if (! function_exists('set_interact_as_actor')) {
/** /**
* Sets the actor id of which the user is acting as * Sets the actor id of which the user is acting as
*/ */
@ -37,7 +37,7 @@ if (!function_exists('set_interact_as_actor')) {
} }
} }
if (!function_exists('remove_interact_as_actor')) { if (! function_exists('remove_interact_as_actor')) {
/** /**
* Removes the actor id of which the user is acting as * Removes the actor id of which the user is acting as
*/ */
@ -48,7 +48,7 @@ if (!function_exists('remove_interact_as_actor')) {
} }
} }
if (!function_exists('interact_as_actor_id')) { if (! function_exists('interact_as_actor_id')) {
/** /**
* Sets the podcast id of which the user is acting as * Sets the podcast id of which the user is acting as
*/ */
@ -62,27 +62,25 @@ if (!function_exists('interact_as_actor_id')) {
} }
} }
if (!function_exists('interact_as_actor')) { if (! function_exists('interact_as_actor')) {
/** /**
* Get the actor the user is currently interacting as * Get the actor the user is currently interacting as
*/ */
function interact_as_actor(): Actor|false function interact_as_actor(): Actor | false
{ {
$authenticate = Services::authentication(); $authenticate = Services::authentication();
$authenticate->check(); $authenticate->check();
$session = session(); $session = session();
if ($session->has('interact_as_actor_id')) { if ($session->has('interact_as_actor_id')) {
return model('ActorModel')->getActorById( return model('ActorModel')->getActorById($session->get('interact_as_actor_id'),);
$session->get('interact_as_actor_id'),
);
} }
return false; return false;
} }
} }
if (!function_exists('can_user_interact')) { if (! function_exists('can_user_interact')) {
/** /**
* @throws DataException * @throws DataException
*/ */

View File

@ -8,7 +8,7 @@
use Config\Services; use Config\Services;
if (!function_exists('render_breadcrumb')) { if (! function_exists('render_breadcrumb')) {
/** /**
* Renders the breadcrumb navigation through the Breadcrumb service * Renders the breadcrumb navigation through the Breadcrumb service
* *
@ -22,7 +22,7 @@ if (!function_exists('render_breadcrumb')) {
} }
} }
if (!function_exists('replace_breadcrumb_params')) { if (! function_exists('replace_breadcrumb_params')) {
/** /**
* @param string[] $newParams * @param string[] $newParams
*/ */

Some files were not shown because too many files have changed in this diff Show More