Commit 0e31bb8c by RichWeber

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

parents d5bd6816 b927d36f
......@@ -30,7 +30,7 @@ install:
- tests/unit/data/travis/memcache-setup.sh
- tests/unit/data/travis/cubrid-setup.sh
# basic and advanced application:
# - tests/unit/data/travis/setup-apps.sh
- tests/unit/data/travis/setup-apps.sh
before_script:
- echo 'elasticsearch version ' && curl http://localhost:9200/
......@@ -39,16 +39,16 @@ before_script:
- tests/unit/data/travis/sphinx-setup.sh
- mongo yii2test --eval 'db.addUser("travis", "test");'
# basic and advanced application:
# - tests/unit/data/travis/init-apps.sh
- tests/unit/data/travis/init-apps.sh
script:
- vendor/bin/phpunit --verbose --coverage-clover=coverage.clover --exclude-group mssql,oci,wincache,xcache,zenddata
# - cd apps/basic && php vendor/bin/codecept run
# - cd ../advanced/backend && ../vendor/bin/codecept run
# - cd ../common && ../vendor/bin/codecept run
# - cd ../frontend && ../vendor/bin/codecept run
- cd apps/basic && php vendor/bin/codecept run
- cd ../advanced/backend && ../vendor/bin/codecept run
- cd ../common && ../vendor/bin/codecept run
- cd ../frontend && ../vendor/bin/codecept run
after_script:
# - cd ../../..
- cd ../../..
- wget https://scrutinizer-ci.com/ocular.phar
- php ocular.phar code-coverage:upload --format=php-clover coverage.clover
......@@ -112,7 +112,7 @@ if you are starting from `frontend` tests then you should run `yii migrate` in e
it will upgrade your database to the last state according migrations.
To be able to run acceptance tests you need a running webserver. For this you can use the php builtin server and run it in the directory where your main project folder is located. For example if your application is located in `/www/advanced` all you need to is:
`cd /www` and then `php -S 127.0.0.1:8080 index-test.php` because the default configuration of acceptance tests expects the url of the application to be `/advanced/`.
`cd /www` and then `php -S 127.0.0.1:8080` because the default configuration of acceptance tests expects the url of the application to be `/advanced/`.
If you already have a server configured or your application is not located in a folder called `advanced`, you may need to adjust the `TEST_ENTRY_URL` in `frontend/tests/_bootstrap.php` and `backend/tests/_bootstrap.php`.
After that is done you should be able to run your tests, for example to run `frontend` tests do:
......
......@@ -100,7 +100,7 @@ en vez de llamadas al método [[Yii::setAlias()]].
#### [[yii\base\Application::bootstrap|bootstrap]] <a name="bootstrap"></a>
Esta es una propiedad importante. Te permite definir un array de los componentes que deben ejecutarse
Esta es una propiedad importante. Te permite definir un array de los componentes que deben ejecutarse
durante el [[yii\base\Application::bootstrap()|proceso de `bootstrapping`]] de la aplicación.
Por ejemplo, si quieres personalizar las [reglas de URL](runtime-url-handling.md) de un [módulo](structure-modules.md),
podrías listar su ID como un elemento de este array.
......@@ -355,7 +355,7 @@ si tu no la usarás en tu código.
### Propiedades Útiles <a name="useful-properties"></a>
Las propiedades especificadas en esta sub-sección are no son configuradas normalmente ya que sus valores por defecto
Las propiedades especificadas en esta sub-sección no son configuradas normalmente ya que sus valores por defecto
estipulan convenciones comunes. De cualquier modo, aún puedes configurarlas en caso de que quieras romper con la convención.
......@@ -540,7 +540,7 @@ Por ejemplo:
```
Ten en cuenta que el mismo evento `beforeAction` también es disparado por [módulos](structure-modules.md)
y [controladores)(structure-controllers.md). Los objectos aplicación son los primeros en disparar este evento,
y [controladores)(structure-controllers.md). Los objectos aplicación son los primeros en disparar este evento,
seguidos por módulos (si los hubiera), y finalmente controladores. Si un manejador de eventos define [[yii\base\ActionEvent::isValid]]
como `false`, todos los eventos siguientes NO serán disparados.
......
......@@ -396,10 +396,10 @@ In Yii in order to build it you can first form two query objects and then use `u
```php
$query = new Query();
$query->select("id, 'post' as type, name")->from('post')->limit(10);
$query->select("id, category_id as type, name")->from('post')->limit(10);
$anotherQuery = new Query();
$anotherQuery->select('id, 'user' as type, name')->from('user')->limit(10);
$anotherQuery->select('id, type, name')->from('user')->limit(10);
$query->union($anotherQuery);
```
......
......@@ -316,7 +316,7 @@ to end users.
* For [[yii\web\Application|Web applications]], the return value can also be some arbitrary data which will
be assigned to [[yii\web\Response::data]] and be further converted into a string representing the response body.
* For [[yii\console\Application|console applications], the return value can also be an integer representing
* For [[yii\console\Application|console applications]], the return value can also be an integer representing
the [[yii\console\Response::exitStatus|exit status]] of the command execution.
In the examples shown above, the action results are all strings which will be treated as the response body
......
......@@ -93,7 +93,7 @@ You can get the label of an attribute by calling [[yii\base\Model::getAttributeL
```php
$model = new \app\models\ContactForm;
// displays "Label"
// displays "Name"
echo $model->getAttributeLabel('name');
```
......@@ -500,7 +500,7 @@ you may take the following strategy:
[modules](structure-modules.md). These model classes should contain minimal sets of rules and logic that
are common among all their usages.
* In each [application](structure-applications.md) or [module](structure-modules.md) that uses a model,
define a crete model class by extending from the corresponding base model class. The concrete model classes
define a concrete model class by extending from the corresponding base model class. The concrete model classes
should contain rules and logic that are specific for that application or module.
For example, in the [Advanced Application Template](tutorial-advanced-app.md), you may define a base model
......
......@@ -361,10 +361,10 @@ the places where these methods are called.
- [[yii\web\View::head()|head()]]: This method should be called within the `<head>` section of an HTML page.
It generates a placeholder which will be replaced with the registered head HTML code (e.g. link tags, meta tags)
when a page finishes rendering.
- [[yii\base\View::beginBody()|beginBody()]]: This method should be called at the beginning of the `<body>` section.
- [[yii\web\View::beginBody()|beginBody()]]: This method should be called at the beginning of the `<body>` section.
It triggers the [[yii\web\View::EVENT_BEGIN_BODY|EVENT_BEGIN_BODY]] event and generates a placeholder which will
be replaced by the registered HTML code (e.g. JavaScript) targeted at the body begin position.
- [[yii\base\View::endBody()|endBody()]]: This method should be called at the end of the `<body>` section.
- [[yii\web\View::endBody()|endBody()]]: This method should be called at the end of the `<body>` section.
It triggers the [[yii\web\View::EVENT_END_BODY|EVENT_END_BODY]] event and generates a placeholder which will
be replaced by the registered HTML code (e.g. JavaScript) targeted at the body end position.
......
......@@ -187,7 +187,7 @@ if (YII_ENV_DEV) {
'crud' => [ //name generator
'class' => 'yii\gii\generators\crud\Generator', //class generator
'templates' => [ //setting for out templates
'myCrud' => '@app\myTemplates\crud\default', //name template => path to template
'myCrud' => '@app/myTemplates/crud/default', //name template => path to template
]
]
],
......
......@@ -65,7 +65,7 @@ webserver:
```
cd apps/advanced/frontend/www
php -S 127.0.0.1:8080 index-test.php
php -S 127.0.0.1:8080
```
Note that you should have Codeception and PHPUnit installed globally:
......
......@@ -55,7 +55,7 @@ class Alert extends Widget
/**
* @var array the options for rendering the close button tag.
* The close button is displayed in the header of the modal window. Clicking
* on the button will hide the modal window. If this is null, no close button will be rendered.
* on the button will hide the modal window. If this is false, no close button will be rendered.
*
* The following special options are supported:
*
......@@ -117,7 +117,7 @@ class Alert extends Widget
*/
protected function renderCloseButton()
{
if ($this->closeButton !== null) {
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'])) {
......
......@@ -8,9 +8,15 @@ Yii Framework 2 bootstrap extension Change Log
- Bug #3740: Fixed duplicate error message when client validation is enabled (tadaszelvys)
- Bug #3749: Fixed invalid plugin registration and ensure clickable links in dropdown (kartik-v)
- Enh #4024: Added ability to `yii\bootstrap\Tabs` to encode each `Tabs::items['label']` separately (creocoder, umneeq)
- Chg #3036: Upgraded Twitter Bootstrap to 3.1.x (qiangxue)
- Enh #4120: Added ability for each item to choose it's encoding option in `Dropdown` and `Nav` (Alex-Code)
- Enh #4363: Added `showIndicators` property to make Carousel indicators optional (sdkiller)
- Chg #3036: Upgraded Twitter Bootstrap to 3.1.x (qiangxue)
- Chg #4595: The following properties are now taking `false` instead of `null` for "don't use" case (samdark)
- `yii\bootstrap\NavBar::$brandLabel`.
- `yii\bootstrap\NavBar::$brandUrl`.
- `yii\bootstrap\Modal::$closeButton`.
- `yii\bootstrap\Modal::$toggleButton`.
- `yii\bootstrap\Alert::$closeButton`.
2.0.0-beta April 13, 2014
-------------------------
......
......@@ -52,9 +52,9 @@ class Modal extends Widget
*/
public $size;
/**
* @var array the options for rendering the close button tag.
* @var array|false the options for rendering the close button tag.
* The close button is displayed in the header of the modal window. Clicking
* on the button will hide the modal window. If this is null, no close button will be rendered.
* on the button will hide the modal window. If this is false, no close button will be rendered.
*
* The following special options are supported:
*
......@@ -69,7 +69,7 @@ class Modal extends Widget
/**
* @var array the options for rendering the toggle button tag.
* The toggle button is used to toggle the visibility of the modal window.
* If this property is null, no toggle button will be rendered.
* If this property is false, no toggle button will be rendered.
*
* The following special options are supported:
*
......@@ -80,7 +80,7 @@ class Modal extends Widget
* Please refer to the [Modal plugin help](http://getbootstrap.com/javascript/#modals)
* for the supported HTML attributes.
*/
public $toggleButton;
public $toggleButton = false;
/**
......@@ -187,7 +187,7 @@ class Modal extends Widget
*/
protected function renderCloseButton()
{
if ($this->closeButton !== null) {
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'])) {
......@@ -217,7 +217,7 @@ class Modal extends Widget
$this->clientOptions = array_merge(['show' => false], $this->clientOptions);
}
if ($this->closeButton !== null) {
if ($this->closeButton !== false) {
$this->closeButton = array_merge([
'data-dismiss' => 'modal',
'aria-hidden' => 'true',
......@@ -225,7 +225,7 @@ class Modal extends Widget
], $this->closeButton);
}
if ($this->toggleButton !== null) {
if ($this->toggleButton !== false) {
$this->toggleButton = array_merge([
'data-toggle' => 'modal',
], $this->toggleButton);
......
......@@ -56,15 +56,16 @@ class NavBar extends Widget
*/
public $containerOptions = [];
/**
* @var string the text of the brand. Note that this is not HTML-encoded.
* @var string|boolean the text of the brand of false if it's not used. Note that this is not HTML-encoded.
* @see http://getbootstrap.com/components/#navbar
*/
public $brandLabel;
public $brandLabel = false;
/**
* @param array|string $url the URL for the brand's hyperlink tag. This parameter will be processed by [[Url::to()]]
* and will be used for the "href" attribute of the brand link. If not set, [[\yii\web\Application::homeUrl]] will be used.
* @param array|string|boolean $url the URL for the brand's hyperlink tag. This parameter will be processed by [[Url::to()]]
* and will be used for the "href" attribute of the brand link. Default value is false that means
* [[\yii\web\Application::homeUrl]] will be used.
*/
public $brandUrl;
public $brandUrl = false;
/**
* @var array the HTML attributes of the brand link.
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
......@@ -115,9 +116,9 @@ class NavBar extends Widget
$this->containerOptions['id'] = "{$this->options['id']}-collapse";
}
echo $this->renderToggleButton();
if ($this->brandLabel !== null) {
if ($this->brandLabel !== false) {
Html::addCssClass($this->brandOptions, 'navbar-brand');
echo Html::a($this->brandLabel, $this->brandUrl === null ? Yii::$app->homeUrl : $this->brandUrl, $this->brandOptions);
echo Html::a($this->brandLabel, $this->brandUrl === false ? Yii::$app->homeUrl : $this->brandUrl, $this->brandOptions);
}
echo Html::endTag('div');
Html::addCssClass($this->containerOptions, 'collapse');
......
......@@ -11,6 +11,7 @@ use Yii;
use yii\console\Exception;
use yii\helpers\Console;
use yii\helpers\FileHelper;
use yii\helpers\VarDumper;
/**
* This command manage fixtures creations based on given template.
......@@ -316,22 +317,7 @@ class FixtureController extends \yii\console\controllers\FixtureController
*/
public function exportFixtures($fixtures)
{
$content = "<?php\n\nreturn [";
foreach ($fixtures as $fixture) {
$content .= "\n\t[";
foreach ($fixture as $name => $value) {
$content .= "\n\t\t'{$name}' => '{$value}',";
}
$content .= "\n\t],";
}
$content .= "\n];\n";
return $content;
return "<?php\n\nreturn " . VarDumper::export($fixtures) . ";\n";
}
/**
......
......@@ -7,6 +7,7 @@ Yii Framework 2 twig extension Change Log
- Bug #2925: Fixed throwing exception when accessing AR property with null value (samdark)
- Bug #3767: Fixed repeated adding of extensions when using config. One may now pass extension instances as well (grachov)
- Bug #3877: Fixed `lexerOptions` throwing exception (dapatrese)
- Bug #4290: Fixed throwing exception when trying to access AR relation that is null (samdark, tenitski)
- Enh #1799: Added `form_begin`, `form_end` to twig extension (samdark)
- Enh #3674: Various enhancements (samdark)
- Removed `FileLoader` and used `\Twig_Loader_Filesystem` instead.
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\twig;
/**
* Template base class
*
* @author Alexei Tenitski <alexei@ten.net.nz>
*/
abstract class Template extends \Twig_Template
{
/**
* @inheritdoc
*/
protected function getAttribute($object, $item, array $arguments = [], $type = \Twig_Template::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
{
// Twig uses isset() to check if attribute exists which does not work when attribute exists but is null
if ($object instanceof \yii\db\BaseActiveRecord) {
if ($type === \Twig_Template::METHOD_CALL) {
return $object->$item();
} else {
return $object->$item;
}
}
return parent::getAttribute($object, $item, $arguments, $type, $isDefinedTest, $ignoreStrictCheck);
}
}
......@@ -98,6 +98,8 @@ class ViewRenderer extends BaseViewRenderer
'charset' => Yii::$app->charset,
], $this->options));
$this->twig->setBaseTemplateClass('yii\twig\Template');
// Adding custom globals (objects or static classes)
if (!empty($this->globals)) {
$this->addGlobals($this->globals);
......
......@@ -78,6 +78,7 @@ Yii Framework 2 Change Log
- Bug #4497: Fixed StringHelper::byteSubstr() returning empty string on null $length param (mbman)
- Bug #4514: Fixed Request class crashing when empty CSRF token value is sent in cookie (cebe)
- Bug #4519: `yii\base\Model::isAttributeRequired()` should check if the `when` option of the validator is set (thiagotalma)
- Bug #4592: Fixed `yii help` command was listing incorrect action names for methods like `actionSayNO` (samdark)
- Bug: Fixed inconsistent return of `\yii\console\Application::runAction()` (samdark)
- Bug: URL encoding for the route parameter added to `\yii\web\UrlManager` (klimov-paul)
- Bug: Fixed the bug that requesting protected or private action methods would cause 500 error instead of 404 (qiangxue)
......@@ -168,7 +169,10 @@ Yii Framework 2 Change Log
- Enh #4436: Added callback functions to AJAX-based form validation (thiagotalma)
- Enh #4485: Added support for deferred validation in `ActiveForm` (Alex-Code)
- Enh #4520: Added sasl support to `yii\caching\MemCache` (xjflyttp)
- Enh #4559: Added `beforeValidateAll` and `afterValidateAll` callbacks to `ActiveForm` (Alex-Code)
- Enh #4566: Added client validation support for image validator (Skysplit, qiangxue)
- Enh #4581: Added ability to disable url encoding in `UrlRule` (tadaszelvys)
- Enh #4602: Added $key param in ActionColumn buttons Closure call (disem)
- Enh: Added support for using sub-queries when building a DB query with `IN` condition (qiangxue)
- Enh: Supported adding a new response formatter without the need to reconfigure existing formatters (qiangxue)
- Enh: Added `yii\web\UrlManager::addRules()` to simplify adding new URL rules (qiangxue)
......@@ -214,6 +218,8 @@ Yii Framework 2 Change Log
- Chg #4310: Removed `$data` from signature of `yii\rbac\ManagerInterface` (samdark)
- Chg #4318: `yii\helpers\Html::ul()` and `ol()` will return an empty list tag if an empty item array is given (qiangxue)
- Chg #4331: `yii\helpers\Url` now uses `UrlManager` to determine base URL when generating URLs (qiangxue)
- Chg #4591: `yii\helpers\Url::to()` will no longer prefix relative URLs with the base URL (qiangxue)
- Chg #4595: `yii\widgets\LinkPager`'s `nextPageLabel`, `prevPageLabel`, `firstPageLabel`, `lastPageLabel` are now taking `false` instead of `null` for "no label" (samdark)
- Chg: Replaced `clearAll()` and `clearAllAssignments()` in `yii\rbac\ManagerInterface` with `removeAll()`, `removeAllRoles()`, `removeAllPermissions()`, `removeAllRules()` and `removeAllAssignments()` (qiangxue)
- Chg: Added `$user` as the first parameter of `yii\rbac\Rule::execute()` (qiangxue)
- Chg: `yii\grid\DataColumn::getDataCellValue()` visibility is now `public` to allow accessing the value from a GridView directly (cebe)
......@@ -225,6 +231,7 @@ Yii Framework 2 Change Log
- Chg: `yii\web\Request::cookieValidationKey` must be explicitly specified for each application that wants to use cookie validation (qiangxue)
- New #3911: Added `yii\behaviors\SluggableBehavior` that fills the specified model attribute with the transliterated and adjusted version to use in URLs (creocoder)
- New #4193: Added `yii\filters\Cors` CORS filter to allow Cross Origin Resource Sharing (pgaultier)
- New: Added `yii\base\InvalidValueException` (qiangxue)
2.0.0-beta April 13, 2014
......
......@@ -174,6 +174,20 @@ new ones save the following code as `convert.php` that should be placed in the s
```
* Due to significant changes to security you need to upgrade your code to use `\yii\base\Security` component instead of
helper. If you have any data encrypted it should be re-encrypted. In order to do so you can use old security helper [as
explained by @docsolver at github](https://github.com/yiisoft/yii2/issues/4461#issuecomment-50237807).
helper. If you have any data encrypted it should be re-encrypted. In order to do so you can use old security helper
[as explained by @docsolver at github](https://github.com/yiisoft/yii2/issues/4461#issuecomment-50237807).
* [[yii\helpers\Url::to()]] will no longer prefix base URL to relative URLs. For example, `Url::to('images/logo.png')`
will return `images/logo.png` directly. If you want a relative URL to be prefix with base URL, you should make use
of the alias `@web`. For example, `Url::to('@web/images/logo.png')` will return `/BaseUrl/images/logo.png`.
- The following properties are now taking `false` instead of `null` for "don't use" case:
- `yii\bootstrap\NavBar::$brandLabel`.
- `yii\bootstrap\NavBar::$brandUrl`.
- `yii\bootstrap\Modal::$closeButton`.
- `yii\bootstrap\Modal::$toggleButton`.
- `yii\bootstrap\Alert::$closeButton`.
- `yii\widgets\LinkPager::$nextPageLabel`.
- `yii\widgets\LinkPager::$prevPageLabel`.
- `yii\widgets\LinkPager::$firstPageLabel`.
- `yii\widgets\LinkPager::$lastPageLabel`.
......@@ -41,9 +41,15 @@
// a callback that is called before validating each attribute. The signature of the callback should be:
// function ($form, attribute, messages) { ...return false to cancel the validation...}
beforeValidate: undefined,
// a callback that is called before validation starts (This callback is only called when the form is submitted). This signature of the callback should be:
// function($form, data) { ...return false to cancel the validation...}
beforeValidateAll: undefined,
// a callback that is called after an attribute is validated. The signature of the callback should be:
// function ($form, attribute, messages)
afterValidate: undefined,
// a callback that is called after all validation has run (This callback is only called when the form is submitted). The signature of the callback should be:
// function ($form, data, messages)
afterValidateAll: undefined,
// a pre-request callback function on AJAX-based validation. The signature of the callback should be:
// function ($form, jqXHR, textStatus)
ajaxBeforeSend: undefined,
......@@ -152,6 +158,11 @@
clearTimeout(data.settings.timer);
}
data.submitting = true;
if (data.settings.beforeValidateAll && !data.settings.beforeValidateAll($form, data)) {
data.submitting = false;
return false;
}
validate($form, function (messages) {
var errors = [];
$.each(data.attributes, function () {
......@@ -159,6 +170,11 @@
errors.push(this.input);
}
});
if (data.settings.afterValidateAll) {
data.settings.afterValidateAll($form, data, messages);
}
updateSummary($form, messages);
if (errors.length) {
var top = $form.find(errors.join(',')).first().offset().top;
......
......@@ -111,7 +111,7 @@ yii.validation = (function ($) {
};
img.onerror = function () {
messages.push(options.notImage);
messages.push(options.notImage.replace(/\{file\}/g, file.name));
def.resolve();
};
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\base;
/**
* InvalidValueException represents an exception caused by a function returning a value of unexpected type.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class InvalidValueException extends \UnexpectedValueException
{
/**
* @return string the user-friendly name of this exception
*/
public function getName()
{
return 'Invalid Return Value';
}
}
......@@ -121,7 +121,7 @@ class HelpController extends Controller
foreach ($class->getMethods() as $method) {
$name = $method->getName();
if ($method->isPublic() && !$method->isStatic() && strpos($name, 'action') === 0 && $name !== 'actions') {
$actions[] = Inflector::camel2id(substr($name, 6));
$actions[] = Inflector::camel2id(substr($name, 6), '-', true);
}
}
sort($actions);
......
......@@ -54,20 +54,20 @@ class ActionColumn extends Column
* signature:
*
* ```php
* function ($url, $model) {
* function ($url, $model, $key) {
* // return the button HTML code
* }
* ```
*
* where `$url` is the URL that the column creates for the button, and `$model` is the model object
* being rendered for the current row.
* where `$url` is the URL that the column creates for the button, `$model` is the model object
* being rendered for the current row, and `$key` is the key of the model in the data provider array.
*
* You can add further conditions to the button, for example only display it, when the model is
* editable (here assuming you have a status field that indicates that):
*
* ```php
* [
* 'update' => function ($url, $model) {
* 'update' => function ($url, $model, $key) {
* return $model->status == 'editable' ? Html::a('Update', $url) : '';
* };
* ],
......@@ -155,7 +155,7 @@ class ActionColumn extends Column
if (isset($this->buttons[$name])) {
$url = $this->createUrl($name, $model, $key, $index);
return call_user_func($this->buttons[$name], $url, $model);
return call_user_func($this->buttons[$name], $url, $model, $key);
} else {
return '';
}
......
......@@ -33,7 +33,7 @@ class BaseMarkdown
'html5' => true,
],
'gfm-comment' => [
'class' => 'cebe\markdown\Markdown',
'class' => 'cebe\markdown\GithubMarkdown',
'html5' => true,
'enableNewlines' => true,
],
......
......@@ -73,7 +73,7 @@ class BaseUrl
* @param boolean|string $scheme the URI scheme to use in the generated URL:
*
* - `false` (default): generating a relative URL.
* - `true`: generating an absolute URL whose scheme is the same as the current request.
* - `true`: returning an absolute base URL whose scheme is the same as that in [[\yii\web\UrlManager::hostInfo]].
* - string: generating an absolute URL with the specified scheme (either `http` or `https`).
*
* @return string the generated URL
......@@ -133,21 +133,20 @@ class BaseUrl
* Creates a URL based on the given parameters.
*
* This method is very similar to [[toRoute()]]. The only difference is that this method
* requires a route to be specified as an array only. If a string is given, it will be treated
* as a URL which will be prefixed with the base URL if it does not start with a slash.
* requires a route to be specified as an array only. If a string is given, it will be treated as a URL.
* In particular, if `$url` is
*
* - an array: [[toRoute()]] will be called to generate the URL. For example:
* `['site/index']`, `['post/index', 'page' => 2]`. Please refer to [[toRoute()]] for more details
* on how to specify a route.
* - a string with a leading `@`: it is treated as an alias and the corresponding aliased string
* will be subject to the following rules.
* - a string with a leading `@`: it is treated as an alias, and the corresponding aliased string
* will be returned.
* - an empty string: the currently requested URL will be returned;
* - a string without a leading slash: it will be prefixed with [[\yii\web\Request::baseUrl]].
* - a string with a leading slash: it will be returned as is.
* - a normal string: it will be returned as is.
*
* Note that in case `$scheme` is specified (either a string or true), an absolute URL with host info
* will be returned.
* When `$scheme` is specified (either a string or true), an absolute URL with host info (obtained from
* [[\yii\web\UrlManager::hostInfo]]) will be returned. If `$url` is already an absolute URL, its scheme
* will be replaced with the specified one.
*
* Below are some examples of using this method:
*
......@@ -162,13 +161,16 @@ class BaseUrl
* echo Url::to();
*
* // /images/logo.gif
* echo Url::to('@web/images/logo.gif');
*
* // images/logo.gif
* echo Url::to('images/logo.gif');
*
* // http://www.example.com/index.php?r=site/index
* echo Url::to(['site/index'], true);
* // http://www.example.com/images/logo.gif
* echo Url::to('@web/images/logo.gif', true);
*
* // https://www.example.com/index.php?r=site/index
* echo Url::to(['site/index'], 'https');
* // https://www.example.com/images/logo.gif
* echo Url::to('@web/images/logo.gif', 'https');
* ```
*
*
......@@ -176,7 +178,7 @@ class BaseUrl
* @param boolean|string $scheme the URI scheme to use in the generated URL:
*
* - `false` (default): generating a relative URL.
* - `true`: generating an absolute URL whose scheme is the same as the current request.
* - `true`: returning an absolute base URL whose scheme is the same as that in [[\yii\web\UrlManager::hostInfo]].
* - string: generating an absolute URL with the specified scheme (either `http` or `https`).
*
* @return string the generated URL
......@@ -188,25 +190,28 @@ class BaseUrl
return static::toRoute($url, $scheme);
}
$url = (string) Yii::getAlias($url);
$url = Yii::getAlias($url);
if ($url === '') {
$url = Yii::$app->getRequest()->getUrl();
} else {
$hasScheme = ($pos = strpos($url, ':')) > 0 && ctype_alpha(substr($url, 0, $pos));
$char = $url[0];
if ($char !== '/' && $char !== '#' && $char !== '.' && !$hasScheme) {
$url = Yii::$app->getUrlManager()->getBaseUrl() . '/' . $url;
}
}
if ($scheme) {
if (empty($hasScheme)) {
$url = Yii::$app->getUrlManager()->getHostInfo() . '/' . ltrim($url, '/');
}
if (is_string($scheme) && ($pos = strpos($url, ':')) !== false) {
$url = $scheme . substr($url, $pos);
}
if (!$scheme) {
return $url;
}
if (strncmp($url, '//', 2) === 0) {
// e.g. //hostname/path/to/resource
return is_string($scheme) ? "$scheme:$url" : $url;
}
if (($pos = strpos($url, ':')) == false || !ctype_alpha(substr($url, 0, $pos))) {
// turn relative URL into absolute
$url = Yii::$app->getUrlManager()->getHostInfo() . '/' . ltrim($url, '/');
}
if (is_string($scheme) && ($pos = strpos($url, ':')) !== false) {
// replace the scheme with the specified one
$url = $scheme . substr($url, $pos);
}
return $url;
......@@ -217,7 +222,7 @@ class BaseUrl
* @param boolean|string $scheme the URI scheme to use in the returned base URL:
*
* - `false` (default): returning the base URL without host info.
* - `true`: returning an absolute base URL whose scheme is the same as the current request.
* - `true`: returning an absolute base URL whose scheme is the same as that in [[\yii\web\UrlManager::hostInfo]].
* - string: returning an absolute base URL with the specified scheme (either `http` or `https`).
* @return string
*/
......@@ -296,7 +301,7 @@ class BaseUrl
* @param boolean|string $scheme the URI scheme to use for the returned URL:
*
* - `false` (default): returning a relative URL.
* - `true`: returning an absolute URL whose scheme is the same as the current request.
* - `true`: returning an absolute base URL whose scheme is the same as that in [[\yii\web\UrlManager::hostInfo]].
* - string: returning an absolute URL with the specified scheme (either `http` or `https`).
*
* @return string home URL
......
......@@ -197,13 +197,8 @@ class Validator extends Component
$type = static::$builtInValidators[$type];
}
if (is_array($type)) {
foreach ($type as $name => $value) {
$params[$name] = $value;
}
$params = array_merge($type, $params);
} else {
if (!class_exists($type)) {
throw new InvalidConfigException("Unknown validator: '$type'.");
}
$params['class'] = $type;
}
}
......@@ -308,6 +303,7 @@ class Validator extends Component
* - `attribute`: the name of the attribute being validated.
* - `value`: the value being validated.
* - `messages`: an array used to hold the validation error messages for the attribute.
* - `deferred`: an array used to hold deferred objects for asynchronous validation
*
* @param \yii\base\Model $object the data object being validated
* @param string $attribute the name of the attribute to be validated.
......
......@@ -83,6 +83,10 @@ class UrlRule extends Object implements UrlRuleInterface
* If it is [[CREATION_ONLY]], the rule is for URL creation only.
*/
public $mode;
/**
* @var bool a value indicating if parameters should be url encoded.
*/
public $encodeParams = true;
/**
* @var string the template for generating a new URL. This is derived from [[pattern]] and is used in generating URL.
......@@ -310,7 +314,7 @@ class UrlRule extends Object implements UrlRuleInterface
// match params in the pattern
foreach ($this->_paramRules as $name => $rule) {
if (isset($params[$name]) && !is_array($params[$name]) && ($rule === '' || preg_match($rule, $params[$name]))) {
$tr["<$name>"] = urlencode($params[$name]);
$tr["<$name>"] = $this->encodeParams ? urlencode($params[$name]) : $params[$name];
unset($params[$name]);
} elseif (!isset($this->defaults[$name]) || isset($params[$name])) {
return false;
......
......@@ -10,6 +10,7 @@ namespace yii\web;
use Yii;
use yii\base\Component;
use yii\base\InvalidConfigException;
use yii\base\InvalidValueException;
/**
* User is the class for the "user" application component that manages the user authentication status.
......@@ -186,11 +187,18 @@ class User extends Component
*
* @param IdentityInterface|null $identity the identity object associated with the currently logged user.
* If null, it means the current user will be a guest without any associated identity.
* @throws InvalidValueException if `$identity` object does not implement [[IdentityInterface]].
*/
public function setIdentity($identity)
{
$this->_identity = $identity;
$this->_access = [];
if ($identity instanceof IdentityInterface) {
$this->_identity = $identity;
$this->_access = [];
} elseif ($identity === null) {
$this->_identity = null;
} else {
throw new InvalidValueException('The identity object must implement IdentityInterface.');
}
}
/**
......@@ -219,7 +227,7 @@ class User extends Component
* Note that if [[enableSession]] is false, this parameter will be ignored.
* @return boolean whether the user is logged in
*/
public function login($identity, $duration = 0)
public function login(IdentityInterface $identity, $duration = 0)
{
if ($this->beforeLogin($identity, false, $duration)) {
$this->switchIdentity($identity, $duration);
......@@ -274,21 +282,29 @@ class User extends Component
}
$data = json_decode($value, true);
if (count($data) === 3 && isset($data[0], $data[1], $data[2])) {
list ($id, $authKey, $duration) = $data;
/* @var $class IdentityInterface */
$class = $this->identityClass;
$identity = $class::findIdentity($id);
if ($identity !== null && $identity->validateAuthKey($authKey)) {
if ($this->beforeLogin($identity, true, $duration)) {
$this->switchIdentity($identity, $this->autoRenewCookie ? $duration : 0);
$ip = Yii::$app->getRequest()->getUserIP();
Yii::info("User '$id' logged in from $ip via cookie.", __METHOD__);
$this->afterLogin($identity, true, $duration);
}
} elseif ($identity !== null) {
Yii::warning("Invalid auth key attempted for user '$id': $authKey", __METHOD__);
if (count($data) !== 3 || !isset($data[0], $data[1], $data[2])) {
return;
}
list ($id, $authKey, $duration) = $data;
/* @var $class IdentityInterface */
$class = $this->identityClass;
$identity = $class::findIdentity($id);
if ($identity === null) {
return;
} elseif (!$identity instanceof IdentityInterface) {
throw new InvalidValueException("$class::findIdentity() must return an object implementing IdentityInterface.");
}
if ($identity->validateAuthKey($authKey)) {
if ($this->beforeLogin($identity, true, $duration)) {
$this->switchIdentity($identity, $this->autoRenewCookie ? $duration : 0);
$ip = Yii::$app->getRequest()->getUserIP();
Yii::info("User '$id' logged in from $ip via cookie.", __METHOD__);
$this->afterLogin($identity, true, $duration);
}
} else {
Yii::warning("Invalid auth key attempted for user '$id': $authKey", __METHOD__);
}
}
......@@ -552,7 +568,7 @@ class User extends Component
$session->remove($this->idParam);
$session->remove($this->authTimeoutParam);
if ($identity instanceof IdentityInterface) {
if ($identity) {
$session->set($this->idParam, $identity->getId());
if ($this->authTimeout !== null) {
$session->set($this->authTimeoutParam, time() + $this->authTimeout);
......
......@@ -142,6 +142,17 @@ class ActiveForm extends Widget
*/
public $beforeValidate;
/**
* @var string|JsExpression a JS callback that is called before any validation has run (Only called when the form is submitted).
* The signature of the callback should be:
*
* ~~~
* function ($form, data) {
* ...return false to cancel the validation...
* }
* ~~~
*/
public $beforeValidateAll;
/**
* @var string|JsExpression a JS callback that is called after validating an attribute.
* The signature of the callback should be:
*
......@@ -152,6 +163,16 @@ class ActiveForm extends Widget
*/
public $afterValidate;
/**
* @var string|JsExpression a JS callback that is called after all validation has run (Only called when the form is submitted).
* The signature of the callback should be:
*
* ~~~
* function ($form, data, messages) {
* }
* ~~~
*/
public $afterValidateAll;
/**
* @var string|JsExpression a JS pre-request callback function on AJAX-based validation.
* The signature of the callback should be:
*
......@@ -229,7 +250,7 @@ class ActiveForm extends Widget
if ($this->validationUrl !== null) {
$options['validationUrl'] = Url::to($this->validationUrl);
}
foreach (['beforeSubmit', 'beforeValidate', 'afterValidate', 'ajaxBeforeSend', 'ajaxComplete'] as $name) {
foreach (['beforeSubmit', 'beforeValidate', 'beforeValidateAll', 'afterValidate', 'afterValidateAll', 'ajaxBeforeSend', 'ajaxComplete'] as $name) {
if (($value = $this->$name) !== null) {
$options[$name] = $value instanceof JsExpression ? $value : new JsExpression($value);
}
......
......@@ -72,25 +72,25 @@ class LinkPager extends Widget
*/
public $maxButtonCount = 10;
/**
* @var string the label for the "next" page button. Note that this will NOT be HTML-encoded.
* If this property is null, the "next" page button will not be displayed.
* @var string|boolean the label for the "next" page button. Note that this will NOT be HTML-encoded.
* If this property is false, the "next" page button will not be displayed.
*/
public $nextPageLabel = '&raquo;';
/**
* @var string the text label for the previous page button. Note that this will NOT be HTML-encoded.
* If this property is null, the "previous" page button will not be displayed.
* @var string|boolean the text label for the previous page button. Note that this will NOT be HTML-encoded.
* If this property is false, the "previous" page button will not be displayed.
*/
public $prevPageLabel = '&laquo;';
/**
* @var string the text label for the "first" page button. Note that this will NOT be HTML-encoded.
* If this property is null, the "first" page button will not be displayed.
* @var string|boolean the text label for the "first" page button. Note that this will NOT be HTML-encoded.
* Default is false that means the "first" page button will not be displayed.
*/
public $firstPageLabel;
public $firstPageLabel = false;
/**
* @var string the text label for the "last" page button. Note that this will NOT be HTML-encoded.
* If this property is null, the "last" page button will not be displayed.
* @var string|boolean the text label for the "last" page button. Note that this will NOT be HTML-encoded.
* Default is false that means the "last" page button will not be displayed.
*/
public $lastPageLabel;
public $lastPageLabel = false;
/**
* @var boolean whether to register link tags in the HTML header for prev, next, first and last page.
* Defaults to `false` to avoid conflicts when multiple pagers are used on one page.
......@@ -154,12 +154,12 @@ class LinkPager extends Widget
$currentPage = $this->pagination->getPage();
// first page
if ($this->firstPageLabel !== null) {
if ($this->firstPageLabel !== false) {
$buttons[] = $this->renderPageButton($this->firstPageLabel, 0, $this->firstPageCssClass, $currentPage <= 0, false);
}
// prev page
if ($this->prevPageLabel !== null) {
if ($this->prevPageLabel !== false) {
if (($page = $currentPage - 1) < 0) {
$page = 0;
}
......@@ -173,7 +173,7 @@ class LinkPager extends Widget
}
// next page
if ($this->nextPageLabel !== null) {
if ($this->nextPageLabel !== false) {
if (($page = $currentPage + 1) >= $pageCount - 1) {
$page = $pageCount - 1;
}
......@@ -181,7 +181,7 @@ class LinkPager extends Widget
}
// last page
if ($this->lastPageLabel !== null) {
if ($this->lastPageLabel !== false) {
$buttons[] = $this->renderPageButton($this->lastPageLabel, $pageCount - 1, $this->lastPageCssClass, $currentPage >= $pageCount - 1, false);
}
......
......@@ -4,8 +4,9 @@ namespace yiiunit\extensions\twig;
use yii\web\AssetManager;
use yii\web\View;
use Yii;
use yiiunit\data\ar\Order;
use yiiunit\data\base\Singer;
use yiiunit\TestCase;
use yiiunit\framework\db\DatabaseTestCase;
/**
* Tests Twig view renderer
......@@ -13,10 +14,13 @@ use yiiunit\TestCase;
* @author Alexander Makarov <sam@rmcreative.ru>
* @author Carsten Brandt <mail@cebe.cc>
*/
class ViewRendererTest extends TestCase
class ViewRendererTest extends DatabaseTestCase
{
protected $driverName = 'sqlite';
protected function setUp()
{
parent::setUp();
$this->mockApplication();
}
......@@ -93,6 +97,14 @@ class ViewRendererTest extends TestCase
$this->assertFalse(strpos($content, 'Original title') !== false, 'Original title should not be there:' . $content);
}
public function testNullsInAr()
{
$view = $this->mockView();
$order = new Order();
$order::$db = $this->getConnection();
$view->renderFile('@yiiunit/extensions/twig/views/nulls.twig', ['order' => $order]);
}
/**
* Mocks view instance
* @return View
......
{{ order.customer }}
\ No newline at end of file
......@@ -121,21 +121,27 @@ class UrlTest extends TestCase
\Yii::setAlias('@web4', '/test');
\Yii::setAlias('@web5', '#test');
$this->assertEquals('/base/test/me1', Url::to('test/me1'));
$this->assertEquals('test/me1', Url::to('test/me1'));
$this->assertEquals('javascript:test/me1', Url::to('javascript:test/me1'));
$this->assertEquals('/base/java/script:test/me1', Url::to('java/script:test/me1'));
$this->assertEquals('java/script:test/me1', Url::to('java/script:test/me1'));
$this->assertEquals('#test/me1', Url::to('#test/me1'));
$this->assertEquals('.test/me1', Url::to('.test/me1'));
$this->assertEquals('http://example.com/base/test/me1', Url::to('test/me1', true));
$this->assertEquals('https://example.com/base/test/me1', Url::to('test/me1', 'https'));
$this->assertEquals('http://example.com/test/me1', Url::to('test/me1', true));
$this->assertEquals('https://example.com/test/me1', Url::to('test/me1', 'https'));
$this->assertEquals('https://example.com/test/test/me1', Url::to('@web4/test/me1', 'https'));
$this->assertEquals('/test/me1', Url::to('/test/me1'));
$this->assertEquals('http://example.com/test/me1', Url::to('/test/me1', true));
$this->assertEquals('https://example.com/test/me1', Url::to('/test/me1', 'https'));
$this->assertEquals('./test/me1', Url::to('./test/me1'));
$this->assertEquals('http://test.example.com/test/me1', Url::to('@web1'));
$this->assertEquals('http://test.example.com/test/me1', Url::to('@web1', true));
$this->assertEquals('https://test.example.com/test/me1', Url::to('@web1', 'https'));
$this->assertEquals('/base/test/me2', Url::to('@web2'));
$this->assertEquals('http://example.com/base/test/me2', Url::to('@web2', true));
$this->assertEquals('https://example.com/base/test/me2', Url::to('@web2', 'https'));
$this->assertEquals('test/me2', Url::to('@web2'));
$this->assertEquals('http://example.com/test/me2', Url::to('@web2', true));
$this->assertEquals('https://example.com/test/me2', Url::to('@web2', 'https'));
$this->assertEquals('/base/index.php&r=site%2Fcurrent&id=42', Url::to('@web3'));
$this->assertEquals('http://example.com/base/index.php&r=site%2Fcurrent&id=42', Url::to('@web3', true));
......
......@@ -11,6 +11,15 @@ function filemtime($file)
return \yiiunit\framework\rbac\PhpManagerTest::$filemtime ?: \filemtime($file);
}
/**
* Mock for the time() function for rbac classes. Avoid random test fails.
* @return int
*/
function time()
{
return \yiiunit\framework\rbac\PhpManagerTest::$time ?: \time();
}
namespace yiiunit\framework\rbac;
use Yii;
......@@ -22,6 +31,7 @@ use Yii;
class PhpManagerTest extends ManagerTestCase
{
public static $filemtime;
public static $time;
protected function getItemFile()
{
......@@ -60,6 +70,7 @@ class PhpManagerTest extends ManagerTestCase
protected function setUp()
{
static::$filemtime = null;
static::$time = null;
parent::setUp();
$this->mockApplication();
$this->removeDataFiles();
......@@ -70,18 +81,19 @@ class PhpManagerTest extends ManagerTestCase
{
$this->removeDataFiles();
static::$filemtime = null;
static::$time = null;
parent::tearDown();
}
public function testSaveLoad()
{
$this->prepareData();
static::$time = static::$filemtime = \time();
$this->prepareData();
$items = $this->auth->items;
$children = $this->auth->children;
$assignments = $this->auth->assignments;
$rules = $this->auth->rules;
static::$filemtime = time();
$this->auth->save();
$this->auth = $this->createManager();
......
......@@ -17,8 +17,8 @@ class BreadcrumbsTest extends \yiiunit\TestCase
public function setUp()
{
// dirty way to have Request object not throwing exception when running testHomeLinkNull()
$_SERVER['SCRIPT_FILENAME'] = "index.php";
$_SERVER['SCRIPT_NAME'] = "index.php";
$_SERVER['SCRIPT_FILENAME'] = "/index.php";
$_SERVER['SCRIPT_NAME'] = "/index.php";
$this->mockWebApplication();
$this->breadcrumbs = new Breadcrumbs();
......@@ -29,7 +29,7 @@ class BreadcrumbsTest extends \yiiunit\TestCase
$this->breadcrumbs->homeLink = null;
$this->breadcrumbs->links = ['label' => 'My Home Page', 'url' => 'http://my.example.com/yii2/link/page'];
$expectedHtml = "<ul class=\"breadcrumb\"><li><a href=\"./index.php\">Home</a></li>\n"
$expectedHtml = "<ul class=\"breadcrumb\"><li><a href=\"/index.php\">Home</a></li>\n"
. "<li class=\"active\">My Home Page</li>\n"
. "<li class=\"active\">http://my.example.com/yii2/link/page</li>\n"
. "</ul>";
......
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