init
This commit is contained in:
940
vendor/yiisoft/yii2/widgets/ActiveField.php
vendored
Normal file
940
vendor/yiisoft/yii2/widgets/ActiveField.php
vendored
Normal file
@@ -0,0 +1,940 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\widgets;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Component;
|
||||
use yii\base\ErrorHandler;
|
||||
use yii\base\Model;
|
||||
use yii\helpers\ArrayHelper;
|
||||
use yii\helpers\Html;
|
||||
use yii\web\JsExpression;
|
||||
|
||||
/**
|
||||
* ActiveField represents a form input field within an [[ActiveForm]].
|
||||
*
|
||||
* For more details and usage information on ActiveField, see the [guide article on forms](guide:input-forms).
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class ActiveField extends Component
|
||||
{
|
||||
/**
|
||||
* @var ActiveForm the form that this field is associated with.
|
||||
*/
|
||||
public $form;
|
||||
/**
|
||||
* @var Model the data model that this field is associated with.
|
||||
*/
|
||||
public $model;
|
||||
/**
|
||||
* @var string the model attribute that this field is associated with.
|
||||
*/
|
||||
public $attribute;
|
||||
/**
|
||||
* @var array the HTML attributes (name-value pairs) for the field container tag.
|
||||
* The values will be HTML-encoded using [[Html::encode()]].
|
||||
* If a value is `null`, the corresponding attribute will not be rendered.
|
||||
* The following special options are recognized:
|
||||
*
|
||||
* - `tag`: the tag name of the container element. Defaults to `div`. Setting it to `false` will not render a container tag.
|
||||
* See also [[\yii\helpers\Html::tag()]].
|
||||
*
|
||||
* If you set a custom `id` for the container element, you may need to adjust the [[$selectors]] accordingly.
|
||||
*
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
*/
|
||||
public $options = ['class' => 'form-group'];
|
||||
/**
|
||||
* @var string the template that is used to arrange the label, the input field, the error message and the hint text.
|
||||
* The following tokens will be replaced when [[render()]] is called: `{label}`, `{input}`, `{error}` and `{hint}`.
|
||||
*/
|
||||
public $template = "{label}\n{input}\n{hint}\n{error}";
|
||||
/**
|
||||
* @var array the default options for the input tags. The parameter passed to individual input methods
|
||||
* (e.g. [[textInput()]]) will be merged with this property when rendering the input tag.
|
||||
*
|
||||
* If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
|
||||
*
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
*/
|
||||
public $inputOptions = ['class' => 'form-control'];
|
||||
/**
|
||||
* @var array the default options for the error tags. The parameter passed to [[error()]] will be
|
||||
* merged with this property when rendering the error tag.
|
||||
* The following special options are recognized:
|
||||
*
|
||||
* - `tag`: the tag name of the container element. Defaults to `div`. Setting it to `false` will not render a container tag.
|
||||
* See also [[\yii\helpers\Html::tag()]].
|
||||
* - `encode`: whether to encode the error output. Defaults to `true`.
|
||||
*
|
||||
* If you set a custom `id` for the error element, you may need to adjust the [[$selectors]] accordingly.
|
||||
*
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
*/
|
||||
public $errorOptions = ['class' => 'help-block'];
|
||||
/**
|
||||
* @var array the default options for the label tags. The parameter passed to [[label()]] will be
|
||||
* merged with this property when rendering the label tag.
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
*/
|
||||
public $labelOptions = ['class' => 'control-label'];
|
||||
/**
|
||||
* @var array the default options for the hint tags. The parameter passed to [[hint()]] will be
|
||||
* merged with this property when rendering the hint tag.
|
||||
* The following special options are recognized:
|
||||
*
|
||||
* - `tag`: the tag name of the container element. Defaults to `div`. Setting it to `false` will not render a container tag.
|
||||
* See also [[\yii\helpers\Html::tag()]].
|
||||
*
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
*/
|
||||
public $hintOptions = ['class' => 'hint-block'];
|
||||
/**
|
||||
* @var bool whether to enable client-side data validation.
|
||||
* If not set, it will take the value of [[ActiveForm::enableClientValidation]].
|
||||
*/
|
||||
public $enableClientValidation;
|
||||
/**
|
||||
* @var bool whether to enable AJAX-based data validation.
|
||||
* If not set, it will take the value of [[ActiveForm::enableAjaxValidation]].
|
||||
*/
|
||||
public $enableAjaxValidation;
|
||||
/**
|
||||
* @var bool whether to perform validation when the value of the input field is changed.
|
||||
* If not set, it will take the value of [[ActiveForm::validateOnChange]].
|
||||
*/
|
||||
public $validateOnChange;
|
||||
/**
|
||||
* @var bool whether to perform validation when the input field loses focus.
|
||||
* If not set, it will take the value of [[ActiveForm::validateOnBlur]].
|
||||
*/
|
||||
public $validateOnBlur;
|
||||
/**
|
||||
* @var bool whether to perform validation while the user is typing in the input field.
|
||||
* If not set, it will take the value of [[ActiveForm::validateOnType]].
|
||||
* @see validationDelay
|
||||
*/
|
||||
public $validateOnType;
|
||||
/**
|
||||
* @var int number of milliseconds that the validation should be delayed when the user types in the field
|
||||
* and [[validateOnType]] is set `true`.
|
||||
* If not set, it will take the value of [[ActiveForm::validationDelay]].
|
||||
*/
|
||||
public $validationDelay;
|
||||
/**
|
||||
* @var array the jQuery selectors for selecting the container, input and error tags.
|
||||
* The array keys should be `container`, `input`, and/or `error`, and the array values
|
||||
* are the corresponding selectors. For example, `['input' => '#my-input']`.
|
||||
*
|
||||
* The container selector is used under the context of the form, while the input and the error
|
||||
* selectors are used under the context of the container.
|
||||
*
|
||||
* You normally do not need to set this property as the default selectors should work well for most cases.
|
||||
*/
|
||||
public $selectors = [];
|
||||
/**
|
||||
* @var array different parts of the field (e.g. input, label). This will be used together with
|
||||
* [[template]] to generate the final field HTML code. The keys are the token names in [[template]],
|
||||
* while the values are the corresponding HTML code. Valid tokens include `{input}`, `{label}` and `{error}`.
|
||||
* Note that you normally don't need to access this property directly as
|
||||
* it is maintained by various methods of this class.
|
||||
*/
|
||||
public $parts = [];
|
||||
/**
|
||||
* @var bool adds aria HTML attributes `aria-required` and `aria-invalid` for inputs
|
||||
* @since 2.0.11
|
||||
*/
|
||||
public $addAriaAttributes = true;
|
||||
|
||||
/**
|
||||
* @var string this property holds a custom input id if it was set using [[inputOptions]] or in one of the
|
||||
* `$options` parameters of the `input*` methods.
|
||||
*/
|
||||
private $_inputId;
|
||||
/**
|
||||
* @var bool if "for" field label attribute should be skipped.
|
||||
*/
|
||||
private $_skipLabelFor = false;
|
||||
|
||||
|
||||
/**
|
||||
* PHP magic method that returns the string representation of this object.
|
||||
* @return string the string representation of this object.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
// __toString cannot throw exception
|
||||
// use trigger_error to bypass this limitation
|
||||
try {
|
||||
return $this->render();
|
||||
} catch (\Exception $e) {
|
||||
ErrorHandler::convertExceptionToError($e);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the whole field.
|
||||
* This method will generate the label, error tag, input tag and hint tag (if any), and
|
||||
* assemble them into HTML according to [[template]].
|
||||
* @param string|callable $content the content within the field container.
|
||||
* If `null` (not set), the default methods will be called to generate the label, error tag and input tag,
|
||||
* and use them as the content.
|
||||
* If a callable, it will be called to generate the content. The signature of the callable should be:
|
||||
*
|
||||
* ```php
|
||||
* function ($field) {
|
||||
* return $html;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @return string the rendering result.
|
||||
*/
|
||||
public function render($content = null)
|
||||
{
|
||||
if ($content === null) {
|
||||
if (!isset($this->parts['{input}'])) {
|
||||
$this->textInput();
|
||||
}
|
||||
if (!isset($this->parts['{label}'])) {
|
||||
$this->label();
|
||||
}
|
||||
if (!isset($this->parts['{error}'])) {
|
||||
$this->error();
|
||||
}
|
||||
if (!isset($this->parts['{hint}'])) {
|
||||
$this->hint(null);
|
||||
}
|
||||
$content = strtr($this->template, $this->parts);
|
||||
} elseif (!is_string($content)) {
|
||||
$content = call_user_func($content, $this);
|
||||
}
|
||||
|
||||
return $this->begin() . "\n" . $content . "\n" . $this->end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the opening tag of the field container.
|
||||
* @return string the rendering result.
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
if ($this->form->enableClientScript) {
|
||||
$clientOptions = $this->getClientOptions();
|
||||
if (!empty($clientOptions)) {
|
||||
$this->form->attributes[] = $clientOptions;
|
||||
}
|
||||
}
|
||||
|
||||
$inputID = $this->getInputId();
|
||||
$attribute = Html::getAttributeName($this->attribute);
|
||||
$options = $this->options;
|
||||
$class = isset($options['class']) ? (array) $options['class'] : [];
|
||||
$class[] = "field-$inputID";
|
||||
if ($this->model->isAttributeRequired($attribute)) {
|
||||
$class[] = $this->form->requiredCssClass;
|
||||
}
|
||||
$options['class'] = implode(' ', $class);
|
||||
if ($this->form->validationStateOn === ActiveForm::VALIDATION_STATE_ON_CONTAINER) {
|
||||
$this->addErrorClassIfNeeded($options);
|
||||
}
|
||||
$tag = ArrayHelper::remove($options, 'tag', 'div');
|
||||
|
||||
return Html::beginTag($tag, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the closing tag of the field container.
|
||||
* @return string the rendering result.
|
||||
*/
|
||||
public function end()
|
||||
{
|
||||
return Html::endTag(ArrayHelper::keyExists('tag', $this->options) ? $this->options['tag'] : 'div');
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a label tag for [[attribute]].
|
||||
* @param null|string|false $label the label to use. If `null`, the label will be generated via [[Model::getAttributeLabel()]].
|
||||
* If `false`, the generated field will not contain the label part.
|
||||
* Note that this will NOT be [[Html::encode()|encoded]].
|
||||
* @param null|array $options the tag options in terms of name-value pairs. It will be merged with [[labelOptions]].
|
||||
* The options will be rendered as the attributes of the resulting tag. The values will be HTML-encoded
|
||||
* using [[Html::encode()]]. If a value is `null`, the corresponding attribute will not be rendered.
|
||||
* @return $this the field object itself.
|
||||
*/
|
||||
public function label($label = null, $options = [])
|
||||
{
|
||||
if ($label === false) {
|
||||
$this->parts['{label}'] = '';
|
||||
return $this;
|
||||
}
|
||||
|
||||
$options = array_merge($this->labelOptions, $options);
|
||||
if ($label !== null) {
|
||||
$options['label'] = $label;
|
||||
}
|
||||
|
||||
if ($this->_skipLabelFor) {
|
||||
$options['for'] = null;
|
||||
}
|
||||
|
||||
$this->parts['{label}'] = Html::activeLabel($this->model, $this->attribute, $options);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a tag that contains the first validation error of [[attribute]].
|
||||
* Note that even if there is no validation error, this method will still return an empty error tag.
|
||||
* @param array|false $options the tag options in terms of name-value pairs. It will be merged with [[errorOptions]].
|
||||
* The options will be rendered as the attributes of the resulting tag. The values will be HTML-encoded
|
||||
* using [[Html::encode()]]. If this parameter is `false`, no error tag will be rendered.
|
||||
*
|
||||
* The following options are specially handled:
|
||||
*
|
||||
* - `tag`: this specifies the tag name. If not set, `div` will be used.
|
||||
* See also [[\yii\helpers\Html::tag()]].
|
||||
*
|
||||
* If you set a custom `id` for the error element, you may need to adjust the [[$selectors]] accordingly.
|
||||
* @see $errorOptions
|
||||
* @return $this the field object itself.
|
||||
*/
|
||||
public function error($options = [])
|
||||
{
|
||||
if ($options === false) {
|
||||
$this->parts['{error}'] = '';
|
||||
return $this;
|
||||
}
|
||||
$options = array_merge($this->errorOptions, $options);
|
||||
$this->parts['{error}'] = Html::error($this->model, $this->attribute, $options);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the hint tag.
|
||||
* @param string|bool $content the hint content.
|
||||
* If `null`, the hint will be generated via [[Model::getAttributeHint()]].
|
||||
* If `false`, the generated field will not contain the hint part.
|
||||
* Note that this will NOT be [[Html::encode()|encoded]].
|
||||
* @param array $options the tag options in terms of name-value pairs. These will be rendered as
|
||||
* the attributes of the hint tag. The values will be HTML-encoded using [[Html::encode()]].
|
||||
*
|
||||
* The following options are specially handled:
|
||||
*
|
||||
* - `tag`: this specifies the tag name. If not set, `div` will be used.
|
||||
* See also [[\yii\helpers\Html::tag()]].
|
||||
*
|
||||
* @return $this the field object itself.
|
||||
*/
|
||||
public function hint($content, $options = [])
|
||||
{
|
||||
if ($content === false) {
|
||||
$this->parts['{hint}'] = '';
|
||||
return $this;
|
||||
}
|
||||
|
||||
$options = array_merge($this->hintOptions, $options);
|
||||
if ($content !== null) {
|
||||
$options['hint'] = $content;
|
||||
}
|
||||
$this->parts['{hint}'] = Html::activeHint($this->model, $this->attribute, $options);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders an input tag.
|
||||
* @param string $type the input type (e.g. `text`, `password`)
|
||||
* @param array $options the tag options in terms of name-value pairs. These will be rendered as
|
||||
* the attributes of the resulting tag. The values will be HTML-encoded using [[Html::encode()]].
|
||||
*
|
||||
* If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
|
||||
*
|
||||
* @return $this the field object itself.
|
||||
*/
|
||||
public function input($type, $options = [])
|
||||
{
|
||||
$options = array_merge($this->inputOptions, $options);
|
||||
if ($this->form->validationStateOn === ActiveForm::VALIDATION_STATE_ON_INPUT) {
|
||||
$this->addErrorClassIfNeeded($options);
|
||||
}
|
||||
|
||||
$this->addAriaAttributes($options);
|
||||
$this->adjustLabelFor($options);
|
||||
$this->parts['{input}'] = Html::activeInput($type, $this->model, $this->attribute, $options);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a text input.
|
||||
* This method will generate the `name` and `value` tag attributes automatically for the model attribute
|
||||
* unless they are explicitly specified in `$options`.
|
||||
* @param array $options the tag options in terms of name-value pairs. These will be rendered as
|
||||
* the attributes of the resulting tag. The values will be HTML-encoded using [[Html::encode()]].
|
||||
*
|
||||
* The following special options are recognized:
|
||||
*
|
||||
* - `maxlength`: int|bool, when `maxlength` is set `true` and the model attribute is validated
|
||||
* by a string validator, the `maxlength` option will take the value of [[\yii\validators\StringValidator::max]].
|
||||
* This is available since version 2.0.3.
|
||||
*
|
||||
* Note that if you set a custom `id` for the input element, you may need to adjust the value of [[selectors]] accordingly.
|
||||
*
|
||||
* @return $this the field object itself.
|
||||
*/
|
||||
public function textInput($options = [])
|
||||
{
|
||||
$options = array_merge($this->inputOptions, $options);
|
||||
|
||||
if ($this->form->validationStateOn === ActiveForm::VALIDATION_STATE_ON_INPUT) {
|
||||
$this->addErrorClassIfNeeded($options);
|
||||
}
|
||||
|
||||
$this->addAriaAttributes($options);
|
||||
$this->adjustLabelFor($options);
|
||||
$this->parts['{input}'] = Html::activeTextInput($this->model, $this->attribute, $options);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a hidden input.
|
||||
*
|
||||
* Note that this method is provided for completeness. In most cases because you do not need
|
||||
* to validate a hidden input, you should not need to use this method. Instead, you should
|
||||
* use [[\yii\helpers\Html::activeHiddenInput()]].
|
||||
*
|
||||
* This method will generate the `name` and `value` tag attributes automatically for the model attribute
|
||||
* unless they are explicitly specified in `$options`.
|
||||
* @param array $options the tag options in terms of name-value pairs. These will be rendered as
|
||||
* the attributes of the resulting tag. The values will be HTML-encoded using [[Html::encode()]].
|
||||
*
|
||||
* If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
|
||||
*
|
||||
* @return $this the field object itself.
|
||||
*/
|
||||
public function hiddenInput($options = [])
|
||||
{
|
||||
$options = array_merge($this->inputOptions, $options);
|
||||
$this->adjustLabelFor($options);
|
||||
$this->parts['{input}'] = Html::activeHiddenInput($this->model, $this->attribute, $options);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a password input.
|
||||
* This method will generate the `name` and `value` tag attributes automatically for the model attribute
|
||||
* unless they are explicitly specified in `$options`.
|
||||
* @param array $options the tag options in terms of name-value pairs. These will be rendered as
|
||||
* the attributes of the resulting tag. The values will be HTML-encoded using [[Html::encode()]].
|
||||
*
|
||||
* If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
|
||||
*
|
||||
* @return $this the field object itself.
|
||||
*/
|
||||
public function passwordInput($options = [])
|
||||
{
|
||||
$options = array_merge($this->inputOptions, $options);
|
||||
|
||||
if ($this->form->validationStateOn === ActiveForm::VALIDATION_STATE_ON_INPUT) {
|
||||
$this->addErrorClassIfNeeded($options);
|
||||
}
|
||||
|
||||
$this->addAriaAttributes($options);
|
||||
$this->adjustLabelFor($options);
|
||||
$this->parts['{input}'] = Html::activePasswordInput($this->model, $this->attribute, $options);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a file input.
|
||||
* This method will generate the `name` and `value` tag attributes automatically for the model attribute
|
||||
* unless they are explicitly specified in `$options`.
|
||||
* @param array $options the tag options in terms of name-value pairs. These will be rendered as
|
||||
* the attributes of the resulting tag. The values will be HTML-encoded using [[Html::encode()]].
|
||||
*
|
||||
* If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
|
||||
*
|
||||
* @return $this the field object itself.
|
||||
*/
|
||||
public function fileInput($options = [])
|
||||
{
|
||||
// https://github.com/yiisoft/yii2/pull/795
|
||||
if ($this->inputOptions !== ['class' => 'form-control']) {
|
||||
$options = array_merge($this->inputOptions, $options);
|
||||
}
|
||||
// https://github.com/yiisoft/yii2/issues/8779
|
||||
if (!isset($this->form->options['enctype'])) {
|
||||
$this->form->options['enctype'] = 'multipart/form-data';
|
||||
}
|
||||
|
||||
if ($this->form->validationStateOn === ActiveForm::VALIDATION_STATE_ON_INPUT) {
|
||||
$this->addErrorClassIfNeeded($options);
|
||||
}
|
||||
|
||||
$this->addAriaAttributes($options);
|
||||
$this->adjustLabelFor($options);
|
||||
$this->parts['{input}'] = Html::activeFileInput($this->model, $this->attribute, $options);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a text area.
|
||||
* The model attribute value will be used as the content in the textarea.
|
||||
* @param array $options the tag options in terms of name-value pairs. These will be rendered as
|
||||
* the attributes of the resulting tag. The values will be HTML-encoded using [[Html::encode()]].
|
||||
*
|
||||
* If you set a custom `id` for the textarea element, you may need to adjust the [[$selectors]] accordingly.
|
||||
*
|
||||
* @return $this the field object itself.
|
||||
*/
|
||||
public function textarea($options = [])
|
||||
{
|
||||
$options = array_merge($this->inputOptions, $options);
|
||||
|
||||
if ($this->form->validationStateOn === ActiveForm::VALIDATION_STATE_ON_INPUT) {
|
||||
$this->addErrorClassIfNeeded($options);
|
||||
}
|
||||
|
||||
$this->addAriaAttributes($options);
|
||||
$this->adjustLabelFor($options);
|
||||
$this->parts['{input}'] = Html::activeTextarea($this->model, $this->attribute, $options);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a radio button.
|
||||
* This method will generate the `checked` tag attribute according to the model attribute value.
|
||||
* @param array $options the tag options in terms of name-value pairs. The following options are specially handled:
|
||||
*
|
||||
* - `uncheck`: string, the value associated with the uncheck state of the radio button. If not set,
|
||||
* it will take the default value `0`. This method will render a hidden input so that if the radio button
|
||||
* is not checked and is submitted, the value of this attribute will still be submitted to the server
|
||||
* via the hidden input. If you do not want any hidden input, you should explicitly set this option as `null`.
|
||||
* - `label`: string, a label displayed next to the radio button. It will NOT be HTML-encoded. Therefore you can pass
|
||||
* in HTML code such as an image tag. If this is coming from end users, you should [[Html::encode()|encode]] it to prevent XSS attacks.
|
||||
* When this option is specified, the radio button will be enclosed by a label tag. If you do not want any label, you should
|
||||
* explicitly set this option as `null`.
|
||||
* - `labelOptions`: array, the HTML attributes for the label tag. This is only used when the `label` option is specified.
|
||||
*
|
||||
* The rest of the options will be rendered as the attributes of the resulting tag. The values will
|
||||
* be HTML-encoded using [[Html::encode()]]. If a value is `null`, the corresponding attribute will not be rendered.
|
||||
*
|
||||
* If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
|
||||
*
|
||||
* @param bool $enclosedByLabel whether to enclose the radio within the label.
|
||||
* If `true`, the method will still use [[template]] to layout the radio button and the error message
|
||||
* except that the radio is enclosed by the label tag.
|
||||
* @return $this the field object itself.
|
||||
*/
|
||||
public function radio($options = [], $enclosedByLabel = true)
|
||||
{
|
||||
if ($enclosedByLabel) {
|
||||
$this->parts['{input}'] = Html::activeRadio($this->model, $this->attribute, $options);
|
||||
$this->parts['{label}'] = '';
|
||||
} else {
|
||||
if (isset($options['label']) && !isset($this->parts['{label}'])) {
|
||||
$this->parts['{label}'] = $options['label'];
|
||||
if (!empty($options['labelOptions'])) {
|
||||
$this->labelOptions = $options['labelOptions'];
|
||||
}
|
||||
}
|
||||
unset($options['labelOptions']);
|
||||
$options['label'] = null;
|
||||
$this->parts['{input}'] = Html::activeRadio($this->model, $this->attribute, $options);
|
||||
}
|
||||
|
||||
if ($this->form->validationStateOn === ActiveForm::VALIDATION_STATE_ON_INPUT) {
|
||||
$this->addErrorClassIfNeeded($options);
|
||||
}
|
||||
|
||||
$this->addAriaAttributes($options);
|
||||
$this->adjustLabelFor($options);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a checkbox.
|
||||
* This method will generate the `checked` tag attribute according to the model attribute value.
|
||||
* @param array $options the tag options in terms of name-value pairs. The following options are specially handled:
|
||||
*
|
||||
* - `uncheck`: string, the value associated with the uncheck state of the radio button. If not set,
|
||||
* it will take the default value `0`. This method will render a hidden input so that if the radio button
|
||||
* is not checked and is submitted, the value of this attribute will still be submitted to the server
|
||||
* via the hidden input. If you do not want any hidden input, you should explicitly set this option as `null`.
|
||||
* - `label`: string, a label displayed next to the checkbox. It will NOT be HTML-encoded. Therefore you can pass
|
||||
* in HTML code such as an image tag. If this is coming from end users, you should [[Html::encode()|encode]] it to prevent XSS attacks.
|
||||
* When this option is specified, the checkbox will be enclosed by a label tag. If you do not want any label, you should
|
||||
* explicitly set this option as `null`.
|
||||
* - `labelOptions`: array, the HTML attributes for the label tag. This is only used when the `label` option is specified.
|
||||
*
|
||||
* The rest of the options will be rendered as the attributes of the resulting tag. The values will
|
||||
* be HTML-encoded using [[Html::encode()]]. If a value is `null`, the corresponding attribute will not be rendered.
|
||||
*
|
||||
* If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
|
||||
*
|
||||
* @param bool $enclosedByLabel whether to enclose the checkbox within the label.
|
||||
* If `true`, the method will still use [[template]] to layout the checkbox and the error message
|
||||
* except that the checkbox is enclosed by the label tag.
|
||||
* @return $this the field object itself.
|
||||
*/
|
||||
public function checkbox($options = [], $enclosedByLabel = true)
|
||||
{
|
||||
if ($enclosedByLabel) {
|
||||
$this->parts['{input}'] = Html::activeCheckbox($this->model, $this->attribute, $options);
|
||||
$this->parts['{label}'] = '';
|
||||
} else {
|
||||
if (isset($options['label']) && !isset($this->parts['{label}'])) {
|
||||
$this->parts['{label}'] = $options['label'];
|
||||
if (!empty($options['labelOptions'])) {
|
||||
$this->labelOptions = $options['labelOptions'];
|
||||
}
|
||||
}
|
||||
unset($options['labelOptions']);
|
||||
$options['label'] = null;
|
||||
$this->parts['{input}'] = Html::activeCheckbox($this->model, $this->attribute, $options);
|
||||
}
|
||||
|
||||
if ($this->form->validationStateOn === ActiveForm::VALIDATION_STATE_ON_INPUT) {
|
||||
$this->addErrorClassIfNeeded($options);
|
||||
}
|
||||
|
||||
$this->addAriaAttributes($options);
|
||||
$this->adjustLabelFor($options);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a drop-down list.
|
||||
* The selection of the drop-down list is taken from the value of the model attribute.
|
||||
* @param array $items the option data items. The array keys are option values, and the array values
|
||||
* are the corresponding option labels. The array can also be nested (i.e. some array values are arrays too).
|
||||
* For each sub-array, an option group will be generated whose label is the key associated with the sub-array.
|
||||
* If you have a list of data models, you may convert them into the format described above using
|
||||
* [[ArrayHelper::map()]].
|
||||
*
|
||||
* Note, the values and labels will be automatically HTML-encoded by this method, and the blank spaces in
|
||||
* the labels will also be HTML-encoded.
|
||||
* @param array $options the tag options in terms of name-value pairs.
|
||||
*
|
||||
* For the list of available options please refer to the `$options` parameter of [[\yii\helpers\Html::activeDropDownList()]].
|
||||
*
|
||||
* If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
|
||||
*
|
||||
* @return $this the field object itself.
|
||||
*/
|
||||
public function dropDownList($items, $options = [])
|
||||
{
|
||||
$options = array_merge($this->inputOptions, $options);
|
||||
|
||||
if ($this->form->validationStateOn === ActiveForm::VALIDATION_STATE_ON_INPUT) {
|
||||
$this->addErrorClassIfNeeded($options);
|
||||
}
|
||||
|
||||
$this->addAriaAttributes($options);
|
||||
$this->adjustLabelFor($options);
|
||||
$this->parts['{input}'] = Html::activeDropDownList($this->model, $this->attribute, $items, $options);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a list box.
|
||||
* The selection of the list box is taken from the value of the model attribute.
|
||||
* @param array $items the option data items. The array keys are option values, and the array values
|
||||
* are the corresponding option labels. The array can also be nested (i.e. some array values are arrays too).
|
||||
* For each sub-array, an option group will be generated whose label is the key associated with the sub-array.
|
||||
* If you have a list of data models, you may convert them into the format described above using
|
||||
* [[\yii\helpers\ArrayHelper::map()]].
|
||||
*
|
||||
* Note, the values and labels will be automatically HTML-encoded by this method, and the blank spaces in
|
||||
* the labels will also be HTML-encoded.
|
||||
* @param array $options the tag options in terms of name-value pairs.
|
||||
*
|
||||
* For the list of available options please refer to the `$options` parameter of [[\yii\helpers\Html::activeListBox()]].
|
||||
*
|
||||
* If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
|
||||
*
|
||||
* @return $this the field object itself.
|
||||
*/
|
||||
public function listBox($items, $options = [])
|
||||
{
|
||||
$options = array_merge($this->inputOptions, $options);
|
||||
|
||||
if ($this->form->validationStateOn === ActiveForm::VALIDATION_STATE_ON_INPUT) {
|
||||
$this->addErrorClassIfNeeded($options);
|
||||
}
|
||||
|
||||
$this->addAriaAttributes($options);
|
||||
$this->adjustLabelFor($options);
|
||||
$this->parts['{input}'] = Html::activeListBox($this->model, $this->attribute, $items, $options);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a list of checkboxes.
|
||||
* A checkbox list allows multiple selection, like [[listBox()]].
|
||||
* As a result, the corresponding submitted value is an array.
|
||||
* The selection of the checkbox list is taken from the value of the model attribute.
|
||||
* @param array $items the data item used to generate the checkboxes.
|
||||
* The array values are the labels, while the array keys are the corresponding checkbox values.
|
||||
* @param array $options options (name => config) for the checkbox list.
|
||||
* For the list of available options please refer to the `$options` parameter of [[\yii\helpers\Html::activeCheckboxList()]].
|
||||
* @return $this the field object itself.
|
||||
*/
|
||||
public function checkboxList($items, $options = [])
|
||||
{
|
||||
if ($this->form->validationStateOn === ActiveForm::VALIDATION_STATE_ON_INPUT) {
|
||||
$this->addErrorClassIfNeeded($options);
|
||||
}
|
||||
|
||||
$this->addAriaAttributes($options);
|
||||
$this->adjustLabelFor($options);
|
||||
$this->_skipLabelFor = true;
|
||||
$this->parts['{input}'] = Html::activeCheckboxList($this->model, $this->attribute, $items, $options);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a list of radio buttons.
|
||||
* A radio button list is like a checkbox list, except that it only allows single selection.
|
||||
* The selection of the radio buttons is taken from the value of the model attribute.
|
||||
* @param array $items the data item used to generate the radio buttons.
|
||||
* The array values are the labels, while the array keys are the corresponding radio values.
|
||||
* @param array $options options (name => config) for the radio button list.
|
||||
* For the list of available options please refer to the `$options` parameter of [[\yii\helpers\Html::activeRadioList()]].
|
||||
* @return $this the field object itself.
|
||||
*/
|
||||
public function radioList($items, $options = [])
|
||||
{
|
||||
if ($this->form->validationStateOn === ActiveForm::VALIDATION_STATE_ON_INPUT) {
|
||||
$this->addErrorClassIfNeeded($options);
|
||||
}
|
||||
|
||||
$this->addAriaAttributes($options);
|
||||
$this->adjustLabelFor($options);
|
||||
$this->_skipLabelFor = true;
|
||||
$this->parts['{input}'] = Html::activeRadioList($this->model, $this->attribute, $items, $options);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a widget as the input of the field.
|
||||
*
|
||||
* Note that the widget must have both `model` and `attribute` properties. They will
|
||||
* be initialized with [[model]] and [[attribute]] of this field, respectively.
|
||||
*
|
||||
* If you want to use a widget that does not have `model` and `attribute` properties,
|
||||
* please use [[render()]] instead.
|
||||
*
|
||||
* For example to use the [[MaskedInput]] widget to get some date input, you can use
|
||||
* the following code, assuming that `$form` is your [[ActiveForm]] instance:
|
||||
*
|
||||
* ```php
|
||||
* $form->field($model, 'date')->widget(\yii\widgets\MaskedInput::className(), [
|
||||
* 'mask' => '99/99/9999',
|
||||
* ]);
|
||||
* ```
|
||||
*
|
||||
* If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
|
||||
*
|
||||
* @param string $class the widget class name.
|
||||
* @param array $config name-value pairs that will be used to initialize the widget.
|
||||
* @return $this the field object itself.
|
||||
*/
|
||||
public function widget($class, $config = [])
|
||||
{
|
||||
/* @var $class \yii\base\Widget */
|
||||
$config['model'] = $this->model;
|
||||
$config['attribute'] = $this->attribute;
|
||||
$config['view'] = $this->form->getView();
|
||||
if (is_subclass_of($class, 'yii\widgets\InputWidget')) {
|
||||
$config['field'] = $this;
|
||||
if (isset($config['options'])) {
|
||||
if ($this->form->validationStateOn === ActiveForm::VALIDATION_STATE_ON_INPUT) {
|
||||
$this->addErrorClassIfNeeded($config['options']);
|
||||
}
|
||||
|
||||
$this->addAriaAttributes($config['options']);
|
||||
$this->adjustLabelFor($config['options']);
|
||||
}
|
||||
}
|
||||
|
||||
$this->parts['{input}'] = $class::widget($config);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the `for` attribute for the label based on the input options.
|
||||
* @param array $options the input options.
|
||||
*/
|
||||
protected function adjustLabelFor($options)
|
||||
{
|
||||
if (!isset($options['id'])) {
|
||||
return;
|
||||
}
|
||||
$this->_inputId = $options['id'];
|
||||
if (!isset($this->labelOptions['for'])) {
|
||||
$this->labelOptions['for'] = $options['id'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the JS options for the field.
|
||||
* @return array the JS options.
|
||||
*/
|
||||
protected function getClientOptions()
|
||||
{
|
||||
$attribute = Html::getAttributeName($this->attribute);
|
||||
if (!in_array($attribute, $this->model->activeAttributes(), true)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$clientValidation = $this->isClientValidationEnabled();
|
||||
$ajaxValidation = $this->isAjaxValidationEnabled();
|
||||
|
||||
if ($clientValidation) {
|
||||
$validators = [];
|
||||
foreach ($this->model->getActiveValidators($attribute) as $validator) {
|
||||
/* @var $validator \yii\validators\Validator */
|
||||
$js = $validator->clientValidateAttribute($this->model, $attribute, $this->form->getView());
|
||||
if ($validator->enableClientValidation && $js != '') {
|
||||
if ($validator->whenClient !== null) {
|
||||
$js = "if (({$validator->whenClient})(attribute, value)) { $js }";
|
||||
}
|
||||
$validators[] = $js;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$ajaxValidation && (!$clientValidation || empty($validators))) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$options = [];
|
||||
|
||||
$inputID = $this->getInputId();
|
||||
$options['id'] = Html::getInputId($this->model, $this->attribute);
|
||||
$options['name'] = $this->attribute;
|
||||
|
||||
$options['container'] = isset($this->selectors['container']) ? $this->selectors['container'] : ".field-$inputID";
|
||||
$options['input'] = isset($this->selectors['input']) ? $this->selectors['input'] : "#$inputID";
|
||||
if (isset($this->selectors['error'])) {
|
||||
$options['error'] = $this->selectors['error'];
|
||||
} elseif (isset($this->errorOptions['class'])) {
|
||||
$options['error'] = '.' . implode('.', preg_split('/\s+/', $this->errorOptions['class'], -1, PREG_SPLIT_NO_EMPTY));
|
||||
} else {
|
||||
$options['error'] = isset($this->errorOptions['tag']) ? $this->errorOptions['tag'] : 'span';
|
||||
}
|
||||
|
||||
$options['encodeError'] = !isset($this->errorOptions['encode']) || $this->errorOptions['encode'];
|
||||
if ($ajaxValidation) {
|
||||
$options['enableAjaxValidation'] = true;
|
||||
}
|
||||
foreach (['validateOnChange', 'validateOnBlur', 'validateOnType', 'validationDelay'] as $name) {
|
||||
$options[$name] = $this->$name === null ? $this->form->$name : $this->$name;
|
||||
}
|
||||
|
||||
if (!empty($validators)) {
|
||||
$options['validate'] = new JsExpression('function (attribute, value, messages, deferred, $form) {' . implode('', $validators) . '}');
|
||||
}
|
||||
|
||||
if ($this->addAriaAttributes === false) {
|
||||
$options['updateAriaInvalid'] = false;
|
||||
}
|
||||
|
||||
// only get the options that are different from the default ones (set in yii.activeForm.js)
|
||||
return array_diff_assoc($options, [
|
||||
'validateOnChange' => true,
|
||||
'validateOnBlur' => true,
|
||||
'validateOnType' => false,
|
||||
'validationDelay' => 500,
|
||||
'encodeError' => true,
|
||||
'error' => '.help-block',
|
||||
'updateAriaInvalid' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if client validation enabled for the field.
|
||||
* @return bool
|
||||
* @since 2.0.11
|
||||
*/
|
||||
protected function isClientValidationEnabled()
|
||||
{
|
||||
return $this->enableClientValidation || $this->enableClientValidation === null && $this->form->enableClientValidation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if ajax validation enabled for the field.
|
||||
* @return bool
|
||||
* @since 2.0.11
|
||||
*/
|
||||
protected function isAjaxValidationEnabled()
|
||||
{
|
||||
return $this->enableAjaxValidation || $this->enableAjaxValidation === null && $this->form->enableAjaxValidation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTML `id` of the input element of this form field.
|
||||
* @return string the input id.
|
||||
* @since 2.0.7
|
||||
*/
|
||||
protected function getInputId()
|
||||
{
|
||||
return $this->_inputId ?: Html::getInputId($this->model, $this->attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds aria attributes to the input options.
|
||||
* @param $options array input options
|
||||
* @since 2.0.11
|
||||
*/
|
||||
protected function addAriaAttributes(&$options)
|
||||
{
|
||||
if ($this->addAriaAttributes) {
|
||||
if (!isset($options['aria-required']) && $this->model->isAttributeRequired($this->attribute)) {
|
||||
$options['aria-required'] = 'true';
|
||||
}
|
||||
if (!isset($options['aria-invalid'])) {
|
||||
if ($this->model->hasErrors($this->attribute)) {
|
||||
$options['aria-invalid'] = 'true';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds validation class to the input options if needed.
|
||||
* @param $options array input options
|
||||
* @since 2.0.14
|
||||
*/
|
||||
protected function addErrorClassIfNeeded(&$options)
|
||||
{
|
||||
// Get proper attribute name when attribute name is tabular.
|
||||
$attributeName = Html::getAttributeName($this->attribute);
|
||||
|
||||
if ($this->model->hasErrors($attributeName)) {
|
||||
Html::addCssClass($options, $this->form->errorCssClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
462
vendor/yiisoft/yii2/widgets/ActiveForm.php
vendored
Normal file
462
vendor/yiisoft/yii2/widgets/ActiveForm.php
vendored
Normal file
@@ -0,0 +1,462 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\widgets;
|
||||
|
||||
use Yii;
|
||||
use yii\base\InvalidCallException;
|
||||
use yii\base\Model;
|
||||
use yii\base\Widget;
|
||||
use yii\helpers\ArrayHelper;
|
||||
use yii\helpers\Html;
|
||||
use yii\helpers\Json;
|
||||
use yii\helpers\Url;
|
||||
|
||||
/**
|
||||
* ActiveForm is a widget that builds an interactive HTML form for one or multiple data models.
|
||||
*
|
||||
* For more details and usage information on ActiveForm, see the [guide article on forms](guide:input-forms).
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class ActiveForm extends Widget
|
||||
{
|
||||
/**
|
||||
* Add validation state class to container tag
|
||||
* @since 2.0.14
|
||||
*/
|
||||
const VALIDATION_STATE_ON_CONTAINER = 'container';
|
||||
/**
|
||||
* Add validation state class to input tag
|
||||
* @since 2.0.14
|
||||
*/
|
||||
const VALIDATION_STATE_ON_INPUT = 'input';
|
||||
|
||||
/**
|
||||
* @var array|string the form action URL. This parameter will be processed by [[\yii\helpers\Url::to()]].
|
||||
* @see method for specifying the HTTP method for this form.
|
||||
*/
|
||||
public $action = '';
|
||||
/**
|
||||
* @var string the form submission method. This should be either `post` or `get`. Defaults to `post`.
|
||||
*
|
||||
* When you set this to `get` you may see the url parameters repeated on each request.
|
||||
* This is because the default value of [[action]] is set to be the current request url and each submit
|
||||
* will add new parameters instead of replacing existing ones.
|
||||
* You may set [[action]] explicitly to avoid this:
|
||||
*
|
||||
* ```php
|
||||
* $form = ActiveForm::begin([
|
||||
* 'method' => 'get',
|
||||
* 'action' => ['controller/action'],
|
||||
* ]);
|
||||
* ```
|
||||
*/
|
||||
public $method = 'post';
|
||||
/**
|
||||
* @var array the HTML attributes (name-value pairs) for the form tag.
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
*/
|
||||
public $options = [];
|
||||
/**
|
||||
* @var string the default field class name when calling [[field()]] to create a new field.
|
||||
* @see fieldConfig
|
||||
*/
|
||||
public $fieldClass = 'yii\widgets\ActiveField';
|
||||
/**
|
||||
* @var array|\Closure the default configuration used by [[field()]] when creating a new field object.
|
||||
* This can be either a configuration array or an anonymous function returning a configuration array.
|
||||
* If the latter, the signature should be as follows:
|
||||
*
|
||||
* ```php
|
||||
* function ($model, $attribute)
|
||||
* ```
|
||||
*
|
||||
* The value of this property will be merged recursively with the `$options` parameter passed to [[field()]].
|
||||
*
|
||||
* @see fieldClass
|
||||
*/
|
||||
public $fieldConfig = [];
|
||||
/**
|
||||
* @var bool whether to perform encoding on the error summary.
|
||||
*/
|
||||
public $encodeErrorSummary = true;
|
||||
/**
|
||||
* @var string the default CSS class for the error summary container.
|
||||
* @see errorSummary()
|
||||
*/
|
||||
public $errorSummaryCssClass = 'error-summary';
|
||||
/**
|
||||
* @var string the CSS class that is added to a field container when the associated attribute is required.
|
||||
*/
|
||||
public $requiredCssClass = 'required';
|
||||
/**
|
||||
* @var string the CSS class that is added to a field container when the associated attribute has validation error.
|
||||
*/
|
||||
public $errorCssClass = 'has-error';
|
||||
/**
|
||||
* @var string the CSS class that is added to a field container when the associated attribute is successfully validated.
|
||||
*/
|
||||
public $successCssClass = 'has-success';
|
||||
/**
|
||||
* @var string the CSS class that is added to a field container when the associated attribute is being validated.
|
||||
*/
|
||||
public $validatingCssClass = 'validating';
|
||||
/**
|
||||
* @var string where to render validation state class
|
||||
* Could be either "container" or "input".
|
||||
* Default is "container".
|
||||
* @since 2.0.14
|
||||
*/
|
||||
public $validationStateOn = self::VALIDATION_STATE_ON_CONTAINER;
|
||||
/**
|
||||
* @var bool whether to enable client-side data validation.
|
||||
* If [[ActiveField::enableClientValidation]] is set, its value will take precedence for that input field.
|
||||
*/
|
||||
public $enableClientValidation = true;
|
||||
/**
|
||||
* @var bool whether to enable AJAX-based data validation.
|
||||
* If [[ActiveField::enableAjaxValidation]] is set, its value will take precedence for that input field.
|
||||
*/
|
||||
public $enableAjaxValidation = false;
|
||||
/**
|
||||
* @var bool whether to hook up `yii.activeForm` JavaScript plugin.
|
||||
* This property must be set `true` if you want to support client validation and/or AJAX validation, or if you
|
||||
* want to take advantage of the `yii.activeForm` plugin. When this is `false`, the form will not generate
|
||||
* any JavaScript.
|
||||
* @see registerClientScript
|
||||
*/
|
||||
public $enableClientScript = true;
|
||||
/**
|
||||
* @var array|string the URL for performing AJAX-based validation. This property will be processed by
|
||||
* [[Url::to()]]. Please refer to [[Url::to()]] for more details on how to configure this property.
|
||||
* If this property is not set, it will take the value of the form's action attribute.
|
||||
*/
|
||||
public $validationUrl;
|
||||
/**
|
||||
* @var bool whether to perform validation when the form is submitted.
|
||||
*/
|
||||
public $validateOnSubmit = true;
|
||||
/**
|
||||
* @var bool whether to perform validation when the value of an input field is changed.
|
||||
* If [[ActiveField::validateOnChange]] is set, its value will take precedence for that input field.
|
||||
*/
|
||||
public $validateOnChange = true;
|
||||
/**
|
||||
* @var bool whether to perform validation when an input field loses focus.
|
||||
* If [[ActiveField::$validateOnBlur]] is set, its value will take precedence for that input field.
|
||||
*/
|
||||
public $validateOnBlur = true;
|
||||
/**
|
||||
* @var bool whether to perform validation while the user is typing in an input field.
|
||||
* If [[ActiveField::validateOnType]] is set, its value will take precedence for that input field.
|
||||
* @see validationDelay
|
||||
*/
|
||||
public $validateOnType = false;
|
||||
/**
|
||||
* @var int number of milliseconds that the validation should be delayed when the user types in the field
|
||||
* and [[validateOnType]] is set `true`.
|
||||
* If [[ActiveField::validationDelay]] is set, its value will take precedence for that input field.
|
||||
*/
|
||||
public $validationDelay = 500;
|
||||
/**
|
||||
* @var string the name of the GET parameter indicating the validation request is an AJAX request.
|
||||
*/
|
||||
public $ajaxParam = 'ajax';
|
||||
/**
|
||||
* @var string the type of data that you're expecting back from the server.
|
||||
*/
|
||||
public $ajaxDataType = 'json';
|
||||
/**
|
||||
* @var bool whether to scroll to the first error after validation.
|
||||
* @since 2.0.6
|
||||
*/
|
||||
public $scrollToError = true;
|
||||
/**
|
||||
* @var int offset in pixels that should be added when scrolling to the first error.
|
||||
* @since 2.0.11
|
||||
*/
|
||||
public $scrollToErrorOffset = 0;
|
||||
/**
|
||||
* @var array the client validation options for individual attributes. Each element of the array
|
||||
* represents the validation options for a particular attribute.
|
||||
* @internal
|
||||
*/
|
||||
public $attributes = [];
|
||||
|
||||
/**
|
||||
* @var ActiveField[] the ActiveField objects that are currently active
|
||||
*/
|
||||
private $_fields = [];
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the widget.
|
||||
* This renders the form open tag.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if (!isset($this->options['id'])) {
|
||||
$this->options['id'] = $this->getId();
|
||||
}
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the widget.
|
||||
* This registers the necessary JavaScript code and renders the form open and close tags.
|
||||
* @throws InvalidCallException if `beginField()` and `endField()` calls are not matching.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
if (!empty($this->_fields)) {
|
||||
throw new InvalidCallException('Each beginField() should have a matching endField() call.');
|
||||
}
|
||||
|
||||
$content = ob_get_clean();
|
||||
echo Html::beginForm($this->action, $this->method, $this->options);
|
||||
echo $content;
|
||||
|
||||
if ($this->enableClientScript) {
|
||||
$this->registerClientScript();
|
||||
}
|
||||
|
||||
echo Html::endForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* This registers the necessary JavaScript code.
|
||||
* @since 2.0.12
|
||||
*/
|
||||
public function registerClientScript()
|
||||
{
|
||||
$id = $this->options['id'];
|
||||
$options = Json::htmlEncode($this->getClientOptions());
|
||||
$attributes = Json::htmlEncode($this->attributes);
|
||||
$view = $this->getView();
|
||||
ActiveFormAsset::register($view);
|
||||
$view->registerJs("jQuery('#$id').yiiActiveForm($attributes, $options);");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the options for the form JS widget.
|
||||
* @return array the options.
|
||||
*/
|
||||
protected function getClientOptions()
|
||||
{
|
||||
$options = [
|
||||
'encodeErrorSummary' => $this->encodeErrorSummary,
|
||||
'errorSummary' => '.' . implode('.', preg_split('/\s+/', $this->errorSummaryCssClass, -1, PREG_SPLIT_NO_EMPTY)),
|
||||
'validateOnSubmit' => $this->validateOnSubmit,
|
||||
'errorCssClass' => $this->errorCssClass,
|
||||
'successCssClass' => $this->successCssClass,
|
||||
'validatingCssClass' => $this->validatingCssClass,
|
||||
'ajaxParam' => $this->ajaxParam,
|
||||
'ajaxDataType' => $this->ajaxDataType,
|
||||
'scrollToError' => $this->scrollToError,
|
||||
'scrollToErrorOffset' => $this->scrollToErrorOffset,
|
||||
'validationStateOn' => $this->validationStateOn,
|
||||
];
|
||||
if ($this->validationUrl !== null) {
|
||||
$options['validationUrl'] = Url::to($this->validationUrl);
|
||||
}
|
||||
|
||||
// only get the options that are different from the default ones (set in yii.activeForm.js)
|
||||
return array_diff_assoc($options, [
|
||||
'encodeErrorSummary' => true,
|
||||
'errorSummary' => '.error-summary',
|
||||
'validateOnSubmit' => true,
|
||||
'errorCssClass' => 'has-error',
|
||||
'successCssClass' => 'has-success',
|
||||
'validatingCssClass' => 'validating',
|
||||
'ajaxParam' => 'ajax',
|
||||
'ajaxDataType' => 'json',
|
||||
'scrollToError' => true,
|
||||
'scrollToErrorOffset' => 0,
|
||||
'validationStateOn' => self::VALIDATION_STATE_ON_CONTAINER,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a summary of the validation errors.
|
||||
* If there is no validation error, an empty error summary markup will still be generated, but it will be hidden.
|
||||
* @param Model|Model[] $models the model(s) associated with this form.
|
||||
* @param array $options the tag options in terms of name-value pairs. The following options are specially handled:
|
||||
*
|
||||
* - `header`: string, the header HTML for the error summary. If not set, a default prompt string will be used.
|
||||
* - `footer`: string, the footer HTML for the error summary.
|
||||
*
|
||||
* The rest of the options will be rendered as the attributes of the container tag. The values will
|
||||
* be HTML-encoded using [[\yii\helpers\Html::encode()]]. If a value is `null`, the corresponding attribute will not be rendered.
|
||||
* @return string the generated error summary.
|
||||
* @see errorSummaryCssClass
|
||||
*/
|
||||
public function errorSummary($models, $options = [])
|
||||
{
|
||||
Html::addCssClass($options, $this->errorSummaryCssClass);
|
||||
$options['encode'] = $this->encodeErrorSummary;
|
||||
return Html::errorSummary($models, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a form field.
|
||||
* A form field is associated with a model and an attribute. It contains a label, an input and an error message
|
||||
* and use them to interact with end users to collect their inputs for the attribute.
|
||||
* @param Model $model the data model.
|
||||
* @param string $attribute the attribute name or expression. See [[Html::getAttributeName()]] for the format
|
||||
* about attribute expression.
|
||||
* @param array $options the additional configurations for the field object. These are properties of [[ActiveField]]
|
||||
* or a subclass, depending on the value of [[fieldClass]].
|
||||
* @return ActiveField the created ActiveField object.
|
||||
* @see fieldConfig
|
||||
*/
|
||||
public function field($model, $attribute, $options = [])
|
||||
{
|
||||
$config = $this->fieldConfig;
|
||||
if ($config instanceof \Closure) {
|
||||
$config = call_user_func($config, $model, $attribute);
|
||||
}
|
||||
if (!isset($config['class'])) {
|
||||
$config['class'] = $this->fieldClass;
|
||||
}
|
||||
|
||||
return Yii::createObject(ArrayHelper::merge($config, $options, [
|
||||
'model' => $model,
|
||||
'attribute' => $attribute,
|
||||
'form' => $this,
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Begins a form field.
|
||||
* This method will create a new form field and returns its opening tag.
|
||||
* You should call [[endField()]] afterwards.
|
||||
* @param Model $model the data model.
|
||||
* @param string $attribute the attribute name or expression. See [[Html::getAttributeName()]] for the format
|
||||
* about attribute expression.
|
||||
* @param array $options the additional configurations for the field object.
|
||||
* @return string the opening tag.
|
||||
* @see endField()
|
||||
* @see field()
|
||||
*/
|
||||
public function beginField($model, $attribute, $options = [])
|
||||
{
|
||||
$field = $this->field($model, $attribute, $options);
|
||||
$this->_fields[] = $field;
|
||||
return $field->begin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends a form field.
|
||||
* This method will return the closing tag of an active form field started by [[beginField()]].
|
||||
* @return string the closing tag of the form field.
|
||||
* @throws InvalidCallException if this method is called without a prior [[beginField()]] call.
|
||||
*/
|
||||
public function endField()
|
||||
{
|
||||
$field = array_pop($this->_fields);
|
||||
if ($field instanceof ActiveField) {
|
||||
return $field->end();
|
||||
}
|
||||
|
||||
throw new InvalidCallException('Mismatching endField() call.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates one or several models and returns an error message array indexed by the attribute IDs.
|
||||
* This is a helper method that simplifies the way of writing AJAX validation code.
|
||||
*
|
||||
* For example, you may use the following code in a controller action to respond
|
||||
* to an AJAX validation request:
|
||||
*
|
||||
* ```php
|
||||
* $model = new Post;
|
||||
* $model->load(Yii::$app->request->post());
|
||||
* if (Yii::$app->request->isAjax) {
|
||||
* Yii::$app->response->format = Response::FORMAT_JSON;
|
||||
* return ActiveForm::validate($model);
|
||||
* }
|
||||
* // ... respond to non-AJAX request ...
|
||||
* ```
|
||||
*
|
||||
* To validate multiple models, simply pass each model as a parameter to this method, like
|
||||
* the following:
|
||||
*
|
||||
* ```php
|
||||
* ActiveForm::validate($model1, $model2, ...);
|
||||
* ```
|
||||
*
|
||||
* @param Model $model the model to be validated.
|
||||
* @param mixed $attributes list of attributes that should be validated.
|
||||
* If this parameter is empty, it means any attribute listed in the applicable
|
||||
* validation rules should be validated.
|
||||
*
|
||||
* When this method is used to validate multiple models, this parameter will be interpreted
|
||||
* as a model.
|
||||
*
|
||||
* @return array the error message array indexed by the attribute IDs.
|
||||
*/
|
||||
public static function validate($model, $attributes = null)
|
||||
{
|
||||
$result = [];
|
||||
if ($attributes instanceof Model) {
|
||||
// validating multiple models
|
||||
$models = func_get_args();
|
||||
$attributes = null;
|
||||
} else {
|
||||
$models = [$model];
|
||||
}
|
||||
/* @var $model Model */
|
||||
foreach ($models as $model) {
|
||||
$model->validate($attributes);
|
||||
foreach ($model->getErrors() as $attribute => $errors) {
|
||||
$result[Html::getInputId($model, $attribute)] = $errors;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates an array of model instances and returns an error message array indexed by the attribute IDs.
|
||||
* This is a helper method that simplifies the way of writing AJAX validation code for tabular input.
|
||||
*
|
||||
* For example, you may use the following code in a controller action to respond
|
||||
* to an AJAX validation request:
|
||||
*
|
||||
* ```php
|
||||
* // ... load $models ...
|
||||
* if (Yii::$app->request->isAjax) {
|
||||
* Yii::$app->response->format = Response::FORMAT_JSON;
|
||||
* return ActiveForm::validateMultiple($models);
|
||||
* }
|
||||
* // ... respond to non-AJAX request ...
|
||||
* ```
|
||||
*
|
||||
* @param array $models an array of models to be validated.
|
||||
* @param mixed $attributes list of attributes that should be validated.
|
||||
* If this parameter is empty, it means any attribute listed in the applicable
|
||||
* validation rules should be validated.
|
||||
* @return array the error message array indexed by the attribute IDs.
|
||||
*/
|
||||
public static function validateMultiple($models, $attributes = null)
|
||||
{
|
||||
$result = [];
|
||||
/* @var $model Model */
|
||||
foreach ($models as $i => $model) {
|
||||
$model->validate($attributes);
|
||||
foreach ($model->getErrors() as $attribute => $errors) {
|
||||
$result[Html::getInputId($model, "[$i]" . $attribute)] = $errors;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
27
vendor/yiisoft/yii2/widgets/ActiveFormAsset.php
vendored
Normal file
27
vendor/yiisoft/yii2/widgets/ActiveFormAsset.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\widgets;
|
||||
|
||||
use yii\web\AssetBundle;
|
||||
|
||||
/**
|
||||
* The asset bundle for the [[ActiveForm]] widget.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class ActiveFormAsset extends AssetBundle
|
||||
{
|
||||
public $sourcePath = '@yii/assets';
|
||||
public $js = [
|
||||
'yii.activeForm.js',
|
||||
];
|
||||
public $depends = [
|
||||
'yii\web\YiiAsset',
|
||||
];
|
||||
}
|
||||
277
vendor/yiisoft/yii2/widgets/BaseListView.php
vendored
Normal file
277
vendor/yiisoft/yii2/widgets/BaseListView.php
vendored
Normal file
@@ -0,0 +1,277 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\widgets;
|
||||
|
||||
use Yii;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\base\Widget;
|
||||
use yii\helpers\ArrayHelper;
|
||||
use yii\helpers\Html;
|
||||
|
||||
/**
|
||||
* BaseListView is a base class for widgets displaying data from data provider
|
||||
* such as ListView and GridView.
|
||||
*
|
||||
* It provides features like sorting, paging and also filtering the data.
|
||||
*
|
||||
* For more details and usage information on BaseListView, see the [guide article on data widgets](guide:output-data-widgets).
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
abstract class BaseListView extends Widget
|
||||
{
|
||||
/**
|
||||
* @var array the HTML attributes for the container tag of the list view.
|
||||
* The "tag" element specifies the tag name of the container element and defaults to "div".
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
*/
|
||||
public $options = [];
|
||||
/**
|
||||
* @var \yii\data\DataProviderInterface the data provider for the view. This property is required.
|
||||
*/
|
||||
public $dataProvider;
|
||||
/**
|
||||
* @var array the configuration for the pager widget. By default, [[LinkPager]] will be
|
||||
* used to render the pager. You can use a different widget class by configuring the "class" element.
|
||||
* Note that the widget must support the `pagination` property which will be populated with the
|
||||
* [[\yii\data\BaseDataProvider::pagination|pagination]] value of the [[dataProvider]] and will overwrite this value.
|
||||
*/
|
||||
public $pager = [];
|
||||
/**
|
||||
* @var array the configuration for the sorter widget. By default, [[LinkSorter]] will be
|
||||
* used to render the sorter. You can use a different widget class by configuring the "class" element.
|
||||
* Note that the widget must support the `sort` property which will be populated with the
|
||||
* [[\yii\data\BaseDataProvider::sort|sort]] value of the [[dataProvider]] and will overwrite this value.
|
||||
*/
|
||||
public $sorter = [];
|
||||
/**
|
||||
* @var string the HTML content to be displayed as the summary of the list view.
|
||||
* If you do not want to show the summary, you may set it with an empty string.
|
||||
*
|
||||
* The following tokens will be replaced with the corresponding values:
|
||||
*
|
||||
* - `{begin}`: the starting row number (1-based) currently being displayed
|
||||
* - `{end}`: the ending row number (1-based) currently being displayed
|
||||
* - `{count}`: the number of rows currently being displayed
|
||||
* - `{totalCount}`: the total number of rows available
|
||||
* - `{page}`: the page number (1-based) current being displayed
|
||||
* - `{pageCount}`: the number of pages available
|
||||
*/
|
||||
public $summary;
|
||||
/**
|
||||
* @var array the HTML attributes for the summary of the list view.
|
||||
* The "tag" element specifies the tag name of the summary element and defaults to "div".
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
*/
|
||||
public $summaryOptions = ['class' => 'summary'];
|
||||
/**
|
||||
* @var bool whether to show an empty list view if [[dataProvider]] returns no data.
|
||||
* The default value is false which displays an element according to the [[emptyText]]
|
||||
* and [[emptyTextOptions]] properties.
|
||||
*/
|
||||
public $showOnEmpty = false;
|
||||
/**
|
||||
* @var string|false the HTML content to be displayed when [[dataProvider]] does not have any data.
|
||||
* When this is set to `false` no extra HTML content will be generated.
|
||||
* The default value is the text "No results found." which will be translated to the current application language.
|
||||
* @see showOnEmpty
|
||||
* @see emptyTextOptions
|
||||
*/
|
||||
public $emptyText;
|
||||
/**
|
||||
* @var array the HTML attributes for the emptyText of the list view.
|
||||
* The "tag" element specifies the tag name of the emptyText element and defaults to "div".
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
*/
|
||||
public $emptyTextOptions = ['class' => 'empty'];
|
||||
/**
|
||||
* @var string the layout that determines how different sections of the list view should be organized.
|
||||
* The following tokens will be replaced with the corresponding section contents:
|
||||
*
|
||||
* - `{summary}`: the summary section. See [[renderSummary()]].
|
||||
* - `{items}`: the list items. See [[renderItems()]].
|
||||
* - `{sorter}`: the sorter. See [[renderSorter()]].
|
||||
* - `{pager}`: the pager. See [[renderPager()]].
|
||||
*/
|
||||
public $layout = "{summary}\n{items}\n{pager}";
|
||||
|
||||
|
||||
/**
|
||||
* Renders the data models.
|
||||
* @return string the rendering result.
|
||||
*/
|
||||
abstract public function renderItems();
|
||||
|
||||
/**
|
||||
* Initializes the view.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if ($this->dataProvider === null) {
|
||||
throw new InvalidConfigException('The "dataProvider" property must be set.');
|
||||
}
|
||||
if ($this->emptyText === null) {
|
||||
$this->emptyText = Yii::t('yii', 'No results found.');
|
||||
}
|
||||
if (!isset($this->options['id'])) {
|
||||
$this->options['id'] = $this->getId();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the widget.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
if ($this->showOnEmpty || $this->dataProvider->getCount() > 0) {
|
||||
$content = preg_replace_callback('/{\\w+}/', function ($matches) {
|
||||
$content = $this->renderSection($matches[0]);
|
||||
|
||||
return $content === false ? $matches[0] : $content;
|
||||
}, $this->layout);
|
||||
} else {
|
||||
$content = $this->renderEmpty();
|
||||
}
|
||||
|
||||
$options = $this->options;
|
||||
$tag = ArrayHelper::remove($options, 'tag', 'div');
|
||||
echo Html::tag($tag, $content, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a section of the specified name.
|
||||
* If the named section is not supported, false will be returned.
|
||||
* @param string $name the section name, e.g., `{summary}`, `{items}`.
|
||||
* @return string|bool the rendering result of the section, or false if the named section is not supported.
|
||||
*/
|
||||
public function renderSection($name)
|
||||
{
|
||||
switch ($name) {
|
||||
case '{summary}':
|
||||
return $this->renderSummary();
|
||||
case '{items}':
|
||||
return $this->renderItems();
|
||||
case '{pager}':
|
||||
return $this->renderPager();
|
||||
case '{sorter}':
|
||||
return $this->renderSorter();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the HTML content indicating that the list view has no data.
|
||||
* @return string the rendering result
|
||||
* @see emptyText
|
||||
*/
|
||||
public function renderEmpty()
|
||||
{
|
||||
if ($this->emptyText === false) {
|
||||
return '';
|
||||
}
|
||||
$options = $this->emptyTextOptions;
|
||||
$tag = ArrayHelper::remove($options, 'tag', 'div');
|
||||
return Html::tag($tag, $this->emptyText, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the summary text.
|
||||
*/
|
||||
public function renderSummary()
|
||||
{
|
||||
$count = $this->dataProvider->getCount();
|
||||
if ($count <= 0) {
|
||||
return '';
|
||||
}
|
||||
$summaryOptions = $this->summaryOptions;
|
||||
$tag = ArrayHelper::remove($summaryOptions, 'tag', 'div');
|
||||
if (($pagination = $this->dataProvider->getPagination()) !== false) {
|
||||
$totalCount = $this->dataProvider->getTotalCount();
|
||||
$begin = $pagination->getPage() * $pagination->pageSize + 1;
|
||||
$end = $begin + $count - 1;
|
||||
if ($begin > $end) {
|
||||
$begin = $end;
|
||||
}
|
||||
$page = $pagination->getPage() + 1;
|
||||
$pageCount = $pagination->pageCount;
|
||||
if (($summaryContent = $this->summary) === null) {
|
||||
return Html::tag($tag, Yii::t('yii', 'Showing <b>{begin, number}-{end, number}</b> of <b>{totalCount, number}</b> {totalCount, plural, one{item} other{items}}.', [
|
||||
'begin' => $begin,
|
||||
'end' => $end,
|
||||
'count' => $count,
|
||||
'totalCount' => $totalCount,
|
||||
'page' => $page,
|
||||
'pageCount' => $pageCount,
|
||||
]), $summaryOptions);
|
||||
}
|
||||
} else {
|
||||
$begin = $page = $pageCount = 1;
|
||||
$end = $totalCount = $count;
|
||||
if (($summaryContent = $this->summary) === null) {
|
||||
return Html::tag($tag, Yii::t('yii', 'Total <b>{count, number}</b> {count, plural, one{item} other{items}}.', [
|
||||
'begin' => $begin,
|
||||
'end' => $end,
|
||||
'count' => $count,
|
||||
'totalCount' => $totalCount,
|
||||
'page' => $page,
|
||||
'pageCount' => $pageCount,
|
||||
]), $summaryOptions);
|
||||
}
|
||||
}
|
||||
|
||||
return Yii::$app->getI18n()->format($summaryContent, [
|
||||
'begin' => $begin,
|
||||
'end' => $end,
|
||||
'count' => $count,
|
||||
'totalCount' => $totalCount,
|
||||
'page' => $page,
|
||||
'pageCount' => $pageCount,
|
||||
], Yii::$app->language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the pager.
|
||||
* @return string the rendering result
|
||||
*/
|
||||
public function renderPager()
|
||||
{
|
||||
$pagination = $this->dataProvider->getPagination();
|
||||
if ($pagination === false || $this->dataProvider->getCount() <= 0) {
|
||||
return '';
|
||||
}
|
||||
/* @var $class LinkPager */
|
||||
$pager = $this->pager;
|
||||
$class = ArrayHelper::remove($pager, 'class', LinkPager::className());
|
||||
$pager['pagination'] = $pagination;
|
||||
$pager['view'] = $this->getView();
|
||||
|
||||
return $class::widget($pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the sorter.
|
||||
* @return string the rendering result
|
||||
*/
|
||||
public function renderSorter()
|
||||
{
|
||||
$sort = $this->dataProvider->getSort();
|
||||
if ($sort === false || empty($sort->attributes) || $this->dataProvider->getCount() <= 0) {
|
||||
return '';
|
||||
}
|
||||
/* @var $class LinkSorter */
|
||||
$sorter = $this->sorter;
|
||||
$class = ArrayHelper::remove($sorter, 'class', LinkSorter::className());
|
||||
$sorter['sort'] = $sort;
|
||||
$sorter['view'] = $this->getView();
|
||||
|
||||
return $class::widget($sorter);
|
||||
}
|
||||
}
|
||||
71
vendor/yiisoft/yii2/widgets/Block.php
vendored
Normal file
71
vendor/yiisoft/yii2/widgets/Block.php
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\widgets;
|
||||
|
||||
use yii\base\Widget;
|
||||
|
||||
/**
|
||||
* Block records all output between [[begin()]] and [[end()]] calls and stores it in [[\yii\base\View::$blocks]].
|
||||
* for later use.
|
||||
*
|
||||
* [[\yii\base\View]] component contains two methods [[\yii\base\View::beginBlock()]] and [[\yii\base\View::endBlock()]].
|
||||
* The general idea is that you're defining block default in a view or layout:
|
||||
*
|
||||
* ```php
|
||||
* <?php $this->beginBlock('messages', true) ?>
|
||||
* Nothing.
|
||||
* <?php $this->endBlock() ?>
|
||||
* ```
|
||||
*
|
||||
* And then overriding default in sub-views:
|
||||
*
|
||||
* ```php
|
||||
* <?php $this->beginBlock('username') ?>
|
||||
* Umm... hello?
|
||||
* <?php $this->endBlock() ?>
|
||||
* ```
|
||||
*
|
||||
* Second parameter defines if block content should be outputted which is desired when rendering its content but isn't
|
||||
* desired when redefining it in subviews.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class Block extends Widget
|
||||
{
|
||||
/**
|
||||
* @var bool whether to render the block content in place. Defaults to false,
|
||||
* meaning the captured block content will not be displayed.
|
||||
*/
|
||||
public $renderInPlace = false;
|
||||
|
||||
|
||||
/**
|
||||
* Starts recording a block.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends recording a block.
|
||||
* This method stops output buffering and saves the rendering result as a named block in the view.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$block = ob_get_clean();
|
||||
if ($this->renderInPlace) {
|
||||
echo $block;
|
||||
}
|
||||
$this->view->blocks[$this->getId()] = $block;
|
||||
}
|
||||
}
|
||||
181
vendor/yiisoft/yii2/widgets/Breadcrumbs.php
vendored
Normal file
181
vendor/yiisoft/yii2/widgets/Breadcrumbs.php
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\widgets;
|
||||
|
||||
use Yii;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\base\Widget;
|
||||
use yii\helpers\ArrayHelper;
|
||||
use yii\helpers\Html;
|
||||
|
||||
/**
|
||||
* Breadcrumbs displays a list of links indicating the position of the current page in the whole site hierarchy.
|
||||
*
|
||||
* For example, breadcrumbs like "Home / Sample Post / Edit" means the user is viewing an edit page
|
||||
* for the "Sample Post". He can click on "Sample Post" to view that page, or he can click on "Home"
|
||||
* to return to the homepage.
|
||||
*
|
||||
* To use Breadcrumbs, you need to configure its [[links]] property, which specifies the links to be displayed. For example,
|
||||
*
|
||||
* ```php
|
||||
* // $this is the view object currently being used
|
||||
* echo Breadcrumbs::widget([
|
||||
* 'itemTemplate' => "<li><i>{link}</i></li>\n", // template for all links
|
||||
* 'links' => [
|
||||
* [
|
||||
* 'label' => 'Post Category',
|
||||
* 'url' => ['post-category/view', 'id' => 10],
|
||||
* 'template' => "<li><b>{link}</b></li>\n", // template for this link only
|
||||
* ],
|
||||
* ['label' => 'Sample Post', 'url' => ['post/edit', 'id' => 1]],
|
||||
* 'Edit',
|
||||
* ],
|
||||
* ]);
|
||||
* ```
|
||||
*
|
||||
* Because breadcrumbs usually appears in nearly every page of a website, you may consider placing it in a layout view.
|
||||
* You can use a view parameter (e.g. `$this->params['breadcrumbs']`) to configure the links in different
|
||||
* views. In the layout view, you assign this view parameter to the [[links]] property like the following:
|
||||
*
|
||||
* ```php
|
||||
* // $this is the view object currently being used
|
||||
* echo Breadcrumbs::widget([
|
||||
* 'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
|
||||
* ]);
|
||||
* ```
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class Breadcrumbs extends Widget
|
||||
{
|
||||
/**
|
||||
* @var string the name of the breadcrumb container tag.
|
||||
*/
|
||||
public $tag = 'ul';
|
||||
/**
|
||||
* @var array the HTML attributes for the breadcrumb container tag.
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
*/
|
||||
public $options = ['class' => 'breadcrumb'];
|
||||
/**
|
||||
* @var bool whether to HTML-encode the link labels.
|
||||
*/
|
||||
public $encodeLabels = true;
|
||||
/**
|
||||
* @var array the first hyperlink in the breadcrumbs (called home link).
|
||||
* Please refer to [[links]] on the format of the link.
|
||||
* If this property is not set, it will default to a link pointing to [[\yii\web\Application::homeUrl]]
|
||||
* with the label 'Home'. If this property is false, the home link will not be rendered.
|
||||
*/
|
||||
public $homeLink;
|
||||
/**
|
||||
* @var array list of links to appear in the breadcrumbs. If this property is empty,
|
||||
* the widget will not render anything. Each array element represents a single link in the breadcrumbs
|
||||
* with the following structure:
|
||||
*
|
||||
* ```php
|
||||
* [
|
||||
* 'label' => 'label of the link', // required
|
||||
* 'url' => 'url of the link', // optional, will be processed by Url::to()
|
||||
* 'template' => 'own template of the item', // optional, if not set $this->itemTemplate will be used
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* If a link is active, you only need to specify its "label", and instead of writing `['label' => $label]`,
|
||||
* you may simply use `$label`.
|
||||
*
|
||||
* Since version 2.0.1, any additional array elements for each link will be treated as the HTML attributes
|
||||
* for the hyperlink tag. For example, the following link specification will generate a hyperlink
|
||||
* with CSS class `external`:
|
||||
*
|
||||
* ```php
|
||||
* [
|
||||
* 'label' => 'demo',
|
||||
* 'url' => 'http://example.com',
|
||||
* 'class' => 'external',
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* Since version 2.0.3 each individual link can override global [[encodeLabels]] param like the following:
|
||||
*
|
||||
* ```php
|
||||
* [
|
||||
* 'label' => '<strong>Hello!</strong>',
|
||||
* 'encode' => false,
|
||||
* ]
|
||||
* ```
|
||||
*/
|
||||
public $links = [];
|
||||
/**
|
||||
* @var string the template used to render each inactive item in the breadcrumbs. The token `{link}`
|
||||
* will be replaced with the actual HTML link for each inactive item.
|
||||
*/
|
||||
public $itemTemplate = "<li>{link}</li>\n";
|
||||
/**
|
||||
* @var string the template used to render each active item in the breadcrumbs. The token `{link}`
|
||||
* will be replaced with the actual HTML link for each active item.
|
||||
*/
|
||||
public $activeItemTemplate = "<li class=\"active\">{link}</li>\n";
|
||||
|
||||
|
||||
/**
|
||||
* Renders the widget.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
if (empty($this->links)) {
|
||||
return;
|
||||
}
|
||||
$links = [];
|
||||
if ($this->homeLink === null) {
|
||||
$links[] = $this->renderItem([
|
||||
'label' => Yii::t('yii', 'Home'),
|
||||
'url' => Yii::$app->homeUrl,
|
||||
], $this->itemTemplate);
|
||||
} elseif ($this->homeLink !== false) {
|
||||
$links[] = $this->renderItem($this->homeLink, $this->itemTemplate);
|
||||
}
|
||||
foreach ($this->links as $link) {
|
||||
if (!is_array($link)) {
|
||||
$link = ['label' => $link];
|
||||
}
|
||||
$links[] = $this->renderItem($link, isset($link['url']) ? $this->itemTemplate : $this->activeItemTemplate);
|
||||
}
|
||||
echo Html::tag($this->tag, implode('', $links), $this->options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a single breadcrumb item.
|
||||
* @param array $link the link to be rendered. It must contain the "label" element. The "url" element is optional.
|
||||
* @param string $template the template to be used to rendered the link. The token "{link}" will be replaced by the link.
|
||||
* @return string the rendering result
|
||||
* @throws InvalidConfigException if `$link` does not have "label" element.
|
||||
*/
|
||||
protected function renderItem($link, $template)
|
||||
{
|
||||
$encodeLabel = ArrayHelper::remove($link, 'encode', $this->encodeLabels);
|
||||
if (array_key_exists('label', $link)) {
|
||||
$label = $encodeLabel ? Html::encode($link['label']) : $link['label'];
|
||||
} else {
|
||||
throw new InvalidConfigException('The "label" element is required for each link.');
|
||||
}
|
||||
if (isset($link['template'])) {
|
||||
$template = $link['template'];
|
||||
}
|
||||
if (isset($link['url'])) {
|
||||
$options = $link;
|
||||
unset($options['template'], $options['label'], $options['url']);
|
||||
$link = Html::a($label, $link['url'], $options);
|
||||
} else {
|
||||
$link = $label;
|
||||
}
|
||||
|
||||
return strtr($template, ['{link}' => $link]);
|
||||
}
|
||||
}
|
||||
81
vendor/yiisoft/yii2/widgets/ContentDecorator.php
vendored
Normal file
81
vendor/yiisoft/yii2/widgets/ContentDecorator.php
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\widgets;
|
||||
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\base\Widget;
|
||||
|
||||
/**
|
||||
* ContentDecorator records all output between [[begin()]] and [[end()]] calls, passes it to the given view file
|
||||
* as `$content` and then echoes rendering result.
|
||||
*
|
||||
* ```php
|
||||
* <?php ContentDecorator::begin([
|
||||
* 'viewFile' => '@app/views/layouts/base.php',
|
||||
* 'params' => [],
|
||||
* 'view' => $this,
|
||||
* ]) ?>
|
||||
*
|
||||
* some content here
|
||||
*
|
||||
* <?php ContentDecorator::end() ?>
|
||||
* ```
|
||||
*
|
||||
* There are [[\yii\base\View::beginContent()]] and [[\yii\base\View::endContent()]] wrapper methods in the
|
||||
* [[\yii\base\View]] component to make syntax more friendly. In the view these could be used as follows:
|
||||
*
|
||||
* ```php
|
||||
* <?php $this->beginContent('@app/views/layouts/base.php') ?>
|
||||
*
|
||||
* some content here
|
||||
*
|
||||
* <?php $this->endContent() ?>
|
||||
* ```
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class ContentDecorator extends Widget
|
||||
{
|
||||
/**
|
||||
* @var string the view file that will be used to decorate the content enclosed by this widget.
|
||||
* This can be specified as either the view file path or [path alias](guide:concept-aliases).
|
||||
*/
|
||||
public $viewFile;
|
||||
/**
|
||||
* @var array the parameters (name => value) to be extracted and made available in the decorative view.
|
||||
*/
|
||||
public $params = [];
|
||||
|
||||
|
||||
/**
|
||||
* Starts recording a clip.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
|
||||
if ($this->viewFile === null) {
|
||||
throw new InvalidConfigException('ContentDecorator::viewFile must be set.');
|
||||
}
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends recording a clip.
|
||||
* This method stops output buffering and saves the rendering result as a named clip in the controller.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$params = $this->params;
|
||||
$params['content'] = ob_get_clean();
|
||||
// render under the existing context
|
||||
echo $this->view->renderFile($this->viewFile, $params);
|
||||
}
|
||||
}
|
||||
251
vendor/yiisoft/yii2/widgets/DetailView.php
vendored
Normal file
251
vendor/yiisoft/yii2/widgets/DetailView.php
vendored
Normal file
@@ -0,0 +1,251 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\widgets;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Arrayable;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\base\Model;
|
||||
use yii\base\Widget;
|
||||
use yii\helpers\ArrayHelper;
|
||||
use yii\helpers\Html;
|
||||
use yii\helpers\Inflector;
|
||||
use yii\i18n\Formatter;
|
||||
|
||||
/**
|
||||
* DetailView displays the detail of a single data [[model]].
|
||||
*
|
||||
* DetailView is best used for displaying a model in a regular format (e.g. each model attribute
|
||||
* is displayed as a row in a table.) The model can be either an instance of [[Model]]
|
||||
* or an associative array.
|
||||
*
|
||||
* DetailView uses the [[attributes]] property to determines which model attributes
|
||||
* should be displayed and how they should be formatted.
|
||||
*
|
||||
* A typical usage of DetailView is as follows:
|
||||
*
|
||||
* ```php
|
||||
* echo DetailView::widget([
|
||||
* 'model' => $model,
|
||||
* 'attributes' => [
|
||||
* 'title', // title attribute (in plain text)
|
||||
* 'description:html', // description attribute in HTML
|
||||
* [ // the owner name of the model
|
||||
* 'label' => 'Owner',
|
||||
* 'value' => $model->owner->name,
|
||||
* ],
|
||||
* 'created_at:datetime', // creation date formatted as datetime
|
||||
* ],
|
||||
* ]);
|
||||
* ```
|
||||
*
|
||||
* For more details and usage information on DetailView, see the [guide article on data widgets](guide:output-data-widgets).
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class DetailView extends Widget
|
||||
{
|
||||
/**
|
||||
* @var array|object the data model whose details are to be displayed. This can be a [[Model]] instance,
|
||||
* an associative array, an object that implements [[Arrayable]] interface or simply an object with defined
|
||||
* public accessible non-static properties.
|
||||
*/
|
||||
public $model;
|
||||
/**
|
||||
* @var array a list of attributes to be displayed in the detail view. Each array element
|
||||
* represents the specification for displaying one particular attribute.
|
||||
*
|
||||
* An attribute can be specified as a string in the format of `attribute`, `attribute:format` or `attribute:format:label`,
|
||||
* where `attribute` refers to the attribute name, and `format` represents the format of the attribute. The `format`
|
||||
* is passed to the [[Formatter::format()]] method to format an attribute value into a displayable text.
|
||||
* Please refer to [[Formatter]] for the supported types. Both `format` and `label` are optional.
|
||||
* They will take default values if absent.
|
||||
*
|
||||
* An attribute can also be specified in terms of an array with the following elements:
|
||||
*
|
||||
* - `attribute`: the attribute name. This is required if either `label` or `value` is not specified.
|
||||
* - `label`: the label associated with the attribute. If this is not specified, it will be generated from the attribute name.
|
||||
* - `value`: the value to be displayed. If this is not specified, it will be retrieved from [[model]] using the attribute name
|
||||
* by calling [[ArrayHelper::getValue()]]. Note that this value will be formatted into a displayable text
|
||||
* according to the `format` option. Since version 2.0.11 it can be defined as closure with the following
|
||||
* parameters:
|
||||
*
|
||||
* ```php
|
||||
* function ($model, $widget)
|
||||
* ```
|
||||
*
|
||||
* `$model` refers to displayed model and `$widget` is an instance of `DetailView` widget.
|
||||
*
|
||||
* - `format`: the type of the value that determines how the value would be formatted into a displayable text.
|
||||
* Please refer to [[Formatter]] for supported types and [[Formatter::format()]] on how to specify this value.
|
||||
* - `visible`: whether the attribute is visible. If set to `false`, the attribute will NOT be displayed.
|
||||
* - `contentOptions`: the HTML attributes to customize value tag. For example: `['class' => 'bg-red']`.
|
||||
* Please refer to [[\yii\helpers\BaseHtml::renderTagAttributes()]] for the supported syntax.
|
||||
* - `captionOptions`: the HTML attributes to customize label tag. For example: `['class' => 'bg-red']`.
|
||||
* Please refer to [[\yii\helpers\BaseHtml::renderTagAttributes()]] for the supported syntax.
|
||||
*/
|
||||
public $attributes;
|
||||
/**
|
||||
* @var string|callable the template used to render a single attribute. If a string, the token `{label}`
|
||||
* and `{value}` will be replaced with the label and the value of the corresponding attribute.
|
||||
* If a callback (e.g. an anonymous function), the signature must be as follows:
|
||||
*
|
||||
* ```php
|
||||
* function ($attribute, $index, $widget)
|
||||
* ```
|
||||
*
|
||||
* where `$attribute` refer to the specification of the attribute being rendered, `$index` is the zero-based
|
||||
* index of the attribute in the [[attributes]] array, and `$widget` refers to this widget instance.
|
||||
*
|
||||
* Since Version 2.0.10, the tokens `{captionOptions}` and `{contentOptions}` are available, which will represent
|
||||
* HTML attributes of HTML container elements for the label and value.
|
||||
*/
|
||||
public $template = '<tr><th{captionOptions}>{label}</th><td{contentOptions}>{value}</td></tr>';
|
||||
/**
|
||||
* @var array the HTML attributes for the container tag of this widget. The `tag` option specifies
|
||||
* what container tag should be used. It defaults to `table` if not set.
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
*/
|
||||
public $options = ['class' => 'table table-striped table-bordered detail-view'];
|
||||
/**
|
||||
* @var array|Formatter the formatter used to format model attribute values into displayable texts.
|
||||
* This can be either an instance of [[Formatter]] or an configuration array for creating the [[Formatter]]
|
||||
* instance. If this property is not set, the `formatter` application component will be used.
|
||||
*/
|
||||
public $formatter;
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the detail view.
|
||||
* This method will initialize required property values.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
|
||||
if ($this->model === null) {
|
||||
throw new InvalidConfigException('Please specify the "model" property.');
|
||||
}
|
||||
if ($this->formatter === null) {
|
||||
$this->formatter = Yii::$app->getFormatter();
|
||||
} elseif (is_array($this->formatter)) {
|
||||
$this->formatter = Yii::createObject($this->formatter);
|
||||
}
|
||||
if (!$this->formatter instanceof Formatter) {
|
||||
throw new InvalidConfigException('The "formatter" property must be either a Format object or a configuration array.');
|
||||
}
|
||||
$this->normalizeAttributes();
|
||||
|
||||
if (!isset($this->options['id'])) {
|
||||
$this->options['id'] = $this->getId();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the detail view.
|
||||
* This is the main entry of the whole detail view rendering.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$rows = [];
|
||||
$i = 0;
|
||||
foreach ($this->attributes as $attribute) {
|
||||
$rows[] = $this->renderAttribute($attribute, $i++);
|
||||
}
|
||||
|
||||
$options = $this->options;
|
||||
$tag = ArrayHelper::remove($options, 'tag', 'table');
|
||||
echo Html::tag($tag, implode("\n", $rows), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a single attribute.
|
||||
* @param array $attribute the specification of the attribute to be rendered.
|
||||
* @param int $index the zero-based index of the attribute in the [[attributes]] array
|
||||
* @return string the rendering result
|
||||
*/
|
||||
protected function renderAttribute($attribute, $index)
|
||||
{
|
||||
if (is_string($this->template)) {
|
||||
$captionOptions = Html::renderTagAttributes(ArrayHelper::getValue($attribute, 'captionOptions', []));
|
||||
$contentOptions = Html::renderTagAttributes(ArrayHelper::getValue($attribute, 'contentOptions', []));
|
||||
return strtr($this->template, [
|
||||
'{label}' => $attribute['label'],
|
||||
'{value}' => $this->formatter->format($attribute['value'], $attribute['format']),
|
||||
'{captionOptions}' => $captionOptions,
|
||||
'{contentOptions}' => $contentOptions,
|
||||
]);
|
||||
}
|
||||
|
||||
return call_user_func($this->template, $attribute, $index, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the attribute specifications.
|
||||
* @throws InvalidConfigException
|
||||
*/
|
||||
protected function normalizeAttributes()
|
||||
{
|
||||
if ($this->attributes === null) {
|
||||
if ($this->model instanceof Model) {
|
||||
$this->attributes = $this->model->attributes();
|
||||
} elseif (is_object($this->model)) {
|
||||
$this->attributes = $this->model instanceof Arrayable ? array_keys($this->model->toArray()) : array_keys(get_object_vars($this->model));
|
||||
} elseif (is_array($this->model)) {
|
||||
$this->attributes = array_keys($this->model);
|
||||
} else {
|
||||
throw new InvalidConfigException('The "model" property must be either an array or an object.');
|
||||
}
|
||||
sort($this->attributes);
|
||||
}
|
||||
|
||||
foreach ($this->attributes as $i => $attribute) {
|
||||
if (is_string($attribute)) {
|
||||
if (!preg_match('/^([^:]+)(:(\w*))?(:(.*))?$/', $attribute, $matches)) {
|
||||
throw new InvalidConfigException('The attribute must be specified in the format of "attribute", "attribute:format" or "attribute:format:label"');
|
||||
}
|
||||
$attribute = [
|
||||
'attribute' => $matches[1],
|
||||
'format' => isset($matches[3]) ? $matches[3] : 'text',
|
||||
'label' => isset($matches[5]) ? $matches[5] : null,
|
||||
];
|
||||
}
|
||||
|
||||
if (!is_array($attribute)) {
|
||||
throw new InvalidConfigException('The attribute configuration must be an array.');
|
||||
}
|
||||
|
||||
if (isset($attribute['visible']) && !$attribute['visible']) {
|
||||
unset($this->attributes[$i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($attribute['format'])) {
|
||||
$attribute['format'] = 'text';
|
||||
}
|
||||
if (isset($attribute['attribute'])) {
|
||||
$attributeName = $attribute['attribute'];
|
||||
if (!isset($attribute['label'])) {
|
||||
$attribute['label'] = $this->model instanceof Model ? $this->model->getAttributeLabel($attributeName) : Inflector::camel2words($attributeName, true);
|
||||
}
|
||||
if (!array_key_exists('value', $attribute)) {
|
||||
$attribute['value'] = ArrayHelper::getValue($this->model, $attributeName);
|
||||
}
|
||||
} elseif (!isset($attribute['label']) || !array_key_exists('value', $attribute)) {
|
||||
throw new InvalidConfigException('The attribute configuration requires the "attribute" element to determine the value and display label.');
|
||||
}
|
||||
|
||||
if ($attribute['value'] instanceof \Closure) {
|
||||
$attribute['value'] = call_user_func($attribute['value'], $this->model, $this);
|
||||
}
|
||||
|
||||
$this->attributes[$i] = $attribute;
|
||||
}
|
||||
}
|
||||
}
|
||||
166
vendor/yiisoft/yii2/widgets/FragmentCache.php
vendored
Normal file
166
vendor/yiisoft/yii2/widgets/FragmentCache.php
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\widgets;
|
||||
|
||||
use Yii;
|
||||
use yii\base\DynamicContentAwareInterface;
|
||||
use yii\base\DynamicContentAwareTrait;
|
||||
use yii\base\Widget;
|
||||
use yii\caching\CacheInterface;
|
||||
use yii\caching\Dependency;
|
||||
use yii\di\Instance;
|
||||
|
||||
/**
|
||||
* FragmentCache is used by [[\yii\base\View]] to provide caching of page fragments.
|
||||
*
|
||||
* @property string|false $cachedContent The cached content. False is returned if valid content is not found
|
||||
* in the cache. This property is read-only.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class FragmentCache extends Widget implements DynamicContentAwareInterface
|
||||
{
|
||||
use DynamicContentAwareTrait;
|
||||
|
||||
/**
|
||||
* @var CacheInterface|array|string the cache object or the application component ID of the cache object.
|
||||
* After the FragmentCache 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';
|
||||
/**
|
||||
* @var int number of seconds that the data can remain valid in cache.
|
||||
* Use 0 to indicate that the cached data will never expire.
|
||||
*/
|
||||
public $duration = 60;
|
||||
/**
|
||||
* @var array|Dependency the dependency that the cached content depends on.
|
||||
* This can be either a [[Dependency]] object or a configuration array for creating the dependency object.
|
||||
* For example,
|
||||
*
|
||||
* ```php
|
||||
* [
|
||||
* 'class' => 'yii\caching\DbDependency',
|
||||
* 'sql' => 'SELECT MAX(updated_at) FROM post',
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* would make the output cache depends on the last modified time of all posts.
|
||||
* If any post has its modification time changed, the cached content would be invalidated.
|
||||
*/
|
||||
public $dependency;
|
||||
/**
|
||||
* @var string[]|string list of factors that would cause the variation of the content being cached.
|
||||
* Each factor is a string representing a variation (e.g. the language, a GET parameter).
|
||||
* The following variation setting will cause the content to be cached in different versions
|
||||
* according to the current application language:
|
||||
*
|
||||
* ```php
|
||||
* [
|
||||
* Yii::$app->language,
|
||||
* ]
|
||||
* ```
|
||||
*/
|
||||
public $variations;
|
||||
/**
|
||||
* @var bool whether to enable the fragment cache. You may use this property to turn on and off
|
||||
* the fragment cache according to specific setting (e.g. enable fragment cache only for GET requests).
|
||||
*/
|
||||
public $enabled = true;
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the FragmentCache object.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
|
||||
$this->cache = $this->enabled ? Instance::ensure($this->cache, 'yii\caching\CacheInterface') : null;
|
||||
|
||||
if ($this->cache instanceof CacheInterface && $this->getCachedContent() === false) {
|
||||
$this->getView()->pushDynamicContent($this);
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the end of content to be cached.
|
||||
* Content displayed before this method call and after [[init()]]
|
||||
* will be captured and saved in cache.
|
||||
* This method does nothing if valid content is already found in cache.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
if (($content = $this->getCachedContent()) !== false) {
|
||||
echo $content;
|
||||
} elseif ($this->cache instanceof CacheInterface) {
|
||||
$this->getView()->popDynamicContent();
|
||||
|
||||
$content = ob_get_clean();
|
||||
if ($content === false || $content === '') {
|
||||
return;
|
||||
}
|
||||
if (is_array($this->dependency)) {
|
||||
$this->dependency = Yii::createObject($this->dependency);
|
||||
}
|
||||
$data = [$content, $this->getDynamicPlaceholders()];
|
||||
$this->cache->set($this->calculateKey(), $data, $this->duration, $this->dependency);
|
||||
echo $this->updateDynamicContent($content, $this->getDynamicPlaceholders());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @var string|bool the cached content. False if the content is not cached.
|
||||
*/
|
||||
private $_content;
|
||||
|
||||
/**
|
||||
* Returns the cached content if available.
|
||||
* @return string|false the cached content. False is returned if valid content is not found in the cache.
|
||||
*/
|
||||
public function getCachedContent()
|
||||
{
|
||||
if ($this->_content !== null) {
|
||||
return $this->_content;
|
||||
}
|
||||
|
||||
$this->_content = false;
|
||||
|
||||
if (!($this->cache instanceof CacheInterface)) {
|
||||
return $this->_content;
|
||||
}
|
||||
|
||||
$key = $this->calculateKey();
|
||||
$data = $this->cache->get($key);
|
||||
if (!is_array($data) || count($data) !== 2) {
|
||||
return $this->_content;
|
||||
}
|
||||
|
||||
list($this->_content, $placeholders) = $data;
|
||||
if (!is_array($placeholders) || count($placeholders) === 0) {
|
||||
return $this->_content;
|
||||
}
|
||||
|
||||
$this->_content = $this->updateDynamicContent($this->_content, $placeholders, true);
|
||||
return $this->_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a unique key used for storing the content in cache.
|
||||
* The key generated depends on both [[id]] and [[variations]].
|
||||
* @return mixed a valid cache key
|
||||
*/
|
||||
protected function calculateKey()
|
||||
{
|
||||
return array_merge([__CLASS__, $this->getId()], (array)$this->variations);
|
||||
}
|
||||
}
|
||||
110
vendor/yiisoft/yii2/widgets/InputWidget.php
vendored
Normal file
110
vendor/yiisoft/yii2/widgets/InputWidget.php
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\widgets;
|
||||
|
||||
use Yii;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\base\Model;
|
||||
use yii\base\Widget;
|
||||
use yii\helpers\Html;
|
||||
|
||||
/**
|
||||
* InputWidget is the base class for widgets that collect user inputs.
|
||||
*
|
||||
* An input widget can be associated with a data [[model]] and an [[attribute]],
|
||||
* or a [[name]] and a [[value]]. If the former, the name and the value will
|
||||
* be generated automatically (subclasses may call [[renderInputHtml()]] to follow this behavior).
|
||||
*
|
||||
* Classes extending from this widget can be used in an [[\yii\widgets\ActiveForm|ActiveForm]]
|
||||
* using the [[\yii\widgets\ActiveField::widget()|widget()]] method, for example like this:
|
||||
*
|
||||
* ```php
|
||||
* <?= $form->field($model, 'from_date')->widget('WidgetClassName', [
|
||||
* // configure additional widget properties here
|
||||
* ]) ?>
|
||||
* ```
|
||||
*
|
||||
* For more details and usage information on InputWidget, see the [guide article on forms](guide:input-forms).
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class InputWidget extends Widget
|
||||
{
|
||||
/**
|
||||
* @var \yii\widgets\ActiveField active input field, which triggers this widget rendering.
|
||||
* This field will be automatically filled up in case widget instance is created via [[\yii\widgets\ActiveField::widget()]].
|
||||
* @since 2.0.11
|
||||
*/
|
||||
public $field;
|
||||
/**
|
||||
* @var Model the data model that this widget is associated with.
|
||||
*/
|
||||
public $model;
|
||||
/**
|
||||
* @var string the model attribute that this widget is associated with.
|
||||
*/
|
||||
public $attribute;
|
||||
/**
|
||||
* @var string the input name. This must be set if [[model]] and [[attribute]] are not set.
|
||||
*/
|
||||
public $name;
|
||||
/**
|
||||
* @var string the input value.
|
||||
*/
|
||||
public $value;
|
||||
/**
|
||||
* @var array the HTML attributes for the input tag.
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
*/
|
||||
public $options = [];
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the widget.
|
||||
* If you override this method, make sure you call the parent implementation first.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
if ($this->name === null && !$this->hasModel()) {
|
||||
throw new InvalidConfigException("Either 'name', or 'model' and 'attribute' properties must be specified.");
|
||||
}
|
||||
if (!isset($this->options['id'])) {
|
||||
$this->options['id'] = $this->hasModel() ? Html::getInputId($this->model, $this->attribute) : $this->getId();
|
||||
}
|
||||
parent::init();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool whether this widget is associated with a data model.
|
||||
*/
|
||||
protected function hasModel()
|
||||
{
|
||||
return $this->model instanceof Model && $this->attribute !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a HTML input tag.
|
||||
*
|
||||
* This will call [[Html::activeInput()]] if the input widget is [[hasModel()|tied to a model]],
|
||||
* or [[Html::input()]] if not.
|
||||
*
|
||||
* @param string $type the type of the input to create.
|
||||
* @return string the HTML of the input field.
|
||||
* @since 2.0.13
|
||||
* @see Html::activeInput()
|
||||
* @see Html::input()
|
||||
*/
|
||||
protected function renderInputHtml($type)
|
||||
{
|
||||
if ($this->hasModel()) {
|
||||
return Html::activeInput($type, $this->model, $this->attribute, $this->options);
|
||||
}
|
||||
return Html::input($type, $this->name, $this->value, $this->options);
|
||||
}
|
||||
}
|
||||
275
vendor/yiisoft/yii2/widgets/LinkPager.php
vendored
Normal file
275
vendor/yiisoft/yii2/widgets/LinkPager.php
vendored
Normal file
@@ -0,0 +1,275 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\widgets;
|
||||
|
||||
use Yii;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\base\Widget;
|
||||
use yii\data\Pagination;
|
||||
use yii\helpers\ArrayHelper;
|
||||
use yii\helpers\Html;
|
||||
|
||||
/**
|
||||
* LinkPager displays a list of hyperlinks that lead to different pages of target.
|
||||
*
|
||||
* LinkPager works with a [[Pagination]] object which specifies the total number
|
||||
* of pages and the current page number.
|
||||
*
|
||||
* Note that LinkPager only generates the necessary HTML markups. In order for it
|
||||
* to look like a real pager, you should provide some CSS styles for it.
|
||||
* With the default configuration, LinkPager should look good using Twitter Bootstrap CSS framework.
|
||||
*
|
||||
* For more details and usage information on LinkPager, see the [guide article on pagination](guide:output-pagination).
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class LinkPager extends Widget
|
||||
{
|
||||
/**
|
||||
* @var Pagination the pagination object that this pager is associated with.
|
||||
* You must set this property in order to make LinkPager work.
|
||||
*/
|
||||
public $pagination;
|
||||
/**
|
||||
* @var array HTML attributes for the pager container tag.
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
*/
|
||||
public $options = ['class' => 'pagination'];
|
||||
/**
|
||||
* @var array HTML attributes which will be applied to all link containers
|
||||
* @since 2.0.13
|
||||
*/
|
||||
public $linkContainerOptions = [];
|
||||
/**
|
||||
* @var array HTML attributes for the link in a pager container tag.
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
*/
|
||||
public $linkOptions = [];
|
||||
/**
|
||||
* @var string the CSS class for the each page button.
|
||||
* @since 2.0.7
|
||||
*/
|
||||
public $pageCssClass;
|
||||
/**
|
||||
* @var string the CSS class for the "first" page button.
|
||||
*/
|
||||
public $firstPageCssClass = 'first';
|
||||
/**
|
||||
* @var string the CSS class for the "last" page button.
|
||||
*/
|
||||
public $lastPageCssClass = 'last';
|
||||
/**
|
||||
* @var string the CSS class for the "previous" page button.
|
||||
*/
|
||||
public $prevPageCssClass = 'prev';
|
||||
/**
|
||||
* @var string the CSS class for the "next" page button.
|
||||
*/
|
||||
public $nextPageCssClass = 'next';
|
||||
/**
|
||||
* @var string the CSS class for the active (currently selected) page button.
|
||||
*/
|
||||
public $activePageCssClass = 'active';
|
||||
/**
|
||||
* @var string the CSS class for the disabled page buttons.
|
||||
*/
|
||||
public $disabledPageCssClass = 'disabled';
|
||||
/**
|
||||
* @var array the options for the disabled tag to be generated inside the disabled list element.
|
||||
* In order to customize the html tag, please use the tag key.
|
||||
*
|
||||
* ```php
|
||||
* $disabledListItemSubTagOptions = ['tag' => 'div', 'class' => 'disabled-div'];
|
||||
* ```
|
||||
* @since 2.0.11
|
||||
*/
|
||||
public $disabledListItemSubTagOptions = [];
|
||||
/**
|
||||
* @var int maximum number of page buttons that can be displayed. Defaults to 10.
|
||||
*/
|
||||
public $maxButtonCount = 10;
|
||||
/**
|
||||
* @var string|bool the label for the "next" page button. Note that this will NOT be HTML-encoded.
|
||||
* If this property is false, the "next" page button will not be displayed.
|
||||
*/
|
||||
public $nextPageLabel = '»';
|
||||
/**
|
||||
* @var string|bool the text label for the previous page button. Note that this will NOT be HTML-encoded.
|
||||
* If this property is false, the "previous" page button will not be displayed.
|
||||
*/
|
||||
public $prevPageLabel = '«';
|
||||
/**
|
||||
* @var string|bool the text label for the "first" page button. Note that this will NOT be HTML-encoded.
|
||||
* If it's specified as true, page number will be used as label.
|
||||
* Default is false that means the "first" page button will not be displayed.
|
||||
*/
|
||||
public $firstPageLabel = false;
|
||||
/**
|
||||
* @var string|bool the text label for the "last" page button. Note that this will NOT be HTML-encoded.
|
||||
* If it's specified as true, page number will be used as label.
|
||||
* Default is false that means the "last" page button will not be displayed.
|
||||
*/
|
||||
public $lastPageLabel = false;
|
||||
/**
|
||||
* @var bool whether to register link tags in the HTML header for prev, next, first and last page.
|
||||
* Defaults to `false` to avoid conflicts when multiple pagers are used on one page.
|
||||
* @see http://www.w3.org/TR/html401/struct/links.html#h-12.1.2
|
||||
* @see registerLinkTags()
|
||||
*/
|
||||
public $registerLinkTags = false;
|
||||
/**
|
||||
* @var bool Hide widget when only one page exist.
|
||||
*/
|
||||
public $hideOnSinglePage = true;
|
||||
/**
|
||||
* @var bool whether to render current page button as disabled.
|
||||
* @since 2.0.12
|
||||
*/
|
||||
public $disableCurrentPageButton = false;
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the pager.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
|
||||
if ($this->pagination === null) {
|
||||
throw new InvalidConfigException('The "pagination" property must be set.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the widget.
|
||||
* This overrides the parent implementation by displaying the generated page buttons.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
if ($this->registerLinkTags) {
|
||||
$this->registerLinkTags();
|
||||
}
|
||||
echo $this->renderPageButtons();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers relational link tags in the html header for prev, next, first and last page.
|
||||
* These links are generated using [[\yii\data\Pagination::getLinks()]].
|
||||
* @see http://www.w3.org/TR/html401/struct/links.html#h-12.1.2
|
||||
*/
|
||||
protected function registerLinkTags()
|
||||
{
|
||||
$view = $this->getView();
|
||||
foreach ($this->pagination->getLinks() as $rel => $href) {
|
||||
$view->registerLinkTag(['rel' => $rel, 'href' => $href], $rel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the page buttons.
|
||||
* @return string the rendering result
|
||||
*/
|
||||
protected function renderPageButtons()
|
||||
{
|
||||
$pageCount = $this->pagination->getPageCount();
|
||||
if ($pageCount < 2 && $this->hideOnSinglePage) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$buttons = [];
|
||||
$currentPage = $this->pagination->getPage();
|
||||
|
||||
// first page
|
||||
$firstPageLabel = $this->firstPageLabel === true ? '1' : $this->firstPageLabel;
|
||||
if ($firstPageLabel !== false) {
|
||||
$buttons[] = $this->renderPageButton($firstPageLabel, 0, $this->firstPageCssClass, $currentPage <= 0, false);
|
||||
}
|
||||
|
||||
// prev page
|
||||
if ($this->prevPageLabel !== false) {
|
||||
if (($page = $currentPage - 1) < 0) {
|
||||
$page = 0;
|
||||
}
|
||||
$buttons[] = $this->renderPageButton($this->prevPageLabel, $page, $this->prevPageCssClass, $currentPage <= 0, false);
|
||||
}
|
||||
|
||||
// internal pages
|
||||
list($beginPage, $endPage) = $this->getPageRange();
|
||||
for ($i = $beginPage; $i <= $endPage; ++$i) {
|
||||
$buttons[] = $this->renderPageButton($i + 1, $i, null, $this->disableCurrentPageButton && $i == $currentPage, $i == $currentPage);
|
||||
}
|
||||
|
||||
// next page
|
||||
if ($this->nextPageLabel !== false) {
|
||||
if (($page = $currentPage + 1) >= $pageCount - 1) {
|
||||
$page = $pageCount - 1;
|
||||
}
|
||||
$buttons[] = $this->renderPageButton($this->nextPageLabel, $page, $this->nextPageCssClass, $currentPage >= $pageCount - 1, false);
|
||||
}
|
||||
|
||||
// last page
|
||||
$lastPageLabel = $this->lastPageLabel === true ? $pageCount : $this->lastPageLabel;
|
||||
if ($lastPageLabel !== false) {
|
||||
$buttons[] = $this->renderPageButton($lastPageLabel, $pageCount - 1, $this->lastPageCssClass, $currentPage >= $pageCount - 1, false);
|
||||
}
|
||||
|
||||
$options = $this->options;
|
||||
$tag = ArrayHelper::remove($options, 'tag', 'ul');
|
||||
return Html::tag($tag, implode("\n", $buttons), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a page button.
|
||||
* You may override this method to customize the generation of page buttons.
|
||||
* @param string $label the text label for the button
|
||||
* @param int $page the page number
|
||||
* @param string $class the CSS class for the page button.
|
||||
* @param bool $disabled whether this page button is disabled
|
||||
* @param bool $active whether this page button is active
|
||||
* @return string the rendering result
|
||||
*/
|
||||
protected function renderPageButton($label, $page, $class, $disabled, $active)
|
||||
{
|
||||
$options = $this->linkContainerOptions;
|
||||
$linkWrapTag = ArrayHelper::remove($options, 'tag', 'li');
|
||||
Html::addCssClass($options, empty($class) ? $this->pageCssClass : $class);
|
||||
|
||||
if ($active) {
|
||||
Html::addCssClass($options, $this->activePageCssClass);
|
||||
}
|
||||
if ($disabled) {
|
||||
Html::addCssClass($options, $this->disabledPageCssClass);
|
||||
$disabledItemOptions = $this->disabledListItemSubTagOptions;
|
||||
$tag = ArrayHelper::remove($disabledItemOptions, 'tag', 'span');
|
||||
|
||||
return Html::tag($linkWrapTag, Html::tag($tag, $label, $disabledItemOptions), $options);
|
||||
}
|
||||
$linkOptions = $this->linkOptions;
|
||||
$linkOptions['data-page'] = $page;
|
||||
|
||||
return Html::tag($linkWrapTag, Html::a($label, $this->pagination->createUrl($page), $linkOptions), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array the begin and end pages that need to be displayed.
|
||||
*/
|
||||
protected function getPageRange()
|
||||
{
|
||||
$currentPage = $this->pagination->getPage();
|
||||
$pageCount = $this->pagination->getPageCount();
|
||||
|
||||
$beginPage = max(0, $currentPage - (int) ($this->maxButtonCount / 2));
|
||||
if (($endPage = $beginPage + $this->maxButtonCount - 1) >= $pageCount) {
|
||||
$endPage = $pageCount - 1;
|
||||
$beginPage = max(0, $endPage - $this->maxButtonCount + 1);
|
||||
}
|
||||
|
||||
return [$beginPage, $endPage];
|
||||
}
|
||||
}
|
||||
86
vendor/yiisoft/yii2/widgets/LinkSorter.php
vendored
Normal file
86
vendor/yiisoft/yii2/widgets/LinkSorter.php
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\widgets;
|
||||
|
||||
use Yii;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\base\Widget;
|
||||
use yii\data\Sort;
|
||||
use yii\helpers\Html;
|
||||
|
||||
/**
|
||||
* LinkSorter renders a list of sort links for the given sort definition.
|
||||
*
|
||||
* LinkSorter will generate a hyperlink for every attribute declared in [[sort]].
|
||||
*
|
||||
* For more details and usage information on LinkSorter, see the [guide article on sorting](guide:output-sorting).
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class LinkSorter extends Widget
|
||||
{
|
||||
/**
|
||||
* @var Sort the sort definition
|
||||
*/
|
||||
public $sort;
|
||||
/**
|
||||
* @var array list of the attributes that support sorting. If not set, it will be determined
|
||||
* using [[Sort::attributes]].
|
||||
*/
|
||||
public $attributes;
|
||||
/**
|
||||
* @var array HTML attributes for the sorter container tag.
|
||||
* @see \yii\helpers\Html::ul() for special attributes.
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
*/
|
||||
public $options = ['class' => 'sorter'];
|
||||
/**
|
||||
* @var array HTML attributes for the link in a sorter container tag which are passed to [[Sort::link()]].
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
* @since 2.0.6
|
||||
*/
|
||||
public $linkOptions = [];
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the sorter.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
|
||||
if ($this->sort === null) {
|
||||
throw new InvalidConfigException('The "sort" property must be set.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the widget.
|
||||
* This method renders the sort links.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
echo $this->renderSortLinks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the sort links.
|
||||
* @return string the rendering result
|
||||
*/
|
||||
protected function renderSortLinks()
|
||||
{
|
||||
$attributes = empty($this->attributes) ? array_keys($this->sort->attributes) : $this->attributes;
|
||||
$links = [];
|
||||
foreach ($attributes as $name) {
|
||||
$links[] = $this->sort->link($name, $this->linkOptions);
|
||||
}
|
||||
|
||||
return Html::ul($links, array_merge($this->options, ['encode' => false]));
|
||||
}
|
||||
}
|
||||
205
vendor/yiisoft/yii2/widgets/ListView.php
vendored
Normal file
205
vendor/yiisoft/yii2/widgets/ListView.php
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\widgets;
|
||||
|
||||
use Closure;
|
||||
use yii\helpers\ArrayHelper;
|
||||
use yii\helpers\Html;
|
||||
|
||||
/**
|
||||
* The ListView widget is used to display data from data
|
||||
* provider. Each data model is rendered using the view
|
||||
* specified.
|
||||
*
|
||||
* For more details and usage information on ListView, see the [guide article on data widgets](guide:output-data-widgets).
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class ListView extends BaseListView
|
||||
{
|
||||
/**
|
||||
* @var array|Closure the HTML attributes for the container of the rendering result of each data model.
|
||||
* This can be either an array specifying the common HTML attributes for rendering each data item,
|
||||
* or an anonymous function that returns an array of the HTML attributes. The anonymous function will be
|
||||
* called once for every data model returned by [[dataProvider]].
|
||||
* The "tag" element specifies the tag name of the container element and defaults to "div".
|
||||
* If "tag" is false, it means no container element will be rendered.
|
||||
*
|
||||
* If this property is specified as an anonymous function, it should have the following signature:
|
||||
*
|
||||
* ```php
|
||||
* function ($model, $key, $index, $widget)
|
||||
* ```
|
||||
*
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
*/
|
||||
public $itemOptions = [];
|
||||
/**
|
||||
* @var string|callable the name of the view for rendering each data item, or a callback (e.g. an anonymous function)
|
||||
* for rendering each data item. If it specifies a view name, the following variables will
|
||||
* be available in the view:
|
||||
*
|
||||
* - `$model`: mixed, the data model
|
||||
* - `$key`: mixed, the key value associated with the data item
|
||||
* - `$index`: integer, the zero-based index of the data item in the items array returned by [[dataProvider]].
|
||||
* - `$widget`: ListView, this widget instance
|
||||
*
|
||||
* Note that the view name is resolved into the view file by the current context of the [[view]] object.
|
||||
*
|
||||
* If this property is specified as a callback, it should have the following signature:
|
||||
*
|
||||
* ```php
|
||||
* function ($model, $key, $index, $widget)
|
||||
* ```
|
||||
*/
|
||||
public $itemView;
|
||||
/**
|
||||
* @var array additional parameters to be passed to [[itemView]] when it is being rendered.
|
||||
* This property is used only when [[itemView]] is a string representing a view name.
|
||||
*/
|
||||
public $viewParams = [];
|
||||
/**
|
||||
* @var string the HTML code to be displayed between any two consecutive items.
|
||||
*/
|
||||
public $separator = "\n";
|
||||
/**
|
||||
* @var array the HTML attributes for the container tag of the list view.
|
||||
* The "tag" element specifies the tag name of the container element and defaults to "div".
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
*/
|
||||
public $options = ['class' => 'list-view'];
|
||||
/**
|
||||
* @var Closure an anonymous function that is called once BEFORE rendering each data model.
|
||||
* It should have the following signature:
|
||||
*
|
||||
* ```php
|
||||
* function ($model, $key, $index, $widget)
|
||||
* ```
|
||||
*
|
||||
* - `$model`: the current data model being rendered
|
||||
* - `$key`: the key value associated with the current data model
|
||||
* - `$index`: the zero-based index of the data model in the model array returned by [[dataProvider]]
|
||||
* - `$widget`: the ListView object
|
||||
*
|
||||
* The return result of the function will be rendered directly.
|
||||
* Note: If the function returns `null`, nothing will be rendered before the item.
|
||||
* @see renderBeforeItem
|
||||
* @since 2.0.11
|
||||
*/
|
||||
public $beforeItem;
|
||||
/**
|
||||
* @var Closure an anonymous function that is called once AFTER rendering each data model.
|
||||
*
|
||||
* It should have the same signature as [[beforeItem]].
|
||||
*
|
||||
* The return result of the function will be rendered directly.
|
||||
* Note: If the function returns `null`, nothing will be rendered after the item.
|
||||
* @see renderAfterItem
|
||||
* @since 2.0.11
|
||||
*/
|
||||
public $afterItem;
|
||||
|
||||
|
||||
/**
|
||||
* Renders all data models.
|
||||
* @return string the rendering result
|
||||
*/
|
||||
public function renderItems()
|
||||
{
|
||||
$models = $this->dataProvider->getModels();
|
||||
$keys = $this->dataProvider->getKeys();
|
||||
$rows = [];
|
||||
foreach (array_values($models) as $index => $model) {
|
||||
$key = $keys[$index];
|
||||
if (($before = $this->renderBeforeItem($model, $key, $index)) !== null) {
|
||||
$rows[] = $before;
|
||||
}
|
||||
|
||||
$rows[] = $this->renderItem($model, $key, $index);
|
||||
|
||||
if (($after = $this->renderAfterItem($model, $key, $index)) !== null) {
|
||||
$rows[] = $after;
|
||||
}
|
||||
}
|
||||
|
||||
return implode($this->separator, $rows);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls [[beforeItem]] closure, returns execution result.
|
||||
* If [[beforeItem]] is not a closure, `null` will be returned.
|
||||
*
|
||||
* @param mixed $model the data model to be rendered
|
||||
* @param mixed $key the key value associated with the data model
|
||||
* @param int $index the zero-based index of the data model in the model array returned by [[dataProvider]].
|
||||
* @return string|null [[beforeItem]] call result or `null` when [[beforeItem]] is not a closure
|
||||
* @see beforeItem
|
||||
* @since 2.0.11
|
||||
*/
|
||||
protected function renderBeforeItem($model, $key, $index)
|
||||
{
|
||||
if ($this->beforeItem instanceof Closure) {
|
||||
return call_user_func($this->beforeItem, $model, $key, $index, $this);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls [[afterItem]] closure, returns execution result.
|
||||
* If [[afterItem]] is not a closure, `null` will be returned.
|
||||
*
|
||||
* @param mixed $model the data model to be rendered
|
||||
* @param mixed $key the key value associated with the data model
|
||||
* @param int $index the zero-based index of the data model in the model array returned by [[dataProvider]].
|
||||
* @return string|null [[afterItem]] call result or `null` when [[afterItem]] is not a closure
|
||||
* @see afterItem
|
||||
* @since 2.0.11
|
||||
*/
|
||||
protected function renderAfterItem($model, $key, $index)
|
||||
{
|
||||
if ($this->afterItem instanceof Closure) {
|
||||
return call_user_func($this->afterItem, $model, $key, $index, $this);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a single data model.
|
||||
* @param mixed $model the data model to be rendered
|
||||
* @param mixed $key the key value associated with the data model
|
||||
* @param int $index the zero-based index of the data model in the model array returned by [[dataProvider]].
|
||||
* @return string the rendering result
|
||||
*/
|
||||
public function renderItem($model, $key, $index)
|
||||
{
|
||||
if ($this->itemView === null) {
|
||||
$content = $key;
|
||||
} elseif (is_string($this->itemView)) {
|
||||
$content = $this->getView()->render($this->itemView, array_merge([
|
||||
'model' => $model,
|
||||
'key' => $key,
|
||||
'index' => $index,
|
||||
'widget' => $this,
|
||||
], $this->viewParams));
|
||||
} else {
|
||||
$content = call_user_func($this->itemView, $model, $key, $index, $this);
|
||||
}
|
||||
if ($this->itemOptions instanceof Closure) {
|
||||
$options = call_user_func($this->itemOptions, $model, $key, $index, $this);
|
||||
} else {
|
||||
$options = $this->itemOptions;
|
||||
}
|
||||
$tag = ArrayHelper::remove($options, 'tag', 'div');
|
||||
$options['data-key'] = is_array($key) ? json_encode($key, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) : (string) $key;
|
||||
|
||||
return Html::tag($tag, $content, $options);
|
||||
}
|
||||
}
|
||||
193
vendor/yiisoft/yii2/widgets/MaskedInput.php
vendored
Normal file
193
vendor/yiisoft/yii2/widgets/MaskedInput.php
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\widgets;
|
||||
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\helpers\Html;
|
||||
use yii\helpers\Json;
|
||||
use yii\web\JsExpression;
|
||||
use yii\web\View;
|
||||
|
||||
/**
|
||||
* MaskedInput generates a masked text input.
|
||||
*
|
||||
* MaskedInput is similar to [[Html::textInput()]] except that an input mask will be used to force users to enter
|
||||
* properly formatted data, such as phone numbers, social security numbers.
|
||||
*
|
||||
* To use MaskedInput, you must set the [[mask]] property. The following example
|
||||
* shows how to use MaskedInput to collect phone numbers:
|
||||
*
|
||||
* ```php
|
||||
* echo MaskedInput::widget([
|
||||
* 'name' => 'phone',
|
||||
* 'mask' => '999-999-9999',
|
||||
* ]);
|
||||
* ```
|
||||
*
|
||||
* You can also use this widget in an [[ActiveForm]] using the [[ActiveField::widget()|widget()]]
|
||||
* method, for example like this:
|
||||
*
|
||||
* ```php
|
||||
* <?= $form->field($model, 'from_date')->widget(\yii\widgets\MaskedInput::className(), [
|
||||
* 'mask' => '999-999-9999',
|
||||
* ]) ?>
|
||||
* ```
|
||||
*
|
||||
* The masked text field is implemented based on the
|
||||
* [jQuery input masked plugin](https://github.com/RobinHerbots/Inputmask).
|
||||
*
|
||||
* @author Kartik Visweswaran <kartikv2@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class MaskedInput extends InputWidget
|
||||
{
|
||||
/**
|
||||
* The name of the jQuery plugin to use for this widget.
|
||||
*/
|
||||
const PLUGIN_NAME = 'inputmask';
|
||||
|
||||
/**
|
||||
* @var string|array|JsExpression the input mask (e.g. '99/99/9999' for date input). The following characters
|
||||
* can be used in the mask and are predefined:
|
||||
*
|
||||
* - `a`: represents an alpha character (A-Z, a-z)
|
||||
* - `9`: represents a numeric character (0-9)
|
||||
* - `*`: represents an alphanumeric character (A-Z, a-z, 0-9)
|
||||
* - `[` and `]`: anything entered between the square brackets is considered optional user input. This is
|
||||
* based on the `optionalmarker` setting in [[clientOptions]].
|
||||
*
|
||||
* Additional definitions can be set through the [[definitions]] property.
|
||||
*/
|
||||
public $mask;
|
||||
/**
|
||||
* @var array custom mask definitions to use. Should be configured as `maskSymbol => settings`, where
|
||||
*
|
||||
* - `maskSymbol` is a string, containing a character to identify your mask definition and
|
||||
* - `settings` is an array, consisting of the following entries:
|
||||
* - `validator`: string, a JS regular expression or a JS function.
|
||||
* - `cardinality`: int, specifies how many characters are represented and validated for the definition.
|
||||
* - `prevalidator`: array, validate the characters before the definition cardinality is reached.
|
||||
* - `definitionSymbol`: string, allows shifting values from other definitions, with this `definitionSymbol`.
|
||||
*/
|
||||
public $definitions;
|
||||
/**
|
||||
* @var array custom aliases to use. Should be configured as `maskAlias => settings`, where
|
||||
*
|
||||
* - `maskAlias` is a string containing a text to identify your mask alias definition (e.g. 'phone') and
|
||||
* - `settings` is an array containing settings for the mask symbol, exactly similar to parameters as passed in [[clientOptions]].
|
||||
*/
|
||||
public $aliases;
|
||||
/**
|
||||
* @var array the JQuery plugin options for the input mask plugin.
|
||||
* @see https://github.com/RobinHerbots/Inputmask
|
||||
*/
|
||||
public $clientOptions = [];
|
||||
/**
|
||||
* @var array the HTML attributes for the input tag.
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
*/
|
||||
public $options = ['class' => 'form-control'];
|
||||
/**
|
||||
* @var string the type of the input tag. Currently only 'text' and 'tel' are supported.
|
||||
* @see https://github.com/RobinHerbots/Inputmask
|
||||
* @since 2.0.6
|
||||
*/
|
||||
public $type = 'text';
|
||||
|
||||
/**
|
||||
* @var string the hashed variable to store the pluginOptions
|
||||
*/
|
||||
protected $_hashVar;
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the widget.
|
||||
*
|
||||
* @throws InvalidConfigException if the "mask" property is not set.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if (empty($this->mask) && empty($this->clientOptions['alias'])) {
|
||||
throw new InvalidConfigException("Either the 'mask' property or the 'clientOptions[\"alias\"]' property must be set.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$this->registerClientScript();
|
||||
echo $this->renderInputHtml($this->type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a hashed variable to store the plugin `clientOptions`.
|
||||
*
|
||||
* Helps in reusing the variable for similar
|
||||
* options passed for other widgets on the same page. The following special data attribute will also be
|
||||
* added to the input field to allow accessing the client options via javascript:
|
||||
*
|
||||
* - 'data-plugin-inputmask' will store the hashed variable storing the plugin options.
|
||||
*
|
||||
* @param View $view the view instance
|
||||
* @author [Thiago Talma](https://github.com/thiagotalma)
|
||||
*/
|
||||
protected function hashPluginOptions($view)
|
||||
{
|
||||
$encOptions = empty($this->clientOptions) ? '{}' : Json::htmlEncode($this->clientOptions);
|
||||
$this->_hashVar = self::PLUGIN_NAME . '_' . hash('crc32', $encOptions);
|
||||
$this->options['data-plugin-' . self::PLUGIN_NAME] = $this->_hashVar;
|
||||
$view->registerJs("var {$this->_hashVar} = {$encOptions};", View::POS_HEAD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes client options.
|
||||
*/
|
||||
protected function initClientOptions()
|
||||
{
|
||||
$options = $this->clientOptions;
|
||||
foreach ($options as $key => $value) {
|
||||
if (
|
||||
!$value instanceof JsExpression
|
||||
&& in_array($key, [
|
||||
'oncomplete', 'onincomplete', 'oncleared', 'onKeyUp', 'onKeyDown', 'onBeforeMask',
|
||||
'onBeforePaste', 'onUnMask', 'isComplete', 'determineActiveMasksetIndex',
|
||||
], true)
|
||||
) {
|
||||
$options[$key] = new JsExpression($value);
|
||||
}
|
||||
}
|
||||
$this->clientOptions = $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the needed client script and options.
|
||||
*/
|
||||
public function registerClientScript()
|
||||
{
|
||||
$js = '';
|
||||
$view = $this->getView();
|
||||
$this->initClientOptions();
|
||||
if (!empty($this->mask)) {
|
||||
$this->clientOptions['mask'] = $this->mask;
|
||||
}
|
||||
$this->hashPluginOptions($view);
|
||||
if (is_array($this->definitions) && !empty($this->definitions)) {
|
||||
$js .= ucfirst(self::PLUGIN_NAME) . '.extendDefinitions(' . Json::htmlEncode($this->definitions) . ');';
|
||||
}
|
||||
if (is_array($this->aliases) && !empty($this->aliases)) {
|
||||
$js .= ucfirst(self::PLUGIN_NAME) . '.extendAliases(' . Json::htmlEncode($this->aliases) . ');';
|
||||
}
|
||||
$id = $this->options['id'];
|
||||
$js .= 'jQuery("#' . $id . '").' . self::PLUGIN_NAME . '(' . $this->_hashVar . ');';
|
||||
MaskedInputAsset::register($view);
|
||||
$view->registerJs($js);
|
||||
}
|
||||
}
|
||||
29
vendor/yiisoft/yii2/widgets/MaskedInputAsset.php
vendored
Normal file
29
vendor/yiisoft/yii2/widgets/MaskedInputAsset.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\widgets;
|
||||
|
||||
use yii\web\AssetBundle;
|
||||
|
||||
/**
|
||||
* The asset bundle for the [[MaskedInput]] widget.
|
||||
*
|
||||
* Includes client assets of [jQuery input mask plugin](https://github.com/RobinHerbots/Inputmask).
|
||||
*
|
||||
* @author Kartik Visweswaran <kartikv2@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class MaskedInputAsset extends AssetBundle
|
||||
{
|
||||
public $sourcePath = '@bower/inputmask/dist';
|
||||
public $js = [
|
||||
'jquery.inputmask.bundle.js',
|
||||
];
|
||||
public $depends = [
|
||||
'yii\web\YiiAsset',
|
||||
];
|
||||
}
|
||||
331
vendor/yiisoft/yii2/widgets/Menu.php
vendored
Normal file
331
vendor/yiisoft/yii2/widgets/Menu.php
vendored
Normal file
@@ -0,0 +1,331 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\widgets;
|
||||
|
||||
use Closure;
|
||||
use Yii;
|
||||
use yii\base\Widget;
|
||||
use yii\helpers\ArrayHelper;
|
||||
use yii\helpers\Html;
|
||||
use yii\helpers\Url;
|
||||
|
||||
/**
|
||||
* Menu displays a multi-level menu using nested HTML lists.
|
||||
*
|
||||
* The main property of Menu is [[items]], which specifies the possible items in the menu.
|
||||
* A menu item can contain sub-items which specify the sub-menu under that menu item.
|
||||
*
|
||||
* Menu checks the current route and request parameters to toggle certain menu items
|
||||
* with active state.
|
||||
*
|
||||
* Note that Menu only renders the HTML tags about the menu. It does do any styling.
|
||||
* You are responsible to provide CSS styles to make it look like a real menu.
|
||||
*
|
||||
* The following example shows how to use Menu:
|
||||
*
|
||||
* ```php
|
||||
* echo Menu::widget([
|
||||
* 'items' => [
|
||||
* // Important: you need to specify url as 'controller/action',
|
||||
* // not just as 'controller' even if default action is used.
|
||||
* ['label' => 'Home', 'url' => ['site/index']],
|
||||
* // 'Products' menu item will be selected as long as the route is 'product/index'
|
||||
* ['label' => 'Products', 'url' => ['product/index'], 'items' => [
|
||||
* ['label' => 'New Arrivals', 'url' => ['product/index', 'tag' => 'new']],
|
||||
* ['label' => 'Most Popular', 'url' => ['product/index', 'tag' => 'popular']],
|
||||
* ]],
|
||||
* ['label' => 'Login', 'url' => ['site/login'], 'visible' => Yii::$app->user->isGuest],
|
||||
* ],
|
||||
* ]);
|
||||
* ```
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class Menu extends Widget
|
||||
{
|
||||
/**
|
||||
* @var array list of menu items. Each menu item should be an array of the following structure:
|
||||
*
|
||||
* - label: string, optional, specifies the menu item label. When [[encodeLabels]] is true, the label
|
||||
* will be HTML-encoded. If the label is not specified, an empty string will be used.
|
||||
* - encode: boolean, optional, whether this item`s label should be HTML-encoded. This param will override
|
||||
* global [[encodeLabels]] param.
|
||||
* - url: string or array, optional, specifies the URL of the menu item. It will be processed by [[Url::to]].
|
||||
* When this is set, the actual menu item content will be generated using [[linkTemplate]];
|
||||
* otherwise, [[labelTemplate]] will be used.
|
||||
* - visible: boolean, optional, whether this menu item is visible. Defaults to true.
|
||||
* - items: array, optional, specifies the sub-menu items. Its format is the same as the parent items.
|
||||
* - active: boolean or Closure, optional, whether this menu item is in active state (currently selected).
|
||||
* When using a closure, its signature should be `function ($item, $hasActiveChild, $isItemActive, $widget)`.
|
||||
* Closure must return `true` if item should be marked as `active`, otherwise - `false`.
|
||||
* If a menu item is active, its CSS class will be appended with [[activeCssClass]].
|
||||
* If this option is not set, the menu item will be set active automatically when the current request
|
||||
* is triggered by `url`. For more details, please refer to [[isItemActive()]].
|
||||
* - template: string, optional, the template used to render the content of this menu item.
|
||||
* The token `{url}` will be replaced by the URL associated with this menu item,
|
||||
* and the token `{label}` will be replaced by the label of the menu item.
|
||||
* If this option is not set, [[linkTemplate]] or [[labelTemplate]] will be used instead.
|
||||
* - submenuTemplate: string, optional, the template used to render the list of sub-menus.
|
||||
* The token `{items}` will be replaced with the rendered sub-menu items.
|
||||
* If this option is not set, [[submenuTemplate]] will be used instead.
|
||||
* - options: array, optional, the HTML attributes for the menu container tag.
|
||||
*/
|
||||
public $items = [];
|
||||
/**
|
||||
* @var array list of HTML attributes shared by all menu [[items]]. If any individual menu item
|
||||
* specifies its `options`, it will be merged with this property before being used to generate the HTML
|
||||
* attributes for the menu item tag. The following special options are recognized:
|
||||
*
|
||||
* - tag: string, defaults to "li", the tag name of the item container tags.
|
||||
* Set to false to disable container tag.
|
||||
* See also [[\yii\helpers\Html::tag()]].
|
||||
*
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
*/
|
||||
public $itemOptions = [];
|
||||
/**
|
||||
* @var string the template used to render the body of a menu which is a link.
|
||||
* In this template, the token `{url}` will be replaced with the corresponding link URL;
|
||||
* while `{label}` will be replaced with the link text.
|
||||
* This property will be overridden by the `template` option set in individual menu items via [[items]].
|
||||
*/
|
||||
public $linkTemplate = '<a href="{url}">{label}</a>';
|
||||
/**
|
||||
* @var string the template used to render the body of a menu which is NOT a link.
|
||||
* In this template, the token `{label}` will be replaced with the label of the menu item.
|
||||
* This property will be overridden by the `template` option set in individual menu items via [[items]].
|
||||
*/
|
||||
public $labelTemplate = '{label}';
|
||||
/**
|
||||
* @var string the template used to render a list of sub-menus.
|
||||
* In this template, the token `{items}` will be replaced with the rendered sub-menu items.
|
||||
*/
|
||||
public $submenuTemplate = "\n<ul>\n{items}\n</ul>\n";
|
||||
/**
|
||||
* @var bool whether the labels for menu items should be HTML-encoded.
|
||||
*/
|
||||
public $encodeLabels = true;
|
||||
/**
|
||||
* @var string the CSS class to be appended to the active menu item.
|
||||
*/
|
||||
public $activeCssClass = 'active';
|
||||
/**
|
||||
* @var bool whether to automatically activate items according to whether their route setting
|
||||
* matches the currently requested route.
|
||||
* @see isItemActive()
|
||||
*/
|
||||
public $activateItems = true;
|
||||
/**
|
||||
* @var bool whether to activate parent menu items when one of the corresponding child menu items is active.
|
||||
* The activated parent menu items will also have its CSS classes appended with [[activeCssClass]].
|
||||
*/
|
||||
public $activateParents = false;
|
||||
/**
|
||||
* @var bool whether to hide empty menu items. An empty menu item is one whose `url` option is not
|
||||
* set and which has no visible child menu items.
|
||||
*/
|
||||
public $hideEmptyItems = true;
|
||||
/**
|
||||
* @var array the HTML attributes for the menu's container tag. The following special options are recognized:
|
||||
*
|
||||
* - tag: string, defaults to "ul", the tag name of the item container tags. Set to false to disable container tag.
|
||||
* See also [[\yii\helpers\Html::tag()]].
|
||||
*
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
*/
|
||||
public $options = [];
|
||||
/**
|
||||
* @var string the CSS class that will be assigned to the first item in the main menu or each submenu.
|
||||
* Defaults to null, meaning no such CSS class will be assigned.
|
||||
*/
|
||||
public $firstItemCssClass;
|
||||
/**
|
||||
* @var string the CSS class that will be assigned to the last item in the main menu or each submenu.
|
||||
* Defaults to null, meaning no such CSS class will be assigned.
|
||||
*/
|
||||
public $lastItemCssClass;
|
||||
/**
|
||||
* @var string the route used to determine if a menu item is active or not.
|
||||
* If not set, it will use the route of the current request.
|
||||
* @see params
|
||||
* @see isItemActive()
|
||||
*/
|
||||
public $route;
|
||||
/**
|
||||
* @var array the parameters used to determine if a menu item is active or not.
|
||||
* If not set, it will use `$_GET`.
|
||||
* @see route
|
||||
* @see isItemActive()
|
||||
*/
|
||||
public $params;
|
||||
|
||||
|
||||
/**
|
||||
* Renders the menu.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
if ($this->route === null && Yii::$app->controller !== null) {
|
||||
$this->route = Yii::$app->controller->getRoute();
|
||||
}
|
||||
if ($this->params === null) {
|
||||
$this->params = Yii::$app->request->getQueryParams();
|
||||
}
|
||||
$items = $this->normalizeItems($this->items, $hasActiveChild);
|
||||
if (!empty($items)) {
|
||||
$options = $this->options;
|
||||
$tag = ArrayHelper::remove($options, 'tag', 'ul');
|
||||
|
||||
echo Html::tag($tag, $this->renderItems($items), $options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively renders the menu items (without the container tag).
|
||||
* @param array $items the menu items to be rendered recursively
|
||||
* @return string the rendering result
|
||||
*/
|
||||
protected function renderItems($items)
|
||||
{
|
||||
$n = count($items);
|
||||
$lines = [];
|
||||
foreach ($items as $i => $item) {
|
||||
$options = array_merge($this->itemOptions, ArrayHelper::getValue($item, 'options', []));
|
||||
$tag = ArrayHelper::remove($options, 'tag', 'li');
|
||||
$class = [];
|
||||
if ($item['active']) {
|
||||
$class[] = $this->activeCssClass;
|
||||
}
|
||||
if ($i === 0 && $this->firstItemCssClass !== null) {
|
||||
$class[] = $this->firstItemCssClass;
|
||||
}
|
||||
if ($i === $n - 1 && $this->lastItemCssClass !== null) {
|
||||
$class[] = $this->lastItemCssClass;
|
||||
}
|
||||
Html::addCssClass($options, $class);
|
||||
|
||||
$menu = $this->renderItem($item);
|
||||
if (!empty($item['items'])) {
|
||||
$submenuTemplate = ArrayHelper::getValue($item, 'submenuTemplate', $this->submenuTemplate);
|
||||
$menu .= strtr($submenuTemplate, [
|
||||
'{items}' => $this->renderItems($item['items']),
|
||||
]);
|
||||
}
|
||||
$lines[] = Html::tag($tag, $menu, $options);
|
||||
}
|
||||
|
||||
return implode("\n", $lines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the content of a menu item.
|
||||
* Note that the container and the sub-menus are not rendered here.
|
||||
* @param array $item the menu item to be rendered. Please refer to [[items]] to see what data might be in the item.
|
||||
* @return string the rendering result
|
||||
*/
|
||||
protected function renderItem($item)
|
||||
{
|
||||
if (isset($item['url'])) {
|
||||
$template = ArrayHelper::getValue($item, 'template', $this->linkTemplate);
|
||||
|
||||
return strtr($template, [
|
||||
'{url}' => Html::encode(Url::to($item['url'])),
|
||||
'{label}' => $item['label'],
|
||||
]);
|
||||
}
|
||||
|
||||
$template = ArrayHelper::getValue($item, 'template', $this->labelTemplate);
|
||||
|
||||
return strtr($template, [
|
||||
'{label}' => $item['label'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the [[items]] property to remove invisible items and activate certain items.
|
||||
* @param array $items the items to be normalized.
|
||||
* @param bool $active whether there is an active child menu item.
|
||||
* @return array the normalized menu items
|
||||
*/
|
||||
protected function normalizeItems($items, &$active)
|
||||
{
|
||||
foreach ($items as $i => $item) {
|
||||
if (isset($item['visible']) && !$item['visible']) {
|
||||
unset($items[$i]);
|
||||
continue;
|
||||
}
|
||||
if (!isset($item['label'])) {
|
||||
$item['label'] = '';
|
||||
}
|
||||
$encodeLabel = isset($item['encode']) ? $item['encode'] : $this->encodeLabels;
|
||||
$items[$i]['label'] = $encodeLabel ? Html::encode($item['label']) : $item['label'];
|
||||
$hasActiveChild = false;
|
||||
if (isset($item['items'])) {
|
||||
$items[$i]['items'] = $this->normalizeItems($item['items'], $hasActiveChild);
|
||||
if (empty($items[$i]['items']) && $this->hideEmptyItems) {
|
||||
unset($items[$i]['items']);
|
||||
if (!isset($item['url'])) {
|
||||
unset($items[$i]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isset($item['active'])) {
|
||||
if ($this->activateParents && $hasActiveChild || $this->activateItems && $this->isItemActive($item)) {
|
||||
$active = $items[$i]['active'] = true;
|
||||
} else {
|
||||
$items[$i]['active'] = false;
|
||||
}
|
||||
} elseif ($item['active'] instanceof Closure) {
|
||||
$active = $items[$i]['active'] = call_user_func($item['active'], $item, $hasActiveChild, $this->isItemActive($item), $this);
|
||||
} elseif ($item['active']) {
|
||||
$active = true;
|
||||
}
|
||||
}
|
||||
|
||||
return array_values($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a menu item is active.
|
||||
* This is done by checking if [[route]] and [[params]] match that specified in the `url` option of the menu item.
|
||||
* When the `url` option of a menu item is specified in terms of an array, its first element is treated
|
||||
* as the route for the item and the rest of the elements are the associated parameters.
|
||||
* Only when its route and parameters match [[route]] and [[params]], respectively, will a menu item
|
||||
* be considered active.
|
||||
* @param array $item the menu item to be checked
|
||||
* @return bool whether the menu item is active
|
||||
*/
|
||||
protected function isItemActive($item)
|
||||
{
|
||||
if (isset($item['url']) && is_array($item['url']) && isset($item['url'][0])) {
|
||||
$route = Yii::getAlias($item['url'][0]);
|
||||
if ($route[0] !== '/' && Yii::$app->controller) {
|
||||
$route = Yii::$app->controller->module->getUniqueId() . '/' . $route;
|
||||
}
|
||||
if (ltrim($route, '/') !== $this->route) {
|
||||
return false;
|
||||
}
|
||||
unset($item['url']['#']);
|
||||
if (count($item['url']) > 1) {
|
||||
$params = $item['url'];
|
||||
unset($params[0]);
|
||||
foreach ($params as $name => $value) {
|
||||
if ($value !== null && (!isset($this->params[$name]) || $this->params[$name] != $value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
217
vendor/yiisoft/yii2/widgets/Pjax.php
vendored
Normal file
217
vendor/yiisoft/yii2/widgets/Pjax.php
vendored
Normal file
@@ -0,0 +1,217 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\widgets;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Widget;
|
||||
use yii\helpers\ArrayHelper;
|
||||
use yii\helpers\Html;
|
||||
use yii\helpers\Json;
|
||||
use yii\web\Response;
|
||||
|
||||
/**
|
||||
* Pjax is a widget integrating the [pjax](https://github.com/yiisoft/jquery-pjax) jQuery plugin.
|
||||
*
|
||||
* Pjax only deals with the content enclosed between its [[begin()]] and [[end()]] calls, called the *body content* of the widget.
|
||||
* By default, any link click or form submission (for those forms with `data-pjax` attribute) within the body content
|
||||
* will trigger an AJAX request. In responding to the AJAX request, Pjax will send the updated body content (based
|
||||
* on the AJAX request) to the client which will replace the old content with the new one. The browser's URL will then
|
||||
* be updated using pushState. The whole process requires no reloading of the layout or resources (js, css).
|
||||
*
|
||||
* You may configure [[linkSelector]] to specify which links should trigger pjax, and configure [[formSelector]]
|
||||
* to specify which form submission may trigger pjax.
|
||||
*
|
||||
* You may disable pjax for a specific link inside the container by adding `data-pjax="0"` attribute to this link.
|
||||
*
|
||||
* The following example shows how to use Pjax with the [[\yii\grid\GridView]] widget so that the grid pagination,
|
||||
* sorting and filtering can be done via pjax:
|
||||
*
|
||||
* ```php
|
||||
* use yii\widgets\Pjax;
|
||||
*
|
||||
* Pjax::begin();
|
||||
* echo GridView::widget([...]);
|
||||
* Pjax::end();
|
||||
* ```
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class Pjax extends Widget
|
||||
{
|
||||
/**
|
||||
* @var array the HTML attributes for the widget container tag. The following special options are recognized:
|
||||
*
|
||||
* - `tag`: string, the tag name for the container. Defaults to `div`
|
||||
* This option is available since version 2.0.7.
|
||||
* See also [[\yii\helpers\Html::tag()]].
|
||||
*
|
||||
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
|
||||
*/
|
||||
public $options = [];
|
||||
/**
|
||||
* @var string|false the jQuery selector of the links that should trigger pjax requests.
|
||||
* If not set, all links within the enclosed content of Pjax will trigger pjax requests.
|
||||
* If set to false, no code will be registered to handle links.
|
||||
* Note that if the response to the pjax request is a full page, a normal request will be sent again.
|
||||
*/
|
||||
public $linkSelector;
|
||||
/**
|
||||
* @var string|false the jQuery selector of the forms whose submissions should trigger pjax requests.
|
||||
* If not set, all forms with `data-pjax` attribute within the enclosed content of Pjax will trigger pjax requests.
|
||||
* If set to false, no code will be registered to handle forms.
|
||||
* Note that if the response to the pjax request is a full page, a normal request will be sent again.
|
||||
*/
|
||||
public $formSelector;
|
||||
/**
|
||||
* @var string The jQuery event that will trigger form handler. Defaults to "submit".
|
||||
* @since 2.0.9
|
||||
*/
|
||||
public $submitEvent = 'submit';
|
||||
/**
|
||||
* @var bool whether to enable push state.
|
||||
*/
|
||||
public $enablePushState = true;
|
||||
/**
|
||||
* @var bool whether to enable replace state.
|
||||
*/
|
||||
public $enableReplaceState = false;
|
||||
/**
|
||||
* @var int pjax timeout setting (in milliseconds). This timeout is used when making AJAX requests.
|
||||
* Use a bigger number if your server is slow. If the server does not respond within the timeout,
|
||||
* a full page load will be triggered.
|
||||
*/
|
||||
public $timeout = 1000;
|
||||
/**
|
||||
* @var bool|int how to scroll the page when pjax response is received. If false, no page scroll will be made.
|
||||
* Use a number if you want to scroll to a particular place.
|
||||
*/
|
||||
public $scrollTo = false;
|
||||
/**
|
||||
* @var array additional options to be passed to the pjax JS plugin. Please refer to the
|
||||
* [pjax project page](https://github.com/yiisoft/jquery-pjax) for available options.
|
||||
*/
|
||||
public $clientOptions;
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @internal
|
||||
*/
|
||||
public static $counter = 0;
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $autoIdPrefix = 'p';
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if (!isset($this->options['id'])) {
|
||||
$this->options['id'] = $this->getId();
|
||||
}
|
||||
|
||||
if ($this->requiresPjax()) {
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
$view = $this->getView();
|
||||
$view->clear();
|
||||
$view->beginPage();
|
||||
$view->head();
|
||||
$view->beginBody();
|
||||
if ($view->title !== null) {
|
||||
echo Html::tag('title', Html::encode($view->title));
|
||||
}
|
||||
} else {
|
||||
$options = $this->options;
|
||||
$tag = ArrayHelper::remove($options, 'tag', 'div');
|
||||
echo Html::beginTag($tag, array_merge([
|
||||
'data-pjax-container' => '',
|
||||
'data-pjax-push-state' => $this->enablePushState,
|
||||
'data-pjax-replace-state' => $this->enableReplaceState,
|
||||
'data-pjax-timeout' => $this->timeout,
|
||||
'data-pjax-scrollto' => $this->scrollTo,
|
||||
], $options));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
if (!$this->requiresPjax()) {
|
||||
echo Html::endTag(ArrayHelper::remove($this->options, 'tag', 'div'));
|
||||
$this->registerClientScript();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$view = $this->getView();
|
||||
$view->endBody();
|
||||
|
||||
$view->endPage(true);
|
||||
|
||||
$content = ob_get_clean();
|
||||
|
||||
// only need the content enclosed within this widget
|
||||
$response = Yii::$app->getResponse();
|
||||
$response->clearOutputBuffers();
|
||||
$response->setStatusCode(200);
|
||||
$response->format = Response::FORMAT_HTML;
|
||||
$response->content = $content;
|
||||
$response->headers->setDefault('X-Pjax-Url', Yii::$app->request->url);
|
||||
$response->send();
|
||||
|
||||
Yii::$app->end();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool whether the current request requires pjax response from this widget
|
||||
*/
|
||||
protected function requiresPjax()
|
||||
{
|
||||
$headers = Yii::$app->getRequest()->getHeaders();
|
||||
|
||||
return $headers->get('X-Pjax') && explode(' ', $headers->get('X-Pjax-Container'))[0] === '#' . $this->options['id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the needed JavaScript.
|
||||
*/
|
||||
public function registerClientScript()
|
||||
{
|
||||
$id = $this->options['id'];
|
||||
$this->clientOptions['push'] = $this->enablePushState;
|
||||
$this->clientOptions['replace'] = $this->enableReplaceState;
|
||||
$this->clientOptions['timeout'] = $this->timeout;
|
||||
$this->clientOptions['scrollTo'] = $this->scrollTo;
|
||||
if (!isset($this->clientOptions['container'])) {
|
||||
$this->clientOptions['container'] = "#$id";
|
||||
}
|
||||
$options = Json::htmlEncode($this->clientOptions);
|
||||
$js = '';
|
||||
if ($this->linkSelector !== false) {
|
||||
$linkSelector = Json::htmlEncode($this->linkSelector !== null ? $this->linkSelector : '#' . $id . ' a');
|
||||
$js .= "jQuery(document).pjax($linkSelector, $options);";
|
||||
}
|
||||
if ($this->formSelector !== false) {
|
||||
$formSelector = Json::htmlEncode($this->formSelector !== null ? $this->formSelector : '#' . $id . ' form[data-pjax]');
|
||||
$submitEvent = Json::htmlEncode($this->submitEvent);
|
||||
$js .= "\njQuery(document).on($submitEvent, $formSelector, function (event) {jQuery.pjax.submit(event, $options);});";
|
||||
}
|
||||
$view = $this->getView();
|
||||
PjaxAsset::register($view);
|
||||
|
||||
if ($js !== '') {
|
||||
$view->registerJs($js);
|
||||
}
|
||||
}
|
||||
}
|
||||
27
vendor/yiisoft/yii2/widgets/PjaxAsset.php
vendored
Normal file
27
vendor/yiisoft/yii2/widgets/PjaxAsset.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\widgets;
|
||||
|
||||
use yii\web\AssetBundle;
|
||||
|
||||
/**
|
||||
* This asset bundle provides the javascript files required by [[Pjax]] widget.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class PjaxAsset extends AssetBundle
|
||||
{
|
||||
public $sourcePath = '@bower/yii2-pjax';
|
||||
public $js = [
|
||||
'jquery.pjax.js',
|
||||
];
|
||||
public $depends = [
|
||||
'yii\web\YiiAsset',
|
||||
];
|
||||
}
|
||||
70
vendor/yiisoft/yii2/widgets/Spaceless.php
vendored
Normal file
70
vendor/yiisoft/yii2/widgets/Spaceless.php
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\widgets;
|
||||
|
||||
use yii\base\Widget;
|
||||
|
||||
/**
|
||||
* Spaceless widget removes whitespace characters between HTML tags. Whitespaces within HTML tags
|
||||
* or in a plain text are always left untouched.
|
||||
*
|
||||
* Usage example:
|
||||
*
|
||||
* ```php
|
||||
* <body>
|
||||
* <?php Spaceless::begin(); ?>
|
||||
* <div class="nav-bar">
|
||||
* <!-- tags -->
|
||||
* </div>
|
||||
* <div class="content">
|
||||
* <!-- tags -->
|
||||
* </div>
|
||||
* <?php Spaceless::end(); ?>
|
||||
* </body>
|
||||
* ```
|
||||
*
|
||||
* This example will generate the following HTML:
|
||||
*
|
||||
* ```html
|
||||
* <body>
|
||||
* <div class="nav-bar"><!-- tags --></div><div class="content"><!-- tags --></div></body>
|
||||
* ```
|
||||
*
|
||||
* This method is not designed for content compression (you should use `gzip` output compression to
|
||||
* achieve it). Main intention is to strip out extra whitespace characters between HTML tags in order
|
||||
* to avoid browser rendering quirks in some circumstances (e.g. newlines between inline-block elements).
|
||||
*
|
||||
* Note, never use this method with `pre` or `textarea` tags. It's not that trivial to deal with such tags
|
||||
* as it may seem at first sight. For this case you should consider using
|
||||
* [HTML Tidy Project](http://tidy.sourceforge.net/) instead.
|
||||
*
|
||||
* @see http://tidy.sourceforge.net/
|
||||
* @author resurtm <resurtm@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class Spaceless extends Widget
|
||||
{
|
||||
/**
|
||||
* Starts capturing an output to be cleaned from whitespace characters between HTML tags.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the end of content to be cleaned from whitespace characters between HTML tags.
|
||||
* Stops capturing an output and echoes cleaned result.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
echo trim(preg_replace('/>\s+</', '><', ob_get_clean()));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user