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 994 additions and 1073 deletions
......@@ -6,6 +6,9 @@ namespace Config;
use CodeIgniter\Config\ForeignCharacters as BaseForeignCharacters;
/**
* @immutable
*/
class ForeignCharacters extends BaseForeignCharacters
{
}
......@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Config;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Format\FormatterInterface;
use CodeIgniter\Format\JSONFormatter;
use CodeIgniter\Format\XMLFormatter;
......@@ -24,7 +23,7 @@ class Format extends BaseConfig
* These formats are only checked when the data passed to the respond()
* method is an array.
*
* @var string[]
* @var list<string>
*/
public array $supportedResponseFormats = [
'application/json',
......@@ -45,8 +44,8 @@ class Format extends BaseConfig
*/
public array $formatters = [
'application/json' => JSONFormatter::class,
'application/xml' => XMLFormatter::class,
'text/xml' => XMLFormatter::class,
'application/xml' => XMLFormatter::class,
'text/xml' => XMLFormatter::class,
];
/**
......@@ -61,19 +60,7 @@ class Format extends BaseConfig
*/
public array $formatterOptions = [
'application/json' => JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES,
'application/xml' => 0,
'text/xml' => 0,
'application/xml' => 0,
'text/xml' => 0,
];
//--------------------------------------------------------------------
/**
* A Factory method to return the appropriate formatter for the given mime type.
*
* @deprecated This is an alias of `\CodeIgniter\Format\Format::getFormatter`. Use that instead.
*/
public function getFormatter(string $mime): FormatterInterface
{
return Services::format()->getFormatter($mime);
}
}
......@@ -25,22 +25,22 @@ class Generators extends BaseConfig
*
* YOU HAVE BEEN WARNED!
*
* @var array<string, string>
* @var array<string, string|array<string,string>>
*/
public array $views = [
'make:command' =>
'CodeIgniter\Commands\Generators\Views\command.tpl.php',
'make:controller' =>
'CodeIgniter\Commands\Generators\Views\controller.tpl.php',
'make:entity' => 'CodeIgniter\Commands\Generators\Views\entity.tpl.php',
'make:filter' => 'CodeIgniter\Commands\Generators\Views\filter.tpl.php',
'make:migration' =>
'CodeIgniter\Commands\Generators\Views\migration.tpl.php',
'make:model' => 'CodeIgniter\Commands\Generators\Views\model.tpl.php',
'make:seeder' => 'CodeIgniter\Commands\Generators\Views\seeder.tpl.php',
'make:validation' =>
'CodeIgniter\Commands\Generators\Views\validation.tpl.php',
'session:migration' =>
'CodeIgniter\Commands\Generators\Views\migration.tpl.php',
'make:cell' => [
'class' => 'CodeIgniter\Commands\Generators\Views\cell.tpl.php',
'view' => 'CodeIgniter\Commands\Generators\Views\cell_view.tpl.php',
],
'make:command' => 'CodeIgniter\Commands\Generators\Views\command.tpl.php',
'make:config' => 'CodeIgniter\Commands\Generators\Views\config.tpl.php',
'make:controller' => 'CodeIgniter\Commands\Generators\Views\controller.tpl.php',
'make:entity' => 'CodeIgniter\Commands\Generators\Views\entity.tpl.php',
'make:filter' => 'CodeIgniter\Commands\Generators\Views\filter.tpl.php',
'make:migration' => 'CodeIgniter\Commands\Generators\Views\migration.tpl.php',
'make:model' => 'CodeIgniter\Commands\Generators\Views\model.tpl.php',
'make:seeder' => 'CodeIgniter\Commands\Generators\Views\seeder.tpl.php',
'make:validation' => 'CodeIgniter\Commands\Generators\Views\validation.tpl.php',
'session:migration' => 'CodeIgniter\Commands\Generators\Views\migration.tpl.php',
];
}
......@@ -30,6 +30,15 @@ class Honeypot extends BaseConfig
/**
* Honeypot container
*
* If you enabled CSP, you can remove `style="display:none"`.
*/
public string $container = '<div style="display:none">{template}</div>';
/**
* The id attribute for Honeypot container tag
*
* Used when CSP is enabled.
*/
public string $containerId = 'hpc';
}
......@@ -26,48 +26,181 @@ class Images extends BaseConfig
* @var array<string, string>
*/
public array $handlers = [
'gd' => GDHandler::class,
'gd' => GDHandler::class,
'imagick' => ImageMagickHandler::class,
];
/*
|--------------------------------------------------------------------------
| Uploaded images resizing sizes (in px)
| Uploaded images sizes (in px)
|--------------------------------------------------------------------------
| The sizes listed below determine the resizing of images when uploaded.
| All uploaded images are of 1:1 ratio (width and height are the same).
*/
public int $thumbnailSize = 150;
public int $mediumSize = 320;
public int $largeSize = 1024;
/**
* Size of images linked in the rss feed (should be between 1400 and 3000)
* Podcast cover image sizes
*
* Uploaded podcast covers are of 1:1 ratio (width and height are the same).
*
* Size of images linked in the rss feed (should be between 1400 and 3000). Size for ID3 tag cover art (should be
* between 300 and 800)
*
* Array values are as follows: 'name' => [width, height]
*
* @var array<string, array<string, int|string>>
*/
public int $feedSize = 1400;
public array $podcastCoverSizes = [
'tiny' => [
'width' => 40,
'height' => 40,
'mimetype' => 'image/webp',
'extension' => 'webp',
],
'thumbnail' => [
'width' => 150,
'height' => 150,
'mimetype' => 'image/webp',
'extension' => 'webp',
],
'medium' => [
'width' => 320,
'height' => 320,
'mimetype' => 'image/webp',
'extension' => 'webp',
],
'large' => [
'width' => 1024,
'height' => 1024,
'mimetype' => 'image/webp',
'extension' => 'webp',
],
'feed' => [
'width' => 1400,
'height' => 1400,
],
'id3' => [
'width' => 500,
'height' => 500,
],
'og' => [
'width' => 1200,
'height' => 1200,
],
'federation' => [
'width' => 400,
'height' => 400,
],
'webmanifest192' => [
'width' => 192,
'height' => 192,
'mimetype' => 'image/png',
'extension' => 'png',
],
'webmanifest512' => [
'width' => 512,
'height' => 512,
'mimetype' => 'image/png',
'extension' => 'png',
],
];
/**
* Size for ID3 tag cover art (should be between 300 and 800)
* Podcast header cover image
*
* Uploaded podcast header covers are of 3:1 ratio
*
* @var array<string, array<string, int|string>>
*/
public int $id3Size = 500;
/*
|--------------------------------------------------------------------------
| Uploaded images naming extensions
|--------------------------------------------------------------------------
| The properties listed below set the name extensions for the resized images
*/
public array $podcastBannerSizes = [
'small' => [
'width' => 320,
'height' => 128,
'mimetype' => 'image/webp',
'extension' => 'webp',
],
'medium' => [
'width' => 960,
'height' => 320,
'mimetype' => 'image/webp',
'extension' => 'webp',
],
'federation' => [
'width' => 1500,
'height' => 500,
],
];
public string $thumbnailSuffix = '_thumbnail';
public string $avatarDefaultPath = 'assets/images/castopod-avatar.jpg';
public string $mediumSuffix = '_medium';
public string $avatarDefaultMimeType = 'image/jpg';
public string $largeSuffix = '_large';
/**
* @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 $feedSuffix = '_feed';
public string $podcastBannerDefaultMimeType = 'image/jpeg';
public string $id3Suffix = '_id3';
/**
* Person image
*
* Uploaded person images are of 1:1 ratio (width and height are the same).
*
* Array values are as follows: 'name' => [width, height]
*
* @var array<string, array<string, int|string>>
*/
public array $personAvatarSizes = [
'federation' => [
'width' => 400,
'height' => 400,
],
'tiny' => [
'width' => 40,
'height' => 40,
'mimetype' => 'image/webp',
'extension' => 'webp',
],
'thumbnail' => [
'width' => 150,
'height' => 150,
'mimetype' => 'image/webp',
'extension' => 'webp',
],
'medium' => [
'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 = ''): ?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;
}
$proposedExtension = trim(strtolower($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'];
}
......@@ -4,28 +4,31 @@ declare(strict_types=1);
namespace Config;
use ActivityPub\Config\ActivityPub as ActivityPubBase;
use App\Libraries\NoteObject;
class ActivityPub extends ActivityPubBase
/**
* 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
{
/**
* --------------------------------------------------------------------
* ActivityPub Objects
* --------------------------------------------------------------------
* --------------------------------------------------------------------------
* Config Caching
* --------------------------------------------------------------------------
*
* @see https://codeigniter.com/user_guide/concepts/factories.html#config-caching
*/
public string $noteObject = NoteObject::class;
public bool $configCacheEnabled = false;
/**
* --------------------------------------------------------------------
* Default avatar and cover images
* --------------------------------------------------------------------
* --------------------------------------------------------------------------
* Config Caching
* --------------------------------------------------------------------------
*
* @see https://codeigniter.com/user_guide/concepts/autoloader.html#file-locator-caching
*/
public string $defaultAvatarImagePath = 'media/castopod-avatar-default_thumbnail.jpg';
public string $defaultAvatarImageMimetype = 'image/jpeg';
public string $defaultCoverImagePath = 'media/castopod-cover-default.jpg';
public string $defaultCoverImageMimetype = 'image/jpeg';
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';
}
<?php
declare(strict_types=1);
namespace Config;
use CodeIgniter\Config\Publisher as BasePublisher;
/**
* Publisher Configuration
*
* Defines basic security restrictions for the Publisher class to prevent abuse by injecting malicious files into a
* project.
*/
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,41 +2,21 @@
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
* --------------------------------------------------------------------
*/
$routes->addPlaceholder('podcastHandle', '[a-zA-Z0-9\_]{1,32}');
$routes->addPlaceholder('slug', '[a-zA-Z0-9\-]{1,191}');
$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('statusAction', '\bfavourite|\breblog|\breply');
$routes->addPlaceholder('embeddablePlayerTheme', '\blight|\bdark|\blight-transparent|\bdark-transparent');
$routes->addPlaceholder('postAction', '\bfavourite|\breblog|\breply');
$routes->addPlaceholder('embedTheme', '\blight|\bdark|\blight-transparent|\bdark-transparent');
$routes->addPlaceholder(
'uuid',
'[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}',
......@@ -48,700 +28,111 @@ $routes->addPlaceholder(
* --------------------------------------------------------------------
*/
$routes->get('manifest.webmanifest', 'WebmanifestController', [
'as' => 'webmanifest',
]);
$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
// route since we don't have to scan directories.
$routes->get('/', 'HomeController::index', [
$routes->get('/', 'HomeController', [
'as' => 'home',
]);
// Install Wizard route
$routes->group(config('App')->installGateway, function ($routes): void {
$routes->get('/', 'InstallController', [
'as' => 'install',
]);
$routes->post('instance-config', 'InstallController::attemptInstanceConfig', [
'as' => 'instance-config',
]);
$routes->post('database-config', 'InstallController::attemptDatabaseConfig', [
'as' => 'database-config',
]);
$routes->post('cache-config', 'InstallController::attemptCacheConfig', [
'as' => 'cache-config',
]);
$routes->post(
'create-superadmin',
'InstallController::attemptCreateSuperAdmin',
[
'as' => 'create-superadmin',
],
);
});
$routes->get('.well-known/platforms', 'Platform');
// Admin area
$routes->group(
config('App')
->adminGateway,
[
'namespace' => 'App\Controllers\Admin',
],
function ($routes): void {
$routes->get('/', 'HomeController', [
'as' => 'admin',
]);
$routes->group('persons', function ($routes): void {
$routes->get('/', 'PersonController', [
'as' => 'person-list',
'filter' => 'permission:person-list',
]);
$routes->get('new', 'PersonController::create', [
'as' => 'person-create',
'filter' => 'permission:person-create',
]);
$routes->post('new', 'PersonController::attemptCreate', [
'filter' => 'permission:person-create',
]);
$routes->group('(:num)', function ($routes): void {
$routes->get('/', 'PersonController::view/$1', [
'as' => 'person-view',
'filter' => 'permission:person-view',
]);
$routes->get('edit', 'PersonController::edit/$1', [
'as' => 'person-edit',
'filter' => 'permission:person-edit',
]);
$routes->post('edit', 'PersonController::attemptEdit/$1', [
'filter' => 'permission:person-edit',
]);
$routes->add('delete', 'PersonController::delete/$1', [
'as' => 'person-delete',
'filter' => 'permission:person-delete',
]);
});
});
// Podcasts
$routes->group('podcasts', function ($routes): void {
$routes->get('/', 'PodcastController::list', [
'as' => 'podcast-list',
]);
$routes->get('new', 'PodcastController::create', [
'as' => 'podcast-create',
'filter' => 'permission:podcasts-create',
]);
$routes->post('new', 'PodcastController::attemptCreate', [
'filter' => 'permission:podcasts-create',
]);
$routes->get('import', 'PodcastImportController', [
'as' => 'podcast-import',
'filter' => 'permission:podcasts-import',
]);
$routes->post('import', 'PodcastImportController::attemptImport', [
'filter' => 'permission:podcasts-import',
]);
// Podcast
// Use ids in admin area to help permission and group lookups
$routes->group('(:num)', function ($routes): void {
$routes->get('/', 'PodcastController::view/$1', [
'as' => 'podcast-view',
'filter' => 'permission:podcasts-view,podcast-view',
]);
$routes->get('edit', 'PodcastController::edit/$1', [
'as' => 'podcast-edit',
'filter' => 'permission:podcast-edit',
]);
$routes->post('edit', 'PodcastController::attemptEdit/$1', [
'filter' => 'permission:podcast-edit',
]);
$routes->get('delete', 'PodcastController::delete/$1', [
'as' => 'podcast-delete',
'filter' => 'permission:podcasts-delete',
]);
$routes->group('persons', function ($routes): void {
$routes->get('/', 'PodcastPersonController/$1', [
'as' => 'podcast-person-manage',
'filter' => 'permission:podcast-edit',
]);
$routes->post(
'/',
'PodcastPersonController::attemptAdd/$1',
[
'filter' => 'permission:podcast-edit',
],
);
$routes->get(
'(:num)/remove',
'PodcastPersonController::remove/$1/$2',
[
'as' => 'podcast-person-remove',
'filter' => 'permission:podcast-edit',
],
);
});
$routes->group('analytics', function ($routes): void {
$routes->get('/', 'PodcastController::viewAnalytics/$1', [
'as' => 'podcast-analytics',
'filter' => 'permission:podcasts-view,podcast-view',
]);
$routes->get(
'webpages',
'PodcastController::viewAnalyticsWebpages/$1',
[
'as' => 'podcast-analytics-webpages',
'filter' => 'permission:podcasts-view,podcast-view',
],
);
$routes->get(
'locations',
'PodcastController::viewAnalyticsLocations/$1',
[
'as' => 'podcast-analytics-locations',
'filter' => 'permission:podcasts-view,podcast-view',
],
);
$routes->get(
'unique-listeners',
'PodcastController::viewAnalyticsUniqueListeners/$1',
[
'as' => 'podcast-analytics-unique-listeners',
'filter' => 'permission:podcasts-view,podcast-view',
],
);
$routes->get(
'listening-time',
'PodcastController::viewAnalyticsListeningTime/$1',
[
'as' => 'podcast-analytics-listening-time',
'filter' => 'permission:podcasts-view,podcast-view',
],
);
$routes->get(
'time-periods',
'PodcastController::viewAnalyticsTimePeriods/$1',
[
'as' => 'podcast-analytics-time-periods',
'filter' => 'permission:podcasts-view,podcast-view',
],
);
$routes->get(
'players',
'PodcastController::viewAnalyticsPlayers/$1',
[
'as' => 'podcast-analytics-players',
'filter' => 'permission:podcasts-view,podcast-view',
],
);
});
// Podcast episodes
$routes->group('episodes', function ($routes): void {
$routes->get('/', 'EpisodeController::list/$1', [
'as' => 'episode-list',
'filter' =>
'permission:episodes-list,podcast_episodes-list',
]);
$routes->get('new', 'EpisodeController::create/$1', [
'as' => 'episode-create',
'filter' => 'permission:podcast_episodes-create',
]);
$routes->post(
'new',
'EpisodeController::attemptCreate/$1',
[
'filter' => 'permission:podcast_episodes-create',
],
);
// Episode
$routes->group('(:num)', function ($routes): void {
$routes->get('/', 'EpisodeController::view/$1/$2', [
'as' => 'episode-view',
'filter' =>
'permission:episodes-view,podcast_episodes-view',
]);
$routes->get('edit', 'EpisodeController::edit/$1/$2', [
'as' => 'episode-edit',
'filter' => 'permission:podcast_episodes-edit',
]);
$routes->post(
'edit',
'EpisodeController::attemptEdit/$1/$2',
[
'filter' => 'permission:podcast_episodes-edit',
],
);
$routes->get(
'publish',
'EpisodeController::publish/$1/$2',
[
'as' => 'episode-publish',
'filter' =>
'permission:podcast-manage_publications',
],
);
$routes->post(
'publish',
'EpisodeController::attemptPublish/$1/$2',
[
'filter' =>
'permission:podcast-manage_publications',
],
);
$routes->get(
'publish-edit',
'EpisodeController::publishEdit/$1/$2',
[
'as' => 'episode-publish_edit',
'filter' =>
'permission:podcast-manage_publications',
],
);
$routes->post(
'publish-edit',
'EpisodeController::attemptPublishEdit/$1/$2',
[
'filter' =>
'permission:podcast-manage_publications',
],
);
$routes->get(
'publish-cancel',
'EpisodeController::publishCancel/$1/$2',
[
'as' => 'episode-publish-cancel',
'filter' =>
'permission:podcast-manage_publications',
],
);
$routes->get(
'unpublish',
'EpisodeController::unpublish/$1/$2',
[
'as' => 'episode-unpublish',
'filter' =>
'permission:podcast-manage_publications',
],
);
$routes->post(
'unpublish',
'EpisodeController::attemptUnpublish/$1/$2',
[
'filter' =>
'permission:podcast-manage_publications',
],
);
$routes->get(
'delete',
'EpisodeController::delete/$1/$2',
[
'as' => 'episode-delete',
'filter' =>
'permission:podcast_episodes-delete',
],
);
$routes->get(
'transcript-delete',
'EpisodeController::transcriptDelete/$1/$2',
[
'as' => 'transcript-delete',
'filter' => 'permission:podcast_episodes-edit',
],
);
$routes->get(
'chapters-delete',
'EpisodeController::chaptersDelete/$1/$2',
[
'as' => 'chapters-delete',
'filter' => 'permission:podcast_episodes-edit',
],
);
$routes->get(
'soundbites',
'EpisodeController::soundbitesEdit/$1/$2',
[
'as' => 'soundbites-edit',
'filter' => 'permission:podcast_episodes-edit',
],
);
$routes->post(
'soundbites',
'EpisodeController::soundbitesAttemptEdit/$1/$2',
[
'filter' => 'permission:podcast_episodes-edit',
],
);
$routes->get(
'soundbites/(:num)/delete',
'EpisodeController::soundbiteDelete/$1/$2/$3',
[
'as' => 'soundbite-delete',
'filter' => 'permission:podcast_episodes-edit',
],
);
$routes->get(
'embeddable-player',
'EpisodeController::embeddablePlayer/$1/$2',
[
'as' => 'embeddable-player-add',
'filter' => 'permission:podcast_episodes-edit',
],
);
$routes->group('persons', function ($routes): void {
$routes->get('/', 'EpisodePersonController/$1/$2', [
'as' => 'episode-person-manage',
'filter' => 'permission:podcast_episodes-edit',
]);
$routes->post(
'/',
'EpisodePersonController::attemptAdd/$1/$2',
[
'filter' =>
'permission:podcast_episodes-edit',
],
);
$routes->get(
'(:num)/remove',
'EpisodePersonController::remove/$1/$2/$3',
[
'as' => 'episode-person-remove',
'filter' =>
'permission:podcast_episodes-edit',
],
);
});
});
});
// Podcast contributors
$routes->group('contributors', function ($routes): void {
$routes->get('/', 'ContributorController::list/$1', [
'as' => 'contributor-list',
'filter' =>
'permission:podcasts-view,podcast-manage_contributors',
]);
$routes->get('add', 'ContributorController::add/$1', [
'as' => 'contributor-add',
'filter' => 'permission:podcast-manage_contributors',
]);
$routes->post(
'add',
'ContributorController::attemptAdd/$1',
[
'filter' =>
'permission:podcast-manage_contributors',
],
);
// Contributor
$routes->group('(:num)', function ($routes): void {
$routes->get('/', 'ContributorController::view/$1/$2', [
'as' => 'contributor-view',
'filter' =>
'permission:podcast-manage_contributors',
]);
$routes->get(
'edit',
'ContributorController::edit/$1/$2',
[
'as' => 'contributor-edit',
'filter' =>
'permission:podcast-manage_contributors',
],
);
$routes->post(
'edit',
'ContributorController::attemptEdit/$1/$2',
[
'filter' =>
'permission:podcast-manage_contributors',
],
);
$routes->get(
'remove',
'ContributorController::remove/$1/$2',
[
'as' => 'contributor-remove',
'filter' =>
'permission:podcast-manage_contributors',
],
);
});
});
$routes->group('platforms', function ($routes): void {
$routes->get(
'/',
'PodcastPlatformController::platforms/$1/podcasting',
[
'as' => 'platforms-podcasting',
'filter' => 'permission:podcast-manage_platforms',
],
);
$routes->get(
'social',
'PodcastPlatformController::platforms/$1/social',
[
'as' => 'platforms-social',
'filter' => 'permission:podcast-manage_platforms',
],
);
$routes->get(
'funding',
'PodcastPlatformController::platforms/$1/funding',
[
'as' => 'platforms-funding',
'filter' => 'permission:podcast-manage_platforms',
],
);
$routes->post(
'save/(:platformType)',
'PodcastPlatformController::attemptPlatformsUpdate/$1/$2',
[
'as' => 'platforms-save',
'filter' => 'permission:podcast-manage_platforms',
],
);
$routes->get(
'(:slug)/podcast-platform-remove',
'PodcastPlatformController::removePodcastPlatform/$1/$2',
[
'as' => 'podcast-platform-remove',
'filter' => 'permission:podcast-manage_platforms',
],
);
});
});
});
// Instance wide Fediverse config
$routes->group('fediverse', function ($routes): void {
$routes->get('/', 'FediverseController::dashboard', [
'as' => 'fediverse-dashboard',
]);
$routes->get(
'blocked-actors',
'FediverseController::blockedActors',
[
'as' => 'fediverse-blocked-actors',
'filter' => 'permission:fediverse-block_actors',
],
);
$routes->get(
'blocked-domains',
'FediverseController::blockedDomains',
[
'as' => 'fediverse-blocked-domains',
'filter' => 'permission:fediverse-block_domains',
],
);
});
// Pages
$routes->group('pages', function ($routes): void {
$routes->get('/', 'PageController::list', [
'as' => 'page-list',
]);
$routes->get('new', 'PageController::create', [
'as' => 'page-create',
'filter' => 'permission:pages-manage',
]);
$routes->post('new', 'PageController::attemptCreate', [
'filter' => 'permission:pages-manage',
]);
$routes->group('(:num)', function ($routes): void {
$routes->get('/', 'PageController::view/$1', [
'as' => 'page-view',
]);
$routes->get('edit', 'PageController::edit/$1', [
'as' => 'page-edit',
'filter' => 'permission:pages-manage',
]);
$routes->post('edit', 'PageController::attemptEdit/$1', [
'filter' => 'permission:pages-manage',
]);
$routes->get('delete', 'PageController::delete/$1', [
'as' => 'page-delete',
'filter' => 'permission:pages-manage',
]);
});
});
// Users
$routes->group('users', function ($routes): void {
$routes->get('/', 'UserController::list', [
'as' => 'user-list',
'filter' => 'permission:users-list',
]);
$routes->get('new', 'UserController::create', [
'as' => 'user-create',
'filter' => 'permission:users-create',
]);
$routes->post('new', 'UserController::attemptCreate', [
'filter' => 'permission:users-create',
]);
// User
$routes->group('(:num)', function ($routes): void {
$routes->get('/', 'UserController::view/$1', [
'as' => 'user-view',
'filter' => 'permission:users-view',
]);
$routes->get('edit', 'UserController::edit/$1', [
'as' => 'user-edit',
'filter' => 'permission:users-manage_authorizations',
]);
$routes->post('edit', 'UserController::attemptEdit/$1', [
'filter' => 'permission:users-manage_authorizations',
]);
$routes->get('ban', 'UserController::ban/$1', [
'as' => 'user-ban',
'filter' => 'permission:users-manage_bans',
]);
$routes->get('unban', 'UserController::unBan/$1', [
'as' => 'user-unban',
'filter' => 'permission:users-manage_bans',
]);
$routes->get(
'force-pass-reset',
'UserController::forcePassReset/$1',
[
'as' => 'user-force_pass_reset',
'filter' => 'permission:users-force_pass_reset',
],
);
$routes->get('delete', 'UserController::delete/$1', [
'as' => 'user-delete',
'filter' => 'permission:users-delete',
]);
});
});
// My account
$routes->group('my-account', function ($routes): void {
$routes->get('/', 'MyAccountController', [
'as' => 'my-account',
]);
$routes->get(
'change-password',
'MyAccountController::changePassword/$1',
[
'as' => 'change-password',
],
);
$routes->post('change-password', 'MyAccountController::attemptChange/$1');
});
},
);
/**
* Overwriting Myth:auth routes file
*/
$routes->group(config('App')->authGateway, function ($routes): void {
// Login/out
$routes->get('login', 'AuthController::login', [
'as' => 'login',
]);
$routes->post('login', 'AuthController::attemptLogin');
$routes->get('logout', 'AuthController::logout', [
'as' => 'logout',
]);
// Registration
$routes->get('register', 'AuthController::register', [
'as' => 'register',
]);
$routes->post('register', 'AuthController::attemptRegister');
// Activation
$routes->get('activate-account', 'AuthController::activateAccount', [
'as' => 'activate-account',
]);
$routes->get(
'resend-activate-account',
'AuthController::resendActivateAccount',
[
'as' => 'resend-activate-account',
],
);
// Forgot/Resets
$routes->get('forgot', 'AuthController::forgotPassword', [
'as' => 'forgot',
]);
$routes->post('forgot', 'AuthController::attemptForgot');
$routes->get('reset-password', 'AuthController::resetPassword', [
'as' => 'reset-password',
]);
$routes->post('reset-password', 'AuthController::attemptReset');
});
service('auth')
->routes($routes);
// Podcast's Public routes
$routes->group('@(:podcastHandle)', function ($routes): void {
$routes->get('/', 'PodcastController::activity/$1', [
'as' => 'podcast-activity',
]);
// override default ActivityPub Library's actor route
$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' => 'ActivityPub\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' => 'ActivityPub\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',
],
......@@ -751,6 +142,27 @@ $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',
'application/activity+json' => [
'controller-method' => 'EpisodeController::commentObject/$1/$2',
],
'application/podcast-activity+json' => [
'controller-method' => 'EpisodeController::commentObject/$1/$2',
],
'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::likeAction/$1/$2/$3', [
'as' => 'episode-comment-attempt-like',
]);
$routes->get('oembed.json', 'EpisodeController::oembedJSON/$1/$2', [
'as' => 'episode-oembed-json',
......@@ -758,144 +170,139 @@ $routes->group('@(:podcastHandle)', function ($routes): void {
$routes->get('oembed.xml', 'EpisodeController::oembedXML/$1/$2', [
'as' => 'episode-oembed-xml',
]);
$routes->group('embeddable-player', function ($routes): void {
$routes->get('/', 'EpisodeController::embeddablePlayer/$1/$2', [
'as' => 'embeddable-player',
$routes->group('embed', static function ($routes): void {
$routes->get('/', 'EpisodeController::embed/$1/$2', [
'as' => 'embed',
]);
$routes->get(
'(:embeddablePlayerTheme)',
'EpisodeController::embeddablePlayer/$1/$2/$3',
[
'as' => 'embeddable-player-theme',
],
);
$routes->get('(:embedTheme)', 'EpisodeController::embed/$1/$2/$3', [
'as' => 'embed-theme',
],);
});
});
$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',
]);
$routes->get('/map', 'MapMarkerController', [
$routes->get('/map', 'MapController', [
'as' => 'map',
]);
$routes->get('/episodes-markers', 'MapMarkerController::getEpisodesMarkers', [
$routes->get('/episodes-markers', 'MapController::getEpisodesMarkers', [
'as' => 'episodes-markers',
]);
$routes->get('/pages/(:slug)', 'PageController/$1', [
$routes->get('/pages/(:slug)', 'PageController::index/$1', [
'as' => 'page',
]);
// interacting as an actor
$routes->post('interact-as-actor', 'AuthController::attemptInteractAsActor', [
'as' => 'interact-as-actor',
]);
/**
* Overwriting ActivityPub routes file
* Overwriting Fediverse routes file
*/
$routes->group('@(:podcastHandle)', function ($routes): void {
$routes->post('statuses/new', 'StatusController::attemptCreate/$1', [
'as' => 'status-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',
]);
// Status
$routes->group('statuses/(:uuid)', function ($routes): void {
// Post
$routes->group('posts/(:uuid)', static function ($routes): void {
$routes->options('/', 'ActivityPubController::preflight');
$routes->get('/', 'StatusController::view/$1/$2', [
'as' => 'status',
$routes->get('/', 'PostController::view/$1/$2', [
'as' => 'post',
'alternate-content' => [
'application/activity+json' => [
'namespace' => 'ActivityPub\Controllers',
'controller-method' => 'StatusController/$2',
'namespace' => 'Modules\Fediverse\Controllers',
'controller-method' => 'PostController::index/$2',
],
'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [
'namespace' => 'ActivityPub\Controllers',
'controller-method' => 'StatusController/$2',
'namespace' => 'Modules\Fediverse\Controllers',
'controller-method' => 'PostController::index/$2',
],
],
'filter' => 'allow-cors',
]);
$routes->options('replies', 'ActivityPubController::preflight');
$routes->get('replies', 'StatusController/$1/$2', [
'as' => 'status-replies',
$routes->get('replies', 'PostController::index/$1/$2', [
'as' => 'post-replies',
'alternate-content' => [
'application/activity+json' => [
'namespace' => 'ActivityPub\Controllers',
'controller-method' => 'StatusController::replies/$2',
'namespace' => 'Modules\Fediverse\Controllers',
'controller-method' => 'PostController::replies/$2',
],
'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [
'namespace' => 'ActivityPub\Controllers',
'controller-method' => 'StatusController::replies/$2',
'namespace' => 'Modules\Fediverse\Controllers',
'controller-method' => 'PostController::replies/$2',
],
],
'filter' => 'allow-cors',
]);
// Actions
$routes->post('action', 'StatusController::attemptAction/$1/$2', [
'as' => 'status-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',
'StatusController::attemptBlockActor/$1/$2',
'PostController::blockActorAction/$1/$2',
[
'as' => 'status-attempt-block-actor',
'filter' => 'permission:fediverse-block_actors',
'as' => 'post-attempt-block-actor',
'filter' => 'permission:fediverse.manage-blocks',
],
);
$routes->post(
'block-domain',
'StatusController::attemptBlockDomain/$1/$2',
'PostController::blockDomainAction/$1/$2',
[
'as' => 'status-attempt-block-domain',
'filter' => 'permission:fediverse-block_domains',
'as' => 'post-attempt-block-domain',
'filter' => 'permission:fediverse.manage-blocks',
],
);
$routes->post('delete', 'StatusController::attemptDelete/$1/$2', [
'as' => 'status-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/(:statusAction)',
'StatusController::remoteAction/$1/$2/$3',
'remote/(:postAction)',
'PostController::remoteActionAction/$1/$2/$3',
[
'as' => 'status-remote-action',
'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;
}
......@@ -8,12 +8,32 @@ use CodeIgniter\Config\BaseConfig;
class Security extends BaseConfig
{
/**
* --------------------------------------------------------------------------
* CSRF Protection Method
* --------------------------------------------------------------------------
*
* Protection Method for Cross Site Request Forgery protection.
*
* @var 'cookie'|'session'
*/
public string $csrfProtection = 'session';
/**
* --------------------------------------------------------------------------
* CSRF Token Randomization
* --------------------------------------------------------------------------
*
* Randomize the CSRF Token for added security.
*/
public bool $tokenRandomize = true;
/**
* --------------------------------------------------------------------------
* CSRF Token Name
* --------------------------------------------------------------------------
*
* Token name for Cross Site Request Forgery protection cookie.
* Token name for Cross Site Request Forgery protection.
*/
public string $tokenName = 'csrf_test_name';
......@@ -22,7 +42,7 @@ class Security extends BaseConfig
* CSRF Header Name
* --------------------------------------------------------------------------
*
* Token name for Cross Site Request Forgery protection cookie.
* Header name for Cross Site Request Forgery protection.
*/
public string $headerName = 'X-CSRF-TOKEN';
......@@ -31,7 +51,7 @@ class Security extends BaseConfig
* CSRF Cookie Name
* --------------------------------------------------------------------------
*
* Cookie name for Cross Site Request Forgery protection cookie.
* Cookie name for Cross Site Request Forgery protection.
*/
public string $cookieName = 'csrf_cookie_name';
......@@ -51,7 +71,7 @@ class Security extends BaseConfig
* CSRF Regenerate
* --------------------------------------------------------------------------
*
* Regenerate CSRF Token on every request.
* Regenerate CSRF Token on every submission.
*/
public bool $regenerate = true;
......@@ -60,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');
}
......@@ -4,20 +4,14 @@ declare(strict_types=1);
namespace Config;
use App\Authorization\FlatAuthorization;
use App\Authorization\GroupModel;
use App\Authorization\PermissionModel;
use App\Libraries\Breadcrumb;
use App\Libraries\HtmlHead;
use App\Libraries\Negotiate;
use App\Libraries\Router;
use App\Libraries\Vite;
use App\Models\UserModel;
use CodeIgniter\Config\BaseService;
use CodeIgniter\HTTP\Request;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\Model;
use CodeIgniter\Router\RouteCollectionInterface;
use Myth\Auth\Models\LoginModel;
/**
* Services Configuration file.
......@@ -34,20 +28,18 @@ 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);
}
......@@ -55,8 +47,6 @@ class Services extends BaseService
/**
* 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
{
......@@ -64,73 +54,11 @@ class Services extends BaseService
return static::getSharedInstance('negotiator', $request);
}
$request = $request ?? static::request();
$request ??= static::request();
return new Negotiate($request);
}
/**
* @return mixed
*/
public static function authentication(
string $lib = 'local',
Model $userModel = null,
Model $loginModel = null,
bool $getShared = true
) {
if ($getShared) {
return self::getSharedInstance('authentication', $lib, $userModel, $loginModel);
}
// config() checks first in app/Config
$config = config('Auth');
$class = $config->authenticationLibs[$lib];
$instance = new $class($config);
if ($userModel === null) {
$userModel = new UserModel();
}
if ($loginModel === null) {
$loginModel = new LoginModel();
}
return $instance->setUserModel($userModel)
->setLoginModel($loginModel);
}
/**
* @return mixed
*/
public static function authorization(
Model $groupModel = null,
Model $permissionModel = null,
Model $userModel = null,
bool $getShared = true
) {
if ($getShared) {
return self::getSharedInstance('authorization', $groupModel, $permissionModel, $userModel);
}
if ($groupModel === null) {
$groupModel = new GroupModel();
}
if ($permissionModel === null) {
$permissionModel = new PermissionModel();
}
$instance = new FlatAuthorization($groupModel, $permissionModel);
if ($userModel === null) {
$userModel = new UserModel();
}
return $instance->setUserModel($userModel);
}
public static function breadcrumb(bool $getShared = true): Breadcrumb
{
if ($getShared) {
......@@ -140,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');
}
}