Initial
This commit is contained in:
135
system/Config/AutoloadConfig.php
Normal file
135
system/Config/AutoloadConfig.php
Normal file
@@ -0,0 +1,135 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* AUTOLOADER CONFIGURATION
|
||||
*
|
||||
* This file defines the namespaces and class maps so the Autoloader
|
||||
* can find the files as needed.
|
||||
*/
|
||||
class AutoloadConfig
|
||||
{
|
||||
/**
|
||||
* -------------------------------------------------------------------
|
||||
* Namespaces
|
||||
* -------------------------------------------------------------------
|
||||
* This maps the locations of any namespaces in your application to
|
||||
* 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,
|
||||
* 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.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public $psr4 = [];
|
||||
|
||||
/**
|
||||
* -------------------------------------------------------------------
|
||||
* Class Map
|
||||
* -------------------------------------------------------------------
|
||||
* The class map provides a map of class names and their exact
|
||||
* location on the drive. Classes loaded in this manner will have
|
||||
* slightly faster performance because they will not have to be
|
||||
* searched for within one or more directories as they would if they
|
||||
* were being autoloaded through a namespace.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public $classmap = [];
|
||||
|
||||
/**
|
||||
* -------------------------------------------------------------------
|
||||
* Files
|
||||
* -------------------------------------------------------------------
|
||||
* The files array provides a list of paths to __non-class__ files
|
||||
* that will be autoloaded. This can be useful for bootstrap operations
|
||||
* or for loading functions.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
public $files = [];
|
||||
|
||||
/**
|
||||
* -------------------------------------------------------------------
|
||||
* Namespaces
|
||||
* -------------------------------------------------------------------
|
||||
* This maps the locations of any namespaces in your application to
|
||||
* their location on the file system. These are used by the autoloader
|
||||
* to locate files the first time they have been instantiated.
|
||||
*
|
||||
* Do not change the name of the CodeIgniter namespace or your application
|
||||
* will break.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $corePsr4 = [
|
||||
'CodeIgniter' => SYSTEMPATH,
|
||||
'App' => APPPATH, // To ensure filters, etc still found,
|
||||
];
|
||||
|
||||
/**
|
||||
* -------------------------------------------------------------------
|
||||
* Class Map
|
||||
* -------------------------------------------------------------------
|
||||
* The class map provides a map of class names and their exact
|
||||
* location on the drive. Classes loaded in this manner will have
|
||||
* slightly faster performance because they will not have to be
|
||||
* searched for within one or more directories as they would if they
|
||||
* were being autoloaded through a namespace.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $coreClassmap = [
|
||||
'Psr\Log\AbstractLogger' => SYSTEMPATH . 'ThirdParty/PSR/Log/AbstractLogger.php',
|
||||
'Psr\Log\InvalidArgumentException' => SYSTEMPATH . 'ThirdParty/PSR/Log/InvalidArgumentException.php',
|
||||
'Psr\Log\LoggerAwareInterface' => SYSTEMPATH . 'ThirdParty/PSR/Log/LoggerAwareInterface.php',
|
||||
'Psr\Log\LoggerAwareTrait' => SYSTEMPATH . 'ThirdParty/PSR/Log/LoggerAwareTrait.php',
|
||||
'Psr\Log\LoggerInterface' => SYSTEMPATH . 'ThirdParty/PSR/Log/LoggerInterface.php',
|
||||
'Psr\Log\LoggerTrait' => SYSTEMPATH . 'ThirdParty/PSR/Log/LoggerTrait.php',
|
||||
'Psr\Log\LogLevel' => SYSTEMPATH . 'ThirdParty/PSR/Log/LogLevel.php',
|
||||
'Psr\Log\NullLogger' => SYSTEMPATH . 'ThirdParty/PSR/Log/NullLogger.php',
|
||||
'Laminas\Escaper\Escaper' => SYSTEMPATH . 'ThirdParty/Escaper/Escaper.php',
|
||||
];
|
||||
|
||||
/**
|
||||
* -------------------------------------------------------------------
|
||||
* Core Files
|
||||
* -------------------------------------------------------------------
|
||||
* List of files from the framework to be autoloaded early.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $coreFiles = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Merge the built-in and developer-configured psr4 and classmap,
|
||||
* with preference to the developer ones.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (isset($_SERVER['CI_ENVIRONMENT']) && $_SERVER['CI_ENVIRONMENT'] === 'testing') {
|
||||
$this->psr4['Tests\Support'] = SUPPORTPATH;
|
||||
$this->classmap['CodeIgniter\Log\TestLogger'] = SYSTEMPATH . 'Test/TestLogger.php';
|
||||
$this->classmap['CIDatabaseTestCase'] = SYSTEMPATH . 'Test/CIDatabaseTestCase.php';
|
||||
}
|
||||
|
||||
$this->psr4 = array_merge($this->corePsr4, $this->psr4);
|
||||
$this->classmap = array_merge($this->coreClassmap, $this->classmap);
|
||||
$this->files = array_merge($this->coreFiles, $this->files);
|
||||
}
|
||||
}
|
||||
204
system/Config/BaseConfig.php
Normal file
204
system/Config/BaseConfig.php
Normal file
@@ -0,0 +1,204 @@
|
||||
<?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 Config\Encryption;
|
||||
use Config\Modules;
|
||||
use Config\Services;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
class BaseConfig
|
||||
{
|
||||
/**
|
||||
* An optional array of classes that will act as Registrars
|
||||
* for rapidly setting config class properties.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $registrars = [];
|
||||
|
||||
/**
|
||||
* Has module discovery happened yet?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected static $didDiscovery = false;
|
||||
|
||||
/**
|
||||
* The modules configuration.
|
||||
*
|
||||
* @var Modules
|
||||
*/
|
||||
protected static $moduleConfig;
|
||||
|
||||
/**
|
||||
* 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()
|
||||
{
|
||||
static::$moduleConfig = config('Modules');
|
||||
|
||||
$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 (strpos($this->{$property}, 'hex2bin:') === 0) {
|
||||
// Handle hex2bin prefix
|
||||
$this->{$property} = hex2bin(substr($this->{$property}, 8));
|
||||
} elseif (strpos($this->{$property}, 'base64:') === 0) {
|
||||
// Handle base64 prefix
|
||||
$this->{$property} = base64_decode(substr($this->{$property}, 7), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization an environment-specific configuration setting
|
||||
*
|
||||
* @param mixed $property
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
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;
|
||||
}
|
||||
$property = is_bool($value) ? $value : trim($value, '\'"');
|
||||
}
|
||||
|
||||
return $property;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an environment-specific configuration setting
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
protected function registerProperties()
|
||||
{
|
||||
if (! static::$moduleConfig->shouldDiscover('registrars')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! static::$didDiscovery) {
|
||||
$locator = Services::locator();
|
||||
$registrarsFiles = $locator->search('Config/Registrar.php');
|
||||
|
||||
foreach ($registrarsFiles as $file) {
|
||||
$className = $locator->getClassname($file);
|
||||
static::$registrars[] = new $className();
|
||||
}
|
||||
|
||||
static::$didDiscovery = true;
|
||||
}
|
||||
|
||||
$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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
378
system/Config/BaseService.php
Normal file
378
system/Config/BaseService.php
Normal file
@@ -0,0 +1,378 @@
|
||||
<?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\Autoloader;
|
||||
use CodeIgniter\Autoloader\FileLocator;
|
||||
use CodeIgniter\Cache\CacheInterface;
|
||||
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\Filters\Filters;
|
||||
use CodeIgniter\Format\Format;
|
||||
use CodeIgniter\Honeypot\Honeypot;
|
||||
use CodeIgniter\HTTP\CLIRequest;
|
||||
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\Response;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
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\Throttle\Throttler;
|
||||
use CodeIgniter\Typography\Typography;
|
||||
use CodeIgniter\Validation\Validation;
|
||||
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\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\Pager as ConfigPager;
|
||||
use Config\Services as AppServices;
|
||||
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 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, IncomingRequest $request = null, Response $response = 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 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 request(App $config = null, $getShared = true)
|
||||
* @method static Response response(App $config = null, $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(App $config = null, $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 Validation 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
|
||||
*/
|
||||
protected static $instances = [];
|
||||
|
||||
/**
|
||||
* Mock objects for testing which are returned if exist.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
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
|
||||
*/
|
||||
protected static $services = [];
|
||||
|
||||
/**
|
||||
* A cache of the names of services classes found.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
private static $serviceNames = [];
|
||||
|
||||
/**
|
||||
* Returns a shared instance of any of the class' services.
|
||||
*
|
||||
* $key must be a name matching a service.
|
||||
*
|
||||
* @param mixed ...$params
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
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 FileLocator
|
||||
*/
|
||||
public static function locator(bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
if (empty(static::$instances['locator'])) {
|
||||
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 mixed
|
||||
*/
|
||||
public static function __callStatic(string $name, array $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)) {
|
||||
return $service;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset shared instances and mocks for testing.
|
||||
*/
|
||||
public static function reset(bool $initAutoloader = false)
|
||||
{
|
||||
static::$mocks = [];
|
||||
static::$instances = [];
|
||||
|
||||
if ($initAutoloader) {
|
||||
static::autoloader()->initialize(new Autoload(), new Modules());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets any mock and shared instances for a single service.
|
||||
*/
|
||||
public static function resetSingle(string $name)
|
||||
{
|
||||
unset(static::$mocks[$name], static::$instances[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject mock object for testing.
|
||||
*
|
||||
* @param mixed $mock
|
||||
*/
|
||||
public static function injectMock(string $name, $mock)
|
||||
{
|
||||
static::$mocks[strtolower($name)] = $mock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will scan all psr4 namespaces registered with system to look
|
||||
* for new Config\Services files. Caches a copy of each one, then
|
||||
* looks for the service method in each, returning an instance of
|
||||
* the service, if available.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected static function discoverServices(string $name, array $arguments)
|
||||
{
|
||||
if (! static::$discovered) {
|
||||
$config = config('Modules');
|
||||
|
||||
if ($config->shouldDiscover('services')) {
|
||||
$locator = static::locator();
|
||||
$files = $locator->search('Config/Services');
|
||||
|
||||
if (empty($files)) {
|
||||
// no files at all found - this would be really, really bad
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get instances of all service classes and cache them locally.
|
||||
foreach ($files as $file) {
|
||||
$classname = $locator->getClassname($file);
|
||||
|
||||
if (! in_array($classname, ['CodeIgniter\\Config\\Services'], true)) {
|
||||
static::$services[] = new $classname();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static::$discovered = true;
|
||||
}
|
||||
|
||||
if (! static::$services) {
|
||||
// we found stuff, but no services - this would be really bad
|
||||
return null;
|
||||
}
|
||||
|
||||
// Try to find the desired service method
|
||||
foreach (static::$services as $class) {
|
||||
if (method_exists($class, $name)) {
|
||||
return $class::$name(...$arguments);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static function buildServicesCache(): void
|
||||
{
|
||||
if (! static::$discovered) {
|
||||
$config = config('Modules');
|
||||
|
||||
if ($config->shouldDiscover('services')) {
|
||||
$locator = static::locator();
|
||||
$files = $locator->search('Config/Services');
|
||||
|
||||
// Get instances of all service classes and cache them locally.
|
||||
foreach ($files as $file) {
|
||||
$classname = $locator->getClassname($file);
|
||||
|
||||
if ($classname !== 'CodeIgniter\\Config\\Services') {
|
||||
self::$serviceNames[] = $classname;
|
||||
static::$services[] = new $classname();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static::$discovered = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
50
system/Config/Config.php
Normal file
50
system/Config/Config.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* @deprecated Use CodeIgniter\Config\Factories::config()
|
||||
*/
|
||||
class Config
|
||||
{
|
||||
/**
|
||||
* Create new configuration instances or return
|
||||
* a shared instance
|
||||
*
|
||||
* @param string $name Configuration name
|
||||
* @param bool $getShared Use shared instance
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public static function get(string $name, bool $getShared = true)
|
||||
{
|
||||
return Factories::config($name, ['getShared' => $getShared]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for injecting mock instances while testing.
|
||||
*
|
||||
* @param object $instance
|
||||
*/
|
||||
public static function injectMock(string $name, $instance)
|
||||
{
|
||||
Factories::injectMock('config', $name, $instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the static arrays
|
||||
*/
|
||||
public static function reset()
|
||||
{
|
||||
Factories::reset('config');
|
||||
}
|
||||
}
|
||||
233
system/Config/DotEnv.php
Normal file
233
system/Config/DotEnv.php
Normal file
@@ -0,0 +1,233 @@
|
||||
<?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 InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Environment-specific configuration
|
||||
*/
|
||||
class DotEnv
|
||||
{
|
||||
/**
|
||||
* The directory where the .env file can be located.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $path;
|
||||
|
||||
/**
|
||||
* Builds the path to our file.
|
||||
*/
|
||||
public function __construct(string $path, string $file = '.env')
|
||||
{
|
||||
$this->path = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* The main entry point, will load the .env file and process it
|
||||
* so that we end up with all settings in the PHP environment vars
|
||||
* (i.e. getenv(), $_ENV, and $_SERVER)
|
||||
*/
|
||||
public function load(): bool
|
||||
{
|
||||
$vars = $this->parse();
|
||||
|
||||
return $vars !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the .env file into an array of key => value
|
||||
*/
|
||||
public function parse(): ?array
|
||||
{
|
||||
// We don't want to enforce the presence of a .env file, they should be optional.
|
||||
if (! is_file($this->path)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Ensure the file is readable
|
||||
if (! is_readable($this->path)) {
|
||||
throw new InvalidArgumentException("The .env file is not readable: {$this->path}");
|
||||
}
|
||||
|
||||
$vars = [];
|
||||
|
||||
$lines = file($this->path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
|
||||
foreach ($lines as $line) {
|
||||
// Is it a comment?
|
||||
if (strpos(trim($line), '#') === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If there is an equal sign, then we know we are assigning a variable.
|
||||
if (strpos($line, '=') !== false) {
|
||||
[$name, $value] = $this->normaliseVariable($line);
|
||||
$vars[$name] = $value;
|
||||
$this->setVariable($name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the variable into the environment. Will parse the string
|
||||
* first to look for {name}={value} pattern, ensure that nested
|
||||
* variables are handled, and strip it of single and double quotes.
|
||||
*/
|
||||
protected function setVariable(string $name, string $value = '')
|
||||
{
|
||||
if (! getenv($name, true)) {
|
||||
putenv("{$name}={$value}");
|
||||
}
|
||||
|
||||
if (empty($_ENV[$name])) {
|
||||
$_ENV[$name] = $value;
|
||||
}
|
||||
|
||||
if (empty($_SERVER[$name])) {
|
||||
$_SERVER[$name] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses for assignment, cleans the $name and $value, and ensures
|
||||
* that nested variables are handled.
|
||||
*/
|
||||
public function normaliseVariable(string $name, string $value = ''): array
|
||||
{
|
||||
// Split our compound string into its parts.
|
||||
if (strpos($name, '=') !== false) {
|
||||
[$name, $value] = explode('=', $name, 2);
|
||||
}
|
||||
|
||||
$name = trim($name);
|
||||
$value = trim($value);
|
||||
|
||||
// Sanitize the name
|
||||
$name = str_replace(['export', '\'', '"'], '', $name);
|
||||
|
||||
// Sanitize the value
|
||||
$value = $this->sanitizeValue($value);
|
||||
$value = $this->resolveNestedVariables($value);
|
||||
|
||||
return [$name, $value];
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips quotes from the environment variable value.
|
||||
*
|
||||
* This was borrowed from the excellent phpdotenv with very few changes.
|
||||
* https://github.com/vlucas/phpdotenv
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
protected function sanitizeValue(string $value): string
|
||||
{
|
||||
if (! $value) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
// Does it begin with a quote?
|
||||
if (strpbrk($value[0], '"\'') !== false) {
|
||||
// value starts with a quote
|
||||
$quote = $value[0];
|
||||
|
||||
$regexPattern = sprintf(
|
||||
'/^
|
||||
%1$s # match a quote at the start of the value
|
||||
( # capturing sub-pattern used
|
||||
(?: # we do not need to capture this
|
||||
[^%1$s\\\\] # any character other than a quote or backslash
|
||||
|\\\\\\\\ # or two backslashes together
|
||||
|\\\\%1$s # or an escaped quote e.g \"
|
||||
)* # as many characters that match the previous rules
|
||||
) # end of the capturing sub-pattern
|
||||
%1$s # and the closing quote
|
||||
.*$ # and discard any string after the closing quote
|
||||
/mx',
|
||||
$quote
|
||||
);
|
||||
|
||||
$value = preg_replace($regexPattern, '$1', $value);
|
||||
$value = str_replace("\\{$quote}", $quote, $value);
|
||||
$value = str_replace('\\\\', '\\', $value);
|
||||
} else {
|
||||
$parts = explode(' #', $value, 2);
|
||||
$value = trim($parts[0]);
|
||||
|
||||
// Unquoted values cannot contain whitespace
|
||||
if (preg_match('/\s+/', $value) > 0) {
|
||||
throw new InvalidArgumentException('.env values containing spaces must be surrounded by quotes.');
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the nested variables.
|
||||
*
|
||||
* Look for ${varname} patterns in the variable value and replace with an existing
|
||||
* environment variable.
|
||||
*
|
||||
* This was borrowed from the excellent phpdotenv with very few changes.
|
||||
* https://github.com/vlucas/phpdotenv
|
||||
*/
|
||||
protected function resolveNestedVariables(string $value): string
|
||||
{
|
||||
if (strpos($value, '$') !== false) {
|
||||
$value = preg_replace_callback(
|
||||
'/\${([a-zA-Z0-9_\.]+)}/',
|
||||
function ($matchedPatterns) {
|
||||
$nestedVariable = $this->getVariable($matchedPatterns[1]);
|
||||
|
||||
if ($nestedVariable === null) {
|
||||
return $matchedPatterns[0];
|
||||
}
|
||||
|
||||
return $nestedVariable;
|
||||
},
|
||||
$value
|
||||
);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the different places for environment variables and return first value found.
|
||||
*
|
||||
* This was borrowed from the excellent phpdotenv with very few changes.
|
||||
* https://github.com/vlucas/phpdotenv
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
protected function getVariable(string $name)
|
||||
{
|
||||
switch (true) {
|
||||
case array_key_exists($name, $_ENV):
|
||||
return $_ENV[$name];
|
||||
|
||||
case array_key_exists($name, $_SERVER):
|
||||
return $_SERVER[$name];
|
||||
|
||||
default:
|
||||
$value = getenv($name);
|
||||
|
||||
// switch getenv default to null
|
||||
return $value === false ? null : $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
316
system/Config/Factories.php
Normal file
316
system/Config/Factories.php
Normal file
@@ -0,0 +1,316 @@
|
||||
<?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\Model;
|
||||
use Config\Services;
|
||||
|
||||
/**
|
||||
* 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 config(...$arguments)
|
||||
* @method static Model models(...$arguments)
|
||||
*/
|
||||
class Factories
|
||||
{
|
||||
/**
|
||||
* Store of component-specific options, usually
|
||||
* from CodeIgniter\Config\Factory.
|
||||
*
|
||||
* @var array<string, array>
|
||||
*/
|
||||
protected static $options = [];
|
||||
|
||||
/**
|
||||
* Explicit options for the Config
|
||||
* component to prevent logic loops.
|
||||
*
|
||||
* @var array<string, mixed>
|
||||
*/
|
||||
private static $configOptions = [
|
||||
'component' => 'config',
|
||||
'path' => 'Config',
|
||||
'instanceOf' => null,
|
||||
'getShared' => true,
|
||||
'preferApp' => true,
|
||||
];
|
||||
|
||||
/**
|
||||
* Mapping of class basenames (no namespace) to
|
||||
* their instances.
|
||||
*
|
||||
* @var array<string, string[]>
|
||||
*/
|
||||
protected static $basenames = [];
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @var array<string, array>
|
||||
*/
|
||||
protected static $instances = [];
|
||||
|
||||
/**
|
||||
* Loads instances based on the method component name. Either
|
||||
* creates a new instance or returns an existing shared instance.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function __callStatic(string $component, array $arguments)
|
||||
{
|
||||
// First argument is the name, second is options
|
||||
$name = trim(array_shift($arguments), '\\ ');
|
||||
$options = array_shift($arguments) ?? [];
|
||||
|
||||
// Determine the component-specific options
|
||||
$options = array_merge(self::getOptions(strtolower($component)), $options);
|
||||
|
||||
if (! $options['getShared']) {
|
||||
if ($class = self::locateClass($options, $name)) {
|
||||
return new $class(...$arguments);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$basename = self::getBasename($name);
|
||||
|
||||
// Check for an existing instance
|
||||
if (isset(self::$basenames[$options['component']][$basename])) {
|
||||
$class = self::$basenames[$options['component']][$basename];
|
||||
|
||||
// Need to verify if the shared instance matches the request
|
||||
if (self::verifyInstanceOf($options, $class)) {
|
||||
return self::$instances[$options['component']][$class];
|
||||
}
|
||||
}
|
||||
|
||||
// Try to locate the class
|
||||
if (! $class = self::locateClass($options, $name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
self::$instances[$options['component']][$class] = new $class(...$arguments);
|
||||
self::$basenames[$options['component']][$basename] = $class;
|
||||
|
||||
return self::$instances[$options['component']][$class];
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a component class
|
||||
*
|
||||
* @param array $options The array of component-specific directives
|
||||
* @param string $name Class name, namespace optional
|
||||
*/
|
||||
protected static function locateClass(array $options, string $name): ?string
|
||||
{
|
||||
// Check for low-hanging fruit
|
||||
if (class_exists($name, false) && self::verifyPreferApp($options, $name) && self::verifyInstanceOf($options, $name)) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
// Determine the relative class names we need
|
||||
$basename = self::getBasename($name);
|
||||
$appname = $options['component'] === 'config'
|
||||
? 'Config\\' . $basename
|
||||
: rtrim(APP_NAMESPACE, '\\') . '\\' . $options['path'] . '\\' . $basename;
|
||||
|
||||
// If an App version was requested then see if it verifies
|
||||
if ($options['preferApp'] && class_exists($appname) && self::verifyInstanceOf($options, $name)) {
|
||||
return $appname;
|
||||
}
|
||||
|
||||
// If we have ruled out an App version and the class exists then try it
|
||||
if (class_exists($name) && self::verifyInstanceOf($options, $name)) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
// Have to do this the hard way...
|
||||
$locator = Services::locator();
|
||||
|
||||
// Check if the class was namespaced
|
||||
if (strpos($name, '\\') !== false) {
|
||||
if (! $file = $locator->locateFile($name, $options['path'])) {
|
||||
return null;
|
||||
}
|
||||
$files = [$file];
|
||||
}
|
||||
// No namespace? Search for it
|
||||
// Check all namespaces, prioritizing App and modules
|
||||
elseif (! $files = $locator->search($options['path'] . DIRECTORY_SEPARATOR . $name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check all files for a valid class
|
||||
foreach ($files as $file) {
|
||||
$class = $locator->getClassname($file);
|
||||
|
||||
if ($class && self::verifyInstanceOf($options, $class)) {
|
||||
return $class;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that a class & config satisfy the "preferApp" option
|
||||
*
|
||||
* @param array $options The array of component-specific directives
|
||||
* @param string $name Class name, namespace optional
|
||||
*/
|
||||
protected static function verifyPreferApp(array $options, string $name): bool
|
||||
{
|
||||
// Anything without that restriction passes
|
||||
if (! $options['preferApp']) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Special case for Config since its App namespace is actually \Config
|
||||
if ($options['component'] === 'config') {
|
||||
return strpos($name, 'Config') === 0;
|
||||
}
|
||||
|
||||
return strpos($name, APP_NAMESPACE) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that a class & config satisfy the "instanceOf" option
|
||||
*
|
||||
* @param array $options The array of component-specific directives
|
||||
* @param string $name Class name, namespace optional
|
||||
*/
|
||||
protected static function verifyInstanceOf(array $options, string $name): bool
|
||||
{
|
||||
// Anything without that restriction passes
|
||||
if (! $options['instanceOf']) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return is_a($name, $options['instanceOf'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the component-specific configuration
|
||||
*
|
||||
* @param string $component Lowercase, plural component name
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
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 = $component === 'config'
|
||||
// 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} ?? [];
|
||||
|
||||
return self::setOptions($component, $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes, stores, and returns the configuration for a specific component
|
||||
*
|
||||
* @param string $component Lowercase, plural component name
|
||||
*
|
||||
* @return array<string, mixed> The result after applying defaults and normalization
|
||||
*/
|
||||
public static function setOptions(string $component, array $values): array
|
||||
{
|
||||
// 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 $component Lowercase, plural component name
|
||||
*/
|
||||
public static function reset(?string $component = null)
|
||||
{
|
||||
if ($component) {
|
||||
unset(
|
||||
static::$options[$component],
|
||||
static::$basenames[$component],
|
||||
static::$instances[$component]
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static::$options = [];
|
||||
static::$basenames = [];
|
||||
static::$instances = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for injecting mock instances
|
||||
*
|
||||
* @param string $component Lowercase, plural component name
|
||||
* @param string $name The name of the instance
|
||||
*/
|
||||
public static function injectMock(string $component, string $name, object $instance)
|
||||
{
|
||||
// Force a configuration to exist for this component
|
||||
$component = strtolower($component);
|
||||
self::getOptions($component);
|
||||
|
||||
$class = get_class($instance);
|
||||
$basename = self::getBasename($name);
|
||||
|
||||
self::$instances[$component][$class] = $instance;
|
||||
self::$basenames[$component][$basename] = $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a basename from a class name, namespaced or not.
|
||||
*/
|
||||
public static function getBasename(string $name): string
|
||||
{
|
||||
// Determine the basename
|
||||
if ($basename = strrchr($name, '\\')) {
|
||||
return substr($basename, 1);
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
48
system/Config/Factory.php
Normal file
48
system/Config/Factory.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* 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,
|
||||
];
|
||||
}
|
||||
113
system/Config/ForeignCharacters.php
Normal file
113
system/Config/ForeignCharacters.php
Normal file
@@ -0,0 +1,113 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Describes foreign characters for transliteration with the text helper.
|
||||
*/
|
||||
class ForeignCharacters
|
||||
{
|
||||
/**
|
||||
* Without further ado, the list of foreign characters.
|
||||
*/
|
||||
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',
|
||||
];
|
||||
}
|
||||
42
system/Config/Publisher.php
Normal file
42
system/Config/Publisher.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* 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()
|
||||
{
|
||||
}
|
||||
}
|
||||
40
system/Config/Routes.php
Normal file
40
system/Config/Routes.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?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.
|
||||
*/
|
||||
|
||||
use CodeIgniter\Exceptions\PageNotFoundException;
|
||||
|
||||
/*
|
||||
* System URI Routing
|
||||
*
|
||||
* This file contains any routing to system tools, such as command-line
|
||||
* tools for migrations, etc.
|
||||
*
|
||||
* It is called by Config\Routes, and has the $routes RouteCollection
|
||||
* already loaded up and ready for us to use.
|
||||
*/
|
||||
|
||||
// Prevent access to BaseController
|
||||
$routes->add('BaseController(:any)', static function () {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
});
|
||||
|
||||
// Prevent access to initController method
|
||||
$routes->add('(:any)/initController', static function () {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
});
|
||||
|
||||
// Migrations
|
||||
$routes->cli('migrations/(:segment)/(:segment)', '\CodeIgniter\Commands\MigrationsCommand::$1/$2');
|
||||
$routes->cli('migrations/(:segment)', '\CodeIgniter\Commands\MigrationsCommand::$1');
|
||||
$routes->cli('migrations', '\CodeIgniter\Commands\MigrationsCommand::index');
|
||||
|
||||
// CLI Catchall - uses a _remap to call Commands
|
||||
$routes->cli('ci(:any)', '\CodeIgniter\CLI\CommandRunner::index/$1');
|
||||
689
system/Config/Services.php
Normal file
689
system/Config/Services.php
Normal file
@@ -0,0 +1,689 @@
|
||||
<?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\Cache\CacheFactory;
|
||||
use CodeIgniter\Cache\CacheInterface;
|
||||
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\Encryption\Encryption;
|
||||
use CodeIgniter\Filters\Filters;
|
||||
use CodeIgniter\Format\Format;
|
||||
use CodeIgniter\Honeypot\Honeypot;
|
||||
use CodeIgniter\HTTP\CLIRequest;
|
||||
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\Response;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use CodeIgniter\HTTP\URI;
|
||||
use CodeIgniter\HTTP\UserAgent;
|
||||
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\Throttle\Throttler;
|
||||
use CodeIgniter\Typography\Typography;
|
||||
use CodeIgniter\Validation\Validation;
|
||||
use CodeIgniter\View\Cell;
|
||||
use CodeIgniter\View\Parser;
|
||||
use CodeIgniter\View\RendererInterface;
|
||||
use CodeIgniter\View\View;
|
||||
use Config\App;
|
||||
use Config\Cache;
|
||||
use Config\Email as EmailConfig;
|
||||
use Config\Encryption as EncryptionConfig;
|
||||
use Config\Exceptions as ExceptionsConfig;
|
||||
use Config\Filters as FiltersConfig;
|
||||
use Config\Format as FormatConfig;
|
||||
use Config\Honeypot as HoneypotConfig;
|
||||
use Config\Images;
|
||||
use Config\Migrations;
|
||||
use Config\Pager as PagerConfig;
|
||||
use Config\Services as AppServices;
|
||||
use Config\Toolbar as ToolbarConfig;
|
||||
use Config\Validation as ValidationConfig;
|
||||
use Config\View as ViewConfig;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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 ?? new Cache();
|
||||
|
||||
return CacheFactory::getHandler($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* The CLI Request class provides for ways to interact with
|
||||
* a command line request.
|
||||
*
|
||||
* @return CLIRequest
|
||||
*/
|
||||
public static function clirequest(?App $config = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('clirequest', $config);
|
||||
}
|
||||
|
||||
$config = $config ?? config('App');
|
||||
|
||||
return new CLIRequest($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* CodeIgniter, the core of the framework.
|
||||
*
|
||||
* @return CodeIgniter
|
||||
*/
|
||||
public static function codeigniter(?App $config = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('codeigniter', $config);
|
||||
}
|
||||
|
||||
$config = $config ?? config('App');
|
||||
|
||||
return new CodeIgniter($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* The commands utility for running and working with CLI commands.
|
||||
*
|
||||
* @return Commands
|
||||
*/
|
||||
public static function commands(bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('commands');
|
||||
}
|
||||
|
||||
return new Commands();
|
||||
}
|
||||
|
||||
/**
|
||||
* The CURL Request class acts as a simple HTTP client for interacting
|
||||
* with other servers, typically through APIs.
|
||||
*
|
||||
* @return CURLRequest
|
||||
*/
|
||||
public static function curlrequest(array $options = [], ?ResponseInterface $response = null, ?App $config = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared === true) {
|
||||
return static::getSharedInstance('curlrequest', $options, $response, $config);
|
||||
}
|
||||
|
||||
$config = $config ?? config('App');
|
||||
$response = $response ?? new Response($config);
|
||||
|
||||
return new CURLRequest(
|
||||
$config,
|
||||
new URI($options['base_uri'] ?? null),
|
||||
$response,
|
||||
$options
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The Email class allows you to send email via mail, sendmail, SMTP.
|
||||
*
|
||||
* @param array|EmailConfig|null $config
|
||||
*
|
||||
* @return Email
|
||||
*/
|
||||
public static function email($config = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('email', $config);
|
||||
}
|
||||
|
||||
if (empty($config) || ! (is_array($config) || $config instanceof EmailConfig)) {
|
||||
$config = config('Email');
|
||||
}
|
||||
|
||||
return new Email($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* The Encryption class provides two-way encryption.
|
||||
*
|
||||
* @param bool $getShared
|
||||
*
|
||||
* @return EncrypterInterface Encryption handler
|
||||
*/
|
||||
public static function encrypter(?EncryptionConfig $config = null, $getShared = false)
|
||||
{
|
||||
if ($getShared === true) {
|
||||
return static::getSharedInstance('encrypter', $config);
|
||||
}
|
||||
|
||||
$config = $config ?? config('Encryption');
|
||||
$encryption = new Encryption($config);
|
||||
|
||||
return $encryption->initialize($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,
|
||||
?IncomingRequest $request = null,
|
||||
?Response $response = null,
|
||||
bool $getShared = true
|
||||
) {
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('exceptions', $config, $request, $response);
|
||||
}
|
||||
|
||||
$config = $config ?? config('Exceptions');
|
||||
$request = $request ?? AppServices::request();
|
||||
$response = $response ?? AppServices::response();
|
||||
|
||||
return new Exceptions($config, $request, $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters allow you to run tasks before and/or after a controller
|
||||
* is executed. During before filters, the request can be modified,
|
||||
* and actions taken based on the request, while after filters can
|
||||
* act on or modify the response itself before it is sent to the client.
|
||||
*
|
||||
* @return Filters
|
||||
*/
|
||||
public static function filters(?FiltersConfig $config = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('filters', $config);
|
||||
}
|
||||
|
||||
$config = $config ?? config('Filters');
|
||||
|
||||
return new Filters($config, AppServices::request(), AppServices::response());
|
||||
}
|
||||
|
||||
/**
|
||||
* The Format class is a convenient place to create Formatters.
|
||||
*
|
||||
* @return Format
|
||||
*/
|
||||
public static function format(?FormatConfig $config = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('format', $config);
|
||||
}
|
||||
|
||||
$config = $config ?? config('Format');
|
||||
|
||||
return new Format($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* The Honeypot provides a secret input on forms that bots should NOT
|
||||
* fill in, providing an additional safeguard when accepting user input.
|
||||
*
|
||||
* @return Honeypot
|
||||
*/
|
||||
public static function honeypot(?HoneypotConfig $config = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('honeypot', $config);
|
||||
}
|
||||
|
||||
$config = $config ?? config('Honeypot');
|
||||
|
||||
return new Honeypot($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Acts as a factory for ImageHandler classes and returns an instance
|
||||
* of the handler. Used like Services::image()->withFile($path)->rotate(90)->save();
|
||||
*
|
||||
* @return BaseHandler
|
||||
*/
|
||||
public static function image(?string $handler = null, ?Images $config = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('image', $handler, $config);
|
||||
}
|
||||
|
||||
$config = $config ?? config('Images');
|
||||
$handler = $handler ?: $config->defaultHandler;
|
||||
$class = $config->handlers[$handler];
|
||||
|
||||
return new $class($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* The Iterator class provides a simple way of looping over a function
|
||||
* and timing the results and memory usage. Used when debugging and
|
||||
* optimizing applications.
|
||||
*
|
||||
* @return Iterator
|
||||
*/
|
||||
public static function iterator(bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('iterator');
|
||||
}
|
||||
|
||||
return new Iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Responsible for loading the language string translations.
|
||||
*
|
||||
* @return Language
|
||||
*/
|
||||
public static function language(?string $locale = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('language', $locale)->setLocale($locale);
|
||||
}
|
||||
|
||||
// Use '?:' for empty string check
|
||||
$locale = $locale ?: AppServices::request()->getLocale();
|
||||
|
||||
return new Language($locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* The Logger class is a PSR-3 compatible Logging class that supports
|
||||
* multiple handlers that process the actual logging.
|
||||
*
|
||||
* @return Logger
|
||||
*/
|
||||
public static function logger(bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('logger');
|
||||
}
|
||||
|
||||
return new Logger(config('Logger'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the appropriate Migration runner.
|
||||
*
|
||||
* @return MigrationRunner
|
||||
*/
|
||||
public static function migrations(?Migrations $config = null, ?ConnectionInterface $db = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('migrations', $config, $db);
|
||||
}
|
||||
|
||||
$config = $config ?? config('Migrations');
|
||||
|
||||
return new MigrationRunner($config, $db);
|
||||
}
|
||||
|
||||
/**
|
||||
* The Negotiate class provides the content negotiation features for
|
||||
* working the request to determine correct language, encoding, charset,
|
||||
* and more.
|
||||
*
|
||||
* @return Negotiate
|
||||
*/
|
||||
public static function negotiator(?RequestInterface $request = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('negotiator', $request);
|
||||
}
|
||||
|
||||
$request = $request ?? AppServices::request();
|
||||
|
||||
return new Negotiate($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the appropriate pagination handler.
|
||||
*
|
||||
* @return Pager
|
||||
*/
|
||||
public static function pager(?PagerConfig $config = null, ?RendererInterface $view = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('pager', $config, $view);
|
||||
}
|
||||
|
||||
$config = $config ?? config('Pager');
|
||||
$view = $view ?? AppServices::renderer();
|
||||
|
||||
return new Pager($config, $view);
|
||||
}
|
||||
|
||||
/**
|
||||
* The Parser is a simple template parser.
|
||||
*
|
||||
* @return Parser
|
||||
*/
|
||||
public static function parser(?string $viewPath = null, ?ViewConfig $config = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('parser', $viewPath, $config);
|
||||
}
|
||||
|
||||
$viewPath = $viewPath ?: config('Paths')->viewDirectory;
|
||||
$config = $config ?? config('View');
|
||||
|
||||
return new Parser($config, $viewPath, AppServices::locator(), CI_DEBUG, AppServices::logger());
|
||||
}
|
||||
|
||||
/**
|
||||
* The Renderer class is the class that actually displays a file to the user.
|
||||
* The default View class within CodeIgniter is intentionally simple, but this
|
||||
* service could easily be replaced by a template engine if the user needed to.
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public static function renderer(?string $viewPath = null, ?ViewConfig $config = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('renderer', $viewPath, $config);
|
||||
}
|
||||
|
||||
$viewPath = $viewPath ?: config('Paths')->viewDirectory;
|
||||
$config = $config ?? config('View');
|
||||
|
||||
return new View($config, $viewPath, AppServices::locator(), CI_DEBUG, AppServices::logger());
|
||||
}
|
||||
|
||||
/**
|
||||
* The Request class models an HTTP request.
|
||||
*
|
||||
* @return IncomingRequest
|
||||
*/
|
||||
public static function request(?App $config = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('request', $config);
|
||||
}
|
||||
|
||||
$config = $config ?? config('App');
|
||||
|
||||
return new IncomingRequest(
|
||||
$config,
|
||||
AppServices::uri(),
|
||||
'php://input',
|
||||
new UserAgent()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The Response class models an HTTP response.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public static function response(?App $config = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('response', $config);
|
||||
}
|
||||
|
||||
$config = $config ?? config('App');
|
||||
|
||||
return new Response($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* The Redirect class provides nice way of working with redirects.
|
||||
*
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public static function redirectresponse(?App $config = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('redirectresponse', $config);
|
||||
}
|
||||
|
||||
$config = $config ?? config('App');
|
||||
$response = new RedirectResponse($config);
|
||||
$response->setProtocolVersion(AppServices::request()->getProtocolVersion());
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Routes service is a class that allows for easily building
|
||||
* a collection of routes.
|
||||
*
|
||||
* @return RouteCollection
|
||||
*/
|
||||
public static function routes(bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('routes');
|
||||
}
|
||||
|
||||
return new RouteCollection(AppServices::locator(), config('Modules'));
|
||||
}
|
||||
|
||||
/**
|
||||
* The Router class uses a RouteCollection's array of routes, and determines
|
||||
* the correct Controller and Method to execute.
|
||||
*
|
||||
* @return Router
|
||||
*/
|
||||
public static function router(?RouteCollectionInterface $routes = null, ?Request $request = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('router', $routes, $request);
|
||||
}
|
||||
|
||||
$routes = $routes ?? AppServices::routes();
|
||||
$request = $request ?? AppServices::request();
|
||||
|
||||
return new Router($routes, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* The Security class provides a few handy tools for keeping the site
|
||||
* secure, most notably the CSRF protection tools.
|
||||
*
|
||||
* @return Security
|
||||
*/
|
||||
public static function security(?App $config = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('security', $config);
|
||||
}
|
||||
|
||||
$config = $config ?? config('App');
|
||||
|
||||
return new Security($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the session manager.
|
||||
*
|
||||
* @return Session
|
||||
*/
|
||||
public static function session(?App $config = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('session', $config);
|
||||
}
|
||||
|
||||
$config = $config ?? config('App');
|
||||
$logger = AppServices::logger();
|
||||
|
||||
$driverName = $config->sessionDriver;
|
||||
$driver = new $driverName($config, AppServices::request()->getIPAddress());
|
||||
$driver->setLogger($logger);
|
||||
|
||||
$session = new Session($driver, $config);
|
||||
$session->setLogger($logger);
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
$session->start();
|
||||
}
|
||||
|
||||
return $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Throttler class provides a simple method for implementing
|
||||
* rate limiting in your applications.
|
||||
*
|
||||
* @return Throttler
|
||||
*/
|
||||
public static function throttler(bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('throttler');
|
||||
}
|
||||
|
||||
return new Throttler(AppServices::cache());
|
||||
}
|
||||
|
||||
/**
|
||||
* The Timer class provides a simple way to Benchmark portions of your
|
||||
* application.
|
||||
*
|
||||
* @return Timer
|
||||
*/
|
||||
public static function timer(bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('timer');
|
||||
}
|
||||
|
||||
return new Timer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the debug toolbar.
|
||||
*
|
||||
* @return Toolbar
|
||||
*/
|
||||
public static function toolbar(?ToolbarConfig $config = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('toolbar', $config);
|
||||
}
|
||||
|
||||
$config = $config ?? config('Toolbar');
|
||||
|
||||
return new Toolbar($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* The URI class provides a way to model and manipulate URIs.
|
||||
*
|
||||
* @param string $uri
|
||||
*
|
||||
* @return URI
|
||||
*/
|
||||
public static function uri(?string $uri = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('uri', $uri);
|
||||
}
|
||||
|
||||
return new URI($uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* The Validation class provides tools for validating input data.
|
||||
*
|
||||
* @return Validation
|
||||
*/
|
||||
public static function validation(?ValidationConfig $config = null, bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('validation', $config);
|
||||
}
|
||||
|
||||
$config = $config ?? config('Validation');
|
||||
|
||||
return new Validation($config, AppServices::renderer());
|
||||
}
|
||||
|
||||
/**
|
||||
* View cells are intended to let you insert HTML into view
|
||||
* that has been generated by any callable in the system.
|
||||
*
|
||||
* @return Cell
|
||||
*/
|
||||
public static function viewcell(bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('viewcell');
|
||||
}
|
||||
|
||||
return new Cell(AppServices::cache());
|
||||
}
|
||||
|
||||
/**
|
||||
* The Typography class provides a way to format text in semantically relevant ways.
|
||||
*
|
||||
* @return Typography
|
||||
*/
|
||||
public static function typography(bool $getShared = true)
|
||||
{
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('typography');
|
||||
}
|
||||
|
||||
return new Typography();
|
||||
}
|
||||
}
|
||||
100
system/Config/View.php
Normal file
100
system/Config/View.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* View configuration
|
||||
*/
|
||||
class View extends BaseConfig
|
||||
{
|
||||
/**
|
||||
* When false, the view method will clear the data between each
|
||||
* call.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $saveData = true;
|
||||
|
||||
/**
|
||||
* Parser Filters map a filter name with any PHP callable. When the
|
||||
* Parser prepares a variable for display, it will chain it
|
||||
* through the filters in the order defined, inserting any parameters.
|
||||
*
|
||||
* To prevent potential abuse, all filters MUST be defined here
|
||||
* in order for them to be available for use within the Parser.
|
||||
*/
|
||||
public $filters = [];
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public $plugins = [];
|
||||
|
||||
/**
|
||||
* Built-in View filters.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $coreFilters = [
|
||||
'abs' => '\abs',
|
||||
'capitalize' => '\CodeIgniter\View\Filters::capitalize',
|
||||
'date' => '\CodeIgniter\View\Filters::date',
|
||||
'date_modify' => '\CodeIgniter\View\Filters::date_modify',
|
||||
'default' => '\CodeIgniter\View\Filters::default',
|
||||
'esc' => '\CodeIgniter\View\Filters::esc',
|
||||
'excerpt' => '\CodeIgniter\View\Filters::excerpt',
|
||||
'highlight' => '\CodeIgniter\View\Filters::highlight',
|
||||
'highlight_code' => '\CodeIgniter\View\Filters::highlight_code',
|
||||
'limit_words' => '\CodeIgniter\View\Filters::limit_words',
|
||||
'limit_chars' => '\CodeIgniter\View\Filters::limit_chars',
|
||||
'local_currency' => '\CodeIgniter\View\Filters::local_currency',
|
||||
'local_number' => '\CodeIgniter\View\Filters::local_number',
|
||||
'lower' => '\strtolower',
|
||||
'nl2br' => '\CodeIgniter\View\Filters::nl2br',
|
||||
'number_format' => '\number_format',
|
||||
'prose' => '\CodeIgniter\View\Filters::prose',
|
||||
'round' => '\CodeIgniter\View\Filters::round',
|
||||
'strip_tags' => '\strip_tags',
|
||||
'title' => '\CodeIgniter\View\Filters::title',
|
||||
'upper' => '\strtoupper',
|
||||
];
|
||||
|
||||
/**
|
||||
* Built-in View plugins.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $corePlugins = [
|
||||
'current_url' => '\CodeIgniter\View\Plugins::currentURL',
|
||||
'previous_url' => '\CodeIgniter\View\Plugins::previousURL',
|
||||
'mailto' => '\CodeIgniter\View\Plugins::mailto',
|
||||
'safe_mailto' => '\CodeIgniter\View\Plugins::safeMailto',
|
||||
'lang' => '\CodeIgniter\View\Plugins::lang',
|
||||
'validation_errors' => '\CodeIgniter\View\Plugins::validationErrors',
|
||||
'route' => '\CodeIgniter\View\Plugins::route',
|
||||
'siteURL' => '\CodeIgniter\View\Plugins::siteURL',
|
||||
];
|
||||
|
||||
/**
|
||||
* Merge the built-in and developer-configured filters and plugins,
|
||||
* with preference to the developer ones.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->filters = array_merge($this->coreFilters, $this->filters);
|
||||
$this->plugins = array_merge($this->corePlugins, $this->plugins);
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user