fix: update Router to include latest CI changes with alternate-content logic

This commit is contained in:
Yassine Doghri 2023-08-27 13:26:06 +00:00
parent 7ff1dbe903
commit ae57601c83
122 changed files with 803 additions and 963 deletions

View File

@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Config;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Session\Handlers\FileHandler;
class App extends BaseConfig
{
@ -138,191 +137,6 @@ class App extends BaseConfig
*/
public bool $forceGlobalSecureRequests = true;
/**
* --------------------------------------------------------------------------
* Session Driver
* --------------------------------------------------------------------------
*
* The session storage driver to use:
* - `CodeIgniter\Session\Handlers\FileHandler`
* - `CodeIgniter\Session\Handlers\DatabaseHandler`
* - `CodeIgniter\Session\Handlers\MemcachedHandler`
* - `CodeIgniter\Session\Handlers\RedisHandler`
*
* @deprecated use Config\Session::$driver instead.
*/
public string $sessionDriver = FileHandler::class;
/**
* --------------------------------------------------------------------------
* Session Cookie Name
* --------------------------------------------------------------------------
*
* The session cookie name, must contain only [0-9a-z_-] characters
*
* @deprecated use Config\Session::$cookieName instead.
*/
public string $sessionCookieName = 'ci_session';
/**
* --------------------------------------------------------------------------
* Session Expiration
* --------------------------------------------------------------------------
*
* The number of SECONDS you want the session to last.
* Setting to 0 (zero) means expire when the browser is closed.
*
* @deprecated use Config\Session::$expiration instead.
*/
public int $sessionExpiration = 7200;
/**
* --------------------------------------------------------------------------
* Session Save Path
* --------------------------------------------------------------------------
*
* The location to save sessions to and is driver dependent.
*
* For the 'files' driver, it's a path to a writable directory.
* WARNING: Only absolute paths are supported!
*
* For the 'database' driver, it's a table name.
* Please read up the manual for the format with other session drivers.
*
* IMPORTANT: You are REQUIRED to set a valid save path!
*
* @deprecated use Config\Session::$savePath instead.
*/
public string $sessionSavePath = WRITEPATH . 'session';
/**
* --------------------------------------------------------------------------
* Session Match IP
* --------------------------------------------------------------------------
*
* Whether to match the user's IP address when reading the session data.
*
* WARNING: If you're using the database driver, don't forget to update
* your session table's PRIMARY KEY when changing this setting.
*
* @deprecated use Config\Session::$matchIP instead.
*/
public bool $sessionMatchIP = false;
/**
* --------------------------------------------------------------------------
* Session Time to Update
* --------------------------------------------------------------------------
*
* How many seconds between CI regenerating the session ID.
*
* @deprecated use Config\Session::$timeToUpdate instead.
*/
public int $sessionTimeToUpdate = 300;
/**
* --------------------------------------------------------------------------
* Session Regenerate Destroy
* --------------------------------------------------------------------------
*
* Whether to destroy session data associated with the old session ID
* when auto-regenerating the session ID. When set to FALSE, the data
* will be later deleted by the garbage collector.
*
* @deprecated use Config\Session::$regenerateDestroy instead.
*/
public bool $sessionRegenerateDestroy = false;
/**
* --------------------------------------------------------------------------
* Session Database Group
* --------------------------------------------------------------------------
*
* DB Group for the database session.
*
* @deprecated use Config\Session::$DBGroup instead.
*/
public ?string $sessionDBGroup = null;
/**
* --------------------------------------------------------------------------
* Cookie Prefix
* --------------------------------------------------------------------------
*
* Set a cookie name prefix if you need to avoid collisions.
*
* @deprecated use Config\Cookie::$prefix property instead.
*/
public string $cookiePrefix = '';
/**
* --------------------------------------------------------------------------
* Cookie Domain
* --------------------------------------------------------------------------
*
* Set to `.your-domain.com` for site-wide cookies.
*
* @deprecated use Config\Cookie::$domain property instead.
*/
public string $cookieDomain = '';
/**
* --------------------------------------------------------------------------
* Cookie Path
* --------------------------------------------------------------------------
*
* Typically will be a forward slash.
*
* @deprecated use Config\Cookie::$path property instead.
*/
public string $cookiePath = '/';
/**
* --------------------------------------------------------------------------
* Cookie Secure
* --------------------------------------------------------------------------
*
* Cookie will only be set if a secure HTTPS connection exists.
*
* @deprecated use Config\Cookie::$secure property instead.
*/
public bool $cookieSecure = false;
/**
* --------------------------------------------------------------------------
* Cookie HttpOnly
* --------------------------------------------------------------------------
*
* Cookie will only be accessible via HTTP(S) (no JavaScript).
*
* @deprecated use Config\Cookie::$httponly property instead.
*/
public bool $cookieHTTPOnly = true;
/**
* --------------------------------------------------------------------------
* Cookie SameSite
* --------------------------------------------------------------------------
*
* Configure cookie SameSite setting. Allowed values are:
* - None
* - Lax
* - Strict
* - ''
*
* Alternatively, you can use the constant names:
* - `Cookie::SAMESITE_NONE`
* - `Cookie::SAMESITE_LAX`
* - `Cookie::SAMESITE_STRICT`
*
* Defaults to `Lax` for compatibility with modern browsers. Setting `''`
* (empty string) means default SameSite attribute set by browsers (`Lax`)
* will be set on cookies. If set to `None`, `$cookieSecure` must also be set.
*
* @deprecated `Config\Cookie` $samesite property is used.
*/
public ?string $cookieSameSite = 'Lax';
/**
* --------------------------------------------------------------------------
* Reverse Proxy IPs
@ -346,91 +160,6 @@ class App extends BaseConfig
*/
public array $proxyIPs = [];
/**
* --------------------------------------------------------------------------
* CSRF Token Name
* --------------------------------------------------------------------------
*
* The token name.
*
* @deprecated Use `Config\Security` $tokenName property instead of using this property.
*/
public string $CSRFTokenName = 'csrf_test_name';
/**
* --------------------------------------------------------------------------
* CSRF Header Name
* --------------------------------------------------------------------------
*
* The header name.
*
* @deprecated Use `Config\Security` $headerName property instead of using this property.
*/
public string $CSRFHeaderName = 'X-CSRF-TOKEN';
/**
* --------------------------------------------------------------------------
* CSRF Cookie Name
* --------------------------------------------------------------------------
*
* The cookie name.
*
* @deprecated Use `Config\Security` $cookieName property instead of using this property.
*/
public string $CSRFCookieName = 'csrf_cookie_name';
/**
* --------------------------------------------------------------------------
* CSRF Expire
* --------------------------------------------------------------------------
*
* The number in seconds the token should expire.
*
* @deprecated Use `Config\Security` $expire property instead of using this property.
*/
public int $CSRFExpire = 7200;
/**
* --------------------------------------------------------------------------
* CSRF Regenerate
* --------------------------------------------------------------------------
*
* Regenerate token on every submission?
*
* @deprecated Use `Config\Security` $regenerate property instead of using this property.
*/
public bool $CSRFRegenerate = true;
/**
* --------------------------------------------------------------------------
* CSRF Redirect
* --------------------------------------------------------------------------
*
* Redirect to previous page with error on failure?
*
* @deprecated Use `Config\Security` $redirect property instead of using this property.
*/
public bool $CSRFRedirect = true;
/**
* --------------------------------------------------------------------------
* CSRF SameSite
* --------------------------------------------------------------------------
*
* Setting for CSRF SameSite cookie token. Allowed values are:
* - None
* - Lax
* - Strict
* - ''
*
* Defaults to `Lax` as recommended in this link:
*
* @see https://portswigger.net/web-security/csrf/samesite-cookies
*
* @deprecated Use `Config\Security` $samesite property instead of using this property.
*/
public string $CSRFSameSite = 'Lax';
/**
* --------------------------------------------------------------------------
* Content Security Policy

View File

@ -18,5 +18,5 @@ class CURLRequest extends BaseConfig
* If true, all the options won't be reset between requests.
* It may cause an error request with unnecessary headers.
*/
public bool $shareOptions = true;
public bool $shareOptions = false;
}

View File

@ -84,6 +84,8 @@ class Cookie extends BaseConfig
* Defaults to `Lax` for compatibility with modern browsers. Setting `''`
* (empty string) means default SameSite attribute set by browsers (`Lax`)
* will be set on cookies. If set to `None`, `$secure` must also be set.
*
* @phpstan-var 'None'|'Lax'|'Strict'|''
*/
public string $samesite = 'Lax';

View File

@ -27,23 +27,24 @@ class Database extends Config
* @var array<string, mixed>
*/
public array $default = [
'DSN' => '',
'hostname' => 'localhost',
'username' => '',
'password' => '',
'database' => '',
'DBDriver' => 'MySQLi',
'DBPrefix' => 'cp_',
'pConnect' => false,
'DBDebug' => true,
'charset' => 'utf8mb4',
'DBCollat' => 'utf8mb4_unicode_ci',
'swapPre' => '',
'encrypt' => false,
'compress' => false,
'strictOn' => false,
'failover' => [],
'port' => 3306,
'DSN' => '',
'hostname' => 'localhost',
'username' => '',
'password' => '',
'database' => '',
'DBDriver' => 'MySQLi',
'DBPrefix' => 'cp_',
'pConnect' => false,
'DBDebug' => true,
'charset' => 'utf8mb4',
'DBCollat' => 'utf8mb4_unicode_ci',
'swapPre' => '',
'encrypt' => false,
'compress' => false,
'strictOn' => false,
'failover' => [],
'port' => 3306,
'numberNative' => false,
];
/**

View File

@ -10,6 +10,7 @@ use App\Models\EpisodeModel;
use CodeIgniter\Debug\Toolbar\Collectors\Database;
use CodeIgniter\Events\Events;
use CodeIgniter\Exceptions\FrameworkException;
use CodeIgniter\HotReloader\HotReloader;
/*
* --------------------------------------------------------------------
@ -50,6 +51,13 @@ Events::on('pre_system', static function () {
if (CI_DEBUG && ! is_cli()) {
Events::on('DBQuery', Database::class . '::collect');
Services::toolbar()->respond();
// Hot Reload route - for framework use on the hot reloader.
if (ENVIRONMENT === 'development') {
Services::routes()->get('__hot-reload', static function (): void {
(new HotReloader())->run();
});
}
}
});

View File

@ -5,7 +5,10 @@ declare(strict_types=1);
namespace Config;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Debug\ExceptionHandler;
use CodeIgniter\Debug\ExceptionHandlerInterface;
use Psr\Log\LogLevel;
use Throwable;
/**
* Setup how the exception handler works.
@ -80,4 +83,28 @@ class Exceptions extends BaseConfig
* to capture logging the deprecations.
*/
public string $deprecationLogLevel = LogLevel::WARNING;
/*
* DEFINE THE HANDLERS USED
* --------------------------------------------------------------------------
* Given the HTTP status code, returns exception handler that
* should be used to deal with this error. By default, it will run CodeIgniter's
* default handler and display the error information in the expected format
* for CLI, HTTP, or AJAX requests, as determined by is_cli() and the expected
* response format.
*
* Custom handlers can be returned if you want to handle one or more specific
* error codes yourself like:
*
* if (in_array($statusCode, [400, 404, 500])) {
* return new \App\Libraries\MyExceptionHandler();
* }
* if ($exception instanceOf PageNotFoundException) {
* return new \App\Libraries\MyExceptionHandler();
* }
*/
public function handler(int $statusCode, Throwable $exception): ExceptionHandlerInterface
{
return new ExceptionHandler($this);
}
}

View File

@ -34,15 +34,15 @@ class Fediverse extends FediverseBaseConfig
try {
$appTheme = service('settings')
->get('App.theme');
$defaultBanner = config('Images')
->podcastBannerDefaultPaths[$appTheme] ?? config('Images')->podcastBannerDefaultPaths['default'];
$defaultBanner = config(Images::class)
->podcastBannerDefaultPaths[$appTheme] ?? config(Images::class)->podcastBannerDefaultPaths['default'];
} catch (Exception) {
$defaultBanner = config('Images')
$defaultBanner = config(Images::class)
->podcastBannerDefaultPaths['default'];
}
['dirname' => $dirname, 'extension' => $extension, 'filename' => $filename] = pathinfo(
(string) $defaultBanner['path']
$defaultBanner['path']
);
$defaultBannerPath = $filename;
if ($dirname !== '.') {

View File

@ -11,6 +11,8 @@ use CodeIgniter\Filters\DebugToolbar;
use CodeIgniter\Filters\Honeypot;
use CodeIgniter\Filters\InvalidChars;
use CodeIgniter\Filters\SecureHeaders;
use Modules\Admin\Config\Admin;
use Modules\Analytics\Config\Analytics;
use Modules\Auth\Filters\PermissionFilter;
class Filters extends BaseConfig
@ -19,6 +21,7 @@ class Filters extends BaseConfig
* Configures aliases for Filter classes to make reading things nicer and simpler.
*
* @var array<string, string>
* @phpstan-var array<string, class-string>
*/
public array $aliases = [
'csrf' => CSRF::class,
@ -32,7 +35,8 @@ class Filters extends BaseConfig
/**
* List of filter aliases that are always applied before and after every request.
*
* @var array<string, mixed>
* @var array<string, array<string, array<string, string>>>|array<string, array<string>>
* @phpstan-var array<string, list<string>>|array<string, array<string, array<string, string>>>
*/
public array $globals = [
'before' => [
@ -76,7 +80,7 @@ class Filters extends BaseConfig
$this->filters = [
'session' => [
'before' => [config('Admin')->gateway . '*', config('Analytics')->gateway . '*'],
'before' => [config(Admin::class)->gateway . '*', config(Analytics::class)->gateway . '*'],
],
'podcast-unlock' => [
'before' => ['*@*/episodes/*'],

View File

@ -2,28 +2,10 @@
declare(strict_types=1);
namespace Config;
// Create a new instance of our RouteCollection class.
$routes = Services::routes();
use CodeIgniter\Router\RouteCollection;
/**
* --------------------------------------------------------------------
* Router Setup
* --------------------------------------------------------------------
*/
$routes->setDefaultNamespace('App\Controllers');
$routes->setDefaultController('Home');
$routes->setDefaultMethod('index');
$routes->setTranslateURIDashes(false);
$routes->set404Override();
// The Auto Routing (Legacy) is very dangerous. It is easy to create vulnerable apps
// where controller filters or CSRF protection are bypassed.
// If you don't want to define all routes, please use the Auto Routing (Improved).
// Set `$autoRoutesImproved` to true in `app/Config/Feature.php` and set the following to true.
$routes->setAutoRoute(false);
* @var RouteCollection $routes
/**
* --------------------------------------------------------------------
* Placeholder definitions
@ -69,23 +51,14 @@ $routes->get('.well-known/platforms', 'Platform');
// Podcast's Public routes
$routes->group('@(:podcastHandle)', static function ($routes): void {
$routes->get('/', 'PodcastController::activity/$1', [
'as' => 'podcast-activity',
]);
$routes->get('manifest.webmanifest', 'WebmanifestController::podcastManifest/$1', [
'as' => 'podcast-webmanifest',
]);
$routes->get('links', 'PodcastController::links/$1', [
'as' => 'podcast-links',
]);
// override default Fediverse Library's actor route
$routes->options('/', 'ActivityPubController::preflight');
$routes->get('/', 'PodcastController::activity/$1', [
'as' => 'actor',
'as' => 'podcast-activity',
'alternate-content' => [
'application/activity+json' => [
'namespace' => 'Modules\Fediverse\Controllers',
'controller-method' => 'ActorController/$1',
'controller-method' => 'ActorController::index/$1',
],
'application/podcast-activity+json' => [
'namespace' => 'App\Controllers',
@ -93,11 +66,17 @@ $routes->group('@(:podcastHandle)', static function ($routes): void {
],
'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [
'namespace' => 'Modules\Fediverse\Controllers',
'controller-method' => 'ActorController/$1',
'controller-method' => 'ActorController::index/$1',
],
],
'filter' => 'allow-cors',
]);
$routes->get('manifest.webmanifest', 'WebmanifestController::podcastManifest/$1', [
'as' => 'podcast-webmanifest',
]);
$routes->get('links', 'PodcastController::links/$1', [
'as' => 'podcast-links',
]);
$routes->get('about', 'PodcastController::about/$1', [
'as' => 'podcast-about',
]);
@ -106,12 +85,15 @@ $routes->group('@(:podcastHandle)', static function ($routes): void {
'as' => 'podcast-episodes',
'alternate-content' => [
'application/activity+json' => [
'namespace' => 'App\Controllers',
'controller-method' => 'PodcastController::episodeCollection/$1',
],
'application/podcast-activity+json' => [
'namespace' => 'App\Controllers',
'controller-method' => 'PodcastController::episodeCollection/$1',
],
'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [
'namespace' => 'App\Controllers',
'controller-method' => 'PodcastController::episodeCollection/$1',
],
],
@ -119,16 +101,19 @@ $routes->group('@(:podcastHandle)', static function ($routes): void {
]);
$routes->group('episodes/(:slug)', static function ($routes): void {
$routes->options('/', 'ActivityPubController::preflight');
$routes->get('/', 'EpisodeController/$1/$2', [
$routes->get('/', 'EpisodeController::index/$1/$2', [
'as' => 'episode',
'alternate-content' => [
'application/activity+json' => [
'namespace' => 'App\Controllers',
'controller-method' => 'EpisodeController::episodeObject/$1/$2',
],
'application/podcast-activity+json' => [
'namespace' => 'App\Controllers',
'controller-method' => 'EpisodeController::episodeObject/$1/$2',
],
'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [
'namespace' => 'App\Controllers',
'controller-method' => 'EpisodeController::episodeObject/$1/$2',
],
],
@ -186,21 +171,21 @@ $routes->group('@(:podcastHandle)', static function ($routes): void {
],);
});
});
$routes->head('feed.xml', 'FeedController/$1', [
$routes->head('feed.xml', 'FeedController::index/$1', [
'as' => 'podcast-rss-feed',
]);
$routes->get('feed.xml', 'FeedController/$1', [
$routes->get('feed.xml', 'FeedController::index/$1', [
'as' => 'podcast-rss-feed',
]);
$routes->head('feed', 'FeedController/$1');
$routes->get('feed', 'FeedController/$1');
$routes->head('feed', 'FeedController::index/$1');
$routes->get('feed', 'FeedController::index/$1');
});
// audio routes
$routes->head('audio/@(:podcastHandle)/(:slug).(:alphanum)', 'EpisodeAudioController/$1/$2', [
$routes->head('/audio/@(:podcastHandle)/(:slug).(:alphanum)', 'EpisodeAudioController::index/$1/$2', [
'as' => 'episode-audio',
], );
$routes->get('audio/@(:podcastHandle)/(:slug).(:alphanum)', 'EpisodeAudioController/$1/$2', [
$routes->get('/audio/@(:podcastHandle)/(:slug).(:alphanum)', 'EpisodeAudioController::index/$1/$2', [
'as' => 'episode-audio',
], );
@ -223,7 +208,7 @@ $routes->get('/map', 'MapController', [
$routes->get('/episodes-markers', 'MapController::getEpisodesMarkers', [
'as' => 'episodes-markers',
]);
$routes->get('/pages/(:slug)', 'PageController/$1', [
$routes->get('/pages/(:slug)', 'PageController::index/$1', [
'as' => 'page',
]);
@ -253,7 +238,7 @@ $routes->group('@(:podcastHandle)', static function ($routes): void {
'filter' => 'allow-cors',
]);
$routes->options('replies', 'ActivityPubController::preflight');
$routes->get('replies', 'PostController/$1/$2', [
$routes->get('replies', 'PostController::index/$1/$2', [
'as' => 'post-replies',
'alternate-content' => [
'application/activity+json' => [
@ -308,20 +293,3 @@ $routes->group('@(:podcastHandle)', static function ($routes): void {
'filter' => 'fediverse:verify-activitystream',
]);
});
/*
* --------------------------------------------------------------------
* Additional Routing
* --------------------------------------------------------------------
*
* There will often be times that you need additional routing and you
* need it to be able to override any defaults in this file. Environment
* based routes is one such time. require() additional route files here
* to make that happen.
*
* You will have access to the $routes object within that file without
* needing to reload it.
*/
if (is_file(APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php')) {
require APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php';
}

117
app/Config/Routing.php Normal file
View File

@ -0,0 +1,117 @@
<?php
declare(strict_types=1);
namespace Config;
use CodeIgniter\Config\Routing as BaseRouting;
/**
* Routing configuration
*/
class Routing extends BaseRouting
{
/**
* An array of files that contain route definitions.
* Route files are read in order, with the first match
* found taking precedence.
*
* Default: APPPATH . 'Config/Routes.php'
*
* @var string[]
*/
public array $routeFiles = [
APPPATH . 'Config/Routes.php',
ROOTPATH . 'modules/Admin/Config/Routes.php',
ROOTPATH . 'modules/Analytics/Config/Routes.php',
ROOTPATH . 'modules/Api/Rest/V1/Config/Routes.php',
ROOTPATH . 'modules/Auth/Config/Routes.php',
ROOTPATH . 'modules/Fediverse/Config/Routes.php',
ROOTPATH . 'modules/Install/Config/Routes.php',
ROOTPATH . 'modules/Media/Config/Routes.php',
ROOTPATH . 'modules/PodcastImport/Config/Routes.php',
ROOTPATH . 'modules/PremiumPodcasts/Config/Routes.php',
];
/**
* The default namespace to use for Controllers when no other
* namespace has been specified.
*
* Default: 'App\Controllers'
*/
public string $defaultNamespace = 'App\Controllers';
/**
* The default controller to use when no other controller has been
* specified.
*
* Default: 'Home'
*/
public string $defaultController = 'HomeController';
/**
* The default method to call on the controller when no other
* method has been set in the route.
*
* Default: 'index'
*/
public string $defaultMethod = 'index';
/**
* Whether to translate dashes in URIs to underscores.
* Primarily useful when using the auto-routing.
*
* Default: false
*/
public bool $translateURIDashes = false;
/**
* Sets the class/method that should be called if routing doesn't
* find a match. It can be either a closure or the controller/method
* name exactly like a route is defined: Users::index
*
* This setting is passed to the Router class and handled there.
*
* If you want to use a closure, you will have to set it in the
* class constructor or the routes file by calling:
*
* $routes->set404Override(function() {
* // Do something here
* });
*
* Example:
* public $override404 = 'App\Errors::show404';
*/
public ?string $override404 = null;
/**
* If TRUE, the system will attempt to match the URI against
* Controllers by matching each segment against folders/files
* in APPPATH/Controllers, when a match wasn't found against
* defined routes.
*
* If FALSE, will stop searching and do NO automatic routing.
*/
public bool $autoRoute = false;
/**
* If TRUE, will enable the use of the 'prioritize' option
* when defining routes.
*
* Default: false
*/
public bool $prioritize = false;
/**
* Map of URI segments and namespaces. For Auto Routing (Improved).
*
* The key is the first URI segment. The value is the controller namespace.
* E.g.,
* [
* 'blog' => 'Acme\Blog\Controllers',
* ]
*
* @var array<string, string> [ uri_segment => namespace ]
*/
public array $moduleRoutes = [];
}

View File

@ -6,7 +6,6 @@ namespace Config;
use App\Libraries\Breadcrumb;
use App\Libraries\Negotiate;
use App\Libraries\RouteCollection;
use App\Libraries\Router;
use CodeIgniter\Config\BaseService;
use CodeIgniter\HTTP\Request;
@ -44,21 +43,6 @@ class Services extends BaseService
return new Router($routes, $request);
}
/**
* The Routes service is a class that allows for easily building
* a collection of routes.
*
* @return RouteCollection
*/
public static function routes(bool $getShared = true)
{
if ($getShared) {
return static::getSharedInstance('routes');
}
return new RouteCollection(self::locator(), config('Modules'));
}
/**
* The Negotiate class provides the content negotiation features for working the request to determine correct
* language, encoding, charset, and more.

View File

@ -90,4 +90,31 @@ class Toolbar extends BaseConfig
* `$maxQueries` defines the maximum amount of queries that will be stored.
*/
public int $maxQueries = 100;
/**
* --------------------------------------------------------------------------
* Watched Directories
* --------------------------------------------------------------------------
*
* Contains an array of directories that will be watched for changes and
* used to determine if the hot-reload feature should reload the page or not.
* We restrict the values to keep performance as high as possible.
*
* NOTE: The ROOTPATH will be prepended to all values.
*
* @var string[]
*/
public array $watchedDirectories = ['app', 'modules', 'themes'];
/**
* --------------------------------------------------------------------------
* Watched File Extensions
* --------------------------------------------------------------------------
*
* Contains an array of file extensions that will be watched for changes and
* used to determine if the hot-reload feature should reload the page or not.
*
* @var string[]
*/
public array $watchedExtensions = ['php', 'css', 'js', 'html', 'svg', 'json', 'env'];
}

View File

@ -12,6 +12,7 @@ namespace App\Controllers;
use CodeIgniter\Controller;
use CodeIgniter\HTTP\Response;
use Config\Colors;
class ColorsController extends Controller
{
@ -28,7 +29,7 @@ class ColorsController extends Controller
if (
! ($colorsCssBody = cache($cacheName))
) {
$colorThemes = config('Colors')
$colorThemes = config(Colors::class)
->themes;
$colorsCssBody = '';

View File

@ -64,7 +64,7 @@ class EpisodeAudioController extends Controller
set_user_session_location();
set_user_session_player();
$this->analyticsConfig = config('Analytics');
$this->analyticsConfig = config(Analytics::class);
}
public function _remap(string $method, string ...$params): mixed

View File

@ -21,6 +21,8 @@ use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\Response;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Embed;
use Config\Images;
use Config\Services;
use Modules\Analytics\AnalyticsTrait;
use Modules\Fediverse\Objects\OrderedCollectionObject;
@ -104,8 +106,8 @@ class EpisodeController extends BaseController
// The page cache is set to a decade so it is deleted manually upon podcast update
return view('episode/comments', $data, [
'cache' => $secondsToNextUnpublishedEpisode
? $secondsToNextUnpublishedEpisode
: DECADE,
? $secondsToNextUnpublishedEpisode
: DECADE,
'cache_name' => $cacheName,
]);
}
@ -231,15 +233,15 @@ class EpisodeController extends BaseController
'author_url' => $this->podcast->link,
'html' => '<iframe src="' .
$this->episode->embed_url .
'" width="100%" height="' . config('Embed')->height . '" frameborder="0" scrolling="no"></iframe>',
'width' => config('Embed')
'" width="100%" height="' . config(Embed::class)->height . '" frameborder="0" scrolling="no"></iframe>',
'width' => config(Embed::class)
->width,
'height' => config('Embed')
'height' => config(Embed::class)
->height,
'thumbnail_url' => $this->episode->cover->og_url,
'thumbnail_width' => config('Images')
'thumbnail_width' => config(Images::class)
->podcastCoverSizes['og']['width'],
'thumbnail_height' => config('Images')
'thumbnail_height' => config(Images::class)
->podcastCoverSizes['og']['height'],
]);
}
@ -256,18 +258,20 @@ class EpisodeController extends BaseController
$oembed->addChild('author_name', $this->podcast->title);
$oembed->addChild('author_url', $this->podcast->link);
$oembed->addChild('thumbnail', $this->episode->cover->og_url);
$oembed->addChild('thumbnail_width', (string) config('Images')->podcastCoverSizes['og']['width']);
$oembed->addChild('thumbnail_height', (string) config('Images')->podcastCoverSizes['og']['height']);
$oembed->addChild('thumbnail_width', (string) config(Images::class)->podcastCoverSizes['og']['width']);
$oembed->addChild('thumbnail_height', (string) config(Images::class)->podcastCoverSizes['og']['height']);
$oembed->addChild(
'html',
htmlspecialchars(
'<iframe src="' .
$this->episode->embed_url .
'" width="100%" height="' . config('Embed')->height . '" frameborder="0" scrolling="no"></iframe>',
'" width="100%" height="' . config(
Embed::class
)->height . '" frameborder="0" scrolling="no"></iframe>',
),
);
$oembed->addChild('width', (string) config('Embed')->width);
$oembed->addChild('height', (string) config('Embed')->height);
$oembed->addChild('width', (string) config(Embed::class)->width);
$oembed->addChild('height', (string) config(Embed::class)->height);
// @phpstan-ignore-next-line
return $this->response->setXML($oembed);

View File

@ -14,6 +14,7 @@ use App\Models\PodcastModel;
use CodeIgniter\Database\Exceptions\DatabaseException;
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Cache;
use Modules\Media\FileManagers\FileManagerInterface;
class HomeController extends BaseController
@ -53,7 +54,7 @@ class HomeController extends BaseController
}
// --- Can Castopod connect to the cache handler
if (config('Cache')->handler !== 'dummy' && cache()->getCacheInfo() === null) {
if (config(Cache::class)->handler !== 'dummy' && cache()->getCacheInfo() === null) {
$errors[] = 'Unable connect to the cache handler.';
}

View File

@ -23,6 +23,7 @@ use CodeIgniter\Files\File;
use CodeIgniter\HTTP\Files\UploadedFile;
use CodeIgniter\I18n\Time;
use Exception;
use Config\Images;
use League\CommonMark\Environment\Environment;
use League\CommonMark\Extension\Autolink\AutolinkExtension;
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
@ -199,7 +200,7 @@ class Episode extends Entity
} else {
$cover = new Image([
'file_key' => 'podcasts/' . $this->getPodcast()->handle . '/' . $this->attributes['slug'] . '.' . $file->getExtension(),
'sizes' => config('Images')
'sizes' => config(Images::class)
->podcastCoverSizes,
'uploaded_by' => $this->attributes['updated_by'],
'updated_by' => $this->attributes['updated_by'],

View File

@ -14,6 +14,7 @@ use App\Models\PersonModel;
use CodeIgniter\Entity\Entity;
use CodeIgniter\Files\File;
use CodeIgniter\HTTP\Files\UploadedFile;
use Config\Images;
use Modules\Media\Entities\Image;
use Modules\Media\Models\MediaModel;
use RuntimeException;
@ -71,7 +72,7 @@ class Person extends Entity
} else {
$avatar = new Image([
'file_key' => 'persons/' . $this->attributes['unique_name'] . '.' . $file->getExtension(),
'sizes' => config('Images')
'sizes' => config(Images::class)
->personAvatarSizes,
'uploaded_by' => $this->attributes['updated_by'],
'updated_by' => $this->attributes['updated_by'],

View File

@ -21,6 +21,7 @@ use CodeIgniter\Files\File;
use CodeIgniter\HTTP\Files\UploadedFile;
use CodeIgniter\I18n\Time;
use CodeIgniter\Shield\Entities\User;
use Config\Images;
use Exception;
use League\CommonMark\Environment\Environment;
use League\CommonMark\Extension\Autolink\AutolinkExtension;
@ -247,7 +248,7 @@ class Podcast extends Entity
} else {
$cover = new Image([
'file_key' => 'podcasts/' . $this->attributes['handle'] . '/cover.' . $file->getExtension(),
'sizes' => config('Images')
'sizes' => config(Images::class)
->podcastCoverSizes,
'uploaded_by' => $this->attributes['updated_by'],
'updated_by' => $this->attributes['updated_by'],
@ -290,7 +291,7 @@ class Podcast extends Entity
} else {
$banner = new Image([
'file_key' => 'podcasts/' . $this->attributes['handle'] . '/banner.' . $file->getExtension(),
'sizes' => config('Images')
'sizes' => config(Images::class)
->podcastBannerSizes,
'uploaded_by' => $this->attributes['updated_by'],
'updated_by' => $this->attributes['updated_by'],

View File

@ -4,6 +4,8 @@ declare(strict_types=1);
use App\Entities\Person;
use App\Entities\Podcast;
use Config\App;
use Config\Images;
use Modules\Media\Entities\Image;
/**
@ -23,7 +25,7 @@ if (! function_exists('get_browser_language')) {
function get_browser_language(?string $httpAcceptLanguage = null): string
{
if ($httpAcceptLanguage === null) {
return config('App')->defaultLocale;
return config(App::class)->defaultLocale;
}
$langs = explode(',', $httpAcceptLanguage);
@ -290,7 +292,7 @@ if (! function_exists('format_bytes')) {
if (! function_exists('get_site_icon_url')) {
function get_site_icon_url(string $size): string
{
if (config('App')->siteIcon['ico'] === service('settings')->get('App.siteIcon')['ico']) {
if (config(App::class)->siteIcon['ico'] === service('settings')->get('App.siteIcon')['ico']) {
// return default site icon url
return base_url(service('settings')->get('App.siteIcon')[$size]);
}
@ -304,12 +306,12 @@ if (! function_exists('get_podcast_banner')) {
function get_podcast_banner_url(Podcast $podcast, string $size): string
{
if (! $podcast->banner instanceof Image) {
$defaultBanner = config('Images')
$defaultBanner = config(Images::class)
->podcastBannerDefaultPaths[service('settings')->get('App.theme')] ?? config(
'Images'
Images::class
)->podcastBannerDefaultPaths['default'];
$sizes = config('Images')
$sizes = config(Images::class)
->podcastBannerSizes;
$sizeConfig = $sizes[$size];
@ -330,7 +332,7 @@ if (! function_exists('get_podcast_banner_mimetype')) {
function get_podcast_banner_mimetype(Podcast $podcast, string $size): string
{
if (! $podcast->banner instanceof Image) {
$sizes = config('Images')
$sizes = config(Images::class)
->podcastBannerSizes;
$sizeConfig = $sizes[$size];
@ -338,7 +340,7 @@ if (! function_exists('get_podcast_banner_mimetype')) {
// return default site icon url
return array_key_exists('mimetype', $sizeConfig) ? $sizeConfig['mimetype'] : config(
'Images'
Images::class
)->podcastBannerDefaultMimeType;
}
@ -351,10 +353,10 @@ if (! function_exists('get_avatar_url')) {
function get_avatar_url(Person $person, string $size): string
{
if (! $person->avatar instanceof Image) {
$defaultAvatarPath = config('Images')
$defaultAvatarPath = config(Images::class)
->avatarDefaultPath;
$sizes = config('Images')
$sizes = config(Images::class)
->personAvatarSizes;
$sizeConfig = $sizes[$size];

View File

@ -9,6 +9,7 @@ declare(strict_types=1);
*/
use App\Models\PageModel;
use Config\App;
if (! function_exists('render_page_links')) {
/**
@ -41,8 +42,8 @@ if (! function_exists('render_page_links')) {
}
// if set in .env, add legal notice link at the end of page links
if (config('App')->legalNoticeURL !== null) {
$links .= anchor(config('App')->legalNoticeURL, lang('Common.legal_notice'), [
if (config(App::class)->legalNoticeURL !== null) {
$links .= anchor(config(App::class)->legalNoticeURL, lang('Common.legal_notice'), [
'class' => 'px-2 py-1 underline hover:no-underline focus:ring-accent',
'target' => '_blank',
'rel' => 'noopener noreferrer',

View File

@ -17,6 +17,7 @@ use Config\Mimes;
use Modules\Media\Entities\Chapters;
use Modules\Media\Entities\Transcript;
use Modules\PremiumPodcasts\Entities\Subscription;
use Modules\WebSub\Config\WebSub;
if (! function_exists('get_rss_feed')) {
/**
@ -51,7 +52,7 @@ if (! function_exists('get_rss_feed')) {
$atomLink->addAttribute('type', 'application/rss+xml');
// websub: add links to hubs defined in config
$websubHubs = config('WebSub')
$websubHubs = config(WebSub::class)
->hubs;
foreach ($websubHubs as $websubHub) {
$atomLinkHub = $channel->addChild('link', null, $atomNamespace);

View File

@ -9,6 +9,8 @@ use App\Entities\EpisodeComment;
use App\Entities\Page;
use App\Entities\Podcast;
use App\Entities\Post;
use Config\Embed;
use Config\Images;
use Melbahja\Seo\MetaTags;
use Melbahja\Seo\Schema;
use Melbahja\Seo\Schema\Thing;
@ -56,8 +58,8 @@ if (! function_exists('get_podcast_metatags')) {
->description(esc($podcast->description))
->image((string) $podcast->cover->og_url)
->canonical((string) current_url())
->og('image:width', (string) config('Images')->podcastCoverSizes['og']['width'])
->og('image:height', (string) config('Images')->podcastCoverSizes['og']['height'])
->og('image:width', (string) config(Images::class)->podcastCoverSizes['og']['width'])
->og('image:height', (string) config(Images::class)->podcastCoverSizes['og']['height'])
->og('locale', $podcast->language_code)
->og('site_name', esc(service('settings')->get('App.siteName')))
->push('link', [
@ -106,8 +108,8 @@ if (! function_exists('get_episode_metatags')) {
->image((string) $episode->cover->og_url, 'player')
->canonical($episode->link)
->og('site_name', esc(service('settings')->get('App.siteName')))
->og('image:width', (string) config('Images')->podcastCoverSizes['og']['width'])
->og('image:height', (string) config('Images')->podcastCoverSizes['og']['height'])
->og('image:width', (string) config(Images::class)->podcastCoverSizes['og']['width'])
->og('image:height', (string) config(Images::class)->podcastCoverSizes['og']['height'])
->og('locale', $episode->podcast->language_code)
->og('audio', $episode->audio_opengraph_url)
->og('audio:type', $episode->audio->file_mimetype)
@ -116,8 +118,8 @@ if (! function_exists('get_episode_metatags')) {
->twitter('audio:partner', $episode->podcast->publisher ?? '')
->twitter('audio:artist_name', esc($episode->podcast->owner_name))
->twitter('player', $episode->getEmbedUrl('light'))
->twitter('player:width', (string) config('Embed')->width)
->twitter('player:height', (string) config('Embed')->height)
->twitter('player:width', (string) config(Embed::class)->width)
->twitter('player:height', (string) config(Embed::class)->height)
->push('link', [
'rel' => 'alternate',
'type' => 'application/activity+json',

View File

@ -1,280 +0,0 @@
<?php
declare(strict_types=1);
/**
* This file extends the Router class from the CodeIgniter 4 framework.
*
* It introduces the alternate-content option for a route.
*
* @copyright 2023 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
namespace App\Libraries;
use Closure;
use CodeIgniter\Router\RouteCollection as CodeIgniterRouteCollection;
class RouteCollection extends CodeIgniterRouteCollection
{
/**
* The current hostname from $_SERVER['HTTP_HOST']
*/
private ?string $httpHost = null;
/**
* Does the heavy lifting of creating an actual route. You must specify
* the request method(s) that this route will work for. They can be separated
* by a pipe character "|" if there is more than one.
*
* @param array<int, mixed>|Closure|string $to
* @param array<string, mixed> $options
*/
protected function create(string $verb, string $from, $to, ?array $options = null): void
{
$overwrite = false;
$prefix = $this->group === null ? '' : $this->group . '/';
$from = esc(strip_tags($prefix . $from));
// While we want to add a route within a group of '/',
// it doesn't work with matching, so remove them...
if ($from !== '/') {
$from = trim($from, '/');
}
// When redirecting to named route, $to is an array like `['zombies' => '\Zombies::index']`.
if (is_array($to) && count($to) === 2) {
$to = $this->processArrayCallableSyntax($from, $to);
}
$options = array_merge($this->currentOptions ?? [], $options ?? []);
// Route priority detect
if (isset($options['priority'])) {
$options['priority'] = abs((int) $options['priority']);
if ($options['priority'] > 0) {
$this->prioritizeDetected = true;
}
}
// Hostname limiting?
if (! empty($options['hostname'])) {
// @todo determine if there's a way to whitelist hosts?
if (! $this->checkHostname($options['hostname'])) {
return;
}
$overwrite = true;
}
// Limiting to subdomains?
elseif (! empty($options['subdomain'])) {
// If we don't match the current subdomain, then
// we don't need to add the route.
if (! $this->checkSubdomains($options['subdomain'])) {
return;
}
$overwrite = true;
}
// Are we offsetting the binds?
// If so, take care of them here in one
// fell swoop.
if (isset($options['offset']) && is_string($to)) {
// Get a constant string to work with.
$to = preg_replace('/(\$\d+)/', '$X', $to);
for ($i = (int) $options['offset'] + 1; $i < (int) $options['offset'] + 7; ++$i) {
$to = preg_replace_callback('/\$X/', static fn ($m): string => '$' . $i, $to, 1);
}
}
// Replace our regex pattern placeholders with the actual thing
// so that the Router doesn't need to know about any of this.
foreach ($this->placeholders as $tag => $pattern) {
$from = str_ireplace(':' . $tag, $pattern, $from);
}
// If is redirect, No processing
if (! isset($options['redirect']) && is_string($to)) {
// If no namespace found, add the default namespace
if (strpos($to, '\\') === false || strpos($to, '\\') > 0) {
$namespace = $options['namespace'] ?? $this->defaultNamespace;
$to = trim((string) $namespace, '\\') . '\\' . $to;
}
// Always ensure that we escape our namespace so we're not pointing to
// \CodeIgniter\Routes\Controller::method.
$to = '\\' . ltrim($to, '\\');
}
$name = $options['as'] ?? $from;
helper('array');
// Don't overwrite any existing 'froms' so that auto-discovered routes
// do not overwrite any app/Config/Routes settings. The app
// routes should always be the "source of truth".
// this works only because discovered routes are added just prior
// to attempting to route the request.
// TODO: see how to overwrite routes differently
// restored change that broke Castopod routing with fediverse
// in CI4 v4.2.8 https://github.com/codeigniter4/CodeIgniter4/pull/6644
if (isset($this->routes[$verb][$name]) && ! $overwrite) {
return;
}
$this->routes[$verb][$name] = [
'route' => [
$from => $to,
],
];
$this->routesOptions[$verb][$from] = $options;
// Is this a redirect?
if (isset($options['redirect']) && is_numeric($options['redirect'])) {
$this->routes['*'][$name]['redirect'] = $options['redirect'];
}
}
/**
* Compares the hostname passed in against the current hostname
* on this page request.
*
* @param string $hostname Hostname in route options
*/
private function checkHostname($hostname): bool
{
// CLI calls can't be on hostname.
if ($this->httpHost === null) {
return false;
}
return strtolower($this->httpHost) === strtolower($hostname);
}
/**
* @param array<int, mixed> $to
*
* @return string|array<int, mixed>
*/
private function processArrayCallableSyntax(string $from, array $to): string | array
{
// [classname, method]
// eg, [Home::class, 'index']
if (is_callable($to, true, $callableName)) {
// If the route has placeholders, add params automatically.
$params = $this->getMethodParams($from);
return '\\' . $callableName . $params;
}
// [[classname, method], params]
// eg, [[Home::class, 'index'], '$1/$2']
if (
isset($to[0], $to[1])
&& is_callable($to[0], true, $callableName)
&& is_string($to[1])
) {
return '\\' . $callableName . '/' . $to[1];
}
return $to;
}
/**
* Compares the subdomain(s) passed in against the current subdomain
* on this page request.
*
* @param string|string[] $subdomains
*/
private function checkSubdomains($subdomains): bool
{
// CLI calls can't be on subdomain.
if ($this->httpHost === null) {
return false;
}
if ($this->currentSubdomain === null) {
$this->currentSubdomain = $this->determineCurrentSubdomain();
}
if (! is_array($subdomains)) {
$subdomains = [$subdomains];
}
// Routes can be limited to any sub-domain. In that case, though,
// it does require a sub-domain to be present.
if (! empty($this->currentSubdomain) && in_array('*', $subdomains, true)) {
return true;
}
return in_array($this->currentSubdomain, $subdomains, true);
}
/**
* Returns the method param string like `/$1/$2` for placeholders
*/
private function getMethodParams(string $from): string
{
preg_match_all('/\(.+?\)/', $from, $matches);
$count = is_countable($matches[0]) ? count($matches[0]) : 0;
$params = '';
for ($i = 1; $i <= $count; ++$i) {
$params .= '/$' . $i;
}
return $params;
}
/**
* Examines the HTTP_HOST to get the best match for the subdomain. It
* won't be perfect, but should work for our needs.
*
* It's especially not perfect since it's possible to register a domain
* with a period (.) as part of the domain name.
*
* @return false|string the subdomain
*/
private function determineCurrentSubdomain()
{
// We have to ensure that a scheme exists
// on the URL else parse_url will mis-interpret
// 'host' as the 'path'.
$url = $this->httpHost;
if (strpos($url, 'http') !== 0) {
$url = 'http://' . $url;
}
$parsedUrl = parse_url($url);
$host = explode('.', $parsedUrl['host']);
if ($host[0] === 'www') {
unset($host[0]);
}
// Get rid of any domains, which will be the last
unset($host[count($host) - 1]);
// Account for .co.uk, .co.nz, etc. domains
if (end($host) === 'co') {
$host = array_slice($host, 0, -1);
}
// If we only have 1 part left, then we don't have a sub-domain.
if (count($host) === 1) {
// Set it to false so we don't make it back here again.
return false;
}
return array_shift($host);
}
}

View File

@ -14,7 +14,9 @@ declare(strict_types=1);
namespace App\Libraries;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\Router\Exceptions\RedirectException;
use CodeIgniter\Router\Exceptions\RouterException;
use CodeIgniter\Router\Router as CodeIgniterRouter;
use Config\Services;
@ -40,26 +42,14 @@ class Router extends CodeIgniterRouter
$uri = $uri === '/' ? $uri : trim($uri, '/ ');
// Loop through the route array looking for wildcards
foreach ($routes as $routeKey => $val) {
// Reset localeSegment
$localeSegment = null;
foreach ($routes as $routeKey => $handler) {
$routeKey = $routeKey === '/' ? $routeKey : ltrim($routeKey, '/ ');
$matchedKey = $routeKey;
// Are we dealing with a locale?
if (str_contains($routeKey, '{locale}')) {
$localeSegment = array_search(
'{locale}',
preg_split('~[\/]*((^[a-zA-Z0-9])|\(([^()]*)\))*[\/]+~m', $routeKey),
true,
);
// Replace it with a regex so it
// will actually match.
$routeKey = str_replace('/', '\/', $routeKey);
$routeKey = str_replace('{locale}', '[^\/]+', $routeKey);
if (strpos($routeKey, '{locale}') !== false) {
$routeKey = str_replace('{locale}', '[^/]+', $routeKey);
}
// Does the RegEx match?
@ -68,32 +58,51 @@ class Router extends CodeIgniterRouter
// Is this route supposed to redirect to another?
if ($this->collection->isRedirect($routeKey)) {
// replacing matched route groups with references: post/([0-9]+) -> post/$1
$redirectTo = preg_replace_callback('/(\([^\(]+\))/', static function (): string {
static $i = 1;
return '$' . $i++;
}, (string) (is_array($handler) ? key($handler) : $handler));
throw new RedirectException(
is_array($val) ? key($val) : $val,
$this->collection->getRedirectCode($routeKey),
preg_replace('#^' . $routeKey . '$#u', $redirectTo, $uri),
$this->collection->getRedirectCode($routeKey)
);
}
// Store our locale so CodeIgniter object can
// assign it to the Request.
if (isset($localeSegment)) {
// The following may be inefficient, but doesn't upset NetBeans :-/
$temp = explode('/', $uri);
$this->detectedLocale = $temp[$localeSegment];
if (strpos($matchedKey, '{locale}') !== false) {
preg_match(
'#^' . str_replace('{locale}', '(?<locale>[^/]+)', $matchedKey) . '$#u',
$uri,
$matched
);
if ($this->collection->shouldUseSupportedLocalesOnly()
&& ! in_array($matched['locale'], config(App::class)->supportedLocales, true)) {
// Throw exception to prevent the autorouter, if enabled,
// from trying to find a route
throw PageNotFoundException::forLocaleNotSupported($matched['locale']);
}
$this->detectedLocale = $matched['locale'];
unset($matched);
}
// Are we using Closures? If so, then we need
// to collect the params into an array
// so it can be passed to the controller method later.
if (! is_string($val) && is_callable($val)) {
$this->controller = $val;
if (! is_string($handler) && is_callable($handler)) {
$this->controller = $handler;
// Remove the original string from the matches array
array_shift($matches);
$this->params = $matches;
$this->matchedRoute = [$matchedKey, $val];
$this->setMatchedRoute($matchedKey, $handler);
return true;
}
@ -123,62 +132,74 @@ class Router extends CodeIgniterRouter
$expectedContentType = $parsedHeader[0];
foreach ($supported as $available) {
if (
$negotiate->callMatch($expectedContentType, $available, true)
! $negotiate->callMatch($expectedContentType, $available, true)
) {
if (
array_key_exists(
'namespace',
$this->matchedRouteOptions[
'alternate-content'
][$available],
)
) {
$this->collection->setDefaultNamespace(
$this->matchedRouteOptions[
'alternate-content'
][$available]['namespace'],
);
}
$val =
$this->collection->getDefaultNamespace() .
$this->directory .
$this->matchedRouteOptions['alternate-content'][
$available
]['controller-method'];
// no need to continue loop as $val has been overwritten
break;
continue;
}
if (
array_key_exists(
'namespace',
$this->matchedRouteOptions[
'alternate-content'
][$available],
)
) {
$this->collection->setDefaultNamespace(
$this->matchedRouteOptions[
'alternate-content'
][$available]['namespace'],
);
}
$handler =
$this->collection->getDefaultNamespace() .
$this->directory .
$this->matchedRouteOptions['alternate-content'][
$available
]['controller-method'];
// no need to continue loop as $handle has been overwritten
break;
}
}
// Are we using the default method for back-references?
// Are we using Closures? If so, then we need
// to collect the params into an array
// so it can be passed to the controller method later.
if (! is_string($handler) && is_callable($handler)) {
$this->controller = $handler;
// Support resource route when function with subdirectory
// ex: $routes->resource('Admin/Admins');
if (
str_contains((string) $val, '$') &&
str_contains($routeKey, '(') &&
str_contains($routeKey, '/')
) {
$replacekey = str_replace('/(.*)', '', $routeKey);
$val = preg_replace('#^' . $routeKey . '$#u', (string) $val, $uri);
$val = str_replace($replacekey, str_replace('/', '\\', $replacekey), $val);
} elseif (str_contains((string) $val, '$') && str_contains($routeKey, '(')) {
$val = preg_replace('#^' . $routeKey . '$#u', (string) $val, $uri);
} elseif (str_contains((string) $val, '/')) {
[$controller, $method] = explode('::', (string) $val);
// Remove the original string from the matches array
array_shift($matches);
// Only replace slashes in the controller, not in the method.
$controller = str_replace('/', '\\', $controller);
$this->params = $matches;
$val = $controller . '::' . $method;
$this->setMatchedRoute($matchedKey, $handler);
return true;
}
$this->setRequest(explode('/', (string) $val));
[$controller] = explode('::', (string) $handler);
$this->matchedRoute = [$matchedKey, $val];
// Checks `/` in controller name
if (strpos($controller, '/') !== false) {
throw RouterException::forInvalidControllerName($handler);
}
if (strpos((string) $handler, '$') !== false && strpos($routeKey, '(') !== false) {
// Checks dynamic controller
if (strpos($controller, '$') !== false) {
throw RouterException::forDynamicController($handler);
}
// Using back-references
$handler = preg_replace('#^' . $routeKey . '$#u', (string) $handler, $uri);
}
$this->setRequest(explode('/', (string) $handler));
$this->setMatchedRoute($matchedKey, $handler);
return true;
}

View File

@ -16,7 +16,7 @@ class ComponentRenderer
public function __construct()
{
$this->config = config('ViewComponents');
$this->config = config(ViewComponents::class);
}
public function render(string $output): string

View File

@ -32,7 +32,7 @@ class Theme
public function __construct()
{
$this->config = config('Themes');
$this->config = config(Themes::class);
}
/**
@ -85,7 +85,7 @@ class Theme
{
$themes = [];
$config = config('Themes');
$config = config(Themes::class);
foreach ($config->themes as $name => $folder) {
$themes[] = [

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Vite;
use ErrorException;
use Vite\Config\Vite as ViteConfig;
class Vite
{
@ -20,7 +21,7 @@ class Vite
public function asset(string $path, string $type): string
{
if (config('Vite')->environment !== 'production') {
if (config(ViteConfig::class)->environment !== 'production') {
return $this->loadDev($path, $type);
}
@ -29,7 +30,10 @@ class Vite
private function loadDev(string $path, string $type): string
{
return $this->getHtmlTag(config('Vite')->baseUrl . config('Vite')->assetsRoot . "/{$path}", $type);
return $this->getHtmlTag(
config(ViteConfig::class)->baseUrl . config(ViteConfig::class)->assetsRoot . "/{$path}",
$type
);
}
private function loadProd(string $path, string $type): string
@ -37,8 +41,8 @@ class Vite
if ($this->manifestData === null) {
$cacheName = 'vite-manifest';
if (! ($cachedManifest = cache($cacheName))) {
$manifestPath = config('Vite')
->assetsRoot . '/' . config('Vite')
$manifestPath = config(ViteConfig::class)
->assetsRoot . '/' . config(ViteConfig::class)
->manifestFile;
try {
if (($manifestContents = file_get_contents($manifestPath)) !== false) {
@ -62,7 +66,7 @@ class Vite
// import css dependencies if any
if (array_key_exists('css', $manifestElement)) {
foreach ($manifestElement['css'] as $cssFile) {
$html .= $this->getHtmlTag('/' . config('Vite')->assetsRoot . '/' . $cssFile, 'css');
$html .= $this->getHtmlTag('/' . config(ViteConfig::class)->assetsRoot . '/' . $cssFile, 'css');
}
}
@ -73,19 +77,27 @@ class Vite
// import css dependencies if any
if (array_key_exists('css', $this->manifestData[$importPath])) {
foreach ($this->manifestData[$importPath]['css'] as $cssFile) {
$html .= $this->getHtmlTag('/' . config('Vite')->assetsRoot . '/' . $cssFile, 'css');
$html .= $this->getHtmlTag(
'/' . config(ViteConfig::class)->assetsRoot . '/' . $cssFile,
'css'
);
}
}
$html .= $this->getHtmlTag(
'/' . config('Vite')->assetsRoot . '/' . $this->manifestData[$importPath]['file'],
'/' . config(
ViteConfig::class
)->assetsRoot . '/' . $this->manifestData[$importPath]['file'],
'js'
);
}
}
}
$html .= $this->getHtmlTag('/' . config('Vite')->assetsRoot . '/' . $manifestElement['file'], $type);
$html .= $this->getHtmlTag(
'/' . config(ViteConfig::class)->assetsRoot . '/' . $manifestElement['file'],
$type
);
}
return $html;

View File

@ -14,6 +14,7 @@ namespace App\Models;
use App\Entities\Platform;
use CodeIgniter\Model;
use Config\App;
class PlatformModel extends Model
{
@ -53,7 +54,7 @@ class PlatformModel extends Model
public function getPlatforms(): array
{
if (! ($found = cache('platforms'))) {
$baseUrl = rtrim((string) config('app')->baseURL, '/');
$baseUrl = rtrim(config(App::class)->baseURL, '/');
$found = $this->select(
"*, CONCAT('{$baseUrl}/assets/images/platforms/',`type`,'/',`slug`,'.svg') as icon",
)->findAll();

View File

@ -14,6 +14,7 @@ use App\Entities\Actor;
use App\Entities\Podcast;
use CodeIgniter\HTTP\URI;
use CodeIgniter\Model;
use Config\Fediverse;
use phpseclib\Crypt\RSA;
class PodcastModel extends Model
@ -363,7 +364,7 @@ class PodcastModel extends Model
// delete all cache for podcast actor
cache()
->deleteMatching(config('Fediverse') ->cachePrefix . "actor#{$podcast->actor_id}*");
->deleteMatching(config(Fediverse::class) ->cachePrefix . "actor#{$podcast->actor_id}*");
// delete model requests cache, includes feed / query / episode lists, etc.
cache()

View File

@ -7,7 +7,7 @@
"license": "AGPL-3.0-or-later",
"require": {
"php": "^8.1",
"codeigniter4/framework": "v4.3.8",
"codeigniter4/framework": "v4.4.0",
"james-heinrich/getid3": "^2.0.0-beta5",
"whichbrowser/parser": "^v2.1.7",
"geoip2/geoip2": "v2.13.0",

36
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "bf2ad79ae7e152da4c25f9dfa59e887f",
"content-hash": "4526c68d78e5abe8e5c86016356e15f9",
"packages": [
{
"name": "adaures/ipcat-php",
@ -304,16 +304,16 @@
},
{
"name": "codeigniter4/framework",
"version": "v4.3.8",
"version": "v4.4.0",
"source": {
"type": "git",
"url": "https://github.com/codeigniter4/framework.git",
"reference": "10c23e96db99171bc7632184d0e986e6eecc242d"
"reference": "30008a0e3c342f2b6e5083927bec49feec95ed53"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/codeigniter4/framework/zipball/10c23e96db99171bc7632184d0e986e6eecc242d",
"reference": "10c23e96db99171bc7632184d0e986e6eecc242d",
"url": "https://api.github.com/repos/codeigniter4/framework/zipball/30008a0e3c342f2b6e5083927bec49feec95ed53",
"reference": "30008a0e3c342f2b6e5083927bec49feec95ed53",
"shasum": ""
},
"require": {
@ -370,7 +370,7 @@
"slack": "https://codeigniterchat.slack.com",
"source": "https://github.com/codeigniter4/CodeIgniter4"
},
"time": "2023-08-25T01:47:10+00:00"
"time": "2023-08-25T07:02:01+00:00"
},
{
"name": "codeigniter4/settings",
@ -5427,16 +5427,16 @@
},
{
"name": "symfony/console",
"version": "v6.3.2",
"version": "v6.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "aa5d64ad3f63f2e48964fc81ee45cb318a723898"
"reference": "eca495f2ee845130855ddf1cf18460c38966c8b6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/aa5d64ad3f63f2e48964fc81ee45cb318a723898",
"reference": "aa5d64ad3f63f2e48964fc81ee45cb318a723898",
"url": "https://api.github.com/repos/symfony/console/zipball/eca495f2ee845130855ddf1cf18460c38966c8b6",
"reference": "eca495f2ee845130855ddf1cf18460c38966c8b6",
"shasum": ""
},
"require": {
@ -5488,7 +5488,7 @@
"homepage": "https://symfony.com",
"keywords": ["cli", "command-line", "console", "terminal"],
"support": {
"source": "https://github.com/symfony/console/tree/v6.3.2"
"source": "https://github.com/symfony/console/tree/v6.3.4"
},
"funding": [
{
@ -5504,7 +5504,7 @@
"type": "tidelift"
}
],
"time": "2023-07-19T20:17:28+00:00"
"time": "2023-08-16T10:10:12+00:00"
},
{
"name": "symfony/event-dispatcher",
@ -6059,16 +6059,16 @@
},
{
"name": "symfony/process",
"version": "v6.3.2",
"version": "v6.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "c5ce962db0d9b6e80247ca5eb9af6472bd4d7b5d"
"reference": "0b5c29118f2e980d455d2e34a5659f4579847c54"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/c5ce962db0d9b6e80247ca5eb9af6472bd4d7b5d",
"reference": "c5ce962db0d9b6e80247ca5eb9af6472bd4d7b5d",
"url": "https://api.github.com/repos/symfony/process/zipball/0b5c29118f2e980d455d2e34a5659f4579847c54",
"reference": "0b5c29118f2e980d455d2e34a5659f4579847c54",
"shasum": ""
},
"require": {
@ -6096,7 +6096,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/process/tree/v6.3.2"
"source": "https://github.com/symfony/process/tree/v6.3.4"
},
"funding": [
{
@ -6112,7 +6112,7 @@
"type": "tidelift"
}
],
"time": "2023-07-12T16:00:22+00:00"
"time": "2023-08-07T10:39:22+00:00"
},
{
"name": "symfony/service-contracts",

View File

@ -7,7 +7,6 @@ namespace Modules\Admin\Config;
use CodeIgniter\Router\RouteCollection;
/** @var RouteCollection $routes */
$routes = service('routes');
// video-clips scheduler
$routes->add('scheduled-video-clips', 'SchedulerController::generateVideoClips', [
@ -16,8 +15,7 @@ $routes->add('scheduled-video-clips', 'SchedulerController::generateVideoClips',
// Admin area routes
$routes->group(
config('Admin')
->gateway,
config(Admin::class)->gateway,
[
'namespace' => 'Modules\Admin\Controllers',
],
@ -161,7 +159,7 @@ $routes->group(
'filter' => 'permission:podcast#.delete',
]);
$routes->group('persons', static function ($routes): void {
$routes->get('/', 'PodcastPersonController/$1', [
$routes->get('/', 'PodcastPersonController::index/$1', [
'as' => 'podcast-persons-manage',
'filter' => 'permission:podcast#.manage-persons',
]);
@ -457,7 +455,7 @@ $routes->group(
],
);
$routes->group('persons', static function ($routes): void {
$routes->get('/', 'EpisodePersonController/$1/$2', [
$routes->get('/', 'EpisodePersonController::index/$1/$2', [
'as' => 'episode-persons-manage',
'filter' => 'permission:podcast#.episodes.manage-persons',
]);

View File

@ -11,6 +11,7 @@ declare(strict_types=1);
namespace Modules\Admin\Controllers;
use CodeIgniter\HTTP\RedirectResponse;
use Config\App;
use Config\Services;
class AboutController extends BaseController
@ -22,7 +23,7 @@ class AboutController extends BaseController
'version' => CP_VERSION,
'php_version' => PHP_VERSION,
'os' => PHP_OS,
'languages' => implode(', ', config('App')->supportedLocales),
'languages' => implode(', ', config(App::class)->supportedLocales),
];
return view('about', [

View File

@ -13,6 +13,7 @@ namespace Modules\Admin\Controllers;
use App\Models\EpisodeModel;
use App\Models\PodcastModel;
use CodeIgniter\I18n\Time;
use Config\App;
use Modules\Media\Models\MediaModel;
class DashboardController extends BaseController
@ -50,7 +51,7 @@ class DashboardController extends BaseController
->get()
->getResultArray()[0];
$appStorageLimit = config('App')
$appStorageLimit = config(App::class)
->storageLimit;
if ($appStorageLimit === null || $appStorageLimit < 0) {
$storageLimitBytes = disk_total_space('./');
@ -70,7 +71,7 @@ class DashboardController extends BaseController
->id;
}
$bandwidthLimit = config('App')
$bandwidthLimit = config(App::class)
->bandwidthLimit;
$data = [

View File

@ -32,6 +32,7 @@ use Modules\Analytics\Models\AnalyticsPodcastModel;
use Modules\Analytics\Models\AnalyticsWebsiteByBrowserModel;
use Modules\Analytics\Models\AnalyticsWebsiteByEntryPageModel;
use Modules\Analytics\Models\AnalyticsWebsiteByRefererModel;
use Modules\Auth\Config\AuthGroups;
use Modules\Media\Entities\Image;
use Modules\Media\FileManagers\FileManagerInterface;
use Modules\Media\Models\MediaModel;
@ -255,7 +256,7 @@ class PodcastController extends BaseController
// generate podcast roles and permissions
// before setting current user as podcast admin
config('AuthGroups')
config(AuthGroups::class)
->generatePodcastAuthorizations($newPodcastId);
add_podcast_group(auth()->user(), (int) $newPodcastId, setting('AuthGroups.mostPowerfulPodcastGroup'));

View File

@ -18,8 +18,10 @@ use App\Models\EpisodeModel;
use App\Models\PodcastModel;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\RedirectResponse;
use Config\Colors;
use Modules\Media\Entities\Transcript;
use Modules\Media\Models\MediaModel;
use Modules\MediaClipper\Config\MediaClipper;
class VideoClipsController extends BaseController
{
@ -144,8 +146,8 @@ class VideoClipsController extends BaseController
'title' => 'required',
'start_time' => 'required|greater_than_equal_to[0]',
'duration' => 'required|greater_than[0]',
'format' => 'required|in_list[' . implode(',', array_keys(config('MediaClipper')->formats)) . ']',
'theme' => 'required|in_list[' . implode(',', array_keys(config('Colors')->themes)) . ']',
'format' => 'required|in_list[' . implode(',', array_keys(config(MediaClipper::class)->formats)) . ']',
'theme' => 'required|in_list[' . implode(',', array_keys(config(Colors::class)->themes)) . ']',
];
if (! $this->validate($rules)) {
@ -156,7 +158,7 @@ class VideoClipsController extends BaseController
}
$themeName = $this->request->getPost('theme');
$themeColors = config('MediaClipper')
$themeColors = config(MediaClipper::class)
->themes[$themeName];
$theme = [
'name' => $themeName,

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'breadcrumb',
config('Admin')
config(Admin::class)
->gateway => 'الرئيسية',
'podcasts' => 'بودكاستات',
'episodes' => 'حلقات',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'roll-istor',
config('Admin')
config(Admin::class)
->gateway => 'Degemer',
'podcasts' => 'podkastoù',
'episodes' => 'rannoù',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'Ruta de navegació',
config('Admin')
config(Admin::class)
->gateway => 'Inici',
'podcasts' => 'podcasts',
'episodes' => 'episodis',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'brødkrumme',
config('Admin')
config(Admin::class)
->gateway => 'Hjem',
'podcasts' => 'podcasts',
'episodes' => 'episoder',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'Pfad',
config('Admin')
config(Admin::class)
->gateway => 'Startseite',
'podcasts' => 'Podcasts',
'episodes' => 'Folgen',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'διαδρομή (Breadcrumb)',
config('Admin')
config(Admin::class)
->gateway => 'Αρχική σελίδα',
'podcasts' => 'podcasts',
'episodes' => 'επεισόδια',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'breadcrumb',
config('Admin')
config(Admin::class)
->gateway => 'Home',
'podcasts' => 'podcasts',
'episodes' => 'episodes',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'ruta de navegación',
config('Admin')
config(Admin::class)
->gateway => 'Inicio',
'podcasts' => 'podcasts',
'episodes' => 'episodios',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'breadcrumb',
config('Admin')
config(Admin::class)
->gateway => 'Home',
'podcasts' => 'podcasts',
'episodes' => 'episodes',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'Fil dAriane',
config('Admin')
config(Admin::class)
->gateway => 'Accueil',
'podcasts' => 'podcasts',
'episodes' => 'épisodes',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'fil dAriane',
config('Admin')
config(Admin::class)
->gateway => 'Accueil',
'podcasts' => 'podcasts',
'episodes' => 'épisodes',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'breadcrumb',
config('Admin')
config(Admin::class)
->gateway => 'Home',
'podcasts' => 'podcasts',
'episodes' => 'episodes',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'breadcrumb',
config('Admin')
config(Admin::class)
->gateway => 'Home',
'podcasts' => 'podcasts',
'episodes' => 'episodes',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'breadcrumb',
config('Admin')
config(Admin::class)
->gateway => 'Home',
'podcasts' => 'podcasts',
'episodes' => 'episodes',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'menú',
config('Admin')
config(Admin::class)
->gateway => 'Inicio',
'podcasts' => 'podcasts',
'episodes' => 'episodios',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'breadcrumb',
config('Admin')
config(Admin::class)
->gateway => 'Home',
'podcasts' => 'podcasts',
'episodes' => 'episodes',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'breadcrumb',
config('Admin')
config(Admin::class)
->gateway => 'Home',
'podcasts' => 'podcasts',
'episodes' => 'episodi',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'breadcrumb',
config('Admin')
config(Admin::class)
->gateway => 'Home',
'podcasts' => 'podcasts',
'episodes' => 'episodes',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'breadcrumb',
config('Admin')
config(Admin::class)
->gateway => 'Home',
'podcasts' => 'podcasts',
'episodes' => 'episodes',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'kruimelpad',
config('Admin')
config(Admin::class)
->gateway => 'Hoofdpagina',
'podcasts' => 'podcasts',
'episodes' => 'afleveringen',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'navigeringslenke',
config('Admin')
config(Admin::class)
->gateway => 'Heim',
'podcasts' => 'podkastar',
'episodes' => 'episodar',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'breadcrumb',
config('Admin')
config(Admin::class)
->gateway => 'Home',
'podcasts' => 'podcasts',
'episodes' => 'episodes',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'okruszki',
config('Admin')
config(Admin::class)
->gateway => 'Początek',
'podcasts' => 'podcasty',
'episodes' => 'odcinki',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'breadcrumb',
config('Admin')
config(Admin::class)
->gateway => 'Início',
'podcasts' => 'podcasts',
'episodes' => 'episódios',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'breadcrumb',
config('Admin')
config(Admin::class)
->gateway => 'Home',
'podcasts' => 'podcasts',
'episodes' => 'episodes',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'breadcrumb',
config('Admin')
config(Admin::class)
->gateway => 'Home',
'podcasts' => 'podcasts',
'episodes' => 'episodes',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'навигационная цепочка',
config('Admin')
config(Admin::class)
->gateway => 'Главная',
'podcasts' => 'подкасты',
'episodes' => 'выпуски',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'omrvinky',
config('Admin')
config(Admin::class)
->gateway => 'Úvod',
'podcasts' => 'podcasty',
'episodes' => 'časti',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'breadcrumb polja',
config('Admin')
config(Admin::class)
->gateway => 'Početna',
'podcasts' => 'podkasti',
'episodes' => 'epizode',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'breadcrumb',
config('Admin')
config(Admin::class)
->gateway => 'Hem',
'podcasts' => 'podcasts',
'episodes' => 'avsnitt',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => 'breadcrumb',
config('Admin')
config(Admin::class)
->gateway => 'Home',
'podcasts' => 'podcasts',
'episodes' => 'episodes',

View File

@ -2,6 +2,8 @@
declare(strict_types=1);
use Modules\Admin\Config\Admin;
/**
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
@ -10,7 +12,7 @@ declare(strict_types=1);
return [
'label' => '面包屑导航',
config('Admin')
config(Admin::class)
->gateway => '主页',
'podcasts' => '播客',
'episodes' => '剧集',

View File

@ -2,13 +2,16 @@
declare(strict_types=1);
use CodeIgniter\Router\RouteCollection;
use Modules\Analytics\Config\Analytics;
/**
* @copyright 2021 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
$routes = service('routes');
/** @var RouteCollection $routes */
/**
* Analytics routes file
@ -25,17 +28,17 @@ $routes->addPlaceholder(
$routes->group('', [
'namespace' => 'Modules\Analytics\Controllers',
], static function ($routes): void {
$routes->group(config('Analytics')->gateway . '/(:num)/(:class)', static function ($routes): void {
$routes->group(config(Analytics::class)->gateway . '/(:num)/(:class)', static function ($routes): void {
$routes->get('/', 'AnalyticsController::getData/$1/$2', [
'as' => 'analytics-full-data',
'filter' => config('Analytics')
'filter' => config(Analytics::class)
->routeFilters[
'analytics-full-data'
],
]);
$routes->get('(:filter)', 'AnalyticsController::getData/$1/$2/$3', [
'as' => 'analytics-data',
'filter' => config('Analytics')
'filter' => config(Analytics::class)
->routeFilters['analytics-data'],
]);
$routes->get(
@ -43,14 +46,14 @@ $routes->group('', [
'AnalyticsController::getData/$1/$2/$3/$4',
[
'as' => 'analytics-filtered-data',
'filter' => config('Analytics')
'filter' => config(Analytics::class)
->routeFilters[
'analytics-filtered-data'
],
],
);
});
$routes->get(config('Analytics')->gateway . '/(:class)/(:filter)', 'AnalyticsController::getData/$1/$2', [
$routes->get(config(Analytics::class)->gateway . '/(:class)/(:filter)', 'AnalyticsController::getData/$1/$2', [
'as' => 'analytics-data-instance',
]);
@ -63,4 +66,4 @@ $routes->group('', [
// Show the Unknown UserAgents
$routes->get('.well-known/unknown-useragents', 'UnknownUserAgentsController');
$routes->get('.well-known/unknown-useragents/(:num)', 'UnknownUserAgentsController/$1');
$routes->get('.well-known/unknown-useragents/(:num)', 'UnknownUserAgentsController::index/$1');

View File

@ -11,6 +11,7 @@ declare(strict_types=1);
use AdAures\Ipcat\IpDb;
use Config\Services;
use GeoIp2\Database\Reader;
use Modules\Analytics\Config\Analytics;
use Opawg\UserAgentsPhp\UserAgents;
use WhichBrowser\Parser;
@ -260,7 +261,7 @@ if (! function_exists('podcast_hit')) {
? $_SERVER['HTTP_RANGE']
: null;
$salt = config('Analytics')
$salt = config(Analytics::class)
->salt;
// We create a sha1 hash for this Salt+Current_Date+IP_Address+User_Agent+Episode_ID (used to count only once multiple episode downloads):
$episodeListenerHashId =

View File

@ -4,10 +4,12 @@ declare(strict_types=1);
namespace Modules\Api\Rest\V1\Config;
$routes = service('routes');
use CodeIgniter\Router\RouteCollection;
/** @var RouteCollection $routes */
$routes->group(
config('RestApi')
config(RestApi::class)
->gateway . 'podcasts',
[
'namespace' => 'Modules\Api\Rest\V1\Controllers',
@ -21,7 +23,7 @@ $routes->group(
);
$routes->group(
config('RestApi')
config(RestApi::class)
->gateway . 'episodes',
[
'namespace' => 'Modules\Api\Rest\V1\Controllers',

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Modules\Api\Rest\V1\Config;
use CodeIgniter\Config\BaseService;
use Config\Exceptions as ExceptionsConfig;
use Modules\Api\Rest\V1\Core\Exceptions;
class Services extends BaseService
@ -15,6 +16,6 @@ class Services extends BaseService
return static::getSharedInstance('restApiExceptions');
}
return new Exceptions(config('Exceptions'), static::request(), static::response());
return new Exceptions(config(ExceptionsConfig::class), static::request(), static::response());
}
}

View File

@ -9,6 +9,7 @@ use App\Models\EpisodeModel;
use CodeIgniter\API\ResponseTrait;
use CodeIgniter\Controller;
use CodeIgniter\HTTP\Response;
use Modules\Api\Rest\V1\Config\RestApi;
use Modules\Api\Rest\V1\Config\Services;
class EpisodeController extends Controller
@ -45,7 +46,7 @@ class EpisodeController extends Controller
}
$data = $builder->findAll(
(int) ($this->request->getGet('limit') ?? config('RestApi')->limit),
(int) ($this->request->getGet('limit') ?? config(RestApi::class)->limit),
(int) $this->request->getGet('offset')
);

View File

@ -20,7 +20,7 @@ class ApiFilter implements FilterInterface
public function before(RequestInterface $request, $arguments = null)
{
/** @var RestApi $restApiConfig */
$restApiConfig = config('RestApi');
$restApiConfig = config(RestApi::class);
if (! $restApiConfig->enabled) {
throw PageNotFoundException::forPageNotFound();

View File

@ -6,6 +6,8 @@ namespace Modules\Auth;
use CodeIgniter\Router\RouteCollection;
use CodeIgniter\Shield\Auth as ShieldAuth;
use Modules\Auth\Config\Auth as AuthConfig;
use Modules\Auth\Config\AuthRoutes;
class Auth extends ShieldAuth
{
@ -19,10 +21,10 @@ class Auth extends ShieldAuth
*/
public function routes(RouteCollection &$routes, array $config = []): void
{
$authRoutes = config('AuthRoutes')
$authRoutes = config(AuthRoutes::class)
->routes;
$routes->group(config('Auth')->gateway, [
$routes->group(config(AuthConfig::class)->gateway, [
'namespace' => 'Modules\Auth\Controllers',
], static function (RouteCollection $routes) use ($authRoutes, $config): void {
foreach ($authRoutes as $name => $row) {

View File

@ -7,6 +7,7 @@ namespace Modules\Auth\Config;
use CodeIgniter\Shield\Authentication\Actions\ActionInterface;
use CodeIgniter\Shield\Authentication\Actions\Email2FA;
use CodeIgniter\Shield\Config\Auth as ShieldAuth;
use Modules\Admin\Config\Admin;
use Modules\Auth\Models\UserModel;
class Auth extends ShieldAuth
@ -119,7 +120,7 @@ class Auth extends ShieldAuth
{
parent::__construct();
$adminGateway = config('Admin')
$adminGateway = config(Admin::class)
->gateway;
$this->redirects = [

View File

@ -4,14 +4,19 @@ declare(strict_types=1);
namespace Modules\Auth\Config;
$routes = service('routes');
use CodeIgniter\Router\RouteCollection;
use Modules\Admin\Config\Admin;
/**
* @var RouteCollection $routes
*/
service('auth')
->routes($routes);
// Admin routes for users and podcast contributors
$routes->group(
config('Admin')
config(Admin::class)
->gateway,
[
'namespace' => 'Modules\Auth\Controllers',

View File

@ -7,6 +7,7 @@ namespace Modules\Auth\Config;
use CodeIgniter\Shield\Authentication\Authentication;
use Config\Services as BaseService;
use Modules\Auth\Auth;
use Modules\Auth\Config\Auth as AuthConfig;
class Services extends BaseService
{
@ -16,10 +17,11 @@ class Services extends BaseService
public static function auth(bool $getShared = true): Auth
{
if ($getShared) {
/** @var Auth */
return self::getSharedInstance('auth');
}
$config = config('Auth');
$config = config(AuthConfig::class);
return new Auth(new Authentication($config));
}

View File

@ -8,6 +8,7 @@ use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Shield\Controllers\MagicLinkController as ShieldMagicLinkController;
use Modules\Auth\Config\Auth;
use Modules\Auth\Models\UserModel;
use Psr\Log\LoggerInterface;
use ViewThemes\Theme;
@ -32,7 +33,7 @@ class MagicLinkController extends ShieldMagicLinkController
public function setPasswordView(): string | RedirectResponse
{
if (! session('magicLogin')) {
return redirect()->to(config('Auth')->loginRedirect());
return redirect()->to(config(Auth::class)->loginRedirect());
}
return view(setting('Auth.views')['magic-link-set-password']);
@ -70,7 +71,7 @@ class MagicLinkController extends ShieldMagicLinkController
}
// Success!
return redirect()->to(config('Auth')->loginRedirect())
return redirect()->to(config(Auth::class)->loginRedirect())
->with('message', lang('MyAccount.messages.passwordChangeSuccess'));
}
}

View File

@ -2,13 +2,15 @@
declare(strict_types=1);
use CodeIgniter\Router\RouteCollection;
/**
* @copyright 2021 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
$routes = service('routes');
/** @var RouteCollection $routes */
$routes->addPlaceholder('actorUsername', '[a-zA-Z0-9\_]{1,32}');
$routes->addPlaceholder(
@ -35,7 +37,7 @@ $routes->group('', [
// Actor
$routes->group('@(:actorUsername)', static function ($routes): void {
// Actor
$routes->get('/', 'ActorController/$1', [
$routes->get('/', 'ActorController::index/$1', [
'as' => 'actor',
]);
$routes->post('inbox', 'ActorController::inbox/$1', [
@ -61,10 +63,10 @@ $routes->group('', [
$routes->post('posts/new', 'PostController::attemptCreate/$1', [
'as' => 'post-attempt-create',
]);
$routes->get('posts/(:uuid)', 'PostController/$1', [
$routes->get('posts/(:uuid)', 'PostController::index/$1', [
'as' => 'post',
]);
$routes->get('posts/(:uuid)/replies', 'PostController/$1', [
$routes->get('posts/(:uuid)/replies', 'PostController::index/$1', [
'as' => 'post-replies',
]);
$routes->post(

View File

@ -35,7 +35,7 @@ class ActorController extends Controller
public function __construct()
{
$this->config = config('Fediverse');
$this->config = config(Fediverse::class);
}
public function _remap(string $method, string ...$params): mixed

View File

@ -12,6 +12,7 @@ namespace Modules\Fediverse\Controllers;
use CodeIgniter\Controller;
use CodeIgniter\HTTP\ResponseInterface;
use Modules\Auth\Config\Auth;
class NodeInfo2Controller extends Controller
{
@ -35,7 +36,7 @@ class NodeInfo2Controller extends Controller
'version' => CP_VERSION,
],
'protocols' => ['activitypub'],
'openRegistrations' => config('Auth')
'openRegistrations' => config(Auth::class)
->allowRegistration,
'usage' => [
'users' => [

View File

@ -45,7 +45,7 @@ class PostController extends Controller
public function __construct()
{
$this->config = config('Fediverse');
$this->config = config(Fediverse::class);
}
public function _remap(string $method, string ...$params): mixed

View File

@ -11,6 +11,7 @@ declare(strict_types=1);
namespace Modules\Fediverse\Entities;
use CodeIgniter\Entity\Entity;
use Modules\Fediverse\Config\Fediverse;
use RuntimeException;
/**
@ -111,7 +112,7 @@ class Actor extends Entity
public function getAvatarImageUrl(): string
{
if ($this->attributes['avatar_image_url'] === null) {
return base_url(config('Fediverse')->defaultAvatarImagePath);
return base_url(config(Fediverse::class)->defaultAvatarImagePath);
}
return $this->attributes['avatar_image_url'];
@ -120,7 +121,7 @@ class Actor extends Entity
public function getAvatarImageMimetype(): string
{
if ($this->attributes['avatar_image_mimetype'] === null) {
return config('Fediverse')->defaultAvatarImageMimetype;
return config(Fediverse::class)->defaultAvatarImageMimetype;
}
return $this->attributes['avatar_image_mimetype'];
@ -129,7 +130,7 @@ class Actor extends Entity
public function getCoverImageUrl(): string
{
if ($this->attributes['cover_image_url'] === null) {
return base_url(config('Fediverse')->defaultCoverImagePath);
return base_url(config(Fediverse::class)->defaultCoverImagePath);
}
return $this->attributes['cover_image_url'];
@ -138,7 +139,7 @@ class Actor extends Entity
public function getCoverImageMimetype(): string
{
if ($this->attributes['cover_image_mimetype'] === null) {
return config('Fediverse')->defaultCoverImageMimetype;
return config(Fediverse::class)->defaultCoverImageMimetype;
}
return $this->attributes['cover_image_mimetype'];

View File

@ -14,6 +14,7 @@ use CodeIgniter\Database\BaseResult;
use CodeIgniter\I18n\Time;
use DateTimeInterface;
use Michalsn\Uuid\UuidModel;
use Modules\Fediverse\Config\Fediverse;
use Modules\Fediverse\Entities\Activity;
class ActivityModel extends UuidModel
@ -77,7 +78,7 @@ class ActivityModel extends UuidModel
public function getActivityById(string $activityId): ?Activity
{
$cacheName =
config('Fediverse')
config(Fediverse::class)
->cachePrefix . "activity#{$activityId}";
if (! ($found = cache($cacheName))) {
$found = $this->find($activityId);

View File

@ -12,6 +12,7 @@ namespace Modules\Fediverse\Models;
use CodeIgniter\Events\Events;
use CodeIgniter\Model;
use Modules\Fediverse\Config\Fediverse;
use Modules\Fediverse\Entities\Actor;
class ActorModel extends Model
@ -98,7 +99,7 @@ class ActorModel extends Model
{
$hashedActorUri = md5($actorUri);
$cacheName =
config('Fediverse')
config(Fediverse::class)
->cachePrefix . "actor-{$hashedActorUri}";
if (! ($found = cache($cacheName))) {
$found = $this->where('uri', $actorUri)
@ -117,7 +118,7 @@ class ActorModel extends Model
public function getFollowers(int $actorId): array
{
$cacheName =
config('Fediverse')
config(Fediverse::class)
->cachePrefix . "actor#{$actorId}_followers";
if (! ($found = cache($cacheName))) {
$found = $this->join('fediverse_follows', 'fediverse_follows.actor_id = id', 'inner')
@ -150,7 +151,7 @@ class ActorModel extends Model
*/
public function getBlockedActors(): array
{
$cacheName = config('Fediverse')
$cacheName = config(Fediverse::class)
->cachePrefix . 'blocked_actors';
if (! ($found = cache($cacheName))) {
$found = $this->where('is_blocked', 1)
@ -165,7 +166,7 @@ class ActorModel extends Model
public function blockActor(int $actorId): void
{
$prefix = config('Fediverse')
$prefix = config(Fediverse::class)
->cachePrefix;
cache()
->delete($prefix . 'blocked_actors');
@ -181,7 +182,7 @@ class ActorModel extends Model
public function unblockActor(int $actorId): void
{
$prefix = config('Fediverse')
$prefix = config(Fediverse::class)
->cachePrefix;
cache()
->delete($prefix . 'blocked_actors');
@ -199,7 +200,7 @@ class ActorModel extends Model
{
helper('fediverse');
$cacheName = config('Fediverse')
$cacheName = config(Fediverse::class)
->cachePrefix . 'blocked_actors';
if (! ($found = cache($cacheName))) {
$result = $this->select('COUNT(*) as total_local_actors')
@ -220,10 +221,10 @@ class ActorModel extends Model
{
helper('fediverse');
$cacheName = config('Fediverse')
$cacheName = config(Fediverse::class)
->cachePrefix . 'blocked_actors';
if (! ($found = cache($cacheName))) {
$tablePrefix = config('Database')
$tablePrefix = config(Database::class)
->default['DBPrefix'];
$result = $this->select('COUNT(DISTINCT `cp_fediverse_actors`.`id`) as `total_active_actors`', false)
->join(
@ -297,7 +298,7 @@ class ActorModel extends Model
public function clearCache(Actor $actor): void
{
$cachePrefix = config('Fediverse')
$cachePrefix = config(Fediverse::class)
->cachePrefix;
$hashedActorUri = md5($actor->uri);
$cacheDomain = str_replace(':', '', $actor->domain);

View File

@ -13,6 +13,7 @@ namespace Modules\Fediverse\Models;
use CodeIgniter\Database\BaseResult;
use CodeIgniter\Events\Events;
use CodeIgniter\Model;
use Modules\Fediverse\Config\Fediverse;
use Modules\Fediverse\Entities\BlockedDomain;
class BlockedDomainModel extends Model
@ -56,7 +57,7 @@ class BlockedDomainModel extends Model
*/
public function getBlockedDomains(): array
{
$cacheName = config('Fediverse')
$cacheName = config(Fediverse::class)
->cachePrefix . 'blocked_domains';
if (! ($found = cache($cacheName))) {
$found = $this->findAll();
@ -72,7 +73,7 @@ class BlockedDomainModel extends Model
{
$hashedDomainName = md5($name);
$cacheName =
config('Fediverse')
config(Fediverse::class)
->cachePrefix .
"domain#{$hashedDomainName}_isBlocked";
if (! ($found = cache($cacheName))) {
@ -88,7 +89,7 @@ class BlockedDomainModel extends Model
public function blockDomain(string $name): int | bool
{
$hashedDomain = md5($name);
$prefix = config('Fediverse')
$prefix = config(Fediverse::class)
->cachePrefix;
cache()
->delete($prefix . "domain#{$hashedDomain}_isBlocked");
@ -120,7 +121,7 @@ class BlockedDomainModel extends Model
public function unblockDomain(string $name): BaseResult | bool
{
$hashedDomain = md5($name);
$prefix = config('Fediverse')
$prefix = config(Fediverse::class)
->cachePrefix;
cache()
->delete($prefix . "domain#{$hashedDomain}_isBlocked");

View File

@ -20,6 +20,7 @@ use Modules\Fediverse\Activities\AnnounceActivity;
use Modules\Fediverse\Activities\CreateActivity;
use Modules\Fediverse\Activities\DeleteActivity;
use Modules\Fediverse\Activities\UndoActivity;
use Modules\Fediverse\Config\Fediverse;
use Modules\Fediverse\Entities\Actor;
use Modules\Fediverse\Entities\Post;
use Modules\Fediverse\Objects\TombstoneObject;
@ -97,7 +98,7 @@ class PostModel extends UuidModel
{
$hashedPostUri = md5($postUri);
$cacheName =
config('Fediverse')
config(Fediverse::class)
->cachePrefix . "post-{$hashedPostUri}";
if (! ($found = cache($cacheName))) {
$found = $this->where('uri', $postUri)
@ -118,7 +119,7 @@ class PostModel extends UuidModel
public function getActorPublishedPosts(int $actorId): array
{
$cacheName =
config('Fediverse')
config(Fediverse::class)
->cachePrefix .
"actor#{$actorId}_published_posts";
if (! ($found = cache($cacheName))) {
@ -167,7 +168,7 @@ class PostModel extends UuidModel
public function getPostReplies(string $postId, bool $withBlocked = false): array
{
$cacheName =
config('Fediverse')
config(Fediverse::class)
->cachePrefix .
"post#{$postId}_replies" .
($withBlocked ? '_withBlocked' : '');
@ -199,7 +200,7 @@ class PostModel extends UuidModel
public function getPostReblogs(string $postId): array
{
$cacheName =
config('Fediverse')
config(Fediverse::class)
->cachePrefix . "post#{$postId}_reblogs";
if (! ($found = cache($cacheName))) {
@ -276,7 +277,7 @@ class PostModel extends UuidModel
$post->uri = url_to('post', esc($post->actor->username), $newPostId);
$createActivity = new CreateActivity();
$noteObjectClass = config('Fediverse')
$noteObjectClass = config(Fediverse::class)
->noteObject;
$createActivity
->set('actor', $post->actor->uri)
@ -591,7 +592,7 @@ class PostModel extends UuidModel
{
helper('fediverse');
$cacheName = config('Fediverse')
$cacheName = config(Fediverse::class)
->cachePrefix . 'blocked_actors';
if (! ($found = cache($cacheName))) {
$result = $this->select('COUNT(*) as total_local_posts')
@ -660,7 +661,7 @@ class PostModel extends UuidModel
public function clearCache(Post $post): void
{
$cachePrefix = config('Fediverse')
$cachePrefix = config(Fediverse::class)
->cachePrefix;
$hashedPostUri = md5($post->uri);

View File

@ -12,6 +12,7 @@ namespace Modules\Fediverse\Models;
use CodeIgniter\Database\BaseResult;
use CodeIgniter\Model;
use Modules\Fediverse\Config\Fediverse;
use Modules\Fediverse\Entities\PreviewCard;
class PreviewCardModel extends Model
@ -57,7 +58,7 @@ class PreviewCardModel extends Model
{
$hashedPreviewCardUrl = md5($url);
$cacheName =
config('Fediverse')
config(Fediverse::class)
->cachePrefix .
"preview_card-{$hashedPreviewCardUrl}";
if (! ($found = cache($cacheName))) {
@ -73,7 +74,7 @@ class PreviewCardModel extends Model
public function getPostPreviewCard(string $postId): ?PreviewCard
{
$cacheName =
config('Fediverse')
config(Fediverse::class)
->cachePrefix . "post#{$postId}_preview_card";
if (! ($found = cache($cacheName))) {
$found = $this->join(
@ -95,7 +96,7 @@ class PreviewCardModel extends Model
{
$hashedPreviewCardUrl = md5($url);
cache()
->delete(config('Fediverse') ->cachePrefix . "preview_card-{$hashedPreviewCardUrl}");
->delete(config(Fediverse::class) ->cachePrefix . "preview_card-{$hashedPreviewCardUrl}");
return $this->delete($id);
}

View File

@ -4,11 +4,13 @@ declare(strict_types=1);
namespace Modules\Install\Config;
$routes = service('routes');
use CodeIgniter\Router\RouteCollection;
/** @var RouteCollection $routes */
// Install Wizard routes
$routes->group(
config('Install')
config(Install::class)
->gateway,
[
'namespace' => 'Modules\Install\Controllers',

View File

@ -17,11 +17,13 @@ use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Shield\Entities\User;
use Config\App;
use Config\Database;
use Config\Services;
use Dotenv\Dotenv;
use Dotenv\Exception\ValidationException;
use Modules\Auth\Models\UserModel;
use Modules\Install\Config\Install;
use Psr\Log\LoggerInterface;
use Throwable;
use ViewThemes\Theme;
@ -158,7 +160,9 @@ class InstallController extends Controller
if (! $this->validate($rules)) {
return redirect()
->to((host_url() === null ? config('App') ->baseURL : host_url()) . config('Install')->gateway)
->to(
(host_url() === null ? config(App::class) ->baseURL : host_url()) . config(Install::class)->gateway
)
->withInput()
->with('errors', $this->validator->getErrors());
}
@ -176,7 +180,7 @@ class InstallController extends Controller
helper('text');
// redirect to full install url with new baseUrl input
return redirect()->to(reduce_double_slashes($baseUrl . '/' . config('Install')->gateway));
return redirect()->to(reduce_double_slashes($baseUrl . '/' . config(Install::class)->gateway));
}
public function databaseConfig(): string

View File

@ -2,13 +2,15 @@
declare(strict_types=1);
use CodeIgniter\Router\RouteCollection;
/**
* @copyright 2023 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
$routes = service('routes');
/** @var RouteCollection $routes */
$routes->get('static/(:any)', 'MediaController::serve/$1', [
'as' => 'media-serve',

View File

@ -27,8 +27,7 @@ class Services extends BaseService
return self::getSharedInstance('file_manager');
}
/** @var MediaConfig $config * */
$config = config('Media');
$config = config(MediaConfig::class);
$fileManagerClass = $config->fileManagers[$config->fileManager];
$fileManager = new $fileManagerClass($config);

View File

@ -59,9 +59,9 @@ class BaseMedia extends Entity
/**
* @param array<string, mixed> $data
*/
public function setAttributes(array $data): self
public function injectRawData(array $data): static
{
parent::setAttributes($data);
parent::injectRawData($data);
$this->initFileProperties();

View File

@ -54,9 +54,9 @@ class Image extends BaseMedia
/**
* @param array<string, string> $data
*/
public function setAttributes(array $data): self
public function injectRawData(array $data): static
{
parent::setAttributes($data);
parent::injectRawData($data);
if ($this->attributes === []) {
return $this;

View File

@ -150,6 +150,6 @@ class FS implements FileManagerInterface
$uri = trim($uri, '/');
return config('Media')->storage . '/' . config('Media')->root . '/' . $uri;
return config(MediaConfig::class)->storage . '/' . config(MediaConfig::class)->root . '/' . $uri;
}
}

View File

@ -9,6 +9,7 @@ use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\Files\File;
use CodeIgniter\I18n\Time;
use Exception;
use Modules\Admin\Config\Admin;
use Modules\MediaClipper\VideoClipper;
class Generate extends BaseCommand
@ -24,7 +25,7 @@ class Generate extends BaseCommand
// get number of running clips to prevent from having too much running in parallel
// TODO: get the number of running ffmpeg processes directly from the machine?
$runningVideoClips = (new ClipModel())->getRunningVideoClipsCount();
if ($runningVideoClips >= config('Admin')->videoClipWorkers) {
if ($runningVideoClips >= config(Admin::class)->videoClipWorkers) {
return;
}

View File

@ -15,6 +15,7 @@ use Exception;
use GdImage;
use Modules\Media\Entities\Transcript;
use Modules\Media\FileManagers\FileManagerInterface;
use Modules\MediaClipper\Config\MediaClipper;
/**
* TODO: refactor this by splitting process modules into different classes (image generation, subtitles clip, video
@ -80,9 +81,9 @@ class VideoClipper
) {
$this->duration = $end - $start;
$this->episodeNumbering = $this->episodeNumbering($this->episode->number, $this->episode->season_number);
$this->dimensions = config('MediaClipper')
$this->dimensions = config(MediaClipper::class)
->formats[$format];
$this->colors = config('MediaClipper')
$this->colors = config(MediaClipper::class)
->themes[$theme];
/** @var FileManagerInterface $fileManager */
@ -238,7 +239,7 @@ class VideoClipper
) . ":text='%{pts\:gmtime\:{$this->start}\:%H\\\\\\\\\\:%M\\\\\\\\\\:%S\}':x={$this->dimensions['timestamp']['x']}:y={$this->dimensions['timestamp']['y']}:fontsize={$this->dimensions['timestamp']['fontsize']}:fontcolor=0x{$this->colors['timestampText']}:box=1:boxcolor=0x{$this->colors['timestampBg']}:boxborderw={$this->dimensions['timestamp']['padding']}[v3]",
"color=c=0x{$this->colors['progressbar']}:s={$this->dimensions['width']}x{$this->dimensions['progressbar']['height']}[progressbar]",
"[v3][progressbar]overlay=-w+(w/{$this->duration})*t:0:shortest=1:format=rgb,subtitles={$this->subtitlesClipOutput}:fontsdir=" . config(
'MediaClipper'
MediaClipper::class
)->fontsFolder . ":force_style='Fontname=" . self::FONTS['subtitles'] . ",Alignment=5,Fontsize={$this->dimensions['subtitles']['fontsize']},PrimaryColour=&H{$this->colors['subtitles']}&,BorderStyle=1,Outline=0,Shadow=0,MarginL={$this->dimensions['subtitles']['marginL']},MarginR={$this->dimensions['subtitles']['marginR']},MarginV={$this->dimensions['subtitles']['marginV']}'[outv]",
"[6:v]scale={$this->dimensions['watermark']['width']}:{$this->dimensions['watermark']['height']}[watermark]",
"color=0x{$this->colors['watermarkBg']}:{$this->dimensions['watermark']['width']}x{$this->dimensions['watermark']['height']}[over]",
@ -247,7 +248,7 @@ class VideoClipper
'[watermarked]scale=w=-1:h=-1:out_color_matrix=bt709[outfinal]',
];
$watermark = config('MediaClipper')
$watermark = config(MediaClipper::class)
->watermark;
$videoClipCmd = [
@ -402,7 +403,7 @@ class VideoClipper
);
// Add quotes for subtitles
$quotes = imagecreatefrompng(config('MediaClipper')->quotesImage);
$quotes = imagecreatefrompng(config(MediaClipper::class)->quotesImage);
if (! $quotes) {
return false;
@ -480,7 +481,7 @@ class VideoClipper
private function getFont(string $name): string
{
return config('MediaClipper')->fontsFolder . self::FONTS[$name];
return config(MediaClipper::class)->fontsFolder . self::FONTS[$name];
}
private function generateBackground(int $width, int $height): ?GdImage

View File

@ -21,6 +21,7 @@ use CodeIgniter\Shield\Entities\User;
use Config\Services;
use Exception;
use League\HTMLToMarkdown\HtmlConverter;
use Modules\Auth\Config\AuthGroups;
use Modules\Auth\Models\UserModel;
use Modules\PodcastImport\Entities\PodcastImportTask;
use Modules\PodcastImport\Entities\TaskStatus;
@ -256,7 +257,7 @@ class PodcastImport extends BaseCommand
// set current user as podcast admin
// 1. create new group
config('AuthGroups')
config(AuthGroups::class)
->generatePodcastAuthorizations($podcast->id);
add_podcast_group($this->user, $podcast->id, 'admin');

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