chore: update codeigniter to 4.5.1 + other dependencies to latest

This commit is contained in:
Yassine Doghri 2024-04-23 08:57:21 +00:00
parent 303a900f66
commit f9a939471d
57 changed files with 2840 additions and 2406 deletions

1
.gitignore vendored
View File

@ -132,7 +132,6 @@ tmp/
/results/
/phpunit*.xml
/.phpunit.*.cache
# js package manager
yarn.lock

View File

@ -1,6 +1,2 @@
<IfModule authz_core_module>
Require all denied
</IfModule>
<IfModule !authz_core_module>
Deny from all
</IfModule>
<IfModule authz_core_module> Require all denied </IfModule>
<IfModule !authz_core_module> Deny from all </IfModule>

View File

@ -61,6 +61,30 @@ class App extends BaseConfig
*/
public string $uriProtocol = 'REQUEST_URI';
/*
*--------------------------------------------------------------------------
* Allowed URL Characters
*--------------------------------------------------------------------------
*
* This lets you specify which characters are permitted within your URLs.
* When someone tries to submit a URL with disallowed characters they will
* get a warning message.
*
* As a security measure you are STRONGLY encouraged to restrict URLs to
* as few characters as possible.
*
* By default, only these are allowed: `a-z 0-9~%.:_-`
*
* Set an empty string to allow all characters -- but only if you are insane.
*
* The configured value is actually a regular expression character group
* and it will be used as: '/\A[<permittedURIChars>]+\z/iu'
*
* DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!!
*
*/
public string $permittedURIChars = 'a-z 0-9~%.:_\-';
/**
* --------------------------------------------------------------------------
* Default Locale

View File

@ -29,23 +29,17 @@ class Autoload extends AutoloadConfig
* their location on the file system. These are used by the autoloader
* to locate files the first time they have been instantiated.
*
* The '/app' and '/system' directories are already mapped for you.
* you may change the name of the 'App' namespace if you wish,
* The 'Config' (APPPATH . 'Config') and 'CodeIgniter' (SYSTEMPATH) are
* already mapped for you.
*
* You may change the name of the 'App' namespace if you wish,
* but this should be done prior to creating any namespaced classes,
* else you will need to modify all of those classes for this to work.
*
* Prototype:
*
* $psr4 = [
* 'CodeIgniter' => SYSTEMPATH,
* 'App' => APPPATH
* ];
*
* @var array<string, list<string>|string>
*/
public $psr4 = [
APP_NAMESPACE => APPPATH,
'Config' => APPPATH . 'Config/',
'Modules' => ROOTPATH . 'modules/',
'Modules\Admin' => ROOTPATH . 'modules/Admin/',
'Modules\Analytics' => ROOTPATH . 'modules/Analytics/',

View File

@ -11,8 +11,10 @@ declare(strict_types=1);
*
* If you set 'display_errors' to '1', CI4's detailed error report will show.
*/
error_reporting(E_ALL & ~E_DEPRECATED);
// If you want to suppress more types of errors.
// error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT & ~E_USER_NOTICE & ~E_USER_DEPRECATED);
ini_set('display_errors', '0');
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT & ~E_USER_NOTICE & ~E_USER_DEPRECATED);
/**
* --------------------------------------------------------------------------

View File

@ -48,25 +48,6 @@ class Cache extends BaseConfig
*/
public string $storePath = WRITEPATH . 'cache/';
/**
* --------------------------------------------------------------------------
* Cache Include Query String
* --------------------------------------------------------------------------
*
* Whether to take the URL query string into consideration when generating
* output cache files. Valid options are:
*
* false = Disabled
* true = Enabled, take all query parameters into account.
* Please be aware that this may result in numerous cache
* files generated for the same page over and over again.
* ['q'] = Enabled, but only take into account the specified list
* of query parameters.
*
* @var boolean|string[]
*/
public bool | array $cacheQueryString = false;
/**
* --------------------------------------------------------------------------
* Key Prefix
@ -170,4 +151,23 @@ class Cache extends BaseConfig
'redis' => RedisHandler::class,
'wincache' => WincacheHandler::class,
];
/**
* --------------------------------------------------------------------------
* Web Page Caching: Cache Include Query String
* --------------------------------------------------------------------------
*
* Whether to take the URL query string into consideration when generating
* output cache files. Valid options are:
*
* false = Disabled
* true = Enabled, take all query parameters into account.
* Please be aware that this may result in numerous cache
* files generated for the same page over and over again.
* ['q'] = Enabled, but only take into account the specified list
* of query parameters.
*
* @var bool|list<string>
*/
public $cacheQueryString = false;
}

View File

@ -35,28 +35,28 @@ class ContentSecurityPolicy extends BaseConfig
/**
* Will default to self if not overridden
*
* @var string|string[]|null
* @var list<string>|string|null
*/
public string | array | null $defaultSrc = null;
/**
* Lists allowed scripts' URLs.
*
* @var string|string[]
* @var list<string>|string
*/
public string | array $scriptSrc = 'self';
/**
* Lists allowed stylesheets' URLs.
*
* @var string|string[]
* @var list<string>|string
*/
public string | array $styleSrc = 'self';
/**
* Defines the origins from which images can be loaded.
*
* @var string|string[]
* @var list<string>|string
*/
public string | array $imageSrc = 'self';
@ -65,35 +65,35 @@ class ContentSecurityPolicy extends BaseConfig
*
* Will default to self if not overridden
*
* @var string|string[]|null
* @var list<string>|string|null
*/
public string | array | null $baseURI = null;
/**
* Lists the URLs for workers and embedded frame contents
*
* @var string|string[]
* @var list<string>|string
*/
public string | array $childSrc = 'self';
/**
* Limits the origins that you can connect to (via XHR, WebSockets, and EventSource).
*
* @var string|string[]
* @var list<string>|string
*/
public string | array $connectSrc = 'self';
/**
* Specifies the origins that can serve web fonts.
*
* @var string|string[]
* @var list<string>|string
*/
public string | array $fontSrc;
/**
* Lists valid endpoints for submission from `<form>` tags.
*
* @var string|string[]
* @var list<string>|string
*/
public string | array $formAction = 'self';
@ -102,47 +102,47 @@ class ContentSecurityPolicy extends BaseConfig
* `<embed>`, and `<applet>` tags. This directive can't be used in `<meta>` tags and applies only to non-HTML
* resources.
*
* @var string|string[]|null
* @var list<string>|string|null
*/
public string | array | null $frameAncestors = null;
/**
* The frame-src directive restricts the URLs which may be loaded into nested browsing contexts.
*
* @var string[]|string|null
* @var list<string>|string|null
*/
public string | array | null $frameSrc = null;
/**
* Restricts the origins allowed to deliver video and audio.
*
* @var string|string[]|null
* @var list<string>|string|null
*/
public string | array | null $mediaSrc = null;
/**
* Allows control over Flash and other plugins.
*
* @var string|string[]
* @var list<string>|string
*/
public string | array $objectSrc = 'self';
/**
* @var string|string[]|null
* @var list<string>|string|null
*/
public string | array | null $manifestSrc = null;
/**
* Limits the kinds of plugins a page may invoke.
*
* @var string|string[]|null
* @var list<string>|string|null
*/
public string | array | null $pluginTypes = null;
/**
* List of actions allowed.
*
* @var string|string[]|null
* @var list<string>|string|null
*/
public string | array | null $sandbox = null;

105
app/Config/Cors.php Normal file
View File

@ -0,0 +1,105 @@
<?php
namespace Config;
use CodeIgniter\Config\BaseConfig;
/**
* Cross-Origin Resource Sharing (CORS) Configuration
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
*/
class Cors extends BaseConfig
{
/**
* The default CORS configuration.
*
* @var array{
* allowedOrigins: list<string>,
* allowedOriginsPatterns: list<string>,
* supportsCredentials: bool,
* allowedHeaders: list<string>,
* exposedHeaders: list<string>,
* allowedMethods: list<string>,
* maxAge: int,
* }
*/
public array $default = [
/**
* Origins for the `Access-Control-Allow-Origin` header.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
*
* E.g.:
* - ['http://localhost:8080']
* - ['https://www.example.com']
*/
'allowedOrigins' => [],
/**
* Origin regex patterns for the `Access-Control-Allow-Origin` header.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
*
* NOTE: A pattern specified here is part of a regular expression. It will
* be actually `#\A<pattern>\z#`.
*
* E.g.:
* - ['https://\w+\.example\.com']
*/
'allowedOriginsPatterns' => [],
/**
* Weather to send the `Access-Control-Allow-Credentials` header.
*
* The Access-Control-Allow-Credentials response header tells browsers whether
* the server allows cross-origin HTTP requests to include credentials.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials
*/
'supportsCredentials' => false,
/**
* Set headers to allow.
*
* The Access-Control-Allow-Headers response header is used in response to
* a preflight request which includes the Access-Control-Request-Headers to
* indicate which HTTP headers can be used during the actual request.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers
*/
'allowedHeaders' => [],
/**
* Set headers to expose.
*
* The Access-Control-Expose-Headers response header allows a server to
* indicate which response headers should be made available to scripts running
* in the browser, in response to a cross-origin request.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers
*/
'exposedHeaders' => [],
/**
* Set methods to allow.
*
* The Access-Control-Allow-Methods response header specifies one or more
* methods allowed when accessing a resource in response to a preflight
* request.
*
* E.g.:
* - ['GET', 'POST', 'PUT', 'DELETE']
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods
*/
'allowedMethods' => [],
/**
* Set how many seconds the results of a preflight request can be cached.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age
*/
'maxAge' => 7200,
];
}

View File

@ -45,6 +45,11 @@ class Database extends Config
'failover' => [],
'port' => 3306,
'numberNative' => false,
'dateFormat' => [
'date' => 'Y-m-d',
'datetime' => 'Y-m-d H:i:s',
'time' => 'H:i:s',
],
];
/**
@ -64,7 +69,7 @@ class Database extends Config
'pConnect' => false,
'DBDebug' => true,
'charset' => 'utf8',
'DBCollat' => 'utf8_general_ci',
'DBCollat' => '',
'swapPre' => '',
'encrypt' => false,
'compress' => false,
@ -73,6 +78,11 @@ class Database extends Config
'port' => 3306,
'foreignKeys' => true,
'busyTimeout' => 1000,
'dateFormat' => [
'date' => 'Y-m-d',
'datetime' => 'Y-m-d H:i:s',
'time' => 'H:i:s',
],
];
//--------------------------------------------------------------------

View File

@ -33,7 +33,7 @@ class Exceptions extends BaseConfig
* Any status codes here will NOT be logged if logging is turned on.
* By default, only 404 (Page Not Found) exceptions are ignored.
*
* @var int[]
* @var list<int>
*/
public array $ignoreCodes = [404];
@ -56,7 +56,7 @@ class Exceptions extends BaseConfig
* In order to specify 2 levels, use "/" to separate.
* ex. ['server', 'setup/password', 'secret_token']
*
* @var string[]
* @var list<string>
*/
public array $sensitiveDataInTrace = [];

View File

@ -11,22 +11,21 @@ use CodeIgniter\Config\BaseConfig;
*/
class Feature extends BaseConfig
{
/**
* Enable multiple filters for a route or not.
*
* If you enable this:
* - CodeIgniter\CodeIgniter::handleRequest() uses:
* - CodeIgniter\Filters\Filters::enableFilters(), instead of enableFilter()
* - CodeIgniter\CodeIgniter::tryToRouteIt() uses:
* - CodeIgniter\Router\Router::getFilters(), instead of getFilter()
* - CodeIgniter\Router\Router::handle() uses:
* - property $filtersInfo, instead of $filterInfo
* - CodeIgniter\Router\RouteCollection::getFiltersForRoute(), instead of getFilterForRoute()
*/
public bool $multipleFilters = false;
/**
* Use improved new auto routing instead of the default legacy version.
*/
public bool $autoRoutesImproved = false;
/**
* Use filter execution order in 4.4 or before.
*/
public bool $oldFilterOrder = false;
/**
* The behavior of `limit(0)` in Query Builder.
*
* If true, `limit(0)` returns all records. (the behavior of 4.4.x or before in version 4.x.)
* If false, `limit(0)` returns no records. (the behavior of 3.1.9 or later in version 3.x.)
*/
public bool $limitZeroAsAll = true;
}

View File

@ -8,8 +8,11 @@ use App\Filters\AllowCorsFilter;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Filters\CSRF;
use CodeIgniter\Filters\DebugToolbar;
use CodeIgniter\Filters\ForceHTTPS;
use CodeIgniter\Filters\Honeypot;
use CodeIgniter\Filters\InvalidChars;
use CodeIgniter\Filters\PageCache;
use CodeIgniter\Filters\PerformanceMetrics;
use CodeIgniter\Filters\SecureHeaders;
use Modules\Auth\Filters\PermissionFilter;
@ -18,8 +21,10 @@ class Filters extends BaseConfig
/**
* Configures aliases for Filter classes to make reading things nicer and simpler.
*
* @var array<string, class-string|list<class-string>> [filter_name => classname]
* or [filter_name => [classname1, classname2, ...]]
* @var array<string, class-string|list<class-string>>
*
* [filter_name => classname]
* or [filter_name => [classname1, classname2, ...]]
*/
public array $aliases = [
'csrf' => CSRF::class,
@ -28,12 +33,41 @@ class Filters extends BaseConfig
'invalidchars' => InvalidChars::class,
'secureheaders' => SecureHeaders::class,
'allow-cors' => AllowCorsFilter::class,
'cors' => Cors::class,
'forcehttps' => ForceHTTPS::class,
'pagecache' => PageCache::class,
'performance' => PerformanceMetrics::class,
];
/**
* List of special required filters.
*
* The filters listed here are special. They are applied before and after
* other kinds of filters, and always applied even if a route does not exist.
*
* Filters set by default provide framework functionality. If removed,
* those functions will no longer work.
*
* @see https://codeigniter.com/user_guide/incoming/filters.html#provided-filters
*
* @var array{before: list<string>, after: list<string>}
*/
public array $required = [
'before' => [
'forcehttps', // Force Global Secure Requests
'pagecache', // Web Page Caching
],
'after' => [
'pagecache', // Web Page Caching
'performance', // Performance Metrics
'toolbar', // Debug Toolbar
],
];
/**
* List of filter aliases that are always applied before and after every request.
*
* @var array<string, array<string, array<string, string>>>|array<string, list<string>>
* @var array<string, array<string, array<string, string|array<string>>>>>|array<string, list<string>>
*/
public array $globals = [
'before' => [
@ -44,7 +78,6 @@ class Filters extends BaseConfig
// 'invalidchars',
],
'after' => [
'toolbar',
// 'honeypot',
// 'secureheaders',
],
@ -53,12 +86,12 @@ class Filters extends BaseConfig
/**
* List of filter aliases that works on a particular HTTP method (GET, POST, etc.).
*
* Example: 'post' => ['foo', 'bar']
* Example: 'POST' => ['foo', 'bar']
*
* If you use this, you should disable auto-routing because auto-routing permits any HTTP method to access a
* controller. Accessing the controller with a method you dont expect could bypass the filter.
*
* @var array<string, string[]>
* @var array<string, list<string>>
*/
public array $methods = [];
@ -67,7 +100,7 @@ class Filters extends BaseConfig
*
* Example: 'isLoggedIn' => ['before' => ['account/*', 'profiles/*']]
*
* @var array<string, array<string, string[]>>
* @var array<string, array<string, list<string>>>
*/
public array $filters = [];

View File

@ -24,7 +24,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',

View File

@ -28,8 +28,10 @@ class Generators extends BaseConfig
* @var array<string, string>
*/
public array $views = [
'make:cell' => 'CodeIgniter\Commands\Generators\Views\cell.tpl.php',
'make:cell_view' => 'CodeIgniter\Commands\Generators\Views\cell_view.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',

View File

@ -4,7 +4,6 @@ declare(strict_types=1);
namespace Config;
use CodeIgniter\Config\BaseConfig;
use Kint\Parser\ConstructablePluginInterface;
use Kint\Renderer\AbstractRenderer;
use Kint\Renderer\Rich\TabPluginInterface;
@ -20,7 +19,7 @@ use Kint\Renderer\Rich\ValuePluginInterface;
*
* @see https://kint-php.github.io/kint/ for details on these settings.
*/
class Kint extends BaseConfig
class Kint
{
/*
|--------------------------------------------------------------------------

View File

@ -38,7 +38,7 @@ 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 = (ENVIRONMENT === 'production') ? 4 : 9;
@ -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 = [
/*

View File

@ -22,7 +22,7 @@ class Mimes
/**
* Map of extensions to mime types.
*
* @var array<string, string|string[]>
* @var array<string, list<string>|string>
*/
public static $mimes = [
'hqx' => [

32
app/Config/Optimize.php Normal file
View File

@ -0,0 +1,32 @@
<?php
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;
}

View File

@ -12,13 +12,14 @@ use CodeIgniter\Config\Routing as BaseRouting;
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 string[]
* @var list<string>
*/
public array $routeFiles = [
APPPATH . 'Config/Routes.php',
@ -34,6 +35,7 @@ class Routing extends BaseRouting
];
/**
* For Defined Routes and Auto Routing.
* The default namespace to use for Controllers when no other
* namespace has been specified.
*
@ -42,6 +44,7 @@ class Routing extends BaseRouting
public string $defaultNamespace = 'App\Controllers';
/**
* For Auto Routing.
* The default controller to use when no other controller has been
* specified.
*
@ -50,6 +53,7 @@ class Routing extends BaseRouting
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.
*
@ -58,7 +62,8 @@ class Routing extends BaseRouting
public string $defaultMethod = 'index';
/**
* Whether to translate dashes in URIs to underscores.
* For Auto Routing.
* Whether to translate dashes in URIs for controller/method to underscores.
* Primarily useful when using the auto-routing.
*
* Default: false
@ -94,6 +99,7 @@ class Routing extends BaseRouting
public bool $autoRoute = false;
/**
* For Defined Routes.
* If TRUE, will enable the use of the 'prioritize' option
* when defining routes.
*
@ -102,7 +108,16 @@ class Routing extends BaseRouting
public bool $prioritize = false;
/**
* Map of URI segments and namespaces. For Auto Routing (Improved).
* 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.,
@ -113,4 +128,15 @@ class Routing extends BaseRouting
* @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 = false;
}

View File

@ -80,9 +80,9 @@ 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 = false;
public bool $redirect = (ENVIRONMENT === 'production');
/**
* --------------------------------------------------------------------------

View File

@ -101,4 +101,29 @@ class Session extends BaseConfig
* 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;
}

View File

@ -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;
@ -102,7 +102,7 @@ class Toolbar extends BaseConfig
*
* NOTE: The ROOTPATH will be prepended to all values.
*
* @var string[]
* @var list<string>
*/
public array $watchedDirectories = ['app', 'modules', 'themes'];
@ -114,7 +114,7 @@ class Toolbar extends BaseConfig
* Contains an array of file extensions that will be watched for changes and
* used to determine if the hot-reload feature should reload the page or not.
*
* @var string[]
* @var list<string>
*/
public array $watchedExtensions = ['php', 'css', 'js', 'html', 'svg', 'json', 'env'];
}

View File

@ -16,7 +16,7 @@ class Validation extends BaseConfig
/**
* Stores the classes that contain the rules that are available.
*
* @var string[]
* @var list<string>
*/
public array $ruleSets = [
Rules::class,

View File

@ -9,8 +9,8 @@ use CodeIgniter\View\ViewDecoratorInterface;
use ViewComponents\Decorator;
/**
* @phpstan-type ParserCallable (callable(mixed): mixed)
* @phpstan-type ParserCallableString (callable(mixed): mixed)&string
* @phpstan-type parser_callable (callable(mixed): mixed)
* @phpstan-type parser_callable_string (callable(mixed): mixed)&string
*/
class View extends BaseView
{
@ -31,8 +31,8 @@ class View extends BaseView
*
* Examples: { title|esc(js) } { created_on|date(Y-m-d)|esc(attr) }
*
* @var array<string, string>
* @phpstan-var array<string, ParserCallableString>
* @var array<string, string>
* @phpstan-var array<string, parser_callable_string>
*/
public $filters = [];
@ -40,8 +40,8 @@ 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 array<string, array<string>|callable|string>
* @phpstan-var array<string, array<ParserCallableString>|ParserCallableString|ParserCallable>
* @var array<string, callable|list<string>|string>
* @phpstan-var array<string, list<parser_callable_string>|parser_callable_string|parser_callable>
*/
public $plugins = [];
@ -51,7 +51,7 @@ class View extends BaseView
*
* All classes must implement CodeIgniter\View\ViewDecoratorInterface
*
* @var class-string<ViewDecoratorInterface>[]
* @var list<class-string<ViewDecoratorInterface>>
*/
public array $decorators = [Decorator::class];
}

View File

@ -41,7 +41,7 @@ abstract class BaseController extends Controller
* class instantiation. These helpers will be available
* to all other controllers that extend BaseController.
*
* @var string[]
* @var list<string>
*/
protected $helpers = [];

View File

@ -40,7 +40,7 @@ class EpisodeAudioController extends Controller
* An array of helpers to be loaded automatically upon class instantiation. These helpers will be available to all
* other controllers that extend Analytics.
*
* @var string[]
* @var list<string>
*/
protected $helpers = ['analytics'];

View File

@ -26,7 +26,7 @@ class CategoryModel extends Model
protected $primaryKey = 'id';
/**
* @var string[]
* @var list<string>
*/
protected $allowedFields = ['parent_id', 'code', 'apple_category', 'google_category'];

View File

@ -33,7 +33,7 @@ class ClipModel extends Model
protected $primaryKey = 'id';
/**
* @var string[]
* @var list<string>
*/
protected $allowedFields = [
'id',

View File

@ -40,7 +40,7 @@ class EpisodeCommentModel extends UuidModel
protected $uuidFields = ['id', 'in_reply_to_id'];
/**
* @var string[]
* @var list<string>
*/
protected $allowedFields = [
'id',
@ -57,7 +57,7 @@ class EpisodeCommentModel extends UuidModel
];
/**
* @var string[]
* @var list<string>
*/
protected $beforeInsert = ['setCommentId'];

View File

@ -62,7 +62,7 @@ class EpisodeModel extends UuidModel
protected $table = 'episodes';
/**
* @var string[]
* @var list<string>
*/
protected $allowedFields = [
'id',
@ -127,17 +127,17 @@ class EpisodeModel extends UuidModel
];
/**
* @var string[]
* @var list<string>
*/
protected $afterInsert = ['writeEnclosureMetadata', 'clearCache'];
/**
* @var string[]
* @var list<string>
*/
protected $afterUpdate = ['clearCache', 'writeEnclosureMetadata'];
/**
* @var string[]
* @var list<string>
*/
protected $beforeDelete = ['clearCache'];

View File

@ -26,7 +26,7 @@ class LanguageModel extends Model
protected $primaryKey = 'id';
/**
* @var string[]
* @var list<string>
*/
protected $allowedFields = ['code', 'native_name'];

View File

@ -31,7 +31,7 @@ class LikeModel extends UuidModel
protected $uuidFields = ['comment_id'];
/**
* @var string[]
* @var list<string>
*/
protected $allowedFields = ['actor_id', 'comment_id'];

View File

@ -26,7 +26,7 @@ class PageModel extends Model
protected $primaryKey = 'id';
/**
* @var string[]
* @var list<string>
*/
protected $allowedFields = ['id', 'title', 'slug', 'content_markdown', 'content_html'];
@ -55,19 +55,19 @@ class PageModel extends Model
];
/**
* @var string[]
* @var list<string>
*/
protected $afterInsert = ['clearCache'];
/**
* Before update because slug or title might change
*
* @var string[]
* @var list<string>
*/
protected $beforeUpdate = ['clearCache'];
/**
* @var string[]
* @var list<string>
*/
protected $beforeDelete = ['clearCache'];

View File

@ -26,7 +26,7 @@ class PersonModel extends Model
protected $primaryKey = 'id';
/**
* @var string[]
* @var list<string>
*/
protected $allowedFields = [
'id',
@ -64,19 +64,19 @@ class PersonModel extends Model
];
/**
* @var string[]
* @var list<string>
*/
protected $afterInsert = ['clearCache'];
/**
* clear cache before update if by any chance, the person name changes, so will the person link
*
* @var string[]
* @var list<string>
*/
protected $beforeUpdate = ['clearCache'];
/**
* @var string[]
* @var list<string>
*/
protected $beforeDelete = ['clearCache'];

View File

@ -30,7 +30,7 @@ class PodcastModel extends Model
protected $primaryKey = 'id';
/**
* @var string[]
* @var list<string>
*/
protected $allowedFields = [
'id',
@ -104,29 +104,29 @@ class PodcastModel extends Model
];
/**
* @var string[]
* @var list<string>
*/
protected $beforeInsert = ['setPodcastGUID', 'createPodcastActor'];
/**
* @var string[]
* @var list<string>
*/
protected $afterInsert = ['setActorAvatar'];
/**
* @var string[]
* @var list<string>
*/
protected $afterUpdate = ['updatePodcastActor'];
/**
* clear cache before update if by any chance, the podcast name changes, so will the podcast link
*
* @var string[]
* @var list<string>
*/
protected $beforeUpdate = ['clearCache'];
/**
* @var string[]
* @var list<string>
*/
protected $beforeDelete = ['clearCache'];

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
use CodeIgniter\CLI\CLI;
// The main Exception
CLI::write('[' . get_class($exception) . ']', 'light_gray', 'red');
CLI::write('[' . $exception::class . ']', 'light_gray', 'red');
CLI::write($message);
CLI::write('at ' . CLI::color(clean_path($exception->getFile()) . ':' . $exception->getLine(), 'green'));
CLI::newLine();
@ -16,7 +16,7 @@ while ($prevException = $last->getPrevious()) {
$last = $prevException;
CLI::write(' Caused by:');
CLI::write(' [' . get_class($prevException) . ']', 'red');
CLI::write(' [' . $prevException::class . ']', 'red');
CLI::write(' ' . $prevException->getMessage());
CLI::write(' at ' . CLI::color(clean_path($prevException->getFile()) . ':' . $prevException->getLine(), 'green'));
CLI::newLine();
@ -52,20 +52,11 @@ if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE) {
$function .= $padClass . $error['function'];
}
$args = implode(', ', array_map(static function ($value) {
switch (true) {
case is_object($value):
return 'Object(' . get_class($value) . ')';
case is_array($value):
return count($value) ? '[...]' : '[]';
case $value === null:
return 'null'; // return the lowercased version
default:
return var_export($value, true);
}
$args = implode(', ', array_map(static fn ($value) => match (true) {
is_object($value) => 'Object(' . $value::class . ')',
is_array($value) => count($value) ? '[...]' : '[]',
$value === null => 'null', // return the lowercased version
default => var_export($value, true),
}, array_values($error['args'] ?? [])));
$function .= '(' . $args . ')';

View File

@ -18,62 +18,69 @@ body {
margin: 0;
padding: 0;
}
h1 {
font-weight: lighter;
letter-spacing: 0.8;
font-size: 3rem;
color: var(--dark-text-color);
margin: 0;
}
h1.headline {
margin-top: 20%;
font-size: 5rem;
}
.text-center {
text-align: center;
}
p.lead {
font-size: 1.6rem;
}
.container {
max-width: 75rem;
margin: 0 auto;
padding: 1rem;
}
.header {
background: var(--light-bg-color);
color: var(--dark-text-color);
}
.header .container {
padding: 1rem 1.75rem 1.75rem 1.75rem;
padding: 1rem;
}
.header h1 {
font-size: 2.5rem;
font-weight: 500;
}
.header p {
font-size: 1.2rem;
margin: 0;
line-height: 2.5;
}
.header a {
color: var(--brand-primary-color);
margin-left: 2rem;
display: none;
text-decoration: none;
}
.header:hover a {
display: inline;
}
.footer {
.environment {
background: var(--dark-bg-color);
color: var(--light-text-color);
}
.footer .container {
border-top: 1px solid #e7e7e7;
margin-top: 1rem;
text-align: center;
padding: 0.2rem;
}
.source {
@ -86,17 +93,21 @@ p.lead {
margin: 0;
overflow-x: scroll;
}
.source span.line {
line-height: 1.4;
}
.source span.line .number {
color: #666;
}
.source .line .highlight {
display: block;
background: var(--dark-text-color);
color: var(--light-text-color);
}
.source span.highlight .number {
color: #fff;
}
@ -108,37 +119,44 @@ p.lead {
padding: 0;
margin-bottom: -1px;
}
.tabs li {
display: inline;
}
.tabs a:link,
.tabs a:visited {
padding: 0rem 1rem;
padding: 0 1rem;
line-height: 2.7;
text-decoration: none;
color: var(--dark-text-color);
background: var(--light-bg-color);
border: 1px solid rgba(0, 0, 0, 0.15);
border: 1px solid rgb(0 0 0 / 15%);
border-bottom: 0;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
display: inline-block;
}
.tabs a:hover {
background: var(--light-bg-color);
border-color: rgba(0, 0, 0, 0.15);
border-color: rgb(0 0 0 / 15%);
}
.tabs a.active {
background: var(--main-bg-color);
color: var(--main-text-color);
}
.tab-content {
background: var(--main-bg-color);
border: 1px solid rgba(0, 0, 0, 0.15);
border: 1px solid rgb(0 0 0 / 15%);
}
.content {
padding: 1rem;
}
.hide {
display: none;
}
@ -153,26 +171,26 @@ p.lead {
border-radius: 5px;
color: #31708f;
}
ul,
ol {
line-height: 1.8;
}
table {
width: 100%;
overflow: hidden;
}
th {
text-align: left;
border-bottom: 1px solid #e7e7e7;
padding-bottom: 0.5rem;
}
td {
padding: 0.2rem 0.5rem 0.2rem 0;
}
tr:hover td {
background: #f1f1f1;
}
td pre {
white-space: pre-wrap;
}
@ -180,20 +198,25 @@ td pre {
.trace a {
color: inherit;
}
.trace table {
width: auto;
}
.trace tr td:first-child {
min-width: 5em;
font-weight: bold;
}
.trace td {
background: var(--light-bg-color);
padding: 0 1rem;
}
.trace td pre {
margin: 0;
}
.args {
display: none;
}

View File

@ -3,6 +3,7 @@
declare(strict_types=1);
use CodeIgniter\CodeIgniter;
use CodeIgniter\HTTP\Header;
use Config\Services;
$errorId = uniqid('error', true);
@ -26,6 +27,12 @@ $errorId = uniqid('error', true);
<!-- Header -->
<div class="header">
<div class="environment">
Displayed at <?= esc(date('H:i:sa')) ?> &mdash;
PHP: <?= esc(PHP_VERSION) ?> &mdash;
CodeIgniter: <?= esc(CodeIgniter::CI_VERSION) ?> --
Environment: <?= ENVIRONMENT ?>
</div>
<div class="container">
<h1><?= esc($title), esc($exception->getCode() ? ' #' . $exception->getCode() : '') ?></h1>
<p>
@ -57,10 +64,10 @@ while ($prevException = $last->getPrevious()) {
<pre>
Caused by:
<?= esc(get_class($prevException)), esc($prevException->getCode() ? ' #' . $prevException->getCode() : '') ?>
<?= esc($prevException::class), esc($prevException->getCode() ? ' #' . $prevException->getCode() : '') ?>
<?= nl2br(esc($prevException->getMessage())) ?>
<a href="https://www.duckduckgo.com/?q=<?= urlencode(get_class($prevException) . ' ' . preg_replace('#\'.*\'|".*"#Us', '', $prevException->getMessage())) ?>"
<a href="https://www.duckduckgo.com/?q=<?= urlencode($prevException::class . ' ' . preg_replace('#\'.*\'|".*"#Us', '', $prevException->getMessage())) ?>"
rel="noreferrer" target="_blank">search &rarr;</a>
<?= esc(clean_path($prevException->getFile()) . ':' . $prevException->getLine()) ?>
</pre>
@ -117,7 +124,7 @@ while ($prevException = $last->getPrevious()) {
<?php
$params = null;
// Reflection by name is not available for closure function
if (substr($row['function'], -1) !== '}') {
if (! str_ends_with($row['function'], '}')) {
$mirror = isset($row['class']) ? new ReflectionMethod($row['class'], $row['function']) : new ReflectionFunction($row['function']);
$params = $mirror->getParameters();
}
@ -231,7 +238,7 @@ while ($prevException = $last->getPrevious()) {
</tr>
<tr>
<td>HTTP Method</td>
<td><?= esc(strtoupper($request->getMethod())) ?></td>
<td><?= esc($request->getMethod()) ?></td>
</tr>
<tr>
<td>IP Address</td>
@ -315,22 +322,22 @@ while ($prevException = $last->getPrevious()) {
</tr>
</thead>
<tbody>
<?php foreach ($headers as $value) : ?>
<?php
if (empty($value)) {
continue;
}
if (! is_array($value)) {
$value = [$value];
} ?>
<?php foreach ($value as $h) : ?>
<tr>
<td><?= esc($h->getName(), 'html') ?></td>
<td><?= esc($h->getValueLine(), 'html') ?></td>
</tr>
<?php endforeach; ?>
<?php endforeach; ?>
<?php foreach ($headers as $name => $value) : ?>
<tr>
<td><?= esc($name, 'html') ?></td>
<td>
<?php
if ($value instanceof Header) {
echo esc($value->getValueLine(), 'html');
} else {
foreach ($value as $i => $header) {
echo ' (' . $i + 1 . ') ' . esc($header->getValueLine(), 'html');
}
}
?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
@ -352,8 +359,6 @@ $response->setStatusCode(http_response_code());
<?php $headers = $response->headers(); ?>
<?php if (! empty($headers)) : ?>
<?php natsort($headers) ?>
<h3>Headers</h3>
<table>
@ -364,12 +369,22 @@ $response->setStatusCode(http_response_code());
</tr>
</thead>
<tbody>
<?php foreach (array_keys($headers) as $name) : ?>
<?php foreach ($headers as $name => $value) : ?>
<tr>
<td><?= esc($name, 'html') ?></td>
<td><?= esc($response->getHeaderLine($name), 'html') ?></td>
<td>
<?php
if ($value instanceof Header) {
echo esc($response->getHeaderLine($name), 'html');
} else {
foreach ($value as $i => $header) {
echo ' (' . $i + 1 . ') ' . esc($header->getValueLine(), 'html');
}
}
?>
</td>
</tr>
<?php endforeach; ?>
<?php endforeach; ?>
</tbody>
</table>
@ -414,18 +429,5 @@ $response->setStatusCode(http_response_code());
</div> <!-- /container -->
<?php endif; ?>
<div class="footer">
<div class="container">
<p>
Displayed at <?= esc(date('H:i:sa')) ?> &mdash;
PHP: <?= esc(PHP_VERSION) ?> &mdash;
CodeIgniter: <?= esc(CodeIgniter::CI_VERSION) ?> --
Environment: <?= ENVIRONMENT ?>
</p>
</div>
</div>
</body>
</html>

View File

@ -9,38 +9,41 @@
"php": "^8.1",
"adaures/ipcat-php": "^v1.0.0",
"adaures/podcast-persons-taxonomy": "^v1.0.1",
"aws/aws-sdk-php": "^3.300.8",
"aws/aws-sdk-php": "^3.305.1",
"chrisjean/php-ico": "^1.0.4",
"cocur/slugify": "^v4.5.1",
"codeigniter4/framework": "v4.4.6",
"codeigniter4/framework": "v4.5.1",
"codeigniter4/settings": "v2.2.0",
"codeigniter4/shield": "v1.0.1",
"codeigniter4/shield": "v1.0.3",
"codeigniter4/tasks": "dev-develop",
"geoip2/geoip2": "v3.0.0",
"james-heinrich/getid3": "^2.0.0-beta5",
"league/commonmark": "^2.4.2",
"league/html-to-markdown": "5.1.1",
"melbahja/seo": "^v2.1.1",
"michalsn/codeigniter4-uuid": "v1.0.2",
"mpratt/embera": "^2.0.36",
"michalsn/codeigniter4-uuid": "v1.1.0",
"mpratt/embera": "^2.0.38",
"opawg/user-agents-v2-php": "dev-main",
"phpseclib/phpseclib": "~2.0.47",
"vlucas/phpdotenv": "v5.6.0",
"whichbrowser/parser": "^v2.1.7",
"whichbrowser/parser": "^v2.1.8",
"yassinedoghri/podcast-feed": "dev-main"
},
"require-dev": {
"captainhook/captainhook": "^5.21.2",
"captainhook/captainhook": "^5.23.0",
"codeigniter/phpstan-codeigniter": "v1.4.3",
"mikey179/vfsstream": "^v1.6.11",
"phpstan/extension-installer": "^1.3.1",
"phpstan/phpstan": "^1.10.59",
"phpunit/phpunit": "^10.5.11",
"rector/rector": "^1.0.1",
"phpstan/phpstan": "^1.10.67",
"phpunit/phpunit": "^10.5.20",
"rector/rector": "^1.0.4",
"symplify/coding-standard": "^12.0.7",
"symplify/easy-coding-standard": "^12.0.13"
},
"autoload": {
"psr-4": {
"App\\": "app/"
},
"exclude-from-classmap": [
"**/Database/Migrations/**"
]

436
composer.lock generated

File diff suppressed because it is too large Load Diff

80
env
View File

@ -30,12 +30,15 @@
# DATABASE
#--------------------------------------------------------------------
# If you use MySQLi as tests, first update the values of Config\Database::$tests.
# database.default.hostname = localhost
# database.default.database = ci4
# database.default.username = root
# database.default.password = root
# database.default.DBDriver = MySQLi
# database.default.DBPrefix =
# database.tests.charset = utf8mb4
# database.tests.DBCollat = utf8mb4_general_ci
# database.default.port = 3306
# database.tests.hostname = localhost
@ -46,98 +49,21 @@
# database.tests.DBPrefix =
# database.tests.port = 3306
#--------------------------------------------------------------------
# CONTENT SECURITY POLICY
#--------------------------------------------------------------------
# contentsecuritypolicy.reportOnly = false
# contentsecuritypolicy.defaultSrc = 'none'
# contentsecuritypolicy.scriptSrc = 'self'
# contentsecuritypolicy.styleSrc = 'self'
# contentsecuritypolicy.imageSrc = 'self'
# contentsecuritypolicy.baseURI = null
# contentsecuritypolicy.childSrc = null
# contentsecuritypolicy.connectSrc = 'self'
# contentsecuritypolicy.fontSrc = null
# contentsecuritypolicy.formAction = null
# contentsecuritypolicy.frameAncestors = null
# contentsecuritypolicy.frameSrc = null
# contentsecuritypolicy.mediaSrc = null
# contentsecuritypolicy.objectSrc = null
# contentsecuritypolicy.pluginTypes = null
# contentsecuritypolicy.reportURI = null
# contentsecuritypolicy.sandbox = false
# contentsecuritypolicy.upgradeInsecureRequests = false
# contentsecuritypolicy.styleNonceTag = '{csp-style-nonce}'
# contentsecuritypolicy.scriptNonceTag = '{csp-script-nonce}'
# contentsecuritypolicy.autoNonce = true
#--------------------------------------------------------------------
# COOKIE
#--------------------------------------------------------------------
# cookie.prefix = ''
# cookie.expires = 0
# cookie.path = '/'
# cookie.domain = ''
# cookie.secure = false
# cookie.httponly = false
# cookie.samesite = 'Lax'
# cookie.raw = false
#--------------------------------------------------------------------
# ENCRYPTION
#--------------------------------------------------------------------
# encryption.key =
# encryption.driver = OpenSSL
# encryption.blockSize = 16
# encryption.digest = SHA512
#--------------------------------------------------------------------
# HONEYPOT
#--------------------------------------------------------------------
# honeypot.hidden = 'true'
# honeypot.label = 'Fill This Field'
# honeypot.name = 'honeypot'
# honeypot.template = '<label>{label}</label><input type="text" name="{name}" value=""/>'
# honeypot.container = '<div style="display:none">{template}</div>'
#--------------------------------------------------------------------
# SECURITY
#--------------------------------------------------------------------
# security.csrfProtection = 'cookie'
# security.tokenRandomize = false
# security.tokenName = 'csrf_token_name'
# security.headerName = 'X-CSRF-TOKEN'
# security.cookieName = 'csrf_cookie_name'
# security.expires = 7200
# security.regenerate = true
# security.redirect = false
# security.samesite = 'Lax'
#--------------------------------------------------------------------
# SESSION
#--------------------------------------------------------------------
# session.driver = 'CodeIgniter\Session\Handlers\FileHandler'
# session.cookieName = 'ci_session'
# session.expiration = 7200
# session.savePath = null
# session.matchIP = false
# session.timeToUpdate = 300
# session.regenerateDestroy = false
#--------------------------------------------------------------------
# LOGGER
#--------------------------------------------------------------------
# logger.threshold = 4
#--------------------------------------------------------------------
# CURLRequest
#--------------------------------------------------------------------
# curlrequest.shareOptions = false

View File

@ -30,16 +30,16 @@
"dependencies": {
"@amcharts/amcharts4": "^4.10.38",
"@amcharts/amcharts4-geodata": "^4.1.28",
"@codemirror/commands": "^6.3.3",
"@codemirror/lang-xml": "^6.0.2",
"@codemirror/commands": "^6.5.0",
"@codemirror/lang-xml": "^6.1.0",
"@codemirror/language": "^6.10.1",
"@codemirror/state": "^6.4.1",
"@codemirror/view": "^6.24.1",
"@codemirror/view": "^6.26.3",
"@floating-ui/dom": "^1.6.3",
"@github/clipboard-copy-element": "^1.3.0",
"@github/hotkey": "^3.1.0",
"@github/markdown-toolbar-element": "^2.2.1",
"@github/relative-time-element": "^4.3.1",
"@github/markdown-toolbar-element": "^2.2.3",
"@github/relative-time-element": "^4.4.0",
"@tailwindcss/nesting": "0.0.0-insiders.565cd3e",
"@vime/core": "^5.4.1",
"choices.js": "^10.2.0",
@ -47,28 +47,28 @@
"flatpickr": "^4.6.13",
"leaflet": "^1.9.4",
"leaflet.markercluster": "^1.5.3",
"lit": "^3.1.2",
"marked": "^12.0.0",
"wavesurfer.js": "^7.7.3",
"lit": "^3.1.3",
"marked": "^12.0.2",
"wavesurfer.js": "^7.7.11",
"xml-formatter": "^3.6.2"
},
"devDependencies": {
"@commitlint/cli": "^19.0.3",
"@commitlint/config-conventional": "^19.0.3",
"@csstools/css-tokenizer": "^2.2.3",
"@commitlint/cli": "^19.3.0",
"@commitlint/config-conventional": "^19.2.2",
"@csstools/css-tokenizer": "^2.2.4",
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/exec": "^6.0.3",
"@semantic-release/git": "^10.0.1",
"@semantic-release/gitlab": "^13.0.3",
"@tailwindcss/forms": "^0.5.7",
"@tailwindcss/typography": "^0.5.10",
"@types/leaflet": "^1.9.8",
"@typescript-eslint/eslint-plugin": "^7.1.0",
"@typescript-eslint/parser": "^7.1.0",
"@tailwindcss/typography": "^0.5.12",
"@types/leaflet": "^1.9.12",
"@typescript-eslint/eslint-plugin": "^7.7.1",
"@typescript-eslint/parser": "^7.7.1",
"all-contributors-cli": "^6.26.1",
"commitizen": "^4.3.0",
"cross-env": "^7.0.3",
"cssnano": "^6.0.3",
"cssnano": "^6.1.2",
"cz-conventional-changelog": "^3.3.0",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
@ -76,25 +76,25 @@
"husky": "^9.0.11",
"is-ci": "^3.0.1",
"lint-staged": "^15.2.2",
"postcss": "^8.4.35",
"postcss-import": "^16.0.1",
"postcss-nesting": "^12.0.4",
"postcss-preset-env": "^9.4.0",
"postcss": "^8.4.38",
"postcss-import": "^16.1.0",
"postcss-nesting": "^12.1.2",
"postcss-preset-env": "^9.5.9",
"postcss-reporter": "^7.1.0",
"prettier": "3.2.5",
"prettier-plugin-organize-imports": "^3.2.4",
"semantic-release": "^23.0.2",
"stylelint": "^16.2.1",
"semantic-release": "^23.0.8",
"stylelint": "^16.4.0",
"stylelint-config-standard": "^36.0.0",
"svgo": "^3.2.0",
"tailwindcss": "^3.4.1",
"typescript": "^5.3.3",
"vite": "^5.1.4",
"vite-plugin-pwa": "^0.19.2",
"workbox-build": "^7.0.0",
"workbox-core": "^7.0.0",
"workbox-routing": "^7.0.0",
"workbox-strategies": "^7.0.0"
"tailwindcss": "^3.4.3",
"typescript": "^5.4.5",
"vite": "^5.2.10",
"vite-plugin-pwa": "^0.19.8",
"workbox-build": "^7.1.0",
"workbox-core": "^7.1.0",
"workbox-routing": "^7.1.0",
"workbox-strategies": "^7.1.0"
},
"lint-staged": {
"*.{js,ts,css,md,json}": "prettier --write",

View File

@ -1,6 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="vendor/codeigniter4/framework/system/Test/bootstrap.php" backupGlobals="false" colors="true" stopOnError="false" stopOnFailure="false" stopOnIncomplete="false" stopOnSkipped="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.2/phpunit.xsd" cacheDirectory=".phpunit.cache">
<coverage includeUncoveredFiles="true">
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
bootstrap="vendor/codeigniter4/framework/system/Test/bootstrap.php"
backupGlobals="false"
beStrictAboutOutputDuringTests="true"
colors="true"
columns="max"
failOnRisky="true"
failOnWarning="true"
cacheDirectory="build/.phpunit.cache">
<coverage
includeUncoveredFiles="true"
pathCoverage="false"
ignoreDeprecatedCodeUnits="true"
disableCodeCoverageIgnore="true">
<report>
<clover outputFile="build/logs/clover.xml"/>
<html outputDirectory="build/logs/html"/>
@ -18,6 +31,15 @@
<testdoxText outputFile="build/logs/testdox.txt"/>
<junit outputFile="build/logs/logfile.xml"/>
</logging>
<source>
<include>
<directory suffix=".php">./app</directory>
</include>
<exclude>
<directory suffix=".php">./app/Views</directory>
<file>./app/Config/Routes.php</file>
</exclude>
</source>
<php>
<server name="app.baseURL" value="http://example.com/"/>
<!-- Directory containing phpunit.xml -->
@ -35,13 +57,4 @@
<env name="database.tests.DBPrefix" value="tests_"/>
<env name="restapi.enabled" value="true"/>
</php>
<source>
<include>
<directory suffix=".php">./app</directory>
</include>
<exclude>
<directory suffix=".php">./app/Views</directory>
<file>./app/Config/Routes.php</file>
</exclude>
</source>
</phpunit>

File diff suppressed because it is too large Load Diff

View File

@ -51,7 +51,7 @@ class preload
*/
private array $paths = [
[
'include' => __DIR__ . '/vendor/codeigniter4/framework/system',
'include' => __DIR__ . '/vendor/codeigniter4/framework/system', // Change this path if using manual installation
'exclude' => [
// Not needed if you don't use them.
'/system/Database/OCI8/',

View File

@ -45,5 +45,5 @@ Options -Indexes
</IfModule>
# Disable server signature start
ServerSignature Off
ServerSignature Off
# Disable server signature end

View File

@ -2,11 +2,15 @@
declare(strict_types=1);
use CodeIgniter\Config\DotEnv;
use CodeIgniter\Boot;
use Config\Paths;
use Config\Services;
// Check PHP version.
/*
*---------------------------------------------------------------
* CHECK PHP VERSION
*---------------------------------------------------------------
*/
$minPhpVersion = '8.1'; // If you update this, don't forget to update `spark`.
if (version_compare(PHP_VERSION, $minPhpVersion, '<')) {
$message = sprintf(
@ -15,9 +19,18 @@ if (version_compare(PHP_VERSION, $minPhpVersion, '<')) {
PHP_VERSION
);
exit($message);
header('HTTP/1.1 503 Service Unavailable.', true, 503);
echo $message;
exit(1);
}
/*
*---------------------------------------------------------------
* SET THE CURRENT DIRECTORY
*---------------------------------------------------------------
*/
// Path to the front controller (this file)
define('FCPATH', __DIR__ . DIRECTORY_SEPARATOR);
@ -35,59 +48,14 @@ if (getcwd() . DIRECTORY_SEPARATOR !== FCPATH) {
* and fires up an environment-specific bootstrapping.
*/
// Load our paths config file
// LOAD OUR PATHS CONFIG FILE
// This is the line that might need to be changed, depending on your folder structure.
require FCPATH . '../app/Config/Paths.php';
// ^^^ Change this line if you move your application folder
$paths = new Paths();
// Location of the framework bootstrap file.
require rtrim($paths->systemDirectory, '\\/ ') . DIRECTORY_SEPARATOR . 'bootstrap.php';
// LOAD THE FRAMEWORK BOOTSTRAP FILE
require $paths->systemDirectory . '/Boot.php';
// Load environment settings from .env files into $_SERVER and $_ENV
require_once SYSTEMPATH . 'Config/DotEnv.php';
(new DotEnv(ROOTPATH))->load();
// Define ENVIRONMENT
if (! defined('ENVIRONMENT')) {
define('ENVIRONMENT', env('CI_ENVIRONMENT', 'production'));
}
// Load Config Cache
// $factoriesCache = new \CodeIgniter\Cache\FactoriesCache();
// $factoriesCache->load('config');
// ^^^ Uncomment these lines if you want to use Config Caching.
/*
* ---------------------------------------------------------------
* GRAB OUR CODEIGNITER INSTANCE
* ---------------------------------------------------------------
*
* The CodeIgniter class contains the core functionality to make
* the application run, and does all the dirty work to get
* the pieces all working together.
*/
$app = Services::codeigniter();
$app->initialize();
$context = is_cli() ? 'php-cli' : 'web';
$app->setContext($context);
/*
*---------------------------------------------------------------
* LAUNCH THE APPLICATION
*---------------------------------------------------------------
* Now that everything is set up, it's time to actually fire
* up the engines and make this app do its thang.
*/
$app->run();
// Save Config Cache
// $factoriesCache->save('config');
// ^^^ Uncomment this line if you want to use Config Caching.
// Exits the application, setting the exit code for CLI-based applications
// that might be watching.
exit(EXIT_SUCCESS);
exit(Boot::bootWeb($paths));

62
spark
View File

@ -12,13 +12,16 @@
/*
* --------------------------------------------------------------------
* CodeIgniter command-line tools
* CODEIGNITER COMMAND-LINE TOOLS
* --------------------------------------------------------------------
* The main entry point into the CLI system and allows you to run
* commands and perform maintenance on your application.
*
* Because CodeIgniter can handle CLI requests as just another web request
* this class mainly acts as a passthru to the framework itself.
*/
/*
*---------------------------------------------------------------
* CHECK SERVER API
*---------------------------------------------------------------
*/
// Refuse to run when called from php-cgi
@ -26,7 +29,12 @@ if (strpos(PHP_SAPI, 'cgi') === 0) {
exit("The cli tool is not supported when running php-cgi. It needs php-cli to function!\n\n");
}
// Check PHP version.
/*
*---------------------------------------------------------------
* CHECK PHP VERSION
*---------------------------------------------------------------
*/
$minPhpVersion = '8.1'; // If you update this, don't forget to update `public/index.php`.
if (version_compare(PHP_VERSION, $minPhpVersion, '<')) {
$message = sprintf(
@ -42,12 +50,11 @@ if (version_compare(PHP_VERSION, $minPhpVersion, '<')) {
error_reporting(E_ALL);
ini_set('display_errors', '1');
/**
* @var bool
*
* @deprecated No longer in use. `CodeIgniter` has `$context` property.
/*
*---------------------------------------------------------------
* SET THE CURRENT DIRECTORY
*---------------------------------------------------------------
*/
define('SPARKED', true);
// Path to the front controller
define('FCPATH', __DIR__ . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR);
@ -64,41 +71,14 @@ chdir(FCPATH);
* and fires up an environment-specific bootstrapping.
*/
// Load our paths config file
// LOAD OUR PATHS CONFIG FILE
// This is the line that might need to be changed, depending on your folder structure.
require FCPATH . '../app/Config/Paths.php';
// ^^^ Change this line if you move your application folder
$paths = new Config\Paths();
// Location of the framework bootstrap file.
require rtrim($paths->systemDirectory, '\\/ ') . DIRECTORY_SEPARATOR . 'bootstrap.php';
// LOAD THE FRAMEWORK BOOTSTRAP FILE
require $paths->systemDirectory . '/Boot.php';
// Load environment settings from .env files into $_SERVER and $_ENV
require_once SYSTEMPATH . 'Config/DotEnv.php';
(new CodeIgniter\Config\DotEnv(ROOTPATH))->load();
// Define ENVIRONMENT
if (! defined('ENVIRONMENT')) {
define('ENVIRONMENT', env('CI_ENVIRONMENT', 'production'));
}
// Grab our CodeIgniter
$app = Config\Services::codeigniter();
$app->initialize();
// Grab our Console
$console = new CodeIgniter\CLI\Console();
// Show basic information before we do anything else.
if (is_int($suppress = array_search('--no-header', $_SERVER['argv'], true))) {
unset($_SERVER['argv'][$suppress]); // @codeCoverageIgnore
$suppress = true;
}
$console->showHeader($suppress);
// fire off the command in the main framework.
$exit = $console->run();
exit(is_int($exit) ? $exit : EXIT_SUCCESS);
exit(CodeIgniter\Boot::bootSpark($paths));

6
tests/.htaccess Normal file
View File

@ -0,0 +1,6 @@
<IfModule authz_core_module>
Require all denied
</IfModule>
<IfModule !authz_core_module>
Deny from all
</IfModule>

View File

@ -29,7 +29,7 @@ class ExampleModel extends Model
protected $useSoftDeletes = false;
/**
* @var string[]
* @var list<string>
*/
protected $allowedFields = ['name', 'uid', 'class', 'icon', 'summary'];
@ -39,12 +39,12 @@ class ExampleModel extends Model
protected $useTimestamps = true;
/**
* @var mixed[]
* @var array<string, array<string, array<string, string>|string>|string>|string
*/
protected $validationRules = [];
/**
* @var mixed[]
* @var array<string, array<string, string>>
*/
protected $validationMessages = [];

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Tests\Database;
use CodeIgniter\Database\Seeder;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
use Tests\Support\Database\Seeds\ExampleSeeder;
@ -14,7 +15,7 @@ class ExampleDatabaseTest extends CIUnitTestCase
use DatabaseTestTrait;
/**
* @var string
* @var class-string<Seeder>|list<class-string<Seeder>>
*/
protected $seed = ExampleSeeder::class;

9
tests/index.html Normal file
View File

@ -0,0 +1,9 @@
<!doctype html>
<html>
<head>
<title>403 Forbidden</title>
</head>
<body>
<p>Directory access is forbidden.</p>
</body>
</html>

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace modules\Api\Rest\V1;
use App\Database\Seeds\FakeSinglePodcastApiSeeder;
use CodeIgniter\Database\Seeder;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
use CodeIgniter\Test\FeatureTestTrait;
@ -31,9 +32,9 @@ class EpisodeTest extends CIUnitTestCase
protected $namespace;
/**
* @var string
* @var class-string<Seeder>|list<class-string<Seeder>>
*/
protected $seed = 'FakeSinglePodcastApiSeeder';
protected $seed = FakeSinglePodcastApiSeeder::class;
/**
* @var string

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace modules\Api\Rest\V1;
use App\Database\Seeds\FakeSinglePodcastApiSeeder;
use CodeIgniter\Database\Seeder;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
use CodeIgniter\Test\FeatureTestTrait;
@ -31,9 +32,9 @@ class PodcastTest extends CIUnitTestCase
protected $namespace;
/**
* @var string
* @var class-string<Seeder>|list<class-string<Seeder>>
*/
protected $seed = 'FakeSinglePodcastApiSeeder';
protected $seed = FakeSinglePodcastApiSeeder::class;
/**
* @var string

View File

@ -1,6 +1,6 @@
<IfModule authz_core_module>
Require all denied
Require all denied
</IfModule>
<IfModule !authz_core_module>
Deny from all
</IfModule>
Deny from all
</IfModule>

9
writable/index.html Normal file
View File

@ -0,0 +1,9 @@
<!doctype html>
<html>
<head>
<title>403 Forbidden</title>
</head>
<body>
<p>Directory access is forbidden.</p>
</body>
</html>