Initial project files: BESCMS full source
This commit is contained in:
@@ -0,0 +1 @@
|
||||
<?php
|
||||
@@ -0,0 +1,284 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Config;
|
||||
|
||||
use CodeIgniter\Autoloader\FileLocatorInterface;
|
||||
use CodeIgniter\Exceptions\ConfigException;
|
||||
use CodeIgniter\Exceptions\RuntimeException;
|
||||
use Config\Encryption;
|
||||
use Config\Modules;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
|
||||
/**
|
||||
* Class BaseConfig
|
||||
*
|
||||
* Not intended to be used on its own, this class will attempt to
|
||||
* automatically populate the child class' properties with values
|
||||
* from the environment.
|
||||
*
|
||||
* These can be set within the .env file.
|
||||
*
|
||||
* @phpstan-consistent-constructor
|
||||
* @see \CodeIgniter\Config\BaseConfigTest
|
||||
*/
|
||||
class BaseConfig
|
||||
{
|
||||
/**
|
||||
* An optional array of classes that will act as Registrars
|
||||
* for rapidly setting config class properties.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $registrars = [];
|
||||
|
||||
/**
|
||||
* Whether to override properties by Env vars and Registrars.
|
||||
*/
|
||||
public static $override = true;
|
||||
|
||||
/**
|
||||
* Has module discovery completed?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected static $didDiscovery = false;
|
||||
|
||||
/**
|
||||
* Is module discovery running or not?
|
||||
*/
|
||||
protected static $discovering = false;
|
||||
|
||||
/**
|
||||
* The processing Registrar file for error message.
|
||||
*/
|
||||
protected static $registrarFile = '';
|
||||
|
||||
/**
|
||||
* The modules configuration.
|
||||
*
|
||||
* @var Modules|null
|
||||
*/
|
||||
protected static $moduleConfig;
|
||||
|
||||
public static function __set_state(array $array)
|
||||
{
|
||||
static::$override = false;
|
||||
$obj = new static();
|
||||
static::$override = true;
|
||||
|
||||
$properties = array_keys(get_object_vars($obj));
|
||||
|
||||
foreach ($properties as $property) {
|
||||
$obj->{$property} = $array[$property];
|
||||
}
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal For testing purposes only.
|
||||
* @testTag
|
||||
*/
|
||||
public static function setModules(Modules $modules): void
|
||||
{
|
||||
static::$moduleConfig = $modules;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal For testing purposes only.
|
||||
* @testTag
|
||||
*/
|
||||
public static function reset(): void
|
||||
{
|
||||
static::$registrars = [];
|
||||
static::$override = true;
|
||||
static::$didDiscovery = false;
|
||||
static::$moduleConfig = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will attempt to get environment variables with names
|
||||
* that match the properties of the child class.
|
||||
*
|
||||
* The "shortPrefix" is the lowercase-only config class name.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
|
||||
if (! static::$override) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->registerProperties();
|
||||
|
||||
$properties = array_keys(get_object_vars($this));
|
||||
$prefix = static::class;
|
||||
$slashAt = strrpos($prefix, '\\');
|
||||
$shortPrefix = strtolower(substr($prefix, $slashAt === false ? 0 : $slashAt + 1));
|
||||
|
||||
foreach ($properties as $property) {
|
||||
$this->initEnvValue($this->{$property}, $property, $prefix, $shortPrefix);
|
||||
|
||||
if ($this instanceof Encryption && $property === 'key') {
|
||||
if (str_starts_with($this->{$property}, 'hex2bin:')) {
|
||||
// Handle hex2bin prefix
|
||||
$this->{$property} = hex2bin(substr($this->{$property}, 8));
|
||||
} elseif (str_starts_with($this->{$property}, 'base64:')) {
|
||||
// Handle base64 prefix
|
||||
$this->{$property} = base64_decode(substr($this->{$property}, 7), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization an environment-specific configuration setting
|
||||
*
|
||||
* @param array|bool|float|int|string|null $property
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function initEnvValue(&$property, string $name, string $prefix, string $shortPrefix)
|
||||
{
|
||||
if (is_array($property)) {
|
||||
foreach (array_keys($property) as $key) {
|
||||
$this->initEnvValue($property[$key], "{$name}.{$key}", $prefix, $shortPrefix);
|
||||
}
|
||||
} elseif (($value = $this->getEnvValue($name, $prefix, $shortPrefix)) !== false && $value !== null) {
|
||||
if ($value === 'false') {
|
||||
$value = false;
|
||||
} elseif ($value === 'true') {
|
||||
$value = true;
|
||||
}
|
||||
if (is_bool($value)) {
|
||||
$property = $value;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$value = trim($value, '\'"');
|
||||
|
||||
if (is_int($property)) {
|
||||
$value = (int) $value;
|
||||
} elseif (is_float($property)) {
|
||||
$value = (float) $value;
|
||||
}
|
||||
|
||||
// If the default value of the property is `null` and the type is not
|
||||
// `string`, TypeError will happen.
|
||||
// So cannot set `declare(strict_types=1)` in this file.
|
||||
$property = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an environment-specific configuration setting
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
protected function getEnvValue(string $property, string $prefix, string $shortPrefix)
|
||||
{
|
||||
$shortPrefix = ltrim($shortPrefix, '\\');
|
||||
$underscoreProperty = str_replace('.', '_', $property);
|
||||
|
||||
switch (true) {
|
||||
case array_key_exists("{$shortPrefix}.{$property}", $_ENV):
|
||||
return $_ENV["{$shortPrefix}.{$property}"];
|
||||
|
||||
case array_key_exists("{$shortPrefix}_{$underscoreProperty}", $_ENV):
|
||||
return $_ENV["{$shortPrefix}_{$underscoreProperty}"];
|
||||
|
||||
case array_key_exists("{$shortPrefix}.{$property}", $_SERVER):
|
||||
return $_SERVER["{$shortPrefix}.{$property}"];
|
||||
|
||||
case array_key_exists("{$shortPrefix}_{$underscoreProperty}", $_SERVER):
|
||||
return $_SERVER["{$shortPrefix}_{$underscoreProperty}"];
|
||||
|
||||
case array_key_exists("{$prefix}.{$property}", $_ENV):
|
||||
return $_ENV["{$prefix}.{$property}"];
|
||||
|
||||
case array_key_exists("{$prefix}_{$underscoreProperty}", $_ENV):
|
||||
return $_ENV["{$prefix}_{$underscoreProperty}"];
|
||||
|
||||
case array_key_exists("{$prefix}.{$property}", $_SERVER):
|
||||
return $_SERVER["{$prefix}.{$property}"];
|
||||
|
||||
case array_key_exists("{$prefix}_{$underscoreProperty}", $_SERVER):
|
||||
return $_SERVER["{$prefix}_{$underscoreProperty}"];
|
||||
|
||||
default:
|
||||
$value = getenv("{$shortPrefix}.{$property}");
|
||||
$value = $value === false ? getenv("{$shortPrefix}_{$underscoreProperty}") : $value;
|
||||
$value = $value === false ? getenv("{$prefix}.{$property}") : $value;
|
||||
$value = $value === false ? getenv("{$prefix}_{$underscoreProperty}") : $value;
|
||||
|
||||
return $value === false ? null : $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides external libraries a simple way to register one or more
|
||||
* options into a config file.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
protected function registerProperties()
|
||||
{
|
||||
|
||||
|
||||
if (! static::$didDiscovery) {
|
||||
// Discovery must be completed before the first instantiation of any Config class.
|
||||
if (static::$discovering) {
|
||||
throw new ConfigException(
|
||||
'During Auto-Discovery of Registrars,'
|
||||
. ' "' . static::class . '" executes Auto-Discovery again.'
|
||||
. ' "' . clean_path(static::$registrarFile) . '" seems to have bad code.'
|
||||
);
|
||||
}
|
||||
|
||||
static::$discovering = true;
|
||||
|
||||
|
||||
|
||||
static::$didDiscovery = true;
|
||||
static::$discovering = false;
|
||||
}
|
||||
|
||||
$shortName = (new ReflectionClass($this))->getShortName();
|
||||
|
||||
// Check the registrar class for a method named after this class' shortName
|
||||
foreach (static::$registrars as $callable) {
|
||||
// ignore non-applicable registrars
|
||||
if (! method_exists($callable, $shortName)) {
|
||||
continue; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$properties = $callable::$shortName();
|
||||
|
||||
if (! is_array($properties)) {
|
||||
throw new RuntimeException('Registrars must return an array of properties and their values.');
|
||||
}
|
||||
|
||||
foreach ($properties as $property => $value) {
|
||||
if (isset($this->{$property}) && is_array($this->{$property}) && is_array($value)) {
|
||||
$this->{$property} = array_merge($this->{$property}, $value);
|
||||
} else {
|
||||
$this->{$property} = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,405 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Config;
|
||||
|
||||
use CodeIgniter\Autoloader\Autoloader;
|
||||
use CodeIgniter\Autoloader\FileLocator;
|
||||
use CodeIgniter\Autoloader\FileLocatorCached;
|
||||
use CodeIgniter\Autoloader\FileLocatorInterface;
|
||||
use CodeIgniter\Cache\CacheInterface;
|
||||
use CodeIgniter\Cache\ResponseCache;
|
||||
use CodeIgniter\CLI\Commands;
|
||||
use CodeIgniter\CodeIgniter;
|
||||
use CodeIgniter\Database\ConnectionInterface;
|
||||
use CodeIgniter\Database\MigrationRunner;
|
||||
use CodeIgniter\Debug\Exceptions;
|
||||
use CodeIgniter\Debug\Iterator;
|
||||
use CodeIgniter\Debug\Timer;
|
||||
use CodeIgniter\Debug\Toolbar;
|
||||
use CodeIgniter\Email\Email;
|
||||
use CodeIgniter\Encryption\EncrypterInterface;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
use CodeIgniter\Filters\Filters;
|
||||
use CodeIgniter\Format\Format;
|
||||
use CodeIgniter\Honeypot\Honeypot;
|
||||
use CodeIgniter\HTTP\CLIRequest;
|
||||
use CodeIgniter\HTTP\ContentSecurityPolicy;
|
||||
use CodeIgniter\HTTP\CURLRequest;
|
||||
use CodeIgniter\HTTP\IncomingRequest;
|
||||
use CodeIgniter\HTTP\Negotiate;
|
||||
use CodeIgniter\HTTP\RedirectResponse;
|
||||
use CodeIgniter\HTTP\Request;
|
||||
use CodeIgniter\HTTP\RequestInterface;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use CodeIgniter\HTTP\SiteURIFactory;
|
||||
use CodeIgniter\HTTP\URI;
|
||||
use CodeIgniter\Images\Handlers\BaseHandler;
|
||||
use CodeIgniter\Language\Language;
|
||||
use CodeIgniter\Log\Logger;
|
||||
use CodeIgniter\Pager\Pager;
|
||||
use CodeIgniter\Router\RouteCollection;
|
||||
use CodeIgniter\Router\RouteCollectionInterface;
|
||||
use CodeIgniter\Router\Router;
|
||||
use CodeIgniter\Security\Security;
|
||||
use CodeIgniter\Session\Session;
|
||||
use CodeIgniter\Superglobals;
|
||||
use CodeIgniter\Throttle\Throttler;
|
||||
use CodeIgniter\Typography\Typography;
|
||||
use CodeIgniter\Validation\ValidationInterface;
|
||||
use CodeIgniter\View\Cell;
|
||||
use CodeIgniter\View\Parser;
|
||||
use CodeIgniter\View\RendererInterface;
|
||||
use CodeIgniter\View\View;
|
||||
use Config\App;
|
||||
use Config\Autoload;
|
||||
use Config\Cache;
|
||||
use Config\ContentSecurityPolicy as CSPConfig;
|
||||
use Config\Encryption;
|
||||
use Config\Exceptions as ConfigExceptions;
|
||||
use Config\Filters as ConfigFilters;
|
||||
use Config\Format as ConfigFormat;
|
||||
use Config\Honeypot as ConfigHoneyPot;
|
||||
use Config\Images;
|
||||
use Config\Migrations;
|
||||
use Config\Modules;
|
||||
use Config\Optimize;
|
||||
use Config\Pager as ConfigPager;
|
||||
use CodeIgniter\Config\Services as AppServices;
|
||||
use Config\Session as ConfigSession;
|
||||
use Config\Toolbar as ConfigToolbar;
|
||||
use Config\Validation as ConfigValidation;
|
||||
use Config\View as ConfigView;
|
||||
|
||||
/**
|
||||
* Services Configuration file.
|
||||
*
|
||||
* Services are simply other classes/libraries that the system uses
|
||||
* to do its job. This is used by CodeIgniter to allow the core of the
|
||||
* framework to be swapped out easily without affecting the usage within
|
||||
* the rest of your application.
|
||||
*
|
||||
* This is used in place of a Dependency Injection container primarily
|
||||
* due to its simplicity, which allows a better long-term maintenance
|
||||
* of the applications built on top of CodeIgniter. A bonus side-effect
|
||||
* is that IDEs are able to determine what class you are calling
|
||||
* whereas with DI Containers there usually isn't a way for them to do this.
|
||||
*
|
||||
* Warning: To allow overrides by service providers do not use static calls,
|
||||
* instead call out to \Config\Services (imported as AppServices).
|
||||
*
|
||||
* @see http://blog.ircmaxell.com/2015/11/simple-easy-risk-and-change.html
|
||||
* @see http://www.infoq.com/presentations/Simple-Made-Easy
|
||||
*
|
||||
* @method static CacheInterface cache(Cache $config = null, $getShared = true)
|
||||
* @method static CLIRequest clirequest(App $config = null, $getShared = true)
|
||||
* @method static CodeIgniter codeigniter(App $config = null, $getShared = true)
|
||||
* @method static Commands commands($getShared = true)
|
||||
* @method static void createRequest(App $config, bool $isCli = false)
|
||||
* @method static ContentSecurityPolicy csp(CSPConfig $config = null, $getShared = true)
|
||||
* @method static CURLRequest curlrequest($options = [], ResponseInterface $response = null, App $config = null, $getShared = true)
|
||||
* @method static Email email($config = null, $getShared = true)
|
||||
* @method static EncrypterInterface encrypter(Encryption $config = null, $getShared = false)
|
||||
* @method static Exceptions exceptions(ConfigExceptions $config = null, $getShared = true)
|
||||
* @method static Filters filters(ConfigFilters $config = null, $getShared = true)
|
||||
* @method static Format format(ConfigFormat $config = null, $getShared = true)
|
||||
* @method static Honeypot honeypot(ConfigHoneyPot $config = null, $getShared = true)
|
||||
* @method static BaseHandler image($handler = null, Images $config = null, $getShared = true)
|
||||
* @method static IncomingRequest incomingrequest(?App $config = null, bool $getShared = true)
|
||||
* @method static Iterator iterator($getShared = true)
|
||||
* @method static Language language($locale = null, $getShared = true)
|
||||
* @method static Logger logger($getShared = true)
|
||||
* @method static MigrationRunner migrations(Migrations $config = null, ConnectionInterface $db = null, $getShared = true)
|
||||
* @method static Negotiate negotiator(RequestInterface $request = null, $getShared = true)
|
||||
* @method static Pager pager(ConfigPager $config = null, RendererInterface $view = null, $getShared = true)
|
||||
* @method static Parser parser($viewPath = null, ConfigView $config = null, $getShared = true)
|
||||
* @method static RedirectResponse redirectresponse(App $config = null, $getShared = true)
|
||||
* @method static View renderer($viewPath = null, ConfigView $config = null, $getShared = true)
|
||||
* @method static IncomingRequest|CLIRequest request(App $config = null, $getShared = true)
|
||||
* @method static ResponseInterface response(App $config = null, $getShared = true)
|
||||
* @method static ResponseCache responsecache(?Cache $config = null, ?CacheInterface $cache = null, bool $getShared = true)
|
||||
* @method static Router router(RouteCollectionInterface $routes = null, Request $request = null, $getShared = true)
|
||||
* @method static RouteCollection routes($getShared = true)
|
||||
* @method static Security security(App $config = null, $getShared = true)
|
||||
* @method static Session session(ConfigSession $config = null, $getShared = true)
|
||||
* @method static SiteURIFactory siteurifactory(App $config = null, Superglobals $superglobals = null, $getShared = true)
|
||||
* @method static Superglobals superglobals(array $server = null, array $get = null, bool $getShared = true)
|
||||
* @method static Throttler throttler($getShared = true)
|
||||
* @method static Timer timer($getShared = true)
|
||||
* @method static Toolbar toolbar(ConfigToolbar $config = null, $getShared = true)
|
||||
* @method static Typography typography($getShared = true)
|
||||
* @method static URI uri($uri = null, $getShared = true)
|
||||
* @method static ValidationInterface validation(ConfigValidation $config = null, $getShared = true)
|
||||
* @method static Cell viewcell($getShared = true)
|
||||
*/
|
||||
class BaseService
|
||||
{
|
||||
/**
|
||||
* Cache for instance of any services that
|
||||
* have been requested as a "shared" instance.
|
||||
* Keys should be lowercase service names.
|
||||
*
|
||||
* @var array<string, object> [key => instance]
|
||||
*/
|
||||
protected static $instances = [];
|
||||
|
||||
/**
|
||||
* Factory method list.
|
||||
*
|
||||
* @var array<string, (callable(mixed ...$params): object)> [key => callable]
|
||||
*/
|
||||
protected static array $factories = [];
|
||||
|
||||
/**
|
||||
* Mock objects for testing which are returned if exist.
|
||||
*
|
||||
* @var array<string, object> [key => instance]
|
||||
*/
|
||||
protected static $mocks = [];
|
||||
|
||||
/**
|
||||
* Have we already discovered other Services?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected static $discovered = false;
|
||||
|
||||
/**
|
||||
* A cache of other service classes we've found.
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @deprecated 4.5.0 No longer used.
|
||||
*/
|
||||
protected static $services = [];
|
||||
|
||||
/**
|
||||
* A cache of the names of services classes found.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
private static array $serviceNames = [];
|
||||
|
||||
/**
|
||||
* Simple method to get an entry fast.
|
||||
*
|
||||
* @param string $key Identifier of the entry to look for.
|
||||
*
|
||||
* @return object|null Entry.
|
||||
*/
|
||||
public static function get(string $key): ?object
|
||||
{
|
||||
return static::$instances[$key] ?? static::__callStatic($key, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an entry.
|
||||
*
|
||||
* @param string $key Identifier of the entry.
|
||||
*/
|
||||
public static function set(string $key, object $value): void
|
||||
{
|
||||
if (isset(static::$instances[$key])) {
|
||||
throw new InvalidArgumentException('The entry for "' . $key . '" is already set.');
|
||||
}
|
||||
|
||||
static::$instances[$key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides an existing entry.
|
||||
*
|
||||
* @param string $key Identifier of the entry.
|
||||
*/
|
||||
public static function override(string $key, object $value): void
|
||||
{
|
||||
static::$instances[$key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a shared instance of any of the class' services.
|
||||
*
|
||||
* $key must be a name matching a service.
|
||||
*
|
||||
* @param array|bool|float|int|object|string|null ...$params
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
protected static function getSharedInstance(string $key, ...$params)
|
||||
{
|
||||
$key = strtolower($key);
|
||||
|
||||
// Returns mock if exists
|
||||
if (isset(static::$mocks[$key])) {
|
||||
return static::$mocks[$key];
|
||||
}
|
||||
|
||||
if (! isset(static::$instances[$key])) {
|
||||
// Make sure $getShared is false
|
||||
$params[] = false;
|
||||
|
||||
static::$instances[$key] = AppServices::$key(...$params);
|
||||
}
|
||||
|
||||
return static::$instances[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* The Autoloader class is the central class that handles our
|
||||
* spl_autoload_register method, and helper methods.
|
||||
*
|
||||
* @return Autoloader
|
||||
*/
|
||||
public static function autoloader(bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
if (empty(static::$instances['autoloader'])) {
|
||||
static::$instances['autoloader'] = new Autoloader();
|
||||
}
|
||||
|
||||
return static::$instances['autoloader'];
|
||||
}
|
||||
|
||||
return new Autoloader();
|
||||
}
|
||||
|
||||
/**
|
||||
* The file locator provides utility methods for looking for non-classes
|
||||
* within namespaced folders, as well as convenience methods for
|
||||
* loading 'helpers', and 'libraries'.
|
||||
*
|
||||
* @return FileLocatorInterface
|
||||
*/
|
||||
public static function locator(bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
if (empty(static::$instances['locator'])) {
|
||||
$cacheEnabled = class_exists(Optimize::class)
|
||||
&& (new Optimize())->locatorCacheEnabled;
|
||||
|
||||
if ($cacheEnabled) {
|
||||
static::$instances['locator'] = new FileLocatorCached(new FileLocator(static::autoloader()));
|
||||
} else {
|
||||
static::$instances['locator'] = new FileLocator(static::autoloader());
|
||||
}
|
||||
}
|
||||
|
||||
return static::$mocks['locator'] ?? static::$instances['locator'];
|
||||
}
|
||||
|
||||
return new FileLocator(static::autoloader());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the ability to perform case-insensitive calling of service
|
||||
* names.
|
||||
*
|
||||
* @return object|null
|
||||
*/
|
||||
public static function __callStatic(string $name, array $arguments)
|
||||
{
|
||||
if (isset(static::$factories[$name])) {
|
||||
return static::$factories[$name](...$arguments);
|
||||
}
|
||||
|
||||
$service = static::serviceExists($name);
|
||||
|
||||
if ($service === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $service::$name(...$arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the requested service is defined and return the declaring
|
||||
* class. Return null if not found.
|
||||
*/
|
||||
public static function serviceExists(string $name): ?string
|
||||
{
|
||||
static::buildServicesCache();
|
||||
|
||||
$services = array_merge(self::$serviceNames, [Services::class]);
|
||||
$name = strtolower($name);
|
||||
|
||||
foreach ($services as $service) {
|
||||
if (method_exists($service, $name)) {
|
||||
static::$factories[$name] = [$service, $name];
|
||||
|
||||
return $service;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset shared instances and mocks for testing.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @testTag only available to test code
|
||||
*/
|
||||
public static function reset(bool $initAutoloader = true)
|
||||
{
|
||||
static::$mocks = [];
|
||||
static::$instances = [];
|
||||
static::$factories = [];
|
||||
|
||||
if ($initAutoloader) {
|
||||
static::autoloader()->initialize(new Autoload(), new Modules());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets any mock and shared instances for a single service.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @testTag only available to test code
|
||||
*/
|
||||
public static function resetSingle(string $name)
|
||||
{
|
||||
$name = strtolower($name);
|
||||
unset(static::$mocks[$name], static::$instances[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject mock object for testing.
|
||||
*
|
||||
* @param object $mock
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @testTag only available to test code
|
||||
*/
|
||||
public static function injectMock(string $name, $mock)
|
||||
{
|
||||
static::$instances[$name] = $mock;
|
||||
static::$mocks[strtolower($name)] = $mock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the service cache.
|
||||
*/
|
||||
public static function resetServicesCache(): void
|
||||
{
|
||||
self::$serviceNames = [];
|
||||
static::$discovered = false;
|
||||
}
|
||||
|
||||
protected static function buildServicesCache(): void
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
<?php namespace Config;
|
||||
/**
|
||||
* {{www.xunruicms.com}}
|
||||
* {{迅睿内容管理框架系统}}
|
||||
* 本文件是框架系统文件,二次开发时不可以修改本文件
|
||||
**/
|
||||
|
||||
use CodeIgniter\Cache\CacheInterface;
|
||||
use CodeIgniter\Cache\Handlers\DummyHandler;
|
||||
use CodeIgniter\Cache\Handlers\FileHandler;
|
||||
use CodeIgniter\Cache\Handlers\MemcachedHandler;
|
||||
use CodeIgniter\Cache\Handlers\PredisHandler;
|
||||
use CodeIgniter\Cache\Handlers\RedisHandler;
|
||||
use CodeIgniter\Cache\Handlers\WincacheHandler;
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
|
||||
class Cache extends BaseConfig
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Primary Handler
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The name of the preferred handler that should be used. If for some reason
|
||||
| it is not available, the $backupHandler will be used in its place.
|
||||
|
|
||||
*/
|
||||
public $handler = SYS_CACHE_TYPE == 1 ? 'memcached' : (SYS_CACHE_TYPE == 2 ? 'redis' : 'file');
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Backup Handler
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The name of the handler that will be used in case the first one is
|
||||
| unreachable. Often, 'file' is used here since the filesystem is
|
||||
| always available, though that's not always practical for the app.
|
||||
|
|
||||
*/
|
||||
public $backupHandler = 'file';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Directory Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The path to where cache files should be stored, if using a file-based
|
||||
| system.
|
||||
|
|
||||
*/
|
||||
public $storePath = WRITEPATH.'file/';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| 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.
|
||||
| array('q') = Enabled, but only take into account the specified list
|
||||
| of query parameters.
|
||||
|
|
||||
*/
|
||||
public $cacheQueryString = false;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Key Prefix
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This string is added to all cache item names to help avoid collisions
|
||||
| if you run multiple applications with the same cache engine.
|
||||
|
|
||||
*/
|
||||
public string $prefix = '';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Default TTL
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The default number of seconds to save items when none is specified.
|
||||
*
|
||||
* WARNING: This is not used by framework handlers where 60 seconds is
|
||||
* hard-coded, but may be useful to projects and modules. This will replace
|
||||
* the hard-coded value in a future release.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public int $ttl = 600;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Reserved Characters
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* A string of reserved characters that will not be allowed in keys or tags.
|
||||
* Strings that violate this restriction will cause handlers to throw.
|
||||
* Default: {}()/\@:
|
||||
* Note: The default set is required for PSR-6 compliance.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public string $reservedCharacters = '{}()/\@:';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* File settings
|
||||
* --------------------------------------------------------------------------
|
||||
* Your file storage preferences can be specified below, if you are using
|
||||
* the File driver.
|
||||
*
|
||||
* @var array<string, int|string|null>
|
||||
*/
|
||||
public array $file = [
|
||||
'storePath' => WRITEPATH . 'file/',
|
||||
'mode' => 0640,
|
||||
];
|
||||
|
||||
/*
|
||||
| -------------------------------------------------------------------------
|
||||
| Memcached settings
|
||||
| -------------------------------------------------------------------------
|
||||
| Your Memcached servers can be specified below, if you are using
|
||||
| the Memcached drivers.
|
||||
|
|
||||
| See: https://codeigniter.com/user_guide/libraries/caching.html#memcached
|
||||
|
|
||||
*/
|
||||
public array $memcached = [
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 11211,
|
||||
'weight' => 1,
|
||||
'raw' => false,
|
||||
];
|
||||
|
||||
/*
|
||||
| -------------------------------------------------------------------------
|
||||
| Redis settings
|
||||
| -------------------------------------------------------------------------
|
||||
| Your Redis server can be specified below, if you are using
|
||||
| the Redis or Predis drivers.
|
||||
|
|
||||
*/
|
||||
public array $redis = [
|
||||
'host' => '127.0.0.1',
|
||||
'password' => null,
|
||||
'port' => 6379,
|
||||
'timeout' => 0,
|
||||
'database' => 0,
|
||||
];
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Available Cache Handlers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This is an array of cache engine alias' and class names. Only engines
|
||||
| that are listed here are allowed to be used.
|
||||
|
|
||||
*/
|
||||
public array $validHandlers = [
|
||||
'dummy' => DummyHandler::class,
|
||||
'file' => FileHandler::class,
|
||||
'memcached' => MemcachedHandler::class,
|
||||
'predis' => PredisHandler::class,
|
||||
'redis' => RedisHandler::class,
|
||||
'wincache' => WincacheHandler::class,
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
if (is_file(CONFIGPATH.'redis.php')) {
|
||||
$this->redis = require CONFIGPATH.'redis.php';
|
||||
} elseif (is_file(ROOTPATH.'config/redis.php')) {
|
||||
$this->redis = require ROOTPATH.'config/redis.php';
|
||||
}
|
||||
if (is_file(CONFIGPATH.'memcached.php')) {
|
||||
$this->memcached = require CONFIGPATH.'memcached.php';
|
||||
} elseif (is_file(ROOTPATH.'config/memcached.php')) {
|
||||
$this->memcached = require ROOTPATH.'config/memcached.php';
|
||||
}
|
||||
$this->prefix = substr(SYS_KEY, 0, 10).'-';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
<?php namespace Config;
|
||||
/**
|
||||
* {{www.xunruicms.com}}
|
||||
* {{迅睿内容管理框架系统}}
|
||||
* 本文件是框架系统文件,二次开发时不可以修改本文件
|
||||
**/
|
||||
|
||||
use CodeIgniter\Database\Config;
|
||||
|
||||
/**
|
||||
* Database Configuration
|
||||
*/
|
||||
class Database extends Config
|
||||
{
|
||||
/**
|
||||
* The directory that holds the Migrations
|
||||
* and Seeds directories.
|
||||
* @var string
|
||||
*/
|
||||
public $filesPath = WRITEPATH.'database/';
|
||||
|
||||
/**
|
||||
* Lets you choose which connection group to
|
||||
* use if no other is specified.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $defaultGroup = 'default';
|
||||
|
||||
/**
|
||||
* The default database connection.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $default = [
|
||||
'DSN' => '',
|
||||
'hostname' => 'localhost',
|
||||
'username' => '',
|
||||
'password' => '',
|
||||
'database' => '',
|
||||
'DBDriver' => 'MySQLi',
|
||||
'DBPrefix' => '',
|
||||
'pConnect' => false,
|
||||
'DBDebug' => true,
|
||||
'cacheOn' => true,
|
||||
'cacheDir' => WRITEPATH.'database/',
|
||||
'charset' => 'utf8mb4',
|
||||
'DBCollat' => 'utf8mb4_general_ci',
|
||||
'swapPre' => '',
|
||||
'encrypt' => false,
|
||||
'compress' => false,
|
||||
'strictOn' => false,
|
||||
'foreignKeys' => true,
|
||||
'numberNative' => false,
|
||||
'failover' => []
|
||||
];
|
||||
public $db1 = [];
|
||||
public $db2 = [];
|
||||
public $db3 = [];
|
||||
public $db4 = [];
|
||||
public $db5 = [];
|
||||
public $db6 = [];
|
||||
public $db7 = [];
|
||||
public $db8 = [];
|
||||
public $db9 = [];
|
||||
|
||||
private $mykey = 1;
|
||||
private $mydb = [];
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
if (!is_file(CONFIGPATH.'database.php')) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$db = [];
|
||||
require CONFIGPATH.'database.php';
|
||||
|
||||
if (isset($db['failover']) && $db['failover']) {
|
||||
// 备用库
|
||||
$this->default['failover'] = $db['failover'];
|
||||
unset($db['failover']);
|
||||
}
|
||||
|
||||
foreach ($this->default as $p => $t) {
|
||||
foreach ($db as $name => $v) {
|
||||
if (isset($this->$name)) {
|
||||
// 默认库
|
||||
$this->$name[$p] = isset($v[$p]) ? $v[$p] : $t;
|
||||
} else {
|
||||
// 自定义库
|
||||
$key = $this->_get_key($name);
|
||||
if ($key) {
|
||||
$this->$key[$p] = isset($v[$p]) ? $v[$p] : $t;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 判断数据库名称的规范性(SQLite3 为文件路径,允许 .db 等扩展名)
|
||||
$driver = isset($this->default['DBDriver']) ? (string) $this->default['DBDriver'] : 'MySQLi';
|
||||
if (strcasecmp($driver, 'SQLite3') !== 0) {
|
||||
if (is_numeric($this->default['database'])) {
|
||||
exit('数据库名称不能是数字');
|
||||
} elseif (strpos((string) $this->default['database'], '.') !== false) {
|
||||
exit('数据库名称不能存在.号');
|
||||
}
|
||||
} else {
|
||||
// SQLite 默认等待写锁,降低 database is locked 概率
|
||||
if (!isset($this->default['busyTimeout'])) {
|
||||
$this->default['busyTimeout'] = 10000;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function _get_key($name) {
|
||||
if (isset($this->mydb[$name])) {
|
||||
return $this->mydb[$name];
|
||||
} else {
|
||||
$this->mydb[$name] = 'db'.$this->mykey;
|
||||
$this->mykey++;
|
||||
}
|
||||
return $this->mydb[$name];
|
||||
}
|
||||
|
||||
public function get_group($name) {
|
||||
if (isset($this->mydb[$name])) {
|
||||
return $this->mydb[$name];
|
||||
}
|
||||
return 'default';
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<?php
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php namespace Config;
|
||||
/**
|
||||
* {{www.xunruicms.com}}
|
||||
* {{迅睿内容管理框架系统}}
|
||||
* 本文件是框架系统文件,二次开发时不可以修改本文件
|
||||
**/
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
use CodeIgniter\Debug\ExceptionHandler;
|
||||
use CodeIgniter\Debug\ExceptionHandlerInterface;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Setup how the exception handler works.
|
||||
*/
|
||||
class Exceptions extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* LOG EXCEPTIONS?
|
||||
* --------------------------------------------------------------------------
|
||||
* If true, then exceptions will be logged
|
||||
* through Services::Log.
|
||||
*
|
||||
* Default: true
|
||||
*/
|
||||
public bool $log = true;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* DO NOT LOG STATUS CODES
|
||||
* --------------------------------------------------------------------------
|
||||
* Any status codes here will NOT be logged if logging is turned on.
|
||||
* By default, only 404 (Page Not Found) exceptions are ignored.
|
||||
*/
|
||||
public array $ignoreCodes = [404];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Error Views Path
|
||||
* --------------------------------------------------------------------------
|
||||
* This is the path to the directory that contains the 'cli' and 'html'
|
||||
* directories that hold the views used to generate errors.
|
||||
*
|
||||
* Default: APPPATH.'Views/errors'
|
||||
*/
|
||||
public $errorViewPath = FRAMEPATH . 'Exceptions/Views';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* HIDE FROM DEBUG TRACE
|
||||
* --------------------------------------------------------------------------
|
||||
* Any data that you would like to hide from the debug trace.
|
||||
* In order to specify 2 levels, use "/" to separate.
|
||||
* ex. ['server', 'setup/password', 'secret_token']
|
||||
*/
|
||||
public array $sensitiveDataInTrace = [];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* LOG DEPRECATIONS INSTEAD OF THROWING?
|
||||
* --------------------------------------------------------------------------
|
||||
* By default, CodeIgniter converts deprecations into exceptions. Also,
|
||||
* starting in PHP 8.1 will cause a lot of deprecated usage warnings.
|
||||
* Use this option to temporarily cease the warnings and instead log those.
|
||||
* This option also works for user deprecations.
|
||||
*/
|
||||
public bool $logDeprecations = true;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* LOG LEVEL THRESHOLD FOR DEPRECATIONS
|
||||
* --------------------------------------------------------------------------
|
||||
* If `$logDeprecations` is set to `true`, this sets the log level
|
||||
* to which the deprecation will be logged. This should be one of the log
|
||||
* levels recognized by PSR-3.
|
||||
*
|
||||
* The related `Config\Logger::$threshold` should be adjusted, if needed,
|
||||
* to capture logging the deprecations.
|
||||
*/
|
||||
public string $deprecationLogLevel = 'warning';
|
||||
|
||||
/*
|
||||
* DEFINE THE HANDLERS USED
|
||||
* --------------------------------------------------------------------------
|
||||
* Given the HTTP status code, returns exception handler that
|
||||
* should be used to deal with this error. By default, it will run CodeIgniter's
|
||||
* default handler and display the error information in the expected format
|
||||
* for CLI, HTTP, or AJAX requests, as determined by is_cli() and the expected
|
||||
* response format.
|
||||
*
|
||||
* Custom handlers can be returned if you want to handle one or more specific
|
||||
* error codes yourself like:
|
||||
*
|
||||
* if (in_array($statusCode, [400, 404, 500])) {
|
||||
* return new \App\Libraries\MyExceptionHandler();
|
||||
* }
|
||||
* if ($exception instanceOf PageNotFoundException) {
|
||||
* return new \App\Libraries\MyExceptionHandler();
|
||||
* }
|
||||
*/
|
||||
public function handler(int $statusCode, Throwable $exception): ExceptionHandlerInterface
|
||||
{
|
||||
return new ExceptionHandler($this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,539 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Config;
|
||||
|
||||
use CodeIgniter\Autoloader\FileLocatorInterface;
|
||||
use CodeIgniter\Database\ConnectionInterface;
|
||||
use CodeIgniter\Exceptions\InvalidArgumentException;
|
||||
use CodeIgniter\Model;
|
||||
|
||||
/**
|
||||
* Factories for creating instances.
|
||||
*
|
||||
* Factories allow dynamic loading of components by their path
|
||||
* and name. The "shared instance" implementation provides a
|
||||
* large performance boost and helps keep code clean of lengthy
|
||||
* instantiation checks.
|
||||
*
|
||||
* @method static BaseConfig|null config(...$arguments)
|
||||
* @method static Model|null models(string $alias, array $options = [], ?ConnectionInterface &$conn = null)
|
||||
* @see \CodeIgniter\Config\FactoriesTest
|
||||
*/
|
||||
final class Factories
|
||||
{
|
||||
/**
|
||||
* Store of component-specific options, usually
|
||||
* from CodeIgniter\Config\Factory.
|
||||
*
|
||||
* @var array<string, array<string, bool|string|null>>
|
||||
*/
|
||||
private static $options = [];
|
||||
|
||||
/**
|
||||
* Explicit options for the Config
|
||||
* component to prevent logic loops.
|
||||
*
|
||||
* @var array<string, bool|string|null>
|
||||
*/
|
||||
private static $configOptions = [
|
||||
'component' => 'config',
|
||||
'path' => 'Config',
|
||||
'instanceOf' => null,
|
||||
'getShared' => true,
|
||||
'preferApp' => true,
|
||||
];
|
||||
|
||||
/**
|
||||
* Mapping of class aliases to their true Fully Qualified Class Name (FQCN).
|
||||
*
|
||||
* Class aliases can be:
|
||||
* - FQCN. E.g., 'App\Lib\SomeLib'
|
||||
* - short classname. E.g., 'SomeLib'
|
||||
* - short classname with sub-directories. E.g., 'Sub/SomeLib'
|
||||
*
|
||||
* [component => [alias => FQCN]]
|
||||
*
|
||||
* @var array<string, array<string, class-string>>
|
||||
*/
|
||||
private static $aliases = [];
|
||||
|
||||
/**
|
||||
* Store for instances of any component that
|
||||
* has been requested as "shared".
|
||||
*
|
||||
* A multi-dimensional array with components as
|
||||
* keys to the array of name-indexed instances.
|
||||
*
|
||||
* [component => [FQCN => instance]]
|
||||
*
|
||||
* @var array<string, array<class-string, object>>
|
||||
*/
|
||||
private static $instances = [];
|
||||
|
||||
/**
|
||||
* Whether the component instances are updated?
|
||||
*
|
||||
* @var array<string, true> [component => true]
|
||||
*
|
||||
* @internal For caching only
|
||||
*/
|
||||
private static $updated = [];
|
||||
|
||||
/**
|
||||
* Define the class to load. You can *override* the concrete class.
|
||||
*
|
||||
* @param string $component Lowercase, plural component name
|
||||
* @param string $alias Class alias. See the $aliases property.
|
||||
* @param class-string $classname FQCN to be loaded
|
||||
*/
|
||||
public static function define(string $component, string $alias, string $classname): void
|
||||
{
|
||||
$component = strtolower($component);
|
||||
|
||||
if (isset(self::$aliases[$component][$alias])) {
|
||||
if (self::$aliases[$component][$alias] === $classname) {
|
||||
return;
|
||||
}
|
||||
|
||||
$message = 'Already defined in Factories: ' . $component . ' ' . $alias . ' -> ' . self::$aliases[$component][$alias];
|
||||
throw new InvalidArgumentException($message);
|
||||
}
|
||||
|
||||
if (! class_exists($classname)) {
|
||||
throw new InvalidArgumentException('No such class: ' . $classname);
|
||||
}
|
||||
|
||||
// Force a configuration to exist for this component.
|
||||
// Otherwise, getOptions() will reset the component.
|
||||
self::getOptions($component);
|
||||
|
||||
self::$aliases[$component][$alias] = $classname;
|
||||
self::$updated[$component] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads instances based on the method component name. Either
|
||||
* creates a new instance or returns an existing shared instance.
|
||||
*
|
||||
* @return object|null
|
||||
*/
|
||||
public static function __callStatic(string $component, array $arguments)
|
||||
{
|
||||
$component = strtolower($component);
|
||||
|
||||
// First argument is the class alias, second is options
|
||||
$alias = trim(array_shift($arguments), '\\ ');
|
||||
$options = array_shift($arguments) ?? [];
|
||||
|
||||
// Determine the component-specific options
|
||||
$options = array_merge(self::getOptions($component), $options);
|
||||
|
||||
if (! $options['getShared']) {
|
||||
if (isset(self::$aliases[$options['component']][$alias])) {
|
||||
$class = self::$aliases[$options['component']][$alias];
|
||||
|
||||
return new $class(...$arguments);
|
||||
}
|
||||
|
||||
// Try to locate the class
|
||||
$class = self::locateClass($options, $alias);
|
||||
if ($class !== null) {
|
||||
return new $class(...$arguments);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check for an existing definition
|
||||
$instance = self::getDefinedInstance($options, $alias, $arguments);
|
||||
if ($instance !== null) {
|
||||
return $instance;
|
||||
}
|
||||
|
||||
// Try to locate the class
|
||||
if (($class = self::locateClass($options, $alias)) === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
self::createInstance($options['component'], $class, $arguments);
|
||||
self::setAlias($options['component'], $alias, $class);
|
||||
|
||||
return self::$instances[$options['component']][$class];
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple method to get the shared instance fast.
|
||||
*/
|
||||
public static function get(string $component, string $alias): ?object
|
||||
{
|
||||
if (isset(self::$aliases[$component][$alias])) {
|
||||
$class = self::$aliases[$component][$alias];
|
||||
|
||||
if (isset(self::$instances[$component][$class])) {
|
||||
return self::$instances[$component][$class];
|
||||
}
|
||||
}
|
||||
|
||||
return self::__callStatic($component, [$alias]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the defined instance. If not exists, creates new one.
|
||||
*
|
||||
* @return object|null
|
||||
*/
|
||||
private static function getDefinedInstance(array $options, string $alias, array $arguments)
|
||||
{
|
||||
// The alias is already defined.
|
||||
if (isset(self::$aliases[$options['component']][$alias])) {
|
||||
$class = self::$aliases[$options['component']][$alias];
|
||||
|
||||
// Need to verify if the shared instance matches the request
|
||||
if (self::verifyInstanceOf($options, $class)) {
|
||||
// Check for an existing instance
|
||||
if (isset(self::$instances[$options['component']][$class])) {
|
||||
return self::$instances[$options['component']][$class];
|
||||
}
|
||||
|
||||
self::createInstance($options['component'], $class, $arguments);
|
||||
|
||||
return self::$instances[$options['component']][$class];
|
||||
}
|
||||
}
|
||||
|
||||
// Try to locate the class
|
||||
if (($class = self::locateClass($options, $alias)) === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check for an existing instance for the class
|
||||
if (isset(self::$instances[$options['component']][$class])) {
|
||||
self::setAlias($options['component'], $alias, $class);
|
||||
|
||||
return self::$instances[$options['component']][$class];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the shared instance.
|
||||
*/
|
||||
private static function createInstance(string $component, string $class, array $arguments): void
|
||||
{
|
||||
self::$instances[$component][$class] = new $class(...$arguments);
|
||||
self::$updated[$component] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets alias
|
||||
*/
|
||||
private static function setAlias(string $component, string $alias, string $class): void
|
||||
{
|
||||
self::$aliases[$component][$alias] = $class;
|
||||
self::$updated[$component] = true;
|
||||
|
||||
// If a short classname is specified, also register FQCN to share the instance.
|
||||
if (! isset(self::$aliases[$component][$class]) && ! self::isNamespaced($alias)) {
|
||||
self::$aliases[$component][$class] = $class;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the component Config?
|
||||
*
|
||||
* @param string $component Lowercase, plural component name
|
||||
*/
|
||||
private static function isConfig(string $component): bool
|
||||
{
|
||||
return $component === 'config';
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a component class
|
||||
*
|
||||
* @param array $options The array of component-specific directives
|
||||
* @param string $alias Class alias. See the $aliases property.
|
||||
*/
|
||||
private static function locateClass(array $options, string $alias): ?string
|
||||
{
|
||||
// Check for low-hanging fruit
|
||||
if (
|
||||
class_exists($alias, false)
|
||||
&& self::verifyPreferApp($options, $alias)
|
||||
&& self::verifyInstanceOf($options, $alias)
|
||||
) {
|
||||
return $alias;
|
||||
}
|
||||
|
||||
// Determine the relative class names we need
|
||||
$basename = self::getBasename($alias);
|
||||
$appname = self::isConfig($options['component'])
|
||||
? 'Config\\' . $basename
|
||||
: rtrim(APP_NAMESPACE, '\\') . '\\' . $options['path'] . '\\' . $basename;
|
||||
|
||||
// If an App version was requested then see if it verifies
|
||||
if (
|
||||
// preferApp is used only for no namespaced class.
|
||||
! self::isNamespaced($alias)
|
||||
&& $options['preferApp'] && class_exists($appname)
|
||||
&& self::verifyInstanceOf($options, $alias)
|
||||
) {
|
||||
return $appname;
|
||||
}
|
||||
|
||||
// If we have ruled out an App version and the class exists then try it
|
||||
if (class_exists($alias) && self::verifyInstanceOf($options, $alias)) {
|
||||
return $alias;
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the class alias namespaced or not?
|
||||
*
|
||||
* @param string $alias Class alias. See the $aliases property.
|
||||
*/
|
||||
private static function isNamespaced(string $alias): bool
|
||||
{
|
||||
return str_contains($alias, '\\');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that a class & config satisfy the "preferApp" option
|
||||
*
|
||||
* @param array $options The array of component-specific directives
|
||||
* @param string $alias Class alias. See the $aliases property.
|
||||
*/
|
||||
private static function verifyPreferApp(array $options, string $alias): bool
|
||||
{
|
||||
// Anything without that restriction passes
|
||||
if (! $options['preferApp']) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Special case for Config since its App namespace is actually \Config
|
||||
if (self::isConfig($options['component'])) {
|
||||
return str_starts_with($alias, 'Config');
|
||||
}
|
||||
|
||||
return str_starts_with($alias, APP_NAMESPACE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that a class & config satisfy the "instanceOf" option
|
||||
*
|
||||
* @param array $options The array of component-specific directives
|
||||
* @param string $alias Class alias. See the $aliases property.
|
||||
*/
|
||||
private static function verifyInstanceOf(array $options, string $alias): bool
|
||||
{
|
||||
// Anything without that restriction passes
|
||||
if (! $options['instanceOf']) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return is_a($alias, $options['instanceOf'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the component-specific configuration
|
||||
*
|
||||
* @param string $component Lowercase, plural component name
|
||||
*
|
||||
* @return array<string, bool|string|null>
|
||||
*
|
||||
* @internal For testing only
|
||||
* @testTag
|
||||
*/
|
||||
public static function getOptions(string $component): array
|
||||
{
|
||||
$component = strtolower($component);
|
||||
|
||||
// Check for a stored version
|
||||
if (isset(self::$options[$component])) {
|
||||
return self::$options[$component];
|
||||
}
|
||||
|
||||
$values = self::isConfig($component)
|
||||
// Handle Config as a special case to prevent logic loops
|
||||
? self::$configOptions
|
||||
// Load values from the best Factory configuration (will include Registrars)
|
||||
: config('Factory')->{$component} ?? [];
|
||||
|
||||
// The setOptions() reset the component. So getOptions() may reset
|
||||
// the component.
|
||||
return self::setOptions($component, $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes, stores, and returns the configuration for a specific component
|
||||
*
|
||||
* @param string $component Lowercase, plural component name
|
||||
* @param array $values option values
|
||||
*
|
||||
* @return array<string, bool|string|null> The result after applying defaults and normalization
|
||||
*/
|
||||
public static function setOptions(string $component, array $values): array
|
||||
{
|
||||
$component = strtolower($component);
|
||||
|
||||
// Allow the config to replace the component name, to support "aliases"
|
||||
$values['component'] = strtolower($values['component'] ?? $component);
|
||||
|
||||
// Reset this component so instances can be rediscovered with the updated config
|
||||
self::reset($values['component']);
|
||||
|
||||
// If no path was available then use the component
|
||||
$values['path'] = trim($values['path'] ?? ucfirst($values['component']), '\\ ');
|
||||
|
||||
// Add defaults for any missing values
|
||||
$values = array_merge(Factory::$default, $values);
|
||||
|
||||
// Store the result to the supplied name and potential alias
|
||||
self::$options[$component] = $values;
|
||||
self::$options[$values['component']] = $values;
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the static arrays, optionally just for one component
|
||||
*
|
||||
* @param string|null $component Lowercase, plural component name
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function reset(?string $component = null)
|
||||
{
|
||||
if ($component !== null) {
|
||||
unset(
|
||||
self::$options[$component],
|
||||
self::$aliases[$component],
|
||||
self::$instances[$component],
|
||||
self::$updated[$component]
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
self::$options = [];
|
||||
self::$aliases = [];
|
||||
self::$instances = [];
|
||||
self::$updated = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for injecting mock instances
|
||||
*
|
||||
* @param string $component Lowercase, plural component name
|
||||
* @param string $alias Class alias. See the $aliases property.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @internal For testing only
|
||||
* @testTag
|
||||
*/
|
||||
public static function injectMock(string $component, string $alias, object $instance)
|
||||
{
|
||||
$component = strtolower($component);
|
||||
|
||||
// Force a configuration to exist for this component
|
||||
self::getOptions($component);
|
||||
|
||||
//$class = $instance::class;
|
||||
$class = get_class($instance);
|
||||
|
||||
self::$instances[$component][$class] = $instance;
|
||||
self::$aliases[$component][$alias] = $class;
|
||||
|
||||
if (self::isConfig($component)) {
|
||||
if (self::isNamespaced($alias)) {
|
||||
self::$aliases[$component][self::getBasename($alias)] = $class;
|
||||
} else {
|
||||
self::$aliases[$component]['Config\\' . $alias] = $class;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a basename from a class alias, namespaced or not.
|
||||
*
|
||||
* @internal For testing only
|
||||
* @testTag
|
||||
*/
|
||||
public static function getBasename(string $alias): string
|
||||
{
|
||||
// Determine the basename
|
||||
if ($basename = strrchr($alias, '\\')) {
|
||||
return substr($basename, 1);
|
||||
}
|
||||
|
||||
return $alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets component data for caching.
|
||||
*
|
||||
* @return array{
|
||||
* options: array<string, bool|string|null>,
|
||||
* aliases: array<string, class-string>,
|
||||
* instances: array<class-string, object>,
|
||||
* }
|
||||
*
|
||||
* @internal For caching only
|
||||
*/
|
||||
public static function getComponentInstances(string $component): array
|
||||
{
|
||||
if (! isset(self::$aliases[$component])) {
|
||||
return [
|
||||
'options' => [],
|
||||
'aliases' => [],
|
||||
'instances' => [],
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'options' => self::$options[$component],
|
||||
'aliases' => self::$aliases[$component],
|
||||
'instances' => self::$instances[$component],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets component data
|
||||
*
|
||||
* @internal For caching only
|
||||
*/
|
||||
public static function setComponentInstances(string $component, array $data): void
|
||||
{
|
||||
self::$options[$component] = $data['options'];
|
||||
self::$aliases[$component] = $data['aliases'];
|
||||
self::$instances[$component] = $data['instances'];
|
||||
|
||||
unset(self::$updated[$component]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the component instances are updated?
|
||||
*
|
||||
* @internal For caching only
|
||||
*/
|
||||
public static function isUpdated(string $component): bool
|
||||
{
|
||||
return isset(self::$updated[$component]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Config;
|
||||
|
||||
/**
|
||||
* Factories Configuration file.
|
||||
*
|
||||
* Provides overriding directives for how
|
||||
* Factories should handle discovery and
|
||||
* instantiation of specific components.
|
||||
* Each property should correspond to the
|
||||
* lowercase, plural component name.
|
||||
*/
|
||||
class Factory extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* Supplies a default set of options to merge for
|
||||
* all unspecified factory components.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $default = [
|
||||
'component' => null,
|
||||
'path' => null,
|
||||
'instanceOf' => null,
|
||||
'getShared' => true,
|
||||
'preferApp' => true,
|
||||
];
|
||||
|
||||
/**
|
||||
* Specifies that Models should always favor child
|
||||
* classes to allow easy extension of module Models.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $models = [
|
||||
'preferApp' => true,
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<?php
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Config;
|
||||
|
||||
/**
|
||||
* Describes foreign characters for transliteration with the text helper.
|
||||
*/
|
||||
class ForeignCharacters
|
||||
{
|
||||
/**
|
||||
* The list of foreign characters.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public $characterList = [
|
||||
'/ä|æ|ǽ/' => 'ae',
|
||||
'/ö|œ/' => 'oe',
|
||||
'/ü/' => 'ue',
|
||||
'/Ä/' => 'Ae',
|
||||
'/Ü/' => 'Ue',
|
||||
'/Ö/' => 'Oe',
|
||||
'/À|Á|Â|Ã|Ä|Å|Ǻ|Ā|Ă|Ą|Ǎ|Α|Ά|Ả|Ạ|Ầ|Ẫ|Ẩ|Ậ|Ằ|Ắ|Ẵ|Ẳ|Ặ|А/' => 'A',
|
||||
'/à|á|â|ã|å|ǻ|ā|ă|ą|ǎ|ª|α|ά|ả|ạ|ầ|ấ|ẫ|ẩ|ậ|ằ|ắ|ẵ|ẳ|ặ|а/' => 'a',
|
||||
'/Б/' => 'B',
|
||||
'/б/' => 'b',
|
||||
'/Ç|Ć|Ĉ|Ċ|Č/' => 'C',
|
||||
'/ç|ć|ĉ|ċ|č/' => 'c',
|
||||
'/Д/' => 'D',
|
||||
'/д/' => 'd',
|
||||
'/Ð|Ď|Đ|Δ/' => 'Dj',
|
||||
'/ð|ď|đ|δ/' => 'dj',
|
||||
'/È|É|Ê|Ë|Ē|Ĕ|Ė|Ę|Ě|Ε|Έ|Ẽ|Ẻ|Ẹ|Ề|Ế|Ễ|Ể|Ệ|Е|Э/' => 'E',
|
||||
'/è|é|ê|ë|ē|ĕ|ė|ę|ě|έ|ε|ẽ|ẻ|ẹ|ề|ế|ễ|ể|ệ|е|э/' => 'e',
|
||||
'/Ф/' => 'F',
|
||||
'/ф/' => 'f',
|
||||
'/Ĝ|Ğ|Ġ|Ģ|Γ|Г|Ґ/' => 'G',
|
||||
'/ĝ|ğ|ġ|ģ|γ|г|ґ/' => 'g',
|
||||
'/Ĥ|Ħ/' => 'H',
|
||||
'/ĥ|ħ/' => 'h',
|
||||
'/Ì|Í|Î|Ï|Ĩ|Ī|Ĭ|Ǐ|Į|İ|Η|Ή|Ί|Ι|Ϊ|Ỉ|Ị|И|Ы/' => 'I',
|
||||
'/ì|í|î|ï|ĩ|ī|ĭ|ǐ|į|ı|η|ή|ί|ι|ϊ|ỉ|ị|и|ы|ї/' => 'i',
|
||||
'/Ĵ/' => 'J',
|
||||
'/ĵ/' => 'j',
|
||||
'/Ķ|Κ|К/' => 'K',
|
||||
'/ķ|κ|к/' => 'k',
|
||||
'/Ĺ|Ļ|Ľ|Ŀ|Ł|Λ|Л/' => 'L',
|
||||
'/ĺ|ļ|ľ|ŀ|ł|λ|л/' => 'l',
|
||||
'/М/' => 'M',
|
||||
'/м/' => 'm',
|
||||
'/Ñ|Ń|Ņ|Ň|Ν|Н/' => 'N',
|
||||
'/ñ|ń|ņ|ň|ʼn|ν|н/' => 'n',
|
||||
'/Ò|Ó|Ô|Õ|Ō|Ŏ|Ǒ|Ő|Ơ|Ø|Ǿ|Ο|Ό|Ω|Ώ|Ỏ|Ọ|Ồ|Ố|Ỗ|Ổ|Ộ|Ờ|Ớ|Ỡ|Ở|Ợ|О/' => 'O',
|
||||
'/ò|ó|ô|õ|ō|ŏ|ǒ|ő|ơ|ø|ǿ|º|ο|ό|ω|ώ|ỏ|ọ|ồ|ố|ỗ|ổ|ộ|ờ|ớ|ỡ|ở|ợ|о/' => 'o',
|
||||
'/П/' => 'P',
|
||||
'/п/' => 'p',
|
||||
'/Ŕ|Ŗ|Ř|Ρ|Р/' => 'R',
|
||||
'/ŕ|ŗ|ř|ρ|р/' => 'r',
|
||||
'/Ś|Ŝ|Ş|Ș|Š|Σ|С/' => 'S',
|
||||
'/ś|ŝ|ş|ș|š|ſ|σ|ς|с/' => 's',
|
||||
'/Ț|Ţ|Ť|Ŧ|τ|Т/' => 'T',
|
||||
'/ț|ţ|ť|ŧ|т/' => 't',
|
||||
'/Ù|Ú|Û|Ũ|Ū|Ŭ|Ů|Ű|Ų|Ư|Ǔ|Ǖ|Ǘ|Ǚ|Ǜ|Ũ|Ủ|Ụ|Ừ|Ứ|Ữ|Ử|Ự|У/' => 'U',
|
||||
'/ù|ú|û|ũ|ū|ŭ|ů|ű|ų|ư|ǔ|ǖ|ǘ|ǚ|ǜ|υ|ύ|ϋ|ủ|ụ|ừ|ứ|ữ|ử|ự|у/' => 'u',
|
||||
'/Ƴ|Ɏ|Ỵ|Ẏ|Ӳ|Ӯ|Ў|Ý|Ÿ|Ŷ|Υ|Ύ|Ϋ|Ỳ|Ỹ|Ỷ|Ỵ|Й/' => 'Y',
|
||||
'/ẙ|ʏ|ƴ|ɏ|ỵ|ẏ|ӳ|ӯ|ў|ý|ÿ|ŷ|ỳ|ỹ|ỷ|ỵ|й/' => 'y',
|
||||
'/В/' => 'V',
|
||||
'/в/' => 'v',
|
||||
'/Ŵ/' => 'W',
|
||||
'/ŵ/' => 'w',
|
||||
'/Ź|Ż|Ž|Ζ|З/' => 'Z',
|
||||
'/ź|ż|ž|ζ|з/' => 'z',
|
||||
'/Æ|Ǽ/' => 'AE',
|
||||
'/ß/' => 'ss',
|
||||
'/IJ/' => 'IJ',
|
||||
'/ij/' => 'ij',
|
||||
'/Œ/' => 'OE',
|
||||
'/ƒ/' => 'f',
|
||||
'/ξ/' => 'ks',
|
||||
'/π/' => 'p',
|
||||
'/β/' => 'v',
|
||||
'/μ/' => 'm',
|
||||
'/ψ/' => 'ps',
|
||||
'/Ё/' => 'Yo',
|
||||
'/ё/' => 'yo',
|
||||
'/Є/' => 'Ye',
|
||||
'/є/' => 'ye',
|
||||
'/Ї/' => 'Yi',
|
||||
'/Ж/' => 'Zh',
|
||||
'/ж/' => 'zh',
|
||||
'/Х/' => 'Kh',
|
||||
'/х/' => 'kh',
|
||||
'/Ц/' => 'Ts',
|
||||
'/ц/' => 'ts',
|
||||
'/Ч/' => 'Ch',
|
||||
'/ч/' => 'ch',
|
||||
'/Ш/' => 'Sh',
|
||||
'/ш/' => 'sh',
|
||||
'/Щ/' => 'Shch',
|
||||
'/щ/' => 'shch',
|
||||
'/Ъ|ъ|Ь|ь/' => '',
|
||||
'/Ю/' => 'Yu',
|
||||
'/ю/' => 'yu',
|
||||
'/Я/' => 'Ya',
|
||||
'/я/' => 'ya',
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Config;
|
||||
|
||||
/**
|
||||
* Publisher Configuration
|
||||
*
|
||||
* Defines basic security restrictions for the Publisher class
|
||||
* to prevent abuse by injecting malicious files into a project.
|
||||
*/
|
||||
class Publisher extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* 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 => '#\.(?css|js|map|htm?|xml|json|webmanifest|tff|eot|woff?|gif|jpe?g|tiff?|png|webp|bmp|ico|svg)$#i',
|
||||
];
|
||||
|
||||
/**
|
||||
* Disables Registrars to prevent modules from altering the restrictions.
|
||||
*/
|
||||
final protected function registerProperties(): void
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Config;
|
||||
|
||||
use CodeIgniter\Cache\CacheFactory;
|
||||
use CodeIgniter\Cache\CacheInterface;
|
||||
use CodeIgniter\Debug\Exceptions;
|
||||
use Config\Cache;
|
||||
use Config\Exceptions as ExceptionsConfig;
|
||||
|
||||
/**
|
||||
* Services Configuration file.
|
||||
*
|
||||
* Services are simply other classes/libraries that the system uses
|
||||
* to do its job. This is used by CodeIgniter to allow the core of the
|
||||
* framework to be swapped out easily without affecting the usage within
|
||||
* the rest of your application.
|
||||
*
|
||||
* This is used in place of a Dependency Injection container primarily
|
||||
* due to its simplicity, which allows a better long-term maintenance
|
||||
* of the applications built on top of CodeIgniter. A bonus side-effect
|
||||
* is that IDEs are able to determine what class you are calling
|
||||
* whereas with DI Containers there usually isn't a way for them to do this.
|
||||
*
|
||||
* @see http://blog.ircmaxell.com/2015/11/simple-easy-risk-and-change.html
|
||||
* @see http://www.infoq.com/presentations/Simple-Made-Easy
|
||||
* @see \CodeIgniter\Config\ServicesTest
|
||||
*/
|
||||
class Services extends BaseService
|
||||
{
|
||||
/**
|
||||
* The cache class provides a simple way to store and retrieve
|
||||
* complex data for later.
|
||||
*
|
||||
* @return CacheInterface
|
||||
*/
|
||||
public static function cache(?Cache $config = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('cache', $config);
|
||||
}
|
||||
|
||||
$config ??= config(Cache::class);
|
||||
|
||||
return CacheFactory::getHandler($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* The Exceptions class holds the methods that handle:
|
||||
*
|
||||
* - set_exception_handler
|
||||
* - set_error_handler
|
||||
* - register_shutdown_function
|
||||
*
|
||||
* @return Exceptions
|
||||
*/
|
||||
public static function exceptions(
|
||||
?ExceptionsConfig $config = null,
|
||||
bool $getShared = true,
|
||||
) {
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('exceptions', $config);
|
||||
}
|
||||
|
||||
$config ??= config(ExceptionsConfig::class);
|
||||
|
||||
return new Exceptions($config);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
<?php namespace Config;
|
||||
/**
|
||||
* {{www.xunruicms.com}}
|
||||
* {{迅睿内容管理框架系统}}
|
||||
* 本文件是框架系统文件,二次开发时不可以修改本文件
|
||||
**/
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
use CodeIgniter\Debug\Toolbar\Collectors\Database;
|
||||
use CodeIgniter\Debug\Toolbar\Collectors\Files;
|
||||
use CodeIgniter\Debug\Toolbar\Collectors\Routes;
|
||||
use CodeIgniter\Debug\Toolbar\Collectors\Views;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Debug Toolbar
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The Debug Toolbar provides a way to see information about the performance
|
||||
* and state of your application during that page display. By default it will
|
||||
* NOT be displayed under production environments, and will only display if
|
||||
* `CI_DEBUG` is true, since if it's not, there's not much to display anyway.
|
||||
*/
|
||||
class Toolbar extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Toolbar Collectors
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* List of toolbar collectors that will be called when Debug Toolbar
|
||||
* fires up and collects data from.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public $collectors = [
|
||||
Database::class,
|
||||
Views::class,
|
||||
Files::class,
|
||||
Routes::class
|
||||
];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Max History
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* `$maxHistory` sets a limit on the number of past requests that are stored,
|
||||
* helping to conserve file space used to store them. You can set it to
|
||||
* 0 (zero) to not have any history stored, or -1 for unlimited history.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $maxHistory = 20;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Toolbar Views Path
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* The full path to the the views that are used by the toolbar.
|
||||
* This MUST have a trailing slash.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $viewsPath = FRAMEPATH . 'Debug/Toolbar/Views/';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Max Queries
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* If the Database Collector is enabled, it will log every query that the
|
||||
* the system generates so they can be displayed on the toolbar's timeline
|
||||
* and in the query log. This can lead to memory issues in some instances
|
||||
* with hundreds of queries.
|
||||
*
|
||||
* `$maxQueries` defines the maximum amount of queries that will be stored.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $maxQueries = 100;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Collect Var Data
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* If set to false var data from the views will not be colleted. Usefull to
|
||||
* avoid high memory usage when there are lots of data passed to the view.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $collectVarData = true;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Watched Directories
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Contains an array of directories that will be watched for changes and
|
||||
* used to determine if the hot-reload feature should reload the page or not.
|
||||
* We restrict the values to keep performance as high as possible.
|
||||
*
|
||||
* NOTE: The ROOTPATH will be prepended to all values.
|
||||
*/
|
||||
public $watchedDirectories = [
|
||||
'app',
|
||||
];
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Watched File Extensions
|
||||
* --------------------------------------------------------------------------
|
||||
*
|
||||
* Contains an array of file extensions that will be watched for changes and
|
||||
* used to determine if the hot-reload feature should reload the page or not.
|
||||
*/
|
||||
public $watchedExtensions = [
|
||||
'php', 'css', 'js', 'html', 'svg', 'json', 'env',
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user