Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • adaures/castopod
  • mkljczk/castopod-host
  • spaetz/castopod-host
  • PatrykMis/castopod
  • jonas/castopod
  • ajeremias/castopod
  • misuzu/castopod
  • KrzysztofDomanczyk/castopod
  • Behel/castopod
  • nebulon/castopod
  • ewen/castopod
  • NeoluxConsulting/castopod
  • nateritter/castopod-og
  • prcutler/castopod
14 results
Show changes
Showing
with 1011 additions and 528 deletions
......@@ -26,7 +26,7 @@ class Images extends BaseConfig
* @var array<string, string>
*/
public array $handlers = [
'gd' => GDHandler::class,
'gd' => GDHandler::class,
'imagick' => ImageMagickHandler::class,
];
......@@ -51,51 +51,55 @@ class Images extends BaseConfig
*/
public array $podcastCoverSizes = [
'tiny' => [
'width' => 40,
'height' => 40,
'mimetype' => 'image/webp',
'width' => 40,
'height' => 40,
'mimetype' => 'image/webp',
'extension' => 'webp',
],
'thumbnail' => [
'width' => 150,
'height' => 150,
'mimetype' => 'image/webp',
'width' => 150,
'height' => 150,
'mimetype' => 'image/webp',
'extension' => 'webp',
],
'medium' => [
'width' => 320,
'height' => 320,
'mimetype' => 'image/webp',
'width' => 320,
'height' => 320,
'mimetype' => 'image/webp',
'extension' => 'webp',
],
'large' => [
'width' => 1024,
'height' => 1024,
'mimetype' => 'image/webp',
'width' => 1024,
'height' => 1024,
'mimetype' => 'image/webp',
'extension' => 'webp',
],
'feed' => [
'width' => 1400,
'width' => 1400,
'height' => 1400,
],
'id3' => [
'width' => 500,
'width' => 500,
'height' => 500,
],
'og' => [
'width' => 1200,
'height' => 1200,
],
'federation' => [
'width' => 400,
'width' => 400,
'height' => 400,
],
'webmanifest192' => [
'width' => 192,
'height' => 192,
'mimetype' => 'image/png',
'width' => 192,
'height' => 192,
'mimetype' => 'image/png',
'extension' => 'png',
],
'webmanifest512' => [
'width' => 512,
'height' => 512,
'mimetype' => 'image/png',
'width' => 512,
'height' => 512,
'mimetype' => 'image/png',
'extension' => 'png',
],
];
......@@ -109,28 +113,60 @@ class Images extends BaseConfig
*/
public array $podcastBannerSizes = [
'small' => [
'width' => 320,
'height' => 128,
'mimetype' => 'image/webp',
'width' => 320,
'height' => 128,
'mimetype' => 'image/webp',
'extension' => 'webp',
],
'medium' => [
'width' => 960,
'height' => 320,
'mimetype' => 'image/webp',
'width' => 960,
'height' => 320,
'mimetype' => 'image/webp',
'extension' => 'webp',
],
'federation' => [
'width' => 1500,
'width' => 1500,
'height' => 500,
],
];
public string $avatarDefaultPath = 'castopod-avatar-default.jpg';
public string $avatarDefaultPath = 'assets/images/castopod-avatar.jpg';
public string $avatarDefaultMimeType = 'image/jpg';
public string $podcastBannerDefaultPath = 'castopod-banner-default.jpg';
/**
* @var array<string, array<string, string>>
*/
public array $podcastBannerDefaultPaths = [
'default' => [
'path' => 'assets/images/castopod-banner-pine.jpg',
'mimetype' => 'image/jpeg',
],
'pine' => [
'path' => 'assets/images/castopod-banner-pine.jpg',
'mimetype' => 'image/jpeg',
],
'crimson' => [
'path' => 'assets/images/castopod-banner-crimson.jpg',
'mimetype' => 'image/jpeg',
],
'amber' => [
'path' => 'assets/images/castopod-banner-amber.jpg',
'mimetype' => 'image/jpeg',
],
'lake' => [
'path' => 'assets/images/castopod-banner-lake.jpg',
'mimetype' => 'image/jpeg',
],
'jacaranda' => [
'path' => 'assets/images/castopod-banner-jacaranda.jpg',
'mimetype' => 'image/jpeg',
],
'onyx' => [
'path' => 'assets/images/castopod-banner-onyx.jpg',
'mimetype' => 'image/jpeg',
],
];
public string $podcastBannerDefaultMimeType = 'image/jpeg';
......@@ -144,23 +180,26 @@ class Images extends BaseConfig
* @var array<string, array<string, int|string>>
*/
public array $personAvatarSizes = [
'federation' => [
'width' => 400,
'height' => 400,
],
'tiny' => [
'width' => 40,
'height' => 40,
'mimetype' => 'image/webp',
'width' => 40,
'height' => 40,
'mimetype' => 'image/webp',
'extension' => 'webp',
],
'thumbnail' => [
'width' => 150,
'height' => 150,
'mimetype' => 'image/webp',
'width' => 150,
'height' => 150,
'mimetype' => 'image/webp',
'extension' => 'webp',
],
'medium' => [
'width' => 320,
'height' => 320,
'mimetype' =>
'image/webp',
'width' => 320,
'height' => 320,
'mimetype' => 'image/webp',
'extension' => 'webp',
],
];
......
......@@ -4,12 +4,12 @@ declare(strict_types=1);
namespace Config;
use CodeIgniter\Config\BaseConfig;
use Kint\Renderer\Renderer;
use Kint\Parser\ConstructablePluginInterface;
use Kint\Renderer\Rich\TabPluginInterface;
use Kint\Renderer\Rich\ValuePluginInterface;
/**
* --------------------------------------------------------------------------
* Kint
* --------------------------------------------------------------------------
*
* We use Kint's `RichRenderer` and `CLIRenderer`. This area contains options
......@@ -17,7 +17,7 @@ use Kint\Renderer\Renderer;
*
* @see https://kint-php.github.io/kint/ for details on these settings.
*/
class Kint extends BaseConfig
class Kint
{
/*
|--------------------------------------------------------------------------
......@@ -26,9 +26,9 @@ class Kint extends BaseConfig
*/
/**
* @var string[]
* @var list<class-string<ConstructablePluginInterface>|ConstructablePluginInterface>|null
*/
public array $plugins = [];
public ?array $plugins = [];
public int $maxDepth = 6;
......@@ -46,17 +46,15 @@ class Kint extends BaseConfig
public bool $richFolder = false;
public int $richSort = Renderer::SORT_FULL;
/**
* @var string[]
* @var array<string, class-string<ValuePluginInterface>>|null
*/
public array $richObjectPlugins = [];
public ?array $richObjectPlugins = [];
/**
* @var string[]
* @var array<string, class-string<TabPluginInterface>>|null
*/
public array $richTabPlugins = [];
public ?array $richTabPlugins = [];
/*
|--------------------------------------------------------------------------
......
......@@ -38,9 +38,9 @@ class Logger extends BaseConfig
* For a live site you'll usually enable Critical or higher (3) to be logged otherwise
* your log files will fill up very fast.
*
* @var int|int[]
* @var int|list<int>
*/
public int | array $threshold = 4;
public int | array $threshold = (ENVIRONMENT === 'production') ? 4 : 9;
/**
* --------------------------------------------------------------------------
......@@ -60,7 +60,7 @@ class Logger extends BaseConfig
* The logging system supports multiple actions to be taken when something
* is logged. This is done by allowing for multiple Handlers, special classes
* designed to write the log to their chosen destinations, whether that is
* a file on the getServer, a cloud-based service, or even taking actions such
* a file on the server, a cloud-based service, or even taking actions such
* as emailing the dev team.
*
* Each handler is defined by the class name used for that handler, and it
......@@ -75,7 +75,7 @@ class Logger extends BaseConfig
* Handlers are executed in the order defined in this array, starting with
* the handler on top and continuing down.
*
* @var array<string, mixed>
* @var array<class-string, array<string, int|list<string>|string>>
*/
public array $handlers = [
/*
......@@ -114,5 +114,32 @@ class Logger extends BaseConfig
*/
'path' => '',
],
/*
* The ChromeLoggerHandler requires the use of the Chrome web browser
* and the ChromeLogger extension. Uncomment this block to use it.
*/
// 'CodeIgniter\Log\Handlers\ChromeLoggerHandler' => [
// /*
// * The log levels that this handler will handle.
// */
// 'handles' => ['critical', 'alert', 'emergency', 'debug',
// 'error', 'info', 'notice', 'warning'],
// ],
/*
* The ErrorlogHandler writes the logs to PHP's native `error_log()` function.
* Uncomment this block to use it.
*/
// 'CodeIgniter\Log\Handlers\ErrorlogHandler' => [
// /* The log levels this handler can handle. */
// 'handles' => ['critical', 'alert', 'emergency', 'debug', 'error', 'info', 'notice', 'warning'],
//
// /*
// * The message type where the error should go. Can be 0 or 4, or use the
// * class constants: `ErrorlogHandler::TYPE_OS` (0) or `ErrorlogHandler::TYPE_SAPI` (4)
// */
// 'messageType' => 0,
// ],
];
}
......@@ -27,9 +27,7 @@ class Migrations extends BaseConfig
*
* This is the name of the table that will store the current migrations state.
* When migrations runs it will store in a database table which migration
* level the system is at. It then compares the migration level in this
* table to the $config['migration_version'] if they are not the same it
* will migrate up. This must be set.
* files have already been run.
*/
public string $table = 'migrations';
......
......@@ -5,8 +5,6 @@ declare(strict_types=1);
namespace Config;
/**
* Mimes
*
* This file contains an array of mime types. It is used by the Upload class to help identify allowed file types.
*
* When more than one variation for an extension exist (like jpg, jpeg, etc) the most common one should be first in the
......@@ -14,14 +12,15 @@ namespace Config;
*
* When working with mime types, please make sure you have the ´fileinfo´ extension enabled to reliably detect the
* media types.
*
* @immutable
*/
class Mimes
{
/**
* Map of extensions to mime types.
*
* @var array<string, string|string[]>
* @var array<string, list<string>|string>
*/
public static $mimes = [
'hqx' => [
......@@ -53,21 +52,24 @@ class Mimes
'dms' => 'application/octet-stream',
'lha' => 'application/octet-stream',
'lzh' => 'application/octet-stream',
'exe' => ['application/octet-stream', 'application/x-msdownload'],
'exe' => ['application/octet-stream',
'application/vnd.microsoft.portable-executable',
'application/x-dosexec',
'application/x-msdownload'],
'class' => 'application/octet-stream',
'psd' => ['application/x-photoshop', 'image/vnd.adobe.photoshop'],
'so' => 'application/octet-stream',
'sea' => 'application/octet-stream',
'dll' => 'application/octet-stream',
'oda' => 'application/oda',
'pdf' => ['application/pdf', 'application/force-download', 'application/x-download'],
'ai' => ['application/pdf', 'application/postscript'],
'eps' => 'application/postscript',
'ps' => 'application/postscript',
'smi' => 'application/smil',
'smil' => 'application/smil',
'mif' => 'application/vnd.mif',
'xls' => [
'psd' => ['application/x-photoshop', 'image/vnd.adobe.photoshop'],
'so' => 'application/octet-stream',
'sea' => 'application/octet-stream',
'dll' => 'application/octet-stream',
'oda' => 'application/oda',
'pdf' => ['application/pdf', 'application/force-download', 'application/x-download'],
'ai' => ['application/pdf', 'application/postscript'],
'eps' => 'application/postscript',
'ps' => 'application/postscript',
'smi' => 'application/smil',
'smil' => 'application/smil',
'mif' => 'application/vnd.mif',
'xls' => [
'application/vnd.ms-excel',
'application/msexcel',
'application/x-msexcel',
......@@ -87,21 +89,17 @@ class Mimes
'application/vnd.ms-office',
'application/msword',
],
'pptx' => [
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'application/x-zip',
'application/zip',
],
'pptx' => ['application/vnd.openxmlformats-officedocument.presentationml.presentation'],
'wbxml' => 'application/wbxml',
'wmlc' => 'application/wmlc',
'dcr' => 'application/x-director',
'dir' => 'application/x-director',
'dxr' => 'application/x-director',
'dvi' => 'application/x-dvi',
'gtar' => 'application/x-gtar',
'gz' => 'application/x-gzip',
'gzip' => 'application/x-gzip',
'php' => [
'wmlc' => 'application/wmlc',
'dcr' => 'application/x-director',
'dir' => 'application/x-director',
'dxr' => 'application/x-director',
'dvi' => 'application/x-dvi',
'gtar' => 'application/x-gtar',
'gz' => 'application/x-gzip',
'gzip' => 'application/x-gzip',
'php' => [
'application/x-php',
'application/x-httpd-php',
'application/php',
......@@ -109,41 +107,41 @@ class Mimes
'text/x-php',
'application/x-httpd-php-source',
],
'php4' => 'application/x-httpd-php',
'php3' => 'application/x-httpd-php',
'php4' => 'application/x-httpd-php',
'php3' => 'application/x-httpd-php',
'phtml' => 'application/x-httpd-php',
'phps' => 'application/x-httpd-php-source',
'js' => ['application/x-javascript', 'text/plain'],
'swf' => 'application/x-shockwave-flash',
'sit' => 'application/x-stuffit',
'tar' => 'application/x-tar',
'tgz' => ['application/x-tar', 'application/x-gzip-compressed'],
'z' => 'application/x-compress',
'phps' => 'application/x-httpd-php-source',
'js' => ['application/x-javascript', 'text/plain'],
'swf' => 'application/x-shockwave-flash',
'sit' => 'application/x-stuffit',
'tar' => 'application/x-tar',
'tgz' => ['application/x-tar', 'application/x-gzip-compressed'],
'z' => 'application/x-compress',
'xhtml' => 'application/xhtml+xml',
'xht' => 'application/xhtml+xml',
'zip' => [
'xht' => 'application/xhtml+xml',
'zip' => [
'application/x-zip',
'application/zip',
'application/x-zip-compressed',
'application/s-compressed',
'multipart/x-zip',
],
'rar' => ['application/vnd.rar', 'application/x-rar', 'application/rar', 'application/x-rar-compressed'],
'mid' => 'audio/midi',
'rar' => ['application/vnd.rar', 'application/x-rar', 'application/rar', 'application/x-rar-compressed'],
'mid' => 'audio/midi',
'midi' => 'audio/midi',
'mp3' => ['audio/mpeg', 'audio/mpg', 'audio/mpeg3', 'audio/mp3', 'application/octet-stream'],
'mp3' => ['audio/mpeg', 'audio/mpg', 'audio/mpeg3', 'audio/mp3', 'application/octet-stream'],
'mpga' => 'audio/mpeg',
'mp2' => 'audio/mpeg',
'aif' => ['audio/x-aiff', 'audio/aiff'],
'mp2' => 'audio/mpeg',
'aif' => ['audio/x-aiff', 'audio/aiff'],
'aiff' => ['audio/x-aiff', 'audio/aiff'],
'aifc' => 'audio/x-aiff',
'ram' => 'audio/x-pn-realaudio',
'rm' => 'audio/x-pn-realaudio',
'rpm' => 'audio/x-pn-realaudio-plugin',
'ra' => 'audio/x-realaudio',
'rv' => 'video/vnd.rn-realvideo',
'wav' => ['audio/x-wav', 'audio/wave', 'audio/wav'],
'bmp' => [
'ram' => 'audio/x-pn-realaudio',
'rm' => 'audio/x-pn-realaudio',
'rpm' => 'audio/x-pn-realaudio-plugin',
'ra' => 'audio/x-realaudio',
'rv' => 'video/vnd.rn-realvideo',
'wav' => ['audio/x-wav', 'audio/wave', 'audio/wav'],
'bmp' => [
'image/bmp',
'image/x-bmp',
'image/x-bitmap',
......@@ -156,47 +154,48 @@ class Mimes
'application/x-bmp',
'application/x-win-bitmap',
],
'gif' => 'image/gif',
'jpg' => ['image/jpeg', 'image/pjpeg'],
'jpeg' => ['image/jpeg', 'image/pjpeg'],
'jpe' => ['image/jpeg', 'image/pjpeg'],
'jp2' => ['image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'],
'j2k' => ['image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'],
'jpf' => ['image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'],
'jpg2' => ['image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'],
'jpx' => ['image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'],
'jpm' => ['image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'],
'mj2' => ['image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'],
'mjp2' => ['image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'],
'png' => ['image/png', 'image/x-png'],
'tif' => 'image/tiff',
'tiff' => 'image/tiff',
'css' => ['text/css', 'text/plain'],
'html' => ['text/html', 'text/plain'],
'htm' => ['text/html', 'text/plain'],
'gif' => 'image/gif',
'jpg' => ['image/jpeg', 'image/pjpeg'],
'jpeg' => ['image/jpeg', 'image/pjpeg'],
'jpe' => ['image/jpeg', 'image/pjpeg'],
'jp2' => ['image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'],
'j2k' => ['image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'],
'jpf' => ['image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'],
'jpg2' => ['image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'],
'jpx' => ['image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'],
'jpm' => ['image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'],
'mj2' => ['image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'],
'mjp2' => ['image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'],
'png' => ['image/png', 'image/x-png'],
'webp' => 'image/webp',
'tif' => 'image/tiff',
'tiff' => 'image/tiff',
'css' => ['text/css', 'text/plain'],
'html' => ['text/html', 'text/plain'],
'htm' => ['text/html', 'text/plain'],
'shtml' => ['text/html', 'text/plain'],
'txt' => 'text/plain',
'text' => 'text/plain',
'log' => ['text/plain', 'text/x-log'],
'rtx' => 'text/richtext',
'rtf' => 'text/rtf',
'xml' => ['application/xml', 'text/xml', 'text/plain'],
'xsl' => ['application/xml', 'text/xsl', 'text/xml'],
'mpeg' => 'video/mpeg',
'mpg' => 'video/mpeg',
'mpe' => 'video/mpeg',
'qt' => 'video/quicktime',
'mov' => 'video/quicktime',
'avi' => ['video/x-msvideo', 'video/msvideo', 'video/avi', 'application/x-troff-msvideo'],
'txt' => 'text/plain',
'text' => 'text/plain',
'log' => ['text/plain', 'text/x-log'],
'rtx' => 'text/richtext',
'rtf' => 'text/rtf',
'xml' => ['application/xml', 'text/xml', 'text/plain'],
'xsl' => ['application/xml', 'text/xsl', 'text/xml'],
'mpeg' => 'video/mpeg',
'mpg' => 'video/mpeg',
'mpe' => 'video/mpeg',
'qt' => 'video/quicktime',
'mov' => 'video/quicktime',
'avi' => ['video/x-msvideo', 'video/msvideo', 'video/avi', 'application/x-troff-msvideo'],
'movie' => 'video/x-sgi-movie',
'doc' => ['application/msword', 'application/vnd.ms-office'],
'docx' => [
'doc' => ['application/msword', 'application/vnd.ms-office'],
'docx' => [
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'application/zip',
'application/msword',
'application/x-zip',
],
'dot' => ['application/msword', 'application/vnd.ms-office'],
'dot' => ['application/msword', 'application/vnd.ms-office'],
'dotx' => [
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'application/zip',
......@@ -212,49 +211,49 @@ class Mimes
'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
'word' => ['application/msword', 'application/octet-stream'],
'xl' => 'application/excel',
'eml' => 'message/rfc822',
'json' => ['application/json', 'text/json'],
'pem' => ['application/x-x509-user-cert', 'application/x-pem-file', 'application/octet-stream'],
'p10' => ['application/x-pkcs10', 'application/pkcs10'],
'p12' => 'application/x-pkcs12',
'p7a' => 'application/x-pkcs7-signature',
'p7c' => ['application/pkcs7-mime', 'application/x-pkcs7-mime'],
'p7m' => ['application/pkcs7-mime', 'application/x-pkcs7-mime'],
'p7r' => 'application/x-pkcs7-certreqresp',
'p7s' => 'application/pkcs7-signature',
'crt' => ['application/x-x509-ca-cert', 'application/x-x509-user-cert', 'application/pkix-cert'],
'crl' => ['application/pkix-crl', 'application/pkcs-crl'],
'der' => 'application/x-x509-ca-cert',
'kdb' => 'application/octet-stream',
'pgp' => 'application/pgp',
'gpg' => 'application/gpg-keys',
'sst' => 'application/octet-stream',
'csr' => 'application/octet-stream',
'rsa' => 'application/x-pkcs7',
'cer' => ['application/pkix-cert', 'application/x-x509-ca-cert'],
'3g2' => 'video/3gpp2',
'3gp' => ['video/3gp', 'video/3gpp'],
'mp4' => 'video/mp4',
'm4a' => ['audio/m4a', 'audio/x-m4a', 'application/octet-stream'],
'f4v' => ['video/mp4', 'video/x-f4v'],
'flv' => 'video/x-flv',
'xl' => 'application/excel',
'eml' => 'message/rfc822',
'json' => ['application/json', 'text/json', 'text/plain'],
'pem' => ['application/x-x509-user-cert', 'application/x-pem-file', 'application/octet-stream'],
'p10' => ['application/x-pkcs10', 'application/pkcs10'],
'p12' => 'application/x-pkcs12',
'p7a' => 'application/x-pkcs7-signature',
'p7c' => ['application/pkcs7-mime', 'application/x-pkcs7-mime'],
'p7m' => ['application/pkcs7-mime', 'application/x-pkcs7-mime'],
'p7r' => 'application/x-pkcs7-certreqresp',
'p7s' => 'application/pkcs7-signature',
'crt' => ['application/x-x509-ca-cert', 'application/x-x509-user-cert', 'application/pkix-cert'],
'crl' => ['application/pkix-crl', 'application/pkcs-crl'],
'der' => 'application/x-x509-ca-cert',
'kdb' => 'application/octet-stream',
'pgp' => 'application/pgp',
'gpg' => 'application/gpg-keys',
'sst' => 'application/octet-stream',
'csr' => 'application/octet-stream',
'rsa' => 'application/x-pkcs7',
'cer' => ['application/pkix-cert', 'application/x-x509-ca-cert'],
'3g2' => 'video/3gpp2',
'3gp' => ['video/3gp', 'video/3gpp'],
'mp4' => 'video/mp4',
'm4a' => ['audio/m4a', 'audio/x-m4a', 'application/octet-stream'],
'f4v' => ['video/mp4', 'video/x-f4v'],
'flv' => 'video/x-flv',
'webm' => 'video/webm',
'aac' => 'audio/x-acc',
'm4u' => 'application/vnd.mpegurl',
'm3u' => 'text/plain',
'aac' => 'audio/x-acc',
'm4u' => 'application/vnd.mpegurl',
'm3u' => 'text/plain',
'xspf' => 'application/xspf+xml',
'vlc' => 'application/videolan',
'wmv' => ['video/x-ms-wmv', 'video/x-ms-asf'],
'au' => 'audio/x-au',
'ac3' => 'audio/ac3',
'vlc' => 'application/videolan',
'wmv' => ['video/x-ms-wmv', 'video/x-ms-asf'],
'au' => 'audio/x-au',
'ac3' => 'audio/ac3',
'flac' => 'audio/x-flac',
'ogg' => ['audio/ogg', 'video/ogg', 'application/ogg'],
'kmz' => ['application/vnd.google-earth.kmz', 'application/zip', 'application/x-zip'],
'kml' => ['application/vnd.google-earth.kml+xml', 'application/xml', 'text/xml'],
'ics' => 'text/calendar',
'ogg' => ['audio/ogg', 'video/ogg', 'application/ogg'],
'kmz' => ['application/vnd.google-earth.kmz', 'application/zip', 'application/x-zip'],
'kml' => ['application/vnd.google-earth.kml+xml', 'application/xml', 'text/xml'],
'ics' => 'text/calendar',
'ical' => 'text/calendar',
'zsh' => 'text/x-scriptzsh',
'zsh' => 'text/x-scriptzsh',
'7zip' => [
'application/x-compressed',
'application/x-zip-compressed',
......@@ -279,7 +278,7 @@ class Mimes
],
'svg' => ['image/svg+xml', 'image/svg', 'application/xml', 'text/xml'],
'vcf' => 'text/x-vcard',
'srt' => ['text/srt', 'text/plain', 'application/octet-stream'],
'srt' => ['application/x-subrip', 'text/srt', 'text/plain', 'application/octet-stream'],
'vtt' => ['text/vtt', 'text/plain'],
'ico' => ['image/x-icon', 'image/x-ico', 'image/vnd.microsoft.icon'],
'stl' => ['application/sla', 'application/vnd.ms-pki.stl', 'application/x-navistyle'],
......@@ -306,35 +305,28 @@ class Mimes
/**
* Attempts to determine the best file extension for a given mime type.
*
* @param string $proposedExtension - default extension (in case there is more than one with the same mime type)
* @param string|null $proposedExtension - default extension (in case there is more than one with the same mime type)
* @return string|null The extension determined, or null if unable to match.
*/
public static function guessExtensionFromType(string $type, string $proposedExtension = null): ?string
public static function guessExtensionFromType(string $type, ?string $proposedExtension = null): ?string
{
$type = trim(strtolower($type), '. ');
$proposedExtension = trim(strtolower($proposedExtension ?? ''));
if ($proposedExtension !== '') {
if (array_key_exists($proposedExtension, static::$mimes) && in_array(
$type,
is_string(static::$mimes[$proposedExtension]) ? [
static::$mimes[$proposedExtension],
] : static::$mimes[$proposedExtension],
true
)) {
// The detected mime type matches with the proposed extension.
return $proposedExtension;
}
// An extension was proposed, but the media type does not match the mime type list.
return null;
if (
$proposedExtension !== ''
&& array_key_exists($proposedExtension, static::$mimes)
&& in_array($type, (array) static::$mimes[$proposedExtension], true)
) {
// The detected mime type matches with the proposed extension.
return $proposedExtension;
}
// Reverse check the mime type list if no extension was proposed.
// This search is order sensitive!
foreach (static::$mimes as $ext => $types) {
if ((is_string($types) && $types === $type) || (is_array($types) && in_array($type, $types, true))) {
if (in_array($type, (array) $types, true)) {
return $ext;
}
}
......
......@@ -6,6 +6,14 @@ namespace Config;
use CodeIgniter\Modules\Modules as BaseModules;
/**
* Modules Configuration.
*
* NOTE: This class is required prior to Autoloader instantiation,
* and does not extend BaseConfig.
*
* @immutable
*/
class Modules extends BaseModules
{
/**
......@@ -33,6 +41,29 @@ class Modules extends BaseModules
*/
public $discoverInComposer = true;
/**
* The Composer package list for Auto-Discovery
* This setting is optional.
*
* E.g.:
* [
* 'only' => [
* // List up all packages to auto-discover
* 'codeigniter4/shield',
* ],
* ]
* or
* [
* 'exclude' => [
* // List up packages to exclude.
* 'pestphp/pest',
* ],
* ]
*
* @var array{only?: list<string>, exclude?: list<string>}
*/
public $composerPackages = [];
/**
* --------------------------------------------------------------------------
* Auto-Discovery Rules
......@@ -43,7 +74,7 @@ class Modules extends BaseModules
*
* If it is not listed, only the base application elements will be used.
*
* @var string[]
* @var list<string>
*/
public $aliases = ['events', 'filters', 'registrars', 'routes', 'services'];
}
<?php
declare(strict_types=1);
namespace Config;
/**
* Optimization Configuration.
*
* NOTE: This class does not extend BaseConfig for performance reasons.
* So you cannot replace the property values with Environment Variables.
*
* @immutable
*/
class Optimize
{
/**
* --------------------------------------------------------------------------
* Config Caching
* --------------------------------------------------------------------------
*
* @see https://codeigniter.com/user_guide/concepts/factories.html#config-caching
*/
public bool $configCacheEnabled = false;
/**
* --------------------------------------------------------------------------
* Config Caching
* --------------------------------------------------------------------------
*
* @see https://codeigniter.com/user_guide/concepts/autoloader.html#file-locator-caching
*/
public bool $locatorCacheEnabled = false;
}
......@@ -21,13 +21,11 @@ class Pager extends BaseConfig
* and the desired group as $pagerGroup;
*
* @var array<string, string>
*
* @noRector Rector\Php55\Rector\String_\StringClassNameToClassConstantRector
*/
public $templates = [
'default_full' => 'App\Views\pager\default_full',
public array $templates = [
'default_full' => 'App\Views\pager\default_full',
'default_simple' => 'CodeIgniter\Pager\Views\default_simple',
'default_head' => 'CodeIgniter\Pager\Views\default_head',
'default_head' => 'CodeIgniter\Pager\Views\default_head',
];
/**
......
......@@ -5,8 +5,6 @@ declare(strict_types=1);
namespace Config;
/**
* Paths
*
* Holds the paths that are used by the system to locate the main directories, app, system, etc.
*
* Modifying these allows you to restructure your application, share a system folder between multiple applications, and
......@@ -26,7 +24,7 @@ class Paths
* the path if the folder is not in the same directory as this file.
*/
public string $systemDirectory =
__DIR__ . '/../../vendor/codeigniter4/codeigniter4/system';
__DIR__ . '/../../vendor/codeigniter4/framework/system';
/**
* ---------------------------------------------------------------
......@@ -35,8 +33,8 @@ class Paths
*
* If you want this front controller to use a different "app"
* folder than the default one you can set its name here. The folder
* can also be renamed or relocated anywhere on your getServer. If
* you do, use a full getServer path.
* can also be renamed or relocated anywhere on your server. If
* you do, use a full server path.
*
* @see http://codeigniter.com/user_guide/general/managing_apps.html
*/
......@@ -72,7 +70,7 @@ class Paths
* This variable must contain the name of the directory that
* contains the view files used by your application. By
* default this is in `app/Views`. This value
* is used when no value is provided to `Services::renderer()`.
* is used when no value is provided to `service('renderer')`.
*/
public string $viewDirectory = __DIR__ . '/../Views';
}
......@@ -14,4 +14,15 @@ use CodeIgniter\Config\Publisher as BasePublisher;
*/
class Publisher extends BasePublisher
{
/**
* A list of allowed destinations with a (pseudo-)regex of allowed files for each destination. Attempts to publish
* to directories not in this list will result in a PublisherException. Files that do no fit the pattern will cause
* copy/merge to fail.
*
* @var array<string, string>
*/
public $restrictions = [
ROOTPATH => '*',
FCPATH => '#\.(s?css|js|map|html?|xml|json|webmanifest|ttf|eot|woff2?|gif|jpe?g|tiff?|png|webp|bmp|ico|svg)$#i',
];
}
......@@ -2,30 +2,11 @@
declare(strict_types=1);
namespace Config;
// Create a new instance of our RouteCollection class.
$routes = Services::routes();
// Load the system's routing file first, so that the app and ENVIRONMENT
// can override as needed.
if (file_exists(SYSTEMPATH . 'Config/Routes.php')) {
require SYSTEMPATH . 'Config/Routes.php';
}
/**
* --------------------------------------------------------------------
* Router Setup
* --------------------------------------------------------------------
*/
$routes->setDefaultNamespace('App\Controllers');
$routes->setDefaultController('Home');
$routes->setDefaultMethod('index');
$routes->setTranslateURIDashes(false);
$routes->set404Override();
$routes->setAutoRoute(false);
use CodeIgniter\Router\RouteCollection;
/**
* @var RouteCollection $routes
*
* --------------------------------------------------------------------
* Placeholder definitions
* --------------------------------------------------------------------
......@@ -34,7 +15,6 @@ $routes->setAutoRoute(false);
$routes->addPlaceholder('podcastHandle', '[a-zA-Z0-9\_]{1,32}');
$routes->addPlaceholder('slug', '[a-zA-Z0-9\-]{1,128}');
$routes->addPlaceholder('base64', '[A-Za-z0-9\.\_]+\-{0,2}');
$routes->addPlaceholder('platformType', '\bpodcasting|\bsocial|\bfunding');
$routes->addPlaceholder('postAction', '\bfavourite|\breblog|\breply');
$routes->addPlaceholder('embedTheme', '\blight|\bdark|\blight-transparent|\bdark-transparent');
$routes->addPlaceholder(
......@@ -51,8 +31,13 @@ $routes->addPlaceholder(
$routes->get('manifest.webmanifest', 'WebmanifestController', [
'as' => 'webmanifest',
]);
$routes->get('styles/themes.css', 'ColorsController', [
'as' => 'color-themes-css',
$routes->get('themes/colors', 'ColorsController', [
'as' => 'themes-colors-css',
]);
// health check
$routes->get('/health', 'HomeController::health', [
'as' => 'health',
]);
// We get a performance increase by specifying the default
......@@ -63,74 +48,91 @@ $routes->get('/', 'HomeController', [
$routes->get('.well-known/platforms', 'Platform');
// Podcast's Public routes
$routes->group('@(:podcastHandle)', function ($routes): void {
$routes->get('/', 'PodcastController::activity/$1', [
'as' => 'podcast-activity',
]);
$routes->get('manifest.webmanifest', 'WebmanifestController::podcastManifest/$1', [
'as' => 'podcast-webmanifest',
]);
service('auth')
->routes($routes);
// Podcast's Public routes
$routes->group('@(:podcastHandle)', static function ($routes): void {
// 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',
'namespace' => 'Modules\Fediverse\Controllers',
'controller-method' => 'ActorController::index/$1',
],
'application/podcast-activity+json' => [
'namespace' => 'App\Controllers',
'namespace' => 'App\Controllers',
'controller-method' => 'PodcastController::podcastActor/$1',
],
'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [
'namespace' => 'Modules\Fediverse\Controllers',
'controller-method' => 'ActorController/$1',
'namespace' => 'Modules\Fediverse\Controllers',
'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',
]);
$routes->options('episodes', 'ActivityPubController::preflight');
$routes->get('episodes', 'PodcastController::episodes/$1', [
'as' => 'podcast-episodes',
'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',
],
],
'filter' => 'allow-cors',
]);
$routes->group('episodes/(:slug)', function ($routes): void {
$routes->group('episodes/(:slug)', static function ($routes): void {
$routes->options('/', 'ActivityPubController::preflight');
$routes->get('/', 'EpisodeController/$1/$2', [
'as' => 'episode',
$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',
],
],
'filter' => 'allow-cors',
]);
$routes->get('activity', 'EpisodeController::activity/$1/$2', [
'as' => 'episode-activity',
]);
$routes->get('chapters', 'EpisodeController::chapters/$1/$2', [
'as' => 'episode-chapters',
]);
$routes->get('transcript', 'EpisodeController::transcript/$1/$2', [
'as' => 'episode-transcript',
]);
$routes->options('comments', 'ActivityPubController::preflight');
$routes->get('comments', 'EpisodeController::comments/$1/$2', [
'as' => 'episode-comments',
'as' => 'episode-comments',
'application/activity+json' => [
'controller-method' => 'EpisodeController::comments/$1/$2',
],
......@@ -140,9 +142,11 @@ $routes->group('@(:podcastHandle)', function ($routes): void {
'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [
'controller-method' => 'EpisodeController::comments/$1/$2',
],
'filter' => 'allow-cors',
]);
$routes->options('comments/(:uuid)', 'ActivityPubController::preflight');
$routes->get('comments/(:uuid)', 'EpisodeCommentController::view/$1/$2/$3', [
'as' => 'episode-comment',
'as' => 'episode-comment',
'application/activity+json' => [
'controller-method' => 'EpisodeController::commentObject/$1/$2',
],
......@@ -152,11 +156,12 @@ $routes->group('@(:podcastHandle)', function ($routes): void {
'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [
'controller-method' => 'EpisodeController::commentObject/$1/$2',
],
'filter' => 'allow-cors',
]);
$routes->get('comments/(:uuid)/replies', 'EpisodeCommentController::replies/$1/$2/$3', [
'as' => 'episode-comment-replies',
]);
$routes->post('comments/(:uuid)/like', 'EpisodeCommentController::attemptLike/$1/$2/$3', [
$routes->post('comments/(:uuid)/like', 'EpisodeCommentController::likeAction/$1/$2/$3', [
'as' => 'episode-comment-attempt-like',
]);
$routes->get('oembed.json', 'EpisodeController::oembedJSON/$1/$2', [
......@@ -165,7 +170,7 @@ $routes->group('@(:podcastHandle)', function ($routes): void {
$routes->get('oembed.xml', 'EpisodeController::oembedXML/$1/$2', [
'as' => 'episode-oembed-xml',
]);
$routes->group('embed', function ($routes): void {
$routes->group('embed', static function ($routes): void {
$routes->get('/', 'EpisodeController::embed/$1/$2', [
'as' => 'embed',
]);
......@@ -174,15 +179,38 @@ $routes->group('@(:podcastHandle)', function ($routes): void {
],);
});
});
$routes->head('feed.xml', 'FeedController/$1', [
'as' => 'podcast_feed',
$routes->head('feed.xml', 'FeedController::index/$1', [
'as' => 'podcast-rss-feed',
]);
$routes->get('feed.xml', 'FeedController/$1', [
'as' => 'podcast_feed',
$routes->get('feed.xml', 'FeedController::index/$1', [
'as' => 'podcast-rss-feed',
]);
$routes->head('feed', 'FeedController::index/$1');
$routes->get('feed', 'FeedController::index/$1');
});
// audio routes
$routes->head('/audio/@(:podcastHandle)/(:slug).(:alphanum)', 'EpisodeAudioController::index/$1/$2', [
'as' => 'episode-audio',
], );
$routes->get('/audio/@(:podcastHandle)/(:slug).(:alphanum)', 'EpisodeAudioController::index/$1/$2', [
'as' => 'episode-audio',
], );
// episode preview link
$routes->get('/p/(:uuid)', 'EpisodePreviewController::index/$1', [
'as' => 'episode-preview',
]);
$routes->get('/p/(:uuid)/activity', 'EpisodePreviewController::activity/$1', [
'as' => 'episode-preview-activity',
]);
$routes->get('/p/(:uuid)/chapters', 'EpisodePreviewController::chapters/$1', [
'as' => 'episode-preview-chapters',
]);
$routes->get('/p/(:uuid)/transcript', 'EpisodePreviewController::transcript/$1', [
'as' => 'episode-preview-transcript',
]);
// Other pages
$routes->get('/credits', 'CreditsController', [
'as' => 'credits',
......@@ -193,108 +221,88 @@ $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',
]);
/**
* Overwriting Fediverse routes file
*/
$routes->group('@(:podcastHandle)', function ($routes): void {
$routes->post('posts/new', 'PostController::attemptCreate/$1', [
'as' => 'post-attempt-create',
'filter' => 'permission:podcast-manage_publications',
$routes->group('@(:podcastHandle)', static function ($routes): void {
$routes->post('posts/new', 'PostController::createAction/$1', [
'as' => 'post-attempt-create',
'filter' => 'permission:podcast$1.manage-publications',
]);
// Post
$routes->group('posts/(:uuid)', function ($routes): void {
$routes->group('posts/(:uuid)', static function ($routes): void {
$routes->options('/', 'ActivityPubController::preflight');
$routes->get('/', 'PostController::view/$1/$2', [
'as' => 'post',
'as' => 'post',
'alternate-content' => [
'application/activity+json' => [
'namespace' => 'Modules\Fediverse\Controllers',
'controller-method' => 'PostController/$2',
'namespace' => 'Modules\Fediverse\Controllers',
'controller-method' => 'PostController::index/$2',
],
'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [
'namespace' => 'Modules\Fediverse\Controllers',
'controller-method' => 'PostController/$2',
'namespace' => 'Modules\Fediverse\Controllers',
'controller-method' => 'PostController::index/$2',
],
],
'filter' => 'allow-cors',
]);
$routes->options('replies', 'ActivityPubController::preflight');
$routes->get('replies', 'PostController/$1/$2', [
'as' => 'post-replies',
$routes->get('replies', 'PostController::index/$1/$2', [
'as' => 'post-replies',
'alternate-content' => [
'application/activity+json' => [
'namespace' => 'Modules\Fediverse\Controllers',
'namespace' => 'Modules\Fediverse\Controllers',
'controller-method' => 'PostController::replies/$2',
],
'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [
'namespace' => 'Modules\Fediverse\Controllers',
'namespace' => 'Modules\Fediverse\Controllers',
'controller-method' => 'PostController::replies/$2',
],
],
'filter' => 'allow-cors',
]);
// Actions
$routes->post('action', 'PostController::attemptAction/$1/$2', [
'as' => 'post-attempt-action',
'filter' => 'permission:podcast-interact_as',
$routes->post('action', 'PostController::action/$1/$2', [
'as' => 'post-attempt-action',
'filter' => 'permission:podcast$1.interact-as',
]);
$routes->post(
'block-actor',
'PostController::attemptBlockActor/$1/$2',
'PostController::blockActorAction/$1/$2',
[
'as' => 'post-attempt-block-actor',
'filter' => 'permission:fediverse-block_actors',
'as' => 'post-attempt-block-actor',
'filter' => 'permission:fediverse.manage-blocks',
],
);
$routes->post(
'block-domain',
'PostController::attemptBlockDomain/$1/$2',
'PostController::blockDomainAction/$1/$2',
[
'as' => 'post-attempt-block-domain',
'filter' => 'permission:fediverse-block_domains',
'as' => 'post-attempt-block-domain',
'filter' => 'permission:fediverse.manage-blocks',
],
);
$routes->post('delete', 'PostController::attemptDelete/$1/$2', [
'as' => 'post-attempt-delete',
'filter' => 'permission:podcast-manage_publications',
$routes->post('delete', 'PostController::deleteAction/$1/$2', [
'as' => 'post-attempt-delete',
'filter' => 'permission:podcast$1.manage-publications',
]);
$routes->get(
'remote/(:postAction)',
'PostController::remoteAction/$1/$2/$3',
'PostController::remoteActionAction/$1/$2/$3',
[
'as' => 'post-remote-action',
],
);
});
$routes->get('follow', 'ActorController::follow/$1', [
$routes->get('follow', 'ActorController::followView/$1', [
'as' => 'follow',
]);
$routes->get('outbox', 'ActorController::outbox/$1', [
'as' => 'outbox',
'filter' => 'activity-pub:verify-activitystream',
'as' => 'outbox',
'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 (file_exists(APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php')) {
require APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php';
}
<?php
declare(strict_types=1);
namespace Config;
use CodeIgniter\Config\Routing as BaseRouting;
/**
* Routing configuration
*/
class Routing extends BaseRouting
{
/**
* For Defined Routes.
* An array of files that contain route definitions.
* Route files are read in order, with the first match
* found taking precedence.
*
* Default: APPPATH . 'Config/Routes.php'
*
* @var list<string>
*/
public array $routeFiles = [
APPPATH . 'Config/Routes.php',
ROOTPATH . 'modules/Admin/Config/Routes.php',
ROOTPATH . 'modules/Analytics/Config/Routes.php',
ROOTPATH . 'modules/Api/Rest/V1/Config/Routes.php',
ROOTPATH . 'modules/Auth/Config/Routes.php',
ROOTPATH . 'modules/Fediverse/Config/Routes.php',
ROOTPATH . 'modules/Install/Config/Routes.php',
ROOTPATH . 'modules/Platforms/Config/Routes.php',
ROOTPATH . 'modules/PodcastImport/Config/Routes.php',
ROOTPATH . 'modules/PremiumPodcasts/Config/Routes.php',
];
/**
* For Defined Routes and Auto Routing.
* The default namespace to use for Controllers when no other
* namespace has been specified.
*
* Default: 'App\Controllers'
*/
public string $defaultNamespace = 'App\Controllers';
/**
* For Auto Routing.
* The default controller to use when no other controller has been
* specified.
*
* Default: 'Home'
*/
public string $defaultController = 'HomeController';
/**
* For Defined Routes and Auto Routing.
* The default method to call on the controller when no other
* method has been set in the route.
*
* Default: 'index'
*/
public string $defaultMethod = 'index';
/**
* For Auto Routing.
* Whether to translate dashes in URIs for controller/method to underscores.
* Primarily useful when using the auto-routing.
*
* Default: false
*/
public bool $translateURIDashes = false;
/**
* Sets the class/method that should be called if routing doesn't
* find a match. It can be the controller/method name like: Users::index
*
* This setting is passed to the Router class and handled there.
*
* If you want to use a closure, you will have to set it in the
* routes file by calling:
*
* $routes->set404Override(function() {
* // Do something here
* });
*
* Example:
* public $override404 = 'App\Errors::show404';
*/
public ?string $override404 = null;
/**
* If TRUE, the system will attempt to match the URI against
* Controllers by matching each segment against folders/files
* in APPPATH/Controllers, when a match wasn't found against
* defined routes.
*
* If FALSE, will stop searching and do NO automatic routing.
*/
public bool $autoRoute = false;
/**
* For Defined Routes.
* If TRUE, will enable the use of the 'prioritize' option
* when defining routes.
*
* Default: false
*/
public bool $prioritize = false;
/**
* For Defined Routes.
* If TRUE, matched multiple URI segments will be passed as one parameter.
*
* Default: false
*/
public bool $multipleSegmentsOneParam = false;
/**
* For Auto Routing (Improved).
* Map of URI segments and namespaces.
*
* The key is the first URI segment. The value is the controller namespace.
* E.g.,
* [
* 'blog' => 'Acme\Blog\Controllers',
* ]
*
* @var array<string, string> [ uri_segment => namespace ]
*/
public array $moduleRoutes = [];
/**
* For Auto Routing (Improved).
* Whether to translate dashes in URIs for controller/method to CamelCase.
* E.g., blog-controller -> BlogController
*
* If you enable this, $translateURIDashes is ignored.
*
* Default: false
*/
public bool $translateUriToCamelCase = true;
}
......@@ -17,7 +17,7 @@ class Security extends BaseConfig
*
* @var 'cookie'|'session'
*/
public string $csrfProtection = 'cookie';
public string $csrfProtection = 'session';
/**
* --------------------------------------------------------------------------
......@@ -26,7 +26,7 @@ class Security extends BaseConfig
*
* Randomize the CSRF Token for added security.
*/
public bool $tokenRandomize = false;
public bool $tokenRandomize = true;
/**
* --------------------------------------------------------------------------
......@@ -80,7 +80,7 @@ class Security extends BaseConfig
* CSRF Redirect
* --------------------------------------------------------------------------
*
* Redirect to previous page with error on failure.
* @see https://codeigniter4.github.io/userguide/libraries/security.html#redirection-on-failure
*/
public bool $redirect = true;
public bool $redirect = (ENVIRONMENT === 'production');
}
......@@ -5,16 +5,13 @@ declare(strict_types=1);
namespace Config;
use App\Libraries\Breadcrumb;
use App\Libraries\HtmlHead;
use App\Libraries\Negotiate;
use App\Libraries\Router;
use App\Libraries\View;
use App\Libraries\Vite;
use CodeIgniter\Config\BaseService;
use CodeIgniter\HTTP\Request;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\Router\RouteCollectionInterface;
use Config\Services as AppServices;
use Config\View as ViewConfig;
/**
* Services Configuration file.
......@@ -31,47 +28,25 @@ class Services extends BaseService
/**
* The Router class uses a RouteCollection's array of routes, and determines the correct Controller and Method to
* execute.
*
* @noRector PHPStan\Reflection\MissingMethodFromReflectionException
*/
public static function router(
?RouteCollectionInterface $routes = null,
?Request $request = null,
bool $getShared = true
bool $getShared = true,
): Router {
if ($getShared) {
return static::getSharedInstance('router', $routes, $request);
}
$routes = $routes ?? static::routes();
$request = $request ?? static::request();
$routes ??= static::routes();
$request ??= static::request();
return new Router($routes, $request);
}
/**
* The Renderer class is the class that actually displays a file to the user. The default View class within
* CodeIgniter is intentionally simple, but this service could easily be replaced by a template engine if the user
* needed to.
*/
public static function renderer(?string $viewPath = null, ?ViewConfig $config = null, bool $getShared = true): View
{
if ($getShared) {
return static::getSharedInstance('renderer', $viewPath, $config);
}
$viewPath = $viewPath ?: config('Paths')
->viewDirectory;
$config = $config ?? config('View');
return new View($config, $viewPath, AppServices::locator(), CI_DEBUG, AppServices::logger());
}
/**
* The Negotiate class provides the content negotiation features for working the request to determine correct
* language, encoding, charset, and more.
*
* @noRector PHPStan\Reflection\MissingMethodFromReflectionException
*/
public static function negotiator(?RequestInterface $request = null, bool $getShared = true): Negotiate
{
......@@ -79,7 +54,7 @@ class Services extends BaseService
return static::getSharedInstance('negotiator', $request);
}
$request = $request ?? static::request();
$request ??= static::request();
return new Negotiate($request);
}
......@@ -93,12 +68,12 @@ class Services extends BaseService
return new Breadcrumb();
}
public static function vite(bool $getShared = true): Vite
public static function html_head(bool $getShared = true): HtmlHead
{
if ($getShared) {
return self::getSharedInstance('vite');
return self::getSharedInstance('html_head');
}
return new Vite();
return new HtmlHead();
}
}
<?php
declare(strict_types=1);
namespace Config;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Session\Handlers\BaseHandler;
use CodeIgniter\Session\Handlers\FileHandler;
class Session extends BaseConfig
{
/**
* --------------------------------------------------------------------------
* Session Driver
* --------------------------------------------------------------------------
*
* The session storage driver to use:
* - `CodeIgniter\Session\Handlers\FileHandler`
* - `CodeIgniter\Session\Handlers\DatabaseHandler`
* - `CodeIgniter\Session\Handlers\MemcachedHandler`
* - `CodeIgniter\Session\Handlers\RedisHandler`
*
* @var class-string<BaseHandler>
*/
public string $driver = FileHandler::class;
/**
* --------------------------------------------------------------------------
* Session Cookie Name
* --------------------------------------------------------------------------
*
* The session cookie name, must contain only [0-9a-z_-] characters
*/
public string $cookieName = '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.
*/
public int $expiration = 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!
*/
public string $savePath = 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.
*/
public bool $matchIP = false;
/**
* --------------------------------------------------------------------------
* Session Time to Update
* --------------------------------------------------------------------------
*
* How many seconds between CI regenerating the session ID.
*/
public int $timeToUpdate = 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.
*/
public bool $regenerateDestroy = false;
/**
* --------------------------------------------------------------------------
* Session Database Group
* --------------------------------------------------------------------------
*
* DB Group for the database session.
*/
public ?string $DBGroup = null;
/**
* --------------------------------------------------------------------------
* Lock Retry Interval (microseconds)
* --------------------------------------------------------------------------
*
* This is used for RedisHandler.
*
* Time (microseconds) to wait if lock cannot be acquired.
* The default is 100,000 microseconds (= 0.1 seconds).
*/
public int $lockRetryInterval = 100_000;
/**
* --------------------------------------------------------------------------
* Lock Max Retries
* --------------------------------------------------------------------------
*
* This is used for RedisHandler.
*
* Maximum number of lock acquisition attempts.
* The default is 300 times. That is lock timeout is about 30 (0.1 * 300)
* seconds.
*/
public int $lockMaxRetries = 300;
}
<?php
declare(strict_types=1);
namespace Config;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Tasks\Scheduler;
class Tasks extends BaseConfig
{
/**
* --------------------------------------------------------------------------
* Should performance metrics be logged
* --------------------------------------------------------------------------
*
* If true, will log the time it takes for each task to run.
* Requires the settings table to have been created previously.
*/
public bool $logPerformance = false;
/**
* --------------------------------------------------------------------------
* Maximum performance logs
* --------------------------------------------------------------------------
*
* The maximum number of logs that should be saved per Task.
* Lower numbers reduced the amount of database required to
* store the logs.
*/
public int $maxLogsPerTask = 10;
/**
* Register any tasks within this method for the application.
* Called by the TaskRunner.
*/
public function init(Scheduler $schedule): void
{
$schedule->command('fediverse:broadcast')
->everyMinute()
->named('fediverse-broadcast');
$schedule->command('websub:publish')
->everyMinute()
->named('websub-publish');
$schedule->command('video-clips:generate')
->everyMinute()
->named('video-clips-generate');
$schedule->command('podcast:import')
->everyMinute()
->named('podcast-import');
$schedule->command('episodes:compute-downloads')
->everyHour()
->named('episodes:compute-downloads');
}
}
......@@ -33,7 +33,7 @@ class Toolbar extends BaseConfig
* List of toolbar collectors that will be called when Debug Toolbar
* fires up and collects data from.
*
* @var string[]
* @var list<class-string>
*/
public array $collectors = [
Timers::class,
......@@ -51,7 +51,7 @@ class Toolbar extends BaseConfig
* Collect Var Data
* --------------------------------------------------------------------------
*
* If set to false var data from the views will not be colleted. Useful to
* If set to false var data from the views will not be collected. Useful to
* avoid high memory usage when there are lots of data passed to the view.
*/
public bool $collectVarData = true;
......@@ -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 list<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 list<string>
*/
public array $watchedExtensions = ['php', 'css', 'js', 'html', 'svg', 'json', 'env'];
}
......@@ -27,47 +27,47 @@ class UserAgents extends BaseConfig
*/
public array $platforms = [
'windows nt 10.0' => 'Windows 10',
'windows nt 6.3' => 'Windows 8.1',
'windows nt 6.2' => 'Windows 8',
'windows nt 6.1' => 'Windows 7',
'windows nt 6.0' => 'Windows Vista',
'windows nt 5.2' => 'Windows 2003',
'windows nt 5.1' => 'Windows XP',
'windows nt 5.0' => 'Windows 2000',
'windows nt 4.0' => 'Windows NT 4.0',
'winnt4.0' => 'Windows NT 4.0',
'winnt 4.0' => 'Windows NT',
'winnt' => 'Windows NT',
'windows 98' => 'Windows 98',
'win98' => 'Windows 98',
'windows 95' => 'Windows 95',
'win95' => 'Windows 95',
'windows phone' => 'Windows Phone',
'windows' => 'Unknown Windows OS',
'android' => 'Android',
'blackberry' => 'BlackBerry',
'iphone' => 'iOS',
'ipad' => 'iOS',
'ipod' => 'iOS',
'os x' => 'Mac OS X',
'ppc mac' => 'Power PC Mac',
'freebsd' => 'FreeBSD',
'ppc' => 'Macintosh',
'linux' => 'Linux',
'debian' => 'Debian',
'sunos' => 'Sun Solaris',
'beos' => 'BeOS',
'apachebench' => 'ApacheBench',
'aix' => 'AIX',
'irix' => 'Irix',
'osf' => 'DEC OSF',
'hp-ux' => 'HP-UX',
'netbsd' => 'NetBSD',
'bsdi' => 'BSDi',
'openbsd' => 'OpenBSD',
'gnu' => 'GNU/Linux',
'unix' => 'Unknown Unix OS',
'symbian' => 'Symbian OS',
'windows nt 6.3' => 'Windows 8.1',
'windows nt 6.2' => 'Windows 8',
'windows nt 6.1' => 'Windows 7',
'windows nt 6.0' => 'Windows Vista',
'windows nt 5.2' => 'Windows 2003',
'windows nt 5.1' => 'Windows XP',
'windows nt 5.0' => 'Windows 2000',
'windows nt 4.0' => 'Windows NT 4.0',
'winnt4.0' => 'Windows NT 4.0',
'winnt 4.0' => 'Windows NT',
'winnt' => 'Windows NT',
'windows 98' => 'Windows 98',
'win98' => 'Windows 98',
'windows 95' => 'Windows 95',
'win95' => 'Windows 95',
'windows phone' => 'Windows Phone',
'windows' => 'Unknown Windows OS',
'android' => 'Android',
'blackberry' => 'BlackBerry',
'iphone' => 'iOS',
'ipad' => 'iOS',
'ipod' => 'iOS',
'os x' => 'Mac OS X',
'ppc mac' => 'Power PC Mac',
'freebsd' => 'FreeBSD',
'ppc' => 'Macintosh',
'linux' => 'Linux',
'debian' => 'Debian',
'sunos' => 'Sun Solaris',
'beos' => 'BeOS',
'apachebench' => 'ApacheBench',
'aix' => 'AIX',
'irix' => 'Irix',
'osf' => 'DEC OSF',
'hp-ux' => 'HP-UX',
'netbsd' => 'NetBSD',
'bsdi' => 'BSDi',
'openbsd' => 'OpenBSD',
'gnu' => 'GNU/Linux',
'unix' => 'Unknown Unix OS',
'symbian' => 'Symbian OS',
];
/**
......@@ -81,37 +81,37 @@ class UserAgents extends BaseConfig
* @var array<string, string>
*/
public array $browsers = [
'OPR' => 'Opera',
'Flock' => 'Flock',
'Edge' => 'Spartan',
'Edg' => 'Edge',
'OPR' => 'Opera',
'Flock' => 'Flock',
'Edge' => 'Spartan',
'Edg' => 'Edge',
'Chrome' => 'Chrome',
// Opera 10+ always reports Opera/9.80 and appends Version/<real version> to the user agent string
'Opera.*?Version' => 'Opera',
'Opera' => 'Opera',
'MSIE' => 'Internet Explorer',
'Opera.*?Version' => 'Opera',
'Opera' => 'Opera',
'MSIE' => 'Internet Explorer',
'Internet Explorer' => 'Internet Explorer',
'Trident.* rv' => 'Internet Explorer',
'Shiira' => 'Shiira',
'Firefox' => 'Firefox',
'Chimera' => 'Chimera',
'Phoenix' => 'Phoenix',
'Firebird' => 'Firebird',
'Camino' => 'Camino',
'Netscape' => 'Netscape',
'OmniWeb' => 'OmniWeb',
'Safari' => 'Safari',
'Mozilla' => 'Mozilla',
'Konqueror' => 'Konqueror',
'icab' => 'iCab',
'Lynx' => 'Lynx',
'Links' => 'Links',
'hotjava' => 'HotJava',
'amaya' => 'Amaya',
'IBrowse' => 'IBrowse',
'Maxthon' => 'Maxthon',
'Ubuntu' => 'Ubuntu Web Browser',
'Vivaldi' => 'Vivaldi',
'Trident.* rv' => 'Internet Explorer',
'Shiira' => 'Shiira',
'Firefox' => 'Firefox',
'Chimera' => 'Chimera',
'Phoenix' => 'Phoenix',
'Firebird' => 'Firebird',
'Camino' => 'Camino',
'Netscape' => 'Netscape',
'OmniWeb' => 'OmniWeb',
'Safari' => 'Safari',
'Mozilla' => 'Mozilla',
'Konqueror' => 'Konqueror',
'icab' => 'iCab',
'Lynx' => 'Lynx',
'Links' => 'Links',
'hotjava' => 'HotJava',
'amaya' => 'Amaya',
'IBrowse' => 'IBrowse',
'Maxthon' => 'Maxthon',
'Ubuntu' => 'Ubuntu Web Browser',
'Vivaldi' => 'Vivaldi',
];
/**
......@@ -139,86 +139,86 @@ class UserAgents extends BaseConfig
// 'motorola' => 'Motorola'
// Phones and Manufacturers
'motorola' => 'Motorola',
'nokia' => 'Nokia',
'palm' => 'Palm',
'iphone' => 'Apple iPhone',
'ipad' => 'iPad',
'ipod' => 'Apple iPod Touch',
'sony' => 'Sony Ericsson',
'ericsson' => 'Sony Ericsson',
'blackberry' => 'BlackBerry',
'cocoon' => 'O2 Cocoon',
'blazer' => 'Treo',
'lg' => 'LG',
'amoi' => 'Amoi',
'xda' => 'XDA',
'mda' => 'MDA',
'vario' => 'Vario',
'htc' => 'HTC',
'samsung' => 'Samsung',
'sharp' => 'Sharp',
'sie-' => 'Siemens',
'alcatel' => 'Alcatel',
'benq' => 'BenQ',
'ipaq' => 'HP iPaq',
'mot-' => 'Motorola',
'motorola' => 'Motorola',
'nokia' => 'Nokia',
'palm' => 'Palm',
'iphone' => 'Apple iPhone',
'ipad' => 'iPad',
'ipod' => 'Apple iPod Touch',
'sony' => 'Sony Ericsson',
'ericsson' => 'Sony Ericsson',
'blackberry' => 'BlackBerry',
'cocoon' => 'O2 Cocoon',
'blazer' => 'Treo',
'lg' => 'LG',
'amoi' => 'Amoi',
'xda' => 'XDA',
'mda' => 'MDA',
'vario' => 'Vario',
'htc' => 'HTC',
'samsung' => 'Samsung',
'sharp' => 'Sharp',
'sie-' => 'Siemens',
'alcatel' => 'Alcatel',
'benq' => 'BenQ',
'ipaq' => 'HP iPaq',
'mot-' => 'Motorola',
'playstation portable' => 'PlayStation Portable',
'playstation 3' => 'PlayStation 3',
'playstation vita' => 'PlayStation Vita',
'hiptop' => 'Danger Hiptop',
'nec-' => 'NEC',
'panasonic' => 'Panasonic',
'philips' => 'Philips',
'sagem' => 'Sagem',
'sanyo' => 'Sanyo',
'spv' => 'SPV',
'zte' => 'ZTE',
'sendo' => 'Sendo',
'nintendo dsi' => 'Nintendo DSi',
'nintendo ds' => 'Nintendo DS',
'nintendo 3ds' => 'Nintendo 3DS',
'wii' => 'Nintendo Wii',
'open web' => 'Open Web',
'openweb' => 'OpenWeb',
'playstation 3' => 'PlayStation 3',
'playstation vita' => 'PlayStation Vita',
'hiptop' => 'Danger Hiptop',
'nec-' => 'NEC',
'panasonic' => 'Panasonic',
'philips' => 'Philips',
'sagem' => 'Sagem',
'sanyo' => 'Sanyo',
'spv' => 'SPV',
'zte' => 'ZTE',
'sendo' => 'Sendo',
'nintendo dsi' => 'Nintendo DSi',
'nintendo ds' => 'Nintendo DS',
'nintendo 3ds' => 'Nintendo 3DS',
'wii' => 'Nintendo Wii',
'open web' => 'Open Web',
'openweb' => 'OpenWeb',
// Operating Systems
'android' => 'Android',
'symbian' => 'Symbian',
'SymbianOS' => 'SymbianOS',
'elaine' => 'Palm',
'series60' => 'Symbian S60',
'android' => 'Android',
'symbian' => 'Symbian',
'SymbianOS' => 'SymbianOS',
'elaine' => 'Palm',
'series60' => 'Symbian S60',
'windows ce' => 'Windows CE',
// Browsers
'obigo' => 'Obigo',
'netfront' => 'Netfront Browser',
'openwave' => 'Openwave Browser',
'obigo' => 'Obigo',
'netfront' => 'Netfront Browser',
'openwave' => 'Openwave Browser',
'mobilexplorer' => 'Mobile Explorer',
'operamini' => 'Opera Mini',
'opera mini' => 'Opera Mini',
'opera mobi' => 'Opera Mobile',
'fennec' => 'Firefox Mobile',
'operamini' => 'Opera Mini',
'opera mini' => 'Opera Mini',
'opera mobi' => 'Opera Mobile',
'fennec' => 'Firefox Mobile',
// Other
'digital paths' => 'Digital Paths',
'avantgo' => 'AvantGo',
'xiino' => 'Xiino',
'novarra' => 'Novarra Transcoder',
'vodafone' => 'Vodafone',
'docomo' => 'NTT DoCoMo',
'o2' => 'O2',
'avantgo' => 'AvantGo',
'xiino' => 'Xiino',
'novarra' => 'Novarra Transcoder',
'vodafone' => 'Vodafone',
'docomo' => 'NTT DoCoMo',
'o2' => 'O2',
// Fallback
'mobile' => 'Generic Mobile',
'wireless' => 'Generic Mobile',
'j2me' => 'Generic Mobile',
'midp' => 'Generic Mobile',
'cldc' => 'Generic Mobile',
'up.link' => 'Generic Mobile',
'mobile' => 'Generic Mobile',
'wireless' => 'Generic Mobile',
'j2me' => 'Generic Mobile',
'midp' => 'Generic Mobile',
'cldc' => 'Generic Mobile',
'up.link' => 'Generic Mobile',
'up.browser' => 'Generic Mobile',
'smartphone' => 'Generic Mobile',
'cellphone' => 'Generic Mobile',
'cellphone' => 'Generic Mobile',
];
/**
......@@ -231,24 +231,24 @@ class UserAgents extends BaseConfig
* @var array<string, string>
*/
public array $robots = [
'googlebot' => 'Googlebot',
'msnbot' => 'MSNBot',
'baiduspider' => 'Baiduspider',
'bingbot' => 'Bing',
'slurp' => 'Inktomi Slurp',
'yahoo' => 'Yahoo',
'ask jeeves' => 'Ask Jeeves',
'fastcrawler' => 'FastCrawler',
'infoseek' => 'InfoSeek Robot 1.0',
'lycos' => 'Lycos',
'yandex' => 'YandexBot',
'googlebot' => 'Googlebot',
'msnbot' => 'MSNBot',
'baiduspider' => 'Baiduspider',
'bingbot' => 'Bing',
'slurp' => 'Inktomi Slurp',
'yahoo' => 'Yahoo',
'ask jeeves' => 'Ask Jeeves',
'fastcrawler' => 'FastCrawler',
'infoseek' => 'InfoSeek Robot 1.0',
'lycos' => 'Lycos',
'yandex' => 'YandexBot',
'mediapartners-google' => 'MediaPartners Google',
'CRAZYWEBCRAWLER' => 'Crazy Webcrawler',
'adsbot-google' => 'AdsBot Google',
'feedfetcher-google' => 'Feedfetcher Google',
'curious george' => 'Curious George',
'ia_archiver' => 'Alexa Crawler',
'MJ12bot' => 'Majestic-12',
'Uptimebot' => 'Uptimebot',
'CRAZYWEBCRAWLER' => 'Crazy Webcrawler',
'adsbot-google' => 'AdsBot Google',
'feedfetcher-google' => 'Feedfetcher Google',
'curious george' => 'Curious George',
'ia_archiver' => 'Alexa Crawler',
'MJ12bot' => 'Majestic-12',
'Uptimebot' => 'Uptimebot',
];
}
......@@ -5,28 +5,27 @@ declare(strict_types=1);
namespace Config;
use App\Validation\FileRules as AppFileRules;
use App\Validation\Rules as AppRules;
use CodeIgniter\Validation\CreditCardRules;
use CodeIgniter\Validation\FileRules;
use CodeIgniter\Validation\FormatRules;
use CodeIgniter\Validation\Rules;
use Myth\Auth\Authentication\Passwords\ValidationRules as PasswordRules;
use App\Validation\OtherRules;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Validation\StrictRules\CreditCardRules;
use CodeIgniter\Validation\StrictRules\FileRules;
use CodeIgniter\Validation\StrictRules\FormatRules;
use CodeIgniter\Validation\StrictRules\Rules;
class Validation
class Validation extends BaseConfig
{
/**
* Stores the classes that contain the rules that are available.
*
* @var string[]
* @var list<string>
*/
public array $ruleSets = [
Rules::class,
FormatRules::class,
FileRules::class,
CreditCardRules::class,
AppRules::class,
AppFileRules::class,
PasswordRules::class,
OtherRules::class,
];
/**
......@@ -35,7 +34,7 @@ class Validation
* @var array<string, string>
*/
public array $templates = [
'list' => 'CodeIgniter\Validation\Views\list',
'list' => 'CodeIgniter\Validation\Views\list',
'single' => 'CodeIgniter\Validation\Views\single',
];
}
......@@ -5,7 +5,13 @@ declare(strict_types=1);
namespace Config;
use CodeIgniter\Config\View as BaseView;
use CodeIgniter\View\ViewDecoratorInterface;
use ViewComponents\Decorator;
/**
* @phpstan-type parser_callable (callable(mixed): mixed)
* @phpstan-type parser_callable_string (callable(mixed): mixed)&string
*/
class View extends BaseView
{
/**
......@@ -25,7 +31,8 @@ class View extends BaseView
*
* Examples: { title|esc(js) } { created_on|date(Y-m-d)|esc(attr) }
*
* @var string[]
* @var array<string, string>
* @phpstan-var array<string, parser_callable_string>
*/
public $filters = [];
......@@ -33,7 +40,18 @@ class View extends BaseView
* Parser Plugins provide a way to extend the functionality provided by the core Parser by creating aliases that
* will be replaced with any callable. Can be single or tag pair.
*
* @var string[]
* @var array<string, callable|list<string>|string>
* @phpstan-var array<string, list<parser_callable_string>|parser_callable_string|parser_callable>
*/
public $plugins = [];
/**
* View Decorators are class methods that will be run in sequence to have a chance to alter the generated output
* just prior to caching the results.
*
* All classes must implement CodeIgniter\View\ViewDecoratorInterface
*
* @var list<class-string<ViewDecoratorInterface>>
*/
public array $decorators = [Decorator::class];
}