Browse Source

Merge branch 'master' of github.com:yiisoft/yii2-bootstrap into html-helper

tags/2.0.6
Klimov Paul 10 years ago
parent
commit
723c1f7299
  1. 6
      .gitignore
  2. 2
      .travis.yml
  3. 12
      Alert.php
  4. 2
      ButtonDropdown.php
  5. 4
      ButtonGroup.php
  6. 12
      CHANGELOG.md
  7. 6
      Collapse.php
  8. 22
      Dropdown.php
  9. 26
      Makefile
  10. 24
      Modal.php
  11. 22
      Tabs.php
  12. 2
      Widget.php
  13. 6
      composer.json
  14. 4
      docs/guide-pt-BR/basic-usage.md
  15. 2
      docs/guide-pt-BR/installation.md
  16. 35
      tests/CollapseTest.php
  17. 42
      tests/DropdownTest.php
  18. 37
      tests/TabsTest.php
  19. 27
      tests/data/Singer.php

6
.gitignore vendored

@ -24,3 +24,9 @@ composer.phar
phpunit.phar
# local phpunit config
/phpunit.xml
/tests/runtime
/tests/data/config.local.php
/tests/docker
/tests/dockerids

2
.travis.yml

@ -26,7 +26,7 @@ cache:
install:
- travis_retry composer self-update && composer --version
- travis_retry composer global require "fxp/composer-asset-plugin:1.0.0"
- travis_retry composer global require "fxp/composer-asset-plugin:~1.0.0"
- export PATH="$HOME/.composer/vendor/bin:$PATH"
- travis_retry composer install --prefer-dist --no-interaction

12
Alert.php

@ -117,14 +117,14 @@ class Alert extends Widget
*/
protected function renderCloseButton()
{
if ($this->closeButton !== false) {
$tag = ArrayHelper::remove($this->closeButton, 'tag', 'button');
$label = ArrayHelper::remove($this->closeButton, 'label', '×');
if ($tag === 'button' && !isset($this->closeButton['type'])) {
$this->closeButton['type'] = 'button';
if (($closeButton = $this->closeButton) !== false) {
$tag = ArrayHelper::remove($closeButton, 'tag', 'button');
$label = ArrayHelper::remove($closeButton, 'label', '×');
if ($tag === 'button' && !isset($closeButton['type'])) {
$closeButton['type'] = 'button';
}
return Html::tag($tag, $label, $this->closeButton);
return Html::tag($tag, $label, $closeButton);
} else {
return null;
}

2
ButtonDropdown.php

@ -81,7 +81,7 @@ class ButtonDropdown extends Widget
$this->registerPlugin('button');
return implode("\n", [
Html::beginTag($tag, $this->containerOptions),
Html::beginTag($tag, $options),
$this->renderButton(),
$this->renderDropdown(),
Html::endTag($tag)

4
ButtonGroup.php

@ -33,8 +33,12 @@ use yii\helpers\Html;
* ]
* ]);
* ```
*
* Pressing on the button should be handled via JavaScript. See the following for details:
*
* @see http://getbootstrap.com/javascript/#buttons
* @see http://getbootstrap.com/components/#btn-groups
*
* @author Antonio Ramirez <amigo.cobos@gmail.com>
* @since 2.0
*/

12
CHANGELOG.md

@ -1,18 +1,28 @@
Yii Framework 2 bootstrap extension Change Log
==============================================
2.0.4 under development
2.0.5 under development
-----------------------
- Enh #38: Added object support for `content` option in `Collapse` class (pana1990, ItsReddi)
- Enh #40: Added `visible` option to `yii\bootstrap\Tab` widget items (klimov-paul)
- Enh #41: Added `submenuOptions` support at `yii\bootstrap\Dropdown` (spikyjt, klimov-paul)
2.0.4 May 10, 2015
------------------
- Bug #18: `label` option ignored by `yii\bootstrap\Activefield::checkbox()` and `yii\bootstrap\Activefield::radio()` (mikehaertl)
- Bug #5984: `yii\bootstrap\Activefield::checkbox()` caused browser to link label to the wrong input (cebe)
- Bug #7894: Fixed incorrect URL config processing at `yii\bootstrap\Nav::items` if route element is not a first one (nkovacs, klimov-paul)
- Bug #8231: Configuration of Alert, ButtonDropdown, Modal widget where not preserved when used multiple times (cebe, idMolotov)
- Bug (CVE-2015-3397): Using `Json::htmlEncode()` for safer JSON data encoding in HTML code (samdark, Tomasz Tokarski)
- Enh #29: Added support to list-groups for Collapse class (pana1990, skullcrasher)
- Enh #1344: Added support for the static form controls via `yii\bootstrap\Html` (klimov-paul)
- Enh #2546: Added `visible` option to `yii\bootstrap\ButtonGroup::$buttons` (samdark, lukBarros)
- Enh #5207: Added support for the glyphicons via `yii\bootstrap\Html::icon()` (klimov-paul)
- Enh #7633: Added `ActionColumn::$buttonOptions` for defining HTML options to be added to the default buttons (cebe)
- Enh: Added `Nav::$dropDownCaret` to allow customization of the dropdown caret symbol (cebe)
- Enh: Added support for using external URLs for `Tabs`. (dynasource, qiangxue)
2.0.3 March 01, 2015

6
Collapse.php

@ -61,7 +61,7 @@ class Collapse extends Widget
* - label: string, required, the group header label.
* - encode: boolean, optional, whether this label should be HTML-encoded. This param will override
* global `$this->encodeLabels` param.
* - content: array|string, required, the content (HTML) of the group
* - content: array|string|object, required, the content (HTML) of the group
* - options: array, optional, the HTML attributes of the group
* - contentOptions: optional, the HTML attributes of the group's content
*/
@ -146,7 +146,7 @@ class Collapse extends Widget
$header = Html::tag('h4', $headerToggle, ['class' => 'panel-title']);
if (is_string($item['content'])) {
if (is_string($item['content']) || is_object($item['content'])) {
$content = Html::tag('div', $item['content'], ['class' => 'panel-body']) . "\n";
} elseif (is_array($item['content'])) {
$content = Html::ul($item['content'], [
@ -160,7 +160,7 @@ class Collapse extends Widget
$content .= Html::tag('div', $item['footer'], ['class' => 'panel-footer']) . "\n";
}
} else {
throw new InvalidConfigException('The "content" option should be a string or array.');
throw new InvalidConfigException('The "content" option should be a string, array or object.');
}
} else {
throw new InvalidConfigException('The "content" option is required.');

22
Dropdown.php

@ -48,6 +48,8 @@ class Dropdown extends Widget
* - options: array, optional, the HTML attributes of the item.
* - items: array, optional, the submenu items. The structure is the same as this property.
* Note that Bootstrap doesn't support dropdown submenu. You have to add your own CSS styles to support it.
* - submenuOptions: array, optional, the HTML attributes for sub-menu container tag. If specified it will be
* merged with [[submenuOptions]].
*
* To insert divider use `<li role="presentation" class="divider"></li>`.
*/
@ -56,6 +58,12 @@ class Dropdown extends Widget
* @var boolean whether the labels for header items should be HTML-encoded.
*/
public $encodeLabels = true;
/**
* @var array|null the HTML attributes for sub-menu container tags.
* If not set - [[options]] value will be used for it.
* @since 2.0.5
*/
public $submenuOptions;
/**
@ -64,6 +72,12 @@ class Dropdown extends Widget
*/
public function init()
{
if ($this->submenuOptions === null) {
// copying of [[options]] kept for BC
// @todo separate [[submenuOptions]] from [[options]] completely before 2.1 release
$this->submenuOptions = $this->options;
unset($this->submenuOptions['id']);
}
parent::init();
Html::addCssClass($this->options, 'dropdown-menu');
}
@ -88,7 +102,7 @@ class Dropdown extends Widget
protected function renderItems($items, $options = [])
{
$lines = [];
foreach ($items as $i => $item) {
foreach ($items as $item) {
if (isset($item['visible']) && !$item['visible']) {
continue;
}
@ -113,8 +127,10 @@ class Dropdown extends Widget
$content = Html::a($label, $url, $linkOptions);
}
} else {
$submenuOptions = $options;
unset($submenuOptions['id']);
$submenuOptions = $this->submenuOptions;
if (isset($item['submenuOptions'])) {
$submenuOptions = array_merge($submenuOptions, $item['submenuOptions']);
}
$content = Html::a($label, $url === null ? '#' : $url, $linkOptions)
. $this->renderItems($item['items'], $submenuOptions);
Html::addCssClass($itemOptions, 'dropdown-submenu');

26
Makefile

@ -0,0 +1,26 @@
# default versions to test against
# these can be overridden by setting the environment variables in the shell
PHP_VERSION=php-5.6.8
YII_VERSION=dev-master
# ensure all the configuration variables above are in environment of the shell commands below
export
help:
@echo "make test - run phpunit tests using a docker environment"
# @echo "make clean - stop docker and remove container"
test: docker-php
composer require "yiisoft/yii2:${YII_VERSION}" --prefer-dist
composer install --prefer-dist
docker run --rm=true -v $(shell pwd):/opt/test yiitest/php:${PHP_VERSION} phpunit --verbose --color
docker-php: dockerfiles
cd tests/docker/php && sh build.sh
dockerfiles:
test -d tests/docker || git clone https://github.com/cebe/jenkins-test-docker tests/docker
cd tests/docker && git checkout -- . && git pull
mkdir -p tests/dockerids

24
Modal.php

@ -182,14 +182,14 @@ class Modal extends Widget
*/
protected function renderToggleButton()
{
if ($this->toggleButton !== false) {
$tag = ArrayHelper::remove($this->toggleButton, 'tag', 'button');
$label = ArrayHelper::remove($this->toggleButton, 'label', 'Show');
if ($tag === 'button' && !isset($this->toggleButton['type'])) {
$this->toggleButton['type'] = 'button';
if (($toggleButton = $this->toggleButton) !== false) {
$tag = ArrayHelper::remove($toggleButton, 'tag', 'button');
$label = ArrayHelper::remove($toggleButton, 'label', 'Show');
if ($tag === 'button' && !isset($toggleButton['type'])) {
$toggleButton['type'] = 'button';
}
return Html::tag($tag, $label, $this->toggleButton);
return Html::tag($tag, $label, $toggleButton);
} else {
return null;
}
@ -201,14 +201,14 @@ class Modal extends Widget
*/
protected function renderCloseButton()
{
if ($this->closeButton !== false) {
$tag = ArrayHelper::remove($this->closeButton, 'tag', 'button');
$label = ArrayHelper::remove($this->closeButton, 'label', '&times;');
if ($tag === 'button' && !isset($this->closeButton['type'])) {
$this->closeButton['type'] = 'button';
if (($closeButton = $this->closeButton) !== false) {
$tag = ArrayHelper::remove($closeButton, 'tag', 'button');
$label = ArrayHelper::remove($closeButton, 'label', '&times;');
if ($tag === 'button' && !isset($closeButton['type'])) {
$closeButton['type'] = 'button';
}
return Html::tag($tag, $label, $this->closeButton);
return Html::tag($tag, $label, $closeButton);
} else {
return null;
}

22
Tabs.php

@ -31,6 +31,10 @@ use yii\helpers\Html;
* 'options' => ['id' => 'myveryownID'],
* ],
* [
* 'label' => 'Example',
* 'url' => 'http://www.example.com',
* ],
* [
* 'label' => 'Dropdown',
* 'items' => [
* [
@ -63,8 +67,12 @@ class Tabs extends Widget
* - headerOptions: array, optional, the HTML attributes of the tab header.
* - linkOptions: array, optional, the HTML attributes of the tab header link tags.
* - content: string, optional, the content (HTML) of the tab pane.
* - url: string, optional, an external URL. When this is specified, clicking on this tab will bring
* the browser to this URL. This option is available since version 2.0.4.
* - options: array, optional, the HTML attributes of the tab pane container.
* - active: boolean, optional, whether the item tab header and pane should be visible or not.
* - active: boolean, optional, whether this item tab header and pane should be active. If no item is marked as
* 'active' explicitly - the first one will be activated.
* - visible: boolean, optional, whether the item tab header and pane should be visible or not. Defaults to true.
* - items: array, optional, can be used instead of `content` to specify a dropdown items
* configuration array. Each item can hold three extra keys, besides the above ones:
* * active: boolean, optional, whether the item tab header and pane should be visible or not.
@ -142,6 +150,9 @@ class Tabs extends Widget
}
foreach ($this->items as $n => $item) {
if (!ArrayHelper::remove($item, 'visible', true)) {
continue;
}
if (!array_key_exists('label', $item)) {
throw new InvalidConfigException("The 'label' option is required.");
}
@ -171,8 +182,14 @@ class Tabs extends Widget
Html::addCssClass($options, 'active');
Html::addCssClass($headerOptions, 'active');
}
if (isset($item['url'])) {
$header = Html::a($label, $item['url'], $linkOptions);
} else {
$linkOptions['data-toggle'] = 'tab';
$header = Html::a($label, '#' . $options['id'], $linkOptions);
}
if ($this->renderTabContent) {
$panes[] = Html::tag('div', isset($item['content']) ? $item['content'] : '', $options);
}
@ -216,6 +233,9 @@ class Tabs extends Widget
if (is_string($item)) {
continue;
}
if (isset($item['visible']) && !$item['visible']) {
continue;
}
if (!array_key_exists('content', $item)) {
throw new InvalidConfigException("The 'content' option is required.");
}

2
Widget.php

@ -66,7 +66,7 @@ class Widget extends \yii\base\Widget
$id = $this->options['id'];
if ($this->clientOptions !== false) {
$options = empty($this->clientOptions) ? '' : Json::encode($this->clientOptions);
$options = empty($this->clientOptions) ? '' : Json::htmlEncode($this->clientOptions);
$js = "jQuery('#$id').$name($options);";
$view->registerJs($js);
}

6
composer.json

@ -5,11 +5,11 @@
"type": "yii2-extension",
"license": "BSD-3-Clause",
"support": {
"issues": "https://github.com/yiisoft/yii2/issues?labels=ext%3Abootstrap",
"issues": "https://github.com/yiisoft/yii2-bootstrap/issues",
"forum": "http://www.yiiframework.com/forum/",
"wiki": "http://www.yiiframework.com/wiki/",
"irc": "irc://irc.freenode.net/yii",
"source": "https://github.com/yiisoft/yii2"
"source": "https://github.com/yiisoft/yii2-bootstrap"
},
"authors": [
{
@ -18,7 +18,7 @@
}
],
"require": {
"yiisoft/yii2": "*",
"yiisoft/yii2": ">=2.0.4",
"bower-asset/bootstrap": "3.3.* | 3.2.* | 3.1.*"
},
"autoload": {

4
docs/guide-pt-BR/basic-usage.md

@ -1,8 +1,8 @@
Uso Básico
===========
O Yii Não registra os básico componentes básicos do bootstrap em código PHP visto que esse HTML é muito simples, por si só.
Você pode encontrar detalhes sobre como usar o básico no [site documentação do bootstrap] (http://getbootstrap.com/css/). O Yii ainda fornece uma
O Yii Não registra os componentes básicos do bootstrap em código PHP visto que esse HTML é muito simples, por si só.
Você pode encontrar detalhes sobre como usar o básico no [site documentação do Bootstrap] (http://getbootstrap.com/css/). O Yii ainda fornece uma
forma conveniente para incluir assets de bootstrap em suas páginas com uma única linha adicionado ao arquivo `AppAsset.php` localizado no seu
diretório `@app/assets`:

2
docs/guide-pt-BR/installation.md

@ -1,4 +1,4 @@
Installation
Instalação
============
## Instalando através do composer

35
tests/CollapseTest.php

@ -108,4 +108,39 @@ class CollapseTest extends TestCase
HTML
, $output);
}
/**
* @see https://github.com/yiisoft/yii2/issues/8357
*/
public function testRenderObject()
{
$template = ['template' => '{input}'];
ob_start();
$form = \yii\widgets\ActiveForm::begin(['action' => '/something']);
ob_end_clean();
$model = new data\Singer;
Collapse::$counter = 0;
$output = Collapse::widget([
'items' => [
[
'label' => 'Collapsible Group Item #1',
'content' => $form->field($model, 'firstName', $template)
],
]
]);
$this->assertEqualsWithoutLE(<<<HTML
<div id="w0" class="panel-group">
<div class="panel panel-default"><div class="panel-heading"><h4 class="panel-title"><a class="collapse-toggle" href="#w0-collapse1" data-toggle="collapse" data-parent="#w0">Collapsible Group Item #1</a>
</h4></div>
<div id="w0-collapse1" class="panel-collapse collapse"><div class="panel-body"><div class="form-group field-singer-firstname">
<input type="text" id="singer-firstname" class="form-control" name="Singer[firstName]">
</div></div>
</div></div>
</div>
HTML
, $output);
}
}

42
tests/DropdownTest.php

@ -41,10 +41,50 @@ class DropdownTest extends TestCase
$expected = <<<EXPECTED
<ul id="w0" class="dropdown-menu"><li class="dropdown-header">Page1</li>
<li class="dropdown-submenu"><a href="#" tabindex="-1">Dropdown1</a><ul class="dropdown-menu"><li class="dropdown-header">Page2</li>
<li class="dropdown-submenu"><a href="#" tabindex="-1">Dropdown1</a><ul><li class="dropdown-header">Page2</li>
<li class="dropdown-header">Page3</li></ul></li></ul>
EXPECTED;
$this->assertEqualsWithoutLE($expected, $out);
}
public function testSubMenuOptions()
{
Dropdown::$counter = 0;
$out = Dropdown::widget(
[
'submenuOptions' => [
'class' => 'submenu-list',
],
'items' => [
[
'label' => 'Dropdown1',
'items' => [
['label' => 'Page1', 'content' => 'Page2'],
['label' => 'Page2', 'content' => 'Page3'],
]
],
[
'label' => 'Dropdown2',
'items' => [
['label' => 'Page3', 'content' => 'Page4'],
['label' => 'Page4', 'content' => 'Page5'],
],
'submenuOptions' => [
'class' => 'submenu-override',
],
]
]
]
);
$expected = <<<EXPECTED
<ul id="w0" class="dropdown-menu"><li class="dropdown-submenu"><a href="#" tabindex="-1">Dropdown1</a><ul class="submenu-list"><li class="dropdown-header">Page1</li>
<li class="dropdown-header">Page2</li></ul></li>
<li class="dropdown-submenu"><a href="#" tabindex="-1">Dropdown2</a><ul class="submenu-override"><li class="dropdown-header">Page3</li>
<li class="dropdown-header">Page4</li></ul></li></ul>
EXPECTED;
$this->assertEqualsWithoutLE($expected, $out);
}
}

37
tests/TabsTest.php

@ -2,6 +2,7 @@
namespace yiiunit\extensions\bootstrap;
use yii\bootstrap\Tabs;
use yii\helpers\Html;
/**
* Tests for Tabs widget
@ -36,7 +37,10 @@ class TabsTest extends TestCase
['label' => 'Page4', 'content' => 'Page4'],
['label' => 'Page5', 'content' => 'Page5'],
]
]
],
[
'label' => $extAnchor = 'External link', 'url' => $extUrl = ['//other/route'],
],
]
]);
@ -65,10 +69,41 @@ class TabsTest extends TestCase
"id=\"$page3\"",
"id=\"$page4\"",
"id=\"$page5\"",
Html::a($extAnchor,$extUrl),
];
foreach ($shouldContain as $string) {
$this->assertContains($string, $out);
}
}
public function testVisible()
{
Tabs::$counter = 0;
$html = Tabs::widget([
'items' => [
[
'label' => 'Page1', 'content' => 'Page1',
],
[
'label' => 'InvisiblePage',
'content' => 'Invisible Page Content',
'visible' => false
],
[
'label' => 'Dropdown1',
'items' => [
['label' => 'Page2', 'content' => 'Page2'],
['label' => 'InvisibleItem', 'content' => 'Invisible Item Content', 'visible' => false],
['label' => 'Page3', 'content' => 'Page3'],
]
],
]
]);
$this->assertNotContains('InvisiblePage', $html);
$this->assertNotContains('Invisible Page Content', $html);
$this->assertNotContains('InvisibleItem', $html);
$this->assertNotContains('Invisible Item Content', $html);
}
}

27
tests/data/Singer.php

@ -0,0 +1,27 @@
<?php
namespace yiiunit\extensions\bootstrap\data;
use yii\base\Model;
/**
* Class Singer
*
* @author Daniel Gomez Pan <pana_1990@hotmail.com>
*/
class Singer extends Model
{
public $firstName;
public $lastName;
public $test;
public function rules()
{
return [
[['lastName'], 'default', 'value' => 'Lennon'],
[['lastName'], 'required'],
[['underscore_style'], 'yii\captcha\CaptchaValidator'],
[['test'], 'required', 'when' => function($model) { return $model->firstName === 'cebe'; }],
];
}
}
Loading…
Cancel
Save