diff --git a/app/Config/App.php b/app/Config/App.php index ab7efc97..164763a3 100644 --- a/app/Config/App.php +++ b/app/Config/App.php @@ -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 diff --git a/app/Config/CURLRequest.php b/app/Config/CURLRequest.php index a0484ca7..040800df 100644 --- a/app/Config/CURLRequest.php +++ b/app/Config/CURLRequest.php @@ -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; } diff --git a/app/Config/Cookie.php b/app/Config/Cookie.php index 0a051c41..26e5da56 100644 --- a/app/Config/Cookie.php +++ b/app/Config/Cookie.php @@ -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'; diff --git a/app/Config/Database.php b/app/Config/Database.php index aca95f04..0f5d9aeb 100644 --- a/app/Config/Database.php +++ b/app/Config/Database.php @@ -27,23 +27,24 @@ class Database extends Config * @var array */ 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, ]; /** diff --git a/app/Config/Events.php b/app/Config/Events.php index 30419869..bedbc5bd 100644 --- a/app/Config/Events.php +++ b/app/Config/Events.php @@ -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(); + }); + } } }); diff --git a/app/Config/Exceptions.php b/app/Config/Exceptions.php index 0c7c681f..248cc3be 100644 --- a/app/Config/Exceptions.php +++ b/app/Config/Exceptions.php @@ -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); + } } diff --git a/app/Config/Fediverse.php b/app/Config/Fediverse.php index f42d4558..e9f46680 100644 --- a/app/Config/Fediverse.php +++ b/app/Config/Fediverse.php @@ -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 !== '.') { diff --git a/app/Config/Filters.php b/app/Config/Filters.php index 3f7a47a7..d4bcb168 100644 --- a/app/Config/Filters.php +++ b/app/Config/Filters.php @@ -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 + * @phpstan-var array */ 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 + * @var array>>|array> + * @phpstan-var array>|array>> */ 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/*'], diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 5eaff586..d28a0785 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -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'; -} diff --git a/app/Config/Routing.php b/app/Config/Routing.php new file mode 100644 index 00000000..c0ddd14d --- /dev/null +++ b/app/Config/Routing.php @@ -0,0 +1,117 @@ +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 [ uri_segment => namespace ] + */ + public array $moduleRoutes = []; +} diff --git a/app/Config/Services.php b/app/Config/Services.php index 70b00cfd..48a3554d 100644 --- a/app/Config/Services.php +++ b/app/Config/Services.php @@ -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. diff --git a/app/Config/Toolbar.php b/app/Config/Toolbar.php index e1806d6c..1f342434 100644 --- a/app/Config/Toolbar.php +++ b/app/Config/Toolbar.php @@ -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']; } diff --git a/app/Controllers/ColorsController.php b/app/Controllers/ColorsController.php index 82d6eed9..4aa1a47c 100644 --- a/app/Controllers/ColorsController.php +++ b/app/Controllers/ColorsController.php @@ -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 = ''; diff --git a/app/Controllers/EpisodeAudioController.php b/app/Controllers/EpisodeAudioController.php index a069bb83..fadb311f 100644 --- a/app/Controllers/EpisodeAudioController.php +++ b/app/Controllers/EpisodeAudioController.php @@ -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 diff --git a/app/Controllers/EpisodeController.php b/app/Controllers/EpisodeController.php index 46a4f860..7ca30bb1 100644 --- a/app/Controllers/EpisodeController.php +++ b/app/Controllers/EpisodeController.php @@ -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' => '', - 'width' => config('Embed') + '" width="100%" height="' . config(Embed::class)->height . '" frameborder="0" scrolling="no">', + '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( '', + '" width="100%" height="' . config( + Embed::class + )->height . '" frameborder="0" scrolling="no">', ), ); - $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); diff --git a/app/Controllers/HomeController.php b/app/Controllers/HomeController.php index 515c0d0b..5acdfd16 100644 --- a/app/Controllers/HomeController.php +++ b/app/Controllers/HomeController.php @@ -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.'; } diff --git a/app/Entities/Episode.php b/app/Entities/Episode.php index c51e1e6d..4adde20e 100644 --- a/app/Entities/Episode.php +++ b/app/Entities/Episode.php @@ -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'], diff --git a/app/Entities/Person.php b/app/Entities/Person.php index 961f5603..9af5f92c 100644 --- a/app/Entities/Person.php +++ b/app/Entities/Person.php @@ -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'], diff --git a/app/Entities/Podcast.php b/app/Entities/Podcast.php index d57a1463..23fd04e7 100644 --- a/app/Entities/Podcast.php +++ b/app/Entities/Podcast.php @@ -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'], diff --git a/app/Helpers/misc_helper.php b/app/Helpers/misc_helper.php index 635a07cb..1b6046e2 100644 --- a/app/Helpers/misc_helper.php +++ b/app/Helpers/misc_helper.php @@ -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]; diff --git a/app/Helpers/page_helper.php b/app/Helpers/page_helper.php index 253b0135..49d15a79 100644 --- a/app/Helpers/page_helper.php +++ b/app/Helpers/page_helper.php @@ -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', diff --git a/app/Helpers/rss_helper.php b/app/Helpers/rss_helper.php index a20f71a6..4b0d187c 100644 --- a/app/Helpers/rss_helper.php +++ b/app/Helpers/rss_helper.php @@ -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); diff --git a/app/Helpers/seo_helper.php b/app/Helpers/seo_helper.php index 0fc27244..c5755998 100644 --- a/app/Helpers/seo_helper.php +++ b/app/Helpers/seo_helper.php @@ -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', diff --git a/app/Libraries/RouteCollection.php b/app/Libraries/RouteCollection.php deleted file mode 100644 index 75ea4757..00000000 --- a/app/Libraries/RouteCollection.php +++ /dev/null @@ -1,280 +0,0 @@ -|Closure|string $to - * @param array $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 $to - * - * @return string|array - */ - 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); - } -} diff --git a/app/Libraries/Router.php b/app/Libraries/Router.php index 6bb71997..0dacb8bd 100644 --- a/app/Libraries/Router.php +++ b/app/Libraries/Router.php @@ -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}', '(?[^/]+)', $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; } diff --git a/app/Libraries/ViewComponents/ComponentRenderer.php b/app/Libraries/ViewComponents/ComponentRenderer.php index f9e916c0..79e1987b 100644 --- a/app/Libraries/ViewComponents/ComponentRenderer.php +++ b/app/Libraries/ViewComponents/ComponentRenderer.php @@ -16,7 +16,7 @@ class ComponentRenderer public function __construct() { - $this->config = config('ViewComponents'); + $this->config = config(ViewComponents::class); } public function render(string $output): string diff --git a/app/Libraries/ViewThemes/Theme.php b/app/Libraries/ViewThemes/Theme.php index 30020dcb..f3d94796 100644 --- a/app/Libraries/ViewThemes/Theme.php +++ b/app/Libraries/ViewThemes/Theme.php @@ -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[] = [ diff --git a/app/Libraries/Vite/Vite.php b/app/Libraries/Vite/Vite.php index 64b4202d..b0dea4ec 100644 --- a/app/Libraries/Vite/Vite.php +++ b/app/Libraries/Vite/Vite.php @@ -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; diff --git a/app/Models/PlatformModel.php b/app/Models/PlatformModel.php index 14219f80..7665a6f5 100644 --- a/app/Models/PlatformModel.php +++ b/app/Models/PlatformModel.php @@ -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(); diff --git a/app/Models/PodcastModel.php b/app/Models/PodcastModel.php index f64d7915..63863b7d 100644 --- a/app/Models/PodcastModel.php +++ b/app/Models/PodcastModel.php @@ -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() diff --git a/composer.json b/composer.json index f0a7a3ff..644be9a3 100644 --- a/composer.json +++ b/composer.json @@ -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", diff --git a/composer.lock b/composer.lock index 87e62f86..970c6488 100644 --- a/composer.lock +++ b/composer.lock @@ -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", diff --git a/modules/Admin/Config/Routes.php b/modules/Admin/Config/Routes.php index 106fd39f..37edabe4 100644 --- a/modules/Admin/Config/Routes.php +++ b/modules/Admin/Config/Routes.php @@ -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', ]); diff --git a/modules/Admin/Controllers/AboutController.php b/modules/Admin/Controllers/AboutController.php index b90f2542..b43453fc 100644 --- a/modules/Admin/Controllers/AboutController.php +++ b/modules/Admin/Controllers/AboutController.php @@ -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', [ diff --git a/modules/Admin/Controllers/DashboardController.php b/modules/Admin/Controllers/DashboardController.php index 7d6f4821..6ac175af 100644 --- a/modules/Admin/Controllers/DashboardController.php +++ b/modules/Admin/Controllers/DashboardController.php @@ -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 = [ diff --git a/modules/Admin/Controllers/PodcastController.php b/modules/Admin/Controllers/PodcastController.php index 75fee3a9..bca38a66 100644 --- a/modules/Admin/Controllers/PodcastController.php +++ b/modules/Admin/Controllers/PodcastController.php @@ -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')); diff --git a/modules/Admin/Controllers/VideoClipsController.php b/modules/Admin/Controllers/VideoClipsController.php index d66fffde..a7205003 100644 --- a/modules/Admin/Controllers/VideoClipsController.php +++ b/modules/Admin/Controllers/VideoClipsController.php @@ -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, diff --git a/modules/Admin/Language/ar/Breadcrumb.php b/modules/Admin/Language/ar/Breadcrumb.php index 66a2065d..f65f731a 100644 --- a/modules/Admin/Language/ar/Breadcrumb.php +++ b/modules/Admin/Language/ar/Breadcrumb.php @@ -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' => 'حلقات', diff --git a/modules/Admin/Language/br/Breadcrumb.php b/modules/Admin/Language/br/Breadcrumb.php index 04072451..2807e934 100644 --- a/modules/Admin/Language/br/Breadcrumb.php +++ b/modules/Admin/Language/br/Breadcrumb.php @@ -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ù', diff --git a/modules/Admin/Language/ca/Breadcrumb.php b/modules/Admin/Language/ca/Breadcrumb.php index d16b4eaa..4ccba18f 100644 --- a/modules/Admin/Language/ca/Breadcrumb.php +++ b/modules/Admin/Language/ca/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/da/Breadcrumb.php b/modules/Admin/Language/da/Breadcrumb.php index a67d497b..fcf3d567 100644 --- a/modules/Admin/Language/da/Breadcrumb.php +++ b/modules/Admin/Language/da/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/de/Breadcrumb.php b/modules/Admin/Language/de/Breadcrumb.php index 65ad6b2b..aa060fda 100644 --- a/modules/Admin/Language/de/Breadcrumb.php +++ b/modules/Admin/Language/de/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/el/Breadcrumb.php b/modules/Admin/Language/el/Breadcrumb.php index aa52554d..e642116c 100644 --- a/modules/Admin/Language/el/Breadcrumb.php +++ b/modules/Admin/Language/el/Breadcrumb.php @@ -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' => 'επεισόδια', diff --git a/modules/Admin/Language/en/Breadcrumb.php b/modules/Admin/Language/en/Breadcrumb.php index ca682262..593322e6 100644 --- a/modules/Admin/Language/en/Breadcrumb.php +++ b/modules/Admin/Language/en/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/es/Breadcrumb.php b/modules/Admin/Language/es/Breadcrumb.php index cc0b23bc..cace2713 100644 --- a/modules/Admin/Language/es/Breadcrumb.php +++ b/modules/Admin/Language/es/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/fa/Breadcrumb.php b/modules/Admin/Language/fa/Breadcrumb.php index ca682262..593322e6 100644 --- a/modules/Admin/Language/fa/Breadcrumb.php +++ b/modules/Admin/Language/fa/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/fr/Breadcrumb.php b/modules/Admin/Language/fr/Breadcrumb.php index 69b8205b..a25e678e 100644 --- a/modules/Admin/Language/fr/Breadcrumb.php +++ b/modules/Admin/Language/fr/Breadcrumb.php @@ -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 d’Ariane', - config('Admin') + config(Admin::class) ->gateway => 'Accueil', 'podcasts' => 'podcasts', 'episodes' => 'épisodes', diff --git a/modules/Admin/Language/fr2/Breadcrumb.php b/modules/Admin/Language/fr2/Breadcrumb.php index daa88fbb..5588f808 100644 --- a/modules/Admin/Language/fr2/Breadcrumb.php +++ b/modules/Admin/Language/fr2/Breadcrumb.php @@ -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 d’Ariane', - config('Admin') + config(Admin::class) ->gateway => 'Accueil', 'podcasts' => 'podcasts', 'episodes' => 'épisodes', diff --git a/modules/Admin/Language/fr_CA/Breadcrumb.php b/modules/Admin/Language/fr_CA/Breadcrumb.php index ca682262..593322e6 100644 --- a/modules/Admin/Language/fr_CA/Breadcrumb.php +++ b/modules/Admin/Language/fr_CA/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/fr_trad/Breadcrumb.php b/modules/Admin/Language/fr_trad/Breadcrumb.php index 558b90f7..896c373c 100644 --- a/modules/Admin/Language/fr_trad/Breadcrumb.php +++ b/modules/Admin/Language/fr_trad/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/gd/Breadcrumb.php b/modules/Admin/Language/gd/Breadcrumb.php index ca682262..593322e6 100644 --- a/modules/Admin/Language/gd/Breadcrumb.php +++ b/modules/Admin/Language/gd/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/gl/Breadcrumb.php b/modules/Admin/Language/gl/Breadcrumb.php index 4517dad4..15c54937 100644 --- a/modules/Admin/Language/gl/Breadcrumb.php +++ b/modules/Admin/Language/gl/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/id/Breadcrumb.php b/modules/Admin/Language/id/Breadcrumb.php index d68fe345..38927596 100644 --- a/modules/Admin/Language/id/Breadcrumb.php +++ b/modules/Admin/Language/id/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/it/Breadcrumb.php b/modules/Admin/Language/it/Breadcrumb.php index 60d86070..21988dad 100644 --- a/modules/Admin/Language/it/Breadcrumb.php +++ b/modules/Admin/Language/it/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/ja/Breadcrumb.php b/modules/Admin/Language/ja/Breadcrumb.php index ca682262..593322e6 100644 --- a/modules/Admin/Language/ja/Breadcrumb.php +++ b/modules/Admin/Language/ja/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/ko/Breadcrumb.php b/modules/Admin/Language/ko/Breadcrumb.php index ca682262..593322e6 100644 --- a/modules/Admin/Language/ko/Breadcrumb.php +++ b/modules/Admin/Language/ko/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/nl/Breadcrumb.php b/modules/Admin/Language/nl/Breadcrumb.php index ff66e639..4f2591f8 100644 --- a/modules/Admin/Language/nl/Breadcrumb.php +++ b/modules/Admin/Language/nl/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/nn-NO/Breadcrumb.php b/modules/Admin/Language/nn-NO/Breadcrumb.php index 8e133d91..d7811c3c 100644 --- a/modules/Admin/Language/nn-NO/Breadcrumb.php +++ b/modules/Admin/Language/nn-NO/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/oc/Breadcrumb.php b/modules/Admin/Language/oc/Breadcrumb.php index ca682262..593322e6 100644 --- a/modules/Admin/Language/oc/Breadcrumb.php +++ b/modules/Admin/Language/oc/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/pl/Breadcrumb.php b/modules/Admin/Language/pl/Breadcrumb.php index 4e95f113..d3e718f0 100644 --- a/modules/Admin/Language/pl/Breadcrumb.php +++ b/modules/Admin/Language/pl/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/pt-BR/Breadcrumb.php b/modules/Admin/Language/pt-BR/Breadcrumb.php index 0194ee38..63d17e97 100644 --- a/modules/Admin/Language/pt-BR/Breadcrumb.php +++ b/modules/Admin/Language/pt-BR/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/pt/Breadcrumb.php b/modules/Admin/Language/pt/Breadcrumb.php index ca682262..593322e6 100644 --- a/modules/Admin/Language/pt/Breadcrumb.php +++ b/modules/Admin/Language/pt/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/ro/Breadcrumb.php b/modules/Admin/Language/ro/Breadcrumb.php index ca682262..593322e6 100644 --- a/modules/Admin/Language/ro/Breadcrumb.php +++ b/modules/Admin/Language/ro/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/ru/Breadcrumb.php b/modules/Admin/Language/ru/Breadcrumb.php index 956be05f..642f273d 100644 --- a/modules/Admin/Language/ru/Breadcrumb.php +++ b/modules/Admin/Language/ru/Breadcrumb.php @@ -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' => 'выпуски', diff --git a/modules/Admin/Language/sk/Breadcrumb.php b/modules/Admin/Language/sk/Breadcrumb.php index c411de81..a3d97f7f 100644 --- a/modules/Admin/Language/sk/Breadcrumb.php +++ b/modules/Admin/Language/sk/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/sr_Latn/Breadcrumb.php b/modules/Admin/Language/sr_Latn/Breadcrumb.php index 678127b0..4f685d60 100644 --- a/modules/Admin/Language/sr_Latn/Breadcrumb.php +++ b/modules/Admin/Language/sr_Latn/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/sv/Breadcrumb.php b/modules/Admin/Language/sv/Breadcrumb.php index a2c81378..a373f4cf 100644 --- a/modules/Admin/Language/sv/Breadcrumb.php +++ b/modules/Admin/Language/sv/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/uk/Breadcrumb.php b/modules/Admin/Language/uk/Breadcrumb.php index ca682262..593322e6 100644 --- a/modules/Admin/Language/uk/Breadcrumb.php +++ b/modules/Admin/Language/uk/Breadcrumb.php @@ -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', diff --git a/modules/Admin/Language/zh-Hans/Breadcrumb.php b/modules/Admin/Language/zh-Hans/Breadcrumb.php index df604854..e4c2d8a3 100644 --- a/modules/Admin/Language/zh-Hans/Breadcrumb.php +++ b/modules/Admin/Language/zh-Hans/Breadcrumb.php @@ -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' => '剧集', diff --git a/modules/Analytics/Config/Routes.php b/modules/Analytics/Config/Routes.php index acc9e49e..f8a925cf 100644 --- a/modules/Analytics/Config/Routes.php +++ b/modules/Analytics/Config/Routes.php @@ -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'); diff --git a/modules/Analytics/Helpers/analytics_helper.php b/modules/Analytics/Helpers/analytics_helper.php index a4612ca6..4e6f1240 100644 --- a/modules/Analytics/Helpers/analytics_helper.php +++ b/modules/Analytics/Helpers/analytics_helper.php @@ -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 = diff --git a/modules/Api/Rest/V1/Config/Routes.php b/modules/Api/Rest/V1/Config/Routes.php index 0a02ebd1..0951a7d5 100644 --- a/modules/Api/Rest/V1/Config/Routes.php +++ b/modules/Api/Rest/V1/Config/Routes.php @@ -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', diff --git a/modules/Api/Rest/V1/Config/Services.php b/modules/Api/Rest/V1/Config/Services.php index c4a3d72c..48c94897 100644 --- a/modules/Api/Rest/V1/Config/Services.php +++ b/modules/Api/Rest/V1/Config/Services.php @@ -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()); } } diff --git a/modules/Api/Rest/V1/Controllers/EpisodeController.php b/modules/Api/Rest/V1/Controllers/EpisodeController.php index 4e4f08eb..f90e809d 100644 --- a/modules/Api/Rest/V1/Controllers/EpisodeController.php +++ b/modules/Api/Rest/V1/Controllers/EpisodeController.php @@ -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') ); diff --git a/modules/Api/Rest/V1/Filters/ApiFilter.php b/modules/Api/Rest/V1/Filters/ApiFilter.php index c28af65e..9ee8fa5f 100644 --- a/modules/Api/Rest/V1/Filters/ApiFilter.php +++ b/modules/Api/Rest/V1/Filters/ApiFilter.php @@ -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(); diff --git a/modules/Auth/Auth.php b/modules/Auth/Auth.php index 09e32581..35a5e31d 100644 --- a/modules/Auth/Auth.php +++ b/modules/Auth/Auth.php @@ -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) { diff --git a/modules/Auth/Config/Auth.php b/modules/Auth/Config/Auth.php index a537c3ef..d765960a 100644 --- a/modules/Auth/Config/Auth.php +++ b/modules/Auth/Config/Auth.php @@ -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 = [ diff --git a/modules/Auth/Config/Routes.php b/modules/Auth/Config/Routes.php index af307640..0bdc30ca 100644 --- a/modules/Auth/Config/Routes.php +++ b/modules/Auth/Config/Routes.php @@ -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', diff --git a/modules/Auth/Config/Services.php b/modules/Auth/Config/Services.php index f3dd45f7..5be76591 100644 --- a/modules/Auth/Config/Services.php +++ b/modules/Auth/Config/Services.php @@ -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)); } diff --git a/modules/Auth/Controllers/MagicLinkController.php b/modules/Auth/Controllers/MagicLinkController.php index 6033a448..92223de5 100644 --- a/modules/Auth/Controllers/MagicLinkController.php +++ b/modules/Auth/Controllers/MagicLinkController.php @@ -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')); } } diff --git a/modules/Fediverse/Config/Routes.php b/modules/Fediverse/Config/Routes.php index 6aa75a00..7d5770c8 100644 --- a/modules/Fediverse/Config/Routes.php +++ b/modules/Fediverse/Config/Routes.php @@ -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( diff --git a/modules/Fediverse/Controllers/ActorController.php b/modules/Fediverse/Controllers/ActorController.php index 52f35e36..8e725dee 100644 --- a/modules/Fediverse/Controllers/ActorController.php +++ b/modules/Fediverse/Controllers/ActorController.php @@ -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 diff --git a/modules/Fediverse/Controllers/NodeInfo2Controller.php b/modules/Fediverse/Controllers/NodeInfo2Controller.php index 4457c600..753f66f3 100644 --- a/modules/Fediverse/Controllers/NodeInfo2Controller.php +++ b/modules/Fediverse/Controllers/NodeInfo2Controller.php @@ -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' => [ diff --git a/modules/Fediverse/Controllers/PostController.php b/modules/Fediverse/Controllers/PostController.php index 6141f402..267e818e 100644 --- a/modules/Fediverse/Controllers/PostController.php +++ b/modules/Fediverse/Controllers/PostController.php @@ -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 diff --git a/modules/Fediverse/Entities/Actor.php b/modules/Fediverse/Entities/Actor.php index 12d65124..97948796 100644 --- a/modules/Fediverse/Entities/Actor.php +++ b/modules/Fediverse/Entities/Actor.php @@ -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']; diff --git a/modules/Fediverse/Models/ActivityModel.php b/modules/Fediverse/Models/ActivityModel.php index cf9181fe..efc4028b 100644 --- a/modules/Fediverse/Models/ActivityModel.php +++ b/modules/Fediverse/Models/ActivityModel.php @@ -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); diff --git a/modules/Fediverse/Models/ActorModel.php b/modules/Fediverse/Models/ActorModel.php index db07c0be..1fe1ed54 100644 --- a/modules/Fediverse/Models/ActorModel.php +++ b/modules/Fediverse/Models/ActorModel.php @@ -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); diff --git a/modules/Fediverse/Models/BlockedDomainModel.php b/modules/Fediverse/Models/BlockedDomainModel.php index e8e4f514..16fbd6a6 100644 --- a/modules/Fediverse/Models/BlockedDomainModel.php +++ b/modules/Fediverse/Models/BlockedDomainModel.php @@ -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"); diff --git a/modules/Fediverse/Models/PostModel.php b/modules/Fediverse/Models/PostModel.php index c472a61b..65d5d703 100644 --- a/modules/Fediverse/Models/PostModel.php +++ b/modules/Fediverse/Models/PostModel.php @@ -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); diff --git a/modules/Fediverse/Models/PreviewCardModel.php b/modules/Fediverse/Models/PreviewCardModel.php index deedbe3b..ed333b1c 100644 --- a/modules/Fediverse/Models/PreviewCardModel.php +++ b/modules/Fediverse/Models/PreviewCardModel.php @@ -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); } diff --git a/modules/Install/Config/Routes.php b/modules/Install/Config/Routes.php index 94a289c5..78012464 100644 --- a/modules/Install/Config/Routes.php +++ b/modules/Install/Config/Routes.php @@ -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', diff --git a/modules/Install/Controllers/InstallController.php b/modules/Install/Controllers/InstallController.php index 54462633..e131ec73 100644 --- a/modules/Install/Controllers/InstallController.php +++ b/modules/Install/Controllers/InstallController.php @@ -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 diff --git a/modules/Media/Config/Routes.php b/modules/Media/Config/Routes.php index 1c7ba01e..c8d4703a 100644 --- a/modules/Media/Config/Routes.php +++ b/modules/Media/Config/Routes.php @@ -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', diff --git a/modules/Media/Config/Services.php b/modules/Media/Config/Services.php index bb66d217..9291c80b 100644 --- a/modules/Media/Config/Services.php +++ b/modules/Media/Config/Services.php @@ -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); diff --git a/modules/Media/Entities/BaseMedia.php b/modules/Media/Entities/BaseMedia.php index 6098edd0..5509296c 100644 --- a/modules/Media/Entities/BaseMedia.php +++ b/modules/Media/Entities/BaseMedia.php @@ -59,9 +59,9 @@ class BaseMedia extends Entity /** * @param array $data */ - public function setAttributes(array $data): self + public function injectRawData(array $data): static { - parent::setAttributes($data); + parent::injectRawData($data); $this->initFileProperties(); diff --git a/modules/Media/Entities/Image.php b/modules/Media/Entities/Image.php index b4b53499..af381455 100644 --- a/modules/Media/Entities/Image.php +++ b/modules/Media/Entities/Image.php @@ -54,9 +54,9 @@ class Image extends BaseMedia /** * @param array $data */ - public function setAttributes(array $data): self + public function injectRawData(array $data): static { - parent::setAttributes($data); + parent::injectRawData($data); if ($this->attributes === []) { return $this; diff --git a/modules/Media/FileManagers/FS.php b/modules/Media/FileManagers/FS.php index ca31bc23..aa2d2066 100644 --- a/modules/Media/FileManagers/FS.php +++ b/modules/Media/FileManagers/FS.php @@ -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; } } diff --git a/modules/MediaClipper/Commands/Generate.php b/modules/MediaClipper/Commands/Generate.php index 9ceb0825..3d625e28 100644 --- a/modules/MediaClipper/Commands/Generate.php +++ b/modules/MediaClipper/Commands/Generate.php @@ -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; } diff --git a/modules/MediaClipper/VideoClipper.php b/modules/MediaClipper/VideoClipper.php index 6a09e53d..ea55c0c6 100644 --- a/modules/MediaClipper/VideoClipper.php +++ b/modules/MediaClipper/VideoClipper.php @@ -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 diff --git a/modules/PodcastImport/Commands/PodcastImport.php b/modules/PodcastImport/Commands/PodcastImport.php index fc7ef61e..cb9f4029 100644 --- a/modules/PodcastImport/Commands/PodcastImport.php +++ b/modules/PodcastImport/Commands/PodcastImport.php @@ -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'); diff --git a/modules/PodcastImport/Config/Routes.php b/modules/PodcastImport/Config/Routes.php index f9131da7..28f349d3 100644 --- a/modules/PodcastImport/Config/Routes.php +++ b/modules/PodcastImport/Config/Routes.php @@ -5,13 +5,13 @@ declare(strict_types=1); namespace Modules\PodcastImport\Config; use CodeIgniter\Router\RouteCollection; +use Modules\Admin\Config\Admin; /** @var RouteCollection $routes */ -$routes = service('routes'); // Admin routes for imports $routes->group( - config('Admin') + config(Admin::class) ->gateway, [ 'namespace' => 'Modules\PodcastImport\Controllers', diff --git a/modules/PremiumPodcasts/Config/Routes.php b/modules/PremiumPodcasts/Config/Routes.php index d21c34df..1da50e43 100644 --- a/modules/PremiumPodcasts/Config/Routes.php +++ b/modules/PremiumPodcasts/Config/Routes.php @@ -4,13 +4,16 @@ declare(strict_types=1); namespace Modules\PremiumPodcasts\Config; -$routes = service('routes'); +use CodeIgniter\Router\RouteCollection; +use Modules\Admin\Config\Admin; + +/** @var RouteCollection $routes */ $routes->addPlaceholder('podcastHandle', '[a-zA-Z0-9\_]{1,32}'); // Admin routes for subscriptions $routes->group( - config('Admin') + config(Admin::class) ->gateway, [ 'namespace' => 'Modules\PremiumPodcasts\Controllers', @@ -115,7 +118,7 @@ $routes->group( 'namespace' => 'Modules\PremiumPodcasts\Controllers', ], static function ($routes): void { - $routes->get('unlock', 'LockController/$1', [ + $routes->get('unlock', 'LockController::index/$1', [ 'as' => 'premium-podcast-unlock', ]); $routes->post('unlock', 'LockController::attemptUnlock/$1', [ diff --git a/modules/PremiumPodcasts/Filters/PodcastUnlockFilter.php b/modules/PremiumPodcasts/Filters/PodcastUnlockFilter.php index a4a1d3f8..4d149bee 100644 --- a/modules/PremiumPodcasts/Filters/PodcastUnlockFilter.php +++ b/modules/PremiumPodcasts/Filters/PodcastUnlockFilter.php @@ -4,12 +4,12 @@ declare(strict_types=1); namespace Modules\PremiumPodcasts\Filters; +use App\Entities\Episode; use App\Models\EpisodeModel; use CodeIgniter\Filters\FilterInterface; use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\ResponseInterface; use CodeIgniter\Router\Router; -use Config\App; use Modules\PremiumPodcasts\PremiumPodcasts; class PodcastUnlockFilter implements FilterInterface @@ -17,27 +17,16 @@ class PodcastUnlockFilter implements FilterInterface /** * Verifies that a user is logged in, or redirects to login. * - * @param array|null $params + * @param string[]|null $arguments * * @return mixed */ - public function before(RequestInterface $request, $params = null) + public function before(RequestInterface $request, $arguments = null) { if (! function_exists('is_unlocked')) { helper('premium_podcasts'); } - $current = (string) current_url(true) - ->setHost('') - ->setScheme('') - ->stripQuery('token'); - - $config = config(App::class); - if ($config->forceGlobalSecureRequests) { - // Remove "https:/" - $current = substr($current, 7); - } - /** @var Router $router */ $router = service('router'); $routerParams = $router->params(); @@ -52,20 +41,28 @@ class PodcastUnlockFilter implements FilterInterface } // Make sure this isn't already a premium podcast route - if ($current === route_to('premium-podcast-unlock', $routerParams[0])) { + if (url_is((string) route_to('premium-podcast-unlock', $routerParams[0]))) { + return; + } + + // expect 2 parameters (podcast handle and episode slug) + if (count($routerParams) < 2) { + return; + } + + $episode = (new EpisodeModel())->getEpisodeBySlug($routerParams[0], $routerParams[1]); + + if (! $episode instanceof Episode) { return; } // Make sure that public episodes are still accessible - if ($routerParams >= 2 && ($episode = (new EpisodeModel())->getEpisodeBySlug( - $routerParams[0], - $routerParams[1] - )) && ! $episode->is_premium) { + if (! $episode->is_premium) { return; } // Episode should be embeddable even if it is premium - if ($current === route_to('embed', $episode->podcast->handle, $episode->slug)) { + if (url_is((string) route_to('embed', $episode->podcast->handle, $episode->slug))) { return; } @@ -80,7 +77,7 @@ class PodcastUnlockFilter implements FilterInterface } /** - * @param array|null $arguments + * @param string[]|null $arguments */ public function after(RequestInterface $request, ResponseInterface $response, $arguments = null): void { diff --git a/modules/WebSub/Commands/Publish.php b/modules/WebSub/Commands/Publish.php index ddca5126..58f40fbb 100644 --- a/modules/WebSub/Commands/Publish.php +++ b/modules/WebSub/Commands/Publish.php @@ -9,6 +9,7 @@ use App\Models\PodcastModel; use CodeIgniter\CLI\BaseCommand; use CodeIgniter\HTTP\CURLRequest; use Exception; +use Modules\WebSub\Config\WebSub; class Publish extends BaseCommand { @@ -55,7 +56,7 @@ class Publish extends BaseCommand ], ]; - $hubUrls = config('WebSub') + $hubUrls = config(WebSub::class) ->hubs; foreach ($podcasts as $podcast) { diff --git a/public/index.php b/public/index.php index 4e0739e5..e4827629 100644 --- a/public/index.php +++ b/public/index.php @@ -22,7 +22,9 @@ if (version_compare(PHP_VERSION, $minPhpVersion, '<')) { define('FCPATH', __DIR__ . DIRECTORY_SEPARATOR); // Ensure the current directory is pointing to the front controller's directory -chdir(FCPATH); +if (getcwd() . DIRECTORY_SEPARATOR !== FCPATH) { + chdir(FCPATH); +} /* *--------------------------------------------------------------- @@ -47,6 +49,16 @@ require rtrim($paths->systemDirectory, '\\/ ') . DIRECTORY_SEPARATOR . 'bootstra require_once SYSTEMPATH . 'Config/DotEnv.php'; (new DotEnv(ROOTPATH))->load(); +// Define ENVIRONMENT +if (! defined('ENVIRONMENT')) { + define('ENVIRONMENT', env('CI_ENVIRONMENT', 'production')); +} + +// Load Config Cache +// $factoriesCache = new \CodeIgniter\Cache\FactoriesCache(); +// $factoriesCache->load('config'); +// ^^^ Uncomment these lines if you want to use Config Caching. + /* * --------------------------------------------------------------- * GRAB OUR CODEIGNITER INSTANCE @@ -71,3 +83,11 @@ $app->setContext($context); */ $app->run(); + +// Save Config Cache +// $factoriesCache->save('config'); +// ^^^ Uncomment this line if you want to use Config Caching. + +// Exits the application, setting the exit code for CLI-based applications +// that might be watching. +exit(EXIT_SUCCESS); diff --git a/spark b/spark index 75150a39..f2bf19f4 100644 --- a/spark +++ b/spark @@ -78,6 +78,11 @@ require rtrim($paths->systemDirectory, '\\/ ') . DIRECTORY_SEPARATOR . 'bootstra require_once SYSTEMPATH . 'Config/DotEnv.php'; (new CodeIgniter\Config\DotEnv(ROOTPATH))->load(); +// Define ENVIRONMENT +if (! defined('ENVIRONMENT')) { + define('ENVIRONMENT', env('CI_ENVIRONMENT', 'production')); +} + // Grab our CodeIgniter $app = Config\Services::codeigniter(); $app->initialize(); diff --git a/tests/modules/Api/Rest/V1/EpisodeTest.php b/tests/modules/Api/Rest/V1/EpisodeTest.php index 7a009764..ee389f12 100644 --- a/tests/modules/Api/Rest/V1/EpisodeTest.php +++ b/tests/modules/Api/Rest/V1/EpisodeTest.php @@ -8,6 +8,7 @@ use App\Database\Seeds\FakeSinglePodcastApiSeeder; use CodeIgniter\Test\CIUnitTestCase; use CodeIgniter\Test\DatabaseTestTrait; use CodeIgniter\Test\FeatureTestTrait; +use Modules\Api\Rest\V1\Config\RestApi; class EpisodeTest extends CIUnitTestCase { @@ -54,7 +55,7 @@ class EpisodeTest extends CIUnitTestCase $this->episode['created_at'] = []; $this->episode['updated_at'] = []; - $this->apiUrl = config('RestApi') + $this->apiUrl = config(RestApi::class) ->gateway; } diff --git a/tests/modules/Api/Rest/V1/PodcastTest.php b/tests/modules/Api/Rest/V1/PodcastTest.php index e1552224..9f5bd45e 100644 --- a/tests/modules/Api/Rest/V1/PodcastTest.php +++ b/tests/modules/Api/Rest/V1/PodcastTest.php @@ -8,6 +8,7 @@ use App\Database\Seeds\FakeSinglePodcastApiSeeder; use CodeIgniter\Test\CIUnitTestCase; use CodeIgniter\Test\DatabaseTestTrait; use CodeIgniter\Test\FeatureTestTrait; +use Modules\Api\Rest\V1\Config\RestApi; class PodcastTest extends CIUnitTestCase { @@ -52,7 +53,7 @@ class PodcastTest extends CIUnitTestCase $this->podcast = FakeSinglePodcastApiSeeder::podcast(); $this->podcast['created_at'] = []; $this->podcast['updated_at'] = []; - $this->podcastApiUrl = config('RestApi') + $this->podcastApiUrl = config(RestApi::class) ->gateway; } diff --git a/themes/cp_admin/episode/embed.php b/themes/cp_admin/episode/embed.php index 821402cb..f45eb4f7 100644 --- a/themes/cp_admin/episode/embed.php +++ b/themes/cp_admin/episode/embed.php @@ -1,7 +1,8 @@ height; +use Config\Embed; + +$embedHeight = config(Embed::class)->height; ?> diff --git a/themes/cp_admin/episode/video_clips_new.php b/themes/cp_admin/episode/video_clips_new.php index 15055c3a..e7cef5c1 100644 --- a/themes/cp_admin/episode/video_clips_new.php +++ b/themes/cp_admin/episode/video_clips_new.php @@ -1,3 +1,9 @@ + + extend('_layout') ?> section('title') ?> @@ -55,7 +61,7 @@
- themes as $themeName => $colors): ?> + themes as $themeName => $colors): ?> + extend('_layout') ?> section('title') ?> @@ -43,7 +49,7 @@ accept=".png,.jpeg,.jpg" class="flex-1" /> - siteIcon['ico'] !== service('settings')->get('App.siteIcon')['ico']): ?> + siteIcon['ico'] !== service('settings')->get('App.siteIcon')['ico']): ?>
<?= esc(service('settings')->get('App.siteName')) ?> Favicon diff --git a/themes/cp_admin/settings/theme.php b/themes/cp_admin/settings/theme.php index 4757a214..76f5bf41 100644 --- a/themes/cp_admin/settings/theme.php +++ b/themes/cp_admin/settings/theme.php @@ -1,3 +1,9 @@ + + extend('_layout') ?> section('title') ?> @@ -17,7 +23,7 @@ subtitle="">
- themes as $themeName => $color): ?> + themes as $themeName => $color): ?> + -extend(config('Auth')->views['layout']) ?> +extend(config(Auth::class)->views['layout']) ?> section('title') ?> endSection() ?> diff --git a/themes/cp_auth/email_2fa_verify.php b/themes/cp_auth/email_2fa_verify.php index 18c67156..4f321b4d 100644 --- a/themes/cp_auth/email_2fa_verify.php +++ b/themes/cp_auth/email_2fa_verify.php @@ -1,5 +1,10 @@ + -extend(config('Auth')->views['layout']) ?> +extend(config(Auth::class)->views['layout']) ?> section('title') ?> endSection() ?> diff --git a/themes/cp_auth/email_activate_show.php b/themes/cp_auth/email_activate_show.php index d0d93d73..d02e3307 100644 --- a/themes/cp_auth/email_activate_show.php +++ b/themes/cp_auth/email_activate_show.php @@ -1,5 +1,10 @@ + -extend(config('Auth')->views['layout']) ?> +extend(config(Auth::class)->views['layout']) ?> section('title') ?>endSection() ?> diff --git a/themes/cp_auth/login.php b/themes/cp_auth/login.php index 34d2849e..d2d86ba9 100644 --- a/themes/cp_auth/login.php +++ b/themes/cp_auth/login.php @@ -1,5 +1,10 @@ + -extend(config('Auth')->views['layout']) ?> +extend(config(Auth::class)->views['layout']) ?> section('title') ?>endSection() ?> diff --git a/themes/cp_auth/magic_link_form.php b/themes/cp_auth/magic_link_form.php index b4f9c978..2d8a47dc 100644 --- a/themes/cp_auth/magic_link_form.php +++ b/themes/cp_auth/magic_link_form.php @@ -1,5 +1,10 @@ + -extend(config('Auth')->views['layout']) ?> +extend(config(Auth::class)->views['layout']) ?> section('title') ?> endSection() ?> diff --git a/themes/cp_auth/magic_link_message.php b/themes/cp_auth/magic_link_message.php index ade1b651..af85d821 100644 --- a/themes/cp_auth/magic_link_message.php +++ b/themes/cp_auth/magic_link_message.php @@ -1,4 +1,9 @@ -extend(config('Auth')->views['layout']) ?> + +extend(config(Auth::class)->views['layout']) ?> section('title') ?> endSection() ?> diff --git a/themes/cp_auth/magic_link_set_password.php b/themes/cp_auth/magic_link_set_password.php index 64d85614..919daa28 100644 --- a/themes/cp_auth/magic_link_set_password.php +++ b/themes/cp_auth/magic_link_set_password.php @@ -1,5 +1,10 @@ + -extend(config('Auth')->views['layout']) ?> +extend(config(Auth::class)->views['layout']) ?> section('title') ?> diff --git a/themes/cp_auth/register.php b/themes/cp_auth/register.php index af5e06df..ab7c6c40 100644 --- a/themes/cp_auth/register.php +++ b/themes/cp_auth/register.php @@ -1,5 +1,10 @@ + -extend(config('Auth')->views['layout']) ?> +extend(config(Auth::class)->views['layout']) ?> section('title') ?> diff --git a/themes/cp_install/database_config.php b/themes/cp_install/database_config.php index 45aa4586..6fa5c2e2 100644 --- a/themes/cp_install/database_config.php +++ b/themes/cp_install/database_config.php @@ -1,3 +1,8 @@ + extend('_layout') ?> section('content') ?> @@ -21,27 +26,27 @@ @@ -50,7 +55,7 @@ name="db_prefix" label="" hint="" - value="default['DBPrefix'] ?>" /> + value="default['DBPrefix'] ?>" /> diff --git a/themes/cp_install/instance_config.php b/themes/cp_install/instance_config.php index 9d613e1f..f51a2859 100644 --- a/themes/cp_install/instance_config.php +++ b/themes/cp_install/instance_config.php @@ -1,8 +1,16 @@ + extend('_layout') ?> section('content') ?> -
+
@@ -13,8 +21,7 @@