first commit
This commit is contained in:
215
vendor/yiisoft/yii2/web/Application.php
vendored
Normal file
215
vendor/yiisoft/yii2/web/Application.php
vendored
Normal file
@ -0,0 +1,215 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use Yii;
|
||||
use yii\base\InvalidRouteException;
|
||||
use yii\base\Module;
|
||||
use yii\helpers\Url;
|
||||
|
||||
/**
|
||||
* Application is the base class for all web application classes.
|
||||
*
|
||||
* For more details and usage information on Application, see the [guide article on applications](guide:structure-applications).
|
||||
*
|
||||
* @property-read ErrorHandler $errorHandler The error handler application component.
|
||||
* @property string $homeUrl The homepage URL.
|
||||
* @property-read Request $request The request component.
|
||||
* @property-read Response $response The response component.
|
||||
* @property-read Session $session The session component.
|
||||
* @property-read User $user The user component.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*
|
||||
* @template TUserIdentity of IdentityInterface
|
||||
*
|
||||
* @phpstan-property-read User<TUserIdentity> $user
|
||||
* @psalm-property-read User<TUserIdentity> $user
|
||||
*/
|
||||
class Application extends \yii\base\Application
|
||||
{
|
||||
/**
|
||||
* @var string the default route of this application. Defaults to 'site'.
|
||||
*/
|
||||
public $defaultRoute = 'site';
|
||||
/**
|
||||
* @var array|null the configuration specifying a controller action which should handle
|
||||
* all user requests. This is mainly used when the application is in maintenance mode
|
||||
* and needs to handle all incoming requests via a single action.
|
||||
* The configuration is an array whose first element specifies the route of the action.
|
||||
* The rest of the array elements (key-value pairs) specify the parameters to be bound
|
||||
* to the action. For example,
|
||||
*
|
||||
* ```
|
||||
* [
|
||||
* 'offline/notice',
|
||||
* 'param1' => 'value1',
|
||||
* 'param2' => 'value2',
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* Defaults to null, meaning catch-all is not used.
|
||||
*/
|
||||
public $catchAll;
|
||||
/**
|
||||
* @var Controller|null the currently active controller instance
|
||||
*
|
||||
* @phpstan-var Controller<Module>|null
|
||||
* @psalm-var Controller<Module>|null
|
||||
*/
|
||||
public $controller;
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function bootstrap()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
Yii::setAlias('@webroot', dirname($request->getScriptFile()));
|
||||
Yii::setAlias('@web', $request->getBaseUrl());
|
||||
|
||||
parent::bootstrap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the specified request.
|
||||
* @param Request $request the request to be handled
|
||||
* @return Response the resulting response
|
||||
* @throws NotFoundHttpException if the requested route is invalid
|
||||
*/
|
||||
public function handleRequest($request)
|
||||
{
|
||||
if (empty($this->catchAll)) {
|
||||
try {
|
||||
list($route, $params) = $request->resolve();
|
||||
} catch (UrlNormalizerRedirectException $e) {
|
||||
$url = $e->url;
|
||||
if (is_array($url)) {
|
||||
if (isset($url[0])) {
|
||||
// ensure the route is absolute
|
||||
$url[0] = '/' . ltrim($url[0], '/');
|
||||
}
|
||||
$url += $request->getQueryParams();
|
||||
}
|
||||
|
||||
return $this->getResponse()->redirect(Url::to($url, $e->scheme), $e->statusCode);
|
||||
}
|
||||
} else {
|
||||
$route = $this->catchAll[0];
|
||||
$params = $this->catchAll;
|
||||
unset($params[0]);
|
||||
}
|
||||
try {
|
||||
Yii::debug("Route requested: '$route'", __METHOD__);
|
||||
$this->requestedRoute = $route;
|
||||
$result = $this->runAction($route, $params);
|
||||
if ($result instanceof Response) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$response = $this->getResponse();
|
||||
if ($result !== null) {
|
||||
$response->data = $result;
|
||||
}
|
||||
|
||||
return $response;
|
||||
} catch (InvalidRouteException $e) {
|
||||
throw new NotFoundHttpException(Yii::t('yii', 'Page not found.'), $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
private $_homeUrl;
|
||||
|
||||
/**
|
||||
* @return string the homepage URL
|
||||
*/
|
||||
public function getHomeUrl()
|
||||
{
|
||||
if ($this->_homeUrl === null) {
|
||||
if ($this->getUrlManager()->showScriptName) {
|
||||
return $this->getRequest()->getScriptUrl();
|
||||
}
|
||||
|
||||
return $this->getRequest()->getBaseUrl() . '/';
|
||||
}
|
||||
|
||||
return $this->_homeUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value the homepage URL
|
||||
*/
|
||||
public function setHomeUrl($value)
|
||||
{
|
||||
$this->_homeUrl = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the error handler component.
|
||||
* @return ErrorHandler the error handler application component.
|
||||
*/
|
||||
public function getErrorHandler()
|
||||
{
|
||||
return $this->get('errorHandler');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request component.
|
||||
* @return Request the request component.
|
||||
*/
|
||||
public function getRequest()
|
||||
{
|
||||
return $this->get('request');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the response component.
|
||||
* @return Response the response component.
|
||||
*/
|
||||
public function getResponse()
|
||||
{
|
||||
return $this->get('response');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the session component.
|
||||
* @return Session the session component.
|
||||
*/
|
||||
public function getSession()
|
||||
{
|
||||
return $this->get('session');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user component.
|
||||
* @return User the user component.
|
||||
*
|
||||
* @phpstan-return User<TUserIdentity>
|
||||
* @psalm-return User<TUserIdentity>
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
return $this->get('user');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function coreComponents()
|
||||
{
|
||||
return array_merge(parent::coreComponents(), [
|
||||
'request' => ['class' => 'yii\web\Request'],
|
||||
'response' => ['class' => 'yii\web\Response'],
|
||||
'session' => ['class' => 'yii\web\Session'],
|
||||
'user' => ['class' => 'yii\web\User'],
|
||||
'errorHandler' => ['class' => 'yii\web\ErrorHandler'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
241
vendor/yiisoft/yii2/web/AssetBundle.php
vendored
Normal file
241
vendor/yiisoft/yii2/web/AssetBundle.php
vendored
Normal file
@ -0,0 +1,241 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use Yii;
|
||||
use yii\base\BaseObject;
|
||||
use yii\helpers\ArrayHelper;
|
||||
use yii\helpers\Url;
|
||||
|
||||
/**
|
||||
* AssetBundle represents a collection of asset files, such as CSS, JS, images.
|
||||
*
|
||||
* Each asset bundle has a unique name that globally identifies it among all asset bundles used in an application.
|
||||
* The name is the [fully qualified class name](https://www.php.net/manual/en/language.namespaces.rules.php)
|
||||
* of the class representing it.
|
||||
*
|
||||
* An asset bundle can depend on other asset bundles. When registering an asset bundle
|
||||
* with a view, all its dependent asset bundles will be automatically registered.
|
||||
*
|
||||
* For more details and usage information on AssetBundle, see the [guide article on assets](guide:structure-assets).
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*
|
||||
* @phpstan-import-type RegisterJsFileOptions from View
|
||||
* @psalm-import-type RegisterJsFileOptions from View
|
||||
*
|
||||
* @phpstan-import-type RegisterCssFileOptions from View
|
||||
* @psalm-import-type RegisterCssFileOptions from View
|
||||
*
|
||||
* @phpstan-import-type PublishOptions from AssetManager
|
||||
* @psalm-import-type PublishOptions from AssetManager
|
||||
*/
|
||||
class AssetBundle extends BaseObject
|
||||
{
|
||||
/**
|
||||
* @var string|null the directory that contains the source asset files for this asset bundle.
|
||||
* A source asset file is a file that is part of your source code repository of your Web application.
|
||||
*
|
||||
* You must set this property if the directory containing the source asset files is not Web accessible.
|
||||
* By setting this property, [[AssetManager]] will publish the source asset files
|
||||
* to a Web-accessible directory automatically when the asset bundle is registered on a page.
|
||||
*
|
||||
* If you do not set this property, it means the source asset files are located under [[basePath]].
|
||||
*
|
||||
* You can use either a directory or an alias of the directory.
|
||||
* @see publishOptions
|
||||
*/
|
||||
public $sourcePath;
|
||||
/**
|
||||
* @var string the Web-accessible directory that contains the asset files in this bundle.
|
||||
*
|
||||
* If [[sourcePath]] is set, this property will be *overwritten* by [[AssetManager]]
|
||||
* when it publishes the asset files from [[sourcePath]].
|
||||
*
|
||||
* You can use either a directory or an alias of the directory.
|
||||
*/
|
||||
public $basePath;
|
||||
/**
|
||||
* @var string the base URL for the relative asset files listed in [[js]] and [[css]].
|
||||
*
|
||||
* If [[sourcePath]] is set, this property will be *overwritten* by [[AssetManager]]
|
||||
* when it publishes the asset files from [[sourcePath]].
|
||||
*
|
||||
* You can use either a URL or an alias of the URL.
|
||||
*/
|
||||
public $baseUrl;
|
||||
/**
|
||||
* @var array list of bundle class names that this bundle depends on.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* ```
|
||||
* public $depends = [
|
||||
* 'yii\web\YiiAsset',
|
||||
* 'yii\bootstrap\BootstrapAsset',
|
||||
* ];
|
||||
* ```
|
||||
*
|
||||
* @phpstan-var class-string[]
|
||||
* @psalm-var class-string[]
|
||||
*/
|
||||
public $depends = [];
|
||||
/**
|
||||
* @var array list of JavaScript files that this bundle contains. Each JavaScript file can be
|
||||
* specified in one of the following formats:
|
||||
*
|
||||
* - an absolute URL representing an external asset. For example,
|
||||
* `https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js` or
|
||||
* `//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js`.
|
||||
* - a relative path representing a local asset (e.g. `js/main.js`). The actual file path of a local
|
||||
* asset can be determined by prefixing [[basePath]] to the relative path, and the actual URL
|
||||
* of the asset can be determined by prefixing [[baseUrl]] to the relative path.
|
||||
* - an array, with the first entry being the URL or relative path as described before, and a list of key => value pairs
|
||||
* that will be used to overwrite [[jsOptions]] settings for this entry.
|
||||
* This functionality is available since version 2.0.7.
|
||||
*
|
||||
* Note that only a forward slash "/" should be used as directory separator.
|
||||
*
|
||||
* @phpstan-var (string|array<array-key, mixed>)[]
|
||||
* @psalm-var (string|array<array-key, mixed>)[]
|
||||
*/
|
||||
public $js = [];
|
||||
/**
|
||||
* @var array list of CSS files that this bundle contains. Each CSS file can be specified
|
||||
* in one of the three formats as explained in [[js]].
|
||||
*
|
||||
* Note that only a forward slash "/" should be used as directory separator.
|
||||
*
|
||||
* @phpstan-var (string|array<array-key, mixed>)[]
|
||||
* @psalm-var (string|array<array-key, mixed>)[]
|
||||
*/
|
||||
public $css = [];
|
||||
/**
|
||||
* @var array the options that will be passed to [[View::registerJsFile()]]
|
||||
* when registering the JS files in this bundle.
|
||||
*
|
||||
* @phpstan-var RegisterJsFileOptions
|
||||
* @psalm-var RegisterJsFileOptions
|
||||
*/
|
||||
public $jsOptions = [];
|
||||
/**
|
||||
* @var array the options that will be passed to [[View::registerCssFile()]]
|
||||
* when registering the CSS files in this bundle.
|
||||
*
|
||||
* @phpstan-var RegisterCssFileOptions
|
||||
* @psalm-var RegisterCssFileOptions
|
||||
*/
|
||||
public $cssOptions = [];
|
||||
/**
|
||||
* @var array the options to be passed to [[AssetManager::publish()]] when the asset bundle
|
||||
* is being published. This property is used only when [[sourcePath]] is set.
|
||||
*
|
||||
* @phpstan-var PublishOptions
|
||||
* @psalm-var PublishOptions
|
||||
*/
|
||||
public $publishOptions = [];
|
||||
|
||||
|
||||
/**
|
||||
* Registers this asset bundle with a view.
|
||||
* @param View $view the view to be registered with
|
||||
* @return static the registered asset bundle instance
|
||||
*/
|
||||
public static function register($view)
|
||||
{
|
||||
/** @var static */
|
||||
$result = $view->registerAssetBundle(get_called_class());
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the bundle.
|
||||
* If you override this method, make sure you call the parent implementation in the last.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
if ($this->sourcePath !== null) {
|
||||
$this->sourcePath = rtrim(Yii::getAlias($this->sourcePath), '/\\');
|
||||
}
|
||||
if ($this->basePath !== null) {
|
||||
$this->basePath = rtrim(Yii::getAlias($this->basePath), '/\\');
|
||||
}
|
||||
if ($this->baseUrl !== null) {
|
||||
$this->baseUrl = rtrim(Yii::getAlias($this->baseUrl), '/');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the CSS and JS files with the given view.
|
||||
* @param \yii\web\View $view the view that the asset files are to be registered with.
|
||||
*/
|
||||
public function registerAssetFiles($view)
|
||||
{
|
||||
$manager = $view->getAssetManager();
|
||||
foreach ($this->js as $js) {
|
||||
if (is_array($js)) {
|
||||
$file = array_shift($js);
|
||||
$options = ArrayHelper::merge($this->jsOptions, $js);
|
||||
$view->registerJsFile($manager->getAssetUrl($this, $file, ArrayHelper::getValue($options, 'appendTimestamp')), $options);
|
||||
} elseif ($js !== null) {
|
||||
$view->registerJsFile($manager->getAssetUrl($this, $js), $this->jsOptions);
|
||||
}
|
||||
}
|
||||
foreach ($this->css as $css) {
|
||||
if (is_array($css)) {
|
||||
$file = array_shift($css);
|
||||
$options = ArrayHelper::merge($this->cssOptions, $css);
|
||||
$view->registerCssFile($manager->getAssetUrl($this, $file, ArrayHelper::getValue($options, 'appendTimestamp')), $options);
|
||||
} elseif ($css !== null) {
|
||||
$view->registerCssFile($manager->getAssetUrl($this, $css), $this->cssOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Publishes the asset bundle if its source code is not under Web-accessible directory.
|
||||
* It will also try to convert non-CSS or JS files (e.g. LESS, Sass) into the corresponding
|
||||
* CSS or JS files using [[AssetManager::converter|asset converter]].
|
||||
* @param AssetManager $am the asset manager to perform the asset publishing
|
||||
*/
|
||||
public function publish($am)
|
||||
{
|
||||
if ($this->sourcePath !== null && !isset($this->basePath, $this->baseUrl)) {
|
||||
list($this->basePath, $this->baseUrl) = $am->publish($this->sourcePath, $this->publishOptions);
|
||||
}
|
||||
|
||||
if (isset($this->basePath, $this->baseUrl) && ($converter = $am->getConverter()) !== null) {
|
||||
foreach ($this->js as $i => $js) {
|
||||
if (is_array($js)) {
|
||||
$file = array_shift($js);
|
||||
if (Url::isRelative($file)) {
|
||||
$js = ArrayHelper::merge($this->jsOptions, $js);
|
||||
array_unshift($js, $converter->convert($file, $this->basePath));
|
||||
$this->js[$i] = $js;
|
||||
}
|
||||
} elseif (Url::isRelative($js)) {
|
||||
$this->js[$i] = $converter->convert($js, $this->basePath);
|
||||
}
|
||||
}
|
||||
foreach ($this->css as $i => $css) {
|
||||
if (is_array($css)) {
|
||||
$file = array_shift($css);
|
||||
if (Url::isRelative($file)) {
|
||||
$css = ArrayHelper::merge($this->cssOptions, $css);
|
||||
array_unshift($css, $converter->convert($file, $this->basePath));
|
||||
$this->css[$i] = $css;
|
||||
}
|
||||
} elseif (Url::isRelative($css)) {
|
||||
$this->css[$i] = $converter->convert($css, $this->basePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
126
vendor/yiisoft/yii2/web/AssetConverter.php
vendored
Normal file
126
vendor/yiisoft/yii2/web/AssetConverter.php
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Component;
|
||||
use yii\base\Exception;
|
||||
|
||||
/**
|
||||
* AssetConverter supports conversion of several popular formats into JS or CSS files.
|
||||
*
|
||||
* It is used by [[AssetManager]] to convert files after they have been published.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class AssetConverter extends Component implements AssetConverterInterface
|
||||
{
|
||||
/**
|
||||
* @var array the commands that are used to perform the asset conversion.
|
||||
* The keys are the asset file extension names, and the values are the corresponding
|
||||
* target script types (either "css" or "js") and the commands used for the conversion.
|
||||
*
|
||||
* The command placeholders: `{from}` - source file, `{to}` - converted file.
|
||||
*
|
||||
* You may also use a [path alias](guide:concept-aliases) to specify the location of the command:
|
||||
*
|
||||
* ```
|
||||
* [
|
||||
* 'styl' => ['css', '@app/node_modules/bin/stylus < {from} > {to}'],
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* Note: `Yii::getAlias()` can replace alias at the begin of the command only.
|
||||
*
|
||||
* @see https://sass-lang.com/documentation/cli/ SASS/SCSS
|
||||
*/
|
||||
public $commands = [
|
||||
'less' => ['css', 'lessc {from} {to} --no-color --source-map'],
|
||||
'scss' => ['css', 'sass --style=compressed {from} {to}'],
|
||||
'sass' => ['css', 'sass --style=compressed {from} {to}'],
|
||||
'styl' => ['css', 'stylus < {from} > {to}'],
|
||||
'coffee' => ['js', 'coffee -p {from} > {to}'],
|
||||
'ts' => ['js', 'tsc --out {to} {from}'],
|
||||
];
|
||||
/**
|
||||
* @var bool whether the source asset file should be converted even if its result already exists.
|
||||
* You may want to set this to be `true` during the development stage to make sure the converted
|
||||
* assets are always up-to-date. Do not set this to true on production servers as it will
|
||||
* significantly degrade the performance.
|
||||
*/
|
||||
public $forceConvert = false;
|
||||
|
||||
|
||||
/**
|
||||
* Converts a given asset file into a CSS or JS file.
|
||||
* @param string $asset the asset file path, relative to $basePath
|
||||
* @param string $basePath the directory the $asset is relative to.
|
||||
* @return string the converted asset file path, relative to $basePath.
|
||||
*/
|
||||
public function convert($asset, $basePath)
|
||||
{
|
||||
$pos = strrpos($asset, '.');
|
||||
if ($pos !== false) {
|
||||
$ext = substr($asset, $pos + 1);
|
||||
if (isset($this->commands[$ext])) {
|
||||
list($ext, $command) = $this->commands[$ext];
|
||||
$result = substr($asset, 0, $pos + 1) . $ext;
|
||||
if ($this->forceConvert || @filemtime("$basePath/$result") < @filemtime("$basePath/$asset")) {
|
||||
$this->runCommand($command, $basePath, $asset, $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
return $asset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a command to convert asset files.
|
||||
* @param string $command the command to run. If prefixed with an `@` it will be treated as a [path alias](guide:concept-aliases).
|
||||
* @param string $basePath asset base path and command working directory
|
||||
* @param string $asset the name of the asset file
|
||||
* @param string $result the name of the file to be generated by the converter command
|
||||
* @return bool true on success, false on failure. Failures will be logged.
|
||||
* @throws \yii\base\Exception when the command fails and YII_DEBUG is true.
|
||||
* In production mode the error will be logged.
|
||||
*/
|
||||
protected function runCommand($command, $basePath, $asset, $result)
|
||||
{
|
||||
$command = Yii::getAlias($command);
|
||||
|
||||
$command = strtr($command, [
|
||||
'{from}' => escapeshellarg("$basePath/$asset"),
|
||||
'{to}' => escapeshellarg("$basePath/$result"),
|
||||
]);
|
||||
$descriptor = [
|
||||
1 => ['pipe', 'w'],
|
||||
2 => ['pipe', 'w'],
|
||||
];
|
||||
$pipes = [];
|
||||
$proc = proc_open($command, $descriptor, $pipes, $basePath);
|
||||
$stdout = stream_get_contents($pipes[1]);
|
||||
$stderr = stream_get_contents($pipes[2]);
|
||||
foreach ($pipes as $pipe) {
|
||||
fclose($pipe);
|
||||
}
|
||||
$status = proc_close($proc);
|
||||
|
||||
if ($status === 0) {
|
||||
Yii::debug("Converted $asset into $result:\nSTDOUT:\n$stdout\nSTDERR:\n$stderr", __METHOD__);
|
||||
} elseif (YII_DEBUG) {
|
||||
throw new Exception("AssetConverter command '$command' failed with exit code $status:\nSTDOUT:\n$stdout\nSTDERR:\n$stderr");
|
||||
} else {
|
||||
Yii::error("AssetConverter command '$command' failed with exit code $status:\nSTDOUT:\n$stdout\nSTDERR:\n$stderr", __METHOD__);
|
||||
}
|
||||
|
||||
return $status === 0;
|
||||
}
|
||||
}
|
||||
25
vendor/yiisoft/yii2/web/AssetConverterInterface.php
vendored
Normal file
25
vendor/yiisoft/yii2/web/AssetConverterInterface.php
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* The AssetConverterInterface must be implemented by asset converter classes.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
interface AssetConverterInterface
|
||||
{
|
||||
/**
|
||||
* Converts a given asset file into a CSS or JS file.
|
||||
* @param string $asset the asset file path, relative to $basePath
|
||||
* @param string $basePath the directory the $asset is relative to.
|
||||
* @return string the converted asset file path, relative to $basePath.
|
||||
*/
|
||||
public function convert($asset, $basePath);
|
||||
}
|
||||
703
vendor/yiisoft/yii2/web/AssetManager.php
vendored
Normal file
703
vendor/yiisoft/yii2/web/AssetManager.php
vendored
Normal file
@ -0,0 +1,703 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Component;
|
||||
use yii\base\InvalidArgumentException;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\helpers\FileHelper;
|
||||
use yii\helpers\Url;
|
||||
|
||||
/**
|
||||
* AssetManager manages asset bundle configuration and loading.
|
||||
*
|
||||
* AssetManager is configured as an application component in [[\yii\web\Application]] by default.
|
||||
* You can access that instance via `Yii::$app->assetManager`.
|
||||
*
|
||||
* You can modify its configuration by adding an array to your application config under `components`
|
||||
* as shown in the following example:
|
||||
*
|
||||
* ```
|
||||
* 'assetManager' => [
|
||||
* 'bundles' => [
|
||||
* // you can override AssetBundle configs here
|
||||
* ],
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* For more details and usage information on AssetManager, see the [guide article on assets](guide:structure-assets).
|
||||
*
|
||||
* @property AssetConverterInterface $converter The asset converter. Note that the type of this property
|
||||
* differs in getter and setter. See [[getConverter()]] and [[setConverter()]] for details.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*
|
||||
* @phpstan-type PublishOptions array{
|
||||
* only?: string[],
|
||||
* except?: string[],
|
||||
* caseSensitive?: bool,
|
||||
* beforeCopy?: callable,
|
||||
* afterCopy?: callable,
|
||||
* forceCopy?: bool,
|
||||
* }
|
||||
*
|
||||
* @psalm-type PublishOptions = array{
|
||||
* only?: string[],
|
||||
* except?: string[],
|
||||
* caseSensitive?: bool,
|
||||
* beforeCopy?: callable,
|
||||
* afterCopy?: callable,
|
||||
* forceCopy?: bool,
|
||||
* }
|
||||
*/
|
||||
class AssetManager extends Component
|
||||
{
|
||||
/**
|
||||
* @var array|false list of asset bundle configurations. This property is provided to customize asset bundles.
|
||||
* When a bundle is being loaded by [[getBundle()]], if it has a corresponding configuration specified here,
|
||||
* the configuration will be applied to the bundle.
|
||||
*
|
||||
* The array keys are the asset bundle names, which typically are asset bundle class names without leading backslash.
|
||||
* The array values are the corresponding configurations. If a value is false, it means the corresponding asset
|
||||
* bundle is disabled and [[getBundle()]] should return null.
|
||||
*
|
||||
* If this property is false, it means the whole asset bundle feature is disabled and [[getBundle()]]
|
||||
* will always return null.
|
||||
*
|
||||
* The following example shows how to disable the bootstrap css file used by Bootstrap widgets
|
||||
* (because you want to use your own styles):
|
||||
*
|
||||
* ```
|
||||
* [
|
||||
* 'yii\bootstrap\BootstrapAsset' => [
|
||||
* 'css' => [],
|
||||
* ],
|
||||
* ]
|
||||
* ```
|
||||
*/
|
||||
public $bundles = [];
|
||||
/**
|
||||
* @var string the root directory storing the published asset files.
|
||||
*/
|
||||
public $basePath = '@webroot/assets';
|
||||
/**
|
||||
* @var string the base URL through which the published asset files can be accessed.
|
||||
*/
|
||||
public $baseUrl = '@web/assets';
|
||||
/**
|
||||
* @var string[] mapping from source asset files (keys) to target asset files (values).
|
||||
*
|
||||
* This property is provided to support fixing incorrect asset file paths in some asset bundles.
|
||||
* When an asset bundle is registered with a view, each relative asset file in its [[AssetBundle::css|css]]
|
||||
* and [[AssetBundle::js|js]] arrays will be examined against this map. If any of the keys is found
|
||||
* to be the last part of an asset file (which is prefixed with [[AssetBundle::sourcePath]] if available),
|
||||
* the corresponding value will replace the asset and be registered with the view.
|
||||
* For example, an asset file `my/path/to/jquery.js` matches a key `jquery.js`.
|
||||
*
|
||||
* Note that the target asset files should be absolute URLs, domain relative URLs (starting from '/') or paths
|
||||
* relative to [[baseUrl]] and [[basePath]].
|
||||
*
|
||||
* In the following example, any assets ending with `jquery.min.js` will be replaced with `jquery/dist/jquery.js`
|
||||
* which is relative to [[baseUrl]] and [[basePath]].
|
||||
*
|
||||
* ```
|
||||
* [
|
||||
* 'jquery.min.js' => 'jquery/dist/jquery.js',
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* You may also use aliases while specifying map value, for example:
|
||||
*
|
||||
* ```
|
||||
* [
|
||||
* 'jquery.min.js' => '@web/js/jquery/jquery.js',
|
||||
* ]
|
||||
* ```
|
||||
*/
|
||||
public $assetMap = [];
|
||||
/**
|
||||
* @var bool whether to use symbolic link to publish asset files. Defaults to false, meaning
|
||||
* asset files are copied to [[basePath]]. Using symbolic links has the benefit that the published
|
||||
* assets will always be consistent with the source assets and there is no copy operation required.
|
||||
* This is especially useful during development.
|
||||
*
|
||||
* However, there are special requirements for hosting environments in order to use symbolic links.
|
||||
* In particular, symbolic links are supported only on Linux/Unix, and Windows Vista/2008 or greater.
|
||||
*
|
||||
* Moreover, some Web servers need to be properly configured so that the linked assets are accessible
|
||||
* to Web users. For example, for Apache Web server, the following configuration directive should be added
|
||||
* for the Web folder:
|
||||
*
|
||||
* ```
|
||||
* Options FollowSymLinks
|
||||
* ```
|
||||
*/
|
||||
public $linkAssets = false;
|
||||
/**
|
||||
* @var int|null the permission to be set for newly published asset files.
|
||||
* This value will be used by PHP chmod() function. No umask will be applied.
|
||||
* If not set, the permission will be determined by the current environment.
|
||||
*/
|
||||
public $fileMode;
|
||||
/**
|
||||
* @var int the permission to be set for newly generated asset directories.
|
||||
* This value will be used by PHP chmod() function. No umask will be applied.
|
||||
* Defaults to 0775, meaning the directory is read-writable by owner and group,
|
||||
* but read-only for other users.
|
||||
*/
|
||||
public $dirMode = 0775;
|
||||
/**
|
||||
* @var callable|null a PHP callback that is called before copying each sub-directory or file.
|
||||
* This option is used only when publishing a directory. If the callback returns false, the copy
|
||||
* operation for the sub-directory or file will be cancelled.
|
||||
*
|
||||
* The signature of the callback should be: `function ($from, $to)`, where `$from` is the sub-directory or
|
||||
* file to be copied from, while `$to` is the copy target.
|
||||
*
|
||||
* This is passed as a parameter `beforeCopy` to [[\yii\helpers\FileHelper::copyDirectory()]].
|
||||
*/
|
||||
public $beforeCopy;
|
||||
/**
|
||||
* @var callable|null a PHP callback that is called after a sub-directory or file is successfully copied.
|
||||
* This option is used only when publishing a directory. The signature of the callback is the same as
|
||||
* for [[beforeCopy]].
|
||||
* This is passed as a parameter `afterCopy` to [[\yii\helpers\FileHelper::copyDirectory()]].
|
||||
*/
|
||||
public $afterCopy;
|
||||
/**
|
||||
* @var bool whether the directory being published should be copied even if
|
||||
* it is found in the target directory. This option is used only when publishing a directory.
|
||||
* You may want to set this to be `true` during the development stage to make sure the published
|
||||
* directory is always up-to-date. Do not set this to true on production servers as it will
|
||||
* significantly degrade the performance.
|
||||
*/
|
||||
public $forceCopy = false;
|
||||
/**
|
||||
* @var bool whether to append a timestamp to the URL of every published asset. When this is true,
|
||||
* the URL of a published asset may look like `/path/to/asset?v=timestamp`, where `timestamp` is the
|
||||
* last modification time of the published asset file.
|
||||
* You normally would want to set this property to true when you have enabled HTTP caching for assets,
|
||||
* because it allows you to bust caching when the assets are updated.
|
||||
* @since 2.0.3
|
||||
*/
|
||||
public $appendTimestamp = false;
|
||||
/**
|
||||
* @var callable|null a callback that will be called to produce hash for asset directory generation.
|
||||
* The signature of the callback should be as follows:
|
||||
*
|
||||
* ```
|
||||
* function ($path)
|
||||
* ```
|
||||
*
|
||||
* where `$path` is the asset path. Note that the `$path` can be either directory where the asset
|
||||
* files reside or a single file. For a CSS file that uses relative path in `url()`, the hash
|
||||
* implementation should use the directory path of the file instead of the file path to include
|
||||
* the relative asset files in the copying.
|
||||
*
|
||||
* If this is not set, the asset manager will use the default CRC32 and filemtime in the `hash`
|
||||
* method.
|
||||
*
|
||||
* Example of an implementation using MD4 hash:
|
||||
*
|
||||
* ```
|
||||
* function ($path) {
|
||||
* return hash('md4', $path);
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @since 2.0.6
|
||||
*/
|
||||
public $hashCallback;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $_dummyBundles = [];
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the component.
|
||||
* @throws InvalidConfigException if [[basePath]] does not exist.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
$this->basePath = Yii::getAlias($this->basePath);
|
||||
|
||||
$this->basePath = realpath($this->basePath);
|
||||
$this->baseUrl = rtrim(Yii::getAlias($this->baseUrl), '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* @var bool|null
|
||||
*/
|
||||
private $_isBasePathPermissionChecked;
|
||||
|
||||
/**
|
||||
* Check whether the basePath exists and is writeable.
|
||||
*
|
||||
* @since 2.0.40
|
||||
*/
|
||||
public function checkBasePathPermission()
|
||||
{
|
||||
// if the check is been done already, skip further checks
|
||||
if ($this->_isBasePathPermissionChecked) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_dir($this->basePath)) {
|
||||
throw new InvalidConfigException("The directory does not exist: {$this->basePath}");
|
||||
}
|
||||
|
||||
if (!is_writable($this->basePath)) {
|
||||
throw new InvalidConfigException("The directory is not writable by the Web process: {$this->basePath}");
|
||||
}
|
||||
|
||||
$this->_isBasePathPermissionChecked = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the named asset bundle.
|
||||
*
|
||||
* This method will first look for the bundle in [[bundles]]. If not found,
|
||||
* it will treat `$name` as the class of the asset bundle and create a new instance of it.
|
||||
*
|
||||
* @param string $name the class name of the asset bundle (without the leading backslash)
|
||||
* @param bool $publish whether to publish the asset files in the asset bundle before it is returned.
|
||||
* If you set this false, you must manually call `AssetBundle::publish()` to publish the asset files.
|
||||
* @return AssetBundle the asset bundle instance
|
||||
* @throws InvalidConfigException if $name does not refer to a valid asset bundle
|
||||
*/
|
||||
public function getBundle($name, $publish = true)
|
||||
{
|
||||
if ($this->bundles === false) {
|
||||
return $this->loadDummyBundle($name);
|
||||
} elseif (!isset($this->bundles[$name])) {
|
||||
return $this->bundles[$name] = $this->loadBundle($name, [], $publish);
|
||||
} elseif ($this->bundles[$name] instanceof AssetBundle) {
|
||||
return $this->bundles[$name];
|
||||
} elseif (is_array($this->bundles[$name])) {
|
||||
return $this->bundles[$name] = $this->loadBundle($name, $this->bundles[$name], $publish);
|
||||
} elseif ($this->bundles[$name] === false) {
|
||||
return $this->loadDummyBundle($name);
|
||||
}
|
||||
|
||||
throw new InvalidConfigException("Invalid asset bundle configuration: $name");
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads asset bundle class by name.
|
||||
*
|
||||
* @param string $name bundle name
|
||||
* @param array $config bundle object configuration
|
||||
* @param bool $publish if bundle should be published
|
||||
* @return AssetBundle
|
||||
* @throws InvalidConfigException if configuration isn't valid
|
||||
*/
|
||||
protected function loadBundle($name, $config = [], $publish = true)
|
||||
{
|
||||
if (!isset($config['class'])) {
|
||||
$config['class'] = $name;
|
||||
}
|
||||
/** @var AssetBundle $bundle */
|
||||
$bundle = Yii::createObject($config);
|
||||
if ($publish) {
|
||||
$bundle->publish($this);
|
||||
}
|
||||
|
||||
return $bundle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads dummy bundle by name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return AssetBundle
|
||||
*/
|
||||
protected function loadDummyBundle($name)
|
||||
{
|
||||
if (!isset($this->_dummyBundles[$name])) {
|
||||
$bundle = Yii::createObject(['class' => $name]);
|
||||
$bundle->sourcePath = null;
|
||||
$bundle->js = [];
|
||||
$bundle->css = [];
|
||||
|
||||
$this->_dummyBundles[$name] = $bundle;
|
||||
}
|
||||
|
||||
return $this->_dummyBundles[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual URL for the specified asset.
|
||||
* The actual URL is obtained by prepending either [[AssetBundle::$baseUrl]] or [[AssetManager::$baseUrl]] to the given asset path.
|
||||
* @param AssetBundle $bundle the asset bundle which the asset file belongs to
|
||||
* @param string $asset the asset path. This should be one of the assets listed in [[AssetBundle::$js]] or [[AssetBundle::$css]].
|
||||
* @param bool|null $appendTimestamp Whether to append timestamp to the URL.
|
||||
* @return string the actual URL for the specified asset.
|
||||
*/
|
||||
public function getAssetUrl($bundle, $asset, $appendTimestamp = null)
|
||||
{
|
||||
$assetUrl = $this->getActualAssetUrl($bundle, $asset);
|
||||
$assetPath = $this->getAssetPath($bundle, $asset);
|
||||
|
||||
$withTimestamp = $this->appendTimestamp;
|
||||
if ($appendTimestamp !== null) {
|
||||
$withTimestamp = $appendTimestamp;
|
||||
}
|
||||
|
||||
if ($withTimestamp && $assetPath && ($timestamp = @filemtime($assetPath)) > 0) {
|
||||
return "$assetUrl?v=$timestamp";
|
||||
}
|
||||
|
||||
return $assetUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual file path for the specified asset.
|
||||
* @param AssetBundle $bundle the asset bundle which the asset file belongs to
|
||||
* @param string $asset the asset path. This should be one of the assets listed in [[AssetBundle::$js]] or [[AssetBundle::$css]].
|
||||
* @return string|false the actual file path, or `false` if the asset is specified as an absolute URL
|
||||
*/
|
||||
public function getAssetPath($bundle, $asset)
|
||||
{
|
||||
if (($actualAsset = $this->resolveAsset($bundle, $asset)) !== false) {
|
||||
return Url::isRelative($actualAsset) ? $this->basePath . '/' . $actualAsset : false;
|
||||
}
|
||||
|
||||
return Url::isRelative($asset) ? $bundle->basePath . '/' . $asset : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AssetBundle $bundle
|
||||
* @param string $asset
|
||||
* @return string|false
|
||||
*/
|
||||
protected function resolveAsset($bundle, $asset)
|
||||
{
|
||||
if (isset($this->assetMap[$asset])) {
|
||||
return $this->assetMap[$asset];
|
||||
}
|
||||
if ($bundle->sourcePath !== null && Url::isRelative($asset)) {
|
||||
$asset = $bundle->sourcePath . '/' . $asset;
|
||||
}
|
||||
|
||||
$n = mb_strlen($asset, Yii::$app->charset);
|
||||
foreach ($this->assetMap as $from => $to) {
|
||||
$n2 = mb_strlen($from, Yii::$app->charset);
|
||||
if ($n2 <= $n && substr_compare($asset, $from, $n - $n2, $n2) === 0) {
|
||||
return $to;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var AssetConverterInterface
|
||||
*/
|
||||
private $_converter;
|
||||
|
||||
/**
|
||||
* Returns the asset converter.
|
||||
* @return AssetConverterInterface the asset converter.
|
||||
*/
|
||||
public function getConverter()
|
||||
{
|
||||
if ($this->_converter === null) {
|
||||
$this->_converter = Yii::createObject(AssetConverter::className());
|
||||
} elseif (is_array($this->_converter) || is_string($this->_converter)) {
|
||||
if (is_array($this->_converter) && !isset($this->_converter['class'])) {
|
||||
$this->_converter['class'] = AssetConverter::className();
|
||||
}
|
||||
$this->_converter = Yii::createObject($this->_converter);
|
||||
}
|
||||
|
||||
return $this->_converter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the asset converter.
|
||||
* @param array|AssetConverterInterface $value the asset converter. This can be either
|
||||
* an object implementing the [[AssetConverterInterface]], or a configuration
|
||||
* array that can be used to create the asset converter object.
|
||||
*/
|
||||
public function setConverter($value)
|
||||
{
|
||||
$this->_converter = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var array published assets
|
||||
*/
|
||||
private $_published = [];
|
||||
|
||||
/**
|
||||
* Publishes a file or a directory.
|
||||
*
|
||||
* This method will copy the specified file or directory to [[basePath]] so that
|
||||
* it can be accessed via the Web server.
|
||||
*
|
||||
* If the asset is a file, its file modification time will be checked to avoid
|
||||
* unnecessary file copying.
|
||||
*
|
||||
* If the asset is a directory, all files and subdirectories under it will be published recursively.
|
||||
* Note, in case $forceCopy is false the method only checks the existence of the target
|
||||
* directory to avoid repetitive copying (which is very expensive).
|
||||
*
|
||||
* By default, when publishing a directory, subdirectories and files whose name starts with a dot "."
|
||||
* will NOT be published. If you want to change this behavior, you may specify the "beforeCopy" option
|
||||
* as explained in the `$options` parameter.
|
||||
*
|
||||
* Note: On rare scenario, a race condition can develop that will lead to a
|
||||
* one-time-manifestation of a non-critical problem in the creation of the directory
|
||||
* that holds the published assets. This problem can be avoided altogether by 'requesting'
|
||||
* in advance all the resources that are supposed to trigger a 'publish()' call, and doing
|
||||
* that in the application deployment phase, before system goes live. See more in the following
|
||||
* discussion: https://code.google.com/archive/p/yii/issues/2579
|
||||
*
|
||||
* @param string $path the asset (file or directory) to be published
|
||||
* @param array $options the options to be applied when publishing a directory.
|
||||
* The following options are supported:
|
||||
*
|
||||
* - only: array, list of patterns that the file paths should match if they want to be copied.
|
||||
* - except: array, list of patterns that the files or directories should match if they want to be excluded from being copied.
|
||||
* - caseSensitive: boolean, whether patterns specified at "only" or "except" should be case sensitive. Defaults to true.
|
||||
* - beforeCopy: callback, a PHP callback that is called before copying each sub-directory or file.
|
||||
* This overrides [[beforeCopy]] if set.
|
||||
* - afterCopy: callback, a PHP callback that is called after a sub-directory or file is successfully copied.
|
||||
* This overrides [[afterCopy]] if set.
|
||||
* - forceCopy: boolean, whether the directory being published should be copied even if
|
||||
* it is found in the target directory. This option is used only when publishing a directory.
|
||||
* This overrides [[forceCopy]] if set.
|
||||
*
|
||||
* @return array the path (directory or file path) and the URL that the asset is published as.
|
||||
* @throws InvalidArgumentException if the asset to be published does not exist.
|
||||
* @throws InvalidConfigException if the target directory [[basePath]] is not writeable.
|
||||
*
|
||||
* @phpstan-param PublishOptions $options
|
||||
* @psalm-param PublishOptions $options
|
||||
*/
|
||||
public function publish($path, $options = [])
|
||||
{
|
||||
$path = Yii::getAlias($path);
|
||||
|
||||
if (isset($this->_published[$path])) {
|
||||
return $this->_published[$path];
|
||||
}
|
||||
|
||||
if (!is_string($path) || ($src = realpath($path)) === false) {
|
||||
throw new InvalidArgumentException("The file or directory to be published does not exist: $path");
|
||||
}
|
||||
|
||||
if (!is_readable($path)) {
|
||||
throw new InvalidArgumentException("The file or directory to be published is not readable: $path");
|
||||
}
|
||||
|
||||
if (is_file($src)) {
|
||||
return $this->_published[$path] = $this->publishFile($src);
|
||||
}
|
||||
|
||||
return $this->_published[$path] = $this->publishDirectory($src, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publishes a file.
|
||||
* @param string $src the asset file to be published
|
||||
* @return string[] the path and the URL that the asset is published as.
|
||||
* @throws InvalidArgumentException if the asset to be published does not exist.
|
||||
*/
|
||||
protected function publishFile($src)
|
||||
{
|
||||
$this->checkBasePathPermission();
|
||||
|
||||
$dir = $this->hash($src);
|
||||
$fileName = basename($src);
|
||||
$dstDir = $this->basePath . DIRECTORY_SEPARATOR . $dir;
|
||||
$dstFile = $dstDir . DIRECTORY_SEPARATOR . $fileName;
|
||||
|
||||
if (!is_dir($dstDir)) {
|
||||
FileHelper::createDirectory($dstDir, $this->dirMode, true);
|
||||
}
|
||||
|
||||
if ($this->linkAssets) {
|
||||
if (!is_file($dstFile)) {
|
||||
try { // fix #6226 symlinking multi threaded
|
||||
symlink($src, $dstFile);
|
||||
} catch (\Exception $e) {
|
||||
if (!is_file($dstFile)) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif (@filemtime($dstFile) < @filemtime($src)) {
|
||||
copy($src, $dstFile);
|
||||
if ($this->fileMode !== null) {
|
||||
@chmod($dstFile, $this->fileMode);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->appendTimestamp && ($timestamp = @filemtime($dstFile)) > 0) {
|
||||
$fileName = $fileName . "?v=$timestamp";
|
||||
}
|
||||
|
||||
return [$dstFile, $this->baseUrl . "/$dir/$fileName"];
|
||||
}
|
||||
|
||||
/**
|
||||
* Publishes a directory.
|
||||
* @param string $src the asset directory to be published
|
||||
* @param array $options the options to be applied when publishing a directory.
|
||||
* The following options are supported:
|
||||
*
|
||||
* - only: array, list of patterns that the file paths should match if they want to be copied.
|
||||
* - except: array, list of patterns that the files or directories should match if they want to be excluded from being copied.
|
||||
* - caseSensitive: boolean, whether patterns specified at "only" or "except" should be case sensitive. Defaults to true.
|
||||
* - beforeCopy: callback, a PHP callback that is called before copying each sub-directory or file.
|
||||
* This overrides [[beforeCopy]] if set.
|
||||
* - afterCopy: callback, a PHP callback that is called after a sub-directory or file is successfully copied.
|
||||
* This overrides [[afterCopy]] if set.
|
||||
* - forceCopy: boolean, whether the directory being published should be copied even if
|
||||
* it is found in the target directory. This option is used only when publishing a directory.
|
||||
* This overrides [[forceCopy]] if set.
|
||||
*
|
||||
* @return string[] the path directory and the URL that the asset is published as.
|
||||
* @throws InvalidArgumentException if the asset to be published does not exist.
|
||||
*/
|
||||
protected function publishDirectory($src, $options)
|
||||
{
|
||||
$this->checkBasePathPermission();
|
||||
|
||||
$dir = $this->hash($src);
|
||||
$dstDir = $this->basePath . DIRECTORY_SEPARATOR . $dir;
|
||||
if ($this->linkAssets) {
|
||||
if (!is_dir($dstDir)) {
|
||||
FileHelper::createDirectory(dirname($dstDir), $this->dirMode, true);
|
||||
try { // fix #6226 symlinking multi threaded
|
||||
symlink($src, $dstDir);
|
||||
} catch (\Exception $e) {
|
||||
if (!is_dir($dstDir)) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif (!empty($options['forceCopy']) || ($this->forceCopy && !isset($options['forceCopy'])) || !is_dir($dstDir)) {
|
||||
$opts = array_merge(
|
||||
$options,
|
||||
[
|
||||
'dirMode' => $this->dirMode,
|
||||
'fileMode' => $this->fileMode,
|
||||
'copyEmptyDirectories' => false,
|
||||
]
|
||||
);
|
||||
if (!isset($opts['beforeCopy'])) {
|
||||
if ($this->beforeCopy !== null) {
|
||||
$opts['beforeCopy'] = $this->beforeCopy;
|
||||
} else {
|
||||
$opts['beforeCopy'] = function ($from, $to) {
|
||||
return strncmp(basename($from), '.', 1) !== 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
if (!isset($opts['afterCopy']) && $this->afterCopy !== null) {
|
||||
$opts['afterCopy'] = $this->afterCopy;
|
||||
}
|
||||
FileHelper::copyDirectory($src, $dstDir, $opts);
|
||||
}
|
||||
|
||||
return [$dstDir, $this->baseUrl . '/' . $dir];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the published path of a file path.
|
||||
* This method does not perform any publishing. It merely tells you
|
||||
* if the file or directory is published, where it will go.
|
||||
* @param string $path directory or file path being published
|
||||
* @return string|false string the published file path. False if the file or directory does not exist
|
||||
*/
|
||||
public function getPublishedPath($path)
|
||||
{
|
||||
$path = Yii::getAlias($path);
|
||||
|
||||
if (isset($this->_published[$path])) {
|
||||
return $this->_published[$path][0];
|
||||
}
|
||||
if (is_string($path) && ($path = realpath($path)) !== false) {
|
||||
return $this->basePath . DIRECTORY_SEPARATOR . $this->hash($path) . (is_file($path) ? DIRECTORY_SEPARATOR . basename($path) : '');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL of a published file path.
|
||||
* This method does not perform any publishing. It merely tells you
|
||||
* if the file path is published, what the URL will be to access it.
|
||||
* @param string $path directory or file path being published
|
||||
* @return string|false string the published URL for the file or directory. False if the file or directory does not exist.
|
||||
*/
|
||||
public function getPublishedUrl($path)
|
||||
{
|
||||
$path = Yii::getAlias($path);
|
||||
|
||||
if (isset($this->_published[$path])) {
|
||||
return $this->_published[$path][1];
|
||||
}
|
||||
if (is_string($path) && ($path = realpath($path)) !== false) {
|
||||
return $this->baseUrl . '/' . $this->hash($path) . (is_file($path) ? '/' . basename($path) : '');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a CRC32 hash for the directory path. Collisions are higher
|
||||
* than MD5 but generates a much smaller hash string.
|
||||
* @param string $path string to be hashed.
|
||||
* @return string hashed string.
|
||||
*/
|
||||
protected function hash($path)
|
||||
{
|
||||
if (is_callable($this->hashCallback)) {
|
||||
return call_user_func($this->hashCallback, $path);
|
||||
}
|
||||
$path = (is_file($path) ? dirname($path) : $path) . filemtime($path);
|
||||
return sprintf('%x', crc32($path . Yii::getVersion() . '|' . $this->linkAssets));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual URL for the specified asset. Without parameters.
|
||||
* The actual URL is obtained by prepending either [[AssetBundle::$baseUrl]] or [[AssetManager::$baseUrl]] to the given asset path.
|
||||
* @param AssetBundle $bundle the asset bundle which the asset file belongs to
|
||||
* @param string $asset the asset path. This should be one of the assets listed in [[AssetBundle::$js]] or [[AssetBundle::$css]].
|
||||
* @return string the actual URL for the specified asset.
|
||||
* @since 2.0.39
|
||||
*/
|
||||
public function getActualAssetUrl($bundle, $asset)
|
||||
{
|
||||
if (($actualAsset = $this->resolveAsset($bundle, $asset)) !== false) {
|
||||
if (strncmp($actualAsset, '@web/', 5) === 0) {
|
||||
$asset = substr($actualAsset, 5);
|
||||
$baseUrl = Yii::getAlias('@web');
|
||||
} else {
|
||||
$asset = Yii::getAlias($actualAsset);
|
||||
$baseUrl = $this->baseUrl;
|
||||
}
|
||||
} else {
|
||||
$baseUrl = $bundle->baseUrl;
|
||||
}
|
||||
|
||||
if (!Url::isRelative($asset) || strncmp($asset, '/', 1) === 0) {
|
||||
return $asset;
|
||||
}
|
||||
|
||||
return "$baseUrl/$asset";
|
||||
}
|
||||
}
|
||||
34
vendor/yiisoft/yii2/web/BadRequestHttpException.php
vendored
Normal file
34
vendor/yiisoft/yii2/web/BadRequestHttpException.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* BadRequestHttpException represents a "Bad Request" HTTP exception with status code 400.
|
||||
*
|
||||
* Use this exception to represent a generic client error. In many cases, there
|
||||
* may be an HTTP exception that more precisely describes the error. In that
|
||||
* case, consider using the more precise exception to provide the user with
|
||||
* additional information.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7231#section-6.5.1
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class BadRequestHttpException extends HttpException
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
* @param string|null $message error message
|
||||
* @param int $code error code
|
||||
* @param \Throwable|null $previous The previous exception used for the exception chaining.
|
||||
*/
|
||||
public function __construct($message = null, $code = 0, $previous = null)
|
||||
{
|
||||
parent::__construct(400, $message, $code, $previous);
|
||||
}
|
||||
}
|
||||
146
vendor/yiisoft/yii2/web/CacheSession.php
vendored
Normal file
146
vendor/yiisoft/yii2/web/CacheSession.php
vendored
Normal file
@ -0,0 +1,146 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use yii\caching\CacheInterface;
|
||||
use yii\di\Instance;
|
||||
|
||||
/**
|
||||
* CacheSession implements a session component using cache as storage medium.
|
||||
*
|
||||
* The cache being used can be any cache application component.
|
||||
* The ID of the cache application component is specified via [[cache]], which defaults to 'cache'.
|
||||
*
|
||||
* Beware, by definition cache storage are volatile, which means the data stored on them
|
||||
* may be swapped out and get lost. Therefore, you must make sure the cache used by this component
|
||||
* is NOT volatile. If you want to use database as storage medium, [[DbSession]] is a better choice.
|
||||
*
|
||||
* The following example shows how you can configure the application to use CacheSession:
|
||||
* Add the following to your application config under `components`:
|
||||
*
|
||||
* ```
|
||||
* 'session' => [
|
||||
* 'class' => 'yii\web\CacheSession',
|
||||
* // 'cache' => 'mycache',
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* @property-read bool $useCustomStorage Whether to use custom storage.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class CacheSession extends Session
|
||||
{
|
||||
/**
|
||||
* @var CacheInterface|array|string the cache object or the application component ID of the cache object.
|
||||
* The session data will be stored using this cache object.
|
||||
*
|
||||
* After the CacheSession object is created, if you want to change this property,
|
||||
* you should only assign it with a cache object.
|
||||
*
|
||||
* Starting from version 2.0.2, this can also be a configuration array for creating the object.
|
||||
*/
|
||||
public $cache = 'cache';
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the application component.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
$this->cache = Instance::ensure($this->cache, 'yii\caching\CacheInterface');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a value indicating whether to use custom session storage.
|
||||
* This method overrides the parent implementation and always returns true.
|
||||
* @return bool whether to use custom storage.
|
||||
*/
|
||||
public function getUseCustomStorage()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Session open handler.
|
||||
* @internal Do not call this method directly.
|
||||
* @param string $savePath session save path
|
||||
* @param string $sessionName session name
|
||||
* @return bool whether session is opened successfully
|
||||
*/
|
||||
public function openSession($savePath, $sessionName)
|
||||
{
|
||||
if ($this->getUseStrictMode()) {
|
||||
$id = $this->getId();
|
||||
if (!$this->cache->exists($this->calculateKey($id))) {
|
||||
//This session id does not exist, mark it for forced regeneration
|
||||
$this->_forceRegenerateId = $id;
|
||||
}
|
||||
}
|
||||
|
||||
return parent::openSession($savePath, $sessionName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Session read handler.
|
||||
* @internal Do not call this method directly.
|
||||
* @param string $id session ID
|
||||
* @return string|false the session data, or false on failure
|
||||
*/
|
||||
public function readSession($id)
|
||||
{
|
||||
$data = $this->cache->get($this->calculateKey($id));
|
||||
|
||||
return $data === false ? '' : $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Session write handler.
|
||||
* @internal Do not call this method directly.
|
||||
* @param string $id session ID
|
||||
* @param string $data session data
|
||||
* @return bool whether session write is successful
|
||||
*/
|
||||
public function writeSession($id, $data)
|
||||
{
|
||||
if ($this->getUseStrictMode() && $id === $this->_forceRegenerateId) {
|
||||
//Ignore write when forceRegenerate is active for this id
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->cache->set($this->calculateKey($id), $data, $this->getTimeout());
|
||||
}
|
||||
|
||||
/**
|
||||
* Session destroy handler.
|
||||
* @internal Do not call this method directly.
|
||||
* @param string $id session ID
|
||||
* @return bool whether session is destroyed successfully
|
||||
*/
|
||||
public function destroySession($id)
|
||||
{
|
||||
$cacheId = $this->calculateKey($id);
|
||||
if ($this->cache->exists($cacheId) === false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->cache->delete($cacheId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a unique key used for storing session data in cache.
|
||||
* @param string $id session variable name
|
||||
* @return mixed a safe cache key associated with the session variable name
|
||||
*/
|
||||
protected function calculateKey($id)
|
||||
{
|
||||
return [__CLASS__, $id];
|
||||
}
|
||||
}
|
||||
143
vendor/yiisoft/yii2/web/CompositeUrlRule.php
vendored
Normal file
143
vendor/yiisoft/yii2/web/CompositeUrlRule.php
vendored
Normal file
@ -0,0 +1,143 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use Yii;
|
||||
use yii\base\BaseObject;
|
||||
|
||||
/**
|
||||
* CompositeUrlRule is the base class for URL rule classes that consist of multiple simpler rules.
|
||||
*
|
||||
* @property-read int|null $createUrlStatus Status of the URL creation after the last [[createUrl()]] call.
|
||||
* `null` if rule does not provide info about create status.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
abstract class CompositeUrlRule extends BaseObject implements UrlRuleInterface
|
||||
{
|
||||
/**
|
||||
* @var UrlRuleInterface[]|UrlRuleInterface[][]|array[]|string[] the URL rules contained in this composite rule.
|
||||
* This property is set in [[init()]] by the return value of [[createRules()]].
|
||||
*/
|
||||
protected $rules = [];
|
||||
/**
|
||||
* @var int|null status of the URL creation after the last [[createUrl()]] call.
|
||||
* @since 2.0.12
|
||||
*/
|
||||
protected $createStatus;
|
||||
|
||||
|
||||
/**
|
||||
* Creates the URL rules that should be contained within this composite rule.
|
||||
* @return UrlRuleInterface[]|UrlRuleInterface[][] the URL rules
|
||||
*/
|
||||
abstract protected function createRules();
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
$this->rules = $this->createRules();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseRequest($manager, $request)
|
||||
{
|
||||
foreach ($this->rules as $rule) {
|
||||
/** @var UrlRule $rule */
|
||||
$result = $rule->parseRequest($manager, $request);
|
||||
if (YII_DEBUG) {
|
||||
Yii::debug([
|
||||
'rule' => method_exists($rule, '__toString') ? $rule->__toString() : get_class($rule),
|
||||
'match' => $result !== false,
|
||||
'parent' => self::className(),
|
||||
], __METHOD__);
|
||||
}
|
||||
if ($result !== false) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createUrl($manager, $route, $params)
|
||||
{
|
||||
$this->createStatus = UrlRule::CREATE_STATUS_SUCCESS;
|
||||
$url = $this->iterateRules($this->rules, $manager, $route, $params);
|
||||
if ($url !== false) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
if ($this->createStatus === UrlRule::CREATE_STATUS_SUCCESS) {
|
||||
// create status was not changed - there is no rules configured
|
||||
$this->createStatus = UrlRule::CREATE_STATUS_PARSING_ONLY;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates through specified rules and calls [[createUrl()]] for each of them.
|
||||
*
|
||||
* @param UrlRuleInterface[] $rules rules to iterate.
|
||||
* @param UrlManager $manager the URL manager
|
||||
* @param string $route the route. It should not have slashes at the beginning or the end.
|
||||
* @param array $params the parameters
|
||||
* @return bool|string the created URL, or `false` if none of specified rules cannot be used for creating this URL.
|
||||
* @see createUrl()
|
||||
* @since 2.0.12
|
||||
*/
|
||||
protected function iterateRules($rules, $manager, $route, $params)
|
||||
{
|
||||
/** @var UrlRule $rule */
|
||||
foreach ($rules as $rule) {
|
||||
$url = $rule->createUrl($manager, $route, $params);
|
||||
if ($url !== false) {
|
||||
$this->createStatus = UrlRule::CREATE_STATUS_SUCCESS;
|
||||
return $url;
|
||||
}
|
||||
if (
|
||||
$this->createStatus === null
|
||||
|| !method_exists($rule, 'getCreateUrlStatus')
|
||||
|| $rule->getCreateUrlStatus() === null
|
||||
) {
|
||||
$this->createStatus = null;
|
||||
} else {
|
||||
$this->createStatus |= $rule->getCreateUrlStatus();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns status of the URL creation after the last [[createUrl()]] call.
|
||||
*
|
||||
* For multiple rules statuses will be combined by bitwise `or` operator
|
||||
* (e.g. `UrlRule::CREATE_STATUS_PARSING_ONLY | UrlRule::CREATE_STATUS_PARAMS_MISMATCH`).
|
||||
*
|
||||
* @return int|null Status of the URL creation after the last [[createUrl()]] call. `null` if rule does not provide
|
||||
* info about create status.
|
||||
* @see createStatus
|
||||
* @see https://www.php.net/manual/en/language.operators.bitwise.php
|
||||
* @since 2.0.12
|
||||
*/
|
||||
public function getCreateUrlStatus()
|
||||
{
|
||||
return $this->createStatus;
|
||||
}
|
||||
}
|
||||
29
vendor/yiisoft/yii2/web/ConflictHttpException.php
vendored
Normal file
29
vendor/yiisoft/yii2/web/ConflictHttpException.php
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* ConflictHttpException represents a "Conflict" HTTP exception with status code 409.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7231#section-6.5.8
|
||||
* @author Dan Schmidt <danschmidt5189@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class ConflictHttpException extends HttpException
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
* @param string|null $message error message
|
||||
* @param int $code error code
|
||||
* @param \Throwable|null $previous The previous exception used for the exception chaining.
|
||||
*/
|
||||
public function __construct($message = null, $code = 0, $previous = null)
|
||||
{
|
||||
parent::__construct(409, $message, $code, $previous);
|
||||
}
|
||||
}
|
||||
446
vendor/yiisoft/yii2/web/Controller.php
vendored
Normal file
446
vendor/yiisoft/yii2/web/Controller.php
vendored
Normal file
@ -0,0 +1,446 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Exception;
|
||||
use yii\base\InlineAction;
|
||||
use yii\helpers\Url;
|
||||
use yii\base\Action;
|
||||
use yii\base\Controller as BaseController;
|
||||
use yii\base\Module;
|
||||
|
||||
/**
|
||||
* Controller is the base class of web controllers.
|
||||
*
|
||||
* For more details and usage information on Controller, see the [guide article on controllers](guide:structure-controllers).
|
||||
*
|
||||
* @property Request $request The request object.
|
||||
* @property Response $response The response object.
|
||||
* @property View $view The view object that can be used to render views or view files.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*
|
||||
* @template T of Module
|
||||
* @extends BaseController<T>
|
||||
*/
|
||||
class Controller extends BaseController
|
||||
{
|
||||
/**
|
||||
* @var bool whether to enable CSRF validation for the actions in this controller.
|
||||
* CSRF validation is enabled only when both this property and [[\yii\web\Request::enableCsrfValidation]] are true.
|
||||
*/
|
||||
public $enableCsrfValidation = true;
|
||||
/**
|
||||
* @var array the parameters bound to the current action.
|
||||
*/
|
||||
public $actionParams = [];
|
||||
|
||||
|
||||
/**
|
||||
* Renders a view in response to an AJAX request.
|
||||
*
|
||||
* This method is similar to [[renderPartial()]] except that it will inject into
|
||||
* the rendering result with JS/CSS scripts and files which are registered with the view.
|
||||
* For this reason, you should use this method instead of [[renderPartial()]] to render
|
||||
* a view to respond to an AJAX request.
|
||||
*
|
||||
* @param string $view the view name. Please refer to [[render()]] on how to specify a view name.
|
||||
* @param array $params the parameters (name-value pairs) that should be made available in the view.
|
||||
* @return string the rendering result.
|
||||
*/
|
||||
public function renderAjax($view, $params = [])
|
||||
{
|
||||
/** @var View */
|
||||
$viewComponent = $this->getView();
|
||||
|
||||
return $viewComponent->renderAjax($view, $params, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data formatted as JSON.
|
||||
*
|
||||
* This method is a shortcut for sending data formatted as JSON. It will return
|
||||
* the [[Application::getResponse()|response]] application component after configuring
|
||||
* the [[Response::$format|format]] and setting the [[Response::$data|data]] that should
|
||||
* be formatted. A common usage will be:
|
||||
*
|
||||
* ```
|
||||
* return $this->asJson($data);
|
||||
* ```
|
||||
*
|
||||
* @param mixed $data the data that should be formatted.
|
||||
* @return Response a response that is configured to send `$data` formatted as JSON.
|
||||
* @since 2.0.11
|
||||
* @see Response::$format
|
||||
* @see Response::FORMAT_JSON
|
||||
* @see JsonResponseFormatter
|
||||
*/
|
||||
public function asJson($data)
|
||||
{
|
||||
$this->response->format = Response::FORMAT_JSON;
|
||||
$this->response->data = $data;
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data formatted as XML.
|
||||
*
|
||||
* This method is a shortcut for sending data formatted as XML. It will return
|
||||
* the [[Application::getResponse()|response]] application component after configuring
|
||||
* the [[Response::$format|format]] and setting the [[Response::$data|data]] that should
|
||||
* be formatted. A common usage will be:
|
||||
*
|
||||
* ```
|
||||
* return $this->asXml($data);
|
||||
* ```
|
||||
*
|
||||
* @param mixed $data the data that should be formatted.
|
||||
* @return Response a response that is configured to send `$data` formatted as XML.
|
||||
* @since 2.0.11
|
||||
* @see Response::$format
|
||||
* @see Response::FORMAT_XML
|
||||
* @see XmlResponseFormatter
|
||||
*/
|
||||
public function asXml($data)
|
||||
{
|
||||
$this->response->format = Response::FORMAT_XML;
|
||||
$this->response->data = $data;
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the parameters to the action.
|
||||
* This method is invoked by [[Action]] when it begins to run with the given parameters.
|
||||
* This method will check the parameter names that the action requires and return
|
||||
* the provided parameters according to the requirement. If there is any missing parameter,
|
||||
* an exception will be thrown.
|
||||
* @param Action $action the action to be bound with parameters
|
||||
* @param array $params the parameters to be bound to the action
|
||||
* @return array the valid parameters that the action can run with.
|
||||
* @throws BadRequestHttpException if there are missing or invalid parameters.
|
||||
*
|
||||
* @phpstan-param Action<$this> $action
|
||||
* @psalm-param Action<$this> $action
|
||||
*
|
||||
* @phpstan-param array<array-key, mixed> $params
|
||||
* @psalm-param array<array-key, mixed> $params
|
||||
*
|
||||
* @phpstan-return mixed[]
|
||||
* @psalm-return mixed[]
|
||||
*/
|
||||
public function bindActionParams($action, $params)
|
||||
{
|
||||
if ($action instanceof InlineAction) {
|
||||
$method = new \ReflectionMethod($this, $action->actionMethod);
|
||||
} else {
|
||||
$method = new \ReflectionMethod($action, 'run');
|
||||
}
|
||||
|
||||
$args = [];
|
||||
$missing = [];
|
||||
$actionParams = [];
|
||||
$requestedParams = [];
|
||||
foreach ($method->getParameters() as $param) {
|
||||
$name = $param->getName();
|
||||
if (array_key_exists($name, $params)) {
|
||||
$isValid = true;
|
||||
$type = $param->getType();
|
||||
if ($type instanceof \ReflectionNamedType) {
|
||||
[$result, $isValid] = $this->filterSingleTypeActionParam($params[$name], $type);
|
||||
$params[$name] = $result;
|
||||
} elseif ($type instanceof \ReflectionUnionType) {
|
||||
[$result, $isValid] = $this->filterUnionTypeActionParam($params[$name], $type);
|
||||
$params[$name] = $result;
|
||||
}
|
||||
|
||||
if (!$isValid) {
|
||||
throw new BadRequestHttpException(
|
||||
Yii::t('yii', 'Invalid data received for parameter "{param}".', ['param' => $name])
|
||||
);
|
||||
}
|
||||
$args[] = $actionParams[$name] = $params[$name];
|
||||
unset($params[$name]);
|
||||
} elseif (
|
||||
PHP_VERSION_ID >= 70100
|
||||
&& ($type = $param->getType()) !== null
|
||||
&& $type instanceof \ReflectionNamedType
|
||||
&& !$type->isBuiltin()
|
||||
) {
|
||||
try {
|
||||
$this->bindInjectedParams($type, $name, $args, $requestedParams);
|
||||
} catch (HttpException $e) {
|
||||
throw $e;
|
||||
} catch (Exception $e) {
|
||||
throw new ServerErrorHttpException($e->getMessage(), 0, $e);
|
||||
}
|
||||
} elseif ($param->isDefaultValueAvailable()) {
|
||||
$args[] = $actionParams[$name] = $param->getDefaultValue();
|
||||
} else {
|
||||
$missing[] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($missing)) {
|
||||
throw new BadRequestHttpException(
|
||||
Yii::t('yii', 'Missing required parameters: {params}', ['params' => implode(', ', $missing)])
|
||||
);
|
||||
}
|
||||
|
||||
$this->actionParams = $actionParams;
|
||||
|
||||
// We use a different array here, specifically one that doesn't contain service instances but descriptions instead.
|
||||
if (Yii::$app->requestedParams === null) {
|
||||
Yii::$app->requestedParams = array_merge($actionParams, $requestedParams);
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* The logic for [[bindActionParam]] to validate whether a given parameter matches the action's typing
|
||||
* if the function parameter has a single named type.
|
||||
* @param mixed $param The parameter value.
|
||||
* @param \ReflectionNamedType $type
|
||||
* @return array The resulting parameter value and a boolean indicating whether the value is valid.
|
||||
*
|
||||
* @phpstan-return array{mixed, bool}
|
||||
*/
|
||||
private function filterSingleTypeActionParam($param, $type)
|
||||
{
|
||||
$isArray = $type->getName() === 'array';
|
||||
if ($isArray) {
|
||||
return [(array)$param, true];
|
||||
}
|
||||
$isMixed = $type->getName() === 'mixed';
|
||||
if ($isMixed) {
|
||||
return [$param, true];
|
||||
}
|
||||
|
||||
if (is_array($param)) {
|
||||
return [$param, false];
|
||||
}
|
||||
|
||||
if (
|
||||
PHP_VERSION_ID >= 70000
|
||||
&& method_exists($type, 'isBuiltin')
|
||||
&& $type->isBuiltin()
|
||||
&& ($param !== null || !$type->allowsNull())
|
||||
) {
|
||||
$typeName = PHP_VERSION_ID >= 70100 ? $type->getName() : (string)$type;
|
||||
if ($param === '' && $type->allowsNull()) {
|
||||
if ($typeName !== 'string') { // for old string behavior compatibility
|
||||
return [null, true];
|
||||
}
|
||||
return ['', true];
|
||||
}
|
||||
|
||||
if ($typeName === 'string') {
|
||||
return [$param, true];
|
||||
}
|
||||
$filterResult = $this->filterParamByType($param, $typeName);
|
||||
return [$filterResult, $filterResult !== null];
|
||||
}
|
||||
return [$param, true];
|
||||
}
|
||||
|
||||
/**
|
||||
* The logic for [[bindActionParam]] to validate whether a given parameter matches the action's typing
|
||||
* if the function parameter has a union type.
|
||||
* @param mixed $param The parameter value.
|
||||
* @param \ReflectionUnionType $type
|
||||
* @return array The resulting parameter value and a boolean indicating whether the value is valid.
|
||||
*
|
||||
* @phpstan-return array{mixed, bool}
|
||||
*/
|
||||
private function filterUnionTypeActionParam($param, $type)
|
||||
{
|
||||
$types = $type->getTypes();
|
||||
if ($param === '' && $type->allowsNull()) {
|
||||
// check if type can be string for old string behavior compatibility
|
||||
foreach ($types as $partialType) {
|
||||
if (
|
||||
$partialType === null
|
||||
|| !method_exists($partialType, 'isBuiltin')
|
||||
|| !$partialType->isBuiltin()
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
$typeName = PHP_VERSION_ID >= 70100 ? $partialType->getName() : (string)$partialType;
|
||||
if ($typeName === 'string') {
|
||||
return ['', true];
|
||||
}
|
||||
}
|
||||
return [null, true];
|
||||
}
|
||||
// if we found a built-in type but didn't return out, its validation failed
|
||||
$foundBuiltinType = false;
|
||||
// we save returning out an array or string for later because other types should take precedence
|
||||
$canBeArray = false;
|
||||
$canBeString = false;
|
||||
foreach ($types as $partialType) {
|
||||
if (
|
||||
$partialType === null
|
||||
|| !method_exists($partialType, 'isBuiltin')
|
||||
|| !$partialType->isBuiltin()
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
$foundBuiltinType = true;
|
||||
$typeName = PHP_VERSION_ID >= 70100 ? $partialType->getName() : (string)$partialType;
|
||||
$canBeArray |= $typeName === 'array';
|
||||
$canBeString |= $typeName === 'string';
|
||||
if (is_array($param)) {
|
||||
if ($canBeArray) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
$filterResult = $this->filterParamByType($param, $typeName);
|
||||
if ($filterResult !== null) {
|
||||
return [$filterResult, true];
|
||||
}
|
||||
}
|
||||
if (!is_array($param) && $canBeString) {
|
||||
return [$param, true];
|
||||
}
|
||||
if ($canBeArray) {
|
||||
return [(array)$param, true];
|
||||
}
|
||||
return [$param, $canBeString || !$foundBuiltinType];
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the according filter_var logic for teh given type.
|
||||
* @param string $param The value to filter.
|
||||
* @param string $typeName The type name.
|
||||
* @return mixed|null The resulting value, or null if validation failed or the type can't be validated.
|
||||
*/
|
||||
private function filterParamByType(string $param, string $typeName)
|
||||
{
|
||||
switch ($typeName) {
|
||||
case 'int':
|
||||
return filter_var($param, FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE);
|
||||
case 'float':
|
||||
return filter_var($param, FILTER_VALIDATE_FLOAT, FILTER_NULL_ON_FAILURE);
|
||||
case 'bool':
|
||||
return filter_var($param, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function beforeAction($action)
|
||||
{
|
||||
if (parent::beforeAction($action)) {
|
||||
if ($this->enableCsrfValidation && Yii::$app->getErrorHandler()->exception === null && !$this->request->validateCsrfToken()) {
|
||||
throw new BadRequestHttpException(Yii::t('yii', 'Unable to verify your data submission.'));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects the browser to the specified URL.
|
||||
* This method is a shortcut to [[Response::redirect()]].
|
||||
*
|
||||
* You can use it in an action by returning the [[Response]] directly:
|
||||
*
|
||||
* ```
|
||||
* // stop executing this action and redirect to login page
|
||||
* return $this->redirect(['login']);
|
||||
* ```
|
||||
*
|
||||
* @param string|array $url the URL to be redirected to. This can be in one of the following formats:
|
||||
*
|
||||
* - a string representing a URL (e.g. "https://example.com")
|
||||
* - a string representing a URL alias (e.g. "@example.com")
|
||||
* - an array in the format of `[$route, ...name-value pairs...]` (e.g. `['site/index', 'ref' => 1]`)
|
||||
* [[Url::to()]] will be used to convert the array into a URL.
|
||||
*
|
||||
* Any relative URL that starts with a single forward slash "/" will be converted
|
||||
* into an absolute one by prepending it with the host info of the current request.
|
||||
*
|
||||
* @param int $statusCode the HTTP status code. Defaults to 302.
|
||||
* See <https://tools.ietf.org/html/rfc2616#section-10>
|
||||
* for details about HTTP status code
|
||||
* @return Response the current response object
|
||||
*/
|
||||
public function redirect($url, $statusCode = 302)
|
||||
{
|
||||
// calling Url::to() here because Response::redirect() modifies route before calling Url::to()
|
||||
return $this->response->redirect(Url::to($url), $statusCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects the browser to the home page.
|
||||
*
|
||||
* You can use this method in an action by returning the [[Response]] directly:
|
||||
*
|
||||
* ```
|
||||
* // stop executing this action and redirect to home page
|
||||
* return $this->goHome();
|
||||
* ```
|
||||
*
|
||||
* @return Response the current response object
|
||||
*/
|
||||
public function goHome()
|
||||
{
|
||||
return $this->response->redirect(Yii::$app->getHomeUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects the browser to the last visited page.
|
||||
*
|
||||
* You can use this method in an action by returning the [[Response]] directly:
|
||||
*
|
||||
* ```
|
||||
* // stop executing this action and redirect to last visited page
|
||||
* return $this->goBack();
|
||||
* ```
|
||||
*
|
||||
* For this function to work you have to [[User::setReturnUrl()|set the return URL]] in appropriate places before.
|
||||
*
|
||||
* @param string|array|null $defaultUrl the default return URL in case it was not set previously.
|
||||
* If this is null and the return URL was not set previously, [[Application::homeUrl]] will be redirected to.
|
||||
* Please refer to [[User::setReturnUrl()]] on accepted format of the URL.
|
||||
* @return Response the current response object
|
||||
* @see User::getReturnUrl()
|
||||
*/
|
||||
public function goBack($defaultUrl = null)
|
||||
{
|
||||
return $this->response->redirect(Yii::$app->getUser()->getReturnUrl($defaultUrl));
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the current page.
|
||||
* This method is a shortcut to [[Response::refresh()]].
|
||||
*
|
||||
* You can use it in an action by returning the [[Response]] directly:
|
||||
*
|
||||
* ```
|
||||
* // stop executing this action and refresh the current page
|
||||
* return $this->refresh();
|
||||
* ```
|
||||
*
|
||||
* @param string $anchor the anchor that should be appended to the redirection URL.
|
||||
* Defaults to empty. Make sure the anchor starts with '#' if you want to specify it.
|
||||
* @return Response the response object itself
|
||||
*/
|
||||
public function refresh($anchor = '')
|
||||
{
|
||||
return $this->response->redirect($this->request->getUrl() . $anchor);
|
||||
}
|
||||
}
|
||||
102
vendor/yiisoft/yii2/web/Cookie.php
vendored
Normal file
102
vendor/yiisoft/yii2/web/Cookie.php
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* Cookie represents information related with a cookie, such as [[name]], [[value]], [[domain]], etc.
|
||||
*
|
||||
* For more details and usage information on Cookie, see the [guide article on handling cookies](guide:runtime-sessions-cookies).
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class Cookie extends \yii\base\BaseObject
|
||||
{
|
||||
/**
|
||||
* SameSite policy Lax will prevent the cookie from being sent by the browser in all cross-site browsing context
|
||||
* during CSRF-prone request methods (e.g. POST, PUT, PATCH etc).
|
||||
* E.g. a POST request from https://otherdomain.com to https://yourdomain.com will not include the cookie, however a GET request will.
|
||||
* When a user follows a link from https://otherdomain.com to https://yourdomain.com it will include the cookie
|
||||
* @see sameSite
|
||||
*/
|
||||
public const SAME_SITE_LAX = 'Lax';
|
||||
/**
|
||||
* SameSite policy Strict will prevent the cookie from being sent by the browser in all cross-site browsing context
|
||||
* regardless of the request method and even when following a regular link.
|
||||
* E.g. a GET request from https://otherdomain.com to https://yourdomain.com or a user following a link from
|
||||
* https://otherdomain.com to https://yourdomain.com will not include the cookie.
|
||||
* @see sameSite
|
||||
*/
|
||||
public const SAME_SITE_STRICT = 'Strict';
|
||||
/**
|
||||
* SameSite policy None disables the SameSite policy so cookies will be sent in all contexts,
|
||||
* i.e in responses to both first-party and cross-origin requests.
|
||||
* E.g. a POST request from https://otherdomain.com to https://yourdomain.com will include the cookie.
|
||||
* Note: If `sameSite` is set to None, the `secure` attribute must be set to `true` (otherwise the cookie will be blocked by the browser).
|
||||
* @see sameSite
|
||||
* @see secure
|
||||
* @since 2.0.43
|
||||
*/
|
||||
public const SAME_SITE_NONE = 'None';
|
||||
/**
|
||||
* @var string name of the cookie
|
||||
*/
|
||||
public $name;
|
||||
/**
|
||||
* @var string value of the cookie
|
||||
*/
|
||||
public $value = '';
|
||||
/**
|
||||
* @var string domain of the cookie
|
||||
*/
|
||||
public $domain = '';
|
||||
/**
|
||||
* @var int|string|\DateTimeInterface|null the timestamp or date at which the cookie expires. This is the server timestamp.
|
||||
* Defaults to 0, meaning "until the browser is closed" (the same applies to `null`).
|
||||
*/
|
||||
public $expire = 0;
|
||||
/**
|
||||
* @var string the path on the server in which the cookie will be available on. The default is '/'.
|
||||
*/
|
||||
public $path = '/';
|
||||
/**
|
||||
* @var bool whether cookie should be sent via secure connection
|
||||
*/
|
||||
public $secure = false;
|
||||
/**
|
||||
* @var bool whether the cookie should be accessible only through the HTTP protocol.
|
||||
* By setting this property to true, the cookie will not be accessible by scripting languages,
|
||||
* such as JavaScript, which can effectively help to reduce identity theft through XSS attacks.
|
||||
*/
|
||||
public $httpOnly = true;
|
||||
/**
|
||||
* @var string SameSite prevents the browser from sending this cookie along with cross-site requests.
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite for more information about sameSite.
|
||||
*
|
||||
* @since 2.0.21
|
||||
*/
|
||||
public $sameSite = self::SAME_SITE_LAX;
|
||||
|
||||
|
||||
/**
|
||||
* Magic method to turn a cookie object into a string without having to explicitly access [[value]].
|
||||
*
|
||||
* ```
|
||||
* if (isset($request->cookies['name'])) {
|
||||
* $value = (string) $request->cookies['name'];
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @return string The value of the cookie. If the value property is null, an empty string will be returned.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return (string) $this->value;
|
||||
}
|
||||
}
|
||||
279
vendor/yiisoft/yii2/web/CookieCollection.php
vendored
Normal file
279
vendor/yiisoft/yii2/web/CookieCollection.php
vendored
Normal file
@ -0,0 +1,279 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use ArrayIterator;
|
||||
use Yii;
|
||||
use yii\base\BaseObject;
|
||||
use yii\base\InvalidCallException;
|
||||
|
||||
/**
|
||||
* CookieCollection maintains the cookies available in the current request.
|
||||
*
|
||||
* For more details and usage information on CookieCollection, see the [guide article on handling cookies](guide:runtime-sessions-cookies).
|
||||
*
|
||||
* @property-read int $count The number of cookies in the collection.
|
||||
* @property-read ArrayIterator $iterator An iterator for traversing the cookies in the collection.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*
|
||||
* @implements \IteratorAggregate<string, Cookie>
|
||||
* @implements \ArrayAccess<string, Cookie|null>
|
||||
*
|
||||
* @phpstan-property-read ArrayIterator<string, Cookie> $iterator
|
||||
* @psalm-property-read ArrayIterator<string, Cookie> $iterator
|
||||
*/
|
||||
class CookieCollection extends BaseObject implements \IteratorAggregate, \ArrayAccess, \Countable
|
||||
{
|
||||
/**
|
||||
* @var bool whether this collection is read only.
|
||||
*/
|
||||
public $readOnly = false;
|
||||
|
||||
/**
|
||||
* @var Cookie[] the cookies in this collection (indexed by the cookie names)
|
||||
*
|
||||
* @phpstan-var array<string, Cookie>
|
||||
*/
|
||||
private $_cookies;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param array $cookies the cookies that this collection initially contains. This should be
|
||||
* an array of name-value pairs.
|
||||
* @param array $config name-value pairs that will be used to initialize the object properties
|
||||
*/
|
||||
public function __construct($cookies = [], $config = [])
|
||||
{
|
||||
$this->_cookies = $cookies;
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator for traversing the cookies in the collection.
|
||||
* This method is required by the SPL interface [[\IteratorAggregate]].
|
||||
* It will be implicitly called when you use `foreach` to traverse the collection.
|
||||
* @return ArrayIterator an iterator for traversing the cookies in the collection.
|
||||
*
|
||||
* @phpstan-return ArrayIterator<string, Cookie>
|
||||
* @psalm-return ArrayIterator<string, Cookie>
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
return new ArrayIterator($this->_cookies);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of cookies in the collection.
|
||||
* This method is required by the SPL `Countable` interface.
|
||||
* It will be implicitly called when you use `count($collection)`.
|
||||
* @return int the number of cookies in the collection.
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function count()
|
||||
{
|
||||
return $this->getCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of cookies in the collection.
|
||||
* @return int the number of cookies in the collection.
|
||||
*/
|
||||
public function getCount()
|
||||
{
|
||||
return count($this->_cookies);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cookie with the specified name.
|
||||
* @param string $name the cookie name
|
||||
* @return Cookie|null the cookie with the specified name. Null if the named cookie does not exist.
|
||||
* @see getValue()
|
||||
*/
|
||||
public function get($name)
|
||||
{
|
||||
return isset($this->_cookies[$name]) ? $this->_cookies[$name] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the named cookie.
|
||||
* @param string $name the cookie name
|
||||
* @param mixed $defaultValue the value that should be returned when the named cookie does not exist.
|
||||
* @return mixed the value of the named cookie.
|
||||
* @see get()
|
||||
*/
|
||||
public function getValue($name, $defaultValue = null)
|
||||
{
|
||||
return isset($this->_cookies[$name]) ? $this->_cookies[$name]->value : $defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether there is a cookie with the specified name.
|
||||
* Note that if a cookie is marked for deletion from browser or its value is an empty string, this method will return false.
|
||||
* @param string $name the cookie name
|
||||
* @return bool whether the named cookie exists
|
||||
* @see remove()
|
||||
*/
|
||||
public function has($name)
|
||||
{
|
||||
if (!isset($this->_cookies[$name]) || $this->_cookies[$name]->value === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$expire = $this->_cookies[$name]->expire;
|
||||
|
||||
if ($expire === null || $expire === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$currentTime = time();
|
||||
|
||||
if (is_numeric($expire)) {
|
||||
return (int) $expire >= $currentTime;
|
||||
}
|
||||
|
||||
if (is_string($expire)) {
|
||||
return strtotime($expire) >= $currentTime;
|
||||
}
|
||||
|
||||
return $expire->getTimestamp() >= $currentTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a cookie to the collection.
|
||||
* If there is already a cookie with the same name in the collection, it will be removed first.
|
||||
* @param Cookie $cookie the cookie to be added
|
||||
* @throws InvalidCallException if the cookie collection is read only
|
||||
*/
|
||||
public function add($cookie)
|
||||
{
|
||||
if ($this->readOnly) {
|
||||
throw new InvalidCallException('The cookie collection is read only.');
|
||||
}
|
||||
$this->_cookies[$cookie->name] = $cookie;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a cookie.
|
||||
* If `$removeFromBrowser` is true, the cookie will be removed from the browser.
|
||||
* In this case, a cookie with outdated expiry will be added to the collection.
|
||||
* @param Cookie|string $cookie the cookie object or the name of the cookie to be removed.
|
||||
* @param bool $removeFromBrowser whether to remove the cookie from browser
|
||||
* @throws InvalidCallException if the cookie collection is read only
|
||||
*/
|
||||
public function remove($cookie, $removeFromBrowser = true)
|
||||
{
|
||||
if ($this->readOnly) {
|
||||
throw new InvalidCallException('The cookie collection is read only.');
|
||||
}
|
||||
if ($cookie instanceof Cookie) {
|
||||
$cookie->expire = 1;
|
||||
$cookie->value = '';
|
||||
} else {
|
||||
$cookie = Yii::createObject([
|
||||
'class' => 'yii\web\Cookie',
|
||||
'name' => $cookie,
|
||||
'expire' => 1,
|
||||
]);
|
||||
}
|
||||
if ($removeFromBrowser) {
|
||||
$this->_cookies[$cookie->name] = $cookie;
|
||||
} else {
|
||||
unset($this->_cookies[$cookie->name]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all cookies.
|
||||
* @throws InvalidCallException if the cookie collection is read only
|
||||
*/
|
||||
public function removeAll()
|
||||
{
|
||||
if ($this->readOnly) {
|
||||
throw new InvalidCallException('The cookie collection is read only.');
|
||||
}
|
||||
$this->_cookies = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the collection as a PHP array.
|
||||
* @return Cookie[] the array representation of the collection.
|
||||
* The array keys are cookie names, and the array values are the corresponding cookie objects.
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return $this->_cookies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the cookie collection from an array.
|
||||
* @param array $array the cookies to populate from
|
||||
* @since 2.0.3
|
||||
*/
|
||||
public function fromArray(array $array)
|
||||
{
|
||||
$this->_cookies = $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether there is a cookie with the specified name.
|
||||
* This method is required by the SPL interface [[\ArrayAccess]].
|
||||
* It is implicitly called when you use something like `isset($collection[$name])`.
|
||||
* @param string $name the cookie name
|
||||
* @return bool whether the named cookie exists
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetExists($name)
|
||||
{
|
||||
return $this->has($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cookie with the specified name.
|
||||
* This method is required by the SPL interface [[\ArrayAccess]].
|
||||
* It is implicitly called when you use something like `$cookie = $collection[$name];`.
|
||||
* This is equivalent to [[get()]].
|
||||
* @param string $name the cookie name
|
||||
* @return Cookie|null the cookie with the specified name, null if the named cookie does not exist.
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetGet($name)
|
||||
{
|
||||
return $this->get($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the cookie to the collection.
|
||||
* This method is required by the SPL interface [[\ArrayAccess]].
|
||||
* It is implicitly called when you use something like `$collection[$name] = $cookie;`.
|
||||
* This is equivalent to [[add()]].
|
||||
* @param string $name the cookie name
|
||||
* @param Cookie $cookie the cookie to be added
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetSet($name, $cookie)
|
||||
{
|
||||
$this->add($cookie);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the named cookie.
|
||||
* This method is required by the SPL interface [[\ArrayAccess]].
|
||||
* It is implicitly called when you use something like `unset($collection[$name])`.
|
||||
* This is equivalent to [[remove()]].
|
||||
* @param string $name the cookie name
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetUnset($name)
|
||||
{
|
||||
$this->remove($name);
|
||||
}
|
||||
}
|
||||
288
vendor/yiisoft/yii2/web/DbSession.php
vendored
Normal file
288
vendor/yiisoft/yii2/web/DbSession.php
vendored
Normal file
@ -0,0 +1,288 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use Yii;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\db\Connection;
|
||||
use yii\db\PdoValue;
|
||||
use yii\db\Query;
|
||||
use yii\di\Instance;
|
||||
|
||||
/**
|
||||
* DbSession extends [[Session]] by using database as session data storage.
|
||||
*
|
||||
* By default, DbSession stores session data in a DB table named 'session'. This table
|
||||
* must be pre-created. The table name can be changed by setting [[sessionTable]].
|
||||
*
|
||||
* The following example shows how you can configure the application to use DbSession:
|
||||
* Add the following to your application config under `components`:
|
||||
*
|
||||
* ```
|
||||
* 'session' => [
|
||||
* 'class' => 'yii\web\DbSession',
|
||||
* // 'db' => 'mydb',
|
||||
* // 'sessionTable' => 'my_session',
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* DbSession extends [[MultiFieldSession]], thus it allows saving extra fields into the [[sessionTable]].
|
||||
* Refer to [[MultiFieldSession]] for more details.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class DbSession extends MultiFieldSession
|
||||
{
|
||||
/**
|
||||
* @var Connection|array|string the DB connection object or the application component ID of the DB connection.
|
||||
* After the DbSession object is created, if you want to change this property, you should only assign it
|
||||
* with a DB connection object.
|
||||
* Starting from version 2.0.2, this can also be a configuration array for creating the object.
|
||||
*/
|
||||
public $db = 'db';
|
||||
/**
|
||||
* @var string the name of the DB table that stores the session data.
|
||||
* The table should be pre-created as follows:
|
||||
*
|
||||
* ```
|
||||
* CREATE TABLE session
|
||||
* (
|
||||
* id CHAR(40) NOT NULL PRIMARY KEY,
|
||||
* expire INTEGER,
|
||||
* data BLOB
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* where 'BLOB' refers to the BLOB-type of your preferred DBMS. Below are the BLOB type
|
||||
* that can be used for some popular DBMS:
|
||||
*
|
||||
* - MySQL: LONGBLOB
|
||||
* - PostgreSQL: BYTEA
|
||||
* - MSSQL: BLOB
|
||||
*
|
||||
* When using DbSession in a production server, we recommend you create a DB index for the 'expire'
|
||||
* column in the session table to improve the performance.
|
||||
*
|
||||
* Note that according to the php.ini setting of `session.hash_function`, you may need to adjust
|
||||
* the length of the `id` column. For example, if `session.hash_function=sha256`, you should use
|
||||
* length 64 instead of 40.
|
||||
*/
|
||||
public $sessionTable = '{{%session}}';
|
||||
|
||||
/**
|
||||
* @var array Session fields to be written into session table columns
|
||||
* @since 2.0.17
|
||||
*/
|
||||
protected $fields = [];
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the DbSession component.
|
||||
* This method will initialize the [[db]] property to make sure it refers to a valid DB connection.
|
||||
* @throws InvalidConfigException if [[db]] is invalid.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
$this->db = Instance::ensure($this->db, Connection::className());
|
||||
}
|
||||
|
||||
/**
|
||||
* Session open handler.
|
||||
* @internal Do not call this method directly.
|
||||
* @param string $savePath session save path
|
||||
* @param string $sessionName session name
|
||||
* @return bool whether session is opened successfully
|
||||
*/
|
||||
public function openSession($savePath, $sessionName)
|
||||
{
|
||||
if ($this->getUseStrictMode()) {
|
||||
$id = $this->getId();
|
||||
if (!$this->getReadQuery($id)->exists($this->db)) {
|
||||
//This session id does not exist, mark it for forced regeneration
|
||||
$this->_forceRegenerateId = $id;
|
||||
}
|
||||
}
|
||||
|
||||
return parent::openSession($savePath, $sessionName);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function regenerateID($deleteOldSession = false)
|
||||
{
|
||||
$oldID = session_id();
|
||||
|
||||
// if no session is started, there is nothing to regenerate
|
||||
if (empty($oldID)) {
|
||||
return;
|
||||
}
|
||||
|
||||
parent::regenerateID(false);
|
||||
$newID = session_id();
|
||||
// if session id regeneration failed, no need to create/update it.
|
||||
if (empty($newID)) {
|
||||
Yii::warning('Failed to generate new session ID', __METHOD__);
|
||||
return;
|
||||
}
|
||||
|
||||
$row = $this->db->useMaster(function () use ($oldID) {
|
||||
return (new Query())->from($this->sessionTable)
|
||||
->where(['id' => $oldID])
|
||||
->createCommand($this->db)
|
||||
->queryOne();
|
||||
});
|
||||
|
||||
if ($row !== false && $this->getIsActive()) {
|
||||
if ($deleteOldSession) {
|
||||
$this->db->createCommand()
|
||||
->update($this->sessionTable, ['id' => $newID], ['id' => $oldID])
|
||||
->execute();
|
||||
} else {
|
||||
$row['id'] = $newID;
|
||||
$this->db->createCommand()
|
||||
->insert($this->sessionTable, $row)
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends the current session and store session data.
|
||||
* @since 2.0.17
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
if ($this->getIsActive()) {
|
||||
// prepare writeCallback fields before session closes
|
||||
$this->fields = $this->composeFields();
|
||||
YII_DEBUG ? session_write_close() : @session_write_close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Session read handler.
|
||||
* @internal Do not call this method directly.
|
||||
* @param string $id session ID
|
||||
* @return string|false the session data, or false on failure
|
||||
*/
|
||||
public function readSession($id)
|
||||
{
|
||||
$query = $this->getReadQuery($id);
|
||||
|
||||
if ($this->readCallback !== null) {
|
||||
$fields = $query->one($this->db);
|
||||
return $fields === false ? '' : $this->extractData($fields);
|
||||
}
|
||||
|
||||
$data = $query->select(['data'])->scalar($this->db);
|
||||
return $data === false ? '' : $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Session write handler.
|
||||
* @internal Do not call this method directly.
|
||||
* @param string $id session ID
|
||||
* @param string $data session data
|
||||
* @return bool whether session write is successful
|
||||
*/
|
||||
public function writeSession($id, $data)
|
||||
{
|
||||
if ($this->getUseStrictMode() && $id === $this->_forceRegenerateId) {
|
||||
//Ignore write when forceRegenerate is active for this id
|
||||
return true;
|
||||
}
|
||||
|
||||
// exception must be caught in session write handler
|
||||
// https://www.php.net/manual/en/function.session-set-save-handler.php#refsect1-function.session-set-save-handler-notes
|
||||
try {
|
||||
// ensure backwards compatability (fixed #9438)
|
||||
if ($this->writeCallback && !$this->fields) {
|
||||
$this->fields = $this->composeFields();
|
||||
}
|
||||
// ensure data consistency
|
||||
if (!isset($this->fields['data'])) {
|
||||
$this->fields['data'] = $data;
|
||||
} else {
|
||||
$_SESSION = $this->fields['data'];
|
||||
}
|
||||
// ensure 'id' and 'expire' are never affected by [[writeCallback]]
|
||||
$this->fields = array_merge($this->fields, [
|
||||
'id' => $id,
|
||||
'expire' => time() + $this->getTimeout(),
|
||||
]);
|
||||
$this->fields = $this->typecastFields($this->fields);
|
||||
$this->db->createCommand()->upsert($this->sessionTable, $this->fields)->execute();
|
||||
$this->fields = [];
|
||||
} catch (\Exception $e) {
|
||||
Yii::$app->errorHandler->handleException($e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Session destroy handler.
|
||||
* @internal Do not call this method directly.
|
||||
* @param string $id session ID
|
||||
* @return bool whether session is destroyed successfully
|
||||
*/
|
||||
public function destroySession($id)
|
||||
{
|
||||
$this->db->createCommand()
|
||||
->delete($this->sessionTable, ['id' => $id])
|
||||
->execute();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Session GC (garbage collection) handler.
|
||||
* @internal Do not call this method directly.
|
||||
* @param int $maxLifetime the number of seconds after which data will be seen as 'garbage' and cleaned up.
|
||||
* @return int|false the number of deleted sessions on success, or false on failure
|
||||
*/
|
||||
public function gcSession($maxLifetime)
|
||||
{
|
||||
return $this->db->createCommand()
|
||||
->delete($this->sessionTable, '[[expire]]<:expire', [':expire' => time()])
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a query to get the session from db
|
||||
* @param string $id The id of the session
|
||||
* @return Query
|
||||
*/
|
||||
protected function getReadQuery($id)
|
||||
{
|
||||
return (new Query())
|
||||
->from($this->sessionTable)
|
||||
->where('[[expire]]>:expire AND [[id]]=:id', [':expire' => time(), ':id' => $id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method typecasts $fields before passing them to PDO.
|
||||
* Default implementation casts field `data` to `\PDO::PARAM_LOB`.
|
||||
* You can override this method in case you need special type casting.
|
||||
*
|
||||
* @param array $fields Fields, that will be passed to PDO. Key - name, Value - value
|
||||
* @return array
|
||||
* @since 2.0.13
|
||||
*/
|
||||
protected function typecastFields($fields)
|
||||
{
|
||||
if (isset($fields['data']) && !is_array($fields['data']) && !is_object($fields['data'])) {
|
||||
$fields['data'] = new PdoValue($fields['data'], \PDO::PARAM_LOB);
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
}
|
||||
224
vendor/yiisoft/yii2/web/ErrorAction.php
vendored
Normal file
224
vendor/yiisoft/yii2/web/ErrorAction.php
vendored
Normal file
@ -0,0 +1,224 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Action;
|
||||
use yii\base\Exception;
|
||||
use yii\base\UserException;
|
||||
|
||||
/**
|
||||
* ErrorAction displays application errors using a specified view.
|
||||
*
|
||||
* To use ErrorAction, you need to do the following steps:
|
||||
*
|
||||
* First, declare an action of ErrorAction type in the `actions()` method of your `SiteController`
|
||||
* class (or whatever controller you prefer), like the following:
|
||||
*
|
||||
* ```
|
||||
* public function actions()
|
||||
* {
|
||||
* return [
|
||||
* 'error' => ['class' => 'yii\web\ErrorAction'],
|
||||
* ];
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Then, create a view file for this action. If the route of your error action is `site/error`, then
|
||||
* the view file should be `views/site/error.php`. In this view file, the following variables are available:
|
||||
*
|
||||
* - `$name`: the error name
|
||||
* - `$message`: the error message
|
||||
* - `$exception`: the exception being handled
|
||||
*
|
||||
* Finally, configure the "errorHandler" application component as follows,
|
||||
*
|
||||
* ```
|
||||
* 'errorHandler' => [
|
||||
* 'errorAction' => 'site/error',
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @author Dmitry Naumenko <d.naumenko.a@gmail.com>
|
||||
* @since 2.0
|
||||
*
|
||||
* @template T of Controller
|
||||
* @extends Action<T>
|
||||
*/
|
||||
class ErrorAction extends Action
|
||||
{
|
||||
/**
|
||||
* @var string|null the view file to be rendered. If not set, it will take the value of [[id]].
|
||||
* That means, if you name the action as "error" in "SiteController", then the view name
|
||||
* would be "error", and the corresponding view file would be "views/site/error.php".
|
||||
*/
|
||||
public $view;
|
||||
/**
|
||||
* @var string the name of the error when the exception name cannot be determined.
|
||||
* Defaults to "Error".
|
||||
*/
|
||||
public $defaultName;
|
||||
/**
|
||||
* @var string the message to be displayed when the exception message contains sensitive information.
|
||||
* Defaults to "An internal server error occurred.".
|
||||
*/
|
||||
public $defaultMessage;
|
||||
/**
|
||||
* @var string|null|false the name of the layout to be applied to this error action view.
|
||||
* If not set, the layout configured in the controller will be used.
|
||||
* @see \yii\base\Controller::$layout
|
||||
* @since 2.0.14
|
||||
*/
|
||||
public $layout;
|
||||
|
||||
/**
|
||||
* @var \Throwable the exception object, normally is filled on [[init()]] method call.
|
||||
* @see findException() to know default way of obtaining exception.
|
||||
* @since 2.0.11
|
||||
*/
|
||||
protected $exception;
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$this->exception = $this->findException();
|
||||
|
||||
if ($this->defaultMessage === null) {
|
||||
$this->defaultMessage = Yii::t('yii', 'An internal server error occurred.');
|
||||
}
|
||||
|
||||
if ($this->defaultName === null) {
|
||||
$this->defaultName = Yii::t('yii', 'Error');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the action.
|
||||
*
|
||||
* @return string result content
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
if ($this->layout !== null) {
|
||||
$this->controller->layout = $this->layout;
|
||||
}
|
||||
|
||||
Yii::$app->getResponse()->setStatusCodeByException($this->exception);
|
||||
|
||||
if (Yii::$app->getRequest()->getIsAjax()) {
|
||||
return $this->renderAjaxResponse();
|
||||
}
|
||||
|
||||
return $this->renderHtmlResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds string that represents the exception.
|
||||
* Normally used to generate a response to AJAX request.
|
||||
* @return string
|
||||
* @since 2.0.11
|
||||
*/
|
||||
protected function renderAjaxResponse()
|
||||
{
|
||||
return $this->getExceptionName() . ': ' . $this->getExceptionMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a view that represents the exception.
|
||||
* @return string
|
||||
* @since 2.0.11
|
||||
*/
|
||||
protected function renderHtmlResponse()
|
||||
{
|
||||
return $this->controller->render($this->view ?: $this->id, $this->getViewRenderParams());
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds array of parameters that will be passed to the view.
|
||||
* @return array
|
||||
* @since 2.0.11
|
||||
*/
|
||||
protected function getViewRenderParams()
|
||||
{
|
||||
return [
|
||||
'name' => $this->getExceptionName(),
|
||||
'message' => $this->getExceptionMessage(),
|
||||
'exception' => $this->exception,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets exception from the [[yii\web\ErrorHandler|ErrorHandler]] component.
|
||||
* In case there is no exception in the component, treat as the action has been invoked
|
||||
* not from error handler, but by direct route, so '404 Not Found' error will be displayed.
|
||||
* @return \Throwable
|
||||
* @since 2.0.11
|
||||
*/
|
||||
protected function findException()
|
||||
{
|
||||
if (($exception = Yii::$app->getErrorHandler()->exception) === null) {
|
||||
$exception = new NotFoundHttpException(Yii::t('yii', 'Page not found.'));
|
||||
}
|
||||
|
||||
return $exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the code from the [[exception]].
|
||||
* @return mixed
|
||||
* @since 2.0.11
|
||||
*/
|
||||
protected function getExceptionCode()
|
||||
{
|
||||
if ($this->exception instanceof HttpException) {
|
||||
return $this->exception->statusCode;
|
||||
}
|
||||
|
||||
return $this->exception->getCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exception name, followed by the code (if present).
|
||||
*
|
||||
* @return string
|
||||
* @since 2.0.11
|
||||
*/
|
||||
protected function getExceptionName()
|
||||
{
|
||||
if ($this->exception instanceof Exception) {
|
||||
$name = $this->exception->getName();
|
||||
} else {
|
||||
$name = $this->defaultName;
|
||||
}
|
||||
|
||||
if ($code = $this->getExceptionCode()) {
|
||||
$name .= " (#$code)";
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [[exception]] message for [[yii\base\UserException]] only.
|
||||
* For other cases [[defaultMessage]] will be returned.
|
||||
* @return string
|
||||
* @since 2.0.11
|
||||
*/
|
||||
protected function getExceptionMessage()
|
||||
{
|
||||
if ($this->exception instanceof UserException) {
|
||||
return $this->exception->getMessage();
|
||||
}
|
||||
|
||||
return $this->defaultMessage;
|
||||
}
|
||||
}
|
||||
508
vendor/yiisoft/yii2/web/ErrorHandler.php
vendored
Normal file
508
vendor/yiisoft/yii2/web/ErrorHandler.php
vendored
Normal file
@ -0,0 +1,508 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use Yii;
|
||||
use yii\base\ErrorException;
|
||||
use yii\base\Exception;
|
||||
use yii\base\UserException;
|
||||
use yii\helpers\VarDumper;
|
||||
|
||||
/**
|
||||
* ErrorHandler handles uncaught PHP errors and exceptions.
|
||||
*
|
||||
* ErrorHandler displays these errors using appropriate views based on the
|
||||
* nature of the errors and the mode the application runs at.
|
||||
*
|
||||
* ErrorHandler is configured as an application component in [[\yii\base\Application]] by default.
|
||||
* You can access that instance via `Yii::$app->errorHandler`.
|
||||
*
|
||||
* For more details and usage information on ErrorHandler, see the [guide article on handling errors](guide:runtime-handling-errors).
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @author Timur Ruziev <resurtm@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class ErrorHandler extends \yii\base\ErrorHandler
|
||||
{
|
||||
/**
|
||||
* @var int maximum number of source code lines to be displayed. Defaults to 19.
|
||||
*/
|
||||
public $maxSourceLines = 19;
|
||||
/**
|
||||
* @var int maximum number of trace source code lines to be displayed. Defaults to 13.
|
||||
*/
|
||||
public $maxTraceSourceLines = 13;
|
||||
/**
|
||||
* @var string|null the route (e.g. `site/error`) to the controller action that will be used
|
||||
* to display external errors. Inside the action, it can retrieve the error information
|
||||
* using `Yii::$app->errorHandler->exception`. This property defaults to null, meaning ErrorHandler
|
||||
* will handle the error display.
|
||||
*/
|
||||
public $errorAction;
|
||||
/**
|
||||
* @var string the path of the view file for rendering exceptions without call stack information.
|
||||
*/
|
||||
public $errorView = '@yii/views/errorHandler/error.php';
|
||||
/**
|
||||
* @var string the path of the view file for rendering exceptions.
|
||||
*/
|
||||
public $exceptionView = '@yii/views/errorHandler/exception.php';
|
||||
/**
|
||||
* @var string the path of the view file for rendering exceptions and errors call stack element.
|
||||
*/
|
||||
public $callStackItemView = '@yii/views/errorHandler/callStackItem.php';
|
||||
/**
|
||||
* @var string the path of the view file for rendering previous exceptions.
|
||||
*/
|
||||
public $previousExceptionView = '@yii/views/errorHandler/previousException.php';
|
||||
/**
|
||||
* @var array list of the PHP predefined variables that should be displayed on the error page.
|
||||
* Note that a variable must be accessible via `$GLOBALS`. Otherwise it won't be displayed.
|
||||
* Defaults to `['_GET', '_POST', '_FILES', '_COOKIE', '_SESSION']`.
|
||||
* @see renderRequest()
|
||||
* @since 2.0.7
|
||||
*/
|
||||
public $displayVars = ['_GET', '_POST', '_FILES', '_COOKIE', '_SESSION'];
|
||||
/**
|
||||
* @var string trace line with placeholders to be be substituted.
|
||||
* The placeholders are {file}, {line} and {text} and the string should be as follows.
|
||||
*
|
||||
* `File: {file} - Line: {line} - Text: {text}`
|
||||
*
|
||||
* @example <a href="ide://open?file={file}&line={line}">{html}</a>
|
||||
* @see https://github.com/yiisoft/yii2-debug#open-files-in-ide
|
||||
* @since 2.0.14
|
||||
*/
|
||||
public $traceLine = '{html}';
|
||||
|
||||
|
||||
/**
|
||||
* Renders the exception.
|
||||
* @param \Throwable $exception the exception to be rendered.
|
||||
*/
|
||||
protected function renderException($exception)
|
||||
{
|
||||
if (Yii::$app->has('response')) {
|
||||
$response = Yii::$app->getResponse();
|
||||
// reset parameters of response to avoid interference with partially created response data
|
||||
// in case the error occurred while sending the response.
|
||||
$response->isSent = false;
|
||||
$response->stream = null;
|
||||
$response->data = null;
|
||||
$response->content = null;
|
||||
} else {
|
||||
$response = new Response();
|
||||
}
|
||||
|
||||
$response->setStatusCodeByException($exception);
|
||||
|
||||
$useErrorView = $response->format === Response::FORMAT_HTML && (!YII_DEBUG || $exception instanceof UserException);
|
||||
|
||||
if ($useErrorView && $this->errorAction !== null) {
|
||||
/** @var View */
|
||||
$view = Yii::$app->view;
|
||||
$view->clear();
|
||||
$result = Yii::$app->runAction($this->errorAction);
|
||||
if ($result instanceof Response) {
|
||||
$response = $result;
|
||||
} else {
|
||||
$response->data = $result;
|
||||
}
|
||||
} elseif ($response->format === Response::FORMAT_HTML) {
|
||||
if ($this->shouldRenderSimpleHtml()) {
|
||||
// AJAX request
|
||||
$response->data = '<pre>' . $this->htmlEncode(static::convertExceptionToString($exception)) . '</pre>';
|
||||
} else {
|
||||
// if there is an error during error rendering it's useful to
|
||||
// display PHP error in debug mode instead of a blank screen
|
||||
if (YII_DEBUG) {
|
||||
ini_set('display_errors', 1);
|
||||
}
|
||||
$file = $useErrorView ? $this->errorView : $this->exceptionView;
|
||||
$response->data = $this->renderFile($file, [
|
||||
'exception' => $exception,
|
||||
]);
|
||||
}
|
||||
} elseif ($response->format === Response::FORMAT_RAW) {
|
||||
$response->data = static::convertExceptionToString($exception);
|
||||
} else {
|
||||
$response->data = $this->convertExceptionToArray($exception);
|
||||
}
|
||||
|
||||
$response->send();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an exception into an array.
|
||||
* @param \Throwable $exception the exception being converted
|
||||
* @return array the array representation of the exception.
|
||||
*/
|
||||
protected function convertExceptionToArray($exception)
|
||||
{
|
||||
if (!YII_DEBUG && !$exception instanceof UserException && !$exception instanceof HttpException) {
|
||||
$exception = new HttpException(500, Yii::t('yii', 'An internal server error occurred.'));
|
||||
}
|
||||
|
||||
$array = [
|
||||
'name' => ($exception instanceof Exception || $exception instanceof ErrorException) ? $exception->getName() : 'Exception',
|
||||
'message' => $exception->getMessage(),
|
||||
'code' => $exception->getCode(),
|
||||
];
|
||||
if ($exception instanceof HttpException) {
|
||||
$array['status'] = $exception->statusCode;
|
||||
}
|
||||
if (YII_DEBUG) {
|
||||
$array['type'] = get_class($exception);
|
||||
if (!$exception instanceof UserException) {
|
||||
$array['file'] = $exception->getFile();
|
||||
$array['line'] = $exception->getLine();
|
||||
$array['stack-trace'] = explode("\n", $exception->getTraceAsString());
|
||||
if ($exception instanceof \yii\db\Exception) {
|
||||
$array['error-info'] = $exception->errorInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (($prev = $exception->getPrevious()) !== null) {
|
||||
$array['previous'] = $this->convertExceptionToArray($prev);
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts special characters to HTML entities.
|
||||
* @param string $text to encode.
|
||||
* @return string encoded original text.
|
||||
*/
|
||||
public function htmlEncode($text)
|
||||
{
|
||||
return htmlspecialchars($text, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5, 'UTF-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds informational links to the given PHP type/class.
|
||||
* @param string $code type/class name to be linkified.
|
||||
* @return string linkified with HTML type/class name.
|
||||
*/
|
||||
public function addTypeLinks($code)
|
||||
{
|
||||
if (preg_match('/(.*?)::([^(]+)/', $code, $matches)) {
|
||||
$class = $matches[1];
|
||||
$method = $matches[2];
|
||||
$text = $this->htmlEncode($class) . '::' . $this->htmlEncode($method);
|
||||
} else {
|
||||
$class = $code;
|
||||
$method = null;
|
||||
$text = $this->htmlEncode($class);
|
||||
}
|
||||
|
||||
$url = null;
|
||||
|
||||
$shouldGenerateLink = true;
|
||||
if ($method !== null && strpos($method, '{closure') === false) {
|
||||
$reflection = new \ReflectionClass($class);
|
||||
if ($reflection->hasMethod($method)) {
|
||||
$reflectionMethod = $reflection->getMethod($method);
|
||||
$shouldGenerateLink = $reflectionMethod->isPublic() || $reflectionMethod->isProtected();
|
||||
} else {
|
||||
$shouldGenerateLink = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($shouldGenerateLink) {
|
||||
$url = $this->getTypeUrl($class, $method);
|
||||
}
|
||||
|
||||
if ($url === null) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
return '<a href="' . $url . '" target="_blank">' . $text . '</a>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the informational link URL for a given PHP type/class.
|
||||
* @param string $class the type or class name.
|
||||
* @param string|null $method the method name.
|
||||
* @return string|null the informational link URL.
|
||||
* @see addTypeLinks()
|
||||
*/
|
||||
protected function getTypeUrl($class, $method)
|
||||
{
|
||||
if (strncmp($class, 'yii\\', 4) !== 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$page = $this->htmlEncode(strtolower(str_replace('\\', '-', $class)));
|
||||
$url = "https://www.yiiframework.com/doc-2.0/$page.html";
|
||||
if ($method) {
|
||||
$url .= "#$method()-detail";
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a view file as a PHP script.
|
||||
* @param string $_file_ the view file.
|
||||
* @param array $_params_ the parameters (name-value pairs) that will be extracted and made available in the view file.
|
||||
* @return string the rendering result
|
||||
*/
|
||||
public function renderFile($_file_, $_params_)
|
||||
{
|
||||
$_params_['handler'] = $this;
|
||||
if ($this->exception instanceof ErrorException || !Yii::$app->has('view')) {
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
extract($_params_, EXTR_OVERWRITE);
|
||||
require Yii::getAlias($_file_);
|
||||
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/** @var View */
|
||||
$view = Yii::$app->getView();
|
||||
$view->clear();
|
||||
|
||||
return $view->renderFile($_file_, $_params_, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the previous exception stack for a given Exception.
|
||||
* @param \Throwable $exception the exception whose precursors should be rendered.
|
||||
* @return string HTML content of the rendered previous exceptions.
|
||||
* Empty string if there are none.
|
||||
*/
|
||||
public function renderPreviousExceptions($exception)
|
||||
{
|
||||
if (($previous = $exception->getPrevious()) !== null) {
|
||||
return $this->renderFile($this->previousExceptionView, ['exception' => $previous]);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a single call stack element.
|
||||
* @param string|null $file name where call has happened.
|
||||
* @param int|null $line number on which call has happened.
|
||||
* @param string|null $class called class name.
|
||||
* @param string|null $method called function/method name.
|
||||
* @param array $args array of method arguments.
|
||||
* @param int $index number of the call stack element.
|
||||
* @return string HTML content of the rendered call stack element.
|
||||
*/
|
||||
public function renderCallStackItem($file, $line, $class, $method, $args, $index)
|
||||
{
|
||||
$lines = [];
|
||||
$begin = $end = 0;
|
||||
if ($file !== null && $line !== null) {
|
||||
$line--; // adjust line number from one-based to zero-based
|
||||
$lines = @file($file);
|
||||
if ($line < 0 || $lines === false || ($lineCount = count($lines)) < $line) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$half = (int) (($index === 1 ? $this->maxSourceLines : $this->maxTraceSourceLines) / 2);
|
||||
$begin = $line - $half > 0 ? $line - $half : 0;
|
||||
$end = $line + $half < $lineCount ? $line + $half : $lineCount - 1;
|
||||
}
|
||||
|
||||
return $this->renderFile($this->callStackItemView, [
|
||||
'file' => $file,
|
||||
'line' => $line,
|
||||
'class' => $class,
|
||||
'method' => $method,
|
||||
'index' => $index,
|
||||
'lines' => $lines,
|
||||
'begin' => $begin,
|
||||
'end' => $end,
|
||||
'args' => $args,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders call stack.
|
||||
* @param \Throwable $exception exception to get call stack from
|
||||
* @return string HTML content of the rendered call stack.
|
||||
* @since 2.0.12
|
||||
*/
|
||||
public function renderCallStack($exception)
|
||||
{
|
||||
$out = '<ul>';
|
||||
$out .= $this->renderCallStackItem($exception->getFile(), $exception->getLine(), null, null, [], 1);
|
||||
for ($i = 0, $trace = $exception->getTrace(), $length = count($trace); $i < $length; ++$i) {
|
||||
$file = !empty($trace[$i]['file']) ? $trace[$i]['file'] : null;
|
||||
$line = !empty($trace[$i]['line']) ? $trace[$i]['line'] : null;
|
||||
$class = !empty($trace[$i]['class']) ? $trace[$i]['class'] : null;
|
||||
$function = null;
|
||||
if (!empty($trace[$i]['function']) && $trace[$i]['function'] !== 'unknown') {
|
||||
$function = $trace[$i]['function'];
|
||||
}
|
||||
$args = !empty($trace[$i]['args']) ? $trace[$i]['args'] : [];
|
||||
$out .= $this->renderCallStackItem($file, $line, $class, $function, $args, $i + 2);
|
||||
}
|
||||
$out .= '</ul>';
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the global variables of the request.
|
||||
* List of global variables is defined in [[displayVars]].
|
||||
* @return string the rendering result
|
||||
* @see displayVars
|
||||
*/
|
||||
public function renderRequest()
|
||||
{
|
||||
$request = '';
|
||||
foreach ($this->displayVars as $name) {
|
||||
if (!empty($GLOBALS[$name])) {
|
||||
$request .= '$' . $name . ' = ' . VarDumper::export($GLOBALS[$name]) . ";\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
return '<pre>' . $this->htmlEncode(rtrim($request, "\n")) . '</pre>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether given name of the file belongs to the framework.
|
||||
* @param string $file name to be checked.
|
||||
* @return bool whether given name of the file belongs to the framework.
|
||||
*/
|
||||
public function isCoreFile($file)
|
||||
{
|
||||
return $file === null || strpos(realpath($file), YII2_PATH . DIRECTORY_SEPARATOR) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates HTML containing link to the page with the information on given HTTP status code.
|
||||
* @param int $statusCode to be used to generate information link.
|
||||
* @param string $statusDescription Description to display after the the status code.
|
||||
* @return string generated HTML with HTTP status code information.
|
||||
*/
|
||||
public function createHttpStatusLink($statusCode, $statusDescription)
|
||||
{
|
||||
return '<a href="https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#' . (int) $statusCode . '" target="_blank">HTTP ' . (int) $statusCode . ' – ' . $statusDescription . '</a>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates string containing HTML link which refers to the home page of determined web-server software
|
||||
* and its full name.
|
||||
* @return string server software information hyperlink.
|
||||
*/
|
||||
public function createServerInformationLink()
|
||||
{
|
||||
$serverUrls = [
|
||||
'https://httpd.apache.org/' => ['apache'],
|
||||
'https://nginx.org/' => ['nginx'],
|
||||
'https://www.lighttpd.net/' => ['lighttpd'],
|
||||
'http://gwan.com/' => ['g-wan', 'gwan'],
|
||||
'https://www.iis.net/' => ['iis', 'services'],
|
||||
'https://www.php.net/manual/en/features.commandline.webserver.php' => ['development'],
|
||||
];
|
||||
if (isset($_SERVER['SERVER_SOFTWARE'])) {
|
||||
foreach ($serverUrls as $url => $keywords) {
|
||||
foreach ($keywords as $keyword) {
|
||||
if (stripos($_SERVER['SERVER_SOFTWARE'], $keyword) !== false) {
|
||||
return '<a href="' . $url . '" target="_blank">' . $this->htmlEncode($_SERVER['SERVER_SOFTWARE']) . '</a>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates string containing HTML link which refers to the page with the current version
|
||||
* of the framework and version number text.
|
||||
* @return string framework version information hyperlink.
|
||||
*/
|
||||
public function createFrameworkVersionLink()
|
||||
{
|
||||
return '<a href="https://github.com/yiisoft/yii2/" target="_blank">' . $this->htmlEncode(Yii::getVersion()) . '</a>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts arguments array to its string representation.
|
||||
*
|
||||
* @param array $args arguments array to be converted
|
||||
* @return string string representation of the arguments array
|
||||
*/
|
||||
public function argumentsToString($args)
|
||||
{
|
||||
$count = 0;
|
||||
$isAssoc = $args !== array_values($args);
|
||||
|
||||
foreach ($args as $key => $value) {
|
||||
$count++;
|
||||
if ($count >= 5) {
|
||||
if ($count > 5) {
|
||||
unset($args[$key]);
|
||||
} else {
|
||||
$args[$key] = '...';
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_object($value)) {
|
||||
$args[$key] = '<span class="title">' . $this->htmlEncode(get_class($value)) . '</span>';
|
||||
} elseif (is_bool($value)) {
|
||||
$args[$key] = '<span class="keyword">' . ($value ? 'true' : 'false') . '</span>';
|
||||
} elseif (is_string($value)) {
|
||||
$fullValue = $this->htmlEncode($value);
|
||||
if (mb_strlen($value, 'UTF-8') > 32) {
|
||||
$displayValue = $this->htmlEncode(mb_substr($value, 0, 32, 'UTF-8')) . '...';
|
||||
$args[$key] = "<span class=\"string\" title=\"$fullValue\">'$displayValue'</span>";
|
||||
} else {
|
||||
$args[$key] = "<span class=\"string\">'$fullValue'</span>";
|
||||
}
|
||||
} elseif (is_array($value)) {
|
||||
$args[$key] = '[' . $this->argumentsToString($value) . ']';
|
||||
} elseif ($value === null) {
|
||||
$args[$key] = '<span class="keyword">null</span>';
|
||||
} elseif (is_resource($value)) {
|
||||
$args[$key] = '<span class="keyword">resource</span>';
|
||||
} else {
|
||||
$args[$key] = '<span class="number">' . $value . '</span>';
|
||||
}
|
||||
|
||||
if (is_string($key)) {
|
||||
$args[$key] = '<span class="string">\'' . $this->htmlEncode($key) . "'</span> => $args[$key]";
|
||||
} elseif ($isAssoc) {
|
||||
$args[$key] = "<span class=\"number\">$key</span> => $args[$key]";
|
||||
}
|
||||
}
|
||||
|
||||
return implode(', ', $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns human-readable exception name.
|
||||
* @param \Throwable $exception
|
||||
* @return string|null human-readable exception name or null if it cannot be determined
|
||||
*/
|
||||
public function getExceptionName($exception)
|
||||
{
|
||||
if ($exception instanceof \yii\base\Exception || $exception instanceof \yii\base\InvalidCallException || $exception instanceof \yii\base\InvalidParamException || $exception instanceof \yii\base\UnknownMethodException) {
|
||||
return $exception->getName();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool if simple HTML should be rendered
|
||||
* @since 2.0.12
|
||||
*/
|
||||
protected function shouldRenderSimpleHtml()
|
||||
{
|
||||
return YII_ENV_TEST || Yii::$app->request->getIsAjax();
|
||||
}
|
||||
}
|
||||
34
vendor/yiisoft/yii2/web/ForbiddenHttpException.php
vendored
Normal file
34
vendor/yiisoft/yii2/web/ForbiddenHttpException.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* ForbiddenHttpException represents a "Forbidden" HTTP exception with status code 403.
|
||||
*
|
||||
* Use this exception when a user is not allowed to perform the requested action.
|
||||
* Using different credentials might or might not allow performing the requested action.
|
||||
* If you do not want to expose authorization information to the user, it is valid
|
||||
* to respond with a 404 [[NotFoundHttpException]].
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7231#section-6.5.3
|
||||
* @author Dan Schmidt <danschmidt5189@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class ForbiddenHttpException extends HttpException
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
* @param string|null $message error message
|
||||
* @param int $code error code
|
||||
* @param \Throwable|null $previous The previous exception used for the exception chaining.
|
||||
*/
|
||||
public function __construct($message = null, $code = 0, $previous = null)
|
||||
{
|
||||
parent::__construct(403, $message, $code, $previous);
|
||||
}
|
||||
}
|
||||
34
vendor/yiisoft/yii2/web/GoneHttpException.php
vendored
Normal file
34
vendor/yiisoft/yii2/web/GoneHttpException.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* GoneHttpException represents a "Gone" HTTP exception with status code 410.
|
||||
*
|
||||
* Throw a GoneHttpException when a user requests a resource that no longer exists
|
||||
* at the requested url. For example, after a record is deleted, future requests
|
||||
* for that record should return a 410 GoneHttpException instead of a 404
|
||||
* [[NotFoundHttpException]].
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7231#section-6.5.9
|
||||
* @author Dan Schmidt <danschmidt5189@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class GoneHttpException extends HttpException
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
* @param string|null $message error message
|
||||
* @param int $code error code
|
||||
* @param \Throwable|null $previous The previous exception used for the exception chaining.
|
||||
*/
|
||||
public function __construct($message = null, $code = 0, $previous = null)
|
||||
{
|
||||
parent::__construct(410, $message, $code, $previous);
|
||||
}
|
||||
}
|
||||
144
vendor/yiisoft/yii2/web/GroupUrlRule.php
vendored
Normal file
144
vendor/yiisoft/yii2/web/GroupUrlRule.php
vendored
Normal file
@ -0,0 +1,144 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use Yii;
|
||||
use yii\base\InvalidConfigException;
|
||||
|
||||
/**
|
||||
* GroupUrlRule represents a collection of URL rules sharing the same prefix in their patterns and routes.
|
||||
*
|
||||
* GroupUrlRule is best used by a module which often uses module ID as the prefix for the URL rules.
|
||||
* For example, the following code creates a rule for the `admin` module:
|
||||
*
|
||||
* ```
|
||||
* new GroupUrlRule([
|
||||
* 'prefix' => 'admin',
|
||||
* 'rules' => [
|
||||
* 'login' => 'user/login',
|
||||
* 'logout' => 'user/logout',
|
||||
* 'dashboard' => 'default/dashboard',
|
||||
* ],
|
||||
* ]);
|
||||
*
|
||||
* // the above rule is equivalent to the following three rules:
|
||||
*
|
||||
* [
|
||||
* 'admin/login' => 'admin/user/login',
|
||||
* 'admin/logout' => 'admin/user/logout',
|
||||
* 'admin/dashboard' => 'admin/default/dashboard',
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* The above example assumes the prefix for patterns and routes are the same. They can be made different
|
||||
* by configuring [[prefix]] and [[routePrefix]] separately.
|
||||
*
|
||||
* Using a GroupUrlRule is more efficient than directly declaring the individual rules it contains.
|
||||
* This is because GroupUrlRule can quickly determine if it should process a URL parsing or creation request
|
||||
* by simply checking if the prefix matches.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class GroupUrlRule extends CompositeUrlRule
|
||||
{
|
||||
/**
|
||||
* @var UrlRuleInterface[]|array[]|string[] the rules contained within this composite rule. Please refer to [[UrlManager::rules]]
|
||||
* for the format of this property.
|
||||
* @see prefix
|
||||
* @see routePrefix
|
||||
*/
|
||||
public $rules = [];
|
||||
/**
|
||||
* @var string the prefix for the pattern part of every rule declared in [[rules]].
|
||||
* The prefix and the pattern will be separated with a slash.
|
||||
*/
|
||||
public $prefix;
|
||||
/**
|
||||
* @var string|null the prefix for the route part of every rule declared in [[rules]].
|
||||
* The prefix and the route will be separated with a slash.
|
||||
* If this property is not set, it will take the value of [[prefix]].
|
||||
*/
|
||||
public $routePrefix;
|
||||
/**
|
||||
* @var array the default configuration of URL rules. Individual rule configurations
|
||||
* specified via [[rules]] will take precedence when the same property of the rule is configured.
|
||||
*/
|
||||
public $ruleConfig = ['class' => 'yii\web\UrlRule'];
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$this->prefix = trim((string)$this->prefix, '/');
|
||||
$this->routePrefix = $this->routePrefix === null ? $this->prefix : trim($this->routePrefix, '/');
|
||||
parent::init();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createRules()
|
||||
{
|
||||
$rules = [];
|
||||
foreach ($this->rules as $key => $rule) {
|
||||
if (!is_array($rule)) {
|
||||
$verbs = 'GET|HEAD|POST|PUT|PATCH|DELETE|OPTIONS';
|
||||
$verb = null;
|
||||
if (preg_match("/^((?:(?:$verbs),)*(?:$verbs))\\s+(.*)$/", $key, $matches)) {
|
||||
$verb = explode(',', $matches[1]);
|
||||
$key = $matches[2];
|
||||
}
|
||||
$rule = [
|
||||
'pattern' => ltrim($this->prefix . '/' . $key, '/'),
|
||||
'route' => ltrim($this->routePrefix . '/' . $rule, '/'),
|
||||
'verb' => $verb
|
||||
];
|
||||
} elseif (isset($rule['pattern'], $rule['route'])) {
|
||||
$rule['pattern'] = ltrim($this->prefix . '/' . $rule['pattern'], '/');
|
||||
$rule['route'] = ltrim($this->routePrefix . '/' . $rule['route'], '/');
|
||||
}
|
||||
|
||||
$rule = Yii::createObject(array_merge($this->ruleConfig, $rule));
|
||||
if (!$rule instanceof UrlRuleInterface) {
|
||||
throw new InvalidConfigException('URL rule class must implement UrlRuleInterface.');
|
||||
}
|
||||
$rules[] = $rule;
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseRequest($manager, $request)
|
||||
{
|
||||
$pathInfo = $request->getPathInfo();
|
||||
if ($this->prefix === '' || strpos($pathInfo . '/', $this->prefix . '/') === 0) {
|
||||
return parent::parseRequest($manager, $request);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createUrl($manager, $route, $params)
|
||||
{
|
||||
if ($this->routePrefix === '' || strpos($route, $this->routePrefix . '/') === 0) {
|
||||
return parent::createUrl($manager, $route, $params);
|
||||
}
|
||||
|
||||
$this->createStatus = UrlRule::CREATE_STATUS_ROUTE_MISMATCH;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
282
vendor/yiisoft/yii2/web/HeaderCollection.php
vendored
Normal file
282
vendor/yiisoft/yii2/web/HeaderCollection.php
vendored
Normal file
@ -0,0 +1,282 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use yii\base\BaseObject;
|
||||
|
||||
/**
|
||||
* HeaderCollection is used by [[Response]] to maintain the currently registered HTTP headers.
|
||||
*
|
||||
* @property-read int $count The number of headers in the collection.
|
||||
* @property-read \ArrayIterator $iterator An iterator for traversing the headers in the collection.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*
|
||||
* @implements \IteratorAggregate<string, string[]>
|
||||
* @implements \ArrayAccess<string, string|null>
|
||||
*
|
||||
* @phpstan-property-read \ArrayIterator<string, string[]> $iterator
|
||||
* @psalm-property-read \ArrayIterator<string, string[]> $iterator
|
||||
*/
|
||||
class HeaderCollection extends BaseObject implements \IteratorAggregate, \ArrayAccess, \Countable
|
||||
{
|
||||
/**
|
||||
* @var array the headers in this collection (indexed by the normalized header names)
|
||||
*
|
||||
* @phpstan-var array<string, string[]>
|
||||
*/
|
||||
private $_headers = [];
|
||||
/**
|
||||
* @var array the original names of the headers (indexed by the normalized header names)
|
||||
*
|
||||
* @phpstan-var array<string, string>
|
||||
*/
|
||||
private $_originalHeaderNames = [];
|
||||
|
||||
|
||||
/**
|
||||
* Returns an iterator for traversing the headers in the collection.
|
||||
* This method is required by the SPL interface [[\IteratorAggregate]].
|
||||
* It will be implicitly called when you use `foreach` to traverse the collection.
|
||||
* @return \ArrayIterator an iterator for traversing the headers in the collection.
|
||||
*
|
||||
* @phpstan-return \ArrayIterator<string, string[]>
|
||||
* @psalm-return \ArrayIterator<string, string[]>
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->_headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of headers in the collection.
|
||||
* This method is required by the SPL `Countable` interface.
|
||||
* It will be implicitly called when you use `count($collection)`.
|
||||
* @return int the number of headers in the collection.
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function count()
|
||||
{
|
||||
return $this->getCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of headers in the collection.
|
||||
* @return int the number of headers in the collection.
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getCount()
|
||||
{
|
||||
return count($this->_headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the named header(s).
|
||||
* @param string $name the name of the header to return
|
||||
* @param string|array|null $default the value to return in case the named header does not exist
|
||||
* @param bool $first whether to only return the first header of the specified name.
|
||||
* If false, all headers of the specified name will be returned.
|
||||
* @return string|array|null the named header(s). If `$first` is true, a string will be returned;
|
||||
* If `$first` is false, an array will be returned.
|
||||
*
|
||||
* @phpstan-param ($first is true ? string|null : string[]|null) $default
|
||||
* @psalm-param ($first is true ? string|null : string[]|null) $default
|
||||
*
|
||||
* @phpstan-return ($first is true ? string|null : string[]|null)
|
||||
* @psalm-return ($first is true ? string|null : string[]|null)
|
||||
*/
|
||||
public function get($name, $default = null, $first = true)
|
||||
{
|
||||
$normalizedName = strtolower($name);
|
||||
if (isset($this->_headers[$normalizedName])) {
|
||||
return $first ? reset($this->_headers[$normalizedName]) : $this->_headers[$normalizedName];
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new header.
|
||||
* If there is already a header with the same name, it will be replaced.
|
||||
* @param string $name the name of the header
|
||||
* @param string $value the value of the header
|
||||
* @return $this the collection object itself
|
||||
*/
|
||||
public function set($name, $value = '')
|
||||
{
|
||||
$normalizedName = strtolower($name);
|
||||
$this->_headers[$normalizedName] = (array) $value;
|
||||
$this->_originalHeaderNames[$normalizedName] = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new header.
|
||||
* If there is already a header with the same name, the new one will
|
||||
* be appended to it instead of replacing it.
|
||||
* @param string $name the name of the header
|
||||
* @param string $value the value of the header
|
||||
* @return $this the collection object itself
|
||||
*/
|
||||
public function add($name, $value)
|
||||
{
|
||||
$normalizedName = strtolower($name);
|
||||
$this->_headers[$normalizedName][] = $value;
|
||||
if (!\array_key_exists($normalizedName, $this->_originalHeaderNames)) {
|
||||
$this->_originalHeaderNames[$normalizedName] = $name;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new header only if it does not exist yet.
|
||||
* If there is already a header with the same name, the new one will be ignored.
|
||||
* @param string $name the name of the header
|
||||
* @param string $value the value of the header
|
||||
* @return $this the collection object itself
|
||||
*/
|
||||
public function setDefault($name, $value)
|
||||
{
|
||||
$normalizedName = strtolower($name);
|
||||
if (empty($this->_headers[$normalizedName])) {
|
||||
$this->_headers[$normalizedName][] = $value;
|
||||
$this->_originalHeaderNames[$normalizedName] = $name;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a value indicating whether the named header exists.
|
||||
* @param string $name the name of the header
|
||||
* @return bool whether the named header exists
|
||||
*/
|
||||
public function has($name)
|
||||
{
|
||||
return isset($this->_headers[strtolower($name)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a header.
|
||||
* @param string $name the name of the header to be removed.
|
||||
* @return array|null the value of the removed header. Null is returned if the header does not exist.
|
||||
*/
|
||||
public function remove($name)
|
||||
{
|
||||
$normalizedName = strtolower($name);
|
||||
if (isset($this->_headers[$normalizedName])) {
|
||||
$value = $this->_headers[$normalizedName];
|
||||
unset($this->_headers[$normalizedName], $this->_originalHeaderNames[$normalizedName]);
|
||||
return $value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all headers.
|
||||
*/
|
||||
public function removeAll()
|
||||
{
|
||||
$this->_headers = [];
|
||||
$this->_originalHeaderNames = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the collection as a PHP array.
|
||||
* @return array the array representation of the collection.
|
||||
* The array keys are header names, and the array values are the corresponding header values.
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return $this->_headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the collection as a PHP array but instead of using normalized header names as keys (like [[toArray()]])
|
||||
* it uses original header names (case-sensitive).
|
||||
* @return array the array representation of the collection.
|
||||
* @since 2.0.45
|
||||
*/
|
||||
public function toOriginalArray()
|
||||
{
|
||||
return \array_map(function ($normalizedName) {
|
||||
return $this->_headers[$normalizedName];
|
||||
}, \array_flip($this->_originalHeaderNames));
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the header collection from an array.
|
||||
* @param array $array the headers to populate from
|
||||
* @since 2.0.3
|
||||
*/
|
||||
public function fromArray(array $array)
|
||||
{
|
||||
foreach ($array as $name => $value) {
|
||||
$this->set($name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether there is a header with the specified name.
|
||||
* This method is required by the SPL interface [[\ArrayAccess]].
|
||||
* It is implicitly called when you use something like `isset($collection[$name])`.
|
||||
* @param string $name the header name
|
||||
* @return bool whether the named header exists
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetExists($name)
|
||||
{
|
||||
return $this->has($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the header with the specified name.
|
||||
* This method is required by the SPL interface [[\ArrayAccess]].
|
||||
* It is implicitly called when you use something like `$header = $collection[$name];`.
|
||||
* This is equivalent to [[get()]].
|
||||
* @param string $name the header name
|
||||
* @return string|null the header value with the specified name, null if the named header does not exist.
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetGet($name)
|
||||
{
|
||||
return $this->get($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the header to the collection.
|
||||
* This method is required by the SPL interface [[\ArrayAccess]].
|
||||
* It is implicitly called when you use something like `$collection[$name] = $header;`.
|
||||
* This is equivalent to [[add()]].
|
||||
* @param string $name the header name
|
||||
* @param string $value the header value to be added
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetSet($name, $value)
|
||||
{
|
||||
$this->set($name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the named header.
|
||||
* This method is required by the SPL interface [[\ArrayAccess]].
|
||||
* It is implicitly called when you use something like `unset($collection[$name])`.
|
||||
* This is equivalent to [[remove()]].
|
||||
* @param string $name the header name
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetUnset($name)
|
||||
{
|
||||
$this->remove($name);
|
||||
}
|
||||
}
|
||||
29
vendor/yiisoft/yii2/web/HeadersAlreadySentException.php
vendored
Normal file
29
vendor/yiisoft/yii2/web/HeadersAlreadySentException.php
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use yii\base\Exception;
|
||||
|
||||
/**
|
||||
* HeadersAlreadySentException represents an exception caused by
|
||||
* any headers that were already sent before web response was sent.
|
||||
*
|
||||
* @author Dmitry Dorogin <dmirogin@ya.ru>
|
||||
* @since 2.0.14
|
||||
*/
|
||||
class HeadersAlreadySentException extends Exception
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct($file, $line)
|
||||
{
|
||||
$message = YII_DEBUG ? "Headers already sent in {$file} on line {$line}." : 'Headers already sent.';
|
||||
parent::__construct($message);
|
||||
}
|
||||
}
|
||||
42
vendor/yiisoft/yii2/web/HtmlResponseFormatter.php
vendored
Normal file
42
vendor/yiisoft/yii2/web/HtmlResponseFormatter.php
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use yii\base\Component;
|
||||
|
||||
/**
|
||||
* HtmlResponseFormatter formats the given data into an HTML response content.
|
||||
*
|
||||
* It is used by [[Response]] to format response data.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class HtmlResponseFormatter extends Component implements ResponseFormatterInterface
|
||||
{
|
||||
/**
|
||||
* @var string the Content-Type header for the response
|
||||
*/
|
||||
public $contentType = 'text/html';
|
||||
|
||||
|
||||
/**
|
||||
* Formats the specified response.
|
||||
* @param Response $response the response to be formatted.
|
||||
*/
|
||||
public function format($response)
|
||||
{
|
||||
if (stripos($this->contentType, 'charset') === false) {
|
||||
$this->contentType .= '; charset=' . $response->charset;
|
||||
}
|
||||
$response->getHeaders()->set('Content-Type', $this->contentType);
|
||||
if ($response->data !== null) {
|
||||
$response->content = $response->data;
|
||||
}
|
||||
}
|
||||
}
|
||||
62
vendor/yiisoft/yii2/web/HttpException.php
vendored
Normal file
62
vendor/yiisoft/yii2/web/HttpException.php
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use yii\base\UserException;
|
||||
|
||||
/**
|
||||
* HttpException represents an exception caused by an improper request of the end-user.
|
||||
*
|
||||
* HttpException can be differentiated via its [[statusCode]] property value which
|
||||
* keeps a standard HTTP status code (e.g. 404, 500). Error handlers may use this status code
|
||||
* to decide how to format the error page.
|
||||
*
|
||||
* Throwing an HttpException like in the following example will result in the 404 page to be displayed.
|
||||
*
|
||||
* ```
|
||||
* if ($item === null) { // item does not exist
|
||||
* throw new \yii\web\HttpException(404, 'The requested Item could not be found.');
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class HttpException extends UserException
|
||||
{
|
||||
/**
|
||||
* @var int HTTP status code, such as 403, 404, 500, etc.
|
||||
*/
|
||||
public $statusCode;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param int $status HTTP status code, such as 404, 500, etc.
|
||||
* @param string|null $message error message
|
||||
* @param int $code error code
|
||||
* @param \Throwable|null $previous The previous exception used for the exception chaining.
|
||||
*/
|
||||
public function __construct($status, $message = null, $code = 0, $previous = null)
|
||||
{
|
||||
$this->statusCode = $status;
|
||||
parent::__construct((string)$message, $code, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the user-friendly name of this exception
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
if (isset(Response::$httpStatuses[$this->statusCode])) {
|
||||
return Response::$httpStatuses[$this->statusCode];
|
||||
}
|
||||
|
||||
return 'Error';
|
||||
}
|
||||
}
|
||||
110
vendor/yiisoft/yii2/web/IdentityInterface.php
vendored
Normal file
110
vendor/yiisoft/yii2/web/IdentityInterface.php
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* IdentityInterface is the interface that should be implemented by a class providing identity information.
|
||||
*
|
||||
* This interface can typically be implemented by a user model class. For example, the following
|
||||
* code shows how to implement this interface by a User ActiveRecord class:
|
||||
*
|
||||
* ```
|
||||
* class User extends ActiveRecord implements IdentityInterface
|
||||
* {
|
||||
* public static function findIdentity($id)
|
||||
* {
|
||||
* return static::findOne($id);
|
||||
* }
|
||||
*
|
||||
* public static function findIdentityByAccessToken($token, $type = null)
|
||||
* {
|
||||
* return static::findOne(['access_token' => $token]);
|
||||
* }
|
||||
*
|
||||
* public function getId()
|
||||
* {
|
||||
* return $this->id;
|
||||
* }
|
||||
*
|
||||
* public function getAuthKey()
|
||||
* {
|
||||
* return $this->authKey;
|
||||
* }
|
||||
*
|
||||
* public function validateAuthKey($authKey)
|
||||
* {
|
||||
* return $this->authKey === $authKey;
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* In some situations not all of these methods are required to be implemented.
|
||||
* For example, if your application is a pure stateless RESTful application,
|
||||
* you would only need to implement [[yii\web\IdentityInterface::findIdentityByAccessToken()|findIdentityByAccessToken()]]
|
||||
* and [[yii\web\IdentityInterface::getId()|getId()]] while leaving all other methods with an empty body.
|
||||
* Or if your application uses session only authentication, you would need to implement all the methods
|
||||
* except [[yii\web\IdentityInterface::findIdentityByAccessToken()|findIdentityByAccessToken()]].
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
interface IdentityInterface
|
||||
{
|
||||
/**
|
||||
* Finds an identity by the given ID.
|
||||
* @param string|int $id the ID to be looked for
|
||||
* @return IdentityInterface|null the identity object that matches the given ID.
|
||||
* Null should be returned if such an identity cannot be found
|
||||
* or the identity is not in an active state (disabled, deleted, etc.)
|
||||
*/
|
||||
public static function findIdentity($id);
|
||||
|
||||
/**
|
||||
* Finds an identity by the given token.
|
||||
* @param mixed $token the token to be looked for
|
||||
* @param mixed $type the type of the token. The value of this parameter depends on the implementation.
|
||||
* For example, [[\yii\filters\auth\HttpBearerAuth]] will set this parameter to be `yii\filters\auth\HttpBearerAuth`.
|
||||
* @return IdentityInterface|null the identity object that matches the given token.
|
||||
* Null should be returned if such an identity cannot be found
|
||||
* or the identity is not in an active state (disabled, deleted, etc.)
|
||||
*/
|
||||
public static function findIdentityByAccessToken($token, $type = null);
|
||||
|
||||
/**
|
||||
* Returns an ID that can uniquely identify a user identity.
|
||||
* @return string|int an ID that uniquely identifies a user identity.
|
||||
*/
|
||||
public function getId();
|
||||
|
||||
/**
|
||||
* Returns a key that can be used to check the validity of a given identity ID.
|
||||
*
|
||||
* The key should be unique for each individual user, and should be persistent
|
||||
* so that it can be used to check the validity of the user identity.
|
||||
*
|
||||
* The space of such keys should be big enough to defeat potential identity attacks.
|
||||
*
|
||||
* The returned key is used to validate session and auto-login (if [[User::enableAutoLogin]] is enabled).
|
||||
*
|
||||
* Make sure to invalidate earlier issued authKeys when you implement force user logout, password change and
|
||||
* other scenarios, that require forceful access revocation for old sessions.
|
||||
*
|
||||
* @return string|null a key that is used to check the validity of a given identity ID.
|
||||
* @see validateAuthKey()
|
||||
*/
|
||||
public function getAuthKey();
|
||||
|
||||
/**
|
||||
* Validates the given auth key.
|
||||
*
|
||||
* @param string $authKey the given auth key
|
||||
* @return bool|null whether the given auth key is valid.
|
||||
* @see getAuthKey()
|
||||
*/
|
||||
public function validateAuthKey($authKey);
|
||||
}
|
||||
22
vendor/yiisoft/yii2/web/JqueryAsset.php
vendored
Normal file
22
vendor/yiisoft/yii2/web/JqueryAsset.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* This asset bundle provides the [jQuery](https://jquery.com/) JavaScript library.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class JqueryAsset extends AssetBundle
|
||||
{
|
||||
public $sourcePath = '@bower/jquery/dist';
|
||||
public $js = [
|
||||
'jquery.js',
|
||||
];
|
||||
}
|
||||
48
vendor/yiisoft/yii2/web/JsExpression.php
vendored
Normal file
48
vendor/yiisoft/yii2/web/JsExpression.php
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use yii\base\BaseObject;
|
||||
|
||||
/**
|
||||
* `JsExpression` marks a string as a JavaScript expression.
|
||||
*
|
||||
* When using [[\yii\helpers\Json::encode()]] or [[\yii\helpers\Json::htmlEncode()]] to encode a value, `JsExpression` objects
|
||||
* will be specially handled and encoded as a JavaScript expression instead of a string.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class JsExpression extends BaseObject
|
||||
{
|
||||
/**
|
||||
* @var string the JavaScript expression represented by this object
|
||||
*/
|
||||
public $expression;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param string $expression the JavaScript expression represented by this object
|
||||
* @param array $config additional configurations for this object
|
||||
*/
|
||||
public function __construct($expression, $config = [])
|
||||
{
|
||||
$this->expression = $expression;
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* The PHP magic function converting an object into a string.
|
||||
* @return string the JavaScript expression.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return (string) $this->expression;
|
||||
}
|
||||
}
|
||||
66
vendor/yiisoft/yii2/web/JsonParser.php
vendored
Normal file
66
vendor/yiisoft/yii2/web/JsonParser.php
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use yii\base\InvalidArgumentException;
|
||||
use yii\helpers\Json;
|
||||
|
||||
/**
|
||||
* Parses a raw HTTP request using [[\yii\helpers\Json::decode()]].
|
||||
*
|
||||
* To enable parsing for JSON requests you can configure [[Request::parsers]] using this class:
|
||||
*
|
||||
* ```
|
||||
* 'request' => [
|
||||
* 'parsers' => [
|
||||
* 'application/json' => 'yii\web\JsonParser',
|
||||
* ]
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* @author Dan Schmidt <danschmidt5189@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class JsonParser implements RequestParserInterface
|
||||
{
|
||||
/**
|
||||
* @var bool whether to return objects in terms of associative arrays.
|
||||
*/
|
||||
public $asArray = true;
|
||||
/**
|
||||
* @var bool whether to throw a [[BadRequestHttpException]] if the body is invalid JSON
|
||||
*/
|
||||
public $throwException = true;
|
||||
|
||||
|
||||
/**
|
||||
* Parses a HTTP request body.
|
||||
* @param string $rawBody the raw HTTP request body.
|
||||
* @param string $contentType the content type specified for the request body.
|
||||
* @return array|\stdClass parameters parsed from the request body
|
||||
* @throws BadRequestHttpException if the body contains invalid json and [[throwException]] is `true`.
|
||||
*/
|
||||
public function parse($rawBody, $contentType)
|
||||
{
|
||||
// converts JSONP to JSON
|
||||
if (strpos($contentType, 'application/javascript') !== false) {
|
||||
$rawBody = preg_filter('/(^[^{]+|[^}]+$)/', '', $rawBody);
|
||||
}
|
||||
|
||||
try {
|
||||
$parameters = Json::decode($rawBody, $this->asArray);
|
||||
return $parameters === null ? [] : $parameters;
|
||||
} catch (InvalidArgumentException $e) {
|
||||
if ($this->throwException) {
|
||||
throw new BadRequestHttpException('Invalid JSON data in request body: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
164
vendor/yiisoft/yii2/web/JsonResponseFormatter.php
vendored
Normal file
164
vendor/yiisoft/yii2/web/JsonResponseFormatter.php
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Component;
|
||||
use yii\helpers\Json;
|
||||
|
||||
/**
|
||||
* JsonResponseFormatter formats the given data into a JSON or JSONP response content.
|
||||
*
|
||||
* It is used by [[Response]] to format response data.
|
||||
*
|
||||
* To configure properties like [[encodeOptions]] or [[prettyPrint]], you can configure the `response`
|
||||
* application component like the following:
|
||||
*
|
||||
* ```
|
||||
* 'response' => [
|
||||
* // ...
|
||||
* 'formatters' => [
|
||||
* \yii\web\Response::FORMAT_JSON => [
|
||||
* 'class' => 'yii\web\JsonResponseFormatter',
|
||||
* 'prettyPrint' => YII_DEBUG, // use "pretty" output in debug mode
|
||||
* 'keepObjectType' => false, // keep object type for zero-indexed objects
|
||||
* // ...
|
||||
* ],
|
||||
* ],
|
||||
* ],
|
||||
* ```
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class JsonResponseFormatter extends Component implements ResponseFormatterInterface
|
||||
{
|
||||
/**
|
||||
* JSON Content Type
|
||||
* @since 2.0.14
|
||||
*/
|
||||
public const CONTENT_TYPE_JSONP = 'application/javascript; charset=UTF-8';
|
||||
/**
|
||||
* JSONP Content Type
|
||||
* @since 2.0.14
|
||||
*/
|
||||
public const CONTENT_TYPE_JSON = 'application/json; charset=UTF-8';
|
||||
/**
|
||||
* HAL JSON Content Type
|
||||
* @since 2.0.14
|
||||
*/
|
||||
public const CONTENT_TYPE_HAL_JSON = 'application/hal+json; charset=UTF-8';
|
||||
/**
|
||||
* @var string|null custom value of the `Content-Type` header of the response.
|
||||
* When equals `null` default content type will be used based on the `useJsonp` property.
|
||||
* @since 2.0.14
|
||||
*/
|
||||
public $contentType;
|
||||
/**
|
||||
* @var bool whether to use JSONP response format. When this is true, the [[Response::data|response data]]
|
||||
* must be an array consisting of `data` and `callback` members. The latter should be a JavaScript
|
||||
* function name while the former will be passed to this function as a parameter.
|
||||
*/
|
||||
public $useJsonp = false;
|
||||
/**
|
||||
* @var int the encoding options passed to [[Json::encode()]]. For more details please refer to
|
||||
* <https://www.php.net/manual/en/function.json-encode.php>.
|
||||
* Default is `JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE`.
|
||||
* This property has no effect, when [[useJsonp]] is `true`.
|
||||
* @since 2.0.7
|
||||
*/
|
||||
public $encodeOptions = 320;
|
||||
/**
|
||||
* @var bool whether to format the output in a readable "pretty" format. This can be useful for debugging purpose.
|
||||
* If this is true, `JSON_PRETTY_PRINT` will be added to [[encodeOptions]].
|
||||
* Defaults to `false`.
|
||||
* This property has no effect, when [[useJsonp]] is `true`.
|
||||
* @since 2.0.7
|
||||
*/
|
||||
public $prettyPrint = false;
|
||||
/**
|
||||
* @var bool Avoids objects with zero-indexed keys to be encoded as array
|
||||
* Json::encode((object)['test']) will be encoded as an object not array. This matches the behaviour of json_encode().
|
||||
* Defaults to Json::$keepObjectType value
|
||||
* @since 2.0.44
|
||||
*/
|
||||
public $keepObjectType;
|
||||
|
||||
|
||||
/**
|
||||
* Formats the specified response.
|
||||
* @param Response $response the response to be formatted.
|
||||
*/
|
||||
public function format($response)
|
||||
{
|
||||
if ($this->contentType === null) {
|
||||
$this->contentType = $this->useJsonp
|
||||
? self::CONTENT_TYPE_JSONP
|
||||
: self::CONTENT_TYPE_JSON;
|
||||
} elseif (strpos($this->contentType, 'charset') === false) {
|
||||
$this->contentType .= '; charset=UTF-8';
|
||||
}
|
||||
$response->getHeaders()->set('Content-Type', $this->contentType);
|
||||
|
||||
if ($this->useJsonp) {
|
||||
$this->formatJsonp($response);
|
||||
} else {
|
||||
$this->formatJson($response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats response data in JSON format.
|
||||
* @param Response $response
|
||||
*/
|
||||
protected function formatJson($response)
|
||||
{
|
||||
if ($response->data !== null) {
|
||||
$options = $this->encodeOptions;
|
||||
if ($this->prettyPrint) {
|
||||
$options |= JSON_PRETTY_PRINT;
|
||||
}
|
||||
|
||||
$default = Json::$keepObjectType;
|
||||
if ($this->keepObjectType !== null) {
|
||||
Json::$keepObjectType = $this->keepObjectType;
|
||||
}
|
||||
|
||||
$response->content = Json::encode($response->data, $options);
|
||||
|
||||
// Restore default value to avoid any unexpected behaviour
|
||||
Json::$keepObjectType = $default;
|
||||
} elseif ($response->content === null) {
|
||||
$response->content = 'null';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats response data in JSONP format.
|
||||
* @param Response $response
|
||||
*/
|
||||
protected function formatJsonp($response)
|
||||
{
|
||||
if (
|
||||
is_array($response->data)
|
||||
&& isset($response->data['data'], $response->data['callback'])
|
||||
) {
|
||||
$response->content = sprintf(
|
||||
'%s(%s);',
|
||||
$response->data['callback'],
|
||||
Json::htmlEncode($response->data['data'])
|
||||
);
|
||||
} elseif ($response->data !== null) {
|
||||
$response->content = '';
|
||||
Yii::warning(
|
||||
"The 'jsonp' response requires that the data be an array consisting of both 'data' and 'callback' elements.",
|
||||
__METHOD__
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
74
vendor/yiisoft/yii2/web/Link.php
vendored
Normal file
74
vendor/yiisoft/yii2/web/Link.php
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use yii\base\BaseObject;
|
||||
|
||||
/**
|
||||
* Link represents a link object as defined in [JSON Hypermedia API Language](https://tools.ietf.org/html/draft-kelly-json-hal-03).
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class Link extends BaseObject
|
||||
{
|
||||
/**
|
||||
* The self link.
|
||||
*/
|
||||
public const REL_SELF = 'self';
|
||||
/**
|
||||
* @var string a URI [RFC3986](https://tools.ietf.org/html/rfc3986) or
|
||||
* URI template [RFC6570](https://tools.ietf.org/html/rfc6570). This property is required.
|
||||
*/
|
||||
public $href;
|
||||
/**
|
||||
* @var string a secondary key for selecting Link Objects which share the same relation type
|
||||
*/
|
||||
public $name;
|
||||
/**
|
||||
* @var string a hint to indicate the media type expected when dereferencing the target resource
|
||||
*/
|
||||
public $type;
|
||||
/**
|
||||
* @var bool a value indicating whether [[href]] refers to a URI or URI template.
|
||||
*/
|
||||
public $templated = false;
|
||||
/**
|
||||
* @var string a URI that hints about the profile of the target resource.
|
||||
*/
|
||||
public $profile;
|
||||
/**
|
||||
* @var string a label describing the link
|
||||
*/
|
||||
public $title;
|
||||
/**
|
||||
* @var string the language of the target resource
|
||||
*/
|
||||
public $hreflang;
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a list of links into proper array format.
|
||||
* @param array $links the links to be serialized
|
||||
* @return array the proper array representation of the links.
|
||||
*/
|
||||
public static function serialize(array $links)
|
||||
{
|
||||
foreach ($links as $rel => $link) {
|
||||
if (is_array($link)) {
|
||||
$links[$rel] = self::serialize($link);
|
||||
} elseif ($link instanceof self) {
|
||||
$links[$rel] = array_filter((array)$link);
|
||||
} else {
|
||||
$links[$rel] = ['href' => $link];
|
||||
}
|
||||
}
|
||||
|
||||
return $links;
|
||||
}
|
||||
}
|
||||
42
vendor/yiisoft/yii2/web/Linkable.php
vendored
Normal file
42
vendor/yiisoft/yii2/web/Linkable.php
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* Linkable is the interface that should be implemented by classes that typically represent locatable resources.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
interface Linkable
|
||||
{
|
||||
/**
|
||||
* Returns a list of links.
|
||||
*
|
||||
* Each link is either a URI or a [[Link]] object. The return value of this method should
|
||||
* be an array whose keys are the relation names and values the corresponding links.
|
||||
*
|
||||
* If a relation name corresponds to multiple links, use an array to represent them.
|
||||
*
|
||||
* For example,
|
||||
*
|
||||
* ```
|
||||
* [
|
||||
* 'self' => 'https://example.com/users/1',
|
||||
* 'friends' => [
|
||||
* 'https://example.com/users/2',
|
||||
* 'https://example.com/users/3',
|
||||
* ],
|
||||
* 'manager' => $managerLink, // $managerLink is a Link object
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* @return array the links
|
||||
*/
|
||||
public function getLinks();
|
||||
}
|
||||
29
vendor/yiisoft/yii2/web/MethodNotAllowedHttpException.php
vendored
Normal file
29
vendor/yiisoft/yii2/web/MethodNotAllowedHttpException.php
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* MethodNotAllowedHttpException represents a "Method Not Allowed" HTTP exception with status code 405.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7231#section-6.5.5
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class MethodNotAllowedHttpException extends HttpException
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
* @param string|null $message error message
|
||||
* @param int $code error code
|
||||
* @param \Throwable|null $previous The previous exception used for the exception chaining.
|
||||
*/
|
||||
public function __construct($message = null, $code = 0, $previous = null)
|
||||
{
|
||||
parent::__construct(405, $message, $code, $previous);
|
||||
}
|
||||
}
|
||||
131
vendor/yiisoft/yii2/web/MultiFieldSession.php
vendored
Normal file
131
vendor/yiisoft/yii2/web/MultiFieldSession.php
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* MultiFieldSession is the base class for session storage implementations with multi-field data storage support.
|
||||
*
|
||||
* With multi-field data storage, session data can be split between several fields in the storage record.
|
||||
* Using such a storage allows saving particular session data into separated field, which then can be used
|
||||
* to manipulate sessions in the way plain PHP does not allow.
|
||||
*
|
||||
* For example the ID of the authenticated user can be saved as separated column in the MySQL 'session' table,
|
||||
* which allows to query all active sessions for a particular user or terminate them at will.
|
||||
*
|
||||
* Customizing of the session writing is performed via [[writeCallback]], reading via [[readCallback]].
|
||||
*
|
||||
* While extending this class you should use [[composeFields()]] method - while writing the session data into the storage and
|
||||
* [[extractData()]] - while reading session data from the storage.
|
||||
*
|
||||
* @property-read bool $useCustomStorage Whether to use custom storage.
|
||||
*
|
||||
* @author Paul Klimov <klimov.paul@gmail.com>
|
||||
* @since 2.0.6
|
||||
*/
|
||||
abstract class MultiFieldSession extends Session
|
||||
{
|
||||
/**
|
||||
* @var callable a callback that will be called during session data reading.
|
||||
* The signature of the callback should be as follows:
|
||||
*
|
||||
* ```
|
||||
* function ($fields)
|
||||
* ```
|
||||
*
|
||||
* where `$fields` is the storage field set for read session and `$session` is this session instance.
|
||||
* If callback returns an array, it will be merged into the session data.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* ```
|
||||
* function ($fields) {
|
||||
* return [
|
||||
* 'expireDate' => Yii::$app->formatter->asDate($fields['expire']),
|
||||
* ];
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
public $readCallback;
|
||||
/**
|
||||
* @var callable a callback that will be called during session data writing.
|
||||
* The signature of the callback should be as follows:
|
||||
*
|
||||
* ```
|
||||
* function ($session)
|
||||
* ```
|
||||
*
|
||||
* where `$session` is this session instance, this variable can be used to retrieve session data.
|
||||
* Callback should return the actual fields set, which should be saved into the session storage.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* ```
|
||||
* function ($session) {
|
||||
* return [
|
||||
* 'user_id' => Yii::$app->user->id,
|
||||
* 'ip' => $_SERVER['REMOTE_ADDR'],
|
||||
* 'is_trusted' => $session->get('is_trusted', false),
|
||||
* ];
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
public $writeCallback;
|
||||
|
||||
|
||||
/**
|
||||
* Returns a value indicating whether to use custom session storage.
|
||||
* This method overrides the parent implementation and always returns true.
|
||||
* @return bool whether to use custom storage.
|
||||
*/
|
||||
public function getUseCustomStorage()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Composes storage field set for session writing.
|
||||
* @param string|null $id Optional session id
|
||||
* @param string|null $data Optional session data
|
||||
* @return array storage fields
|
||||
*/
|
||||
protected function composeFields($id = null, $data = null)
|
||||
{
|
||||
$fields = $this->writeCallback ? call_user_func($this->writeCallback, $this) : [];
|
||||
if ($id !== null) {
|
||||
$fields['id'] = $id;
|
||||
}
|
||||
if ($data !== null) {
|
||||
$fields['data'] = $data;
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts session data from storage field set.
|
||||
* @param array $fields storage fields.
|
||||
* @return string session data.
|
||||
*/
|
||||
protected function extractData($fields)
|
||||
{
|
||||
if ($this->readCallback !== null) {
|
||||
if (!isset($fields['data'])) {
|
||||
$fields['data'] = '';
|
||||
}
|
||||
$extraData = call_user_func($this->readCallback, $fields);
|
||||
if (!empty($extraData)) {
|
||||
session_decode($fields['data']);
|
||||
$_SESSION = array_merge((array) $_SESSION, (array) $extraData);
|
||||
return session_encode();
|
||||
}
|
||||
|
||||
return $fields['data'];
|
||||
}
|
||||
|
||||
return isset($fields['data']) ? $fields['data'] : '';
|
||||
}
|
||||
}
|
||||
372
vendor/yiisoft/yii2/web/MultipartFormDataParser.php
vendored
Normal file
372
vendor/yiisoft/yii2/web/MultipartFormDataParser.php
vendored
Normal file
@ -0,0 +1,372 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use yii\base\BaseObject;
|
||||
use yii\helpers\ArrayHelper;
|
||||
use yii\helpers\StringHelper;
|
||||
|
||||
/**
|
||||
* MultipartFormDataParser parses content encoded as 'multipart/form-data'.
|
||||
* This parser provides the fallback for the 'multipart/form-data' processing on non POST requests,
|
||||
* for example: the one with 'PUT' request method.
|
||||
*
|
||||
* In order to enable this parser you should configure [[Request::parsers]] in the following way:
|
||||
*
|
||||
* ```
|
||||
* return [
|
||||
* 'components' => [
|
||||
* 'request' => [
|
||||
* 'parsers' => [
|
||||
* 'multipart/form-data' => 'yii\web\MultipartFormDataParser'
|
||||
* ],
|
||||
* ],
|
||||
* // ...
|
||||
* ],
|
||||
* // ...
|
||||
* ];
|
||||
* ```
|
||||
*
|
||||
* Method [[parse()]] of this parser automatically populates `$_FILES` with the files parsed from raw body.
|
||||
*
|
||||
* > Note: since this is a request parser, it will initialize `$_FILES` values on [[Request::getBodyParams()]].
|
||||
* Until this method is invoked, `$_FILES` array will remain empty even if there are submitted files in the
|
||||
* request body. Make sure you have requested body params before any attempt to get uploaded file in case
|
||||
* you are using this parser.
|
||||
*
|
||||
* Usage example:
|
||||
*
|
||||
* ```
|
||||
* use yii\web\UploadedFile;
|
||||
*
|
||||
* $restRequestData = Yii::$app->request->getBodyParams();
|
||||
* $uploadedFile = UploadedFile::getInstancesByName('photo');
|
||||
*
|
||||
* $model = new Item();
|
||||
* $model->populate($restRequestData);
|
||||
* copy($uploadedFile->tempName, '/path/to/file/storage/photo.jpg');
|
||||
* ```
|
||||
*
|
||||
* > Note: although this parser fully emulates regular structure of the `$_FILES`, related temporary
|
||||
* files, which are available via `tmp_name` key, will not be recognized by PHP as uploaded ones.
|
||||
* Thus functions like `is_uploaded_file()` and `move_uploaded_file()` will fail on them.
|
||||
*
|
||||
* @property int $uploadFileMaxCount Maximum upload files count.
|
||||
* @property int $uploadFileMaxSize Upload file max size in bytes.
|
||||
*
|
||||
* @author Paul Klimov <klimov.paul@gmail.com>
|
||||
* @since 2.0.10
|
||||
*/
|
||||
class MultipartFormDataParser extends BaseObject implements RequestParserInterface
|
||||
{
|
||||
/**
|
||||
* @var bool whether to parse raw body even for 'POST' request and `$_FILES` already populated.
|
||||
* By default this option is disabled saving performance for 'POST' requests, which are already
|
||||
* processed by PHP automatically.
|
||||
* > Note: if this option is enabled, value of `$_FILES` will be reset on each parse.
|
||||
* @since 2.0.13
|
||||
*/
|
||||
public $force = false;
|
||||
|
||||
/**
|
||||
* @var int upload file max size in bytes.
|
||||
*/
|
||||
private $_uploadFileMaxSize;
|
||||
/**
|
||||
* @var int maximum upload files count.
|
||||
*/
|
||||
private $_uploadFileMaxCount;
|
||||
|
||||
|
||||
/**
|
||||
* @return int upload file max size in bytes.
|
||||
*/
|
||||
public function getUploadFileMaxSize()
|
||||
{
|
||||
if ($this->_uploadFileMaxSize === null) {
|
||||
$this->_uploadFileMaxSize = $this->getByteSize(ini_get('upload_max_filesize'));
|
||||
}
|
||||
|
||||
return $this->_uploadFileMaxSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $uploadFileMaxSize upload file max size in bytes.
|
||||
*/
|
||||
public function setUploadFileMaxSize($uploadFileMaxSize)
|
||||
{
|
||||
$this->_uploadFileMaxSize = $uploadFileMaxSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int maximum upload files count.
|
||||
*/
|
||||
public function getUploadFileMaxCount()
|
||||
{
|
||||
if ($this->_uploadFileMaxCount === null) {
|
||||
$this->_uploadFileMaxCount = (int)ini_get('max_file_uploads');
|
||||
}
|
||||
|
||||
return $this->_uploadFileMaxCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $uploadFileMaxCount maximum upload files count.
|
||||
*/
|
||||
public function setUploadFileMaxCount($uploadFileMaxCount)
|
||||
{
|
||||
$this->_uploadFileMaxCount = $uploadFileMaxCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parse($rawBody, $contentType)
|
||||
{
|
||||
if (!$this->force) {
|
||||
if (!empty($_POST) || !empty($_FILES)) {
|
||||
// normal POST request is parsed by PHP automatically
|
||||
return $_POST;
|
||||
}
|
||||
} else {
|
||||
$_FILES = [];
|
||||
}
|
||||
|
||||
if (empty($rawBody)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!preg_match('/boundary="?(.*)"?$/is', $contentType, $matches)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$boundary = trim($matches[1], '"');
|
||||
|
||||
$bodyParts = preg_split('/\\R?-+' . preg_quote($boundary, '/') . '/s', $rawBody);
|
||||
array_pop($bodyParts); // last block always has no data, contains boundary ending like `--`
|
||||
|
||||
$bodyParams = [];
|
||||
$filesCount = 0;
|
||||
foreach ($bodyParts as $bodyPart) {
|
||||
if (empty($bodyPart)) {
|
||||
continue;
|
||||
}
|
||||
list($headers, $value) = preg_split('/\\R\\R/', $bodyPart, 2);
|
||||
$headers = $this->parseHeaders($headers);
|
||||
|
||||
if (!isset($headers['content-disposition']['name'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($headers['content-disposition']['filename'])) {
|
||||
// file upload:
|
||||
if ($filesCount >= $this->getUploadFileMaxCount()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$fileInfo = [
|
||||
'name' => $headers['content-disposition']['filename'],
|
||||
'type' => ArrayHelper::getValue($headers, 'content-type', 'application/octet-stream'),
|
||||
'size' => StringHelper::byteLength($value),
|
||||
'error' => UPLOAD_ERR_OK,
|
||||
'tmp_name' => null,
|
||||
];
|
||||
|
||||
if ($fileInfo['size'] > $this->getUploadFileMaxSize()) {
|
||||
$fileInfo['error'] = UPLOAD_ERR_INI_SIZE;
|
||||
} else {
|
||||
$tmpResource = tmpfile();
|
||||
if ($tmpResource === false) {
|
||||
$fileInfo['error'] = UPLOAD_ERR_CANT_WRITE;
|
||||
} else {
|
||||
$tmpResourceMetaData = stream_get_meta_data($tmpResource);
|
||||
$tmpFileName = $tmpResourceMetaData['uri'];
|
||||
if (empty($tmpFileName)) {
|
||||
$fileInfo['error'] = UPLOAD_ERR_CANT_WRITE;
|
||||
@fclose($tmpResource);
|
||||
} else {
|
||||
fwrite($tmpResource, $value);
|
||||
rewind($tmpResource);
|
||||
$fileInfo['tmp_name'] = $tmpFileName;
|
||||
$fileInfo['tmp_resource'] = $tmpResource; // save file resource, otherwise it will be deleted
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->addFile($_FILES, $headers['content-disposition']['name'], $fileInfo);
|
||||
|
||||
$filesCount++;
|
||||
} else {
|
||||
// regular parameter:
|
||||
$this->addValue($bodyParams, $headers['content-disposition']['name'], $value);
|
||||
}
|
||||
}
|
||||
|
||||
return $bodyParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses content part headers.
|
||||
* @param string $headerContent headers source content
|
||||
* @return array parsed headers.
|
||||
*/
|
||||
private function parseHeaders($headerContent)
|
||||
{
|
||||
$headers = [];
|
||||
$headerParts = preg_split('/\\R/su', $headerContent, -1, PREG_SPLIT_NO_EMPTY);
|
||||
foreach ($headerParts as $headerPart) {
|
||||
if (strpos($headerPart, ':') === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
list($headerName, $headerValue) = explode(':', $headerPart, 2);
|
||||
$headerName = strtolower(trim($headerName));
|
||||
$headerValue = trim($headerValue);
|
||||
|
||||
if (strpos($headerValue, ';') === false) {
|
||||
$headers[$headerName] = $headerValue;
|
||||
} else {
|
||||
$headers[$headerName] = [];
|
||||
foreach (explode(';', $headerValue) as $part) {
|
||||
$part = trim($part);
|
||||
if (strpos($part, '=') === false) {
|
||||
$headers[$headerName][] = $part;
|
||||
} else {
|
||||
list($name, $value) = explode('=', $part, 2);
|
||||
$name = strtolower(trim($name));
|
||||
$value = trim(trim($value), '"');
|
||||
$headers[$headerName][$name] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds value to the array by input name, e.g. `Item[name]`.
|
||||
* @param array $array array which should store value.
|
||||
* @param string $name input name specification.
|
||||
* @param mixed $value value to be added.
|
||||
*/
|
||||
private function addValue(&$array, $name, $value)
|
||||
{
|
||||
$nameParts = preg_split('/\\]\\[|\\[/s', $name);
|
||||
$current = &$array;
|
||||
foreach ($nameParts as $namePart) {
|
||||
$namePart = trim($namePart, ']');
|
||||
if ($namePart === '') {
|
||||
$current[] = [];
|
||||
$keys = array_keys($current);
|
||||
$lastKey = array_pop($keys);
|
||||
$current = &$current[$lastKey];
|
||||
} else {
|
||||
if (!isset($current[$namePart])) {
|
||||
$current[$namePart] = [];
|
||||
}
|
||||
$current = &$current[$namePart];
|
||||
}
|
||||
}
|
||||
$current = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds file info to the uploaded files array by input name, e.g. `Item[file]`.
|
||||
* @param array $files array containing uploaded files
|
||||
* @param string $name input name specification.
|
||||
* @param array $info file info.
|
||||
*/
|
||||
private function addFile(&$files, $name, $info)
|
||||
{
|
||||
if (strpos($name, '[') === false) {
|
||||
$files[$name] = $info;
|
||||
return;
|
||||
}
|
||||
|
||||
$fileInfoAttributes = [
|
||||
'name',
|
||||
'type',
|
||||
'size',
|
||||
'error',
|
||||
'tmp_name',
|
||||
'tmp_resource',
|
||||
];
|
||||
|
||||
$nameParts = preg_split('/\\]\\[|\\[/s', $name);
|
||||
$baseName = array_shift($nameParts);
|
||||
if (!isset($files[$baseName])) {
|
||||
$files[$baseName] = [];
|
||||
foreach ($fileInfoAttributes as $attribute) {
|
||||
$files[$baseName][$attribute] = [];
|
||||
}
|
||||
} else {
|
||||
foreach ($fileInfoAttributes as $attribute) {
|
||||
$files[$baseName][$attribute] = (array) $files[$baseName][$attribute];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($fileInfoAttributes as $attribute) {
|
||||
if (!isset($info[$attribute])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$current = &$files[$baseName][$attribute];
|
||||
foreach ($nameParts as $namePart) {
|
||||
$namePart = trim($namePart, ']');
|
||||
if ($namePart === '') {
|
||||
$current[] = [];
|
||||
$keys = array_keys($current);
|
||||
$lastKey = array_pop($keys);
|
||||
$current = &$current[$lastKey];
|
||||
} else {
|
||||
if (!isset($current[$namePart])) {
|
||||
$current[$namePart] = [];
|
||||
}
|
||||
$current = &$current[$namePart];
|
||||
}
|
||||
}
|
||||
$current = $info[$attribute];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size in bytes from verbose size representation.
|
||||
*
|
||||
* For example: '5K' => 5*1024.
|
||||
* @param string $verboseSize verbose size representation.
|
||||
* @return int actual size in bytes.
|
||||
*/
|
||||
private function getByteSize($verboseSize)
|
||||
{
|
||||
if (empty($verboseSize)) {
|
||||
return 0;
|
||||
}
|
||||
if (is_numeric($verboseSize)) {
|
||||
return (int) $verboseSize;
|
||||
}
|
||||
$sizeUnit = trim($verboseSize, '0123456789');
|
||||
$size = trim(str_replace($sizeUnit, '', $verboseSize));
|
||||
if (!is_numeric($size)) {
|
||||
return 0;
|
||||
}
|
||||
switch (strtolower($sizeUnit)) {
|
||||
case 'kb':
|
||||
case 'k':
|
||||
return $size * 1024;
|
||||
case 'mb':
|
||||
case 'm':
|
||||
return $size * 1024 * 1024;
|
||||
case 'gb':
|
||||
case 'g':
|
||||
return $size * 1024 * 1024 * 1024;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
33
vendor/yiisoft/yii2/web/NotAcceptableHttpException.php
vendored
Normal file
33
vendor/yiisoft/yii2/web/NotAcceptableHttpException.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* NotAcceptableHttpException represents a "Not Acceptable" HTTP exception with status code 406.
|
||||
*
|
||||
* Use this exception when the client requests a Content-Type that your
|
||||
* application cannot return. Note that, according to the HTTP 1.1 specification,
|
||||
* you are not required to respond with this status code in this situation.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7231#section-6.5.6
|
||||
* @author Dan Schmidt <danschmidt5189@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class NotAcceptableHttpException extends HttpException
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
* @param string|null $message error message
|
||||
* @param int $code error code
|
||||
* @param \Throwable|null $previous The previous exception used for the exception chaining.
|
||||
*/
|
||||
public function __construct($message = null, $code = 0, $previous = null)
|
||||
{
|
||||
parent::__construct(406, $message, $code, $previous);
|
||||
}
|
||||
}
|
||||
29
vendor/yiisoft/yii2/web/NotFoundHttpException.php
vendored
Normal file
29
vendor/yiisoft/yii2/web/NotFoundHttpException.php
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* NotFoundHttpException represents a "Not Found" HTTP exception with status code 404.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7231#section-6.5.4
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class NotFoundHttpException extends HttpException
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
* @param string|null $message error message
|
||||
* @param int $code error code
|
||||
* @param \Throwable|null $previous The previous exception used for the exception chaining.
|
||||
*/
|
||||
public function __construct($message = null, $code = 0, $previous = null)
|
||||
{
|
||||
parent::__construct(404, $message, $code, $previous);
|
||||
}
|
||||
}
|
||||
35
vendor/yiisoft/yii2/web/RangeNotSatisfiableHttpException.php
vendored
Normal file
35
vendor/yiisoft/yii2/web/RangeNotSatisfiableHttpException.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* RangeNotSatisfiableHttpException represents an exception caused by an improper request of the end-user.
|
||||
* This exception thrown when the requested range is not satisfiable: the client asked for a portion of
|
||||
* the file (byte serving), but the server cannot supply that portion. For example, if the client asked for
|
||||
* a part of the file that lies beyond the end of the file.
|
||||
*
|
||||
* Throwing an RangeNotSatisfiableHttpException like in the following example will result in the error page
|
||||
* with error 416 to be displayed.
|
||||
*
|
||||
* @author Zalatov Alexander <CaHbKa.Z@gmail.com>
|
||||
*
|
||||
* @since 2.0.11
|
||||
*/
|
||||
class RangeNotSatisfiableHttpException extends HttpException
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
* @param string|null $message error message
|
||||
* @param int $code error code
|
||||
* @param \Throwable|null $previous The previous exception used for the exception chaining.
|
||||
*/
|
||||
public function __construct($message = null, $code = 0, $previous = null)
|
||||
{
|
||||
parent::__construct(416, $message, $code, $previous);
|
||||
}
|
||||
}
|
||||
2037
vendor/yiisoft/yii2/web/Request.php
vendored
Normal file
2037
vendor/yiisoft/yii2/web/Request.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
25
vendor/yiisoft/yii2/web/RequestParserInterface.php
vendored
Normal file
25
vendor/yiisoft/yii2/web/RequestParserInterface.php
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* Interface for classes that parse the raw request body into a parameters array.
|
||||
*
|
||||
* @author Dan Schmidt <danschmidt5189@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
interface RequestParserInterface
|
||||
{
|
||||
/**
|
||||
* Parses a HTTP request body.
|
||||
* @param string $rawBody the raw HTTP request body.
|
||||
* @param string $contentType the content type specified for the request body.
|
||||
* @return array|object parameters parsed from the request body
|
||||
*/
|
||||
public function parse($rawBody, $contentType);
|
||||
}
|
||||
1149
vendor/yiisoft/yii2/web/Response.php
vendored
Normal file
1149
vendor/yiisoft/yii2/web/Response.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
23
vendor/yiisoft/yii2/web/ResponseFormatterInterface.php
vendored
Normal file
23
vendor/yiisoft/yii2/web/ResponseFormatterInterface.php
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* ResponseFormatterInterface specifies the interface needed to format a response before it is sent out.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
interface ResponseFormatterInterface
|
||||
{
|
||||
/**
|
||||
* Formats the specified response.
|
||||
* @param Response $response the response to be formatted.
|
||||
*/
|
||||
public function format($response);
|
||||
}
|
||||
29
vendor/yiisoft/yii2/web/ServerErrorHttpException.php
vendored
Normal file
29
vendor/yiisoft/yii2/web/ServerErrorHttpException.php
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* ServerErrorHttpException represents an "Internal Server Error" HTTP exception with status code 500.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7231#section-6.6.1
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class ServerErrorHttpException extends HttpException
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
* @param string|null $message error message
|
||||
* @param int $code error code
|
||||
* @param \Throwable|null $previous The previous exception used for the exception chaining.
|
||||
*/
|
||||
public function __construct($message = null, $code = 0, $previous = null)
|
||||
{
|
||||
parent::__construct(500, $message, $code, $previous);
|
||||
}
|
||||
}
|
||||
1082
vendor/yiisoft/yii2/web/Session.php
vendored
Normal file
1082
vendor/yiisoft/yii2/web/Session.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
80
vendor/yiisoft/yii2/web/SessionHandler.php
vendored
Normal file
80
vendor/yiisoft/yii2/web/SessionHandler.php
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use SessionHandlerInterface;
|
||||
|
||||
/**
|
||||
* SessionHandler implements an [[\SessionHandlerInterface]] for handling [[Session]] with custom session storage.
|
||||
*
|
||||
* @author Viktor Khokhryakov <viktor.khokhryakov@gmail.com>
|
||||
* @since 2.0.52
|
||||
*/
|
||||
class SessionHandler implements SessionHandlerInterface
|
||||
{
|
||||
/**
|
||||
* @var Session
|
||||
*/
|
||||
private $_session;
|
||||
|
||||
|
||||
public function __construct(Session $session)
|
||||
{
|
||||
$this->_session = $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function close(): bool
|
||||
{
|
||||
return $this->_session->closeSession();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function destroy($id): bool
|
||||
{
|
||||
return $this->_session->destroySession($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function gc($max_lifetime)
|
||||
{
|
||||
return $this->_session->gcSession($max_lifetime);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function open($path, $name): bool
|
||||
{
|
||||
return $this->_session->openSession($path, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function read($id)
|
||||
{
|
||||
return $this->_session->readSession($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function write($id, $data): bool
|
||||
{
|
||||
return $this->_session->writeSession($id, $data);
|
||||
}
|
||||
}
|
||||
93
vendor/yiisoft/yii2/web/SessionIterator.php
vendored
Normal file
93
vendor/yiisoft/yii2/web/SessionIterator.php
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* SessionIterator implements an [[\Iterator|iterator]] for traversing session variables managed by [[Session]].
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*
|
||||
* @implements \Iterator<array-key, mixed>
|
||||
*/
|
||||
class SessionIterator implements \Iterator
|
||||
{
|
||||
/**
|
||||
* @var array list of keys in the map
|
||||
*/
|
||||
private $_keys;
|
||||
/**
|
||||
* @var string|int|false current key
|
||||
*/
|
||||
private $_key;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->_keys = array_keys(isset($_SESSION) ? $_SESSION : []);
|
||||
$this->rewind();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewinds internal array pointer.
|
||||
* This method is required by the interface [[\Iterator]].
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function rewind()
|
||||
{
|
||||
$this->_key = reset($this->_keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key of the current array element.
|
||||
* This method is required by the interface [[\Iterator]].
|
||||
* @return string|int|null the key of the current array element
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function key()
|
||||
{
|
||||
return $this->_key === false ? null : $this->_key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current array element.
|
||||
* This method is required by the interface [[\Iterator]].
|
||||
* @return mixed the current array element
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function current()
|
||||
{
|
||||
return $this->_key !== false && isset($_SESSION[$this->_key]) ? $_SESSION[$this->_key] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the internal pointer to the next array element.
|
||||
* This method is required by the interface [[\Iterator]].
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function next()
|
||||
{
|
||||
do {
|
||||
$this->_key = next($this->_keys);
|
||||
} while ($this->_key !== false && !isset($_SESSION[$this->_key]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether there is an element at current position.
|
||||
* This method is required by the interface [[\Iterator]].
|
||||
* @return bool
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function valid()
|
||||
{
|
||||
return $this->_key !== false;
|
||||
}
|
||||
}
|
||||
33
vendor/yiisoft/yii2/web/TooManyRequestsHttpException.php
vendored
Normal file
33
vendor/yiisoft/yii2/web/TooManyRequestsHttpException.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* TooManyRequestsHttpException represents a "Too Many Requests" HTTP exception with status code 429.
|
||||
*
|
||||
* Use this exception to indicate that a client has made too many requests in a
|
||||
* given period of time. For example, you would throw this exception when
|
||||
* 'throttling' an API user.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc6585#section-4
|
||||
* @author Dan Schmidt <danschmidt5189@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class TooManyRequestsHttpException extends HttpException
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
* @param string|null $message error message
|
||||
* @param int $code error code
|
||||
* @param \Throwable|null $previous The previous exception used for the exception chaining.
|
||||
*/
|
||||
public function __construct($message = null, $code = 0, $previous = null)
|
||||
{
|
||||
parent::__construct(429, $message, $code, $previous);
|
||||
}
|
||||
}
|
||||
36
vendor/yiisoft/yii2/web/UnauthorizedHttpException.php
vendored
Normal file
36
vendor/yiisoft/yii2/web/UnauthorizedHttpException.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* UnauthorizedHttpException represents an "Unauthorized" HTTP exception with status code 401.
|
||||
*
|
||||
* Use this exception to indicate that a client needs to authenticate via WWW-Authenticate header
|
||||
* to perform the requested action.
|
||||
*
|
||||
* If the client is already authenticated and is simply not allowed to
|
||||
* perform the action, consider using a 403 [[ForbiddenHttpException]]
|
||||
* or 404 [[NotFoundHttpException]] instead.
|
||||
*
|
||||
* @link https://tools.ietf.org/html/rfc7235#section-3.1
|
||||
* @author Dan Schmidt <danschmidt5189@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class UnauthorizedHttpException extends HttpException
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
* @param string|null $message error message
|
||||
* @param int $code error code
|
||||
* @param \Throwable|null $previous The previous exception used for the exception chaining.
|
||||
*/
|
||||
public function __construct($message = null, $code = 0, $previous = null)
|
||||
{
|
||||
parent::__construct(401, $message, $code, $previous);
|
||||
}
|
||||
}
|
||||
35
vendor/yiisoft/yii2/web/UnprocessableEntityHttpException.php
vendored
Normal file
35
vendor/yiisoft/yii2/web/UnprocessableEntityHttpException.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* UnprocessableEntityHttpException represents an "Unprocessable Entity" HTTP
|
||||
* exception with status code 422.
|
||||
*
|
||||
* Use this exception to inform that the server understands the content type of
|
||||
* the request entity and the syntax of that request entity is correct but the server
|
||||
* was unable to process the contained instructions. For example, to return form
|
||||
* validation errors.
|
||||
*
|
||||
* @link http://www.webdav.org/specs/rfc2518.html#STATUS_422
|
||||
* @author Jan Silva <janfrs3@gmail.com>
|
||||
* @since 2.0.7
|
||||
*/
|
||||
class UnprocessableEntityHttpException extends HttpException
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
* @param string|null $message error message
|
||||
* @param int $code error code
|
||||
* @param \Throwable|null $previous The previous exception used for the exception chaining.
|
||||
*/
|
||||
public function __construct($message = null, $code = 0, $previous = null)
|
||||
{
|
||||
parent::__construct(422, $message, $code, $previous);
|
||||
}
|
||||
}
|
||||
34
vendor/yiisoft/yii2/web/UnsupportedMediaTypeHttpException.php
vendored
Normal file
34
vendor/yiisoft/yii2/web/UnsupportedMediaTypeHttpException.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* UnsupportedMediaTypeHttpException represents an "Unsupported Media Type" HTTP exception with status code 415.
|
||||
*
|
||||
* Use this exception when the client sends data in a format that your
|
||||
* application does not understand. For example, you would throw this exception
|
||||
* if the client POSTs XML data to an action or controller that only accepts
|
||||
* JSON.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7231#section-6.5.13
|
||||
* @author Dan Schmidt <danschmidt5189@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class UnsupportedMediaTypeHttpException extends HttpException
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
* @param string|null $message error message
|
||||
* @param int $code error code
|
||||
* @param \Throwable|null $previous The previous exception used for the exception chaining.
|
||||
*/
|
||||
public function __construct($message = null, $code = 0, $previous = null)
|
||||
{
|
||||
parent::__construct(415, $message, $code, $previous);
|
||||
}
|
||||
}
|
||||
319
vendor/yiisoft/yii2/web/UploadedFile.php
vendored
Normal file
319
vendor/yiisoft/yii2/web/UploadedFile.php
vendored
Normal file
@ -0,0 +1,319 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use Yii;
|
||||
use yii\base\BaseObject;
|
||||
use yii\helpers\ArrayHelper;
|
||||
use yii\helpers\Html;
|
||||
|
||||
/**
|
||||
* UploadedFile represents the information for an uploaded file.
|
||||
*
|
||||
* You can call [[getInstance()]] to retrieve the instance of an uploaded file,
|
||||
* and then use [[saveAs()]] to save it on the server.
|
||||
* You may also query other information about the file, including [[name]],
|
||||
* [[tempName]], [[type]], [[size]], [[error]] and [[fullPath]].
|
||||
*
|
||||
* For more details and usage information on UploadedFile, see the [guide article on handling uploads](guide:input-file-upload).
|
||||
*
|
||||
* @property-read string $baseName Original file base name.
|
||||
* @property-read string $extension File extension.
|
||||
* @property-read bool $hasError Whether there is an error with the uploaded file. Check [[error]] for
|
||||
* detailed error code information.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class UploadedFile extends BaseObject
|
||||
{
|
||||
/**
|
||||
* @var string the original name of the file being uploaded
|
||||
*/
|
||||
public $name;
|
||||
/**
|
||||
* @var string the path of the uploaded file on the server.
|
||||
* Note, this is a temporary file which will be automatically deleted by PHP
|
||||
* after the current request is processed.
|
||||
*/
|
||||
public $tempName;
|
||||
/**
|
||||
* @var string the MIME-type of the uploaded file (such as "image/gif").
|
||||
* Since this MIME type is not checked on the server-side, do not take this value for granted.
|
||||
* Instead, use [[\yii\helpers\FileHelper::getMimeType()]] to determine the exact MIME type.
|
||||
*/
|
||||
public $type;
|
||||
/**
|
||||
* @var int the actual size of the uploaded file in bytes
|
||||
*/
|
||||
public $size;
|
||||
/**
|
||||
* @var int an error code describing the status of this file uploading.
|
||||
* @see https://www.php.net/manual/en/features.file-upload.errors.php
|
||||
*/
|
||||
public $error;
|
||||
/**
|
||||
* @var string|null The full path as submitted by the browser. Note this value does not always
|
||||
* contain a real directory structure, and cannot be trusted. Available as of PHP 8.1.
|
||||
* @since 2.0.46
|
||||
*/
|
||||
public $fullPath;
|
||||
|
||||
/**
|
||||
* @var resource|null a temporary uploaded stream resource used within PUT and PATCH request.
|
||||
*/
|
||||
private $_tempResource;
|
||||
/**
|
||||
* @var array[]|null
|
||||
*/
|
||||
private static $_files;
|
||||
|
||||
|
||||
/**
|
||||
* UploadedFile constructor.
|
||||
*
|
||||
* @param array $config name-value pairs that will be used to initialize the object properties
|
||||
*/
|
||||
public function __construct($config = [])
|
||||
{
|
||||
$this->_tempResource = ArrayHelper::remove($config, 'tempResource');
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* String output.
|
||||
* This is PHP magic method that returns string representation of an object.
|
||||
* The implementation here returns the uploaded file's name.
|
||||
* @return string the string representation of the object
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an uploaded file for the given model attribute.
|
||||
* The file should be uploaded using [[\yii\widgets\ActiveField::fileInput()]].
|
||||
* @param \yii\base\Model $model the data model
|
||||
* @param string $attribute the attribute name. The attribute name may contain array indexes.
|
||||
* For example, '[1]file' for tabular file uploading; and 'file[1]' for an element in a file array.
|
||||
* @return UploadedFile|null the instance of the uploaded file.
|
||||
* Null is returned if no file is uploaded for the specified model attribute.
|
||||
* @see getInstanceByName()
|
||||
*/
|
||||
public static function getInstance($model, $attribute)
|
||||
{
|
||||
$name = Html::getInputName($model, $attribute);
|
||||
return static::getInstanceByName($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all uploaded files for the given model attribute.
|
||||
* @param \yii\base\Model $model the data model
|
||||
* @param string $attribute the attribute name. The attribute name may contain array indexes
|
||||
* for tabular file uploading, e.g. '[1]file'.
|
||||
* @return UploadedFile[] array of UploadedFile objects.
|
||||
* Empty array is returned if no available file was found for the given attribute.
|
||||
*/
|
||||
public static function getInstances($model, $attribute)
|
||||
{
|
||||
$name = Html::getInputName($model, $attribute);
|
||||
return static::getInstancesByName($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an uploaded file according to the given file input name.
|
||||
* The name can be a plain string or a string like an array element (e.g. 'Post[imageFile]', or 'Post[0][imageFile]').
|
||||
* @param string $name the name of the file input field.
|
||||
* @return UploadedFile|null the instance of the uploaded file.
|
||||
* Null is returned if no file is uploaded for the specified name.
|
||||
*/
|
||||
public static function getInstanceByName($name)
|
||||
{
|
||||
$files = self::loadFiles();
|
||||
return isset($files[$name]) ? new static($files[$name]) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of uploaded files corresponding to the specified file input name.
|
||||
* This is mainly used when multiple files were uploaded and saved as 'files[0]', 'files[1]',
|
||||
* 'files[n]'..., and you can retrieve them all by passing 'files' as the name.
|
||||
* @param string $name the name of the array of files
|
||||
* @return UploadedFile[] the array of UploadedFile objects. Empty array is returned
|
||||
* if no adequate upload was found. Please note that this array will contain
|
||||
* all files from all sub-arrays regardless how deeply nested they are.
|
||||
*/
|
||||
public static function getInstancesByName($name)
|
||||
{
|
||||
$files = self::loadFiles();
|
||||
if (isset($files[$name])) {
|
||||
return [new static($files[$name])];
|
||||
}
|
||||
$results = [];
|
||||
foreach ($files as $key => $file) {
|
||||
if (strpos($key, "{$name}[") === 0) {
|
||||
$results[] = new static($file);
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up the loaded UploadedFile instances.
|
||||
* This method is mainly used by test scripts to set up a fixture.
|
||||
*/
|
||||
public static function reset()
|
||||
{
|
||||
self::$_files = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the uploaded file.
|
||||
* If the target file `$file` already exists, it will be overwritten.
|
||||
* @param string $file the file path or a path alias used to save the uploaded file.
|
||||
* @param bool $deleteTempFile whether to delete the temporary file after saving.
|
||||
* If true, you will not be able to save the uploaded file again in the current request.
|
||||
* @return bool true whether the file is saved successfully
|
||||
* @see error
|
||||
*/
|
||||
public function saveAs($file, $deleteTempFile = true)
|
||||
{
|
||||
if ($this->hasError) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$targetFile = Yii::getAlias($file);
|
||||
if (is_resource($this->_tempResource)) {
|
||||
$result = $this->copyTempFile($targetFile);
|
||||
return $deleteTempFile ? @fclose($this->_tempResource) : (bool) $result;
|
||||
}
|
||||
|
||||
return $deleteTempFile ? move_uploaded_file($this->tempName, $targetFile) : copy($this->tempName, $targetFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy temporary file into file specified
|
||||
*
|
||||
* @param string $targetFile path of the file to copy to
|
||||
* @return int|false the total count of bytes copied, or false on failure
|
||||
* @since 2.0.32
|
||||
*/
|
||||
protected function copyTempFile($targetFile)
|
||||
{
|
||||
$target = fopen($targetFile, 'wb');
|
||||
if ($target === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = stream_copy_to_stream($this->_tempResource, $target);
|
||||
@fclose($target);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string original file base name
|
||||
*/
|
||||
public function getBaseName()
|
||||
{
|
||||
// https://github.com/yiisoft/yii2/issues/11012
|
||||
$pathInfo = pathinfo('_' . $this->name, PATHINFO_FILENAME);
|
||||
return mb_substr($pathInfo, 1, mb_strlen($pathInfo, '8bit'), '8bit');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string file extension
|
||||
*/
|
||||
public function getExtension()
|
||||
{
|
||||
return strtolower(pathinfo($this->name, PATHINFO_EXTENSION));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool whether there is an error with the uploaded file.
|
||||
* Check [[error]] for detailed error code information.
|
||||
*/
|
||||
public function getHasError()
|
||||
{
|
||||
return $this->error != UPLOAD_ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns reformated data of uplodaded files.
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
private static function loadFiles()
|
||||
{
|
||||
if (self::$_files === null) {
|
||||
self::$_files = [];
|
||||
if (is_array($_FILES)) {
|
||||
foreach ($_FILES as $key => $info) {
|
||||
self::loadFilesRecursive(
|
||||
$key,
|
||||
$info['name'],
|
||||
$info['tmp_name'],
|
||||
$info['type'],
|
||||
$info['size'],
|
||||
$info['error'],
|
||||
isset($info['full_path']) ? $info['full_path'] : [],
|
||||
isset($info['tmp_resource']) ? $info['tmp_resource'] : []
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self::$_files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive reformats data of uplodaded file(s).
|
||||
*
|
||||
* @param string $key key for identifying uploaded file(sub-array index)
|
||||
* @param string[]|string $names file name(s) provided by PHP
|
||||
* @param string[]|string $tempNames temporary file name(s) provided by PHP
|
||||
* @param string[]|string $types file type(s) provided by PHP
|
||||
* @param int[]|int $sizes file size(s) provided by PHP
|
||||
* @param int[]|int $errors uploading issue(s) provided by PHP
|
||||
* @param array|string|null $fullPaths the full path(s) as submitted by the browser/PHP
|
||||
* @param array|resource|null $tempResources the resource(s)
|
||||
*/
|
||||
private static function loadFilesRecursive($key, $names, $tempNames, $types, $sizes, $errors, $fullPaths, $tempResources)
|
||||
{
|
||||
if (is_array($names)) {
|
||||
foreach ($names as $i => $name) {
|
||||
self::loadFilesRecursive(
|
||||
$key . '[' . $i . ']',
|
||||
$name,
|
||||
$tempNames[$i],
|
||||
$types[$i],
|
||||
$sizes[$i],
|
||||
$errors[$i],
|
||||
isset($fullPaths[$i]) ? $fullPaths[$i] : null,
|
||||
isset($tempResources[$i]) ? $tempResources[$i] : null
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var int $errors */
|
||||
if ($errors != UPLOAD_ERR_NO_FILE) {
|
||||
self::$_files[$key] = [
|
||||
'name' => $names,
|
||||
'tempName' => $tempNames,
|
||||
'tempResource' => is_resource($tempResources) ? $tempResources : null,
|
||||
'type' => $types,
|
||||
'size' => $sizes,
|
||||
'error' => $errors,
|
||||
'fullPath' => is_string($fullPaths) ? $fullPaths : null,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
663
vendor/yiisoft/yii2/web/UrlManager.php
vendored
Normal file
663
vendor/yiisoft/yii2/web/UrlManager.php
vendored
Normal file
@ -0,0 +1,663 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Component;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\caching\CacheInterface;
|
||||
use yii\di\Instance;
|
||||
use yii\helpers\Url;
|
||||
|
||||
/**
|
||||
* UrlManager handles HTTP request parsing and creation of URLs based on a set of rules.
|
||||
*
|
||||
* UrlManager is configured as an application component in [[\yii\base\Application]] by default.
|
||||
* You can access that instance via `Yii::$app->urlManager`.
|
||||
*
|
||||
* You can modify its configuration by adding an array to your application config under `components`
|
||||
* as it is shown in the following example:
|
||||
*
|
||||
* ```
|
||||
* 'urlManager' => [
|
||||
* 'enablePrettyUrl' => true,
|
||||
* 'rules' => [
|
||||
* // your rules go here
|
||||
* ],
|
||||
* // ...
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* Rules are classes implementing the [[UrlRuleInterface]], by default that is [[UrlRule]].
|
||||
* For nesting rules, there is also a [[GroupUrlRule]] class.
|
||||
*
|
||||
* For more details and usage information on UrlManager, see the [guide article on routing](guide:runtime-routing).
|
||||
*
|
||||
* @property string $baseUrl The base URL that is used by [[createUrl()]] to prepend to created URLs.
|
||||
* @property string $hostInfo The host info (e.g. `https://www.example.com`) that is used by
|
||||
* [[createAbsoluteUrl()]] to prepend to created URLs.
|
||||
* @property string $scriptUrl The entry script URL that is used by [[createUrl()]] to prepend to created
|
||||
* URLs.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class UrlManager extends Component
|
||||
{
|
||||
/**
|
||||
* @var bool whether to enable pretty URLs. Instead of putting all parameters in the query
|
||||
* string part of a URL, pretty URLs allow using path info to represent some of the parameters
|
||||
* and can thus produce more user-friendly URLs, such as "/news/Yii-is-released", instead of
|
||||
* "/index.php?r=news%2Fview&id=100".
|
||||
*/
|
||||
public $enablePrettyUrl = false;
|
||||
/**
|
||||
* @var bool whether to enable strict parsing. If strict parsing is enabled, the incoming
|
||||
* requested URL must match at least one of the [[rules]] in order to be treated as a valid request.
|
||||
* Otherwise, the path info part of the request will be treated as the requested route.
|
||||
* This property is used only when [[enablePrettyUrl]] is `true`.
|
||||
*/
|
||||
public $enableStrictParsing = false;
|
||||
/**
|
||||
* @var array the rules for creating and parsing URLs when [[enablePrettyUrl]] is `true`.
|
||||
* This property is used only if [[enablePrettyUrl]] is `true`. Each element in the array
|
||||
* is the configuration array for creating a single URL rule. The configuration will
|
||||
* be merged with [[ruleConfig]] first before it is used for creating the rule object.
|
||||
*
|
||||
* A special shortcut format can be used if a rule only specifies [[UrlRule::pattern|pattern]]
|
||||
* and [[UrlRule::route|route]]: `'pattern' => 'route'`. That is, instead of using a configuration
|
||||
* array, one can use the key to represent the pattern and the value the corresponding route.
|
||||
* For example, `'post/<id:\d+>' => 'post/view'`.
|
||||
*
|
||||
* For RESTful routing the mentioned shortcut format also allows you to specify the
|
||||
* [[UrlRule::verb|HTTP verb]] that the rule should apply for.
|
||||
* You can do that by prepending it to the pattern, separated by space.
|
||||
* For example, `'PUT post/<id:\d+>' => 'post/update'`.
|
||||
* You may specify multiple verbs by separating them with comma
|
||||
* like this: `'POST,PUT post/index' => 'post/create'`.
|
||||
* The supported verbs in the shortcut format are: GET, HEAD, POST, PUT, PATCH and DELETE.
|
||||
* Note that [[UrlRule::mode|mode]] will be set to PARSING_ONLY when specifying verb in this way
|
||||
* so you normally would not specify a verb for normal GET request.
|
||||
*
|
||||
* Here is an example configuration for RESTful CRUD controller:
|
||||
*
|
||||
* ```
|
||||
* [
|
||||
* 'dashboard' => 'site/index',
|
||||
*
|
||||
* 'POST <controller:[\w-]+>' => '<controller>/create',
|
||||
* '<controller:[\w-]+>s' => '<controller>/index',
|
||||
*
|
||||
* 'PUT <controller:[\w-]+>/<id:\d+>' => '<controller>/update',
|
||||
* 'DELETE <controller:[\w-]+>/<id:\d+>' => '<controller>/delete',
|
||||
* '<controller:[\w-]+>/<id:\d+>' => '<controller>/view',
|
||||
* ];
|
||||
* ```
|
||||
*
|
||||
* Note that if you modify this property after the UrlManager object is created, make sure
|
||||
* you populate the array with rule objects instead of rule configurations.
|
||||
*/
|
||||
public $rules = [];
|
||||
/**
|
||||
* @var string the URL suffix used when [[enablePrettyUrl]] is `true`.
|
||||
* For example, ".html" can be used so that the URL looks like pointing to a static HTML page.
|
||||
* This property is used only if [[enablePrettyUrl]] is `true`.
|
||||
*/
|
||||
public $suffix;
|
||||
/**
|
||||
* @var bool whether to show entry script name in the constructed URL. Defaults to `true`.
|
||||
* This property is used only if [[enablePrettyUrl]] is `true`.
|
||||
*/
|
||||
public $showScriptName = true;
|
||||
/**
|
||||
* @var string the GET parameter name for route. This property is used only if [[enablePrettyUrl]] is `false`.
|
||||
*/
|
||||
public $routeParam = 'r';
|
||||
/**
|
||||
* @var CacheInterface|array|string|bool|null the cache object or the application component ID of the cache object.
|
||||
* This can also be an array that is used to create a [[CacheInterface]] instance in case you do not want to use
|
||||
* an application component.
|
||||
* Compiled URL rules will be cached through this cache object, if it is available.
|
||||
*
|
||||
* After the UrlManager object is created, if you want to change this property,
|
||||
* you should only assign it with a cache object.
|
||||
* Set this property to `false` or `null` if you do not want to cache the URL rules.
|
||||
*
|
||||
* Cache entries are stored for the time set by [[\yii\caching\Cache::$defaultDuration|$defaultDuration]] in
|
||||
* the cache configuration, which is unlimited by default. You may want to tune this value if your [[rules]]
|
||||
* change frequently.
|
||||
*/
|
||||
public $cache = 'cache';
|
||||
/**
|
||||
* @var array the default configuration of URL rules. Individual rule configurations
|
||||
* specified via [[rules]] will take precedence when the same property of the rule is configured.
|
||||
*/
|
||||
public $ruleConfig = ['class' => 'yii\web\UrlRule'];
|
||||
/**
|
||||
* @var UrlNormalizer|array|string|false the configuration for [[UrlNormalizer]] used by this UrlManager.
|
||||
* The default value is `false`, which means normalization will be skipped.
|
||||
* If you wish to enable URL normalization, you should configure this property manually.
|
||||
* For example:
|
||||
*
|
||||
* ```
|
||||
* [
|
||||
* 'class' => 'yii\web\UrlNormalizer',
|
||||
* 'collapseSlashes' => true,
|
||||
* 'normalizeTrailingSlash' => true,
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* @since 2.0.10
|
||||
*/
|
||||
public $normalizer = false;
|
||||
|
||||
/**
|
||||
* @var string the cache key for cached rules
|
||||
* @since 2.0.8
|
||||
*/
|
||||
protected $cacheKey = __CLASS__;
|
||||
|
||||
private $_baseUrl;
|
||||
private $_scriptUrl;
|
||||
private $_hostInfo;
|
||||
private $_ruleCache;
|
||||
|
||||
|
||||
/**
|
||||
* Initializes UrlManager.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
|
||||
if ($this->normalizer !== false) {
|
||||
$this->normalizer = Yii::createObject($this->normalizer);
|
||||
if (!$this->normalizer instanceof UrlNormalizer) {
|
||||
throw new InvalidConfigException('`' . get_class($this) . '::normalizer` should be an instance of `' . UrlNormalizer::className() . '` or its DI compatible configuration.');
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->enablePrettyUrl) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($this->rules)) {
|
||||
$this->rules = $this->buildRules($this->rules);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds additional URL rules.
|
||||
*
|
||||
* This method will call [[buildRules()]] to parse the given rule declarations and then append or insert
|
||||
* them to the existing [[rules]].
|
||||
*
|
||||
* Note that if [[enablePrettyUrl]] is `false`, this method will do nothing.
|
||||
*
|
||||
* @param array $rules the new rules to be added. Each array element represents a single rule declaration.
|
||||
* Please refer to [[rules]] for the acceptable rule format.
|
||||
* @param bool $append whether to add the new rules by appending them to the end of the existing rules.
|
||||
*/
|
||||
public function addRules($rules, $append = true)
|
||||
{
|
||||
if (!$this->enablePrettyUrl) {
|
||||
return;
|
||||
}
|
||||
$rules = $this->buildRules($rules);
|
||||
if ($append) {
|
||||
$this->rules = array_merge($this->rules, $rules);
|
||||
} else {
|
||||
$this->rules = array_merge($rules, $this->rules);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds URL rule objects from the given rule declarations.
|
||||
*
|
||||
* @param array $ruleDeclarations the rule declarations. Each array element represents a single rule declaration.
|
||||
* Please refer to [[rules]] for the acceptable rule formats.
|
||||
* @return UrlRuleInterface[] the rule objects built from the given rule declarations
|
||||
* @throws InvalidConfigException if a rule declaration is invalid
|
||||
*/
|
||||
protected function buildRules($ruleDeclarations)
|
||||
{
|
||||
$builtRules = $this->getBuiltRulesFromCache($ruleDeclarations);
|
||||
if ($builtRules !== false) {
|
||||
return $builtRules;
|
||||
}
|
||||
|
||||
$builtRules = [];
|
||||
$verbs = 'GET|HEAD|POST|PUT|PATCH|DELETE|OPTIONS';
|
||||
foreach ($ruleDeclarations as $key => $rule) {
|
||||
if (is_string($rule)) {
|
||||
$rule = ['route' => $rule];
|
||||
if (preg_match("/^((?:($verbs),)*($verbs))\\s+(.*)$/", $key, $matches)) {
|
||||
$rule['verb'] = explode(',', $matches[1]);
|
||||
$key = $matches[4];
|
||||
}
|
||||
$rule['pattern'] = $key;
|
||||
}
|
||||
if (is_array($rule)) {
|
||||
$rule = Yii::createObject(array_merge($this->ruleConfig, $rule));
|
||||
}
|
||||
if (!$rule instanceof UrlRuleInterface) {
|
||||
throw new InvalidConfigException('URL rule class must implement UrlRuleInterface.');
|
||||
}
|
||||
$builtRules[] = $rule;
|
||||
}
|
||||
|
||||
$this->setBuiltRulesCache($ruleDeclarations, $builtRules);
|
||||
|
||||
return $builtRules;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CacheInterface|null|bool
|
||||
*/
|
||||
private function ensureCache()
|
||||
{
|
||||
if (!$this->cache instanceof CacheInterface && $this->cache !== false && $this->cache !== null) {
|
||||
try {
|
||||
$this->cache = Instance::ensure($this->cache, 'yii\caching\CacheInterface');
|
||||
} catch (InvalidConfigException $e) {
|
||||
Yii::warning('Unable to use cache for URL manager: ' . $e->getMessage());
|
||||
$this->cache = null;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores $builtRules to cache, using $rulesDeclaration as a part of cache key.
|
||||
*
|
||||
* @param array $ruleDeclarations the rule declarations. Each array element represents a single rule declaration.
|
||||
* Please refer to [[rules]] for the acceptable rule formats.
|
||||
* @param UrlRuleInterface[] $builtRules the rule objects built from the given rule declarations.
|
||||
* @return bool whether the value is successfully stored into cache
|
||||
* @since 2.0.14
|
||||
*/
|
||||
protected function setBuiltRulesCache($ruleDeclarations, $builtRules)
|
||||
{
|
||||
$cache = $this->ensureCache();
|
||||
if (!$cache) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $cache->set([$this->cacheKey, $this->ruleConfig, $ruleDeclarations], $builtRules);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the built URL rules that are associated with the $ruleDeclarations from cache.
|
||||
*
|
||||
* @param array $ruleDeclarations the rule declarations. Each array element represents a single rule declaration.
|
||||
* Please refer to [[rules]] for the acceptable rule formats.
|
||||
* @return UrlRuleInterface[]|false the rule objects built from the given rule declarations or boolean `false` when
|
||||
* there are no cache items for this definition exists.
|
||||
* @since 2.0.14
|
||||
*/
|
||||
protected function getBuiltRulesFromCache($ruleDeclarations)
|
||||
{
|
||||
$cache = $this->ensureCache();
|
||||
if (!$cache) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $cache->get([$this->cacheKey, $this->ruleConfig, $ruleDeclarations]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the user request.
|
||||
* @param Request $request the request component
|
||||
* @return array|bool the route and the associated parameters. The latter is always empty
|
||||
* if [[enablePrettyUrl]] is `false`. `false` is returned if the current request cannot be successfully parsed.
|
||||
*/
|
||||
public function parseRequest($request)
|
||||
{
|
||||
if ($this->enablePrettyUrl) {
|
||||
/** @var UrlRule $rule */
|
||||
foreach ($this->rules as $rule) {
|
||||
$result = $rule->parseRequest($this, $request);
|
||||
if (YII_DEBUG) {
|
||||
Yii::debug([
|
||||
'rule' => method_exists($rule, '__toString') ? $rule->__toString() : get_class($rule),
|
||||
'match' => $result !== false,
|
||||
'parent' => null,
|
||||
], __METHOD__);
|
||||
}
|
||||
if ($result !== false) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->enableStrictParsing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Yii::debug('No matching URL rules. Using default URL parsing logic.', __METHOD__);
|
||||
|
||||
$suffix = (string) $this->suffix;
|
||||
$pathInfo = $request->getPathInfo();
|
||||
$normalized = false;
|
||||
if ($this->normalizer !== false) {
|
||||
$pathInfo = $this->normalizer->normalizePathInfo($pathInfo, $suffix, $normalized);
|
||||
}
|
||||
if ($suffix !== '' && $pathInfo !== '') {
|
||||
$n = strlen($this->suffix);
|
||||
if (substr_compare($pathInfo, $this->suffix, -$n, $n) === 0) {
|
||||
$pathInfo = substr($pathInfo, 0, -$n);
|
||||
if ($pathInfo === '') {
|
||||
// suffix alone is not allowed
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// suffix doesn't match
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($normalized) {
|
||||
// pathInfo was changed by normalizer - we need also normalize route
|
||||
return $this->normalizer->normalizeRoute([$pathInfo, []]);
|
||||
}
|
||||
|
||||
return [$pathInfo, []];
|
||||
}
|
||||
|
||||
Yii::debug('Pretty URL not enabled. Using default URL parsing logic.', __METHOD__);
|
||||
$route = $request->getQueryParam($this->routeParam, '');
|
||||
if (is_array($route)) {
|
||||
$route = '';
|
||||
}
|
||||
|
||||
return [(string) $route, []];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a URL using the given route and query parameters.
|
||||
*
|
||||
* You may specify the route as a string, e.g., `site/index`. You may also use an array
|
||||
* if you want to specify additional query parameters for the URL being created. The
|
||||
* array format must be:
|
||||
*
|
||||
* ```
|
||||
* // generates: /index.php?r=site%2Findex¶m1=value1¶m2=value2
|
||||
* ['site/index', 'param1' => 'value1', 'param2' => 'value2']
|
||||
* ```
|
||||
*
|
||||
* If you want to create a URL with an anchor, you can use the array format with a `#` parameter.
|
||||
* For example,
|
||||
*
|
||||
* ```
|
||||
* // generates: /index.php?r=site%2Findex¶m1=value1#name
|
||||
* ['site/index', 'param1' => 'value1', '#' => 'name']
|
||||
* ```
|
||||
*
|
||||
* The URL created is a relative one. Use [[createAbsoluteUrl()]] to create an absolute URL.
|
||||
*
|
||||
* Note that unlike [[\yii\helpers\Url::toRoute()]], this method always treats the given route
|
||||
* as an absolute route.
|
||||
*
|
||||
* @param string|array $params use a string to represent a route (e.g. `site/index`),
|
||||
* or an array to represent a route with query parameters (e.g. `['site/index', 'param1' => 'value1']`).
|
||||
* @return string the created URL
|
||||
*/
|
||||
public function createUrl($params)
|
||||
{
|
||||
$params = (array) $params;
|
||||
$anchor = isset($params['#']) ? '#' . $params['#'] : '';
|
||||
unset($params['#'], $params[$this->routeParam]);
|
||||
|
||||
$route = trim(isset($params[0]) ? $params[0] : '', '/');
|
||||
unset($params[0]);
|
||||
|
||||
$baseUrl = $this->showScriptName || !$this->enablePrettyUrl ? $this->getScriptUrl() : $this->getBaseUrl();
|
||||
|
||||
if ($this->enablePrettyUrl) {
|
||||
$cacheKey = $route . '?';
|
||||
foreach ($params as $key => $value) {
|
||||
if ($value !== null) {
|
||||
$cacheKey .= $key . '&';
|
||||
}
|
||||
}
|
||||
|
||||
$url = $this->getUrlFromCache($cacheKey, $route, $params);
|
||||
if ($url === false) {
|
||||
/** @var UrlRule $rule */
|
||||
foreach ($this->rules as $rule) {
|
||||
if (in_array($rule, $this->_ruleCache[$cacheKey], true)) {
|
||||
// avoid redundant calls of `UrlRule::createUrl()` for rules checked in `getUrlFromCache()`
|
||||
// @see https://github.com/yiisoft/yii2/issues/14094
|
||||
continue;
|
||||
}
|
||||
$url = $rule->createUrl($this, $route, $params);
|
||||
if ($this->canBeCached($rule)) {
|
||||
$this->setRuleToCache($cacheKey, $rule);
|
||||
}
|
||||
if ($url !== false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($url !== false) {
|
||||
if (strpos($url, '://') !== false) {
|
||||
if ($baseUrl !== '' && ($pos = strpos($url, '/', 8)) !== false) {
|
||||
return substr($url, 0, $pos) . $baseUrl . substr($url, $pos) . $anchor;
|
||||
}
|
||||
|
||||
return $url . $baseUrl . $anchor;
|
||||
} elseif (strncmp($url, '//', 2) === 0) {
|
||||
if ($baseUrl !== '' && ($pos = strpos($url, '/', 2)) !== false) {
|
||||
return substr($url, 0, $pos) . $baseUrl . substr($url, $pos) . $anchor;
|
||||
}
|
||||
|
||||
return $url . $baseUrl . $anchor;
|
||||
}
|
||||
|
||||
$url = ltrim($url, '/');
|
||||
return "$baseUrl/{$url}{$anchor}";
|
||||
}
|
||||
|
||||
if ($this->suffix !== null) {
|
||||
$route .= $this->suffix;
|
||||
}
|
||||
if (!empty($params) && ($query = http_build_query($params)) !== '') {
|
||||
$route .= '?' . $query;
|
||||
}
|
||||
|
||||
$route = ltrim($route, '/');
|
||||
return "$baseUrl/{$route}{$anchor}";
|
||||
}
|
||||
|
||||
$url = "$baseUrl?{$this->routeParam}=" . urlencode($route);
|
||||
if (!empty($params) && ($query = http_build_query($params)) !== '') {
|
||||
$url .= '&' . $query;
|
||||
}
|
||||
|
||||
return $url . $anchor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value indicating whether result of [[createUrl()]] of rule should be cached in internal cache.
|
||||
*
|
||||
* @param UrlRuleInterface $rule
|
||||
* @return bool `true` if result should be cached, `false` if not.
|
||||
* @since 2.0.12
|
||||
* @see getUrlFromCache()
|
||||
* @see setRuleToCache()
|
||||
* @see UrlRule::getCreateUrlStatus()
|
||||
*/
|
||||
protected function canBeCached(UrlRuleInterface $rule)
|
||||
{
|
||||
return
|
||||
// if rule does not provide info about create status, we cache it every time to prevent bugs like #13350
|
||||
// @see https://github.com/yiisoft/yii2/pull/13350#discussion_r114873476
|
||||
!method_exists($rule, 'getCreateUrlStatus') || ($status = $rule->getCreateUrlStatus()) === null
|
||||
|| $status === UrlRule::CREATE_STATUS_SUCCESS
|
||||
|| $status & UrlRule::CREATE_STATUS_PARAMS_MISMATCH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get URL from internal cache if exists.
|
||||
* @param string $cacheKey generated cache key to store data.
|
||||
* @param string $route the route (e.g. `site/index`).
|
||||
* @param array $params rule params.
|
||||
* @return bool|string the created URL
|
||||
* @see createUrl()
|
||||
* @since 2.0.8
|
||||
*/
|
||||
protected function getUrlFromCache($cacheKey, $route, $params)
|
||||
{
|
||||
if (!empty($this->_ruleCache[$cacheKey])) {
|
||||
foreach ($this->_ruleCache[$cacheKey] as $rule) {
|
||||
/** @var UrlRule $rule */
|
||||
if (($url = $rule->createUrl($this, $route, $params)) !== false) {
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->_ruleCache[$cacheKey] = [];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store rule (e.g. [[UrlRule]]) to internal cache.
|
||||
* @param $cacheKey
|
||||
* @param UrlRuleInterface $rule
|
||||
* @since 2.0.8
|
||||
*/
|
||||
protected function setRuleToCache($cacheKey, UrlRuleInterface $rule)
|
||||
{
|
||||
$this->_ruleCache[$cacheKey][] = $rule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an absolute URL using the given route and query parameters.
|
||||
*
|
||||
* This method prepends the URL created by [[createUrl()]] with the [[hostInfo]].
|
||||
*
|
||||
* Note that unlike [[\yii\helpers\Url::toRoute()]], this method always treats the given route
|
||||
* as an absolute route.
|
||||
*
|
||||
* @param string|array $params use a string to represent a route (e.g. `site/index`),
|
||||
* or an array to represent a route with query parameters (e.g. `['site/index', 'param1' => 'value1']`).
|
||||
* @param string|null $scheme the scheme to use for the URL (either `http`, `https` or empty string
|
||||
* for protocol-relative URL).
|
||||
* If not specified the scheme of the current request will be used.
|
||||
* @return string the created URL
|
||||
* @see createUrl()
|
||||
*/
|
||||
public function createAbsoluteUrl($params, $scheme = null)
|
||||
{
|
||||
$params = (array) $params;
|
||||
$url = $this->createUrl($params);
|
||||
if (strpos($url, '://') === false) {
|
||||
$hostInfo = $this->getHostInfo();
|
||||
if (strncmp($url, '//', 2) === 0) {
|
||||
$url = substr($hostInfo, 0, strpos($hostInfo, '://')) . ':' . $url;
|
||||
} else {
|
||||
$url = $hostInfo . $url;
|
||||
}
|
||||
}
|
||||
|
||||
return Url::ensureScheme($url, $scheme);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base URL that is used by [[createUrl()]] to prepend to created URLs.
|
||||
* It defaults to [[Request::baseUrl]].
|
||||
* This is mainly used when [[enablePrettyUrl]] is `true` and [[showScriptName]] is `false`.
|
||||
* @return string the base URL that is used by [[createUrl()]] to prepend to created URLs.
|
||||
* @throws InvalidConfigException if running in console application and [[baseUrl]] is not configured.
|
||||
*/
|
||||
public function getBaseUrl()
|
||||
{
|
||||
if ($this->_baseUrl === null) {
|
||||
$request = Yii::$app->getRequest();
|
||||
if ($request instanceof Request) {
|
||||
$this->_baseUrl = $request->getBaseUrl();
|
||||
} else {
|
||||
throw new InvalidConfigException('Please configure UrlManager::baseUrl correctly as you are running a console application.');
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_baseUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the base URL that is used by [[createUrl()]] to prepend to created URLs.
|
||||
* This is mainly used when [[enablePrettyUrl]] is `true` and [[showScriptName]] is `false`.
|
||||
* @param string $value the base URL that is used by [[createUrl()]] to prepend to created URLs.
|
||||
*/
|
||||
public function setBaseUrl($value)
|
||||
{
|
||||
$this->_baseUrl = $value === null ? null : rtrim(Yii::getAlias($value), '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entry script URL that is used by [[createUrl()]] to prepend to created URLs.
|
||||
* It defaults to [[Request::scriptUrl]].
|
||||
* This is mainly used when [[enablePrettyUrl]] is `false` or [[showScriptName]] is `true`.
|
||||
* @return string the entry script URL that is used by [[createUrl()]] to prepend to created URLs.
|
||||
* @throws InvalidConfigException if running in console application and [[scriptUrl]] is not configured.
|
||||
*/
|
||||
public function getScriptUrl()
|
||||
{
|
||||
if ($this->_scriptUrl === null) {
|
||||
$request = Yii::$app->getRequest();
|
||||
if ($request instanceof Request) {
|
||||
$this->_scriptUrl = $request->getScriptUrl();
|
||||
} else {
|
||||
throw new InvalidConfigException('Please configure UrlManager::scriptUrl correctly as you are running a console application.');
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_scriptUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the entry script URL that is used by [[createUrl()]] to prepend to created URLs.
|
||||
* This is mainly used when [[enablePrettyUrl]] is `false` or [[showScriptName]] is `true`.
|
||||
* @param string $value the entry script URL that is used by [[createUrl()]] to prepend to created URLs.
|
||||
*/
|
||||
public function setScriptUrl($value)
|
||||
{
|
||||
$this->_scriptUrl = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the host info that is used by [[createAbsoluteUrl()]] to prepend to created URLs.
|
||||
* @return string the host info (e.g. `https://www.example.com`) that is used by [[createAbsoluteUrl()]] to prepend to created URLs.
|
||||
* @throws InvalidConfigException if running in console application and [[hostInfo]] is not configured.
|
||||
*/
|
||||
public function getHostInfo()
|
||||
{
|
||||
if ($this->_hostInfo === null) {
|
||||
$request = Yii::$app->getRequest();
|
||||
if ($request instanceof \yii\web\Request) {
|
||||
$this->_hostInfo = $request->getHostInfo();
|
||||
} else {
|
||||
throw new InvalidConfigException('Please configure UrlManager::hostInfo correctly as you are running a console application.');
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_hostInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the host info that is used by [[createAbsoluteUrl()]] to prepend to created URLs.
|
||||
* @param string $value the host info (e.g. "https://www.example.com") that is used by [[createAbsoluteUrl()]] to prepend to created URLs.
|
||||
*/
|
||||
public function setHostInfo($value)
|
||||
{
|
||||
$this->_hostInfo = $value === null ? null : rtrim($value, '/');
|
||||
}
|
||||
}
|
||||
149
vendor/yiisoft/yii2/web/UrlNormalizer.php
vendored
Normal file
149
vendor/yiisoft/yii2/web/UrlNormalizer.php
vendored
Normal file
@ -0,0 +1,149 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use Yii;
|
||||
use yii\base\BaseObject;
|
||||
use yii\base\InvalidConfigException;
|
||||
|
||||
/**
|
||||
* UrlNormalizer normalizes URLs for [[UrlManager]] and [[UrlRule]].
|
||||
*
|
||||
* @author Robert Korulczyk <robert@korulczyk.pl>
|
||||
* @author Cronfy <cronfy@gmail.com>
|
||||
* @since 2.0.10
|
||||
*/
|
||||
class UrlNormalizer extends BaseObject
|
||||
{
|
||||
/**
|
||||
* Represents permament redirection during route normalization.
|
||||
* @see https://en.wikipedia.org/wiki/HTTP_301
|
||||
*/
|
||||
public const ACTION_REDIRECT_PERMANENT = 301;
|
||||
/**
|
||||
* Represents temporary redirection during route normalization.
|
||||
* @see https://en.wikipedia.org/wiki/HTTP_302
|
||||
*/
|
||||
public const ACTION_REDIRECT_TEMPORARY = 302;
|
||||
/**
|
||||
* Represents showing 404 error page during route normalization.
|
||||
* @see https://en.wikipedia.org/wiki/HTTP_404
|
||||
*/
|
||||
public const ACTION_NOT_FOUND = 404;
|
||||
/**
|
||||
* @var bool whether slashes should be collapsed, for example `site///index` will be
|
||||
* converted into `site/index`
|
||||
*/
|
||||
public $collapseSlashes = true;
|
||||
/**
|
||||
* @var bool whether trailing slash should be normalized according to the suffix settings
|
||||
* of the rule
|
||||
*/
|
||||
public $normalizeTrailingSlash = true;
|
||||
/**
|
||||
* @var int|callable|null action to perform during route normalization.
|
||||
* Available options are:
|
||||
* - `null` - no special action will be performed
|
||||
* - `301` - the request should be redirected to the normalized URL using
|
||||
* permanent redirection
|
||||
* - `302` - the request should be redirected to the normalized URL using
|
||||
* temporary redirection
|
||||
* - `404` - [[NotFoundHttpException]] will be thrown
|
||||
* - `callable` - custom user callback, for example:
|
||||
*
|
||||
* ```
|
||||
* function ($route, $normalizer) {
|
||||
* // use custom action for redirections
|
||||
* $route[1]['oldRoute'] = $route[0];
|
||||
* $route[0] = 'site/redirect';
|
||||
* return $route;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
public $action = self::ACTION_REDIRECT_PERMANENT;
|
||||
|
||||
|
||||
/**
|
||||
* Performs normalization action for the specified $route.
|
||||
* @param array $route route for normalization
|
||||
* @return array normalized route
|
||||
* @throws InvalidConfigException if invalid normalization action is used.
|
||||
* @throws UrlNormalizerRedirectException if normalization requires redirection.
|
||||
* @throws NotFoundHttpException if normalization suggests action matching route does not exist.
|
||||
*/
|
||||
public function normalizeRoute($route)
|
||||
{
|
||||
if ($this->action === null) {
|
||||
return $route;
|
||||
} elseif ($this->action === static::ACTION_REDIRECT_PERMANENT || $this->action === static::ACTION_REDIRECT_TEMPORARY) {
|
||||
throw new UrlNormalizerRedirectException([$route[0]] + $route[1], $this->action);
|
||||
} elseif ($this->action === static::ACTION_NOT_FOUND) {
|
||||
throw new NotFoundHttpException(Yii::t('yii', 'Page not found.'));
|
||||
} elseif (is_callable($this->action)) {
|
||||
return call_user_func($this->action, $route, $this);
|
||||
}
|
||||
|
||||
throw new InvalidConfigException('Invalid normalizer action.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes specified pathInfo.
|
||||
* @param string $pathInfo pathInfo for normalization
|
||||
* @param string $suffix current rule suffix
|
||||
* @param bool $normalized if specified, this variable will be set to `true` if $pathInfo
|
||||
* was changed during normalization
|
||||
* @return string normalized pathInfo
|
||||
*/
|
||||
public function normalizePathInfo($pathInfo, $suffix, &$normalized = false)
|
||||
{
|
||||
if (empty($pathInfo)) {
|
||||
return $pathInfo;
|
||||
}
|
||||
|
||||
$sourcePathInfo = $pathInfo;
|
||||
if ($this->collapseSlashes) {
|
||||
$pathInfo = $this->collapseSlashes($pathInfo);
|
||||
}
|
||||
|
||||
if ($this->normalizeTrailingSlash === true) {
|
||||
$pathInfo = $this->normalizeTrailingSlash($pathInfo, $suffix);
|
||||
}
|
||||
|
||||
$normalized = $sourcePathInfo !== $pathInfo;
|
||||
|
||||
return $pathInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collapse consecutive slashes in $pathInfo, for example converts `site///index` into `site/index`.
|
||||
* @param string $pathInfo raw path info.
|
||||
* @return string normalized path info.
|
||||
*/
|
||||
protected function collapseSlashes($pathInfo)
|
||||
{
|
||||
return ltrim(preg_replace('#/{2,}#', '/', $pathInfo), '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds or removes trailing slashes from $pathInfo depending on whether the $suffix has a
|
||||
* trailing slash or not.
|
||||
* @param string $pathInfo raw path info.
|
||||
* @param string $suffix
|
||||
* @return string normalized path info.
|
||||
*/
|
||||
protected function normalizeTrailingSlash($pathInfo, $suffix)
|
||||
{
|
||||
if (substr($suffix, -1) === '/' && substr($pathInfo, -1) !== '/') {
|
||||
$pathInfo .= '/';
|
||||
} elseif (substr($suffix, -1) !== '/' && substr($pathInfo, -1) === '/') {
|
||||
$pathInfo = rtrim($pathInfo, '/');
|
||||
}
|
||||
|
||||
return $pathInfo;
|
||||
}
|
||||
}
|
||||
52
vendor/yiisoft/yii2/web/UrlNormalizerRedirectException.php
vendored
Normal file
52
vendor/yiisoft/yii2/web/UrlNormalizerRedirectException.php
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* UrlNormalizerRedirectException represents an information for redirection which should be
|
||||
* performed during the URL normalization.
|
||||
*
|
||||
* @author Robert Korulczyk <robert@korulczyk.pl>
|
||||
* @since 2.0.10
|
||||
*/
|
||||
class UrlNormalizerRedirectException extends \yii\base\Exception
|
||||
{
|
||||
/**
|
||||
* @var array|string the parameter to be used to generate a valid URL for redirection
|
||||
* @see \yii\helpers\Url::to()
|
||||
*/
|
||||
public $url;
|
||||
/**
|
||||
* @var bool|string the URI scheme to use in the generated URL for redirection
|
||||
* @see \yii\helpers\Url::to()
|
||||
*/
|
||||
public $scheme;
|
||||
/**
|
||||
* @var int the HTTP status code
|
||||
*/
|
||||
public $statusCode;
|
||||
|
||||
|
||||
/**
|
||||
* @param array|string $url the parameter to be used to generate a valid URL for redirection.
|
||||
* This will be used as first parameter for [[\yii\helpers\Url::to()]]
|
||||
* @param int $statusCode HTTP status code used for redirection
|
||||
* @param bool|string $scheme the URI scheme to use in the generated URL for redirection.
|
||||
* This will be used as second parameter for [[\yii\helpers\Url::to()]]
|
||||
* @param string|null $message the error message
|
||||
* @param int $code the error code
|
||||
* @param \Throwable|null $previous the previous exception used for the exception chaining
|
||||
*/
|
||||
public function __construct($url, $statusCode = 302, $scheme = false, $message = null, $code = 0, $previous = null)
|
||||
{
|
||||
$this->url = $url;
|
||||
$this->scheme = $scheme;
|
||||
$this->statusCode = $statusCode;
|
||||
parent::__construct((string)$message, $code, $previous);
|
||||
}
|
||||
}
|
||||
603
vendor/yiisoft/yii2/web/UrlRule.php
vendored
Normal file
603
vendor/yiisoft/yii2/web/UrlRule.php
vendored
Normal file
@ -0,0 +1,603 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use Yii;
|
||||
use yii\base\BaseObject;
|
||||
use yii\base\InvalidConfigException;
|
||||
|
||||
/**
|
||||
* UrlRule represents a rule used by [[UrlManager]] for parsing and generating URLs.
|
||||
*
|
||||
* To define your own URL parsing and creation logic you can extend from this class
|
||||
* and add it to [[UrlManager::rules]] like this:
|
||||
*
|
||||
* ```
|
||||
* 'rules' => [
|
||||
* ['class' => 'MyUrlRule', 'pattern' => '...', 'route' => 'site/index', ...],
|
||||
* // ...
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* @property-read int|null $createUrlStatus Status of the URL creation after the last [[createUrl()]] call.
|
||||
* `null` if rule does not provide info about create status.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class UrlRule extends BaseObject implements UrlRuleInterface
|
||||
{
|
||||
/**
|
||||
* Set [[mode]] with this value to mark that this rule is for URL parsing only.
|
||||
*/
|
||||
public const PARSING_ONLY = 1;
|
||||
/**
|
||||
* Set [[mode]] with this value to mark that this rule is for URL creation only.
|
||||
*/
|
||||
public const CREATION_ONLY = 2;
|
||||
/**
|
||||
* Represents the successful URL generation by last [[createUrl()]] call.
|
||||
* @see createStatus
|
||||
* @since 2.0.12
|
||||
*/
|
||||
public const CREATE_STATUS_SUCCESS = 0;
|
||||
/**
|
||||
* Represents the unsuccessful URL generation by last [[createUrl()]] call, because rule does not support
|
||||
* creating URLs.
|
||||
* @see createStatus
|
||||
* @since 2.0.12
|
||||
*/
|
||||
public const CREATE_STATUS_PARSING_ONLY = 1;
|
||||
/**
|
||||
* Represents the unsuccessful URL generation by last [[createUrl()]] call, because of mismatched route.
|
||||
* @see createStatus
|
||||
* @since 2.0.12
|
||||
*/
|
||||
public const CREATE_STATUS_ROUTE_MISMATCH = 2;
|
||||
/**
|
||||
* Represents the unsuccessful URL generation by last [[createUrl()]] call, because of mismatched
|
||||
* or missing parameters.
|
||||
* @see createStatus
|
||||
* @since 2.0.12
|
||||
*/
|
||||
public const CREATE_STATUS_PARAMS_MISMATCH = 4;
|
||||
/**
|
||||
* @var string|null the name of this rule. If not set, it will use [[pattern]] as the name.
|
||||
*/
|
||||
public $name;
|
||||
/**
|
||||
* On the rule initialization, the [[pattern]] matching parameters names will be replaced with [[placeholders]].
|
||||
* @var string the pattern used to parse and create the path info part of a URL.
|
||||
* @see host
|
||||
* @see placeholders
|
||||
*/
|
||||
public $pattern;
|
||||
/**
|
||||
* @var string|null the pattern used to parse and create the host info part of a URL (e.g. `https://example.com`).
|
||||
* @see pattern
|
||||
*/
|
||||
public $host;
|
||||
/**
|
||||
* @var string the route to the controller action
|
||||
*/
|
||||
public $route;
|
||||
/**
|
||||
* @var array the default GET parameters (name => value) that this rule provides.
|
||||
* When this rule is used to parse the incoming request, the values declared in this property
|
||||
* will be injected into $_GET.
|
||||
*/
|
||||
public $defaults = [];
|
||||
/**
|
||||
* @var string|null the URL suffix used for this rule.
|
||||
* For example, ".html" can be used so that the URL looks like pointing to a static HTML page.
|
||||
* If not set, the value of [[UrlManager::suffix]] will be used.
|
||||
* Default values should be strings. Non-string values will be automatically converted to
|
||||
* strings for comparison with URL parameters.
|
||||
*/
|
||||
public $suffix;
|
||||
/**
|
||||
* @var string|array|null the HTTP verb (e.g. GET, POST, DELETE) that this rule should match.
|
||||
* Use array to represent multiple verbs that this rule may match.
|
||||
* If this property is not set, the rule can match any verb.
|
||||
* Note that this property is only used when parsing a request. It is ignored for URL creation.
|
||||
*/
|
||||
public $verb;
|
||||
/**
|
||||
* @var int|null a value indicating if this rule should be used for both request parsing and URL creation,
|
||||
* parsing only, or creation only.
|
||||
* If not set or 0, it means the rule is both request parsing and URL creation.
|
||||
* If it is [[PARSING_ONLY]], the rule is for request parsing only.
|
||||
* If it is [[CREATION_ONLY]], the rule is for URL creation only.
|
||||
*/
|
||||
public $mode;
|
||||
/**
|
||||
* @var bool a value indicating if parameters should be url encoded.
|
||||
*/
|
||||
public $encodeParams = true;
|
||||
/**
|
||||
* @var UrlNormalizer|array|false|null the configuration for [[UrlNormalizer]] used by this rule.
|
||||
* If `null`, [[UrlManager::normalizer]] will be used, if `false`, normalization will be skipped
|
||||
* for this rule.
|
||||
* @since 2.0.10
|
||||
*/
|
||||
public $normalizer;
|
||||
|
||||
/**
|
||||
* @var int|null status of the URL creation after the last [[createUrl()]] call.
|
||||
* @since 2.0.12
|
||||
*/
|
||||
protected $createStatus;
|
||||
/**
|
||||
* @var array list of placeholders for matching parameters names. Used in [[parseRequest()]], [[createUrl()]].
|
||||
* On the rule initialization, the [[pattern]] parameters names will be replaced with placeholders.
|
||||
* This array contains relations between the original parameters names and their placeholders.
|
||||
* The array keys are the placeholders and the values are the original names.
|
||||
*
|
||||
* @see parseRequest()
|
||||
* @see createUrl()
|
||||
* @since 2.0.7
|
||||
*/
|
||||
protected $placeholders = [];
|
||||
|
||||
/**
|
||||
* @var string the template for generating a new URL. This is derived from [[pattern]] and is used in generating URL.
|
||||
*/
|
||||
private $_template;
|
||||
/**
|
||||
* @var string the regex for matching the route part. This is used in generating URL.
|
||||
*/
|
||||
private $_routeRule;
|
||||
/**
|
||||
* @var array list of regex for matching parameters. This is used in generating URL.
|
||||
*/
|
||||
private $_paramRules = [];
|
||||
/**
|
||||
* @var array list of parameters used in the route.
|
||||
*/
|
||||
private $_routeParams = [];
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 2.0.11
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$str = '';
|
||||
if ($this->verb !== null) {
|
||||
$str .= implode(',', $this->verb) . ' ';
|
||||
}
|
||||
if ($this->host !== null && strrpos($this->name, $this->host) === false) {
|
||||
$str .= $this->host . '/';
|
||||
}
|
||||
$str .= $this->name;
|
||||
|
||||
if ($str === '') {
|
||||
return '/';
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes this rule.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
if ($this->pattern === null) {
|
||||
throw new InvalidConfigException('UrlRule::pattern must be set.');
|
||||
}
|
||||
if ($this->route === null) {
|
||||
throw new InvalidConfigException('UrlRule::route must be set.');
|
||||
}
|
||||
if (is_array($this->normalizer)) {
|
||||
$normalizerConfig = array_merge(['class' => UrlNormalizer::className()], $this->normalizer);
|
||||
$this->normalizer = Yii::createObject($normalizerConfig);
|
||||
}
|
||||
if ($this->normalizer !== null && $this->normalizer !== false && !$this->normalizer instanceof UrlNormalizer) {
|
||||
throw new InvalidConfigException('Invalid config for UrlRule::normalizer.');
|
||||
}
|
||||
if ($this->verb !== null) {
|
||||
if (is_array($this->verb)) {
|
||||
foreach ($this->verb as $i => $verb) {
|
||||
$this->verb[$i] = strtoupper($verb);
|
||||
}
|
||||
} else {
|
||||
$this->verb = [strtoupper($this->verb)];
|
||||
}
|
||||
}
|
||||
if ($this->name === null) {
|
||||
$this->name = $this->pattern;
|
||||
}
|
||||
|
||||
$this->preparePattern();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process [[$pattern]] on rule initialization.
|
||||
*/
|
||||
private function preparePattern()
|
||||
{
|
||||
$this->pattern = $this->trimSlashes($this->pattern);
|
||||
$this->route = trim($this->route, '/');
|
||||
|
||||
if ($this->host !== null) {
|
||||
$this->host = rtrim($this->host, '/');
|
||||
$this->pattern = rtrim($this->host . '/' . $this->pattern, '/');
|
||||
} elseif ($this->pattern === '') {
|
||||
$this->_template = '';
|
||||
$this->pattern = '#^$#u';
|
||||
|
||||
return;
|
||||
} elseif (($pos = strpos($this->pattern, '://')) !== false) {
|
||||
if (($pos2 = strpos($this->pattern, '/', $pos + 3)) !== false) {
|
||||
$this->host = substr($this->pattern, 0, $pos2);
|
||||
} else {
|
||||
$this->host = $this->pattern;
|
||||
}
|
||||
} elseif (strncmp($this->pattern, '//', 2) === 0) {
|
||||
if (($pos2 = strpos($this->pattern, '/', 2)) !== false) {
|
||||
$this->host = substr($this->pattern, 0, $pos2);
|
||||
} else {
|
||||
$this->host = $this->pattern;
|
||||
}
|
||||
} else {
|
||||
$this->pattern = '/' . $this->pattern . '/';
|
||||
}
|
||||
|
||||
if (strpos($this->route, '<') !== false && preg_match_all('/<([\w._-]+)>/', $this->route, $matches)) {
|
||||
foreach ($matches[1] as $name) {
|
||||
$this->_routeParams[$name] = "<$name>";
|
||||
}
|
||||
}
|
||||
|
||||
$this->translatePattern(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares [[$pattern]] on rule initialization - replace parameter names by placeholders.
|
||||
*
|
||||
* @param bool $allowAppendSlash Defines position of slash in the param pattern in [[$pattern]].
|
||||
* If `false` slash will be placed at the beginning of param pattern. If `true` slash position will be detected
|
||||
* depending on non-optional pattern part.
|
||||
*/
|
||||
private function translatePattern($allowAppendSlash)
|
||||
{
|
||||
$tr = [
|
||||
'.' => '\\.',
|
||||
'*' => '\\*',
|
||||
'$' => '\\$',
|
||||
'[' => '\\[',
|
||||
']' => '\\]',
|
||||
'(' => '\\(',
|
||||
')' => '\\)',
|
||||
];
|
||||
|
||||
$tr2 = [];
|
||||
$requiredPatternPart = $this->pattern;
|
||||
$oldOffset = 0;
|
||||
if (preg_match_all('/<([\w._-]+):?([^>]+)?>/', $this->pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
|
||||
$appendSlash = false;
|
||||
foreach ($matches as $match) {
|
||||
$name = $match[1][0];
|
||||
$pattern = isset($match[2][0]) ? $match[2][0] : '[^\/]+';
|
||||
$placeholder = 'a' . hash('crc32b', $name); // placeholder must begin with a letter
|
||||
$this->placeholders[$placeholder] = $name;
|
||||
if (array_key_exists($name, $this->defaults)) {
|
||||
$length = strlen($match[0][0]);
|
||||
$offset = $match[0][1];
|
||||
$requiredPatternPart = str_replace("/{$match[0][0]}/", '//', $requiredPatternPart);
|
||||
if (
|
||||
$allowAppendSlash
|
||||
&& ($appendSlash || $offset === 1)
|
||||
&& (($offset - $oldOffset) === 1)
|
||||
&& isset($this->pattern[$offset + $length])
|
||||
&& $this->pattern[$offset + $length] === '/'
|
||||
&& isset($this->pattern[$offset + $length + 1])
|
||||
) {
|
||||
// if pattern starts from optional params, put slash at the end of param pattern
|
||||
// @see https://github.com/yiisoft/yii2/issues/13086
|
||||
$appendSlash = true;
|
||||
$tr["<$name>/"] = "((?P<$placeholder>$pattern)/)?";
|
||||
} elseif (
|
||||
$offset > 1
|
||||
&& $this->pattern[$offset - 1] === '/'
|
||||
&& (!isset($this->pattern[$offset + $length]) || $this->pattern[$offset + $length] === '/')
|
||||
) {
|
||||
$appendSlash = false;
|
||||
$tr["/<$name>"] = "(/(?P<$placeholder>$pattern))?";
|
||||
}
|
||||
$tr["<$name>"] = "(?P<$placeholder>$pattern)?";
|
||||
$oldOffset = $offset + $length;
|
||||
} else {
|
||||
$appendSlash = false;
|
||||
$tr["<$name>"] = "(?P<$placeholder>$pattern)";
|
||||
}
|
||||
|
||||
if (isset($this->_routeParams[$name])) {
|
||||
$tr2["<$name>"] = "(?P<$placeholder>$pattern)";
|
||||
} else {
|
||||
$this->_paramRules[$name] = $pattern === '[^\/]+' ? '' : "#^$pattern$#u";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we have only optional params in route - ensure slash position on param patterns
|
||||
if ($allowAppendSlash && trim($requiredPatternPart, '/') === '') {
|
||||
$this->translatePattern(false);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->_template = preg_replace('/<([\w._-]+):?([^>]+)?>/', '<$1>', $this->pattern);
|
||||
$this->pattern = '#^' . trim(strtr($this->_template, $tr), '/') . '$#u';
|
||||
|
||||
// if host starts with relative scheme, then insert pattern to match any
|
||||
if ($this->host !== null && strncmp($this->host, '//', 2) === 0) {
|
||||
$this->pattern = substr_replace($this->pattern, '[\w]+://', 2, 0);
|
||||
}
|
||||
|
||||
if (!empty($this->_routeParams)) {
|
||||
$this->_routeRule = '#^' . strtr($this->route, $tr2) . '$#u';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UrlManager $manager the URL manager
|
||||
* @return UrlNormalizer|null
|
||||
* @since 2.0.10
|
||||
*/
|
||||
protected function getNormalizer($manager)
|
||||
{
|
||||
if ($this->normalizer === null) {
|
||||
return $manager->normalizer;
|
||||
}
|
||||
|
||||
return $this->normalizer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UrlManager $manager the URL manager
|
||||
* @return bool
|
||||
* @since 2.0.10
|
||||
*/
|
||||
protected function hasNormalizer($manager)
|
||||
{
|
||||
return $this->getNormalizer($manager) instanceof UrlNormalizer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given request and returns the corresponding route and parameters.
|
||||
* @param UrlManager $manager the URL manager
|
||||
* @param Request $request the request component
|
||||
* @return array|bool the parsing result. The route and the parameters are returned as an array.
|
||||
* If `false`, it means this rule cannot be used to parse this path info.
|
||||
*/
|
||||
public function parseRequest($manager, $request)
|
||||
{
|
||||
if ($this->mode === self::CREATION_ONLY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!empty($this->verb) && !in_array($request->getMethod(), $this->verb, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$suffix = (string) ($this->suffix === null ? $manager->suffix : $this->suffix);
|
||||
$pathInfo = $request->getPathInfo();
|
||||
$normalized = false;
|
||||
if ($this->hasNormalizer($manager)) {
|
||||
$pathInfo = $this->getNormalizer($manager)->normalizePathInfo($pathInfo, $suffix, $normalized);
|
||||
}
|
||||
if ($suffix !== '' && $pathInfo !== '') {
|
||||
$n = strlen($suffix);
|
||||
if (substr_compare($pathInfo, $suffix, -$n, $n) === 0) {
|
||||
$pathInfo = substr($pathInfo, 0, -$n);
|
||||
if ($pathInfo === '') {
|
||||
// suffix alone is not allowed
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->host !== null) {
|
||||
$pathInfo = strtolower($request->getHostInfo()) . ($pathInfo === '' ? '' : '/' . $pathInfo);
|
||||
}
|
||||
|
||||
if (!preg_match($this->pattern, $pathInfo, $matches)) {
|
||||
return false;
|
||||
}
|
||||
$matches = $this->substitutePlaceholderNames($matches);
|
||||
|
||||
foreach ($this->defaults as $name => $value) {
|
||||
if (!isset($matches[$name]) || $matches[$name] === '') {
|
||||
$matches[$name] = $value;
|
||||
}
|
||||
}
|
||||
$params = $this->defaults;
|
||||
$tr = [];
|
||||
foreach ($matches as $name => $value) {
|
||||
if (isset($this->_routeParams[$name])) {
|
||||
$tr[$this->_routeParams[$name]] = $value;
|
||||
unset($params[$name]);
|
||||
} elseif (isset($this->_paramRules[$name])) {
|
||||
$params[$name] = $value;
|
||||
}
|
||||
}
|
||||
if ($this->_routeRule !== null) {
|
||||
$route = strtr($this->route, $tr);
|
||||
} else {
|
||||
$route = $this->route;
|
||||
}
|
||||
|
||||
Yii::debug("Request parsed with URL rule: {$this->name}", __METHOD__);
|
||||
|
||||
if ($normalized) {
|
||||
// pathInfo was changed by normalizer - we need also normalize route
|
||||
return $this->getNormalizer($manager)->normalizeRoute([$route, $params]);
|
||||
}
|
||||
|
||||
return [$route, $params];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a URL according to the given route and parameters.
|
||||
* @param UrlManager $manager the URL manager
|
||||
* @param string $route the route. It should not have slashes at the beginning or the end.
|
||||
* @param array $params the parameters
|
||||
* @return string|bool the created URL, or `false` if this rule cannot be used for creating this URL.
|
||||
*/
|
||||
public function createUrl($manager, $route, $params)
|
||||
{
|
||||
if ($this->mode === self::PARSING_ONLY) {
|
||||
$this->createStatus = self::CREATE_STATUS_PARSING_ONLY;
|
||||
return false;
|
||||
}
|
||||
|
||||
$tr = [];
|
||||
|
||||
// match the route part first
|
||||
if ($route !== $this->route) {
|
||||
if ($this->_routeRule !== null && preg_match($this->_routeRule, $route, $matches)) {
|
||||
$matches = $this->substitutePlaceholderNames($matches);
|
||||
foreach ($this->_routeParams as $name => $token) {
|
||||
if (isset($this->defaults[$name]) && strcmp($this->defaults[$name], $matches[$name]) === 0) {
|
||||
$tr[$token] = '';
|
||||
} else {
|
||||
$tr[$token] = $matches[$name];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->createStatus = self::CREATE_STATUS_ROUTE_MISMATCH;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// match default params
|
||||
// if a default param is not in the route pattern, its value must also be matched
|
||||
foreach ($this->defaults as $name => $value) {
|
||||
if (isset($this->_routeParams[$name])) {
|
||||
continue;
|
||||
}
|
||||
if (!isset($params[$name])) {
|
||||
// allow omit empty optional params
|
||||
// @see https://github.com/yiisoft/yii2/issues/10970
|
||||
if (in_array($name, $this->placeholders) && strcmp($value, '') === 0) {
|
||||
$params[$name] = '';
|
||||
} else {
|
||||
$this->createStatus = self::CREATE_STATUS_PARAMS_MISMATCH;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (strcmp($params[$name], (string) $value) === 0) {
|
||||
unset($params[$name]);
|
||||
if (isset($this->_paramRules[$name])) {
|
||||
$tr["<$name>"] = '';
|
||||
}
|
||||
} elseif (!isset($this->_paramRules[$name])) {
|
||||
$this->createStatus = self::CREATE_STATUS_PARAMS_MISMATCH;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// match params in the pattern
|
||||
foreach ($this->_paramRules as $name => $rule) {
|
||||
if (isset($params[$name]) && !is_array($params[$name]) && ($rule === '' || preg_match($rule, $params[$name]))) {
|
||||
$tr["<$name>"] = $this->encodeParams ? urlencode($params[$name]) : $params[$name];
|
||||
unset($params[$name]);
|
||||
} elseif (!isset($this->defaults[$name]) || isset($params[$name])) {
|
||||
$this->createStatus = self::CREATE_STATUS_PARAMS_MISMATCH;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$url = $this->trimSlashes(strtr($this->_template, $tr));
|
||||
if ($this->host !== null) {
|
||||
$pos = strpos($url, '/', 8);
|
||||
if ($pos !== false) {
|
||||
$url = substr($url, 0, $pos) . preg_replace('#/+#', '/', substr($url, $pos));
|
||||
}
|
||||
} elseif (strpos($url, '//') !== false) {
|
||||
$url = preg_replace('#/+#', '/', trim($url, '/'));
|
||||
}
|
||||
|
||||
if ($url !== '') {
|
||||
$url .= ($this->suffix === null ? $manager->suffix : $this->suffix);
|
||||
}
|
||||
|
||||
if (!empty($params) && ($query = http_build_query($params)) !== '') {
|
||||
$url .= '?' . $query;
|
||||
}
|
||||
|
||||
$this->createStatus = self::CREATE_STATUS_SUCCESS;
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns status of the URL creation after the last [[createUrl()]] call.
|
||||
*
|
||||
* @return int|null Status of the URL creation after the last [[createUrl()]] call. `null` if rule does not provide
|
||||
* info about create status.
|
||||
* @see createStatus
|
||||
* @since 2.0.12
|
||||
*/
|
||||
public function getCreateUrlStatus()
|
||||
{
|
||||
return $this->createStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of regex for matching parameter.
|
||||
* @return array parameter keys and regexp rules.
|
||||
*
|
||||
* @since 2.0.6
|
||||
*/
|
||||
protected function getParamRules()
|
||||
{
|
||||
return $this->_paramRules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over [[placeholders]] and checks whether each placeholder exists as a key in $matches array.
|
||||
* When found - replaces this placeholder key with a appropriate name of matching parameter.
|
||||
* Used in [[parseRequest()]], [[createUrl()]].
|
||||
*
|
||||
* @param array $matches result of `preg_match()` call
|
||||
* @return array input array with replaced placeholder keys
|
||||
* @see placeholders
|
||||
* @since 2.0.7
|
||||
*/
|
||||
protected function substitutePlaceholderNames(array $matches)
|
||||
{
|
||||
foreach ($this->placeholders as $placeholder => $name) {
|
||||
if (isset($matches[$placeholder])) {
|
||||
$matches[$name] = $matches[$placeholder];
|
||||
unset($matches[$placeholder]);
|
||||
}
|
||||
}
|
||||
|
||||
return $matches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim slashes in passed string. If string begins with '//', two slashes are left as is
|
||||
* in the beginning of a string.
|
||||
*
|
||||
* @param string $string
|
||||
* @return string
|
||||
*/
|
||||
private function trimSlashes($string)
|
||||
{
|
||||
if (strncmp($string, '//', 2) === 0) {
|
||||
return '//' . trim($string, '/');
|
||||
}
|
||||
|
||||
return trim($string, '/');
|
||||
}
|
||||
}
|
||||
35
vendor/yiisoft/yii2/web/UrlRuleInterface.php
vendored
Normal file
35
vendor/yiisoft/yii2/web/UrlRuleInterface.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* UrlRuleInterface is the interface that should be implemented by URL rule classes.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
interface UrlRuleInterface
|
||||
{
|
||||
/**
|
||||
* Parses the given request and returns the corresponding route and parameters.
|
||||
* @param UrlManager $manager the URL manager
|
||||
* @param Request $request the request component
|
||||
* @return array|bool the parsing result. The route and the parameters are returned as an array.
|
||||
* If false, it means this rule cannot be used to parse this path info.
|
||||
*/
|
||||
public function parseRequest($manager, $request);
|
||||
|
||||
/**
|
||||
* Creates a URL according to the given route and parameters.
|
||||
* @param UrlManager $manager the URL manager
|
||||
* @param string $route the route. It should not have slashes at the beginning or the end.
|
||||
* @param array $params the parameters
|
||||
* @return string|bool the created URL, or false if this rule cannot be used for creating this URL.
|
||||
*/
|
||||
public function createUrl($manager, $route, $params);
|
||||
}
|
||||
847
vendor/yiisoft/yii2/web/User.php
vendored
Normal file
847
vendor/yiisoft/yii2/web/User.php
vendored
Normal file
@ -0,0 +1,847 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Component;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\base\InvalidValueException;
|
||||
use yii\di\Instance;
|
||||
use yii\rbac\CheckAccessInterface;
|
||||
|
||||
/**
|
||||
* User is the class for the `user` application component that manages the user authentication status.
|
||||
*
|
||||
* You may use [[isGuest]] to determine whether the current user is a guest or not.
|
||||
* If the user is a guest, the [[identity]] property would return `null`. Otherwise, it would
|
||||
* be an instance of [[IdentityInterface]].
|
||||
*
|
||||
* You may call various methods to change the user authentication status:
|
||||
*
|
||||
* - [[login()]]: sets the specified identity and remembers the authentication status in session and cookie;
|
||||
* - [[logout()]]: marks the user as a guest and clears the relevant information from session and cookie;
|
||||
* - [[setIdentity()]]: changes the user identity without touching session or cookie
|
||||
* (this is best used in stateless RESTful API implementation).
|
||||
*
|
||||
* Note that User only maintains the user authentication status. It does NOT handle how to authenticate
|
||||
* a user. The logic of how to authenticate a user should be done in the class implementing [[IdentityInterface]].
|
||||
* You are also required to set [[identityClass]] with the name of this class.
|
||||
*
|
||||
* User is configured as an application component in [[\yii\web\Application]] by default.
|
||||
* You can access that instance via `Yii::$app->user`.
|
||||
*
|
||||
* You can modify its configuration by adding an array to your application config under `components`
|
||||
* as it is shown in the following example:
|
||||
*
|
||||
* ```
|
||||
* 'user' => [
|
||||
* 'identityClass' => 'app\models\User', // User must implement the IdentityInterface
|
||||
* 'enableAutoLogin' => true,
|
||||
* // 'loginUrl' => ['user/login'],
|
||||
* // ...
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* @property-read string|int|null $id The unique identifier for the user. If `null`, it means the user is a
|
||||
* guest.
|
||||
* @property IdentityInterface|null $identity The identity object associated with the currently logged-in
|
||||
* user. `null` is returned if the user is not logged in (not authenticated).
|
||||
* @property-read bool $isGuest Whether the current user is a guest.
|
||||
* @property string $returnUrl The URL that the user should be redirected to after login. Note that the type
|
||||
* of this property differs in getter and setter. See [[getReturnUrl()]] and [[setReturnUrl()]] for details.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
* @phpstan-template T of IdentityInterface
|
||||
* @psalm-template T of IdentityInterface
|
||||
* @phpstan-property T|null $identity
|
||||
* @psalm-property T|null $identity
|
||||
*/
|
||||
class User extends Component
|
||||
{
|
||||
public const EVENT_BEFORE_LOGIN = 'beforeLogin';
|
||||
public const EVENT_AFTER_LOGIN = 'afterLogin';
|
||||
public const EVENT_BEFORE_LOGOUT = 'beforeLogout';
|
||||
public const EVENT_AFTER_LOGOUT = 'afterLogout';
|
||||
/**
|
||||
* @var string the class name of the [[identity]] object.
|
||||
* @phpstan-var class-string<T>
|
||||
* @psalm-var class-string<T>
|
||||
*/
|
||||
public $identityClass;
|
||||
/**
|
||||
* @var bool whether to enable cookie-based login. Defaults to `false`.
|
||||
* Note that this property will be ignored if [[enableSession]] is `false`.
|
||||
*/
|
||||
public $enableAutoLogin = false;
|
||||
/**
|
||||
* @var bool whether to use session to persist authentication status across multiple requests.
|
||||
* You set this property to be `false` if your application is stateless, which is often the case
|
||||
* for RESTful APIs.
|
||||
*/
|
||||
public $enableSession = true;
|
||||
/**
|
||||
* @var string|array|null the URL for login when [[loginRequired()]] is called.
|
||||
* If an array is given, [[UrlManager::createUrl()]] will be called to create the corresponding URL.
|
||||
* The first element of the array should be the route to the login action, and the rest of
|
||||
* the name-value pairs are GET parameters used to construct the login URL. For example,
|
||||
*
|
||||
* ```
|
||||
* ['site/login', 'ref' => 1]
|
||||
* ```
|
||||
*
|
||||
* If this property is `null`, a 403 HTTP exception will be raised when [[loginRequired()]] is called.
|
||||
*/
|
||||
public $loginUrl = ['site/login'];
|
||||
/**
|
||||
* @var array the configuration of the identity cookie. This property is used only when [[enableAutoLogin]] is `true`.
|
||||
* @see Cookie
|
||||
*/
|
||||
public $identityCookie = ['name' => '_identity', 'httpOnly' => true];
|
||||
/**
|
||||
* @var int|null the number of seconds in which the user will be logged out automatically if the user
|
||||
* remains inactive. If this property is not set, the user will be logged out after
|
||||
* the current session expires (c.f. [[Session::timeout]]).
|
||||
* Note that this will not work if [[enableAutoLogin]] is `true`.
|
||||
*/
|
||||
public $authTimeout;
|
||||
/**
|
||||
* @var CheckAccessInterface|string|array|null The access checker object to use for checking access or the application
|
||||
* component ID of the access checker.
|
||||
* If not set the application auth manager will be used.
|
||||
* @since 2.0.9
|
||||
*/
|
||||
public $accessChecker;
|
||||
/**
|
||||
* @var int|null the number of seconds in which the user will be logged out automatically
|
||||
* regardless of activity.
|
||||
* Note that this will not work if [[enableAutoLogin]] is `true`.
|
||||
*/
|
||||
public $absoluteAuthTimeout;
|
||||
/**
|
||||
* @var bool whether to automatically renew the identity cookie each time a page is requested.
|
||||
* This property is effective only when [[enableAutoLogin]] is `true`.
|
||||
* When this is `false`, the identity cookie will expire after the specified duration since the user
|
||||
* is initially logged in. When this is `true`, the identity cookie will expire after the specified duration
|
||||
* since the user visits the site the last time.
|
||||
* @see enableAutoLogin
|
||||
*/
|
||||
public $autoRenewCookie = true;
|
||||
/**
|
||||
* @var string the session variable name used to store the value of [[id]].
|
||||
*/
|
||||
public $idParam = '__id';
|
||||
/**
|
||||
* @var string the session variable name used to store authentication key.
|
||||
* @since 2.0.41
|
||||
*/
|
||||
public $authKeyParam = '__authKey';
|
||||
/**
|
||||
* @var string the session variable name used to store the value of expiration timestamp of the authenticated state.
|
||||
* This is used when [[authTimeout]] is set.
|
||||
*/
|
||||
public $authTimeoutParam = '__expire';
|
||||
/**
|
||||
* @var string the session variable name used to store the value of absolute expiration timestamp of the authenticated state.
|
||||
* This is used when [[absoluteAuthTimeout]] is set.
|
||||
*/
|
||||
public $absoluteAuthTimeoutParam = '__absoluteExpire';
|
||||
/**
|
||||
* @var string the session variable name used to store the value of [[returnUrl]].
|
||||
*/
|
||||
public $returnUrlParam = '__returnUrl';
|
||||
/**
|
||||
* @var array MIME types for which this component should redirect to the [[loginUrl]].
|
||||
* @since 2.0.8
|
||||
*/
|
||||
public $acceptableRedirectTypes = ['text/html', 'application/xhtml+xml'];
|
||||
|
||||
private $_access = [];
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the application component.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
|
||||
if ($this->identityClass === null) {
|
||||
throw new InvalidConfigException('User::identityClass must be set.');
|
||||
}
|
||||
if ($this->enableAutoLogin && !isset($this->identityCookie['name'])) {
|
||||
throw new InvalidConfigException('User::identityCookie must contain the "name" element.');
|
||||
}
|
||||
if ($this->accessChecker !== null) {
|
||||
$this->accessChecker = Instance::ensure($this->accessChecker, '\yii\rbac\CheckAccessInterface');
|
||||
}
|
||||
}
|
||||
|
||||
private $_identity = false;
|
||||
|
||||
/**
|
||||
* Returns the identity object associated with the currently logged-in user.
|
||||
* When [[enableSession]] is true, this method may attempt to read the user's authentication data
|
||||
* stored in session and reconstruct the corresponding identity object, if it has not done so before.
|
||||
* @param bool $autoRenew whether to automatically renew authentication status if it has not been done so before.
|
||||
* This is only useful when [[enableSession]] is true.
|
||||
* @return IdentityInterface|null the identity object associated with the currently logged-in user.
|
||||
* `null` is returned if the user is not logged in (not authenticated).
|
||||
* @see login()
|
||||
* @see logout()
|
||||
* @phpstan-return T|null
|
||||
* @psalm-return T|null
|
||||
*/
|
||||
public function getIdentity($autoRenew = true)
|
||||
{
|
||||
if ($this->_identity === false) {
|
||||
if ($this->enableSession && $autoRenew) {
|
||||
try {
|
||||
$this->_identity = null;
|
||||
$this->renewAuthStatus();
|
||||
} catch (\Exception $e) {
|
||||
$this->_identity = false;
|
||||
throw $e;
|
||||
} catch (\Throwable $e) {
|
||||
$this->_identity = false;
|
||||
throw $e;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_identity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the user identity object.
|
||||
*
|
||||
* Note that this method does not deal with session or cookie. You should usually use [[switchIdentity()]]
|
||||
* to change the identity of the current user.
|
||||
*
|
||||
* @param IdentityInterface|null $identity the identity object associated with the currently logged user.
|
||||
* If null, it means the current user will be a guest without any associated identity.
|
||||
* @throws InvalidValueException if `$identity` object does not implement [[IdentityInterface]].
|
||||
* @phpstan-param T|null $identity
|
||||
* @psalm-param T|null $identity
|
||||
*/
|
||||
public function setIdentity($identity)
|
||||
{
|
||||
if ($identity instanceof IdentityInterface) {
|
||||
$this->_identity = $identity;
|
||||
} elseif ($identity === null) {
|
||||
$this->_identity = null;
|
||||
} else {
|
||||
throw new InvalidValueException('The identity object must implement IdentityInterface.');
|
||||
}
|
||||
$this->_access = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs in a user.
|
||||
*
|
||||
* After logging in a user:
|
||||
* - the user's identity information is obtainable from the [[identity]] property
|
||||
*
|
||||
* If [[enableSession]] is `true`:
|
||||
* - the identity information will be stored in session and be available in the next requests
|
||||
* - in case of `$duration == 0`: as long as the session remains active or till the user closes the browser
|
||||
* - in case of `$duration > 0`: as long as the session remains active or as long as the cookie
|
||||
* remains valid by it's `$duration` in seconds when [[enableAutoLogin]] is set `true`.
|
||||
*
|
||||
* If [[enableSession]] is `false`:
|
||||
* - the `$duration` parameter will be ignored
|
||||
*
|
||||
* @param IdentityInterface $identity the user identity (which should already be authenticated)
|
||||
* @param int $duration number of seconds that the user can remain in logged-in status, defaults to `0`
|
||||
* @return bool whether the user is logged in
|
||||
* @phpstan-param T $identity
|
||||
* @psalm-param T $identity
|
||||
*/
|
||||
public function login(IdentityInterface $identity, $duration = 0)
|
||||
{
|
||||
if ($this->beforeLogin($identity, false, $duration)) {
|
||||
$this->switchIdentity($identity, $duration);
|
||||
$id = $identity->getId();
|
||||
$ip = Yii::$app->getRequest()->getUserIP();
|
||||
if ($this->enableSession) {
|
||||
$log = "User '$id' logged in from $ip with duration $duration.";
|
||||
} else {
|
||||
$log = "User '$id' logged in from $ip. Session not enabled.";
|
||||
}
|
||||
|
||||
$this->regenerateCsrfToken();
|
||||
|
||||
Yii::info($log, __METHOD__);
|
||||
$this->afterLogin($identity, false, $duration);
|
||||
}
|
||||
|
||||
return !$this->getIsGuest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Regenerates CSRF token
|
||||
*
|
||||
* @since 2.0.14.2
|
||||
*/
|
||||
protected function regenerateCsrfToken()
|
||||
{
|
||||
$request = Yii::$app->getRequest();
|
||||
if ($request->enableCsrfCookie || $this->enableSession) {
|
||||
$request->getCsrfToken(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs in a user by the given access token.
|
||||
* This method will first authenticate the user by calling [[IdentityInterface::findIdentityByAccessToken()]]
|
||||
* with the provided access token. If successful, it will call [[login()]] to log in the authenticated user.
|
||||
* If authentication fails or [[login()]] is unsuccessful, it will return null.
|
||||
* @param string $token the access token
|
||||
* @param mixed $type the type of the token. The value of this parameter depends on the implementation.
|
||||
* For example, [[\yii\filters\auth\HttpBearerAuth]] will set this parameter to be `yii\filters\auth\HttpBearerAuth`.
|
||||
* @return IdentityInterface|null the identity associated with the given access token. Null is returned if
|
||||
* the access token is invalid or [[login()]] is unsuccessful.
|
||||
* @phpstan-return T|null
|
||||
* @psalm-return T|null
|
||||
*/
|
||||
public function loginByAccessToken($token, $type = null)
|
||||
{
|
||||
/**
|
||||
* @var IdentityInterface $class
|
||||
* @phpstan-var class-string<T> $class
|
||||
* @psalm-var class-string<T> $class
|
||||
*/
|
||||
$class = $this->identityClass;
|
||||
$identity = $class::findIdentityByAccessToken($token, $type);
|
||||
if ($identity && $this->login($identity)) {
|
||||
return $identity;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs in a user by cookie.
|
||||
*
|
||||
* This method attempts to log in a user using the ID and authKey information
|
||||
* provided by the [[identityCookie|identity cookie]].
|
||||
*/
|
||||
protected function loginByCookie()
|
||||
{
|
||||
$data = $this->getIdentityAndDurationFromCookie();
|
||||
if (isset($data['identity'], $data['duration'])) {
|
||||
$identity = $data['identity'];
|
||||
$duration = $data['duration'];
|
||||
if ($this->beforeLogin($identity, true, $duration)) {
|
||||
$this->switchIdentity($identity, $this->autoRenewCookie ? $duration : 0);
|
||||
$id = $identity->getId();
|
||||
$ip = Yii::$app->getRequest()->getUserIP();
|
||||
Yii::info("User '$id' logged in from $ip via cookie.", __METHOD__);
|
||||
$this->afterLogin($identity, true, $duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs out the current user.
|
||||
* This will remove authentication-related session data.
|
||||
* If `$destroySession` is true, all session data will be removed.
|
||||
* @param bool $destroySession whether to destroy the whole session. Defaults to true.
|
||||
* This parameter is ignored if [[enableSession]] is false.
|
||||
* @return bool whether the user is logged out
|
||||
*/
|
||||
public function logout($destroySession = true)
|
||||
{
|
||||
$identity = $this->getIdentity();
|
||||
if ($identity !== null && $this->beforeLogout($identity)) {
|
||||
$this->switchIdentity(null);
|
||||
$id = $identity->getId();
|
||||
$ip = Yii::$app->getRequest()->getUserIP();
|
||||
Yii::info("User '$id' logged out from $ip.", __METHOD__);
|
||||
if ($destroySession && $this->enableSession) {
|
||||
Yii::$app->getSession()->destroy();
|
||||
}
|
||||
$this->afterLogout($identity);
|
||||
}
|
||||
|
||||
return $this->getIsGuest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a value indicating whether the user is a guest (not authenticated).
|
||||
* @return bool whether the current user is a guest.
|
||||
* @see getIdentity()
|
||||
*/
|
||||
public function getIsGuest()
|
||||
{
|
||||
return $this->getIdentity() === null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a value that uniquely represents the user.
|
||||
* @return string|int|null the unique identifier for the user. If `null`, it means the user is a guest.
|
||||
* @see getIdentity()
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
$identity = $this->getIdentity();
|
||||
|
||||
return $identity !== null ? $identity->getId() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL that the browser should be redirected to after successful login.
|
||||
*
|
||||
* This method reads the return URL from the session. It is usually used by the login action which
|
||||
* may call this method to redirect the browser to where it goes after successful authentication.
|
||||
*
|
||||
* @param string|array|null $defaultUrl the default return URL in case it was not set previously.
|
||||
* If this is null and the return URL was not set previously, [[Application::homeUrl]] will be redirected to.
|
||||
* Please refer to [[setReturnUrl()]] on accepted format of the URL.
|
||||
* @return string the URL that the user should be redirected to after login.
|
||||
* @see loginRequired()
|
||||
*/
|
||||
public function getReturnUrl($defaultUrl = null)
|
||||
{
|
||||
$url = Yii::$app->getSession()->get($this->returnUrlParam, $defaultUrl);
|
||||
if (is_array($url)) {
|
||||
if (isset($url[0])) {
|
||||
return Yii::$app->getUrlManager()->createUrl($url);
|
||||
}
|
||||
|
||||
$url = null;
|
||||
}
|
||||
|
||||
return $url === null ? Yii::$app->getHomeUrl() : $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remembers the URL in the session so that it can be retrieved back later by [[getReturnUrl()]].
|
||||
* @param string|array $url the URL that the user should be redirected to after login.
|
||||
* If an array is given, [[UrlManager::createUrl()]] will be called to create the corresponding URL.
|
||||
* The first element of the array should be the route, and the rest of
|
||||
* the name-value pairs are GET parameters used to construct the URL. For example,
|
||||
*
|
||||
* ```
|
||||
* ['admin/index', 'ref' => 1]
|
||||
* ```
|
||||
*/
|
||||
public function setReturnUrl($url)
|
||||
{
|
||||
Yii::$app->getSession()->set($this->returnUrlParam, $url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects the user browser to the login page.
|
||||
*
|
||||
* Before the redirection, the current URL (if it's not an AJAX url) will be kept as [[returnUrl]] so that
|
||||
* the user browser may be redirected back to the current page after successful login.
|
||||
*
|
||||
* Make sure you set [[loginUrl]] so that the user browser can be redirected to the specified login URL after
|
||||
* calling this method.
|
||||
*
|
||||
* Note that when [[loginUrl]] is set, calling this method will NOT terminate the application execution.
|
||||
*
|
||||
* @param bool $checkAjax whether to check if the request is an AJAX request. When this is true and the request
|
||||
* is an AJAX request, the current URL (for AJAX request) will NOT be set as the return URL.
|
||||
* @param bool $checkAcceptHeader whether to check if the request accepts HTML responses. Defaults to `true`. When this is true and
|
||||
* the request does not accept HTML responses the current URL will not be SET as the return URL. Also instead of
|
||||
* redirecting the user an ForbiddenHttpException is thrown. This parameter is available since version 2.0.8.
|
||||
* @return Response the redirection response if [[loginUrl]] is set
|
||||
* @throws ForbiddenHttpException the "Access Denied" HTTP exception if [[loginUrl]] is not set or a redirect is
|
||||
* not applicable.
|
||||
*/
|
||||
public function loginRequired($checkAjax = true, $checkAcceptHeader = true)
|
||||
{
|
||||
$request = Yii::$app->getRequest();
|
||||
$canRedirect = !$checkAcceptHeader || $this->checkRedirectAcceptable();
|
||||
if (
|
||||
$this->enableSession
|
||||
&& $request->getIsGet()
|
||||
&& (!$checkAjax || !$request->getIsAjax())
|
||||
&& $canRedirect
|
||||
) {
|
||||
$this->setReturnUrl($request->getAbsoluteUrl());
|
||||
}
|
||||
if ($this->loginUrl !== null && $canRedirect) {
|
||||
$loginUrl = (array) $this->loginUrl;
|
||||
if ($loginUrl[0] !== Yii::$app->requestedRoute) {
|
||||
return Yii::$app->getResponse()->redirect($this->loginUrl);
|
||||
}
|
||||
}
|
||||
throw new ForbiddenHttpException(Yii::t('yii', 'Login Required'));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called before logging in a user.
|
||||
* The default implementation will trigger the [[EVENT_BEFORE_LOGIN]] event.
|
||||
* If you override this method, make sure you call the parent implementation
|
||||
* so that the event is triggered.
|
||||
* @param IdentityInterface $identity the user identity information
|
||||
* @param bool $cookieBased whether the login is cookie-based
|
||||
* @param int $duration number of seconds that the user can remain in logged-in status.
|
||||
* If 0, it means login till the user closes the browser or the session is manually destroyed.
|
||||
* @return bool whether the user should continue to be logged in
|
||||
* @phpstan-param T $identity
|
||||
* @psalm-param T $identity
|
||||
*/
|
||||
protected function beforeLogin($identity, $cookieBased, $duration)
|
||||
{
|
||||
$event = new UserEvent([
|
||||
'identity' => $identity,
|
||||
'cookieBased' => $cookieBased,
|
||||
'duration' => $duration,
|
||||
]);
|
||||
$this->trigger(self::EVENT_BEFORE_LOGIN, $event);
|
||||
|
||||
return $event->isValid;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called after the user is successfully logged in.
|
||||
* The default implementation will trigger the [[EVENT_AFTER_LOGIN]] event.
|
||||
* If you override this method, make sure you call the parent implementation
|
||||
* so that the event is triggered.
|
||||
* @param IdentityInterface $identity the user identity information
|
||||
* @param bool $cookieBased whether the login is cookie-based
|
||||
* @param int $duration number of seconds that the user can remain in logged-in status.
|
||||
* If 0, it means login till the user closes the browser or the session is manually destroyed.
|
||||
* @phpstan-param T $identity
|
||||
* @psalm-param T $identity
|
||||
*/
|
||||
protected function afterLogin($identity, $cookieBased, $duration)
|
||||
{
|
||||
$this->trigger(self::EVENT_AFTER_LOGIN, new UserEvent([
|
||||
'identity' => $identity,
|
||||
'cookieBased' => $cookieBased,
|
||||
'duration' => $duration,
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is invoked when calling [[logout()]] to log out a user.
|
||||
* The default implementation will trigger the [[EVENT_BEFORE_LOGOUT]] event.
|
||||
* If you override this method, make sure you call the parent implementation
|
||||
* so that the event is triggered.
|
||||
* @param IdentityInterface $identity the user identity information
|
||||
* @return bool whether the user should continue to be logged out
|
||||
* @phpstan-param T $identity
|
||||
* @psalm-param T $identity
|
||||
*/
|
||||
protected function beforeLogout($identity)
|
||||
{
|
||||
$event = new UserEvent([
|
||||
'identity' => $identity,
|
||||
]);
|
||||
$this->trigger(self::EVENT_BEFORE_LOGOUT, $event);
|
||||
|
||||
return $event->isValid;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is invoked right after a user is logged out via [[logout()]].
|
||||
* The default implementation will trigger the [[EVENT_AFTER_LOGOUT]] event.
|
||||
* If you override this method, make sure you call the parent implementation
|
||||
* so that the event is triggered.
|
||||
* @param IdentityInterface $identity the user identity information
|
||||
* @phpstan-param T $identity
|
||||
* @psalm-param T $identity
|
||||
*/
|
||||
protected function afterLogout($identity)
|
||||
{
|
||||
$this->trigger(self::EVENT_AFTER_LOGOUT, new UserEvent([
|
||||
'identity' => $identity,
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Renews the identity cookie.
|
||||
* This method will set the expiration time of the identity cookie to be the current time
|
||||
* plus the originally specified cookie duration.
|
||||
*/
|
||||
protected function renewIdentityCookie()
|
||||
{
|
||||
$name = $this->identityCookie['name'];
|
||||
$value = Yii::$app->getRequest()->getCookies()->getValue($name);
|
||||
if ($value !== null) {
|
||||
$data = json_decode($value, true);
|
||||
if (is_array($data) && isset($data[2])) {
|
||||
$cookie = Yii::createObject(array_merge($this->identityCookie, [
|
||||
'class' => 'yii\web\Cookie',
|
||||
'value' => $value,
|
||||
'expire' => time() + (int) $data[2],
|
||||
]));
|
||||
Yii::$app->getResponse()->getCookies()->add($cookie);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an identity cookie.
|
||||
* This method is used when [[enableAutoLogin]] is true.
|
||||
* It saves [[id]], [[IdentityInterface::getAuthKey()|auth key]], and the duration of cookie-based login
|
||||
* information in the cookie.
|
||||
* @param IdentityInterface $identity
|
||||
* @param int $duration number of seconds that the user can remain in logged-in status.
|
||||
* @see loginByCookie()
|
||||
* @phpstan-param T $identity
|
||||
* @psalm-param T $identity
|
||||
*/
|
||||
protected function sendIdentityCookie($identity, $duration)
|
||||
{
|
||||
$cookie = Yii::createObject(array_merge($this->identityCookie, [
|
||||
'class' => 'yii\web\Cookie',
|
||||
'value' => json_encode([
|
||||
$identity->getId(),
|
||||
$identity->getAuthKey(),
|
||||
$duration,
|
||||
], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE),
|
||||
'expire' => time() + $duration,
|
||||
]));
|
||||
Yii::$app->getResponse()->getCookies()->add($cookie);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if an identity cookie has a valid format and contains a valid auth key.
|
||||
* This method is used when [[enableAutoLogin]] is true.
|
||||
* This method attempts to authenticate a user using the information in the identity cookie.
|
||||
* @return array|null Returns an array of 'identity' and 'duration' if valid, otherwise null.
|
||||
* @see loginByCookie()
|
||||
* @since 2.0.9
|
||||
*/
|
||||
protected function getIdentityAndDurationFromCookie()
|
||||
{
|
||||
$value = Yii::$app->getRequest()->getCookies()->getValue($this->identityCookie['name']);
|
||||
if ($value === null) {
|
||||
return null;
|
||||
}
|
||||
$data = json_decode($value, true);
|
||||
if (is_array($data) && count($data) == 3) {
|
||||
list($id, $authKey, $duration) = $data;
|
||||
/**
|
||||
* @var IdentityInterface
|
||||
* @phpstan-var class-string<IdentityInterface>
|
||||
*/
|
||||
$class = $this->identityClass;
|
||||
$identity = $class::findIdentity($id);
|
||||
if ($identity !== null) {
|
||||
if (!$identity instanceof IdentityInterface) {
|
||||
throw new InvalidValueException("$class::findIdentity() must return an object implementing IdentityInterface.");
|
||||
} elseif (!$identity->validateAuthKey($authKey)) {
|
||||
$ip = Yii::$app->getRequest()->getUserIP();
|
||||
Yii::warning("Invalid cookie auth key attempted for user '$id' from $ip: $authKey", __METHOD__);
|
||||
} else {
|
||||
return ['identity' => $identity, 'duration' => $duration];
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->removeIdentityCookie();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the identity cookie.
|
||||
* This method is used when [[enableAutoLogin]] is true.
|
||||
* @since 2.0.9
|
||||
*/
|
||||
protected function removeIdentityCookie()
|
||||
{
|
||||
Yii::$app->getResponse()->getCookies()->remove(Yii::createObject(array_merge($this->identityCookie, [
|
||||
'class' => 'yii\web\Cookie',
|
||||
])));
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches to a new identity for the current user.
|
||||
*
|
||||
* When [[enableSession]] is true, this method may use session and/or cookie to store the user identity information,
|
||||
* according to the value of `$duration`. Please refer to [[login()]] for more details.
|
||||
*
|
||||
* This method is mainly called by [[login()]], [[logout()]] and [[loginByCookie()]]
|
||||
* when the current user needs to be associated with the corresponding identity information.
|
||||
*
|
||||
* @param IdentityInterface|null $identity the identity information to be associated with the current user.
|
||||
* If null, it means switching the current user to be a guest.
|
||||
* @param int $duration number of seconds that the user can remain in logged-in status.
|
||||
* This parameter is used only when `$identity` is not null.
|
||||
* @phpstan-param T|null $identity
|
||||
* @psalm-param T|null $identity
|
||||
*/
|
||||
public function switchIdentity($identity, $duration = 0)
|
||||
{
|
||||
$this->setIdentity($identity);
|
||||
|
||||
if (!$this->enableSession) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ensure any existing identity cookies are removed. */
|
||||
if ($this->enableAutoLogin && ($this->autoRenewCookie || $identity === null)) {
|
||||
$this->removeIdentityCookie();
|
||||
}
|
||||
|
||||
$session = Yii::$app->getSession();
|
||||
$session->regenerateID(true);
|
||||
$session->remove($this->idParam);
|
||||
$session->remove($this->authTimeoutParam);
|
||||
$session->remove($this->authKeyParam);
|
||||
|
||||
if ($identity) {
|
||||
$session->set($this->idParam, $identity->getId());
|
||||
$session->set($this->authKeyParam, $identity->getAuthKey());
|
||||
if ($this->authTimeout !== null) {
|
||||
$session->set($this->authTimeoutParam, time() + $this->authTimeout);
|
||||
}
|
||||
if ($this->absoluteAuthTimeout !== null) {
|
||||
$session->set($this->absoluteAuthTimeoutParam, time() + $this->absoluteAuthTimeout);
|
||||
}
|
||||
if ($this->enableAutoLogin && $duration > 0) {
|
||||
$this->sendIdentityCookie($identity, $duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the authentication status using the information from session and cookie.
|
||||
*
|
||||
* This method will try to determine the user identity using the [[idParam]] session variable.
|
||||
*
|
||||
* If [[authTimeout]] is set, this method will refresh the timer.
|
||||
*
|
||||
* If the user identity cannot be determined by session, this method will try to [[loginByCookie()|login by cookie]]
|
||||
* if [[enableAutoLogin]] is true.
|
||||
*/
|
||||
protected function renewAuthStatus()
|
||||
{
|
||||
$session = Yii::$app->getSession();
|
||||
$id = $session->getHasSessionId() || $session->getIsActive() ? $session->get($this->idParam) : null;
|
||||
|
||||
if ($id === null) {
|
||||
$identity = null;
|
||||
} else {
|
||||
/** @var IdentityInterface $class */
|
||||
$class = $this->identityClass;
|
||||
$identity = $class::findIdentity($id);
|
||||
if ($identity === null) {
|
||||
$this->switchIdentity(null);
|
||||
}
|
||||
}
|
||||
|
||||
if ($identity !== null) {
|
||||
$authKey = $session->get($this->authKeyParam);
|
||||
if ($authKey !== null && !$identity->validateAuthKey($authKey)) {
|
||||
$identity = null;
|
||||
$ip = Yii::$app->getRequest()->getUserIP();
|
||||
Yii::warning("Invalid session auth key attempted for user '$id' from $ip: $authKey", __METHOD__);
|
||||
}
|
||||
}
|
||||
|
||||
$this->setIdentity($identity);
|
||||
|
||||
if ($identity !== null && ($this->authTimeout !== null || $this->absoluteAuthTimeout !== null)) {
|
||||
$expire = $this->authTimeout !== null ? $session->get($this->authTimeoutParam) : null;
|
||||
$expireAbsolute = $this->absoluteAuthTimeout !== null ? $session->get($this->absoluteAuthTimeoutParam) : null;
|
||||
if ($expire !== null && $expire < time() || $expireAbsolute !== null && $expireAbsolute < time()) {
|
||||
$this->logout(false);
|
||||
} elseif ($this->authTimeout !== null) {
|
||||
$session->set($this->authTimeoutParam, time() + $this->authTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->enableAutoLogin) {
|
||||
if ($this->getIsGuest()) {
|
||||
$this->loginByCookie();
|
||||
} elseif ($this->autoRenewCookie) {
|
||||
$this->renewIdentityCookie();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the user can perform the operation as specified by the given permission.
|
||||
*
|
||||
* Note that you must configure "authManager" application component in order to use this method.
|
||||
* Otherwise it will always return false.
|
||||
*
|
||||
* @param string $permissionName the name of the permission (e.g. "edit post") that needs access check.
|
||||
* @param array $params name-value pairs that would be passed to the rules associated
|
||||
* with the roles and permissions assigned to the user.
|
||||
* @param bool $allowCaching whether to allow caching the result of access check.
|
||||
* When this parameter is true (default), if the access check of an operation was performed
|
||||
* before, its result will be directly returned when calling this method to check the same
|
||||
* operation. If this parameter is false, this method will always call
|
||||
* [[\yii\rbac\CheckAccessInterface::checkAccess()]] to obtain the up-to-date access result. Note that this
|
||||
* caching is effective only within the same request and only works when `$params = []`.
|
||||
* @return bool whether the user can perform the operation as specified by the given permission.
|
||||
*/
|
||||
public function can($permissionName, $params = [], $allowCaching = true)
|
||||
{
|
||||
if ($allowCaching && empty($params) && isset($this->_access[$permissionName])) {
|
||||
return $this->_access[$permissionName];
|
||||
}
|
||||
if (($accessChecker = $this->getAccessChecker()) === null) {
|
||||
return false;
|
||||
}
|
||||
$access = $accessChecker->checkAccess($this->getId(), $permissionName, $params);
|
||||
if ($allowCaching && empty($params)) {
|
||||
$this->_access[$permissionName] = $access;
|
||||
}
|
||||
|
||||
return $access;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the `Accept` header contains a content type that allows redirection to the login page.
|
||||
* The login page is assumed to serve `text/html` or `application/xhtml+xml` by default. You can change acceptable
|
||||
* content types by modifying [[acceptableRedirectTypes]] property.
|
||||
* @return bool whether this request may be redirected to the login page.
|
||||
* @see acceptableRedirectTypes
|
||||
* @since 2.0.8
|
||||
*/
|
||||
public function checkRedirectAcceptable()
|
||||
{
|
||||
$acceptableTypes = Yii::$app->getRequest()->getAcceptableContentTypes();
|
||||
if (empty($acceptableTypes) || (count($acceptableTypes) === 1 && array_keys($acceptableTypes)[0] === '*/*')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($acceptableTypes as $type => $params) {
|
||||
if (in_array($type, $this->acceptableRedirectTypes, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns auth manager associated with the user component.
|
||||
*
|
||||
* By default this is the `authManager` application component.
|
||||
* You may override this method to return a different auth manager instance if needed.
|
||||
* @return \yii\rbac\ManagerInterface
|
||||
* @since 2.0.6
|
||||
* @deprecated since version 2.0.9, to be removed in 2.1. Use [[getAccessChecker()]] instead.
|
||||
*/
|
||||
protected function getAuthManager()
|
||||
{
|
||||
return Yii::$app->getAuthManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the access checker used for checking access.
|
||||
* @return CheckAccessInterface
|
||||
* @since 2.0.9
|
||||
*/
|
||||
protected function getAccessChecker()
|
||||
{
|
||||
return $this->accessChecker !== null ? $this->accessChecker : $this->getAuthManager();
|
||||
}
|
||||
}
|
||||
40
vendor/yiisoft/yii2/web/UserEvent.php
vendored
Normal file
40
vendor/yiisoft/yii2/web/UserEvent.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use yii\base\Event;
|
||||
|
||||
/**
|
||||
* This event class is used for Events triggered by the [[User]] class.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class UserEvent extends Event
|
||||
{
|
||||
/**
|
||||
* @var IdentityInterface the identity object associated with this event
|
||||
*/
|
||||
public $identity;
|
||||
/**
|
||||
* @var bool whether the login is cookie-based. This property is only meaningful
|
||||
* for [[User::EVENT_BEFORE_LOGIN]] and [[User::EVENT_AFTER_LOGIN]] events.
|
||||
*/
|
||||
public $cookieBased;
|
||||
/**
|
||||
* @var int number of seconds that the user can remain in logged-in status.
|
||||
* If 0, it means login till the user closes the browser or the session is manually destroyed.
|
||||
*/
|
||||
public $duration;
|
||||
/**
|
||||
* @var bool whether the login or logout should proceed.
|
||||
* Event handlers may modify this property to determine whether the login or logout should proceed.
|
||||
* This property is only meaningful for [[User::EVENT_BEFORE_LOGIN]] and [[User::EVENT_BEFORE_LOGOUT]] events.
|
||||
*/
|
||||
public $isValid = true;
|
||||
}
|
||||
727
vendor/yiisoft/yii2/web/View.php
vendored
Normal file
727
vendor/yiisoft/yii2/web/View.php
vendored
Normal file
@ -0,0 +1,727 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use Yii;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\helpers\ArrayHelper;
|
||||
use yii\helpers\Html;
|
||||
use yii\helpers\Url;
|
||||
|
||||
/**
|
||||
* View represents a view object in the MVC pattern.
|
||||
*
|
||||
* View provides a set of methods (e.g. [[render()]]) for rendering purpose.
|
||||
*
|
||||
* View is configured as an application component in [[\yii\base\Application]] by default.
|
||||
* You can access that instance via `Yii::$app->view`.
|
||||
*
|
||||
* You can modify its configuration by adding an array to your application config under `components`
|
||||
* as it is shown in the following example:
|
||||
*
|
||||
* ```
|
||||
* 'view' => [
|
||||
* 'theme' => 'app\themes\MyTheme',
|
||||
* 'renderers' => [
|
||||
* // you may add Smarty or Twig renderer here
|
||||
* ]
|
||||
* // ...
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* For more details and usage information on View, see the [guide article on views](guide:structure-views).
|
||||
*
|
||||
* @property \yii\web\AssetManager $assetManager The asset manager. Defaults to the "assetManager" application
|
||||
* component.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*
|
||||
* @phpstan-type RegisterJsFileOptions array{
|
||||
* depends?: class-string[],
|
||||
* position?: int,
|
||||
* appendTimestamp?: bool,
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* @psalm-type RegisterJsFileOptions = array{
|
||||
* depends?: class-string[],
|
||||
* position?: int,
|
||||
* appendTimestamp?: bool,
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* @phpstan-type RegisterCssFileOptions array{
|
||||
* depends?: class-string[],
|
||||
* appendTimestamp?: bool,
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* @psalm-type RegisterCssFileOptions = array{
|
||||
* depends?: class-string[],
|
||||
* appendTimestamp?: bool,
|
||||
* ...
|
||||
* }
|
||||
*/
|
||||
class View extends \yii\base\View
|
||||
{
|
||||
/**
|
||||
* @event Event an event that is triggered by [[beginBody()]].
|
||||
*/
|
||||
public const EVENT_BEGIN_BODY = 'beginBody';
|
||||
/**
|
||||
* @event Event an event that is triggered by [[endBody()]].
|
||||
*/
|
||||
public const EVENT_END_BODY = 'endBody';
|
||||
/**
|
||||
* The location of registered JavaScript code block or files.
|
||||
* This means the location is in the head section.
|
||||
*/
|
||||
public const POS_HEAD = 1;
|
||||
/**
|
||||
* The location of registered JavaScript code block or files.
|
||||
* This means the location is at the beginning of the body section.
|
||||
*/
|
||||
public const POS_BEGIN = 2;
|
||||
/**
|
||||
* The location of registered JavaScript code block or files.
|
||||
* This means the location is at the end of the body section.
|
||||
*/
|
||||
public const POS_END = 3;
|
||||
/**
|
||||
* The location of registered JavaScript code block.
|
||||
* This means the JavaScript code block will be enclosed within `jQuery(document).ready()`.
|
||||
*/
|
||||
public const POS_READY = 4;
|
||||
/**
|
||||
* The location of registered JavaScript code block.
|
||||
* This means the JavaScript code block will be enclosed within `jQuery(window).load()`.
|
||||
*/
|
||||
public const POS_LOAD = 5;
|
||||
/**
|
||||
* This is internally used as the placeholder for receiving the content registered for the head section.
|
||||
*/
|
||||
public const PH_HEAD = '<![CDATA[YII-BLOCK-HEAD]]>';
|
||||
/**
|
||||
* This is internally used as the placeholder for receiving the content registered for the beginning of the body section.
|
||||
*/
|
||||
public const PH_BODY_BEGIN = '<![CDATA[YII-BLOCK-BODY-BEGIN]]>';
|
||||
/**
|
||||
* This is internally used as the placeholder for receiving the content registered for the end of the body section.
|
||||
*/
|
||||
public const PH_BODY_END = '<![CDATA[YII-BLOCK-BODY-END]]>';
|
||||
/**
|
||||
* @var AssetBundle[] list of the registered asset bundles. The keys are the bundle names, and the values
|
||||
* are the registered [[AssetBundle]] objects.
|
||||
* @see registerAssetBundle()
|
||||
*/
|
||||
public $assetBundles = [];
|
||||
/**
|
||||
* @var string the page title
|
||||
*/
|
||||
public $title;
|
||||
/**
|
||||
* @var array the registered meta tags.
|
||||
* @see registerMetaTag()
|
||||
*/
|
||||
public $metaTags = [];
|
||||
/**
|
||||
* @var array the registered link tags.
|
||||
* @see registerLinkTag()
|
||||
*/
|
||||
public $linkTags = [];
|
||||
/**
|
||||
* @var array the registered CSS code blocks.
|
||||
* @see registerCss()
|
||||
*/
|
||||
public $css = [];
|
||||
/**
|
||||
* @var array the registered CSS files.
|
||||
* @see registerCssFile()
|
||||
*/
|
||||
public $cssFiles = [];
|
||||
/**
|
||||
* @since 2.0.53
|
||||
* @var array the style tag options.
|
||||
*/
|
||||
public $styleOptions = [];
|
||||
/**
|
||||
* @var array the registered JS code blocks
|
||||
* @see registerJs()
|
||||
*/
|
||||
public $js = [];
|
||||
/**
|
||||
* @var array the registered JS files.
|
||||
* @see registerJsFile()
|
||||
*/
|
||||
public $jsFiles = [];
|
||||
/**
|
||||
* @since 2.0.50
|
||||
* @var array the script tag options.
|
||||
*/
|
||||
public $scriptOptions = [];
|
||||
|
||||
private $_assetManager;
|
||||
|
||||
|
||||
/**
|
||||
* Whether [[endPage()]] has been called and all files have been registered
|
||||
* @var bool
|
||||
* @since 2.0.44
|
||||
*/
|
||||
protected $isPageEnded = false;
|
||||
|
||||
/**
|
||||
* Marks the position of an HTML head section.
|
||||
*/
|
||||
public function head()
|
||||
{
|
||||
echo self::PH_HEAD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the beginning of an HTML body section.
|
||||
*/
|
||||
public function beginBody()
|
||||
{
|
||||
echo self::PH_BODY_BEGIN;
|
||||
$this->trigger(self::EVENT_BEGIN_BODY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the ending of an HTML body section.
|
||||
*/
|
||||
public function endBody()
|
||||
{
|
||||
$this->trigger(self::EVENT_END_BODY);
|
||||
echo self::PH_BODY_END;
|
||||
|
||||
foreach (array_keys($this->assetBundles) as $bundle) {
|
||||
$this->registerAssetFiles($bundle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the ending of an HTML page.
|
||||
* @param bool $ajaxMode whether the view is rendering in AJAX mode.
|
||||
* If true, the JS scripts registered at [[POS_READY]] and [[POS_LOAD]] positions
|
||||
* will be rendered at the end of the view like normal scripts.
|
||||
*/
|
||||
public function endPage($ajaxMode = false)
|
||||
{
|
||||
$this->trigger(self::EVENT_END_PAGE);
|
||||
|
||||
$this->isPageEnded = true;
|
||||
|
||||
$content = ob_get_clean();
|
||||
|
||||
echo strtr($content, [
|
||||
self::PH_HEAD => $this->renderHeadHtml(),
|
||||
self::PH_BODY_BEGIN => $this->renderBodyBeginHtml(),
|
||||
self::PH_BODY_END => $this->renderBodyEndHtml($ajaxMode),
|
||||
]);
|
||||
|
||||
$this->clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a view in response to an AJAX request.
|
||||
*
|
||||
* This method is similar to [[render()]] except that it will surround the view being rendered
|
||||
* with the calls of [[beginPage()]], [[head()]], [[beginBody()]], [[endBody()]] and [[endPage()]].
|
||||
* By doing so, the method is able to inject into the rendering result with JS/CSS scripts and files
|
||||
* that are registered with the view.
|
||||
*
|
||||
* @param string $view the view name. Please refer to [[render()]] on how to specify this parameter.
|
||||
* @param array $params the parameters (name-value pairs) that will be extracted and made available in the view file.
|
||||
* @param object|null $context the context that the view should use for rendering the view. If null,
|
||||
* existing [[context]] will be used.
|
||||
* @return string the rendering result
|
||||
* @see render()
|
||||
*/
|
||||
public function renderAjax($view, $params = [], $context = null)
|
||||
{
|
||||
$viewFile = $this->findViewFile($view, $context);
|
||||
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
|
||||
$this->beginPage();
|
||||
$this->head();
|
||||
$this->beginBody();
|
||||
echo $this->renderFile($viewFile, $params, $context);
|
||||
$this->endBody();
|
||||
$this->endPage(true);
|
||||
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the asset manager being used by this view object.
|
||||
* @return \yii\web\AssetManager the asset manager. Defaults to the "assetManager" application component.
|
||||
*/
|
||||
public function getAssetManager()
|
||||
{
|
||||
return $this->_assetManager ?: Yii::$app->getAssetManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the asset manager.
|
||||
* @param \yii\web\AssetManager $value the asset manager
|
||||
*/
|
||||
public function setAssetManager($value)
|
||||
{
|
||||
$this->_assetManager = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears up the registered meta tags, link tags, css/js scripts and files.
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->metaTags = [];
|
||||
$this->linkTags = [];
|
||||
$this->css = [];
|
||||
$this->cssFiles = [];
|
||||
$this->js = [];
|
||||
$this->jsFiles = [];
|
||||
$this->assetBundles = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all files provided by an asset bundle including depending bundles files.
|
||||
* Removes a bundle from [[assetBundles]] once files are registered.
|
||||
* @param string $name name of the bundle to register
|
||||
*/
|
||||
protected function registerAssetFiles($name)
|
||||
{
|
||||
if (!isset($this->assetBundles[$name])) {
|
||||
return;
|
||||
}
|
||||
$bundle = $this->assetBundles[$name];
|
||||
if ($bundle) {
|
||||
foreach ($bundle->depends as $dep) {
|
||||
$this->registerAssetFiles($dep);
|
||||
}
|
||||
$bundle->registerAssetFiles($this);
|
||||
}
|
||||
unset($this->assetBundles[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the named asset bundle.
|
||||
* All dependent asset bundles will be registered.
|
||||
* @param string $name the class name of the asset bundle (without the leading backslash)
|
||||
* @param int|null $position if set, this forces a minimum position for javascript files.
|
||||
* This will adjust depending assets javascript file position or fail if requirement can not be met.
|
||||
* If this is null, asset bundles position settings will not be changed.
|
||||
* See [[registerJsFile]] for more details on javascript position.
|
||||
* @return AssetBundle the registered asset bundle instance
|
||||
* @throws InvalidConfigException if the asset bundle does not exist or a circular dependency is detected
|
||||
*/
|
||||
public function registerAssetBundle($name, $position = null)
|
||||
{
|
||||
if (!isset($this->assetBundles[$name])) {
|
||||
$am = $this->getAssetManager();
|
||||
$bundle = $am->getBundle($name);
|
||||
$this->assetBundles[$name] = false;
|
||||
// register dependencies
|
||||
$pos = isset($bundle->jsOptions['position']) ? $bundle->jsOptions['position'] : null;
|
||||
foreach ($bundle->depends as $dep) {
|
||||
$this->registerAssetBundle($dep, $pos);
|
||||
}
|
||||
$this->assetBundles[$name] = $bundle;
|
||||
} elseif ($this->assetBundles[$name] === false) {
|
||||
throw new InvalidConfigException("A circular dependency is detected for bundle '$name'.");
|
||||
} else {
|
||||
$bundle = $this->assetBundles[$name];
|
||||
}
|
||||
|
||||
if ($position !== null) {
|
||||
$pos = isset($bundle->jsOptions['position']) ? $bundle->jsOptions['position'] : null;
|
||||
if ($pos === null) {
|
||||
$bundle->jsOptions['position'] = $pos = $position;
|
||||
} elseif ($pos > $position) {
|
||||
throw new InvalidConfigException("An asset bundle that depends on '$name' has a higher javascript file position configured than '$name'.");
|
||||
}
|
||||
// update position for all dependencies
|
||||
foreach ($bundle->depends as $dep) {
|
||||
$this->registerAssetBundle($dep, $pos);
|
||||
}
|
||||
}
|
||||
|
||||
return $bundle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a meta tag.
|
||||
*
|
||||
* For example, a description meta tag can be added like the following:
|
||||
*
|
||||
* ```
|
||||
* $view->registerMetaTag([
|
||||
* 'name' => 'description',
|
||||
* 'content' => 'This website is about funny raccoons.'
|
||||
* ]);
|
||||
* ```
|
||||
*
|
||||
* will result in the meta tag `<meta name="description" content="This website is about funny raccoons.">`.
|
||||
*
|
||||
* @param array $options the HTML attributes for the meta tag.
|
||||
* @param string|null $key the key that identifies the meta tag. If two meta tags are registered
|
||||
* with the same key, the latter will overwrite the former. If this is null, the new meta tag
|
||||
* will be appended to the existing ones.
|
||||
*/
|
||||
public function registerMetaTag($options, $key = null)
|
||||
{
|
||||
if ($key === null) {
|
||||
$this->metaTags[] = Html::tag('meta', '', $options);
|
||||
} else {
|
||||
$this->metaTags[$key] = Html::tag('meta', '', $options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers CSRF meta tags.
|
||||
* They are rendered dynamically to retrieve a new CSRF token for each request.
|
||||
*
|
||||
* ```
|
||||
* $view->registerCsrfMetaTags();
|
||||
* ```
|
||||
*
|
||||
* The above code will result in `<meta name="csrf-param" content="[yii\web\Request::$csrfParam]">`
|
||||
* and `<meta name="csrf-token" content="tTNpWKpdy-bx8ZmIq9R72...K1y8IP3XGkzZA==">` added to the page.
|
||||
*
|
||||
* Note: Hidden CSRF input of ActiveForm will be automatically refreshed by calling `window.yii.refreshCsrfToken()`
|
||||
* from `yii.js`.
|
||||
*
|
||||
* @since 2.0.13
|
||||
*/
|
||||
public function registerCsrfMetaTags()
|
||||
{
|
||||
$this->metaTags['csrf_meta_tags'] = $this->renderDynamic('return yii\helpers\Html::csrfMetaTags();');
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a link tag.
|
||||
*
|
||||
* For example, a link tag for a custom [favicon](https://www.w3.org/2005/10/howto-favicon)
|
||||
* can be added like the following:
|
||||
*
|
||||
* ```
|
||||
* $view->registerLinkTag(['rel' => 'icon', 'type' => 'image/png', 'href' => '/myicon.png']);
|
||||
* ```
|
||||
*
|
||||
* which will result in the following HTML: `<link rel="icon" type="image/png" href="/myicon.png">`.
|
||||
*
|
||||
* **Note:** To register link tags for CSS stylesheets, use [[registerCssFile()]] instead, which
|
||||
* has more options for this kind of link tag.
|
||||
*
|
||||
* @param array $options the HTML attributes for the link tag.
|
||||
* @param string|null $key the key that identifies the link tag. If two link tags are registered
|
||||
* with the same key, the latter will overwrite the former. If this is null, the new link tag
|
||||
* will be appended to the existing ones.
|
||||
*/
|
||||
public function registerLinkTag($options, $key = null)
|
||||
{
|
||||
if ($key === null) {
|
||||
$this->linkTags[] = Html::tag('link', '', $options);
|
||||
} else {
|
||||
$this->linkTags[$key] = Html::tag('link', '', $options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a CSS code block.
|
||||
* @param string $css the content of the CSS code block to be registered
|
||||
* @param array $options the HTML attributes for the `<style>`-tag.
|
||||
* @param string|null $key the key that identifies the CSS code block. If null, it will use
|
||||
* $css as the key. If two CSS code blocks are registered with the same key, the latter
|
||||
* will overwrite the former.
|
||||
*/
|
||||
public function registerCss($css, $options = [], $key = null)
|
||||
{
|
||||
$key = $key ?: md5($css);
|
||||
$this->css[$key] = Html::style($css, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a CSS file.
|
||||
*
|
||||
* This method should be used for simple registration of CSS files. If you want to use features of
|
||||
* [[AssetManager]] like appending timestamps to the URL and file publishing options, use [[AssetBundle]]
|
||||
* and [[registerAssetBundle()]] instead.
|
||||
*
|
||||
* @param string $url the CSS file to be registered.
|
||||
* @param array $options the HTML attributes for the link tag. Please refer to [[Html::cssFile()]] for
|
||||
* the supported options. The following options are specially handled and are not treated as HTML attributes:
|
||||
*
|
||||
* - `depends`: array, specifies the names of the asset bundles that this CSS file depends on.
|
||||
* - `appendTimestamp`: bool whether to append a timestamp to the URL.
|
||||
*
|
||||
* @param string|null $key the key that identifies the CSS script file. If null, it will use
|
||||
* $url as the key. If two CSS files are registered with the same key, the latter
|
||||
* will overwrite the former.
|
||||
* @throws InvalidConfigException
|
||||
*
|
||||
* @phpstan-param RegisterCssFileOptions $options
|
||||
* @psalm-param RegisterCssFileOptions $options
|
||||
*/
|
||||
public function registerCssFile($url, $options = [], $key = null)
|
||||
{
|
||||
$this->registerFile('css', $url, $options, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a JS code block.
|
||||
* @param string $js the JS code block to be registered
|
||||
* @param int $position the position at which the JS script tag should be inserted
|
||||
* in a page. The possible values are:
|
||||
*
|
||||
* - [[POS_HEAD]]: in the head section
|
||||
* - [[POS_BEGIN]]: at the beginning of the body section
|
||||
* - [[POS_END]]: at the end of the body section
|
||||
* - [[POS_LOAD]]: enclosed within jQuery(window).load().
|
||||
* Note that by using this position, the method will automatically register the jQuery js file.
|
||||
* - [[POS_READY]]: enclosed within jQuery(document).ready(). This is the default value.
|
||||
* Note that by using this position, the method will automatically register the jQuery js file.
|
||||
*
|
||||
* @param string|null $key the key that identifies the JS code block. If null, it will use
|
||||
* $js as the key. If two JS code blocks are registered with the same key, the latter
|
||||
* will overwrite the former.
|
||||
*/
|
||||
public function registerJs($js, $position = self::POS_READY, $key = null)
|
||||
{
|
||||
$key = $key ?: md5($js);
|
||||
$this->js[$position][$key] = $js;
|
||||
if ($position === self::POS_READY || $position === self::POS_LOAD) {
|
||||
JqueryAsset::register($this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a JS or CSS file.
|
||||
*
|
||||
* @param string $url the JS file to be registered.
|
||||
* @param string $type type (js or css) of the file.
|
||||
* @param array $options the HTML attributes for the script tag. The following options are specially handled
|
||||
* and are not treated as HTML attributes:
|
||||
*
|
||||
* - `depends`: array, specifies the names of the asset bundles that this CSS file depends on.
|
||||
* - `appendTimestamp`: bool whether to append a timestamp to the URL.
|
||||
*
|
||||
* @param string|null $key the key that identifies the JS script file. If null, it will use
|
||||
* $url as the key. If two JS files are registered with the same key at the same position, the latter
|
||||
* will overwrite the former. Note that position option takes precedence, thus files registered with the same key,
|
||||
* but different position option will not override each other.
|
||||
* @throws InvalidConfigException
|
||||
*/
|
||||
private function registerFile($type, $url, $options = [], $key = null)
|
||||
{
|
||||
$url = Yii::getAlias($url);
|
||||
$key = $key ?: $url;
|
||||
$depends = ArrayHelper::remove($options, 'depends', []);
|
||||
$originalOptions = $options;
|
||||
$position = ArrayHelper::remove($options, 'position', self::POS_END);
|
||||
|
||||
try {
|
||||
$assetManagerAppendTimestamp = $this->getAssetManager()->appendTimestamp;
|
||||
} catch (InvalidConfigException $e) {
|
||||
$depends = null; // the AssetManager is not available
|
||||
$assetManagerAppendTimestamp = false;
|
||||
}
|
||||
$appendTimestamp = ArrayHelper::remove($options, 'appendTimestamp', $assetManagerAppendTimestamp);
|
||||
|
||||
if ($this->isPageEnded) {
|
||||
Yii::warning('You\'re trying to register a file after View::endPage() has been called.');
|
||||
}
|
||||
|
||||
if (empty($depends)) {
|
||||
// register directly without AssetManager
|
||||
if ($appendTimestamp && Url::isRelative($url)) {
|
||||
$prefix = Yii::getAlias('@web');
|
||||
$prefixLength = strlen($prefix);
|
||||
$trimmedUrl = ltrim((substr($url, 0, $prefixLength) === $prefix) ? substr($url, $prefixLength) : $url, '/');
|
||||
$timestamp = @filemtime(Yii::getAlias('@webroot/' . $trimmedUrl, false));
|
||||
if ($timestamp > 0) {
|
||||
$url = $timestamp ? "$url?v=$timestamp" : $url;
|
||||
}
|
||||
}
|
||||
if ($type === 'js') {
|
||||
$this->jsFiles[$position][$key] = Html::jsFile($url, $options);
|
||||
} else {
|
||||
$this->cssFiles[$key] = Html::cssFile($url, $options);
|
||||
}
|
||||
} else {
|
||||
$this->getAssetManager()->bundles[$key] = Yii::createObject([
|
||||
'class' => AssetBundle::className(),
|
||||
'baseUrl' => '',
|
||||
'basePath' => '@webroot',
|
||||
(string)$type => [ArrayHelper::merge([!Url::isRelative($url) ? $url : ltrim($url, '/')], $originalOptions)],
|
||||
"{$type}Options" => $options,
|
||||
'depends' => (array)$depends,
|
||||
]);
|
||||
$this->registerAssetBundle($key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a JS file.
|
||||
*
|
||||
* This method should be used for simple registration of JS files. If you want to use features of
|
||||
* [[AssetManager]] like appending timestamps to the URL and file publishing options, use [[AssetBundle]]
|
||||
* and [[registerAssetBundle()]] instead.
|
||||
*
|
||||
* @param string $url the JS file to be registered.
|
||||
* @param array $options the HTML attributes for the script tag. The following options are specially handled
|
||||
* and are not treated as HTML attributes:
|
||||
*
|
||||
* - `depends`: array, specifies the names of the asset bundles that this JS file depends on.
|
||||
* - `position`: specifies where the JS script tag should be inserted in a page. The possible values are:
|
||||
* * [[POS_HEAD]]: in the head section
|
||||
* * [[POS_BEGIN]]: at the beginning of the body section
|
||||
* * [[POS_END]]: at the end of the body section. This is the default value.
|
||||
* - `appendTimestamp`: bool whether to append a timestamp to the URL.
|
||||
*
|
||||
* Please refer to [[Html::jsFile()]] for other supported options.
|
||||
*
|
||||
* @param string|null $key the key that identifies the JS script file. If null, it will use
|
||||
* $url as the key. If two JS files are registered with the same key at the same position, the latter
|
||||
* will overwrite the former. Note that position option takes precedence, thus files registered with the same key,
|
||||
* but different position option will not override each other.
|
||||
* @throws InvalidConfigException
|
||||
*
|
||||
* @phpstan-param RegisterJsFileOptions $options
|
||||
* @psalm-param RegisterJsFileOptions $options
|
||||
*/
|
||||
public function registerJsFile($url, $options = [], $key = null)
|
||||
{
|
||||
$this->registerFile('js', $url, $options, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a JS code block defining a variable. The name of variable will be
|
||||
* used as key, preventing duplicated variable names.
|
||||
*
|
||||
* @param string $name Name of the variable
|
||||
* @param array|string $value Value of the variable
|
||||
* @param int $position the position in a page at which the JavaScript variable should be inserted.
|
||||
* The possible values are:
|
||||
*
|
||||
* - [[POS_HEAD]]: in the head section. This is the default value.
|
||||
* - [[POS_BEGIN]]: at the beginning of the body section.
|
||||
* - [[POS_END]]: at the end of the body section.
|
||||
* - [[POS_LOAD]]: enclosed within jQuery(window).load().
|
||||
* Note that by using this position, the method will automatically register the jQuery js file.
|
||||
* - [[POS_READY]]: enclosed within jQuery(document).ready().
|
||||
* Note that by using this position, the method will automatically register the jQuery js file.
|
||||
*
|
||||
* @since 2.0.14
|
||||
*/
|
||||
public function registerJsVar($name, $value, $position = self::POS_HEAD)
|
||||
{
|
||||
$js = sprintf('var %s = %s;', $name, \yii\helpers\Json::htmlEncode($value));
|
||||
$this->registerJs($js, $position, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the content to be inserted in the head section.
|
||||
* The content is rendered using the registered meta tags, link tags, CSS/JS code blocks and files.
|
||||
* @return string the rendered content
|
||||
*/
|
||||
protected function renderHeadHtml()
|
||||
{
|
||||
$lines = [];
|
||||
if (!empty($this->metaTags)) {
|
||||
$lines[] = implode("\n", $this->metaTags);
|
||||
}
|
||||
|
||||
if (!empty($this->linkTags)) {
|
||||
$lines[] = implode("\n", $this->linkTags);
|
||||
}
|
||||
if (!empty($this->cssFiles)) {
|
||||
$lines[] = implode("\n", $this->cssFiles);
|
||||
}
|
||||
if (!empty($this->css)) {
|
||||
$lines[] = implode("\n", $this->css);
|
||||
}
|
||||
if (!empty($this->jsFiles[self::POS_HEAD])) {
|
||||
$lines[] = implode("\n", $this->jsFiles[self::POS_HEAD]);
|
||||
}
|
||||
if (!empty($this->js[self::POS_HEAD])) {
|
||||
$lines[] = Html::script(implode("\n", $this->js[self::POS_HEAD]));
|
||||
}
|
||||
|
||||
return empty($lines) ? '' : implode("\n", $lines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the content to be inserted at the beginning of the body section.
|
||||
* The content is rendered using the registered JS code blocks and files.
|
||||
* @return string the rendered content
|
||||
*/
|
||||
protected function renderBodyBeginHtml()
|
||||
{
|
||||
$lines = [];
|
||||
if (!empty($this->jsFiles[self::POS_BEGIN])) {
|
||||
$lines[] = implode("\n", $this->jsFiles[self::POS_BEGIN]);
|
||||
}
|
||||
if (!empty($this->js[self::POS_BEGIN])) {
|
||||
$lines[] = Html::script(implode("\n", $this->js[self::POS_BEGIN]));
|
||||
}
|
||||
|
||||
return empty($lines) ? '' : implode("\n", $lines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the content to be inserted at the end of the body section.
|
||||
* The content is rendered using the registered JS code blocks and files.
|
||||
* @param bool $ajaxMode whether the view is rendering in AJAX mode.
|
||||
* If true, the JS scripts registered at [[POS_READY]] and [[POS_LOAD]] positions
|
||||
* will be rendered at the end of the view like normal scripts.
|
||||
* @return string the rendered content
|
||||
*/
|
||||
protected function renderBodyEndHtml($ajaxMode)
|
||||
{
|
||||
$lines = [];
|
||||
|
||||
if (!empty($this->jsFiles[self::POS_END])) {
|
||||
$lines[] = implode("\n", $this->jsFiles[self::POS_END]);
|
||||
}
|
||||
|
||||
if ($ajaxMode) {
|
||||
$scripts = [];
|
||||
if (!empty($this->js[self::POS_END])) {
|
||||
$scripts[] = implode("\n", $this->js[self::POS_END]);
|
||||
}
|
||||
if (!empty($this->js[self::POS_READY])) {
|
||||
$scripts[] = implode("\n", $this->js[self::POS_READY]);
|
||||
}
|
||||
if (!empty($this->js[self::POS_LOAD])) {
|
||||
$scripts[] = implode("\n", $this->js[self::POS_LOAD]);
|
||||
}
|
||||
if (!empty($scripts)) {
|
||||
$lines[] = Html::script(implode("\n", $scripts));
|
||||
}
|
||||
} else {
|
||||
if (!empty($this->js[self::POS_END])) {
|
||||
$lines[] = Html::script(implode("\n", $this->js[self::POS_END]));
|
||||
}
|
||||
if (!empty($this->js[self::POS_READY])) {
|
||||
$js = "jQuery(function ($) {\n" . implode("\n", $this->js[self::POS_READY]) . "\n});";
|
||||
$lines[] = Html::script($js);
|
||||
}
|
||||
if (!empty($this->js[self::POS_LOAD])) {
|
||||
$js = "jQuery(window).on('load', function () {\n" . implode("\n", $this->js[self::POS_LOAD]) . "\n});";
|
||||
$lines[] = Html::script($js);
|
||||
}
|
||||
}
|
||||
|
||||
return empty($lines) ? '' : implode("\n", $lines);
|
||||
}
|
||||
}
|
||||
134
vendor/yiisoft/yii2/web/ViewAction.php
vendored
Normal file
134
vendor/yiisoft/yii2/web/ViewAction.php
vendored
Normal file
@ -0,0 +1,134 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Action;
|
||||
use yii\base\ViewNotFoundException;
|
||||
|
||||
/**
|
||||
* ViewAction represents an action that displays a view according to a user-specified parameter.
|
||||
*
|
||||
* By default, the view being displayed is specified via the `view` GET parameter.
|
||||
* The name of the GET parameter can be customized via [[viewParam]].
|
||||
*
|
||||
* Users specify a view in the format of `path/to/view`, which translates to the view name
|
||||
* `ViewPrefix/path/to/view` where `ViewPrefix` is given by [[viewPrefix]]. The view will then
|
||||
* be rendered by the [[\yii\base\Controller::render()|render()]] method of the currently active controller.
|
||||
*
|
||||
* Note that the user-specified view name must start with a word character and can only contain
|
||||
* word characters, forward slashes, dots and dashes.
|
||||
*
|
||||
* @author Alexander Makarov <sam@rmcreative.ru>
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*
|
||||
* @template T of Controller
|
||||
* @extends Action<T>
|
||||
*/
|
||||
class ViewAction extends Action
|
||||
{
|
||||
/**
|
||||
* @var string the name of the GET parameter that contains the requested view name.
|
||||
*/
|
||||
public $viewParam = 'view';
|
||||
/**
|
||||
* @var string the name of the default view when [[\yii\web\ViewAction::$viewParam]] GET parameter is not provided
|
||||
* by user. Defaults to 'index'. This should be in the format of 'path/to/view', similar to that given in the
|
||||
* GET parameter.
|
||||
* @see \yii\web\ViewAction::$viewPrefix
|
||||
*/
|
||||
public $defaultView = 'index';
|
||||
/**
|
||||
* @var string a string to be prefixed to the user-specified view name to form a complete view name.
|
||||
* For example, if a user requests for `tutorial/chap1`, the corresponding view name will
|
||||
* be `pages/tutorial/chap1`, assuming the prefix is `pages`.
|
||||
* The actual view file is determined by [[\yii\base\View::findViewFile()]].
|
||||
* @see \yii\base\View::findViewFile()
|
||||
*/
|
||||
public $viewPrefix = 'pages';
|
||||
/**
|
||||
* @var mixed the name of the layout to be applied to the requested view.
|
||||
* This will be assigned to [[\yii\base\Controller::$layout]] before the view is rendered.
|
||||
* Defaults to null, meaning the controller's layout will be used.
|
||||
* If false, no layout will be applied.
|
||||
*/
|
||||
public $layout;
|
||||
|
||||
|
||||
/**
|
||||
* Runs the action.
|
||||
* This method displays the view requested by the user.
|
||||
* @throws NotFoundHttpException if the view file cannot be found
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$viewName = $this->resolveViewName();
|
||||
$this->controller->actionParams[$this->viewParam] = Yii::$app->request->get($this->viewParam);
|
||||
|
||||
$controllerLayout = null;
|
||||
if ($this->layout !== null) {
|
||||
$controllerLayout = $this->controller->layout;
|
||||
$this->controller->layout = $this->layout;
|
||||
}
|
||||
|
||||
try {
|
||||
$output = $this->render($viewName);
|
||||
|
||||
if ($controllerLayout) {
|
||||
$this->controller->layout = $controllerLayout;
|
||||
}
|
||||
} catch (ViewNotFoundException $e) {
|
||||
if ($controllerLayout) {
|
||||
$this->controller->layout = $controllerLayout;
|
||||
}
|
||||
|
||||
if (YII_DEBUG) {
|
||||
throw new NotFoundHttpException($e->getMessage());
|
||||
}
|
||||
|
||||
throw new NotFoundHttpException(
|
||||
Yii::t('yii', 'The requested view "{name}" was not found.', ['name' => $viewName])
|
||||
);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a view.
|
||||
*
|
||||
* @param string $viewName view name
|
||||
* @return string result of the rendering
|
||||
*/
|
||||
protected function render($viewName)
|
||||
{
|
||||
return $this->controller->render($viewName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the view name currently being requested.
|
||||
*
|
||||
* @return string the resolved view name
|
||||
* @throws NotFoundHttpException if the specified view name is invalid
|
||||
*/
|
||||
protected function resolveViewName()
|
||||
{
|
||||
$viewName = Yii::$app->request->get($this->viewParam, $this->defaultView);
|
||||
|
||||
if (!is_string($viewName) || !preg_match('~^\w(?:(?!\/\.{0,2}\/)[\w\/\-\.])*$~', $viewName)) {
|
||||
if (YII_DEBUG) {
|
||||
throw new NotFoundHttpException("The requested view \"$viewName\" must start with a word character, must not contain /../ or /./, can contain only word characters, forward slashes, dots and dashes.");
|
||||
}
|
||||
|
||||
throw new NotFoundHttpException(Yii::t('yii', 'The requested view "{name}" was not found.', ['name' => $viewName]));
|
||||
}
|
||||
|
||||
return empty($this->viewPrefix) ? $viewName : $this->viewPrefix . '/' . $viewName;
|
||||
}
|
||||
}
|
||||
209
vendor/yiisoft/yii2/web/XmlResponseFormatter.php
vendored
Normal file
209
vendor/yiisoft/yii2/web/XmlResponseFormatter.php
vendored
Normal file
@ -0,0 +1,209 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use DOMDocument;
|
||||
use DOMElement;
|
||||
use DOMException;
|
||||
use yii\base\Arrayable;
|
||||
use yii\base\Component;
|
||||
use yii\helpers\StringHelper;
|
||||
|
||||
/**
|
||||
* XmlResponseFormatter formats the given data into an XML response content.
|
||||
*
|
||||
* It is used by [[Response]] to format response data.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class XmlResponseFormatter extends Component implements ResponseFormatterInterface
|
||||
{
|
||||
/**
|
||||
* @var string the Content-Type header for the response
|
||||
*/
|
||||
public $contentType = 'application/xml';
|
||||
/**
|
||||
* @var string the XML version
|
||||
*/
|
||||
public $version = '1.0';
|
||||
/**
|
||||
* @var string|null the XML encoding. If not set, it will use the value of [[Response::charset]].
|
||||
*/
|
||||
public $encoding;
|
||||
/**
|
||||
* @var string|string[]|null|false the name of the root element. If set to false, null or is empty then no root tag
|
||||
* should be added.
|
||||
*
|
||||
* Since 2.0.44 URI namespace could be specified by passing `[namespace, tag name]` array.
|
||||
*/
|
||||
public $rootTag = 'response';
|
||||
/**
|
||||
* @var string the name of the elements that represent the array elements with numeric keys.
|
||||
*/
|
||||
public $itemTag = 'item';
|
||||
/**
|
||||
* @var bool whether to interpret objects implementing the [[\Traversable]] interface as arrays.
|
||||
* Defaults to `true`.
|
||||
* @since 2.0.7
|
||||
*/
|
||||
public $useTraversableAsArray = true;
|
||||
/**
|
||||
* @var bool if object class names should be used as tag names
|
||||
* @since 2.0.11
|
||||
*/
|
||||
public $useObjectTags = true;
|
||||
/**
|
||||
* @var bool if true, converts object tags to lowercase, `$useObjectTags` must be enabled
|
||||
* @since 2.0.43
|
||||
*/
|
||||
public $objectTagToLowercase = false;
|
||||
|
||||
/**
|
||||
* @var DOMDocument the XML document, serves as the root of the document tree
|
||||
* @since 2.0.43
|
||||
*/
|
||||
protected $dom;
|
||||
|
||||
|
||||
/**
|
||||
* Formats the specified response.
|
||||
*
|
||||
* @param Response $response the response to be formatted.
|
||||
*/
|
||||
public function format($response)
|
||||
{
|
||||
$charset = $this->encoding === null ? $response->charset : $this->encoding;
|
||||
if (stripos($this->contentType, 'charset') === false) {
|
||||
$this->contentType .= '; charset=' . $charset;
|
||||
}
|
||||
$response->getHeaders()->set('Content-Type', $this->contentType);
|
||||
if ($response->data !== null) {
|
||||
$this->dom = new DOMDocument($this->version, $charset);
|
||||
if (!empty($this->rootTag)) {
|
||||
if (is_array($this->rootTag)) {
|
||||
$root = $this->dom->createElementNS($this->rootTag[0], $this->rootTag[1]);
|
||||
} else {
|
||||
$root = $this->dom->createElement($this->rootTag);
|
||||
}
|
||||
$this->dom->appendChild($root);
|
||||
$this->buildXml($root, $response->data);
|
||||
} else {
|
||||
$this->buildXml($this->dom, $response->data);
|
||||
}
|
||||
$response->content = $this->dom->saveXML();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively adds data to XML document.
|
||||
*
|
||||
* @param DOMElement|DOMDocument $element current element
|
||||
* @param mixed $data content of the current element
|
||||
*/
|
||||
protected function buildXml($element, $data)
|
||||
{
|
||||
if (
|
||||
is_array($data) ||
|
||||
($data instanceof \Traversable && $this->useTraversableAsArray && !$data instanceof Arrayable)
|
||||
) {
|
||||
foreach ($data as $name => $value) {
|
||||
if (is_int($name) && is_object($value)) {
|
||||
$this->buildXml($element, $value);
|
||||
} elseif (is_array($value) || is_object($value)) {
|
||||
$child = $this->dom->createElement($this->getValidXmlElementName($name));
|
||||
$element->appendChild($child);
|
||||
$this->buildXml($child, $value);
|
||||
} else {
|
||||
$child = $this->dom->createElement($this->getValidXmlElementName($name));
|
||||
$child->appendChild($this->dom->createTextNode($this->formatScalarValue($value)));
|
||||
$element->appendChild($child);
|
||||
}
|
||||
}
|
||||
} elseif (is_object($data)) {
|
||||
if ($this->useObjectTags) {
|
||||
$name = StringHelper::basename(get_class($data));
|
||||
if ($this->objectTagToLowercase) {
|
||||
$name = strtolower($name);
|
||||
}
|
||||
$child = $this->dom->createElement($name);
|
||||
$element->appendChild($child);
|
||||
} else {
|
||||
$child = $element;
|
||||
}
|
||||
if ($data instanceof Arrayable) {
|
||||
$this->buildXml($child, $data->toArray());
|
||||
} else {
|
||||
$array = [];
|
||||
foreach ($data as $name => $value) {
|
||||
$array[$name] = $value;
|
||||
}
|
||||
$this->buildXml($child, $array);
|
||||
}
|
||||
} else {
|
||||
$element->appendChild($this->dom->createTextNode($this->formatScalarValue($data)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats scalar value to use in XML text node.
|
||||
*
|
||||
* @param int|string|bool|float $value a scalar value.
|
||||
* @return string string representation of the value.
|
||||
* @since 2.0.11
|
||||
*/
|
||||
protected function formatScalarValue($value)
|
||||
{
|
||||
if ($value === true) {
|
||||
return 'true';
|
||||
}
|
||||
if ($value === false) {
|
||||
return 'false';
|
||||
}
|
||||
if (is_float($value)) {
|
||||
return StringHelper::floatToString($value);
|
||||
}
|
||||
return (string) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns element name ready to be used in DOMElement if
|
||||
* name is not empty, is not int and is valid.
|
||||
*
|
||||
* Falls back to [[itemTag]] otherwise.
|
||||
*
|
||||
* @param mixed $name the original name
|
||||
* @return string
|
||||
* @since 2.0.12
|
||||
*/
|
||||
protected function getValidXmlElementName($name)
|
||||
{
|
||||
if (empty($name) || is_int($name) || !$this->isValidXmlName($name)) {
|
||||
return $this->itemTag;
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if name is valid to be used in XML.
|
||||
*
|
||||
* @param mixed $name the name to test
|
||||
* @return bool
|
||||
* @see https://stackoverflow.com/questions/2519845/how-to-check-if-string-is-a-valid-xml-element-name/2519943#2519943
|
||||
* @since 2.0.12
|
||||
*/
|
||||
protected function isValidXmlName($name)
|
||||
{
|
||||
try {
|
||||
return $this->dom->createElement($name) !== false;
|
||||
} catch (DOMException $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
vendor/yiisoft/yii2/web/YiiAsset.php
vendored
Normal file
25
vendor/yiisoft/yii2/web/YiiAsset.php
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
/**
|
||||
* This asset bundle provides the base JavaScript files for the Yii Framework.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class YiiAsset extends AssetBundle
|
||||
{
|
||||
public $sourcePath = '@yii/assets';
|
||||
public $js = [
|
||||
'yii.js',
|
||||
];
|
||||
public $depends = [
|
||||
'yii\web\JqueryAsset',
|
||||
];
|
||||
}
|
||||
54
vendor/yiisoft/yii2/web/migrations/m160313_153426_session_init.php
vendored
Normal file
54
vendor/yiisoft/yii2/web/migrations/m160313_153426_session_init.php
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
use yii\db\Migration;
|
||||
|
||||
/**
|
||||
* Initializes Session tables.
|
||||
*
|
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com>
|
||||
* @since 2.0.8
|
||||
*/
|
||||
class m160313_153426_session_init extends Migration
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
$dataType = $this->binary();
|
||||
$tableOptions = null;
|
||||
|
||||
switch ($this->db->driverName) {
|
||||
case 'mysql':
|
||||
// https://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci
|
||||
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
|
||||
break;
|
||||
case 'sqlsrv':
|
||||
case 'mssql':
|
||||
case 'dblib':
|
||||
$dataType = $this->text();
|
||||
break;
|
||||
}
|
||||
|
||||
$this->createTable('{{%session}}', [
|
||||
'id' => $this->string()->notNull(),
|
||||
'expire' => $this->integer(),
|
||||
'data' => $dataType,
|
||||
'PRIMARY KEY ([[id]])',
|
||||
], $tableOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
$this->dropTable('{{%session}}');
|
||||
}
|
||||
}
|
||||
21
vendor/yiisoft/yii2/web/migrations/schema-mssql.sql
vendored
Normal file
21
vendor/yiisoft/yii2/web/migrations/schema-mssql.sql
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Database schema required by \yii\web\DbSession.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com>
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
* @since 2.0.8
|
||||
*/
|
||||
|
||||
if object_id('[session]', 'U') is not null
|
||||
drop table [session];
|
||||
|
||||
create table [session]
|
||||
(
|
||||
[id] varchar(256) not null,
|
||||
[expire] integer,
|
||||
[data] nvarchar(max),
|
||||
primary key ([id])
|
||||
);
|
||||
20
vendor/yiisoft/yii2/web/migrations/schema-mysql.sql
vendored
Normal file
20
vendor/yiisoft/yii2/web/migrations/schema-mysql.sql
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Database schema required by \yii\web\DbSession.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com>
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
* @since 2.0.8
|
||||
*/
|
||||
|
||||
drop table if exists `session`;
|
||||
|
||||
create table `session`
|
||||
(
|
||||
`id` varchar(256) not null,
|
||||
`expire` integer,
|
||||
`data` LONGBLOB,
|
||||
primary key (`id`)
|
||||
) engine InnoDB;
|
||||
20
vendor/yiisoft/yii2/web/migrations/schema-oci.sql
vendored
Normal file
20
vendor/yiisoft/yii2/web/migrations/schema-oci.sql
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Database schema required by \yii\web\DbSession.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com>
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
* @since 2.0.8
|
||||
*/
|
||||
|
||||
drop table if exists "session";
|
||||
|
||||
create table "session"
|
||||
(
|
||||
"id" varchar(256) not null,
|
||||
"expire" integer,
|
||||
"data" BYTEA,
|
||||
primary key ("id")
|
||||
);
|
||||
20
vendor/yiisoft/yii2/web/migrations/schema-pgsql.sql
vendored
Normal file
20
vendor/yiisoft/yii2/web/migrations/schema-pgsql.sql
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Database schema required by \yii\web\DbSession.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com>
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
* @since 2.0.8
|
||||
*/
|
||||
|
||||
drop table if exists "session";
|
||||
|
||||
create table "session"
|
||||
(
|
||||
"id" varchar(256) not null,
|
||||
"expire" integer,
|
||||
"data" bytea,
|
||||
primary key ("id")
|
||||
);
|
||||
20
vendor/yiisoft/yii2/web/migrations/schema-sqlite.sql
vendored
Normal file
20
vendor/yiisoft/yii2/web/migrations/schema-sqlite.sql
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Database schema required by \yii\web\DbSession.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com>
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
* @since 2.0.8
|
||||
*/
|
||||
|
||||
drop table if exists "session";
|
||||
|
||||
create table "session"
|
||||
(
|
||||
"id" varchar(256) not null,
|
||||
"expire" integer,
|
||||
"data" BLOB,
|
||||
primary key ("id")
|
||||
);
|
||||
Reference in New Issue
Block a user