Commit 30d70be0 by Qiang Xue

Finished Html helper.

parent d2fcc69b
......@@ -382,6 +382,15 @@ class Application extends Module
}
/**
* Returns the URL manager for this application.
* @return \yii\web\UrlManager the URL manager for this application.
*/
public function getUrlManager()
{
return $this->getComponent('urlManager');
}
/**
* Returns the internationalization (i18n) component
* @return \yii\i18n\I18N the internationalization component
*/
......@@ -411,8 +420,8 @@ class Application extends Module
'i18n' => array(
'class' => 'yii\i18n\I18N',
),
'securityManager' => array(
'class' => 'yii\base\SecurityManager',
'urlManager' => array(
'class' => 'yii\web\UrlManager',
),
));
}
......
......@@ -55,16 +55,16 @@ class ActiveRelation extends ActiveQuery
/**
* Specifies the relation associated with the pivot table.
* @param string $relationName the relation name. This refers to a relation declared in [[primaryModel]].
* @param callback $callback a PHP callback for customizing the relation associated with the pivot table.
* @param callable $callable a PHP callback for customizing the relation associated with the pivot table.
* Its signature should be `function($query)`, where `$query` is the query to be customized.
* @return ActiveRelation the relation object itself.
*/
public function via($relationName, $callback = null)
public function via($relationName, $callable = null)
{
$relation = $this->primaryModel->getRelation($relationName);
$this->via = array($relationName, $relation);
if ($callback !== null) {
call_user_func($callback, $relation);
if ($callable !== null) {
call_user_func($callable, $relation);
}
return $this;
}
......@@ -75,11 +75,11 @@ class ActiveRelation extends ActiveQuery
* @param array $link the link between the pivot table and the table associated with [[primaryModel]].
* The keys of the array represent the columns in the pivot table, and the values represent the columns
* in the [[primaryModel]] table.
* @param callback $callback a PHP callback for customizing the relation associated with the pivot table.
* @param callable $callable a PHP callback for customizing the relation associated with the pivot table.
* Its signature should be `function($query)`, where `$query` is the query to be customized.
* @return ActiveRelation
*/
public function viaTable($tableName, $link, $callback = null)
public function viaTable($tableName, $link, $callable = null)
{
$relation = new ActiveRelation(array(
'modelClass' => get_class($this->primaryModel),
......@@ -89,8 +89,8 @@ class ActiveRelation extends ActiveQuery
'asArray' => true,
));
$this->via = $relation;
if ($callback !== null) {
call_user_func($callback, $relation);
if ($callable !== null) {
call_user_func($callable, $relation);
}
return $this;
}
......
......@@ -281,33 +281,59 @@ class ArrayHelper
call_user_func_array('array_multisort', $args);
}
/**
* Encodes special characters in an array of strings into HTML entities.
* Both the array keys and values will be encoded if needed.
* Both the array keys and values will be encoded.
* If a value is an array, this method will also encode it recursively.
* @param array $data data to be encoded
* @param boolean $valuesOnly whether to encode array values only. If false,
* both the array keys and array values will be encoded.
* @param string $charset the charset that the data is using. If not set,
* [[\yii\base\Application::charset]] will be used.
* @return array the encoded data
* @see http://www.php.net/manual/en/function.htmlspecialchars.php
*/
public static function htmlEncode($data, $charset = null)
public static function htmlEncode($data, $valuesOnly = false, $charset = null)
{
if ($charset === null) {
$charset = Yii::$app->charset;
}
$d = array();
foreach ($data as $key => $value) {
if (is_string($key)) {
if (!$valuesOnly && is_string($key)) {
$key = htmlspecialchars($key, ENT_QUOTES, $charset);
}
if (is_string($value)) {
$value = htmlspecialchars($value, ENT_QUOTES, $charset);
$d[$key] = htmlspecialchars($value, ENT_QUOTES, $charset);
} elseif (is_array($value)) {
$d[$key] = static::htmlEncode($value, $charset);
}
}
return $d;
}
/**
* Decodes HTML entities into the corresponding characters in an array of strings.
* Both the array keys and values will be decoded.
* If a value is an array, this method will also decode it recursively.
* @param array $data data to be decoded
* @param boolean $valuesOnly whether to decode array values only. If false,
* both the array keys and array values will be decoded.
* @return array the decoded data
* @see http://www.php.net/manual/en/function.htmlspecialchars-decode.php
*/
public static function htmlDecode($data, $valuesOnly = false)
{
$d = array();
foreach ($data as $key => $value) {
if (!$valuesOnly && is_string($key)) {
$key = htmlspecialchars_decode($key, ENT_QUOTES);
}
if (is_string($value)) {
$d[$key] = htmlspecialchars_decode($value, ENT_QUOTES);
} elseif (is_array($value)) {
$value = static::htmlEncode($value);
$d[$key] = static::htmlDecode($value);
}
$d[$key] = $value;
}
return $d;
}
......
......@@ -8,8 +8,11 @@
namespace yii\util;
use Yii;
use yii\base\InvalidParamException;
/**
* Html provides a set of static methods for generating commonly used HTML tags.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
......@@ -22,6 +25,7 @@ class Html
public static $closeVoidElements = true;
/**
* @var array list of void elements (element name => 1)
* @see closeVoidElements
* @see http://www.w3.org/TR/html-markup/syntax.html#void-element
*/
public static $voidElements = array(
......@@ -43,9 +47,78 @@ class Html
'wbr' => 1,
);
/**
* @var boolean whether to render special attributes value. Defaults to true. Can be set to false for HTML5.
*/
public static $renderSpecialAttributesValue = true;
* @var boolean whether to show the values of boolean attributes in element tags.
* If false, only the attribute names will be generated.
* @see booleanAttributes
*/
public static $showBooleanAttributeValues = true;
/**
* @var array list of boolean attributes. The presence of a boolean attribute on
* an element represents the true value, and the absence of the attribute represents the false value.
* @see showBooleanAttributeValues
* @see http://www.w3.org/TR/html5/infrastructure.html#boolean-attributes
*/
public static $booleanAttributes = array(
'async' => 1,
'autofocus' => 1,
'autoplay' => 1,
'checked' => 1,
'controls' => 1,
'declare' => 1,
'default' => 1,
'defer' => 1,
'disabled' => 1,
'formnovalidate' => 1,
'hidden' => 1,
'ismap' => 1,
'loop' => 1,
'multiple' => 1,
'muted' => 1,
'nohref' => 1,
'noresize' => 1,
'novalidate' => 1,
'open' => 1,
'readonly' => 1,
'required' => 1,
'reversed' => 1,
'scoped' => 1,
'seamless' => 1,
'selected' => 1,
'typemustmatch' => 1,
);
/**
* @var array the preferred order of attributes in a tag. This mainly affects the order of the attributes
* that are rendered by [[renderAttributes()]].
*/
public static $attributeOrder = array(
'type',
'id',
'class',
'name',
'value',
'href',
'src',
'action',
'method',
'selected',
'checked',
'readonly',
'disabled',
'size',
'maxlength',
'width',
'height',
'rows',
'cols',
'alt',
'title',
'rel',
'media',
);
/**
......@@ -78,6 +151,7 @@ class Html
* Generates a complete HTML tag.
* @param string $name the tag name
* @param string $content the content to be enclosed between the start and end tags. It will not be HTML-encoded.
* If this is coming from end users, you should consider [[encode()]] it to prevent XSS attacks.
* @param array $attributes the element attributes. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned.
* @return string the generated HTML tag
......@@ -117,7 +191,7 @@ class Html
*/
public static function endTag($name)
{
return !static::$closeVoidElements && isset(static::$voidElements[strtolower($name)]) ? '' : "</$name>";
return "</$name>";
}
/**
......@@ -143,9 +217,7 @@ class Html
if (!isset($attributes['type'])) {
$attributes['type'] = 'text/css';
}
return static::beginTag('style', $attributes)
. "\n/*<![CDATA[*/\n{$content}\n/*]]>*/\n"
. static::endTag('style');
return static::tag('style', "\n/*<![CDATA[*/\n{$content}\n/*]]>*/\n", $attributes);
}
/**
......@@ -161,110 +233,77 @@ class Html
if (!isset($attributes['type'])) {
$attributes['type'] = 'text/javascript';
}
return static::beginTag('script', $attributes)
. "\n/*<![CDATA[*/\n{$content}\n/*]]>*/\n"
. static::endTag('script');
return static::tag('script', "\n/*<![CDATA[*/\n{$content}\n/*]]>*/\n", $attributes);
}
/**
* Registers a 'refresh' meta tag.
* This method can be invoked anywhere in a view. It will register a 'refresh'
* meta tag with {@link CClientScript} so that the page can be refreshed in
* the specified seconds.
* @param integer $seconds the number of seconds to wait before refreshing the page
* @param string $url the URL to which the page should be redirected to. If empty, it means the current page.
* @since 1.1.1
*/
public static function refresh($seconds, $url = '')
{
$content = "$seconds";
if ($url !== '') {
$content .= ';' . static::normalizeUrl($url);
}
Yii::app()->clientScript->registerMetaTag($content, null, 'refresh');
}
/**
* Links to the specified CSS file.
* @param string $url the CSS URL
* @param string $media the media that this CSS should apply to.
* @return string the CSS link.
* Generates a link tag that refers to an external CSS file.
* @param array|string $url the URL of the external CSS file. This parameter will be processed by [[url()]].
* @param array $attributes the attributes of the link tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned.
* @return string the generated link tag
* @see url
*/
public static function cssFile($url, $media = '')
public static function cssFile($url, $attributes = array())
{
return CHtml::linkTag('stylesheet', 'text/css', $url, $media !== '' ? $media : null);
$attributes['rel'] = 'stylesheet';
$attributes['type'] = 'text/css';
$attributes['href'] = static::url($url);
return static::tag('link', '', $attributes);
}
/**
* Encloses the given JavaScript within a script tag.
* @param string $text the JavaScript to be enclosed
* @return string the enclosed JavaScript
* Generates a script tag that refers to an external JavaScript file.
* @param string $url the URL of the external JavaScript file. This parameter will be processed by [[url()]].
* @param array $attributes the attributes of the script tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned.
* @return string the generated script tag
* @see url
*/
public static function script($text)
public static function jsFile($url, $attributes = array())
{
return "<script type=\"text/javascript\">\n/*<![CDATA[*/\n{$text}\n/*]]>*/\n</script>";
$attributes['type'] = 'text/javascript';
$attributes['src'] = static::url($url);
return static::tag('script', '', $attributes);
}
/**
* Includes a JavaScript file.
* @param string $url URL for the JavaScript file
* @return string the JavaScript file tag
* Generates a form start tag.
* @param array|string $action the form action URL. This parameter will be processed by [[url()]].
* @param string $method form method, either "post" or "get" (case-insensitive)
* @param array $attributes the attributes of the form tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned.
* @return string the generated form start tag.
* @see endForm
*/
public static function scriptFile($url)
public static function beginForm($action = '', $method = 'post', $attributes = array())
{
return '<script type="text/javascript" src="' . static::encode($url) . '"></script>';
}
$attributes['action'] = $url = static::url($action);
$attributes['method'] = $method;
/**
* Generates an opening form tag.
* This is a shortcut to {@link beginForm}.
* @param mixed $action the form action URL (see {@link normalizeUrl} for details about this parameter.)
* @param string $method form method (e.g. post, get)
* @param array $htmlOptions additional HTML attributes (see {@link tag}).
* @return string the generated form tag.
*/
public static function form($action = '', $method = 'post', $htmlOptions = array())
{
return static::beginForm($action, $method, $htmlOptions);
}
$form = static::beginTag('form', $attributes);
/**
* Generates an opening form tag.
* Note, only the open tag is generated. A close tag should be placed manually
* at the end of the form.
* @param mixed $action the form action URL (see {@link normalizeUrl} for details about this parameter.)
* @param string $method form method (e.g. post, get)
* @param array $htmlOptions additional HTML attributes (see {@link tag}).
* @return string the generated form tag.
* @see endForm
*/
public static function beginForm($action = '', $method = 'post', $htmlOptions = array())
{
$htmlOptions['action'] = $url = static::normalizeUrl($action);
$htmlOptions['method'] = $method;
$form = static::tag('form', $htmlOptions, false, false);
// query parameters in the action are ignored for GET method
// we use hidden fields to add them back
$hiddens = array();
if (!strcasecmp($method, 'get') && ($pos = strpos($url, '?')) !== false) {
foreach (explode('&', substr($url, $pos + 1)) as $pair) {
if (($pos = strpos($pair, '=')) !== false) {
$hiddens[] = static::hiddenField(urldecode(substr($pair, 0, $pos)), urldecode(substr($pair, $pos + 1)), array('id' => false));
$hiddens[] = static::hiddenInput(urldecode(substr($pair, 0, $pos)), urldecode(substr($pair, $pos + 1)));
} else {
$hiddens[] = static::hiddenField(urldecode($pair), '', array('id' => false));
$hiddens[] = static::hiddenInput(urldecode($pair), '');
}
}
}
$request = Yii::app()->request;
if ($request->enableCsrfValidation && !strcasecmp($method, 'post')) {
$hiddens[] = static::hiddenField($request->csrfTokenName, $request->getCsrfToken(), array('id' => false));
}
if ($hiddens !== array()) {
$form .= "\n" . static::tag('div', array('style' => 'display:none'), implode("\n", $hiddens));
$form .= "\n" . implode("\n", $hiddens);
}
return $form;
}
/**
* Generates a closing form tag.
* Generates a form end tag.
* @return string the generated tag
* @see beginForm
*/
......@@ -275,854 +314,599 @@ class Html
/**
* Generates a hyperlink tag.
* @param string $text link body. It will NOT be HTML-encoded. Therefore you can pass in HTML code such as an image tag.
* @param mixed $url a URL or an action route that can be used to create a URL.
* See {@link normalizeUrl} for more details about how to specify this parameter.
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
* @param string $text link body. It will NOT be HTML-encoded. Therefore you can pass in HTML code
* such as an image tag. If this is is coming from end users, you should consider [[encode()]]
* it to prevent XSS attacks.
* @param array|string|null $url the URL for the hyperlink tag. This parameter will be processed by [[url()]]
* and will be used for the "href" attribute of the tag. If this parameter is null, the "href" attribute
* will not be generated.
* @param array $attributes the attributes of the hyperlink tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned.
* @return string the generated hyperlink
* @see normalizeUrl
* @see clientChange
* @see url
*/
public static function link($text, $url = '#', $htmlOptions = array())
public static function a($text, $url = null, $attributes = array())
{
if ($url !== '') {
$htmlOptions['href'] = static::normalizeUrl($url);
if ($url !== null) {
$attributes['href'] = static::url($url);
}
static::clientChange('click', $htmlOptions);
return static::tag('a', $htmlOptions, $text);
return static::tag('a', $text, $attributes);
}
/**
* Generates a mailto link.
* @param string $text link body. It will NOT be HTML-encoded. Therefore you can pass in HTML code such as an image tag.
* @param string $email email address. If this is empty, the first parameter (link body) will be treated as the email address.
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
* Generates a mailto hyperlink.
* @param string $text link body. It will NOT be HTML-encoded. Therefore you can pass in HTML code
* such as an image tag. If this is is coming from end users, you should consider [[encode()]]
* it to prevent XSS attacks.
* @param string $email email address. If this is null, the first parameter (link body) will be treated
* as the email address and used.
* @param array $attributes the attributes of the hyperlink tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned.
* @return string the generated mailto link
* @see clientChange
*/
public static function mailto($text, $email = '', $htmlOptions = array())
public static function mailto($text, $email = null, $attributes = array())
{
if ($email === '') {
$email = $text;
}
return static::link($text, 'mailto:' . $email, $htmlOptions);
return static::a($text, 'mailto:' . ($email === null ? $text : $email), $attributes);
}
/**
* Generates an image tag.
* @param string $src the image URL
* @param string $alt the alternative text display
* @param array $htmlOptions additional HTML attributes (see {@link tag}).
* @param string $src the image URL. This parameter will be processed by [[url()]].
* @param array $attributes the attributes of the image tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned.
* @return string the generated image tag
*/
public static function image($src, $alt = '', $htmlOptions = array())
public static function img($src, $attributes = array())
{
$htmlOptions['src'] = $src;
$htmlOptions['alt'] = $alt;
return static::tag('img', $htmlOptions);
$attributes['src'] = static::url($src);
if (!isset($attributes['alt'])) {
$attributes['alt'] = '';
}
return static::tag('img', null, $attributes);
}
/**
* Generates a button.
* @param string $label the button label
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
* @return string the generated button tag
* @see clientChange
* Generates a label tag.
* @param string $content label text. It will NOT be HTML-encoded. Therefore you can pass in HTML code
* such as an image tag. If this is is coming from end users, you should consider [[encode()]]
* it to prevent XSS attacks.
* @param string $for the ID of the HTML element that this label is associated with.
* If this is null, the "for" attribute will not be generated.
* @param array $attributes the attributes of the label tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned.
* @return string the generated label tag
*/
public static function button($name, $label = 'button', $htmlOptions = array())
public static function label($content, $for = null, $attributes = array())
{
if (!isset($htmlOptions['name'])) {
if (!array_key_exists('name', $htmlOptions)) {
$htmlOptions['name'] = static::ID_PREFIX . static::$count++;
}
}
if (!isset($htmlOptions['type'])) {
$htmlOptions['type'] = 'button';
}
if (!isset($htmlOptions['value'])) {
$htmlOptions['value'] = $label;
}
static::clientChange('click', $htmlOptions);
return static::tag('input', $htmlOptions);
$attributes['for'] = $for;
return static::tag('label', $content, $attributes);
}
/**
* Generates a button using HTML button tag.
* This method is similar to {@link button} except that it generates a 'button'
* tag instead of 'input' tag.
* @param string $label the button label. Note that this value will be directly inserted in the button element
* without being HTML-encoded.
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
* Generates a button tag.
* @param string $name the name attribute. If it is null, the name attribute will not be generated.
* @param string $value the value attribute. If it is null, the value attribute will not be generated.
* @param string $content the content enclosed within the button tag. It will NOT be HTML-encoded.
* Therefore you can pass in HTML code such as an image tag. If this is is coming from end users,
* you should consider [[encode()]] it to prevent XSS attacks.
* @param array $attributes the attributes of the button tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned.
* If the attributes does not contain "type", a default one with value "button" will be used.
* @return string the generated button tag
* @see clientChange
*/
public static function htmlButton($label = 'button', $htmlOptions = array())
public static function button($name = null, $value = null, $content = 'Button', $attributes = array())
{
if (!isset($htmlOptions['name'])) {
$htmlOptions['name'] = static::ID_PREFIX . static::$count++;
}
if (!isset($htmlOptions['type'])) {
$htmlOptions['type'] = 'button';
$attributes['name'] = $name;
$attributes['value'] = $value;
if (!isset($attributes['type'])) {
$attributes['type'] = 'button';
}
static::clientChange('click', $htmlOptions);
return static::tag('button', $htmlOptions, $label);
return static::tag('button', $content, $attributes);
}
/**
* Generates a submit button.
* @param string $label the button label
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
* @return string the generated button tag
* @see clientChange
* Generates a submit button tag.
* @param string $name the name attribute. If it is null, the name attribute will not be generated.
* @param string $value the value attribute. If it is null, the value attribute will not be generated.
* @param string $content the content enclosed within the button tag. It will NOT be HTML-encoded.
* Therefore you can pass in HTML code such as an image tag. If this is is coming from end users,
* you should consider [[encode()]] it to prevent XSS attacks.
* @param array $attributes the attributes of the button tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned.
* @return string the generated submit button tag
*/
public static function submitButton($label = 'submit', $htmlOptions = array())
public static function submitButton($name = null, $value = null, $content = 'Submit', $attributes = array())
{
$htmlOptions['type'] = 'submit';
return static::button($label, $htmlOptions);
$attributes['type'] = 'submit';
return static::button($name, $value, $content, $attributes);
}
/**
* Generates a reset button.
* @param string $label the button label
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
* @return string the generated button tag
* @see clientChange
* Generates a reset button tag.
* @param string $name the name attribute. If it is null, the name attribute will not be generated.
* @param string $value the value attribute. If it is null, the value attribute will not be generated.
* @param string $content the content enclosed within the button tag. It will NOT be HTML-encoded.
* Therefore you can pass in HTML code such as an image tag. If this is is coming from end users,
* you should consider [[encode()]] it to prevent XSS attacks.
* @param array $attributes the attributes of the button tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned.
* @return string the generated reset button tag
*/
public static function resetButton($label = 'reset', $htmlOptions = array())
public static function resetButton($name = null, $value = null, $content = 'Reset', $attributes = array())
{
$htmlOptions['type'] = 'reset';
return static::button($label, $htmlOptions);
$attributes['type'] = 'reset';
return static::button($name, $value, $content, $attributes);
}
/**
* Generates an image submit button.
* @param string $src the image URL
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
* Generates an input type of the given type.
* @param string $type the type attribute.
* @param string $name the name attribute. If it is null, the name attribute will not be generated.
* @param string $value the value attribute. If it is null, the value attribute will not be generated.
* @param array $attributes the attributes of the input tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned.
* @return string the generated input tag
*/
public static function input($type, $name = null, $value = null, $attributes = array())
{
$attributes['type'] = $type;
$attributes['name'] = $name;
$attributes['value'] = $value;
return static::tag('input', null, $attributes);
}
/**
* Generates an input button.
* @param string $name the name attribute.
* @param string $value the value attribute. If it is null, the value attribute will not be generated.
* @param array $attributes the attributes of the button tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned.
* @return string the generated button tag
* @see clientChange
*/
public static function imageButton($src, $htmlOptions = array())
public static function buttonInput($name, $value = 'Button', $attributes = array())
{
$htmlOptions['src'] = $src;
$htmlOptions['type'] = 'image';
return static::button('submit', $htmlOptions);
return static::input('button', $name, $value, $attributes);
}
/**
* Generates a link submit button.
* @param string $label the button label
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
* Generates a submit input button.
* @param string $name the name attribute. If it is null, the name attribute will not be generated.
* @param string $value the value attribute. If it is null, the value attribute will not be generated.
* @param array $attributes the attributes of the button tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned.
* @return string the generated button tag
* @see clientChange
*/
public static function linkButton($label = 'submit', $htmlOptions = array())
public static function submitInput($name = null, $value = 'Submit', $attributes = array())
{
if (!isset($htmlOptions['submit'])) {
$htmlOptions['submit'] = isset($htmlOptions['href']) ? $htmlOptions['href'] : '';
}
return static::link($label, '#', $htmlOptions);
return static::input('submit', $name, $value, $attributes);
}
/**
* Generates a label tag.
* @param string $label label text. Note, you should HTML-encode the text if needed.
* @param string $for the ID of the HTML element that this label is associated with.
* If this is false, the 'for' attribute for the label tag will not be rendered.
* @param array $htmlOptions additional HTML attributes.
* The following HTML option is recognized:
* <ul>
* <li>required: if this is set and is true, the label will be styled
* with CSS class 'required' (customizable with CHtml::$requiredCss),
* and be decorated with {@link CHtml::beforeRequiredLabel} and
* {@link CHtml::afterRequiredLabel}.</li>
* </ul>
* @return string the generated label tag
* Generates a reset input button.
* @param string $name the name attribute. If it is null, the name attribute will not be generated.
* @param string $value the value attribute. If it is null, the value attribute will not be generated.
* @param array $attributes the attributes of the button tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned.
* @return string the generated button tag
*/
public static function label($label, $for, $htmlOptions = array())
public static function resetInput($name = null, $value = 'Reset', $attributes = array())
{
if ($for === false) {
unset($htmlOptions['for']);
} else {
$htmlOptions['for'] = $for;
}
if (isset($htmlOptions['required'])) {
if ($htmlOptions['required']) {
if (isset($htmlOptions['class'])) {
$htmlOptions['class'] .= ' ' . static::$requiredCss;
} else {
$htmlOptions['class'] = static::$requiredCss;
}
$label = static::$beforeRequiredLabel . $label . static::$afterRequiredLabel;
}
unset($htmlOptions['required']);
}
return static::tag('label', $htmlOptions, $label);
return static::input('reset', $name, $value, $attributes);
}
/**
* Generates a text field input.
* @param string $name the input name
* @param string $value the input value
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
* @return string the generated input field
* @see clientChange
* @see inputField
* Generates a text input field.
* @param string $name the name attribute.
* @param string $value the value attribute. If it is null, the value attribute will not be generated.
* @param array $attributes the attributes of the input tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned.
* @return string the generated button tag
*/
public static function textField($name, $value = '', $htmlOptions = array())
public static function textInput($name, $value = null, $attributes = array())
{
static::clientChange('change', $htmlOptions);
return static::inputField('text', $name, $value, $htmlOptions);
return static::input('text', $name, $value, $attributes);
}
/**
* Generates a hidden input.
* @param string $name the input name
* @param string $value the input value
* @param array $htmlOptions additional HTML attributes (see {@link tag}).
* @return string the generated input field
* @see inputField
* Generates a hidden input field.
* @param string $name the name attribute.
* @param string $value the value attribute. If it is null, the value attribute will not be generated.
* @param array $attributes the attributes of the input tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned.
* @return string the generated button tag
*/
public static function hiddenField($name, $value = '', $htmlOptions = array())
public static function hiddenInput($name, $value = null, $attributes = array())
{
return static::inputField('hidden', $name, $value, $htmlOptions);
return static::input('hidden', $name, $value, $attributes);
}
/**
* Generates a password field input.
* @param string $name the input name
* @param string $value the input value
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
* @return string the generated input field
* @see clientChange
* @see inputField
* Generates a password input field.
* @param string $name the name attribute.
* @param string $value the value attribute. If it is null, the value attribute will not be generated.
* @param array $attributes the attributes of the input tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned.
* @return string the generated button tag
*/
public static function passwordField($name, $value = '', $htmlOptions = array())
public static function passwordInput($name, $value = null, $attributes = array())
{
static::clientChange('change', $htmlOptions);
return static::inputField('password', $name, $value, $htmlOptions);
return static::input('password', $name, $value, $attributes);
}
/**
* Generates a file input.
* Note, you have to set the enclosing form's 'enctype' attribute to be 'multipart/form-data'.
* After the form is submitted, the uploaded file information can be obtained via $_FILES[$name] (see
* PHP documentation).
* @param string $name the input name
* @param string $value the input value
* @param array $htmlOptions additional HTML attributes (see {@link tag}).
* @return string the generated input field
* @see inputField
* Generates a file input field.
* To use a file input field, you should set the enclosing form's "enctype" attribute to
* be "multipart/form-data". After the form is submitted, the uploaded file information
* can be obtained via $_FILES[$name] (see PHP documentation).
* @param string $name the name attribute.
* @param string $value the value attribute. If it is null, the value attribute will not be generated.
* @param array $attributes the attributes of the input tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned.
* @return string the generated button tag
*/
public static function fileField($name, $value = '', $htmlOptions = array())
public static function fileInput($name, $value = null, $attributes = array())
{
return static::inputField('file', $name, $value, $htmlOptions);
return static::input('file', $name, $value, $attributes);
}
/**
* Generates a text area input.
* @param string $name the input name
* @param string $value the input value
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
* @return string the generated text area
* @see clientChange
* @see inputField
* @param string $value the input value. Note that it will be encoded using [[encode()]].
* @param array $attributes the attributes of the input tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned.
* @return string the generated text area tag
*/
public static function textArea($name, $value = '', $htmlOptions = array())
public static function textarea($name, $value = '', $attributes = array())
{
$htmlOptions['name'] = $name;
if (!isset($htmlOptions['id'])) {
$htmlOptions['id'] = static::getIdByName($name);
} elseif ($htmlOptions['id'] === false) {
unset($htmlOptions['id']);
}
static::clientChange('change', $htmlOptions);
return static::tag('textarea', $htmlOptions, isset($htmlOptions['encode']) && !$htmlOptions['encode'] ? $value : static::encode($value));
$attributes['name'] = $name;
return static::tag('textarea', static::encode($value), $attributes);
}
/**
* Generates a radio button.
* @param string $name the input name
* @param boolean $checked whether the radio button is checked
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
* Since version 1.1.2, a special option named 'uncheckValue' is available that can be used to specify
* the value returned when the radio button is not checked. When set, a hidden field is rendered so that
* when the radio button is not checked, we can still obtain the posted uncheck value.
* If 'uncheckValue' is not set or set to NULL, the hidden field will not be rendered.
* @return string the generated radio button
* @see clientChange
* @see inputField
* Generates a radio button input.
* @param string $name the name attribute.
* @param string $value the value attribute. If it is null, the value attribute will not be generated.
* @param boolean $checked whether the radio button should be checked.
* @param array $attributes the attributes of the input tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned. The following attribute
* will be specially handled and not put in the resulting tag:
*
* - uncheck: string, the value associated with the uncheck state of the radio button. When this attribute
* is present, a hidden input will be generated 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.
*
* @return string the generated radio button tag
*/
public static function radioButton($name, $checked = false, $htmlOptions = array())
public static function radio($name, $value = '1', $checked = false, $attributes = array())
{
if ($checked) {
$htmlOptions['checked'] = 'checked';
} else {
unset($htmlOptions['checked']);
}
$value = isset($htmlOptions['value']) ? $htmlOptions['value'] : 1;
static::clientChange('click', $htmlOptions);
if (array_key_exists('uncheckValue', $htmlOptions)) {
$uncheck = $htmlOptions['uncheckValue'];
unset($htmlOptions['uncheckValue']);
} else {
$uncheck = null;
}
if ($uncheck !== null) {
$attributes['checked'] = $checked;
if (isset($attributes['uncheck'])) {
// add a hidden field so that if the radio button is not selected, it still submits a value
if (isset($htmlOptions['id']) && $htmlOptions['id'] !== false) {
$uncheckOptions = array('id' => static::ID_PREFIX . $htmlOptions['id']);
} else {
$uncheckOptions = array('id' => false);
}
$hidden = static::hiddenField($name, $uncheck, $uncheckOptions);
$hidden = static::hiddenInput($name, $attributes['uncheck']);
unset($attributes['uncheck']);
} else {
$hidden = '';
}
// add a hidden field so that if the radio button is not selected, it still submits a value
return $hidden . static::inputField('radio', $name, $value, $htmlOptions);
return $hidden . static::input('radio', $name, $value, $attributes);
}
/**
* Generates a check box.
* @param string $name the input name
* @param boolean $checked whether the check box is checked
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
* Since version 1.1.2, a special option named 'uncheckValue' is available that can be used to specify
* the value returned when the checkbox is not checked. When set, a hidden field is rendered so that
* when the checkbox is not checked, we can still obtain the posted uncheck value.
* If 'uncheckValue' is not set or set to NULL, the hidden field will not be rendered.
* @return string the generated check box
* @see clientChange
* @see inputField
* Generates a checkbox input.
* @param string $name the name attribute.
* @param string $value the value attribute. If it is null, the value attribute will not be generated.
* @param boolean $checked whether the checkbox should be checked.
* @param array $attributes the attributes of the input tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned. The following attribute
* will be specially handled and not put in the resulting tag:
*
* - uncheck: string, the value associated with the uncheck state of the checkbox. When this attribute
* is present, a hidden input will be generated so that if the checkbox is not checked and is submitted,
* the value of this attribute will still be submitted to the server via the hidden input.
*
* @return string the generated checkbox tag
*/
public static function checkBox($name, $checked = false, $htmlOptions = array())
public static function checkbox($name, $value = '1', $checked = false, $attributes = array())
{
if ($checked) {
$htmlOptions['checked'] = 'checked';
} else {
unset($htmlOptions['checked']);
}
$value = isset($htmlOptions['value']) ? $htmlOptions['value'] : 1;
static::clientChange('click', $htmlOptions);
if (array_key_exists('uncheckValue', $htmlOptions)) {
$uncheck = $htmlOptions['uncheckValue'];
unset($htmlOptions['uncheckValue']);
} else {
$uncheck = null;
}
if ($uncheck !== null) {
// add a hidden field so that if the check box is not checked, it still submits a value
if (isset($htmlOptions['id']) && $htmlOptions['id'] !== false) {
$uncheckOptions = array('id' => static::ID_PREFIX . $htmlOptions['id']);
} else {
$uncheckOptions = array('id' => false);
}
$hidden = static::hiddenField($name, $uncheck, $uncheckOptions);
$attributes['checked'] = $checked;
if (isset($attributes['uncheck'])) {
// add a hidden field so that if the checkbox is not selected, it still submits a value
$hidden = static::hiddenInput($name, $attributes['uncheck']);
unset($attributes['uncheck']);
} else {
$hidden = '';
}
// add a hidden field so that if the check box is not checked, it still submits a value
return $hidden . static::inputField('checkbox', $name, $value, $htmlOptions);
return $hidden . static::input('checkbox', $name, $value, $attributes);
}
/**
* Generates a drop down list.
* Generates a drop-down list.
* @param string $name the input name
* @param string $select the selected value
* @param array $data data for generating the list options (value=>display).
* You may use {@link listData} to generate this data.
* Please refer to {@link listOptions} on how this data is used to generate the list options.
* Note, the values and labels will be automatically HTML-encoded by this method.
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
* attributes are recognized. See {@link clientChange} and {@link tag} for more details.
* In addition, the following options are also supported specifically for dropdown list:
* <ul>
* <li>encode: boolean, specifies whether to encode the values. Defaults to true.</li>
* <li>prompt: string, specifies the prompt text shown as the first list option. Its value is empty. Note, the prompt text will NOT be HTML-encoded.</li>
* <li>empty: string, specifies the text corresponding to empty selection. Its value is empty.
* The 'empty' option can also be an array of value-label pairs.
* Each pair will be used to render a list option at the beginning. Note, the text label will NOT be HTML-encoded.</li>
* <li>options: array, specifies additional attributes for each OPTION tag.
* The array keys must be the option values, and the array values are the extra
* OPTION tag attributes in the name-value pairs. For example,
* <pre>
* array(
* 'value1'=>array('disabled'=>true, 'label'=>'value 1'),
* 'value2'=>array('label'=>'value 2'),
* );
* </pre>
* </li>
* </ul>
* Since 1.1.13, a special option named 'unselectValue' is available. It can be used to set the value
* that will be returned when no option is selected in multiple mode. When set, a hidden field is
* rendered so that if no option is selected in multiple mode, we can still obtain the posted
* unselect value. If 'unselectValue' is not set or set to NULL, the hidden field will not be rendered.
* @return string the generated drop down list
* @see clientChange
* @see inputField
* @see listData
* @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\util\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 string $selection the selected value
* @param array $attributes the attributes of the input tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned. The following attribute
* will be specially handled and not put in the resulting tag:
*
* - prompt: string, a prompt text to be displayed as the first option;
* - options: array, the attributes for the option tags. The array keys must be valid option values,
* and the array values are the extra attributes for the corresponding option tags. For example,
*
* ~~~
* array(
* 'value1' => array('disabled' => true),
* 'value2' => array('label' => 'value 2'),
* );
* ~~~
*
* - groups: array, the attributes for the optgroup tags. The structure of this is similar to that of 'options',
* except that the array keys represent the optgroup labels specified in $items.
* @return string the generated drop-down list tag
*/
public static function dropDownList($name, $select, $data, $htmlOptions = array())
public static function dropDownList($name, $items, $selection = null, $attributes = array())
{
$htmlOptions['name'] = $name;
if (!isset($htmlOptions['id'])) {
$htmlOptions['id'] = static::getIdByName($name);
} elseif ($htmlOptions['id'] === false) {
unset($htmlOptions['id']);
}
static::clientChange('change', $htmlOptions);
$options = "\n" . static::listOptions($select, $data, $htmlOptions);
$hidden = '';
if (isset($htmlOptions['multiple'])) {
if (substr($htmlOptions['name'], -2) !== '[]') {
$htmlOptions['name'] .= '[]';
}
if (isset($htmlOptions['unselectValue'])) {
$hiddenOptions = isset($htmlOptions['id']) ? array('id' => static::ID_PREFIX . $htmlOptions['id']) : array('id' => false);
$hidden = static::hiddenField(substr($htmlOptions['name'], 0, -2), $htmlOptions['unselectValue'], $hiddenOptions);
unset($htmlOptions['unselectValue']);
}
}
// add a hidden field so that if the option is not selected, it still submits a value
return $hidden . static::tag('select', $htmlOptions, $options);
$attributes['name'] = $name;
$options = static::renderOptions($items, $selection, $attributes);
return static::tag('select', "\n" . $options . "\n", $attributes);
}
/**
* Generates a list box.
* @param string $name the input name
* @param mixed $select the selected value(s). This can be either a string for single selection or an array for multiple selections.
* @param array $data data for generating the list options (value=>display)
* You may use {@link listData} to generate this data.
* Please refer to {@link listOptions} on how this data is used to generate the list options.
* Note, the values and labels will be automatically HTML-encoded by this method.
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
* attributes are also recognized. See {@link clientChange} and {@link tag} for more details.
* In addition, the following options are also supported specifically for list box:
* <ul>
* <li>encode: boolean, specifies whether to encode the values. Defaults to true.</li>
* <li>prompt: string, specifies the prompt text shown as the first list option. Its value is empty. Note, the prompt text will NOT be HTML-encoded.</li>
* <li>empty: string, specifies the text corresponding to empty selection. Its value is empty.
* The 'empty' option can also be an array of value-label pairs.
* Each pair will be used to render a list option at the beginning. Note, the text label will NOT be HTML-encoded.</li>
* <li>options: array, specifies additional attributes for each OPTION tag.
* The array keys must be the option values, and the array values are the extra
* OPTION tag attributes in the name-value pairs. For example,
* <pre>
* array(
* 'value1'=>array('disabled'=>true, 'label'=>'value 1'),
* 'value2'=>array('label'=>'value 2'),
* );
* </pre>
* </li>
* </ul>
* @return string the generated list box
* @see clientChange
* @see inputField
* @see listData
*/
public static function listBox($name, $select, $data, $htmlOptions = array())
{
if (!isset($htmlOptions['size'])) {
$htmlOptions['size'] = 4;
* @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\util\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 string|array $selection the selected value(s)
* @param array $attributes the attributes of the input tag. The values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the tag returned. The following attribute
* will be specially handled and not put in the resulting tag:
*
* - prompt: string, a prompt text to be displayed as the first option;
* - options: array, the attributes for the option tags. The array keys must be valid option values,
* and the array values are the extra attributes for the corresponding option tags. For example,
*
* ~~~
* array(
* 'value1' => array('disabled' => true),
* 'value2' => array('label' => 'value 2'),
* );
* ~~~
*
* - groups: array, the attributes for the optgroup tags. The structure of this is similar to that of 'options',
* except that the array keys represent the optgroup labels specified in $items.
* - unselect: string, the value that will be submitted when no option is selected.
* When this attribute is set, a hidden field will be generated so that if no option is selected in multiple
* mode, we can still obtain the posted unselect value.
* @return string the generated list box tag
*/
public static function listBox($name, $items, $selection = null, $attributes = array())
{
if (!isset($attributes['size'])) {
$attributes['size'] = 4;
}
if (isset($attributes['unselect'])) {
// add a hidden field so that if the list box has no option being selected, it still submits a value
$hidden = static::hiddenInput($name, $attributes['unselect']);
unset($attributes['unselect']);
} else {
$hidden = '';
}
if (isset($htmlOptions['multiple'])) {
if (substr($name, -2) !== '[]') {
$name .= '[]';
}
if (isset($attributes['multiple']) && $attributes['multiple'] && substr($name, -2) !== '[]') {
$name .= '[]';
}
return static::dropDownList($name, $select, $data, $htmlOptions);
$attributes['name'] = $name;
$options = static::renderOptions($items, $selection, $attributes);
return $hidden . static::tag('select', "\n" . $options . "\n", $attributes);
}
/**
* Generates a check box list.
* A check box list allows multiple selection, like {@link listBox}.
* As a result, the corresponding POST value is an array.
* @param string $name name of the check box list. You can use this name to retrieve
* the selected value(s) once the form is submitted.
* @param mixed $select selection of the check boxes. This can be either a string
* for single selection or an array for multiple selections.
* @param array $data value-label pairs used to generate the check box list.
* Note, the values will be automatically HTML-encoded, while the labels will not.
* @param array $htmlOptions additional HTML options. The options will be applied to
* each checkbox input. The following special options are recognized:
* <ul>
* <li>template: string, specifies how each checkbox is rendered. Defaults
* to "{input} {label}", where "{input}" will be replaced by the generated
* check box input tag while "{label}" be replaced by the corresponding check box label.</li>
* <li>separator: string, specifies the string that separates the generated check boxes.</li>
* <li>checkAll: string, specifies the label for the "check all" checkbox.
* If this option is specified, a 'check all' checkbox will be displayed. Clicking on
* this checkbox will cause all checkboxes checked or unchecked.</li>
* <li>checkAllLast: boolean, specifies whether the 'check all' checkbox should be
* displayed at the end of the checkbox list. If this option is not set (default)
* or is false, the 'check all' checkbox will be displayed at the beginning of
* the checkbox list.</li>
* <li>labelOptions: array, specifies the additional HTML attributes to be rendered
* for every label tag in the list.</li>
* <li>container: string, specifies the checkboxes enclosing tag. Defaults to 'span'.
* If the value is an empty string, no enclosing tag will be generated</li>
* <li>baseID: string, specifies the base ID prefix to be used for checkboxes in the list.
* This option is available since version 1.1.13.</li>
* </ul>
* @return string the generated check box list
* Generates a list of checkboxes.
* A checkbox list allows multiple selection, like [[listBox()]].
* As a result, the corresponding submitted value is an array.
* @param string $name the name attribute of each checkbox.
* @param array $items the data item used to generate the checkboxes.
* The array keys are the labels, while the array values are the corresponding checkbox values.
* Note that the labels will NOT be HTML-encoded, while the values will.
* @param string|array $selection the selected value(s).
* @param callable $formatter a callback that can be used to customize the generation of the HTML code
* corresponding to a single checkbox. The signature of this callback must be:
*
* ~~~
* function ($index, $label, $name, $value, $checked)
* ~~~
*
* where $index is the zero-based index of the checkbox in the whole list; $label
* is the label for the checkbox; and $name, $value and $checked represent the name,
* value and the checked status of the checkbox input.
* @return string the generated checkbox list
*/
public static function checkBoxList($name, $select, $data, $htmlOptions = array())
public static function checkboxList($name, $items, $selection = null, $formatter = null)
{
$template = isset($htmlOptions['template']) ? $htmlOptions['template'] : '{input} {label}';
$separator = isset($htmlOptions['separator']) ? $htmlOptions['separator'] : "<br/>\n";
$container = isset($htmlOptions['container']) ? $htmlOptions['container'] : 'span';
unset($htmlOptions['template'], $htmlOptions['separator'], $htmlOptions['container']);
if (substr($name, -2) !== '[]') {
$name .= '[]';
}
if (isset($htmlOptions['checkAll'])) {
$checkAllLabel = $htmlOptions['checkAll'];
$checkAllLast = isset($htmlOptions['checkAllLast']) && $htmlOptions['checkAllLast'];
}
unset($htmlOptions['checkAll'], $htmlOptions['checkAllLast']);
$labelOptions = isset($htmlOptions['labelOptions']) ? $htmlOptions['labelOptions'] : array();
unset($htmlOptions['labelOptions']);
$items = array();
$baseID = isset($htmlOptions['baseID']) ? $htmlOptions['baseID'] : static::getIdByName($name);
unset($htmlOptions['baseID']);
$id = 0;
$checkAll = true;
foreach ($data as $value => $label) {
$checked = !is_array($select) && !strcmp($value, $select) || is_array($select) && in_array($value, $select);
$checkAll = $checkAll && $checked;
$htmlOptions['value'] = $value;
$htmlOptions['id'] = $baseID . '_' . $id++;
$option = static::checkBox($name, $checked, $htmlOptions);
$label = static::label($label, $htmlOptions['id'], $labelOptions);
$items[] = strtr($template, array('{input}' => $option, '{label}' => $label));
}
if (isset($checkAllLabel)) {
$htmlOptions['value'] = 1;
$htmlOptions['id'] = $id = $baseID . '_all';
$option = static::checkBox($id, $checkAll, $htmlOptions);
$label = static::label($checkAllLabel, $id, $labelOptions);
$item = strtr($template, array('{input}' => $option, '{label}' => $label));
if ($checkAllLast) {
$items[] = $item;
$lines = array();
$index = 0;
foreach ($items as $value => $label) {
$checked = $selection !== null &&
(!is_array($selection) && !strcmp($value, $selection)
|| is_array($selection) && in_array($value, $selection));
if ($formatter !== null) {
$lines[] = call_user_func($formatter, $index, $label, $name, $value, $checked);
} else {
array_unshift($items, $item);
$lines[] = static::label(static::checkbox($name, $value, $checked) . ' ' . $label);
}
$name = strtr($name, array('[' => '\\[', ']' => '\\]'));
$js = <<<EOD
jQuery('#$id').click(function() {
jQuery("input[name='$name']").prop('checked', this.checked);
});
jQuery("input[name='$name']").click(function() {
jQuery('#$id').prop('checked', !jQuery("input[name='$name']:not(:checked)").length);
});
jQuery('#$id').prop('checked', !jQuery("input[name='$name']:not(:checked)").length);
EOD;
$cs = Yii::app()->getClientScript();
$cs->registerCoreScript('jquery');
$cs->registerScript($id, $js);
$index++;
}
if (empty($container)) {
return implode($separator, $items);
} else {
return static::tag($container, array('id' => $baseID), implode($separator, $items));
}
return implode("\n", $lines);
}
/**
* Generates a radio button list.
* A radio button list is like a {@link checkBoxList check box list}, except that
* it only allows single selection.
* @param string $name name of the radio button list. You can use this name to retrieve
* the selected value(s) once the form is submitted.
* @param string $select selection of the radio buttons.
* @param array $data value-label pairs used to generate the radio button list.
* Note, the values will be automatically HTML-encoded, while the labels will not.
* @param array $htmlOptions additional HTML options. The options will be applied to
* each radio button input. The following special options are recognized:
* <ul>
* <li>template: string, specifies how each radio button is rendered. Defaults
* to "{input} {label}", where "{input}" will be replaced by the generated
* radio button input tag while "{label}" will be replaced by the corresponding radio button label.</li>
* <li>separator: string, specifies the string that separates the generated radio buttons. Defaults to new line (<br/>).</li>
* <li>labelOptions: array, specifies the additional HTML attributes to be rendered
* for every label tag in the list.</li>
* <li>container: string, specifies the radio buttons enclosing tag. Defaults to 'span'.
* If the value is an empty string, no enclosing tag will be generated</li>
* <li>baseID: string, specifies the base ID prefix to be used for radio buttons in the list.
* This option is available since version 1.1.13.</li>
* </ul>
* @return string the generated radio button list
*/
public static function radioButtonList($name, $select, $data, $htmlOptions = array())
{
$template = isset($htmlOptions['template']) ? $htmlOptions['template'] : '{input} {label}';
$separator = isset($htmlOptions['separator']) ? $htmlOptions['separator'] : "<br/>\n";
$container = isset($htmlOptions['container']) ? $htmlOptions['container'] : 'span';
unset($htmlOptions['template'], $htmlOptions['separator'], $htmlOptions['container']);
$labelOptions = isset($htmlOptions['labelOptions']) ? $htmlOptions['labelOptions'] : array();
unset($htmlOptions['labelOptions']);
$items = array();
$baseID = isset($htmlOptions['baseID']) ? $htmlOptions['baseID'] : static::getIdByName($name);
unset($htmlOptions['baseID']);
$id = 0;
foreach ($data as $value => $label) {
$checked = !strcmp($value, $select);
$htmlOptions['value'] = $value;
$htmlOptions['id'] = $baseID . '_' . $id++;
$option = static::radioButton($name, $checked, $htmlOptions);
$label = static::label($label, $htmlOptions['id'], $labelOptions);
$items[] = strtr($template, array('{input}' => $option, '{label}' => $label));
}
if (empty($container)) {
return implode($separator, $items);
} else {
return static::tag($container, array('id' => $baseID), implode($separator, $items));
}
}
/**
* Normalizes the input parameter to be a valid URL.
*
* If the input parameter is an empty string, the currently requested URL will be returned.
*
* If the input parameter is a non-empty string, it is treated as a valid URL and will
* be returned without any change.
* Generates a list of radio buttons.
* A radio button list is like a checkbox list, except that it only allows single selection.
* @param string $name the name attribute of each radio button.
* @param array $items the data item used to generate the radio buttons.
* The array keys are the labels, while the array values are the corresponding radio button values.
* Note that the labels will NOT be HTML-encoded, while the values will.
* @param string|array $selection the selected value(s).
* @param callable $formatter a callback that can be used to customize the generation of the HTML code
* corresponding to a single radio button. The signature of this callback must be:
*
* If the input parameter is an array, it is treated as a controller route and a list of
* GET parameters, and the {@link CController::createUrl} method will be invoked to
* create a URL. In this case, the first array element refers to the controller route,
* and the rest key-value pairs refer to the additional GET parameters for the URL.
* For example, <code>array('post/list', 'page'=>3)</code> may be used to generate the URL
* <code>/index.php?r=post/list&page=3</code>.
* ~~~
* function ($index, $label, $name, $value, $checked)
* ~~~
*
* @param mixed $url the parameter to be used to generate a valid URL
* @return string the normalized URL
* where $index is the zero-based index of the radio button in the whole list; $label
* is the label for the radio button; and $name, $value and $checked represent the name,
* value and the checked status of the radio button input.
* @return string the generated radio button list
*/
public static function normalizeUrl($url)
public static function radioList($name, $items, $selection = null, $formatter = null)
{
if (is_array($url)) {
if (isset($url[0])) {
if (($c = Yii::app()->getController()) !== null) {
$url = $c->createUrl($url[0], array_splice($url, 1));
} else {
$url = Yii::app()->createUrl($url[0], array_splice($url, 1));
}
$lines = array();
$index = 0;
foreach ($items as $value => $label) {
$checked = $selection !== null &&
(!is_array($selection) && !strcmp($value, $selection)
|| is_array($selection) && in_array($value, $selection));
if ($formatter !== null) {
$lines[] = call_user_func($formatter, $index, $label, $name, $value, $checked);
} else {
$url = '';
$lines[] = static::label(static::radio($name, $value, $checked) . ' ' . $label);
}
$index++;
}
return $url === '' ? Yii::app()->getRequest()->getUrl() : $url;
}
/**
* Generates an input HTML tag.
* This method generates an input HTML tag based on the given input name and value.
* @param string $type the input type (e.g. 'text', 'radio')
* @param string $name the input name
* @param string $value the input value
* @param array $htmlOptions additional HTML attributes for the HTML tag (see {@link tag}).
* @return string the generated input tag
*/
protected static function inputField($type, $name, $value, $htmlOptions)
{
$htmlOptions['type'] = $type;
$htmlOptions['value'] = $value;
$htmlOptions['name'] = $name;
if (!isset($htmlOptions['id'])) {
$htmlOptions['id'] = static::getIdByName($name);
} elseif ($htmlOptions['id'] === false) {
unset($htmlOptions['id']);
}
return static::tag('input', $htmlOptions);
return implode("\n", $lines);
}
/**
* Generates the list options.
* @param mixed $selection the selected value(s). This can be either a string for single selection or an array for multiple selections.
* @param array $listData the option data (see {@link listData})
* @param array $htmlOptions additional HTML attributes. The following two special attributes are recognized:
* <ul>
* <li>encode: boolean, specifies whether to encode the values. Defaults to true.</li>
* <li>prompt: string, specifies the prompt text shown as the first list option. Its value is empty. Note, the prompt text will NOT be HTML-encoded.</li>
* <li>empty: string, specifies the text corresponding to empty selection. Its value is empty.
* The 'empty' option can also be an array of value-label pairs.
* Each pair will be used to render a list option at the beginning. Note, the text label will NOT be HTML-encoded.</li>
* <li>options: array, specifies additional attributes for each OPTION tag.
* The array keys must be the option values, and the array values are the extra
* OPTION tag attributes in the name-value pairs. For example,
* <pre>
* array(
* 'value1'=>array('disabled'=>true, 'label'=>'value 1'),
* 'value2'=>array('label'=>'value 2'),
* );
* </pre>
* </li>
* <li>key: string, specifies the name of key attribute of the selection object(s).
* This is used when the selection is represented in terms of objects. In this case,
* the property named by the key option of the objects will be treated as the actual selection value.
* This option defaults to 'primaryKey', meaning using the 'primaryKey' property value of the objects in the selection.
* This option has been available since version 1.1.3.</li>
* </ul>
* Renders the option tags that can be used by [[dropDownList()]] and [[listBox()]].
* @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\util\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 string|array $selection the selected value(s). This can be either a string for single selection
* or an array for multiple selections.
* @param array $attributes the attributes parameter that is passed to the [[dropDownList()]] or [[listBox()]] call.
* This method will take out these elements, if any: "prompt", "options" and "groups". See more details
* in [[dropDownList()]] for the explanation of these elements.
*
* @return string the generated list options
*/
public static function listOptions($selection, $listData, &$htmlOptions)
public static function renderOptions($items, $selection = null, &$attributes = array())
{
$raw = isset($htmlOptions['encode']) && !$htmlOptions['encode'];
$content = '';
if (isset($htmlOptions['prompt'])) {
$content .= '<option value="">' . strtr($htmlOptions['prompt'], array('<' => '&lt;', '>' => '&gt;')) . "</option>\n";
unset($htmlOptions['prompt']);
}
if (isset($htmlOptions['empty'])) {
if (!is_array($htmlOptions['empty'])) {
$htmlOptions['empty'] = array('' => $htmlOptions['empty']);
}
foreach ($htmlOptions['empty'] as $value => $label) {
$content .= '<option value="' . static::encode($value) . '">' . strtr($label, array('<' => '&lt;', '>' => '&gt;')) . "</option>\n";
}
unset($htmlOptions['empty']);
$lines = array();
if (isset($attributes['prompt'])) {
$prompt = strtr(static::encode($attributes['prompt']), ' ', '&nbsp;');
$lines[] = static::tag('option', $prompt, array('value' => ''));
}
if (isset($htmlOptions['options'])) {
$options = $htmlOptions['options'];
unset($htmlOptions['options']);
} else {
$options = array();
}
$options = isset($attributes['options']) ? $attributes['options'] : array();
$groups = isset($attributes['groups']) ? $attributes['groups'] : array();
unset($attributes['prompt'], $attributes['options'], $attributes['groups']);
$key = isset($htmlOptions['key']) ? $htmlOptions['key'] : 'primaryKey';
if (is_array($selection)) {
foreach ($selection as $i => $item) {
if (is_object($item)) {
$selection[$i] = $item->$key;
}
}
} elseif (is_object($selection)) {
$selection = $selection->$key;
}
foreach ($listData as $key => $value) {
foreach ($items as $key => $value) {
if (is_array($value)) {
$content .= '<optgroup label="' . ($raw ? $key : static::encode($key)) . "\">\n";
$dummy = array('options' => $options);
if (isset($htmlOptions['encode'])) {
$dummy['encode'] = $htmlOptions['encode'];
}
$content .= static::listOptions($selection, $value, $dummy);
$content .= '</optgroup>' . "\n";
$groupAttrs = isset($groups[$key]) ? $groups[$key] : array();
$groupAttrs['label'] = $key;
$attrs = array('options' => $options, 'groups' => $groups);
$content = static::renderOptions($selection, $value, $attrs);
$lines[] = static::tag('optgroup', "\n" . $content . "\n", $groupAttrs);
} else {
$attributes = array('value' => (string)$key, 'encode' => !$raw);
if (!is_array($selection) && !strcmp($key, $selection) || is_array($selection) && in_array($key, $selection)) {
$attributes['selected'] = 'selected';
}
if (isset($options[$key])) {
$attributes = array_merge($attributes, $options[$key]);
}
$content .= static::tag('option', $attributes, $raw ? (string)$value : static::encode((string)$value)) . "\n";
$attrs = isset($options[$key]) ? $options[$key] : array();
$attrs['value'] = $key;
$attrs['selected'] = $selection !== null &&
(!is_array($selection) && !strcmp($key, $selection)
|| is_array($selection) && in_array($key, $selection));
$lines[] = static::tag('option', strtr(static::encode($value), ' ', '&nbsp;'), $attrs);
}
}
unset($htmlOptions['key']);
return $content;
return implode("\n", $lines);
}
/**
* Renders the HTML tag attributes.
* Since version 1.1.5, attributes whose value is null will not be rendered.
* Special attributes, such as 'checked', 'disabled', 'readonly', will be rendered
* properly based on their corresponding boolean value.
* @param array $attributes attributes to be rendered
* @return string the rendering result
* Boolean attributes such as s 'checked', 'disabled', 'readonly', will be handled specially
* according to [[booleanAttributes]] and [[showBooleanAttributeValues]].
* @param array $attributes attributes to be rendered. The attribute values will be HTML-encoded using [[encode()]].
* Attributes whose value is null will be ignored and not put in the rendering result.
* @return string the rendering result. If the attributes are not empty, they will be rendered
* into a string with a leading white space (such that it can be directly appended to the tag name
* in a tag. If there is no attribute, an empty string will be returned.
*/
public static function renderAttributes($attributes)
{
static $specialAttributes = array(
'async' => 1,
'autofocus' => 1,
'autoplay' => 1,
'checked' => 1,
'controls' => 1,
'declare' => 1,
'default' => 1,
'defer' => 1,
'disabled' => 1,
'formnovalidate' => 1,
'hidden' => 1,
'ismap' => 1,
'loop' => 1,
'multiple' => 1,
'muted' => 1,
'nohref' => 1,
'noresize' => 1,
'novalidate' => 1,
'open' => 1,
'readonly' => 1,
'required' => 1,
'reversed' => 1,
'scoped' => 1,
'seamless' => 1,
'selected' => 1,
'typemustmatch' => 1,
);
if ($attributes === array()) {
return '';
if (count($attributes) > 1) {
$sorted = array();
foreach (static::$attributeOrder as $name) {
if (isset($attributes[$name])) {
$sorted[$name] = $attributes[$name];
}
}
$attributes = array_merge($sorted, $attributes);
}
$html = '';
if (isset($attributes['encode'])) {
$raw = !$attributes['encode'];
unset($attributes['encode']);
} else {
$raw = false;
}
foreach ($attributes as $name => $value) {
if (isset($specialAttributes[$name])) {
if ($value) {
$html .= ' ' . $name;
if (static::$renderSpecialAttributesValue) {
$html .= '="' . $name . '"';
}
if (isset(static::$booleanAttributes[strtolower($name)])) {
if ($value || strcasecmp($name, $value) === 0) {
$html .= static::$showBooleanAttributeValues ? " $name=\"$name\"" : " $name";
}
} elseif ($value !== null) {
$html .= ' ' . $name . '="' . ($raw ? $value : static::encode($value)) . '"';
$html .= " $name=\"" . static::encode($value) . '"';
}
}
return $html;
}
/**
* Normalizes the input parameter to be a valid URL.
*
* If the input parameter
*
* - is an empty string: the currently requested URL will be returned;
* - is a non-empty string: it will be processed by [[Yii::getAlias()]] which, if the string is an alias,
* will be resolved into a URL;
* - is an array: the first array element is considered a route, while the rest of the name-value
* pairs are considered as the parameters to be used for URL creation using [[\yii\base\Application::createUrl()]].
* Here are some examples: `array('post/index', 'page' => 2)`, `array('index')`.
*
* @param array|string $url the parameter to be used to generate a valid URL
* @return string the normalized URL
* @throws InvalidParamException if the parameter is invalid.
*/
public static function url($url)
{
if (is_array($url)) {
if (isset($url[0])) {
return Yii::$app->createUrl($url[0], array_splice($url, 1));
} else {
throw new InvalidParamException('The array specifying a URL must contain at least one element.');
}
} elseif ($url === '') {
return Yii::$app->getRequest()->getUrl();
} else {
return Yii::getAlias($url);
}
}
}
......@@ -6,6 +6,7 @@
*/
namespace yii\web;
use yii\base\InvalidParamException;
/**
* Application is the base class for all application classes.
......@@ -62,11 +63,48 @@ class Application extends \yii\base\Application
}
/**
* @return UrlManager
* Creates a URL using the given route and parameters.
*
* This method first normalizes the given route by converting a relative route into an absolute one.
* A relative route is a route without slash. If the route is an empty string, it stands for
* the route of the currently active [[controller]]. If the route is not empty, it stands for
* an action ID of the [[controller]].
*
* After normalizing the route, this method calls [[\yii\web\UrlManager::createUrl()]]
* to create a relative URL.
*
* @param string $route the route. This can be either an absolute or a relative route.
* @param array $params the parameters (name-value pairs) to be included in the generated URL
* @return string the created URL
* @throws InvalidParamException if a relative route is given and there is no active controller.
* @see createAbsoluteUrl
*/
public function getUrlManager()
public function createUrl($route, $params = array())
{
return $this->getComponent('urlManager');
if (strpos($route, '/') === false) {
// a relative route
if ($this->controller !== null) {
$route = $route === '' ? $this->controller->route : $this->controller->uniqueId . '/' . $route;
} else {
throw new InvalidParamException('No active controller exists for resolving a relative route.');
}
}
return $this->getUrlManager()->createUrl($route, $params);
}
/**
* Creates an absolute URL using the given route and parameters.
* This method first calls [[createUrl()]] to create a relative URL.
* It then prepends [[\yii\web\UrlManager::hostInfo]] to the URL to form an absolute one.
* @param string $route the route. This can be either an absolute or a relative route.
* See [[createUrl()]] for more details.
* @param array $params the parameters (name-value pairs)
* @return string the created URL
* @see createUrl
*/
public function createAbsoluteUrl($route, $params = array())
{
return $this->getUrlManager()->getHostInfo() . $this->createUrl($route, $params);
}
/**
......@@ -86,9 +124,6 @@ class Application extends \yii\base\Application
'session' => array(
'class' => 'yii\web\Session',
),
'urlManager' => array(
'class' => 'yii\web\UrlManager',
),
));
}
}
......@@ -16,4 +16,8 @@ namespace yii\web;
*/
class Controller extends \yii\base\Controller
{
public function createUrl($route, $params = array())
{
}
}
\ No newline at end of file
......@@ -368,7 +368,7 @@ class Request extends \yii\base\Request
*/
protected function resolvePathInfo()
{
$pathInfo = $this->getRequestUri();
$pathInfo = $this->getUrl();
if (($pos = strpos($pathInfo, '?')) !== false) {
$pathInfo = substr($pathInfo, 0, $pos);
......@@ -407,42 +407,41 @@ class Request extends \yii\base\Request
}
/**
* Returns the currently requested URL.
* This is a shortcut to the concatenation of [[hostInfo]] and [[requestUri]].
* @return string the currently requested URL.
* Returns the currently requested absolute URL.
* This is a shortcut to the concatenation of [[hostInfo]] and [[url]].
* @return string the currently requested absolute URL.
*/
public function getUrl()
public function getAbsoluteUrl()
{
return $this->getHostInfo() . $this->getRequestUri();
return $this->getHostInfo() . $this->getUrl();
}
private $_requestUri;
private $_url;
/**
* Returns the portion after [[hostInfo]] for the currently requested URL.
* This refers to the portion that is after the [[hostInfo]] part. It includes the [[queryString]] part if any.
* The implementation of this method referenced Zend_Controller_Request_Http in Zend Framework.
* @return string the request URI portion for the currently requested URL.
* Note that the URI returned is URL-encoded.
* @throws InvalidConfigException if the request URI cannot be determined due to unusual server configuration
* Returns the currently requested relative URL.
* This refers to the portion of the URL that is after the [[hostInfo]] part.
* It includes the [[queryString]] part if any.
* @return string the currently requested relative URL. Note that the URI returned is URL-encoded.
* @throws InvalidConfigException if the URL cannot be determined due to unusual server configuration
*/
public function getRequestUri()
public function getUrl()
{
if ($this->_requestUri === null) {
$this->_requestUri = $this->resolveRequestUri();
if ($this->_url === null) {
$this->_url = $this->resolveRequestUri();
}
return $this->_requestUri;
return $this->_url;
}
/**
* Sets the currently requested URI.
* Sets the currently requested relative URL.
* The URI must refer to the portion that is after [[hostInfo]].
* Note that the URI should be URL-encoded.
* @param string $value the request URI to be set
*/
public function setRequestUri($value)
public function setUrl($value)
{
$this->_requestUri = $value;
$this->_url = $value;
}
/**
......
......@@ -18,6 +18,7 @@
* backend-specific unit tests
* dependency unit tests
- validators
* Refactor validators to add validateValue() for every validator, if possible. Check if value is an array.
* FileValidator: depends on CUploadedFile
* CaptchaValidator: depends on CaptchaAction
* DateValidator: should we use CDateTimeParser, or simply use strtotime()?
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment