Commit 79598ca8 by Qiang Xue

Merge branch 'master' of github.com:yiisoft/yii2

parents 58ca27a4 68adc611
...@@ -216,12 +216,14 @@ Using a widget is more straightforward in 2.0. You mainly use the `begin()`, `en ...@@ -216,12 +216,14 @@ Using a widget is more straightforward in 2.0. You mainly use the `begin()`, `en
methods of the `Widget` class. For example, methods of the `Widget` class. For example,
```php ```php
// $this refers to the View object
// Note that you have to "echo" the result to display it // Note that you have to "echo" the result to display it
echo \yii\widgets\Menu::widget(array('items' => $items)); echo \yii\widgets\Menu::widget(array('items' => $items));
// $this refers to the View object // Passing an array to initialize the object properties
$form = \yii\widgets\ActiveForm::begin($this); $form = \yii\widgets\ActiveForm::begin(array(
'options' => array('class' => 'form-horizontal'),
'fieldConfig' => array('inputOptions' => array('class' => 'input-xlarge')),
));
... form inputs here ... ... form inputs here ...
\yii\widgets\ActiveForm::end(); \yii\widgets\ActiveForm::end();
``` ```
......
...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
"source": "https://github.com/yiisoft/yii2" "source": "https://github.com/yiisoft/yii2"
}, },
"require": { "require": {
"php": ">=5.3.11", "php": ">=5.3.7",
"ext-mbstring": "*", "ext-mbstring": "*",
"lib-pcre": "*" "lib-pcre": "*"
}, },
......
...@@ -9,7 +9,7 @@ namespace yii\base; ...@@ -9,7 +9,7 @@ namespace yii\base;
use ArrayObject; use ArrayObject;
use ArrayIterator; use ArrayIterator;
use yii\helpers\StringHelper; use yii\helpers\Inflector;
use yii\validators\RequiredValidator; use yii\validators\RequiredValidator;
use yii\validators\Validator; use yii\validators\Validator;
...@@ -504,7 +504,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess ...@@ -504,7 +504,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
*/ */
public function generateAttributeLabel($name) public function generateAttributeLabel($name)
{ {
return StringHelper::camel2words($name, true); return Inflector::camel2words($name, true);
} }
/** /**
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\bootstrap;
use yii\base\InvalidConfigException;
use yii\helpers\base\ArrayHelper;
use yii\helpers\Html;
/**
* Carousel renders a carousel bootstrap javascript component.
*
* For example:
*
* ```php
* echo Carousel::widget(array(
* 'items' => array(
* // the item contains only the image
* '<img src="http://twitter.github.io/bootstrap/assets/img/bootstrap-mdo-sfmoma-01.jpg"/>',
* // equivalent to the above
* array(
* 'content' => '<img src="http://twitter.github.io/bootstrap/assets/img/bootstrap-mdo-sfmoma-02.jpg"/>',
* ),
* // the item contains both the image and the caption
* array(
* 'content' => '<img src="http://twitter.github.io/bootstrap/assets/img/bootstrap-mdo-sfmoma-03.jpg"/>',
* 'caption' => '<h4>This is title</h4><p>This is the caption text</p>',
* 'options' => array(...),
* ),
* )
* ));
* ```
*
* @see http://twitter.github.io/bootstrap/javascript.html#carousel
* @author Antonio Ramirez <amigo.cobos@gmail.com>
* @since 2.0
*/
class Carousel extends Widget
{
/**
* @var array|boolean the labels for the previous and the next control buttons.
* If false, it means the previous and the next control buttons should not be displayed.
*/
public $controls = array('&lsaquo;', '&rsaquo;');
/**
* @var array list of slides in the carousel. Each array element represents a single
* slide with the following structure:
*
* ```php
* array(
* // required, slide content (HTML), such as an image tag
* 'content' => '<img src="http://twitter.github.io/bootstrap/assets/img/bootstrap-mdo-sfmoma-01.jpg"/>',
* // optional, the caption (HTML) of the slide
* 'caption'=> '<h4>This is title</h4><p>This is the caption text</p>',
* // optional the HTML attributes of the slide container
* 'options' => array(),
* )
* ```
*/
public $items = array();
/**
* Initializes the widget.
*/
public function init()
{
parent::init();
$this->addCssClass($this->options, 'carousel');
}
/**
* Renders the widget.
*/
public function run()
{
echo Html::beginTag('div', $this->options) . "\n";
echo $this->renderIndicators() . "\n";
echo $this->renderItems() . "\n";
echo $this->renderControls() . "\n";
echo Html::endTag('div') . "\n";
$this->registerPlugin('carousel');
}
/**
* Renders carousel indicators.
* @return string the rendering result
*/
public function renderIndicators()
{
$indicators = array();
for ($i = 0, $count = count($this->items); $i < $count; $i++) {
$options = array('data-target' => '#' . $this->options['id'], 'data-slide-to' => $i);
if ($i === 0) {
$this->addCssClass($options, 'active');
}
$indicators[] = Html::tag('li', '', $options);
}
return Html::tag('ol', implode("\n", $indicators), array('class' => 'carousel-indicators'));
}
/**
* Renders carousel items as specified on [[items]].
* @return string the rendering result
*/
public function renderItems()
{
$items = array();
for ($i = 0, $count = count($this->items); $i < $count; $i++) {
$items[] = $this->renderItem($this->items[$i], $i);
}
return Html::tag('div', implode("\n", $items), array('class' => 'carousel-inner'));
}
/**
* Renders a single carousel item
* @param string|array $item a single item from [[items]]
* @param integer $index the item index as the first item should be set to `active`
* @return string the rendering result
* @throws InvalidConfigException if the item is invalid
*/
public function renderItem($item, $index)
{
if (is_string($item)) {
$content = $item;
$caption = null;
$options = array();
} elseif (isset($item['content'])) {
$content = $item['content'];
$caption = ArrayHelper::getValue($item, 'caption');
if ($caption !== null) {
$caption = Html::tag('div', $caption, array('class' => 'carousel-caption'));
}
$options = ArrayHelper::getValue($item, 'options', array());
} else {
throw new InvalidConfigException('The "content" option is required.');
}
$this->addCssClass($options, 'item');
if ($index === 0) {
$this->addCssClass($options, 'active');
}
return Html::tag('div', $content . "\n" . $caption, $options);
}
/**
* Renders previous and next control buttons.
* @throws InvalidConfigException if [[controls]] is invalid.
*/
public function renderControls()
{
if (isset($this->controls[0], $this->controls[1])) {
return Html::a($this->controls[0], '#' . $this->options['id'], array(
'class' => 'left carousel-control',
'data-slide' => 'prev',
)) . "\n"
. Html::a($this->controls[1], '#' . $this->options['id'], array(
'class' => 'right carousel-control',
'data-slide' => 'next',
));
} elseif ($this->controls === false) {
return '';
} else {
throw new InvalidConfigException('The "controls" property must be either false or an array of two elements.');
}
}
}
...@@ -32,7 +32,7 @@ use yii\helpers\Html; ...@@ -32,7 +32,7 @@ use yii\helpers\Html;
* ```php * ```php
* echo TypeAhead::widget(array( * echo TypeAhead::widget(array(
* 'name' => 'country', * 'name' => 'country',
* 'cloentOptions' => array( * 'clientOptions' => array(
* 'source' => array('USA', 'ESP'), * 'source' => array('USA', 'ESP'),
* ), * ),
* )); * ));
......
...@@ -18,6 +18,7 @@ use yii\db\Connection; ...@@ -18,6 +18,7 @@ use yii\db\Connection;
use yii\db\TableSchema; use yii\db\TableSchema;
use yii\db\Expression; use yii\db\Expression;
use yii\helpers\StringHelper; use yii\helpers\StringHelper;
use yii\helpers\Inflector;
/** /**
* ActiveRecord is the base class for classes representing relational data in terms of objects. * ActiveRecord is the base class for classes representing relational data in terms of objects.
...@@ -261,14 +262,14 @@ class ActiveRecord extends Model ...@@ -261,14 +262,14 @@ class ActiveRecord extends Model
/** /**
* Declares the name of the database table associated with this AR class. * Declares the name of the database table associated with this AR class.
* By default this method returns the class name as the table name by calling [[StringHelper::camel2id()]] * By default this method returns the class name as the table name by calling [[Inflector::camel2id()]]
* with prefix 'tbl_'. For example, 'Customer' becomes 'tbl_customer', and 'OrderItem' becomes * with prefix 'tbl_'. For example, 'Customer' becomes 'tbl_customer', and 'OrderItem' becomes
* 'tbl_order_item'. You may override this method if the table is not named after this convention. * 'tbl_order_item'. You may override this method if the table is not named after this convention.
* @return string the table name * @return string the table name
*/ */
public static function tableName() public static function tableName()
{ {
return 'tbl_' . StringHelper::camel2id(StringHelper::basename(get_called_class()), '_'); return 'tbl_' . Inflector::camel2id(StringHelper::basename(get_called_class()), '_');
} }
/** /**
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\helpers;
/**
* Inflector pluralizes and singularizes English nouns. It also contains some other useful methods.
*
* @author Antonio Ramirez <amigo.cobos@gmail.com>
* @since 2.0
*/
class Inflector extends base\Inflector
{
}
...@@ -65,84 +65,4 @@ class StringHelper ...@@ -65,84 +65,4 @@ class StringHelper
} }
return $path; return $path;
} }
/**
* Converts a word to its plural form.
* Note that this is for English only!
* For example, 'apple' will become 'apples', and 'child' will become 'children'.
* @param string $name the word to be pluralized
* @return string the pluralized word
*/
public static function pluralize($name)
{
static $rules = array(
'/(m)ove$/i' => '\1oves',
'/(f)oot$/i' => '\1eet',
'/(c)hild$/i' => '\1hildren',
'/(h)uman$/i' => '\1umans',
'/(m)an$/i' => '\1en',
'/(s)taff$/i' => '\1taff',
'/(t)ooth$/i' => '\1eeth',
'/(p)erson$/i' => '\1eople',
'/([m|l])ouse$/i' => '\1ice',
'/(x|ch|ss|sh|us|as|is|os)$/i' => '\1es',
'/([^aeiouy]|qu)y$/i' => '\1ies',
'/(?:([^f])fe|([lr])f)$/i' => '\1\2ves',
'/(shea|lea|loa|thie)f$/i' => '\1ves',
'/([ti])um$/i' => '\1a',
'/(tomat|potat|ech|her|vet)o$/i' => '\1oes',
'/(bu)s$/i' => '\1ses',
'/(ax|test)is$/i' => '\1es',
'/s$/' => 's',
);
foreach ($rules as $rule => $replacement) {
if (preg_match($rule, $name)) {
return preg_replace($rule, $replacement, $name);
}
}
return $name . 's';
}
/**
* Converts a CamelCase name into space-separated words.
* For example, 'PostTag' will be converted to 'Post Tag'.
* @param string $name the string to be converted
* @param boolean $ucwords whether to capitalize the first letter in each word
* @return string the resulting words
*/
public static function camel2words($name, $ucwords = true)
{
$label = trim(strtolower(str_replace(array('-', '_', '.'), ' ', preg_replace('/(?<![A-Z])[A-Z]/', ' \0', $name))));
return $ucwords ? ucwords($label) : $label;
}
/**
* Converts a CamelCase name into an ID in lowercase.
* Words in the ID may be concatenated using the specified character (defaults to '-').
* For example, 'PostTag' will be converted to 'post-tag'.
* @param string $name the string to be converted
* @param string $separator the character used to concatenate the words in the ID
* @return string the resulting ID
*/
public static function camel2id($name, $separator = '-')
{
if ($separator === '_') {
return trim(strtolower(preg_replace('/(?<![A-Z])[A-Z]/', '_\0', $name)), '_');
} else {
return trim(strtolower(str_replace('_', $separator, preg_replace('/(?<![A-Z])[A-Z]/', $separator . '\0', $name))), $separator);
}
}
/**
* Converts an ID into a CamelCase name.
* Words in the ID separated by `$separator` (defaults to '-') will be concatenated into a CamelCase name.
* For example, 'post-tag' is converted to 'PostTag'.
* @param string $id the ID to be converted
* @param string $separator the character used to separate the words in the ID
* @return string the resulting CamelCase name
*/
public static function id2camel($id, $separator = '-')
{
return str_replace(' ', '', ucwords(implode(' ', explode($separator, $id))));
}
} }
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\jui;
use Yii;
use yii\base\InvalidConfigException;
use yii\base\Model;
use yii\helpers\Html;
/**
* AutoComplete renders an autocomplete jQuery UI widget.
*
* For example:
*
* ```php
* echo AutoComplete::widget(array(
* 'model' => $model,
* 'attribute' => 'country',
* 'clientOptions' => array(
* 'source' => array('USA', 'RUS'),
* ),
* ));
* ```
*
* The following example will use the name property instead:
*
* ```php
* echo AutoComplete::widget(array(
* 'name' => 'country',
* 'clientOptions' => array(
* 'source' => array('USA', 'RUS'),
* ),
* ));
*```
*
* @see http://api.jqueryui.com/autocomplete/
* @author Alexander Kochetov <creocoder@gmail.com>
* @since 2.0
*/
class AutoComplete extends Widget
{
/**
* @var \yii\base\Model the data model that this widget is associated with.
*/
public $model;
/**
* @var string the model attribute that this widget is associated with.
*/
public $attribute;
/**
* @var string the input name. This must be set if [[model]] and [[attribute]] are not set.
*/
public $name;
/**
* @var string the input value.
*/
public $value;
/**
* Renders the widget.
*/
public function run()
{
echo $this->renderField();
$this->registerWidget('autocomplete');
}
/**
* Renders the AutoComplete field. If [[model]] has been specified then it will render an active field.
* If [[model]] is null or not from an [[Model]] instance, then the field will be rendered according to
* the [[name]] attribute.
* @return string the rendering result.
* @throws InvalidConfigException when none of the required attributes are set to render the textInput.
* That is, if [[model]] and [[attribute]] are not set, then [[name]] is required.
*/
public function renderField()
{
if ($this->model instanceof Model && $this->attribute !== null) {
return Html::activeTextInput($this->model, $this->attribute, $this->options);
} elseif ($this->name !== null) {
return Html::textInput($this->name, $this->value, $this->options);
} else {
throw new InvalidConfigException("Either 'name' or 'model' and 'attribute' properties must be specified.");
}
}
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\jui;
use Yii;
use yii\base\View;
use yii\helpers\Json;
/**
* \yii\jui\Widget is the base class for all jQuery UI widgets.
*
* @author Alexander Kochetov <creocoder@gmail.com>
* @since 2.0
*/
class Widget extends \yii\base\Widget
{
/**
* @var string the jQuery UI theme bundle.
*/
public static $theme = 'yii/jui/theme/base';
/**
* @var array the HTML attributes for the widget container tag.
*/
public $options = array();
/**
* @var array the options for the underlying jQuery UI widget.
* Please refer to the corresponding jQuery UI widget Web page for possible options.
* For example, [this page](http://api.jqueryui.com/accordion/) shows
* how to use the "Accordion" widget and the supported options (e.g. "header").
*/
public $clientOptions = array();
/**
* @var array the event handlers for the underlying jQuery UI widget.
* Please refer to the corresponding jQuery UI widget Web page for possible events.
* For example, [this page](http://api.jqueryui.com/accordion/) shows
* how to use the "Accordion" widget and the supported events (e.g. "create").
*/
public $clientEvents = array();
/**
* Initializes the widget.
* If you override this method, make sure you call the parent implementation first.
*/
public function init()
{
parent::init();
if (!isset($this->options['id'])) {
$this->options['id'] = $this->getId();
}
}
/**
* Registers a specific jQuery UI widget and the related events
* @param string $name the name of the jQuery UI widget
*/
protected function registerWidget($name)
{
$id = $this->options['id'];
$view = $this->getView();
$view->registerAssetBundle("yii/jui/$name");
$view->registerAssetBundle(static::$theme . "/$name");
if ($this->clientOptions !== false) {
$options = empty($this->clientOptions) ? '' : Json::encode($this->clientOptions);
$js = "jQuery('#$id').$name($options);";
$view->registerJs($js);
}
if (!empty($this->clientEvents)) {
$js = array();
foreach ($this->clientEvents as $event => $handler) {
$js[] = "jQuery('#$id').on('$name$event', $handler);";
}
$view->registerJs(implode("\n", $js));
}
}
}
...@@ -9,9 +9,9 @@ return array( ...@@ -9,9 +9,9 @@ return array(
array( array(
'name' => 'PHP version', 'name' => 'PHP version',
'mandatory' => true, 'mandatory' => true,
'condition' => version_compare(PHP_VERSION, '5.3.11', '>='), 'condition' => version_compare(PHP_VERSION, '5.3.7', '>='),
'by' => '<a href="http://www.yiiframework.com">Yii Framework</a>', 'by' => '<a href="http://www.yiiframework.com">Yii Framework</a>',
'memo' => 'PHP 5.3.11 or higher is required.', 'memo' => 'PHP 5.3.7 or higher is required.',
), ),
array( array(
'name' => 'Reflection extension', 'name' => 'Reflection extension',
......
...@@ -26,7 +26,6 @@ use yii\helpers\Html; ...@@ -26,7 +26,6 @@ use yii\helpers\Html;
* The following example shows how to use Menu: * The following example shows how to use Menu:
* *
* ~~~ * ~~~
* // $this is the view object currently being used
* echo Menu::widget(array( * echo Menu::widget(array(
* 'items' => array( * 'items' => array(
* // Important: you need to specify url as 'controller/action', * // Important: you need to specify url as 'controller/action',
......
<?php
namespace yiiunit\framework\helpers;
use Yii;
use yii\helpers\Inflector;
use yiiunit\TestCase;
class InflectorTest extends TestCase
{
public function testPluralize()
{
$testData = array(
'move' => 'moves',
'foot' => 'feet',
'child' => 'children',
'human' => 'humans',
'man' => 'men',
'staff' => 'staff',
'tooth' => 'teeth',
'person' => 'people',
'mouse' => 'mice',
'touch' => 'touches',
'hash' => 'hashes',
'shelf' => 'shelves',
'potato' => 'potatoes',
'bus' => 'buses',
'test' => 'tests',
'car' => 'cars',
);
foreach ($testData as $testIn => $testOut) {
$this->assertEquals($testOut, Inflector::pluralize($testIn));
$this->assertEquals(ucfirst($testOut), ucfirst(Inflector::pluralize($testIn)));
}
}
public function testSingularize()
{
$testData = array(
'moves' => 'move',
'feet' => 'foot',
'children' => 'child',
'humans' => 'human',
'men' => 'man',
'staff' => 'staff',
'teeth' => 'tooth',
'people' => 'person',
'mice' => 'mouse',
'touches' => 'touch',
'hashes' => 'hash',
'shelves' => 'shelf',
'potatoes' => 'potato',
'buses' => 'bus',
'tests' => 'test',
'cars' => 'car',
);
foreach ($testData as $testIn => $testOut) {
$this->assertEquals($testOut, Inflector::singularize($testIn));
$this->assertEquals(ucfirst($testOut), ucfirst(Inflector::singularize($testIn)));
}
}
public function testTitleize()
{
$this->assertEquals("Me my self and i", Inflector::titleize('MeMySelfAndI'));
$this->assertEquals("Me My Self And I", Inflector::titleize('MeMySelfAndI', true));
}
public function testCamelize()
{
$this->assertEquals("MeMySelfAndI", Inflector::camelize('me my_self-andI'));
}
public function testUnderscore()
{
$this->assertEquals("me_my_self_and_i", Inflector::underscore('MeMySelfAndI'));
}
public function testCamel2words()
{
$this->assertEquals('Camel Case', Inflector::camel2words('camelCase'));
$this->assertEquals('Lower Case', Inflector::camel2words('lower_case'));
$this->assertEquals('Tricky Stuff It Is Testing', Inflector::camel2words(' tricky_stuff.it-is testing... '));
}
public function testCamel2id()
{
$this->assertEquals('post-tag', Inflector::camel2id('PostTag'));
$this->assertEquals('post_tag', Inflector::camel2id('PostTag', '_'));
$this->assertEquals('post-tag', Inflector::camel2id('postTag'));
$this->assertEquals('post_tag', Inflector::camel2id('postTag', '_'));
}
public function testId2camel()
{
$this->assertEquals('PostTag', Inflector::id2camel('post-tag'));
$this->assertEquals('PostTag', Inflector::id2camel('post_tag', '_'));
$this->assertEquals('PostTag', Inflector::id2camel('post-tag'));
$this->assertEquals('PostTag', Inflector::id2camel('post_tag', '_'));
}
public function testHumanize()
{
$this->assertEquals("Me my self and i", Inflector::humanize('me_my_self_and_i'));
$this->assertEquals("Me My Self And I", Inflector::humanize('me_my_self_and_i', true));
}
public function testVariablize()
{
$this->assertEquals("customerTable", Inflector::variablize('customer_table'));
}
public function testTableize()
{
$this->assertEquals("customer_tables", Inflector::tableize('customerTable'));
}
public function testSlug()
{
$this->assertEquals("this-is-a-title", Inflector::slug('this is a title'));
}
public function testClassify()
{
$this->assertEquals("CustomerTable", Inflector::classify('customer_tables'));
}
public function testOrdinalize()
{
$this->assertEquals('21st', Inflector::ordinalize('21'));
}
}
...@@ -19,58 +19,6 @@ class StringHelperTest extends \yii\test\TestCase ...@@ -19,58 +19,6 @@ class StringHelperTest extends \yii\test\TestCase
$this->assertEquals('э', StringHelper::substr('это', 0, 2)); $this->assertEquals('э', StringHelper::substr('это', 0, 2));
} }
public function testPluralize()
{
$testData = array(
'move' => 'moves',
'foot' => 'feet',
'child' => 'children',
'human' => 'humans',
'man' => 'men',
'staff' => 'staff',
'tooth' => 'teeth',
'person' => 'people',
'mouse' => 'mice',
'touch' => 'touches',
'hash' => 'hashes',
'shelf' => 'shelves',
'potato' => 'potatoes',
'bus' => 'buses',
'test' => 'tests',
'car' => 'cars',
);
foreach ($testData as $testIn => $testOut) {
$this->assertEquals($testOut, StringHelper::pluralize($testIn));
$this->assertEquals(ucfirst($testOut), ucfirst(StringHelper::pluralize($testIn)));
}
}
public function testCamel2words()
{
$this->assertEquals('Camel Case', StringHelper::camel2words('camelCase'));
$this->assertEquals('Lower Case', StringHelper::camel2words('lower_case'));
$this->assertEquals('Tricky Stuff It Is Testing', StringHelper::camel2words(' tricky_stuff.it-is testing... '));
}
public function testCamel2id()
{
$this->assertEquals('post-tag', StringHelper::camel2id('PostTag'));
$this->assertEquals('post_tag', StringHelper::camel2id('PostTag', '_'));
$this->assertEquals('post-tag', StringHelper::camel2id('postTag'));
$this->assertEquals('post_tag', StringHelper::camel2id('postTag', '_'));
}
public function testId2camel()
{
$this->assertEquals('PostTag', StringHelper::id2camel('post-tag'));
$this->assertEquals('PostTag', StringHelper::id2camel('post_tag', '_'));
$this->assertEquals('PostTag', StringHelper::id2camel('post-tag'));
$this->assertEquals('PostTag', StringHelper::id2camel('post_tag', '_'));
}
public function testBasename() public function testBasename()
{ {
$this->assertEquals('', StringHelper::basename('')); $this->assertEquals('', StringHelper::basename(''));
......
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