Commit 9634b728 by Carsten Brandt

Merge branch 'master' into redis

* master: (27 commits) form wip form wip form WIP script WIP Minor change about twig alias. Added Controller::populate(). Added bootstrap. form WIP form wip form wip Refactored UrlManager. refactored AccessControl activeform WIP Removed the $value parameter from radio and checkbox. Support alternative URL rule syntax. Support default standard component class. updated view renderers docs activeform wip Refactored view renderers. updated view renderers docs refactoring activeform. ...
parents eac48ff2 b07b0c14
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
<?php
class SiteController extends \yii\web\Controller
use yii\web\Controller;
use app\models\LoginForm;
class SiteController extends Controller
{
public function actionIndex()
{
......@@ -9,9 +12,14 @@ class SiteController extends \yii\web\Controller
public function actionLogin()
{
$user = app\models\User::findIdentity(100);
Yii::$app->getUser()->login($user);
Yii::$app->getResponse()->redirect(array('site/index'));
$model = new LoginForm();
if ($this->populate($_POST, $model) && $model->login()) {
Yii::$app->getResponse()->redirect(array('site/index'));
} else {
echo $this->render('login', array(
'model' => $model,
));
}
}
public function actionLogout()
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace app\models;
use Yii;
use yii\base\Model;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class LoginForm extends Model
{
public $username;
public $password;
public $rememberMe = true;
public function rules()
{
return array(
array('username', 'required'),
array('password', 'required'),
array('password', 'validatePassword'),
array('rememberMe', 'boolean'),
);
}
public function validatePassword()
{
$user = User::findByUsername($this->username);
if (!$user || !$user->validatePassword($this->password)) {
$this->addError('password', 'Incorrect username or password.');
}
}
public function login()
{
if ($this->validate()) {
$user = User::findByUsername($this->username);
Yii::$app->getUser()->login($user, $this->rememberMe ? 3600*24*30 : 0);
return true;
} else {
return false;
}
}
}
\ No newline at end of file
......@@ -5,19 +5,22 @@ namespace app\models;
class User extends \yii\base\Object implements \yii\web\Identity
{
public $id;
public $name;
public $username;
public $password;
public $authKey;
private static $users = array(
'100' => array(
'id' => '100',
'username' => 'admin',
'password' => 'admin',
'authKey' => 'test100key',
'name' => 'admin',
),
'101' => array(
'id' => '101',
'username' => 'demo',
'password' => 'demo',
'authKey' => 'test101key',
'name' => 'demo',
),
);
......@@ -26,6 +29,16 @@ class User extends \yii\base\Object implements \yii\web\Identity
return isset(self::$users[$id]) ? new self(self::$users[$id]) : null;
}
public static function findByUsername($username)
{
foreach (self::$users as $user) {
if (strcasecmp($user['username'], $username) === 0) {
return new self($user);
}
}
return null;
}
public function getId()
{
return $this->id;
......@@ -40,4 +53,9 @@ class User extends \yii\base\Object implements \yii\web\Identity
{
return $this->authKey === $authKey;
}
public function validatePassword($password)
{
return $this->password === $password;
}
}
\ No newline at end of file
......@@ -5,18 +5,22 @@
*/
use yii\helpers\Html;
?>
<!DOCTYPE html>
<html>
<?php $this->beginPage(); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title><?php echo Html::encode($this->title); ?></title>
<?php echo Html::cssFile("css/bootstrap.min.css", array('media' => 'screen')); ?>
<?php $this->head(); ?>
</head>
<body>
<h1>Welcome</h1>
<?php $this->beginBody(); ?>
<?php echo $content; ?>
<?php $this->endBody(); ?>
<div class="container">
<h1>Welcome</h1>
<?php $this->beginBody(); ?>
<?php echo $content; ?>
<?php $this->endBody(); ?>
</div>
</body>
<?php $this->endPage(); ?>
</html>
<?php $this->endPage(); ?>
\ No newline at end of file
......@@ -9,7 +9,7 @@ $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 "You are logged in as " . $user->identity->username . "<br/>";
echo Html::a('logout', array('logout'));
}
?>
......
<?php
use yii\helpers\Html;
/**
* @var yii\base\View $this
* @var yii\widgets\ActiveForm $form
* @var app\models\LoginForm $model
*/
?>
<h1>Login</h1>
<p>Please fill out the following fields to login:</p>
<?php $form = $this->beginWidget('yii\widgets\ActiveForm', array('options' => array('class' => 'form-horizontal'))); ?>
<?php echo $form->field($model, 'username')->textInput(); ?>
<?php echo $form->field($model, 'password')->passwordInput(); ?>
<?php echo $form->field($model, 'rememberMe')->checkbox(); ?>
<div class="control-group">
<div class="controls">
<?php echo Html::submitButton('Login', null, null, array('class' => 'btn btn-primary')); ?>
</div>
</div>
<?php $this->endWidget(); ?>
\ No newline at end of file
Yii2 view renderers
===================
By default Yii uses PHP as template language but you can configure it to be able
to render templates with special engines such as Twig or Smarty.
The component responsible for rendering a view is called `view`. You can add
a custom template engines as follows:
```php
array(
'components' => array(
'view' => array(
'class' => 'yii\base\View',
'renderers' => array(
'tpl' => array(
'class' => 'yii\renderers\SmartyViewRenderer',
),
'twig' => array(
'class' => 'yii\renderers\TwigViewRenderer',
),
// ...
),
),
),
)
```
Twig
----
In order to use Twig you need to put you templates in files with extension `.twig`
(or another one if configured differently).
Also you need to specify this extension explicitly when calling `$this->render()`
or `$this->renderPartial()` from your controller:
```php
echo $this->render('renderer.twig', array('username' => 'Alex'));
```
Smarty
------
In order to use Smarty you need to put you templates in files with extension `.tpl`
(or another one if configured differently).
Also you need to specify this extension explicitly when calling `$this->render()`
or `$this->renderPartial()` from your controller:
```php
echo $this->render('renderer.tpl', array('username' => 'Alex'));
```
<?php
return array(
'basePath' => __DIR__ . '/web/assets',
'jquery' => array(
'sourcePath' => __DIR__ . '/assets',
'js' => array(
'jquery.min.js',
),
),
'yii' => array(
'sourcePath' => __DIR__ . '/assets',
'js' => array(
'yii.js',
),
'depends' => array('jquery'),
),
'yii/validation' => array(
'sourcePath' => __DIR__ . '/assets',
'js' => array(
'yii.validation.js',
),
'depends' => array('yii'),
),
'yii/form' => array(
'sourcePath' => __DIR__ . '/assets',
'js' => array(
'yii.activeForm.js',
),
'depends' => array('yii', 'yii/validation'),
),
);
\ No newline at end of file
/**
* Yii JavaScript module.
*
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
yii = (function ($) {
var pub = {
version: '2.0'
};
return pub;
})(jQuery);
jQuery(document).ready(function ($) {
// call the init() method of every module
var init = function (module) {
if ($.isFunction(module.init) && (module.trigger == undefined || $(module.trigger).length)) {
module.init();
}
$.each(module, function () {
if ($.isPlainObject(this)) {
init(this);
}
});
};
init(yii);
});
/**
* Yii validation module.
*
* This is the JavaScript widget used by the yii\widgets\ActiveForm widget.
*
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
yii.validation = (function ($) {
var pub = {
};
return pub;
})(jQuery);
......@@ -176,7 +176,7 @@ class Application extends Module
*/
public function getRuntimePath()
{
if ($this->_runtimePath !== null) {
if ($this->_runtimePath === null) {
$this->setRuntimePath($this->getBasePath() . DIRECTORY_SEPARATOR . 'runtime');
}
return $this->_runtimePath;
......
......@@ -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;
if ($this->beforeAction($action)) {
$status = $action->runWithParams($params);
$this->afterAction($action);
} else {
$status = 1;
$status = 1;
if ($this->module->beforeAction($action)) {
if ($this->beforeAction($action)) {
$status = $action->runWithParams($params);
$this->afterAction($action);
}
$this->module->afterAction($action);
}
$this->action = $oldAction;
return $status;
} else {
throw new InvalidRouteException('Unable to resolve the request: ' . $this->getUniqueId() . '/' . $id);
......@@ -297,6 +303,34 @@ class Controller extends Component
}
/**
* Populates one or multiple models from the given data array.
* @param array $data the data array. This is usually `$_POST` or `$_GET`, but can also be any valid array.
* @param Model $model the model to be populated. If there are more than one model to be populated,
* you may supply them as additional parameters.
* @return boolean whether at least one model is successfully populated with the data.
*/
public function populate($data, $model)
{
$success = false;
if (!empty($data) && is_array($data)) {
$models = func_get_args();
array_shift($models);
foreach ($models as $model) {
/** @var Model $model */
$scope = $model->formName();
if ($scope == '') {
$model->attributes = $data;
$success = true;
} elseif (isset($data[$scope])) {
$model->attributes = $data[$scope];
$success = true;
}
}
}
return $success;
}
/**
* Renders a view and applies layout if available.
*
* The view to be rendered can be specified in one of the following formats:
......
......@@ -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();
......@@ -523,6 +531,9 @@ abstract class Module extends Component
public function setComponents($components)
{
foreach ($components as $id => $component) {
if (isset($this->_components[$id]['class']) && !isset($component['class'])) {
$component['class'] = $this->_components[$id]['class'];
}
$this->_components[$id] = $component;
}
}
......@@ -613,4 +624,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));
}
}
......@@ -70,10 +70,25 @@ class View extends Component
*/
public $params;
/**
* @var ViewRenderer|array the view renderer object or the configuration array for
* creating the view renderer. If not set, view files will be treated as normal PHP files.
* @var array a list of available renderers indexed by their corresponding supported file extensions.
* Each renderer may be a view renderer object or the configuration for creating the renderer object.
* For example,
*
* ~~~
* array(
* 'tpl' => array(
* 'class' => 'yii\renderers\SmartyRenderer',
* ),
* 'twig' => array(
* 'class' => 'yii\renderers\TwigRenderer',
* ),
* )
* ~~~
*
* If no renderer is available for the given view file, the view file will be treated as a normal PHP
* and rendered via [[renderPhpFile()]].
*/
public $renderer;
public $renderers = array();
/**
* @var Theme|array the theme object or the configuration array for creating the theme object.
* If not set, it means theming is not enabled.
......@@ -152,9 +167,6 @@ class View extends Component
public function init()
{
parent::init();
if (is_array($this->renderer)) {
$this->renderer = Yii::createObject($this->renderer);
}
if (is_array($this->theme)) {
$this->theme = Yii::createObject($this->theme);
}
......@@ -226,8 +238,14 @@ class View extends Component
$output = '';
if ($this->beforeRender($viewFile)) {
if ($this->renderer !== null) {
$output = $this->renderer->render($this, $viewFile, $params);
$ext = pathinfo($viewFile, PATHINFO_EXTENSION);
if (isset($this->renderers[$ext])) {
if (is_array($this->renderers[$ext])) {
$this->renderers[$ext] = Yii::createObject($this->renderers[$ext]);
}
/** @var ViewRenderer $renderer */
$renderer = $this->renderers[$ext];
$output = $renderer->render($this, $viewFile, $params);
} else {
$output = $this->renderPhpFile($viewFile, $params);
}
......@@ -352,7 +370,7 @@ class View extends Component
if (!isset($properties['view'])) {
$properties['view'] = $this;
}
return Yii::createObject($properties, $this);
return Yii::createObject($properties);
}
/**
......
<?php
/**
* Smarty view renderer class file.
*
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\renderers;
use Yii;
use Smarty;
use yii\base\View;
use yii\base\ViewRenderer;
/**
* SmartyViewRenderer allows you to use Smarty templates in views.
*
* @author Alexander Makarov <sam@rmcreative.ru>
* @since 2.0
*/
class SmartyViewRenderer extends ViewRenderer
{
/**
* @var string the directory or path alias pointing to where Smarty code is located.
*/
public $smartyPath = '@app/vendors/Smarty';
/**
* @var string the directory or path alias pointing to where Smarty cache will be stored.
*/
public $cachePath = '@app/runtime/Smarty/cache';
/**
* @var string the directory or path alias pointing to where Smarty compiled templates will be stored.
*/
public $compilePath = '@app/runtime/Smarty/compile';
/**
* @var Smarty
*/
public $smarty;
public function init()
{
require_once(Yii::getAlias($this->smartyPath) . '/Smarty.class.php');
$this->smarty = new Smarty();
$this->smarty->setCompileDir(Yii::getAlias($this->compilePath));
$this->smarty->setCacheDir(Yii::getAlias($this->cachePath));
}
/**
* Renders a view file.
*
* This method is invoked by [[View]] whenever it tries to render a view.
* Child classes must implement this method to render the given view file.
*
* @param View $view the view object used for rendering the file.
* @param string $file the view file.
* @param array $params the parameters to be passed to the view file.
*
* @return string the rendering result
*/
public function render($view, $file, $params)
{
$ext = pathinfo($file, PATHINFO_EXTENSION);
/** @var \Smarty_Internal_Template $template */
$template = $this->smarty->createTemplate($file, null, null, $params, true);
return $template->fetch();
}
}
\ No newline at end of file
<?php
/**
* Twig view renderer class file.
*
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\renderers;
use Yii;
use yii\base\View;
use yii\base\ViewRenderer;
/**
* TwigViewRenderer allows you to use Twig templates in views.
*
* @author Alexander Makarov <sam@rmcreative.ru>
* @since 2.0
*/
class TwigViewRenderer extends ViewRenderer
{
/**
* @var string the directory or path alias pointing to where Twig code is located.
*/
public $twigPath = '@Twig';
/**
* @var string the directory or path alias pointing to where Twig cache will be stored.
*/
public $cachePath = '@app/runtime/Twig/cache';
/**
* @var array Twig options
* @see http://twig.sensiolabs.org/doc/api.html#environment-options
*/
public $options = array();
/**
* @var \Twig_Environment
*/
public $twig;
public function init()
{
if (!isset(Yii::$aliases['@Twig'])) {
Yii::setAlias('@Twig', $this->twigPath);
}
$loader = new \Twig_Loader_String();
$this->twig = new \Twig_Environment($loader, array_merge(array(
'cache' => Yii::getAlias($this->cachePath),
), $this->options));
}
/**
* Renders a view file.
*
* This method is invoked by [[View]] whenever it tries to render a view.
* Child classes must implement this method to render the given view file.
*
* @param View $view the view object used for rendering the file.
* @param string $file the view file.
* @param array $params the parameters to be passed to the view file.
*
* @return string the rendering result
*/
public function render($view, $file, $params)
{
return $this->twig->render(file_get_contents($file), $params);
}
}
......@@ -70,8 +70,8 @@ class BooleanValidator extends Validator
*/
public function validateValue($value)
{
return $this->strict && ($value == $this->trueValue || $value == $this->falseValue)
|| !$this->strict && ($value === $this->trueValue || $value === $this->falseValue);
return !$this->strict && ($value == $this->trueValue || $value == $this->falseValue)
|| $this->strict && ($value === $this->trueValue || $value === $this->falseValue);
}
/**
......
......@@ -47,7 +47,7 @@ class RequiredValidator extends Validator
{
parent::init();
if ($this->message === null) {
$this->message = $this->requiredValue === null ? Yii::t('yii|{attribute} is invalid.')
$this->message = $this->requiredValue === null ? Yii::t('yii|{attribute} cannot be blank.')
: Yii::t('yii|{attribute} must be "{requiredValue}".');
}
}
......
......@@ -33,12 +33,17 @@ class AccessControl extends ActionFilter
*/
public $denyCallback;
/**
* @var string the default class of the access rules. This is used when
* a rule is configured without specifying a class in [[rules]].
* @var array the default configuration of access rules. Individual rule configurations
* specified via [[rules]] will take precedence when the same property of the rule is configured.
*/
public $defaultRuleClass = 'yii\web\AccessRule';
public $ruleConfig = array(
'class' => 'yii\web\AccessRule',
);
/**
* @var array a list of access rule objects or configurations for creating the rule objects.
* @var array a list of access rule objects or configuration arrays for creating the rule objects.
* If a rule is specified via a configuration array, it will be merged with [[ruleConfig]] first
* before it is used for creating the rule object.
* @see ruleConfig
*/
public $rules = array();
......@@ -50,10 +55,7 @@ class AccessControl extends ActionFilter
parent::init();
foreach ($this->rules as $i => $rule) {
if (is_array($rule)) {
if (!isset($rule['class'])) {
$rule['class'] = $this->defaultRuleClass;
}
$this->rules[$i] = Yii::createObject($rule);
$this->rules[$i] = Yii::createObject(array_merge($this->ruleConfig, $rule));
}
}
}
......
......@@ -18,6 +18,27 @@ use yii\base\InvalidConfigException;
class Request extends \yii\base\Request
{
/**
* @var boolean whether to enable CSRF (Cross-Site Request Forgery) validation. Defaults to false.
* By setting this property to true, forms submitted to an Yii Web application must be originated
* from the same application. If not, a 400 HTTP exception will be raised.
*
* Note, this feature requires that the user client accepts cookie. Also, to use this feature,
* forms submitted via POST method must contain a hidden input whose name is specified by [[csrfTokenName]].
* You may use [[\yii\web\Html::beginForm()]] to generate his hidden input.
* @see http://en.wikipedia.org/wiki/Cross-site_request_forgery
*/
public $enableCsrfValidation = false;
/**
* @var string the name of the token used to prevent CSRF. Defaults to 'YII_CSRF_TOKEN'.
* This property is effectively only when {@link enableCsrfValidation} is true.
*/
public $csrfTokenName = '_csrf';
/**
* @var array the configuration of the CSRF cookie. This property is used only when [[enableCsrfValidation]] is true.
* @see Cookie
*/
public $csrfCookie = array('httponly' => true);
/**
* @var boolean whether cookies should be validated to ensure they are not tampered. Defaults to true.
*/
public $enableCookieValidation = true;
......@@ -27,8 +48,7 @@ class Request extends \yii\base\Request
public $cookieValidationKey;
/**
* @var string|boolean the name of the POST parameter that is used to indicate if a request is a PUT or DELETE
* request tunneled through POST. If false, it means disabling REST request tunneled through POST.
* Default to '_method'.
* request tunneled through POST. Default to '_method'.
* @see getRequestMethod
* @see getRestParams
*/
......@@ -36,6 +56,7 @@ class Request extends \yii\base\Request
private $_cookies;
/**
* Resolves the current request into a route and the associated parameters.
* @return array the first element is the route, and the second is the associated parameters.
......@@ -43,6 +64,8 @@ class Request extends \yii\base\Request
*/
public function resolve()
{
$this->validateCsrfToken();
$result = Yii::$app->getUrlManager()->parseRequest($this);
if ($result !== false) {
list ($route, $params) = $result;
......@@ -60,7 +83,7 @@ class Request extends \yii\base\Request
*/
public function getRequestMethod()
{
if ($this->restVar !== false && isset($_POST[$this->restVar])) {
if (isset($_POST[$this->restVar])) {
return strtoupper($_POST[$this->restVar]);
} else {
return isset($_SERVER['REQUEST_METHOD']) ? strtoupper($_SERVER['REQUEST_METHOD']) : 'GET';
......@@ -123,7 +146,7 @@ class Request extends \yii\base\Request
public function getRestParams()
{
if ($this->_restParams === null) {
if ($this->restVar !== false && isset($_POST[$this->restVar])) {
if (isset($_POST[$this->restVar])) {
$this->_restParams = $_POST;
} else {
$this->_restParams = array();
......@@ -700,5 +723,72 @@ class Request extends \yii\base\Request
}
return $this->_cookies;
}
private $_csrfToken;
/**
* Returns the random token used to perform CSRF validation.
* The token will be read from cookie first. If not found, a new token will be generated.
* @return string the random token for CSRF validation.
* @see enableCsrfValidation
*/
public function getCsrfToken()
{
if ($this->_csrfToken === null) {
$cookies = $this->getCookies();
if (($this->_csrfToken = $cookies->getValue($this->csrfTokenName)) === null) {
$cookie = $this->createCsrfCookie();
$this->_csrfToken = $cookie->value;
$cookies->add($cookie);
}
}
return $this->_csrfToken;
}
/**
* Creates a cookie with a randomly generated CSRF token.
* Initial values specified in [[csrfCookie]] will be applied to the generated cookie.
* @return Cookie the generated cookie
* @see enableCsrfValidation
*/
protected function createCsrfCookie()
{
$options = $this->csrfCookie;
$options['name'] = $this->csrfTokenName;
$options['value'] = sha1(uniqid(mt_rand(), true));
return new Cookie($options);
}
/**
* Performs the CSRF validation.
* The method will compare the CSRF token obtained from a cookie and from a POST field.
* If they are different, a CSRF attack is detected and a 400 HTTP exception will be raised.
* @throws HttpException if the validation fails
*/
public function validateCsrfToken()
{
if (!$this->enableCsrfValidation) {
return;
}
$method = $this->getRequestMethod();
if ($method === 'POST' || $method === 'PUT' || $method === 'DELETE') {
$cookies = $this->getCookies();
switch ($method) {
case 'POST':
$token = $this->getPost($this->csrfTokenName);
break;
case 'PUT':
$token = $this->getPut($this->csrfTokenName);
break;
case 'DELETE':
$token = $this->getDelete($this->csrfTokenName);
}
if (empty($token) || $cookies->getValue($this->csrfTokenName) !== $token) {
throw new HttpException(400, Yii::t('yii|Unable to verify your data submission.'));
}
}
}
}
......@@ -29,8 +29,15 @@ class UrlManager extends Component
/**
* @var array the rules for creating and parsing URLs when [[enablePrettyUrl]] is true.
* This property is used only if [[enablePrettyUrl]] is true. Each element in the array
* is the configuration of creating a single URL rule whose class by default is [[defaultRuleClass]].
* If you modify this property after the UrlManager object is created, make sure
* is the configuration array for creating a single URL rule. The configuration will
* be merged with [[ruleConfig]] first before it is used for creating the rule object.
*
* A special shortcut format can be used if a rule only specifies [[UrlRule::pattern|pattern]]
* and [[UrlRule::route|route]]: `'pattern' => 'route'`. That is, instead of using a configuration
* array, one can use the key to represent the pattern and the value the corresponding route.
* For example, `'post/<id:\d+>' => 'post/view'`.
*
* Note that if you modify this property after the UrlManager object is created, make sure
* you populate the array with rule objects instead of rule configurations.
*/
public $rules = array();
......@@ -59,15 +66,16 @@ class UrlManager extends Component
*/
public $cache = 'cache';
/**
* @var string the default class name for creating URL rule instances
* when it is not specified in [[rules]].
* @var array the default configuration of URL rules. Individual rule configurations
* specified via [[rules]] will take precedence when the same property of the rule is configured.
*/
public $defaultRuleClass = 'yii\web\UrlRule';
public $ruleConfig = array(
'class' => 'yii\web\UrlRule',
);
private $_baseUrl;
private $_hostInfo;
/**
* Initializes UrlManager.
*/
......@@ -97,12 +105,17 @@ class UrlManager extends Component
}
}
foreach ($this->rules as $i => $rule) {
if (!isset($rule['class'])) {
$rule['class'] = $this->defaultRuleClass;
$rules = array();
foreach ($this->rules as $key => $rule) {
if (!is_array($rule)) {
$rule = array(
'pattern' => $key,
'route' => $rule,
);
}
$this->rules[$i] = Yii::createObject($rule);
$rules[] = Yii::createObject(array_merge($this->ruleConfig, $rule));
}
$this->rules = $rules;
if (isset($key, $hash)) {
$this->cache->set($key, array($this->rules, $hash));
......
......@@ -32,7 +32,7 @@ class User extends Component
const EVENT_AFTER_LOGOUT = 'afterLogout';
/**
* @var string the class name or alias of the [[identity]] object.
* @var string the class name of the [[identity]] object.
*/
public $identityClass;
/**
......@@ -56,7 +56,7 @@ class User extends Component
* @var array the configuration of the identity cookie. This property is used only when [[enableAutoLogin]] is true.
* @see Cookie
*/
public $identityCookie = array('name' => '__identity', 'httponly' => true);
public $identityCookie = array('name' => '_identity', 'httponly' => true);
/**
* @var integer the number of seconds in which the user will be logged out automatically if he
* remains inactive. If this property is not set, the user will be logged out after
......
......@@ -157,20 +157,20 @@ class HtmlTest extends \yii\test\TestCase
public function testButton()
{
$this->assertEquals('<button type="button">Button</button>', Html::button());
$this->assertEquals('<button type="button" name="test" value="value">content<></button>', Html::button('test', 'value', 'content<>'));
$this->assertEquals('<button type="submit" class="t" name="test" value="value">content<></button>', Html::button('test', 'value', 'content<>', array('type' => 'submit', 'class' => "t")));
$this->assertEquals('<button type="button" name="test" value="value">content<></button>', Html::button('content<>', 'test', 'value'));
$this->assertEquals('<button type="submit" class="t" name="test" value="value">content<></button>', Html::button('content<>', 'test', 'value', array('type' => 'submit', 'class' => "t")));
}
public function testSubmitButton()
{
$this->assertEquals('<button type="submit">Submit</button>', Html::submitButton());
$this->assertEquals('<button type="submit" class="t" name="test" value="value">content<></button>', Html::submitButton('test', 'value', 'content<>', array('class' => 't')));
$this->assertEquals('<button type="submit" class="t" name="test" value="value">content<></button>', Html::submitButton('content<>', 'test', 'value', array('class' => 't')));
}
public function testResetButton()
{
$this->assertEquals('<button type="reset">Reset</button>', Html::resetButton());
$this->assertEquals('<button type="reset" class="t" name="test" value="value">content<></button>', Html::resetButton('test', 'value', 'content<>', array('class' => 't')));
$this->assertEquals('<button type="reset" class="t" name="test" value="value">content<></button>', Html::resetButton('content<>', 'test', 'value', array('class' => 't')));
}
public function testInput()
......@@ -230,15 +230,15 @@ class HtmlTest extends \yii\test\TestCase
public function testRadio()
{
$this->assertEquals('<input type="radio" name="test" value="1" />', Html::radio('test'));
$this->assertEquals('<input type="radio" class="a" name="test" checked="checked" />', Html::radio('test', true, null, array('class' => 'a')));
$this->assertEquals('<input type="hidden" name="test" value="0" /><input type="radio" class="a" name="test" value="2" checked="checked" />', Html::radio('test', true, 2, array('class' => 'a' , 'uncheck' => '0')));
$this->assertEquals('<input type="radio" class="a" name="test" checked="checked" />', Html::radio('test', true, array('class' => 'a', 'value' => null)));
$this->assertEquals('<input type="hidden" name="test" value="0" /><input type="radio" class="a" name="test" value="2" checked="checked" />', Html::radio('test', true, array('class' => 'a' , 'uncheck' => '0', 'value' => 2)));
}
public function testCheckbox()
{
$this->assertEquals('<input type="checkbox" name="test" value="1" />', Html::checkbox('test'));
$this->assertEquals('<input type="checkbox" class="a" name="test" checked="checked" />', Html::checkbox('test', true, null, array('class' => 'a')));
$this->assertEquals('<input type="hidden" name="test" value="0" /><input type="checkbox" class="a" name="test" value="2" checked="checked" />', Html::checkbox('test', true, 2, array('class' => 'a', 'uncheck' => '0')));
$this->assertEquals('<input type="checkbox" class="a" name="test" checked="checked" />', Html::checkbox('test', true, array('class' => 'a', 'value' => null)));
$this->assertEquals('<input type="hidden" name="test" value="0" /><input type="checkbox" class="a" name="test" value="2" checked="checked" />', Html::checkbox('test', true, array('class' => 'a', 'uncheck' => '0', 'value' => 2)));
}
public function testDropDownList()
......@@ -347,7 +347,7 @@ EOD;
EOD;
$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));
return $index . Html::label($label . ' ' . Html::checkbox($name, $checked, array('value' => $value)));
}
)));
}
......@@ -383,7 +383,7 @@ EOD;
EOD;
$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));
return $index . Html::label($label . ' ' . Html::radio($name, $checked, array('value' => $value)));
}
)));
}
......
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