Commit bf22d96b by Qiang Xue

Merge branch 'master' of git.yiisoft.com:yii2

parents 989b8fa5 a578938d
<?php
defined('YII_DEBUG') or define('YII_DEBUG', true);
require(__DIR__ . '/../framework/yii.php');
$config = require(__DIR__ . '/protected/config/main.php');
$application = new yii\web\Application($config);
$application->run();
<?php
return array(
'id' => 'hello',
'basePath' => dirname(__DIR__),
'components' => array(
'cache' => array(
'class' => 'yii\caching\FileCache',
),
'user' => array(
'class' => 'yii\web\User',
'identityClass' => 'app\models\User',
)
),
);
\ No newline at end of file
<?php
class SiteController extends \yii\web\Controller
{
public function actionIndex()
{
echo $this->render('index');
}
public function actionLogin()
{
$user = app\models\User::findIdentity(100);
Yii::$app->getUser()->login($user);
Yii::$app->getResponse()->redirect(array('site/index'));
}
public function actionLogout()
{
Yii::$app->getUser()->logout();
Yii::$app->getResponse()->redirect(array('site/index'));
}
}
\ No newline at end of file
<?php
namespace app\models;
class User extends \yii\base\Object implements \yii\web\Identity
{
public $id;
public $name;
public $authKey;
private static $users = array(
'100' => array(
'id' => '100',
'authKey' => 'test100key',
'name' => 'admin',
),
'101' => array(
'id' => '101',
'authKey' => 'test101key',
'name' => 'demo',
),
);
public static function findIdentity($id)
{
return isset(self::$users[$id]) ? new self(self::$users[$id]) : null;
}
public function getId()
{
return $this->id;
}
public function getAuthKey()
{
return $this->authKey;
}
public function validateAuthKey($authKey)
{
return $this->authKey === $authKey;
}
}
\ No newline at end of file
<?php
/**
* @var $this \yii\base\View
* @var $content string
*/
use yii\helpers\Html;
?>
<!DOCTYPE html>
<html>
<?php $this->beginPage(); ?>
<head>
<title><?php echo Html::encode($this->title); ?></title>
<?php $this->head(); ?>
</head>
<body>
<h1>Welcome</h1>
<?php $this->beginBody(); ?>
<?php echo $content; ?>
<?php $this->endBody(); ?>
</body>
<?php $this->endPage(); ?>
</html>
<?php
/** @var $this \yii\base\View */
use yii\helpers\Html;
$this->title = 'Hello World';
$user = Yii::$app->getUser();
if ($user->isGuest) {
echo Html::a('login', array('login'));
} else {
echo "You are logged in as " . $user->identity->name . "<br/>";
echo Html::a('logout', array('logout'));
}
?>
......@@ -19,7 +19,14 @@ use yii\helpers\StringHelper;
*/
class Controller extends Component
{
/**
* @event ActionEvent an event raised right before executing a controller action.
* You may set [[ActionEvent::isValid]] to be false to cancel the action execution.
*/
const EVENT_BEFORE_ACTION = 'beforeAction';
/**
* @event ActionEvent an event raised right after executing a controller action.
*/
const EVENT_AFTER_ACTION = 'afterAction';
/**
......@@ -105,16 +112,15 @@ class Controller extends Component
if ($action !== null) {
$oldAction = $this->action;
$this->action = $action;
$status = 1;
if ($this->module->beforeAction($action)) {
if ($this->beforeAction($action)) {
$status = $action->runWithParams($params);
$this->afterAction($action);
} else {
$status = 1;
}
$this->module->afterAction($action);
}
$this->action = $oldAction;
return $status;
} else {
throw new InvalidRouteException('Unable to resolve the request: ' . $this->getUniqueId() . '/' . $id);
......
......@@ -9,7 +9,6 @@ namespace yii\base;
use Yii;
use yii\helpers\StringHelper;
use yii\helpers\FileHelper;
/**
* Module is the base class for module and application classes.
......@@ -39,6 +38,15 @@ use yii\helpers\FileHelper;
abstract class Module extends Component
{
/**
* @event ActionEvent an event raised before executing a controller action.
* You may set [[ActionEvent::isValid]] to be false to cancel the action execution.
*/
const EVENT_BEFORE_ACTION = 'beforeAction';
/**
* @event ActionEvent an event raised after executing a controller action.
*/
const EVENT_AFTER_ACTION = 'afterAction';
/**
* @var array custom module parameters (name => value).
*/
public $params = array();
......@@ -613,4 +621,27 @@ abstract class Module extends Component
return isset($controller) ? array($controller, $route) : false;
}
/**
* This method is invoked right before an action is to be executed (after all possible filters.)
* You may override this method to do last-minute preparation for the action.
* @param Action $action the action to be executed.
* @return boolean whether the action should continue to be executed.
*/
public function beforeAction($action)
{
$event = new ActionEvent($action);
$this->trigger(self::EVENT_BEFORE_ACTION, $event);
return $event->isValid;
}
/**
* This method is invoked right after an action is executed.
* You may override this method to do some postprocessing for the action.
* @param Action $action the action just executed.
*/
public function afterAction($action)
{
$this->trigger(self::EVENT_AFTER_ACTION, new ActionEvent($action));
}
}
......@@ -11,6 +11,7 @@ namespace yii\caching;
* ApcCache provides APC caching in terms of an application component.
*
* To use this application component, the [APC PHP extension](http://www.php.net/apc) must be loaded.
* In order to enable APC for CLI you should add "apc.enable_cli = 1" to your php.ini.
*
* See [[Cache]] for common cache operations that ApcCache supports.
*
......
......@@ -129,7 +129,7 @@ class Application extends \yii\base\Application
'migrate' => 'yii\console\controllers\MigrateController',
'app' => 'yii\console\controllers\AppController',
'cache' => 'yii\console\controllers\CacheController',
'script' => 'yii\console\controllers\ScriptController',
'asset' => 'yii\console\controllers\AssetController',
);
}
......
......@@ -15,7 +15,7 @@ use yii\console\Controller;
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class ScriptController extends Controller
class AssetController extends Controller
{
public $defaultAction = 'compress';
......@@ -33,13 +33,15 @@ class ScriptController extends Controller
*/
public $targets = array();
public $assetManager = array();
public $jsCompressor = 'java -jar compiler.jar --js {from} --js_output_file {to}';
public $cssCompressor = 'java -jar yuicompressor.jar {from} -o {to}';
public function actionCompress($configFile, $bundleFile)
{
$this->loadConfiguration($configFile);
$bundles = $this->loadBundles($this->bundles, $this->extensions);
$targets = $this->loadTargets($this->targets, $bundles);
// $this->publishBundles($bundles, $this->publishOptions);
$this->publishBundles($bundles, $this->publishOptions);
$timestamp = time();
foreach ($targets as $target) {
if (!empty($target->js)) {
......@@ -96,11 +98,38 @@ class ScriptController extends Controller
protected function loadTargets($targets, $bundles)
{
// build the dependency order of bundles
$registered = array();
foreach ($bundles as $name => $bundle) {
$this->registerBundle($bundles, $name, $registered);
}
$bundleOrders = array_combine(array_keys($registered), range(0, count($bundles) - 1));
// fill up the target which has empty 'depends'.
$referenced = array();
foreach ($targets as $name => $target) {
if (empty($target['depends'])) {
if (!isset($all)) {
$all = $name;
} else {
throw new Exception("Only one target can have empty 'depends' option. Found two now: $all, $name");
}
} else {
foreach ($target['depends'] as $bundle) {
if (!isset($referenced[$bundle])) {
$referenced[$bundle] = $name;
} else {
throw new Exception("Target '{$referenced[$bundle]}' and '$name' cannot contain the bundle '$bundle' at the same time.");
}
}
}
}
if (isset($all)) {
$targets[$all]['depends'] = array_diff(array_keys($registered), array_keys($referenced));
}
// adjust the 'depends' order for each target according to the dependency order of bundles
// create an AssetBundle object for each target
foreach ($targets as $name => $target) {
if (!isset($target['basePath'])) {
throw new Exception("Please specify 'basePath' for the '$name' target.");
......@@ -172,11 +201,7 @@ class ScriptController extends Controller
$map = array();
foreach ($targets as $name => $target) {
foreach ($target->depends as $bundle) {
if (!isset($map[$bundle])) {
$map[$bundle] = $name;
} else {
throw new Exception("Bundle '$bundle' is found in both target '{$map[$bundle]}' and '$name'.");
}
}
}
......@@ -236,7 +261,8 @@ class ScriptController extends Controller
file_put_contents($bundleFile, <<<EOD
<?php
/**
* Do not modify this file manually as it is automatically generated by the "yiic script" command.
* This file is generated by the "yiic script" command.
* DO NOT MODIFY THIS FILE DIRECTLY.
* @version $version
*/
return $array;
......@@ -246,11 +272,82 @@ EOD
protected function compressJsFiles($inputFiles, $outputFile)
{
if (is_string($this->jsCompressor)) {
$tmpFile = $outputFile . '.tmp';
$this->combineJsFiles($inputFiles, $tmpFile);
$log = shell_exec(strtr($this->jsCompressor, array(
'{from}' => $tmpFile,
'{to}' => $outputFile,
)));
@unlink($tmpFile);
} else {
$log = call_user_func($this->jsCompressor, $this, $inputFiles, $outputFile);
}
}
protected function compressCssFiles($inputFiles, $outputFile)
{
if (is_string($this->cssCompressor)) {
$tmpFile = $outputFile . '.tmp';
$this->combineCssFiles($inputFiles, $tmpFile);
$log = shell_exec(strtr($this->cssCompressor, array(
'{from}' => $inputFiles,
'{to}' => $outputFile,
)));
} else {
$log = call_user_func($this->cssCompressor, $this, $inputFiles, $outputFile);
}
}
public function combineJsFiles($files, $tmpFile)
{
$content = '';
foreach ($files as $file) {
$content .= "/*** BEGIN FILE: $file ***/\n"
. file_get_contents($file)
. "/*** END FILE: $file ***/\n";
}
file_put_contents($tmpFile, $content);
}
public function combineCssFiles($files, $tmpFile)
{
// todo: adjust url() references in CSS files
$content = '';
foreach ($files as $file) {
$content .= "/*** BEGIN FILE: $file ***/\n"
. file_get_contents($file)
. "/*** END FILE: $file ***/\n";
}
file_put_contents($tmpFile, $content);
}
public function actionTemplate($configFile)
{
$template = <<<EOD
<?php
return array(
//
'bundles' => require('path/to/bundles.php'),
//
'extensions' => require('path/to/namespaces.php'),
//
'targets' => array(
'all' => array(
'basePath' => __DIR__,
'baseUrl' => '/test',
'js' => 'all-{ts}.js',
'css' => 'all-{ts}.css',
),
),
'assetManager' => array(
'basePath' => __DIR__,
'baseUrl' => '/test',
),
);
EOD;
file_put_contents($configFile, $template);
}
}
\ No newline at end of file
......@@ -522,7 +522,7 @@ class Connection extends Component
if (isset($matches[3])) {
return $db->quoteColumnName($matches[3]);
} else {
return str_replace('%', $this->tablePrefix, $db->quoteTableName($matches[2]));
return str_replace('%', $db->tablePrefix, $db->quoteTableName($matches[2]));
}
}, $sql);
}
......
......@@ -744,7 +744,7 @@ class QueryBuilder extends \yii\base\Object
$parts = array();
foreach ($condition as $column => $value) {
if (is_array($value)) { // IN condition
$parts[] = $this->buildInCondition('in', array($column, $value), $query);
$parts[] = $this->buildInCondition('in', array($column, $value), $params);
} else {
if (strpos($column, '(') === false) {
$column = $this->db->quoteColumnName($column);
......
......@@ -74,9 +74,6 @@ class UrlManager extends Component
public function init()
{
parent::init();
if (is_string($this->cache)) {
$this->cache = Yii::$app->getComponent($this->cache);
}
$this->compileRules();
}
......@@ -88,6 +85,9 @@ class UrlManager extends Component
if (!$this->enablePrettyUrl || $this->rules === array()) {
return;
}
if (is_string($this->cache)) {
$this->cache = Yii::$app->getComponent($this->cache);
}
if ($this->cache instanceof Cache) {
$key = $this->cache->buildKey(__CLASS__);
$hash = md5(json_encode($this->rules));
......@@ -104,7 +104,7 @@ class UrlManager extends Component
$this->rules[$i] = Yii::createObject($rule);
}
if ($this->cache instanceof Cache) {
if (isset($key, $hash)) {
$this->cache->set($key, array($this->rules, $hash));
}
}
......
......@@ -9,4 +9,6 @@ require_once(__DIR__ . '/../../framework/yii.php');
Yii::setAlias('@yiiunit', __DIR__);
new \yii\web\Application(array('id' => 'testapp', 'basePath' => __DIR__));
require_once(__DIR__ . '/TestCase.php');
......@@ -195,7 +195,7 @@ class ModelTest extends TestCase
public function testCreateValidators()
{
$this->setExpectedException('yii\base\InvalidConfigException', 'Invalid validation rule: a rule must be an array specifying both attribute names and validator type.');
$this->setExpectedException('yii\base\InvalidConfigException', 'Invalid validation rule: a rule must specify both attribute names and validator type.');
$invalid = new InvalidRulesModel();
$invalid->createValidators();
......
......@@ -16,9 +16,9 @@ abstract class CacheTest extends TestCase
public function testSet()
{
$cache = $this->getCacheInstance();
$cache->set('string_test', 'string_test');
$cache->set('number_test', 42);
$cache->set('array_test', array('array_test' => 'array_test'));
$this->assertTrue($cache->set('string_test', 'string_test'));
$this->assertTrue($cache->set('number_test', 42));
$this->assertTrue($cache->set('array_test', array('array_test' => 'array_test')));
$cache['arrayaccess_test'] = new \stdClass();
}
......@@ -45,7 +45,7 @@ abstract class CacheTest extends TestCase
public function testExpire()
{
$cache = $this->getCacheInstance();
$cache->set('expire_test', 'expire_test', 2);
$this->assertTrue($cache->set('expire_test', 'expire_test', 2));
sleep(1);
$this->assertEquals('expire_test', $cache->get('expire_test'));
sleep(2);
......@@ -57,11 +57,11 @@ abstract class CacheTest extends TestCase
$cache = $this->getCacheInstance();
// should not change existing keys
$cache->add('number_test', 13);
$this->assertFalse($cache->add('number_test', 13));
$this->assertEquals(42, $cache->get('number_test'));
// should store data is it's not there yet
$cache->add('add_test', 13);
$this->assertTrue($cache->add('add_test', 13));
$this->assertEquals(13, $cache->get('add_test'));
}
......@@ -69,14 +69,14 @@ abstract class CacheTest extends TestCase
{
$cache = $this->getCacheInstance();
$cache->delete('number_test');
$this->assertTrue($cache->delete('number_test'));
$this->assertEquals(null, $cache->get('number_test'));
}
public function testFlush()
{
$cache = $this->getCacheInstance();
$cache->flush();
$this->assertTrue($cache->flush());
$this->assertEquals(null, $cache->get('add_test'));
}
}
......@@ -22,6 +22,14 @@ class HtmlTest extends \yii\test\TestCase
));
}
public function assertEqualsWithoutLE($expected, $actual)
{
$expected = str_replace("\r\n", "\n", $expected);
$actual = str_replace("\r\n", "\n", $actual);
$this->assertEquals($expected, $actual);
}
public function tearDown()
{
Yii::$app = null;
......@@ -240,21 +248,21 @@ class HtmlTest extends \yii\test\TestCase
</select>
EOD;
$this->assertEquals($expected, Html::dropDownList('test'));
$this->assertEqualsWithoutLE($expected, Html::dropDownList('test'));
$expected = <<<EOD
<select name="test">
<option value="value1">text1</option>
<option value="value2">text2</option>
</select>
EOD;
$this->assertEquals($expected, Html::dropDownList('test', null, $this->getDataItems()));
$this->assertEqualsWithoutLE($expected, Html::dropDownList('test', null, $this->getDataItems()));
$expected = <<<EOD
<select name="test">
<option value="value1">text1</option>
<option value="value2" selected="selected">text2</option>
</select>
EOD;
$this->assertEquals($expected, Html::dropDownList('test', 'value2', $this->getDataItems()));
$this->assertEqualsWithoutLE($expected, Html::dropDownList('test', 'value2', $this->getDataItems()));
}
public function testListBox()
......@@ -264,48 +272,48 @@ EOD;
</select>
EOD;
$this->assertEquals($expected, Html::listBox('test'));
$this->assertEqualsWithoutLE($expected, Html::listBox('test'));
$expected = <<<EOD
<select name="test" size="5">
<option value="value1">text1</option>
<option value="value2">text2</option>
</select>
EOD;
$this->assertEquals($expected, Html::listBox('test', null, $this->getDataItems(), array('size' => 5)));
$this->assertEqualsWithoutLE($expected, Html::listBox('test', null, $this->getDataItems(), array('size' => 5)));
$expected = <<<EOD
<select name="test" size="4">
<option value="value1&lt;&gt;">text1&lt;&gt;</option>
<option value="value 2">text&nbsp;&nbsp;2</option>
</select>
EOD;
$this->assertEquals($expected, Html::listBox('test', null, $this->getDataItems2()));
$this->assertEqualsWithoutLE($expected, Html::listBox('test', null, $this->getDataItems2()));
$expected = <<<EOD
<select name="test" size="4">
<option value="value1">text1</option>
<option value="value2" selected="selected">text2</option>
</select>
EOD;
$this->assertEquals($expected, Html::listBox('test', 'value2', $this->getDataItems()));
$this->assertEqualsWithoutLE($expected, Html::listBox('test', 'value2', $this->getDataItems()));
$expected = <<<EOD
<select name="test" size="4">
<option value="value1" selected="selected">text1</option>
<option value="value2" selected="selected">text2</option>
</select>
EOD;
$this->assertEquals($expected, Html::listBox('test', array('value1', 'value2'), $this->getDataItems()));
$this->assertEqualsWithoutLE($expected, Html::listBox('test', array('value1', 'value2'), $this->getDataItems()));
$expected = <<<EOD
<select name="test[]" multiple="multiple" size="4">
</select>
EOD;
$this->assertEquals($expected, Html::listBox('test', null, array(), array('multiple' => true)));
$this->assertEqualsWithoutLE($expected, Html::listBox('test', null, array(), array('multiple' => true)));
$expected = <<<EOD
<input type="hidden" name="test" value="0" /><select name="test" size="4">
</select>
EOD;
$this->assertEquals($expected, Html::listBox('test', '', array(), array('unselect' => '0')));
$this->assertEqualsWithoutLE($expected, Html::listBox('test', '', array(), array('unselect' => '0')));
}
public function testCheckboxList()
......@@ -316,19 +324,19 @@ EOD;
<label><input type="checkbox" name="test[]" value="value1" /> text1</label>
<label><input type="checkbox" name="test[]" value="value2" checked="checked" /> text2</label>
EOD;
$this->assertEquals($expected, Html::checkboxList('test', array('value2'), $this->getDataItems()));
$this->assertEqualsWithoutLE($expected, Html::checkboxList('test', array('value2'), $this->getDataItems()));
$expected = <<<EOD
<label><input type="checkbox" name="test[]" value="value1&lt;&gt;" /> text1<></label>
<label><input type="checkbox" name="test[]" value="value 2" /> text 2</label>
EOD;
$this->assertEquals($expected, Html::checkboxList('test', array('value2'), $this->getDataItems2()));
$this->assertEqualsWithoutLE($expected, Html::checkboxList('test', array('value2'), $this->getDataItems2()));
$expected = <<<EOD
<input type="hidden" name="test" value="0" /><label><input type="checkbox" name="test[]" value="value1" /> text1</label><br />
<label><input type="checkbox" name="test[]" value="value2" checked="checked" /> text2</label>
EOD;
$this->assertEquals($expected, Html::checkboxList('test', array('value2'), $this->getDataItems(), array(
$this->assertEqualsWithoutLE($expected, Html::checkboxList('test', array('value2'), $this->getDataItems(), array(
'separator' => "<br />\n",
'unselect' => '0',
)));
......@@ -337,7 +345,7 @@ EOD;
0<label>text1 <input type="checkbox" name="test[]" value="value1" /></label>
1<label>text2 <input type="checkbox" name="test[]" value="value2" checked="checked" /></label>
EOD;
$this->assertEquals($expected, Html::checkboxList('test', array('value2'), $this->getDataItems(), array(
$this->assertEqualsWithoutLE($expected, Html::checkboxList('test', array('value2'), $this->getDataItems(), array(
'item' => function ($index, $label, $name, $checked, $value) {
return $index . Html::label($label . ' ' . Html::checkbox($name, $checked, $value));
}
......@@ -352,19 +360,19 @@ EOD;
<label><input type="radio" name="test" value="value1" /> text1</label>
<label><input type="radio" name="test" value="value2" checked="checked" /> text2</label>
EOD;
$this->assertEquals($expected, Html::radioList('test', array('value2'), $this->getDataItems()));
$this->assertEqualsWithoutLE($expected, Html::radioList('test', array('value2'), $this->getDataItems()));
$expected = <<<EOD
<label><input type="radio" name="test" value="value1&lt;&gt;" /> text1<></label>
<label><input type="radio" name="test" value="value 2" /> text 2</label>
EOD;
$this->assertEquals($expected, Html::radioList('test', array('value2'), $this->getDataItems2()));
$this->assertEqualsWithoutLE($expected, Html::radioList('test', array('value2'), $this->getDataItems2()));
$expected = <<<EOD
<input type="hidden" name="test" value="0" /><label><input type="radio" name="test" value="value1" /> text1</label><br />
<label><input type="radio" name="test" value="value2" checked="checked" /> text2</label>
EOD;
$this->assertEquals($expected, Html::radioList('test', array('value2'), $this->getDataItems(), array(
$this->assertEqualsWithoutLE($expected, Html::radioList('test', array('value2'), $this->getDataItems(), array(
'separator' => "<br />\n",
'unselect' => '0',
)));
......@@ -373,7 +381,7 @@ EOD;
0<label>text1 <input type="radio" name="test" value="value1" /></label>
1<label>text2 <input type="radio" name="test" value="value2" checked="checked" /></label>
EOD;
$this->assertEquals($expected, Html::radioList('test', array('value2'), $this->getDataItems(), array(
$this->assertEqualsWithoutLE($expected, Html::radioList('test', array('value2'), $this->getDataItems(), array(
'item' => function ($index, $label, $name, $checked, $value) {
return $index . Html::label($label . ' ' . Html::radio($name, $checked, $value));
}
......@@ -420,7 +428,7 @@ EOD;
'group12' => array('class' => 'group'),
),
);
$this->assertEquals($expected, Html::renderSelectOptions(array('value111', 'value1'), $data, $attributes));
$this->assertEqualsWithoutLE($expected, Html::renderSelectOptions(array('value111', 'value1'), $data, $attributes));
}
public function testRenderAttributes()
......
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