Loading app/Common.php +0 −40 Original line number Diff line number Diff line Loading @@ -2,7 +2,6 @@ declare(strict_types=1); use Config\Services; use Config\View; use ViewThemes\Theme; Loading Loading @@ -49,42 +48,3 @@ if (! function_exists('view')) { ->render($name, $options, $saveData); } } if (! function_exists('lang')) { /** * A convenience method to translate a string or array of them and format the result with the intl extension's * MessageFormatter. * * Overwritten to include an escape parameter (escaped by default). * * @param array<int|string, string> $args * * TODO: remove, and escape args when necessary * * @return string|string[] */ function lang(string $line, array $args = [], ?string $locale = null, bool $escape = true): string | array { $language = Services::language(); // Get active locale $activeLocale = $language->getLocale(); if ($locale && $locale !== $activeLocale) { $language->setLocale($locale); } $line = $language->getLine($line, $args); if (! $locale) { return $escape ? esc($line) : $line; } if ($locale === $activeLocale) { return $escape ? esc($line) : $line; } // Reset to active locale $language->setLocale($activeLocale); return $escape ? esc($line) : $line; } } app/Config/Filters.php +2 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Config; use App\Filters\AllowCorsFilter; use CodeIgniter\Config\BaseConfig; use CodeIgniter\Filters\CSRF; use CodeIgniter\Filters\DebugToolbar; Loading @@ -25,6 +26,7 @@ class Filters extends BaseConfig 'honeypot' => Honeypot::class, 'invalidchars' => InvalidChars::class, 'secureheaders' => SecureHeaders::class, 'allow-cors' => AllowCorsFilter::class, ]; /** Loading app/Config/Services.php +16 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ 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; Loading Loading @@ -43,6 +44,21 @@ 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. Loading app/Libraries/RouteCollection.php 0 → 100644 +137 −0 Original line number Diff line number Diff line <?php declare(strict_types=1); /** * This file extends the Router class from the CodeIgniter 4 framework. * * It introduces the alternate-content option for a route. * * @copyright 2023 Ad Aures * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @link https://castopod.org/ */ namespace App\Libraries; use CodeIgniter\Router\RouteCollection as CodeIgniterRouteCollection; class RouteCollection extends CodeIgniterRouteCollection { /** * Does the heavy lifting of creating an actual route. You must specify * the request method(s) that this route will work for. They can be separated * by a pipe character "|" if there is more than one. * * @param array|Closure|string $to */ protected function create(string $verb, string $from, $to, ?array $options = null) { $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) => '$' . $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($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']; } } } app/Resources/js/modules/Tooltip.ts +2 −1 Original line number Diff line number Diff line import { arrow, computePosition, Coords, flip, offset, Placement, Loading Loading @@ -46,7 +47,7 @@ const Tooltip = (): void => { }); // Accessing the data const { x: arrowX, y: arrowY } = middlewareData.arrow as any; const { x: arrowX, y: arrowY } = middlewareData.arrow as Coords; const staticSide = { top: "bottom", Loading Loading
app/Common.php +0 −40 Original line number Diff line number Diff line Loading @@ -2,7 +2,6 @@ declare(strict_types=1); use Config\Services; use Config\View; use ViewThemes\Theme; Loading Loading @@ -49,42 +48,3 @@ if (! function_exists('view')) { ->render($name, $options, $saveData); } } if (! function_exists('lang')) { /** * A convenience method to translate a string or array of them and format the result with the intl extension's * MessageFormatter. * * Overwritten to include an escape parameter (escaped by default). * * @param array<int|string, string> $args * * TODO: remove, and escape args when necessary * * @return string|string[] */ function lang(string $line, array $args = [], ?string $locale = null, bool $escape = true): string | array { $language = Services::language(); // Get active locale $activeLocale = $language->getLocale(); if ($locale && $locale !== $activeLocale) { $language->setLocale($locale); } $line = $language->getLine($line, $args); if (! $locale) { return $escape ? esc($line) : $line; } if ($locale === $activeLocale) { return $escape ? esc($line) : $line; } // Reset to active locale $language->setLocale($activeLocale); return $escape ? esc($line) : $line; } }
app/Config/Filters.php +2 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Config; use App\Filters\AllowCorsFilter; use CodeIgniter\Config\BaseConfig; use CodeIgniter\Filters\CSRF; use CodeIgniter\Filters\DebugToolbar; Loading @@ -25,6 +26,7 @@ class Filters extends BaseConfig 'honeypot' => Honeypot::class, 'invalidchars' => InvalidChars::class, 'secureheaders' => SecureHeaders::class, 'allow-cors' => AllowCorsFilter::class, ]; /** Loading
app/Config/Services.php +16 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ 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; Loading Loading @@ -43,6 +44,21 @@ 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. Loading
app/Libraries/RouteCollection.php 0 → 100644 +137 −0 Original line number Diff line number Diff line <?php declare(strict_types=1); /** * This file extends the Router class from the CodeIgniter 4 framework. * * It introduces the alternate-content option for a route. * * @copyright 2023 Ad Aures * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @link https://castopod.org/ */ namespace App\Libraries; use CodeIgniter\Router\RouteCollection as CodeIgniterRouteCollection; class RouteCollection extends CodeIgniterRouteCollection { /** * Does the heavy lifting of creating an actual route. You must specify * the request method(s) that this route will work for. They can be separated * by a pipe character "|" if there is more than one. * * @param array|Closure|string $to */ protected function create(string $verb, string $from, $to, ?array $options = null) { $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) => '$' . $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($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']; } } }
app/Resources/js/modules/Tooltip.ts +2 −1 Original line number Diff line number Diff line import { arrow, computePosition, Coords, flip, offset, Placement, Loading Loading @@ -46,7 +47,7 @@ const Tooltip = (): void => { }); // Accessing the data const { x: arrowX, y: arrowY } = middlewareData.arrow as any; const { x: arrowX, y: arrowY } = middlewareData.arrow as Coords; const staticSide = { top: "bottom", Loading