diff --git a/framework/util/ArrayHelper.php b/framework/util/ArrayHelper.php index ebf4b23..447d034 100644 --- a/framework/util/ArrayHelper.php +++ b/framework/util/ArrayHelper.php @@ -293,7 +293,7 @@ class ArrayHelper * @return array the encoded data * @see http://www.php.net/manual/en/function.htmlspecialchars.php */ - public static function htmlEncode($data, $valuesOnly = false, $charset = null) + public static function htmlEncode($data, $valuesOnly = true, $charset = null) { if ($charset === null) { $charset = Yii::$app->charset; @@ -322,7 +322,7 @@ class ArrayHelper * @return array the decoded data * @see http://www.php.net/manual/en/function.htmlspecialchars-decode.php */ - public static function htmlDecode($data, $valuesOnly = false) + public static function htmlDecode($data, $valuesOnly = true) { $d = array(); foreach ($data as $key => $value) { diff --git a/framework/util/Html.php b/framework/util/Html.php index 8c29047..92c8f02 100644 --- a/framework/util/Html.php +++ b/framework/util/Html.php @@ -106,6 +106,7 @@ class Html 'checked', 'readonly', 'disabled', + 'multiple', 'size', 'maxlength', @@ -652,7 +653,7 @@ class Html * 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, $items, $selection = null, $attributes = array()) + public static function dropDownList($name, $items = array(), $selection = null, $attributes = array()) { $attributes['name'] = $name; $options = static::renderOptions($items, $selection, $attributes); @@ -693,7 +694,7 @@ class Html * 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()) + public static function listBox($name, $items = array(), $selection = null, $attributes = array()) { if (!isset($attributes['size'])) { $attributes['size'] = 4; @@ -742,7 +743,7 @@ class Html * value and the checked status of the checkbox input. * @return string the generated checkbox list */ - public static function checkboxList($name, $items, $selection = null, $options = array()) + public static function checkboxList($name, $items = array(), $selection = null, $options = array()) { if (substr($name, -2) !== '[]') { $name .= '[]'; @@ -800,7 +801,7 @@ class Html * value and the checked status of the radio button input. * @return string the generated radio button list */ - public static function radioList($name, $items, $selection = null, $options = array()) + public static function radioList($name, $items = array(), $selection = null, $options = array()) { $formatter = isset($options['item']) ? $options['item'] : null; $lines = array(); @@ -850,7 +851,7 @@ class Html { $lines = array(); if (isset($attributes['prompt'])) { - $prompt = strtr(static::encode($attributes['prompt']), ' ', ' '); + $prompt = str_replace(' ', ' ', static::encode($attributes['prompt'])); $lines[] = static::tag('option', $prompt, array('value' => '')); } @@ -863,7 +864,7 @@ class Html $groupAttrs = isset($groups[$key]) ? $groups[$key] : array(); $groupAttrs['label'] = $key; $attrs = array('options' => $options, 'groups' => $groups); - $content = static::renderOptions($selection, $value, $attrs); + $content = static::renderOptions($value, $selection, $attrs); $lines[] = static::tag('optgroup', "\n" . $content . "\n", $groupAttrs); } else { $attrs = isset($options[$key]) ? $options[$key] : array(); @@ -871,7 +872,7 @@ class Html $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), ' ', ' '), $attrs); + $lines[] = static::tag('option', str_replace(' ', ' ', static::encode($value)), $attrs); } } diff --git a/framework/web/Controller.php b/framework/web/Controller.php index 9420034..2779c35 100644 --- a/framework/web/Controller.php +++ b/framework/web/Controller.php @@ -16,8 +16,4 @@ namespace yii\web; */ class Controller extends \yii\base\Controller { - public function createUrl($route, $params = array()) - { - - } } \ No newline at end of file diff --git a/framework/web/Pagination.php b/framework/web/Pagination.php index 84585d6..1d41c0c 100644 --- a/framework/web/Pagination.php +++ b/framework/web/Pagination.php @@ -14,7 +14,7 @@ use Yii; * * When data needs to be rendered in multiple pages, Pagination can be used to * represent information such as [[itemCount|total item count]], [[pageSize|page size]], - * [[page|current page]], etc. These information can be passed to [[yii\web\widgets\Pager|pagers]] + * [[page|current page]], etc. These information can be passed to [[yii\widgets\Pager|pagers]] * to render pagination buttons or links. * * The following example shows how to create a pagination object and feed it @@ -47,7 +47,7 @@ use Yii; * } * * // display pagination - * $this->widget('yii\web\widgets\LinkPager', array( + * $this->widget('yii\widgets\LinkPager', array( * 'pages' => $pages, * )); * ~~~ diff --git a/framework/widgets/ActiveForm.php b/framework/widgets/ActiveForm.php new file mode 100644 index 0000000..77fd9fd --- /dev/null +++ b/framework/widgets/ActiveForm.php @@ -0,0 +1,6 @@ +assertEquals('', Html::tag('input', '', array('type' => 'text', 'name' => 'test', 'value' => '<>'))); Html::$closeVoidElements = true; + + $this->assertEquals('', Html::tag('span', '', array('disabled' => true))); + Html::$showBooleanAttributeValues = false; + $this->assertEquals('', Html::tag('span', '', array('disabled' => true))); + Html::$showBooleanAttributeValues = true; } public function testBeginTag() @@ -166,69 +171,263 @@ class HtmlTest extends \yii\test\TestCase public function testButtonInput() { + $this->assertEquals('', Html::buttonInput('test')); + $this->assertEquals('', Html::buttonInput('test', 'text', array('class' => 'a'))); } public function testSubmitInput() { + $this->assertEquals('', Html::submitInput()); + $this->assertEquals('', Html::submitInput('test', 'text', array('class' => 'a'))); } public function testResetInput() { + $this->assertEquals('', Html::resetInput()); + $this->assertEquals('', Html::resetInput('test', 'text', array('class' => 'a'))); } public function testTextInput() { + $this->assertEquals('', Html::textInput('test')); + $this->assertEquals('', Html::textInput('test', 'value', array('class' => 't'))); } public function testHiddenInput() { + $this->assertEquals('', Html::hiddenInput('test')); + $this->assertEquals('', Html::hiddenInput('test', 'value', array('class' => 't'))); } public function testPasswordInput() { + $this->assertEquals('', Html::passwordInput('test')); + $this->assertEquals('', Html::passwordInput('test', 'value', array('class' => 't'))); } public function testFileInput() { + $this->assertEquals('', Html::fileInput('test')); + $this->assertEquals('', Html::fileInput('test', 'value', array('class' => 't'))); } public function testTextarea() { + $this->assertEquals('', Html::textarea('test')); + $this->assertEquals('', Html::textarea('test', 'value<>', array('class' => 't'))); } public function testRadio() { + $this->assertEquals('', Html::radio('test')); + $this->assertEquals('', Html::radio('test', null, true, array('class' => 'a'))); + $this->assertEquals('', Html::radio('test', null, true, array('class' => 'a' ,'uncheck' => '0'))); } public function testCheckbox() { + $this->assertEquals('', Html::checkbox('test')); + $this->assertEquals('', Html::checkbox('test', null, true, array('class' => 'a'))); + $this->assertEquals('', Html::checkbox('test', null, true, array('class' => 'a' ,'uncheck' => '0'))); } public function testDropDownList() { + $this->assertEquals("", Html::dropDownList('test')); + $this->assertEquals("", Html::dropDownList('test', $this->getDataItems())); + $this->assertEquals("", Html::dropDownList('test', $this->getDataItems(), 'value2')); } public function testListBox() { + $expected = << + + +EOD; + $this->assertEquals($expected, Html::listBox('test')); + $expected = << + + + +EOD; + $this->assertEquals($expected, Html::listBox('test', $this->getDataItems(), null, array('size' => 5))); + $expected = << + + + +EOD; + $this->assertEquals($expected, Html::listBox('test', $this->getDataItems2(), null)); + $expected = << + + + +EOD; + $this->assertEquals($expected, Html::listBox('test', $this->getDataItems(), 'value2')); + $expected = << + + + +EOD; + $this->assertEquals($expected, Html::listBox('test', $this->getDataItems(), array('value1', 'value2'))); + + $expected = << + + +EOD; + $this->assertEquals($expected, Html::listBox('test', array(), null, array('multiple' => true))); + $expected = << +EOD; + $this->assertEquals($expected, Html::listBox('test', array(), '', array('unselect' => '0'))); } public function testCheckboxList() { + $this->assertEquals('', Html::checkboxList('test')); + + $expected = << text1 + +EOD; + $this->assertEquals($expected, Html::checkboxList('test', $this->getDataItems(), array('value2'))); + + $expected = << text1<> + +EOD; + $this->assertEquals($expected, Html::checkboxList('test', $this->getDataItems2(), array('value2'))); + + $expected = <<
+ +EOD; + $this->assertEquals($expected, Html::checkboxList('test', $this->getDataItems(), array('value2'), array( + 'separator' => "
\n", + 'unselect' => '0', + ))); + + $expected = <<text1 + +EOD; + $this->assertEquals($expected, Html::checkboxList('test', $this->getDataItems(), array('value2'), array( + 'item' => function ($index, $label, $name, $value, $checked) { + return Html::label($label . ' ' . Html::checkbox($name, $value, $checked)); + } + ))); } public function testRadioList() { + $this->assertEquals('', Html::radioList('test')); + + $expected = << text1 + +EOD; + $this->assertEquals($expected, Html::radioList('test', $this->getDataItems(), array('value2'))); + + $expected = << text1<> + +EOD; + $this->assertEquals($expected, Html::radioList('test', $this->getDataItems2(), array('value2'))); + + $expected = <<
+ +EOD; + $this->assertEquals($expected, Html::radioList('test', $this->getDataItems(), array('value2'), array( + 'separator' => "
\n", + 'unselect' => '0', + ))); + + $expected = <<text1 + +EOD; + $this->assertEquals($expected, Html::radioList('test', $this->getDataItems(), array('value2'), array( + 'item' => function ($index, $label, $name, $value, $checked) { + return Html::label($label . ' ' . Html::radio($name, $value, $checked)); + } + ))); } public function testRenderOptions() { + $this->assertEquals('', Html::renderOptions(array())); + + $data = array( + 'value1' => 'label1', + 'group1' => array( + 'value11' => 'label11', + 'group11' => array( + 'value111' => 'label111', + ), + 'group12' => array(), + ), + 'value2' => 'label2', + 'group2' => array(), + ); + $expected = <<please select<> + + + + + + + + + + + + + + +EOD; + $attributes = array( + 'prompt' => 'please select<>', + 'options' => array( + 'value111' => array('class' => 'option'), + ), + 'groups' => array( + 'group12' => array('class' => 'group'), + ), + ); + $this->assertEquals($expected, Html::renderOptions($data, array('value111', 'value1'), $attributes)); } public function testRenderAttributes() { + $this->assertEquals('', Html::renderAttributes(array())); + $this->assertEquals(' name="test" value="1<>"', Html::renderAttributes(array('name' => 'test', 'empty' => null, 'value' => '1<>'))); + Html::$showBooleanAttributeValues = false; + $this->assertEquals(' checked disabled', Html::renderAttributes(array('checked' => 'checked', 'disabled' => true, 'hidden' => false))); + Html::$showBooleanAttributeValues = true; + } + + protected function getDataItems() + { + return array( + 'value1' => 'text1', + 'value2' => 'text2', + ); } - public function testUrl() + protected function getDataItems2() { + return array( + 'value1<>' => 'text1<>', + 'value 2' => 'text 2', + ); } } diff --git a/todo.md b/todo.md index 03b9f70..4d5343a 100644 --- a/todo.md +++ b/todo.md @@ -32,8 +32,6 @@ memo * module - Module should be able to define its own configuration including routes. Application should be able to overwrite it. * application - * security - - backport 1.1 changes - built-in console commands + api doc builder * support for markdown syntax @@ -46,7 +44,6 @@ memo * parsing?? * make dates/date patterns uniform application-wide including JUI, formats etc. - helpers - * array * image * string * file @@ -59,8 +56,6 @@ memo * move generation API out of gii, provide yiic commands to use it. Use same templates for gii/yiic. * i18n variant of templates * allow to generate module-specific CRUD -- markup and HTML helpers - * use HTML5 instead of XHTML - assets * ability to manage scripts order (store these in a vector?) * http://ryanbigg.com/guides/asset_pipeline.html, http://guides.rubyonrails.org/asset_pipeline.html, use content hash instead of mtime + directory hash.