diff --git a/apps/advanced/backend/views/layouts/main.php b/apps/advanced/backend/views/layouts/main.php index cb41c08..0a1bf13 100644 --- a/apps/advanced/backend/views/layouts/main.php +++ b/apps/advanced/backend/views/layouts/main.php @@ -37,7 +37,11 @@ AppAsset::register($this); if (Yii::$app->user->isGuest) { $menuItems[] = ['label' => 'Login', 'url' => ['/site/login']]; } else { - $menuItems[] = ['label' => 'Logout (' . Yii::$app->user->identity->username .')' , 'url' => ['/site/logout']]; + $menuItems[] = [ + 'label' => 'Logout (' . Yii::$app->user->identity->username . ')', + 'url' => ['/site/logout'], + 'linkOptions' => ['data-method' => 'post'] + ]; } echo Nav::widget([ 'options' => ['class' => 'navbar-nav navbar-right'], diff --git a/apps/advanced/common/mail/layouts/html.php b/apps/advanced/common/mail/layouts/html.php index 2e6b615..8e2707d 100644 --- a/apps/advanced/common/mail/layouts/html.php +++ b/apps/advanced/common/mail/layouts/html.php @@ -1,10 +1,9 @@ <?php use yii\helpers\Html; -use yii\mail\BaseMessage; /** * @var \yii\web\View $this - * @var BaseMessage $content + * @var \yii\mail\BaseMessage $content */ ?> <?php $this->beginPage() ?> diff --git a/apps/advanced/common/tests/_helpers/FixtureHelper.php b/apps/advanced/common/tests/_helpers/FixtureHelper.php index 00c3a17..507b60c 100644 --- a/apps/advanced/common/tests/_helpers/FixtureHelper.php +++ b/apps/advanced/common/tests/_helpers/FixtureHelper.php @@ -32,7 +32,7 @@ class FixtureHelper extends Module * to use in acceptance and functional tests. * @param array $settings */ - public function _beforeSuite($settings = array()) + public function _beforeSuite($settings = []) { $this->loadFixtures(); } @@ -54,5 +54,4 @@ class FixtureHelper extends Module ], ]; } - } diff --git a/apps/advanced/common/tests/_pages/LoginPage.php b/apps/advanced/common/tests/_pages/LoginPage.php index af95ea3..5fdf3bc 100644 --- a/apps/advanced/common/tests/_pages/LoginPage.php +++ b/apps/advanced/common/tests/_pages/LoginPage.php @@ -18,5 +18,4 @@ class LoginPage extends BasePage $this->guy->fillField('input[name="LoginForm[password]"]', $password); $this->guy->click('login-button'); } - } diff --git a/apps/advanced/common/tests/unit/models/LoginFormTest.php b/apps/advanced/common/tests/unit/models/LoginFormTest.php index 2ececd6..9ca277d 100644 --- a/apps/advanced/common/tests/unit/models/LoginFormTest.php +++ b/apps/advanced/common/tests/unit/models/LoginFormTest.php @@ -25,7 +25,7 @@ class LoginFormTest extends TestCase $model->username = 'some_username'; $model->password = 'some_password'; - $this->specify('user should not be able to login, when there is no identity' , function () use ($model) { + $this->specify('user should not be able to login, when there is no identity', function () use ($model) { expect('model should not login user', $model->login())->false(); expect('user should not be logged in', Yii::$app->user->isGuest)->true(); }); @@ -52,7 +52,7 @@ class LoginFormTest extends TestCase $model->username = 'demo'; $model->password = 'demo'; - $this->specify('user should be able to login with correct credentials', function() use ($model) { + $this->specify('user should be able to login with correct credentials', function () use ($model) { expect('model should login user', $model->login())->true(); expect('error message should not be set', $model->errors)->hasntKey('password'); expect('user should be logged in', Yii::$app->user->isGuest)->false(); @@ -61,9 +61,8 @@ class LoginFormTest extends TestCase private function mockUser($user) { - $loginForm = $this->getMock('common\models\LoginForm',['getUser']); + $loginForm = $this->getMock('common\models\LoginForm', ['getUser']); $loginForm->expects($this->any())->method('getUser')->will($this->returnValue($user)); return $loginForm; } - } diff --git a/apps/advanced/composer.json b/apps/advanced/composer.json index 53e926f..7744971 100644 --- a/apps/advanced/composer.json +++ b/apps/advanced/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-app-advanced", "description": "Yii 2 Advanced Application Template", - "keywords": ["yii", "framework", "advanced", "application template"], + "keywords": ["yii2", "framework", "advanced", "application template"], "homepage": "http://www.yiiframework.com/", "type": "project", "license": "BSD-3-Clause", diff --git a/apps/advanced/frontend/tests/_pages/SignupPage.php b/apps/advanced/frontend/tests/_pages/SignupPage.php index ba4a9cb..0281ac9 100644 --- a/apps/advanced/frontend/tests/_pages/SignupPage.php +++ b/apps/advanced/frontend/tests/_pages/SignupPage.php @@ -20,5 +20,4 @@ class SignupPage extends BasePage } $this->guy->click('signup-button'); } - } diff --git a/apps/advanced/frontend/tests/acceptance/SignupCest.php b/apps/advanced/frontend/tests/acceptance/SignupCest.php index a166f34..268ff6b 100644 --- a/apps/advanced/frontend/tests/acceptance/SignupCest.php +++ b/apps/advanced/frontend/tests/acceptance/SignupCest.php @@ -79,5 +79,4 @@ class SignupCest $I->expectTo('see that user logged in'); $I->see('Logout (tester)'); } - } diff --git a/apps/advanced/frontend/tests/functional/SignupCest.php b/apps/advanced/frontend/tests/functional/SignupCest.php index cfef787..0409d23 100644 --- a/apps/advanced/frontend/tests/functional/SignupCest.php +++ b/apps/advanced/frontend/tests/functional/SignupCest.php @@ -79,5 +79,4 @@ class SignupCest $I->expectTo('see that user logged in'); $I->see('Logout (tester)'); } - } diff --git a/apps/advanced/frontend/tests/unit/models/ContactFormTest.php b/apps/advanced/frontend/tests/unit/models/ContactFormTest.php index 23e6288..a754672 100644 --- a/apps/advanced/frontend/tests/unit/models/ContactFormTest.php +++ b/apps/advanced/frontend/tests/unit/models/ContactFormTest.php @@ -42,7 +42,7 @@ class ContactFormTest extends TestCase expect('email file should exist', file_exists($this->getMessageFile()))->true(); }); - $this->specify('message should contain correct data', function () use($model) { + $this->specify('message should contain correct data', function () use ($model) { $emailMessage = file_get_contents($this->getMessageFile()); expect('email should contain user name', $emailMessage)->contains($model->name); @@ -56,5 +56,4 @@ class ContactFormTest extends TestCase { return Yii::getAlias(Yii::$app->mail->fileTransportPath) . '/testing_message.eml'; } - } diff --git a/apps/advanced/frontend/tests/unit/models/PasswordResetRequestFormTest.php b/apps/advanced/frontend/tests/unit/models/PasswordResetRequestFormTest.php index b736039..7591ff3 100644 --- a/apps/advanced/frontend/tests/unit/models/PasswordResetRequestFormTest.php +++ b/apps/advanced/frontend/tests/unit/models/PasswordResetRequestFormTest.php @@ -28,14 +28,14 @@ class PasswordResetRequestFormTest extends DbTestCase public function testSendEmailWrongUser() { - $this->specify('no user with such email, message should not be send', function() { + $this->specify('no user with such email, message should not be send', function () { $model = new PasswordResetRequestForm(); $model->email = 'not-existing-email@example.com'; expect('email not send', $model->sendEmail())->false(); }); - $this->specify('user is not active, message should not be send', function() { + $this->specify('user is not active, message should not be send', function () { $model = new PasswordResetRequestForm(); $model->email = $this->user[1]['email']; @@ -52,8 +52,8 @@ class PasswordResetRequestFormTest extends DbTestCase expect('email sent', $model->sendEmail())->true(); expect('user has valid token', $user->password_reset_token)->notNull(); - $this->specify('message has correct format', function() use ($model) { - expect('message file exists', file_exists($this->getMessageFile()))->true(); + $this->specify('message has correct format', function () use ($model) { + expect('message file exists', file_exists($this->getMessageFile()))->true(); $message = file_get_contents($this->getMessageFile()); expect('message "from" is correct', $message)->contains(Yii::$app->params['supportEmail']); @@ -75,5 +75,4 @@ class PasswordResetRequestFormTest extends DbTestCase { return Yii::getAlias(Yii::$app->mail->fileTransportPath) . '/testing_message.eml'; } - } diff --git a/apps/advanced/frontend/tests/unit/models/ResetPasswordFormTest.php b/apps/advanced/frontend/tests/unit/models/ResetPasswordFormTest.php index 763683f..b00c2ac 100644 --- a/apps/advanced/frontend/tests/unit/models/ResetPasswordFormTest.php +++ b/apps/advanced/frontend/tests/unit/models/ResetPasswordFormTest.php @@ -13,13 +13,13 @@ class ResetPasswordFormTest extends DbTestCase public function testResetPassword() { - $this->specify('wrong reset token', function() { - $this->setExpectedException('\Exception','Wrong password reset token.'); + $this->specify('wrong reset token', function () { + $this->setExpectedException('\Exception', 'Wrong password reset token.'); new ResetPasswordForm('notexistingtoken_1391882543'); }); - $this->specify('not correct token', function() { - $this->setExpectedException('yii\base\InvalidParamException','Password reset token cannot be blank.'); + $this->specify('not correct token', function () { + $this->setExpectedException('yii\base\InvalidParamException', 'Password reset token cannot be blank.'); new ResetPasswordForm(''); }); } @@ -33,5 +33,4 @@ class ResetPasswordFormTest extends DbTestCase ], ]; } - } diff --git a/apps/advanced/frontend/tests/unit/models/SignupFormTest.php b/apps/advanced/frontend/tests/unit/models/SignupFormTest.php index 5176baa..359a02c 100644 --- a/apps/advanced/frontend/tests/unit/models/SignupFormTest.php +++ b/apps/advanced/frontend/tests/unit/models/SignupFormTest.php @@ -12,7 +12,7 @@ class SignupFormTest extends DbTestCase public function testCorrectSignup() { - $model = $this->getMock('frontend\models\SignupForm',['validate']); + $model = $this->getMock('frontend\models\SignupForm', ['validate']); $model->expects($this->once())->method('validate')->will($this->returnValue(true)); $model->username = 'some_username'; @@ -28,7 +28,7 @@ class SignupFormTest extends DbTestCase public function testNotCorrectSignup() { - $model = $this->getMock('frontend\models\SignupForm',['validate']); + $model = $this->getMock('frontend\models\SignupForm', ['validate']); $model->expects($this->once())->method('validate')->will($this->returnValue(false)); expect('user should not be created', $model->signup())->null(); @@ -43,5 +43,4 @@ class SignupFormTest extends DbTestCase ], ]; } - } diff --git a/apps/advanced/frontend/views/layouts/main.php b/apps/advanced/frontend/views/layouts/main.php index be8d70d..6e3ae8c 100644 --- a/apps/advanced/frontend/views/layouts/main.php +++ b/apps/advanced/frontend/views/layouts/main.php @@ -41,7 +41,11 @@ AppAsset::register($this); $menuItems[] = ['label' => 'Signup', 'url' => ['/site/signup']]; $menuItems[] = ['label' => 'Login', 'url' => ['/site/login']]; } else { - $menuItems[] = ['label' => 'Logout (' . Yii::$app->user->identity->username .')' , 'url' => ['/site/logout']]; + $menuItems[] = [ + 'label' => 'Logout (' . Yii::$app->user->identity->username . ')', + 'url' => ['/site/logout'], + 'linkOptions' => ['data-method' => 'post'] + ]; } echo Nav::widget([ 'options' => ['class' => 'navbar-nav navbar-right'], diff --git a/apps/basic/composer.json b/apps/basic/composer.json index 9990ef7..726a7ea 100644 --- a/apps/basic/composer.json +++ b/apps/basic/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-app-basic", "description": "Yii 2 Basic Application Template", - "keywords": ["yii", "framework", "basic", "application template"], + "keywords": ["yii2", "framework", "basic", "application template"], "homepage": "http://www.yiiframework.com/", "type": "project", "license": "BSD-3-Clause", diff --git a/apps/basic/mail/layouts/html.php b/apps/basic/mail/layouts/html.php index 2e6b615..8e2707d 100644 --- a/apps/basic/mail/layouts/html.php +++ b/apps/basic/mail/layouts/html.php @@ -1,10 +1,9 @@ <?php use yii\helpers\Html; -use yii\mail\BaseMessage; /** * @var \yii\web\View $this - * @var BaseMessage $content + * @var \yii\mail\BaseMessage $content */ ?> <?php $this->beginPage() ?> diff --git a/apps/benchmark/composer.json b/apps/benchmark/composer.json index d980f9a..c8ed589 100644 --- a/apps/benchmark/composer.json +++ b/apps/benchmark/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-app-benchmark", "description": "Yii 2 Benchmark Application", - "keywords": ["yii", "framework", "benchmark", "application"], + "keywords": ["yii2", "framework", "benchmark", "application"], "homepage": "http://www.yiiframework.com/", "type": "project", "license": "BSD-3-Clause", diff --git a/build/controllers/ClassmapController.php b/build/controllers/ClassmapController.php index 706435a..5fd4e5f 100644 --- a/build/controllers/ClassmapController.php +++ b/build/controllers/ClassmapController.php @@ -52,7 +52,7 @@ class ClassmapController extends Controller $files = FileHelper::findFiles($root, $options); $map = []; foreach ($files as $file) { - if (($pos = strpos($file, $root)) !== 0) { + if (strpos($file, $root) !== 0) { die("Something wrong: $file\n"); } $path = str_replace('\\', '/', substr($file, strlen($root))); diff --git a/composer.json b/composer.json index d01de32..2466074 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-dev", "description": "Yii PHP Framework Version 2 - Development Package", - "keywords": ["yii", "framework"], + "keywords": ["yii2", "framework"], "homepage": "http://www.yiiframework.com/", "type": "yii2-extension", "license": "BSD-3-Clause", @@ -74,6 +74,7 @@ "lib-pcre": "*", "yiisoft/yii2-composer": "*", "yiisoft/jquery": "~2.0 | ~1.10", + "yiisoft/jquery-pjax": "*", "ezyang/htmlpurifier": "4.6.*", "cebe/markdown": "0.9.*" }, diff --git a/docs/guide/assets.md b/docs/guide/assets.md index 17c6797..ca3b07c 100644 --- a/docs/guide/assets.md +++ b/docs/guide/assets.md @@ -81,18 +81,26 @@ following way: ```php class LanguageAsset extends AssetBundle { - public $sourcePath = '@app/assets/language'; - public $js = [ - ]; - - public function init() - { - $this->js[] = 'language-' . Yii::$app->language . '.js'; - parent::init(); - } + public $language; + public $sourcePath = '@app/assets/language'; + public $js = [ + ]; + + public function registerAssetFiles($view) + { + $language = $this->language ? $this->language : Yii::$app->language; + $this->js[] = 'language-' . $language . '.js'; + parent::registerAssetFiles($view); + } } ``` +In order to set language use the following code when registering an asset bundle in a view: + +```php +LanguageAsset::register($this)->language = $language; +``` + Registering asset bundle ------------------------ @@ -114,6 +122,10 @@ To register an asset inside of a widget, the view instance is available as `$thi AppAsset::register($this->view); ``` +> Note: If there is a need to modify third party asset bundles it is recommended to create your own bundles depending + on third party ones and use CSS and JavaScript features to modify behavior instead of editing files directly or + copying them over. + Overriding asset bundles ------------------------ diff --git a/docs/guide/controller.md b/docs/guide/controller.md index 074a316..eec7a89 100644 --- a/docs/guide/controller.md +++ b/docs/guide/controller.md @@ -81,13 +81,16 @@ Routes ------ Each controller action has a corresponding internal route. In our example above `actionIndex` has `site/index` route -and `actionTest` has `site/test` route. In this route `site` is referred to as controller ID while `test` is referred to -as action ID. +and `actionTest` has `site/test` route. In this route `site` is referred to as controller ID while `test` is action ID. By default you can access specific controller and action using the `http://example.com/?r=controller/action` URL. This -behavior is fully customizable. For details refer to [URL Management](url.md). +behavior is fully customizable. For more details please refer to [URL Management](url.md). -If controller is located inside a module its action internal route will be `module/controller/action`. +If a controller is located inside a module, the route of its actions will be in the format of `module/controller/action`. + +A controller can be located under a subdirectory of the controller directory of an application or module. The route +will be prefixed with the corresponding directory names. For example, you may have a `UserController` under `controllers/admin`. +The route of its `actionIndex` would be `admin/user/index`, and `admin/user` would be the controller ID. In case module, controller or action specified isn't found Yii will return "not found" page and HTTP status code 404. diff --git a/docs/guide/module-debug.md b/docs/guide/module-debug.md index 91da33a..916101c 100644 --- a/docs/guide/module-debug.md +++ b/docs/guide/module-debug.md @@ -110,7 +110,7 @@ class ViewsPanel extends Panel { parent::init(); Event::on(View::className(), View::EVENT_BEFORE_RENDER, function (ViewEvent $event) { - $this->_viewFiles[] = $event->viewFile; + $this->_viewFiles[] = $event->sender->getViewFile(); }); } diff --git a/docs/guide/theming.md b/docs/guide/theming.md index e627f7c..037e70c 100644 --- a/docs/guide/theming.md +++ b/docs/guide/theming.md @@ -1,7 +1,12 @@ Theming ======= -TBD +A theme is a directory of view and layout files. Each file of the theme overrides corresponding file of an application +when rendered. A single application may use multiple themes and each may provide totally different experience. At any +time only one theme can be active. + +> Note: Themes usually do not meant to be redistributed since views are too application specific. If you want to + redistribute customized look and feel consider CSS and JavaScript files in form of [asset bundles](assets.md) instead. Configuring current theme ------------------------- @@ -18,4 +23,27 @@ be in your application config file: ], ], ], -``` \ No newline at end of file +``` + +In the above `pathMap` defines where to look for view files while `baseUrl` defines base URL for resources referenced +from these files. For example, if `pathMap` is `['/web/views' => '/web/themes/basic']`, then the themed version +for a view file `/web/views/site/index.php` will be `/web/themes/basic/site/index.php`. + +Using multiple paths +-------------------- + +It is possible to map a single path to multiple paths. For example, + +```php +'pathMap' => [ + '/web/views' => [ + '/web/themes/christmas', + '/web/themes/basic', + ], +] +``` + +In this case, the view will be searched in `/web/themes/christmas/site/index.php` then if it's not found it will check +`/web/themes/basic/site/index.php`. If there's no view there as well application view will be used. + +This ability is especially useful if you want to temporary or conditionally override some views. diff --git a/docs/guide/upgrade-from-v1.md b/docs/guide/upgrade-from-v1.md index 92dc868..612eeab 100644 --- a/docs/guide/upgrade-from-v1.md +++ b/docs/guide/upgrade-from-v1.md @@ -329,9 +329,9 @@ public function behaviors() 'class' => 'yii\web\AccessControl', 'rules' => [ ['allow' => true, 'actions' => ['admin'], 'roles' => ['@']], - ), - ), - ); + ], + ], + ]; } ``` diff --git a/extensions/apidoc/composer.json b/extensions/apidoc/composer.json index 276ceb1..6c0c5ce 100644 --- a/extensions/apidoc/composer.json +++ b/extensions/apidoc/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-apidoc", "description": "API Documentation generator for the Yii framework 2.0", - "keywords": ["yii", "phpdoc", "apidoc", "api", "documentation"], + "keywords": ["yii2", "phpdoc", "apidoc", "api", "documentation"], "type": "yii2-extension", "license": "BSD-3-Clause", "support": { diff --git a/extensions/apidoc/templates/html/views/eventDetails.php b/extensions/apidoc/templates/html/views/eventDetails.php index 15a6751..46fc5bd 100644 --- a/extensions/apidoc/templates/html/views/eventDetails.php +++ b/extensions/apidoc/templates/html/views/eventDetails.php @@ -18,7 +18,7 @@ ArrayHelper::multisort($events, 'name'); <h2>Event Details</h2> <?php foreach($events as $event): ?> <div class="detailHeader h3" id="<?= $event->name.'-detail' ?>"> - <?php echo $event->name; ?> + <?= $event->name ?> <span class="detailHeaderTag small"> event <?php if(!empty($event->since)): ?> diff --git a/extensions/apidoc/templates/html/views/eventSummary.php b/extensions/apidoc/templates/html/views/eventSummary.php index 1b716b1..99a003e 100644 --- a/extensions/apidoc/templates/html/views/eventSummary.php +++ b/extensions/apidoc/templates/html/views/eventSummary.php @@ -36,11 +36,11 @@ ArrayHelper::multisort($events, 'name'); <td> <?= ApiMarkdown::process($event->shortDescription, $event->definedBy, true) ?> <?php if(!empty($event->since)): ?> - (available since version <?php echo $event->since; ?>) + (available since version <?= $event->since ?>) <?php endif; ?> </td> <td><?= $this->context->typeLink($event->definedBy) ?></td> </tr> <?php endforeach; ?> </table> -</div> \ No newline at end of file +</div> diff --git a/extensions/apidoc/templates/html/views/propertyDetails.php b/extensions/apidoc/templates/html/views/propertyDetails.php index d02cf62..6efe2f4 100644 --- a/extensions/apidoc/templates/html/views/propertyDetails.php +++ b/extensions/apidoc/templates/html/views/propertyDetails.php @@ -21,7 +21,7 @@ ArrayHelper::multisort($properties, 'name'); <?php foreach($properties as $property): ?> <div class="detailHeader h3" id="<?= $property->name.'-detail' ?>"> - <?php echo $property->name; ?> + <?= $property->name ?> <span class="detailHeaderTag small"> <?= $property->visibility ?> <?php if($property->getIsReadOnly()) echo ' <em>read-only</em> '; ?> @@ -33,7 +33,7 @@ ArrayHelper::multisort($properties, 'name'); </span> </div> - <div class="signature"><?php echo $this->context->renderPropertySignature($property); ?></div> + <div class="signature"><?= $this->context->renderPropertySignature($property) ?></div> <?= ApiMarkdown::process($property->description, $type) ?> diff --git a/extensions/authclient/composer.json b/extensions/authclient/composer.json index 60290cb..81c5aa1 100644 --- a/extensions/authclient/composer.json +++ b/extensions/authclient/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-authclient", "description": "External authentication via OAuth and OpenID for the Yii framework", - "keywords": ["yii", "OAuth", "OpenID", "auth"], + "keywords": ["yii2", "OAuth", "OpenID", "auth"], "type": "yii2-extension", "license": "BSD-3-Clause", "support": { diff --git a/extensions/bootstrap/composer.json b/extensions/bootstrap/composer.json index e2a99df..637a084 100644 --- a/extensions/bootstrap/composer.json +++ b/extensions/bootstrap/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-bootstrap", "description": "The Twitter Bootstrap extension for the Yii framework", - "keywords": ["yii", "bootstrap"], + "keywords": ["yii2", "bootstrap"], "type": "yii2-extension", "license": "BSD-3-Clause", "support": { diff --git a/extensions/codeception/composer.json b/extensions/codeception/composer.json index 0982d8d..fa99992 100644 --- a/extensions/codeception/composer.json +++ b/extensions/codeception/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-codeception", "description": "The Codeception integration for the Yii framework", - "keywords": ["yii", "codeception"], + "keywords": ["yii2", "codeception"], "type": "yii2-extension", "license": "BSD-3-Clause", "support": { diff --git a/extensions/composer/composer.json b/extensions/composer/composer.json index 38f5199..f311581 100644 --- a/extensions/composer/composer.json +++ b/extensions/composer/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-composer", "description": "The composer plugin for Yii extension installer", - "keywords": ["yii", "composer", "extension installer"], + "keywords": ["yii2", "composer", "extension installer"], "type": "composer-plugin", "license": "BSD-3-Clause", "support": { diff --git a/extensions/debug/composer.json b/extensions/debug/composer.json index 84dafd5..3d095b1 100644 --- a/extensions/debug/composer.json +++ b/extensions/debug/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-debug", "description": "The debugger extension for the Yii framework", - "keywords": ["yii", "debug", "debugger"], + "keywords": ["yii2", "debug", "debugger"], "type": "yii2-extension", "license": "BSD-3-Clause", "support": { diff --git a/extensions/debug/views/default/panels/config/detail.php b/extensions/debug/views/default/panels/config/detail.php index 88e96a1..b2cfde1 100644 --- a/extensions/debug/views/default/panels/config/detail.php +++ b/extensions/debug/views/default/panels/config/detail.php @@ -1,6 +1,4 @@ <?php -use yii\helpers\Html; - /** * @var yii\debug\panels\ConfigPanel $panel */ diff --git a/extensions/debug/views/default/panels/config/summary.php b/extensions/debug/views/default/panels/config/summary.php index af72260..bb3a6dd 100644 --- a/extensions/debug/views/default/panels/config/summary.php +++ b/extensions/debug/views/default/panels/config/summary.php @@ -1,7 +1,4 @@ <?php - -use yii\helpers\Html; - /** * @var yii\debug\panels\ConfigPanel $panel */ diff --git a/extensions/debug/views/default/panels/db/summary.php b/extensions/debug/views/default/panels/db/summary.php index dcf49d8..022f9a7 100644 --- a/extensions/debug/views/default/panels/db/summary.php +++ b/extensions/debug/views/default/panels/db/summary.php @@ -1,6 +1,6 @@ <?php if ($queryCount): ?> <div class="yii-debug-toolbar-block"> - <a href="<?= $panel->getUrl() ?>" title="Executed <?php echo $queryCount; ?> database queries which took <?= $queryTime ?>."> + <a href="<?= $panel->getUrl() ?>" title="Executed <?= $queryCount ?> database queries which took <?= $queryTime ?>."> DB <span class="label label-info"><?= $queryCount ?></span> <span class="label"><?= $queryTime ?></span> </a> </div> diff --git a/extensions/elasticsearch/composer.json b/extensions/elasticsearch/composer.json index 097b102..d38454f 100644 --- a/extensions/elasticsearch/composer.json +++ b/extensions/elasticsearch/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-elasticsearch", "description": "Elasticsearch integration and ActiveRecord for the Yii framework", - "keywords": ["yii", "elasticsearch", "active-record", "search", "fulltext"], + "keywords": ["yii2", "elasticsearch", "active-record", "search", "fulltext"], "type": "yii2-extension", "license": "BSD-3-Clause", "support": { diff --git a/extensions/faker/composer.json b/extensions/faker/composer.json index 5af5319..a8a5bc1 100644 --- a/extensions/faker/composer.json +++ b/extensions/faker/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-faker", "description": "Fixture generator. The Faker integration for the Yii framework.", - "keywords": ["yii", "faker", "fixture"], + "keywords": ["yii2", "faker", "fixture"], "type": "yii2-extension", "license": "BSD-3-Clause", "support": { diff --git a/extensions/gii/CHANGELOG.md b/extensions/gii/CHANGELOG.md index 8a7632d..c67f8f4 100644 --- a/extensions/gii/CHANGELOG.md +++ b/extensions/gii/CHANGELOG.md @@ -13,6 +13,8 @@ Yii Framework 2 gii extension Change Log - Enh #1897: diff markup is now copy paste friendly (samdark) - Enh #2327: better visual representation of changed files, added header and refresh button to diff modal (thiagotalma) - Enh #2491: Added support for using the same base class name of search model and data model in Gii (qiangxue) +- Enh #2595: Browse through all generated files using right and left arrows (thiagotalma) +- Enh #2633: Keyboard shortcuts to browse through files (thiagotalma) 2.0.0 alpha, December 1, 2013 ----------------------------- diff --git a/extensions/gii/assets/gii.js b/extensions/gii/assets/gii.js index c5a70ab..282ce58 100644 --- a/extensions/gii/assets/gii.js +++ b/extensions/gii/assets/gii.js @@ -35,10 +35,13 @@ yii.gii = (function ($) { }; var initPreviewDiffLinks = function () { - $('.preview-code, .diff-code, .modal-refresh').on('click', function () { + $('.preview-code, .diff-code, .modal-refresh, .modal-previous, .modal-next').on('click', function () { var $modal = $('#preview-modal'); var $link = $(this); - $modal.find('.modal-refresh').attr('href', $link.prop('href')); + $modal.find('.modal-refresh').attr('href', $link.attr('href')); + if ($link.hasClass('preview-code') || $link.hasClass('diff-code')) { + $modal.data('action', ($link.hasClass('preview-code') ? 'preview-code' : 'diff-code')) + } $modal.find('.modal-title').text($link.data('title')); $modal.find('.modal-body').html('Loading ...'); $modal.modal('show'); @@ -48,6 +51,15 @@ yii.gii = (function ($) { url: $link.prop('href'), data: $('.default-view form').serializeArray(), success: function (data) { + if (!$link.hasClass('modal-refresh')) { + var filesSelector = 'a.' + $modal.data('action'); + var $files = $(filesSelector); + var index = $files.filter('[href="' + $link.attr('href') + '"]').index(filesSelector); + var $prev = $files.eq(index-1); + var $next = $files.eq((index+1 == $files.length ? 0 : index+1)); + $modal.find('.modal-previous').attr('href', $prev.attr('href')).data('title', $prev.data('title')); + $modal.find('.modal-next').attr('href', $next.attr('href')).data('title', $next.data('title')); + } $modal.find('.modal-body').html(data); $modal.find('.content').css('max-height', ($(window).height() - 200) + 'px'); }, @@ -57,6 +69,16 @@ yii.gii = (function ($) { }); return false; }); + + $('#preview-modal').on('keydown', function(e) { + if (e.keyCode === 37) { + $('.modal-previous').trigger('click'); + } else if(e.keyCode === 39) { + $('.modal-next').trigger('click'); + } else if(e.keyCode === 82) { + $('.modal-refresh').trigger('click'); + } + }); }; var initConfirmationCheckboxes = function () { diff --git a/extensions/gii/composer.json b/extensions/gii/composer.json index dad7f87..11fa779 100644 --- a/extensions/gii/composer.json +++ b/extensions/gii/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-gii", "description": "The Gii extension for the Yii framework", - "keywords": ["yii", "gii", "code generator"], + "keywords": ["yii2", "gii", "code generator"], "type": "yii2-extension", "license": "BSD-3-Clause", "support": { diff --git a/extensions/gii/generators/controller/templates/view.php b/extensions/gii/generators/controller/templates/view.php index 6ef2a87..a458b16 100644 --- a/extensions/gii/generators/controller/templates/view.php +++ b/extensions/gii/generators/controller/templates/view.php @@ -18,5 +18,5 @@ echo "<?php\n"; <p> You may change the content of this page by modifying - the file <code><?= '<?php' ?> echo __FILE__; ?></code>. + the file <code><?= '<?=' ?> __FILE__; ?></code>. </p> diff --git a/extensions/gii/generators/crud/templates/views/create.php b/extensions/gii/generators/crud/templates/views/create.php index 68d08ba..72a1f8d 100644 --- a/extensions/gii/generators/crud/templates/views/create.php +++ b/extensions/gii/generators/crud/templates/views/create.php @@ -26,8 +26,8 @@ $this->params['breadcrumbs'][] = $this->title; <h1><?= "<?= " ?>Html::encode($this->title) ?></h1> - <?= "<?php " ?>echo $this->render('_form', [ + <?= "<?= " ?>$this->render('_form', [ 'model' => $model, - ]); ?> + ]) ?> </div> diff --git a/extensions/gii/generators/crud/templates/views/index.php b/extensions/gii/generators/crud/templates/views/index.php index a4f5f0d..aadc586 100644 --- a/extensions/gii/generators/crud/templates/views/index.php +++ b/extensions/gii/generators/crud/templates/views/index.php @@ -37,7 +37,7 @@ $this->params['breadcrumbs'][] = $this->title; </p> <?php if ($generator->indexWidgetType === 'grid'): ?> - <?= "<?php " ?>echo GridView::widget([ + <?= "<?= " ?>GridView::widget([ 'dataProvider' => $dataProvider, 'filterModel' => $searchModel, 'columns' => [ @@ -69,13 +69,13 @@ if (($tableSchema = $generator->getTableSchema()) === false) { ], ]); ?> <?php else: ?> - <?= "<?php " ?>echo ListView::widget([ + <?= "<?= " ?>ListView::widget([ 'dataProvider' => $dataProvider, 'itemOptions' => ['class' => 'item'], 'itemView' => function ($model, $key, $index, $widget) { return Html::a(Html::encode($model-><?= $nameAttribute ?>), ['view', <?= $urlParams ?>]); }, - ]); ?> + ]) ?> <?php endif; ?> </div> diff --git a/extensions/gii/generators/crud/templates/views/update.php b/extensions/gii/generators/crud/templates/views/update.php index 2fbbecf..610b5bb 100644 --- a/extensions/gii/generators/crud/templates/views/update.php +++ b/extensions/gii/generators/crud/templates/views/update.php @@ -29,8 +29,8 @@ $this->params['breadcrumbs'][] = 'Update'; <h1><?= "<?= " ?>Html::encode($this->title) ?></h1> - <?= "<?php " ?>echo $this->render('_form', [ + <?= "<?= " ?>$this->render('_form', [ 'model' => $model, - ]); ?> + ]) ?> </div> diff --git a/extensions/gii/generators/crud/templates/views/view.php b/extensions/gii/generators/crud/templates/views/view.php index 989dab5..8ffa728 100644 --- a/extensions/gii/generators/crud/templates/views/view.php +++ b/extensions/gii/generators/crud/templates/views/view.php @@ -31,16 +31,16 @@ $this->params['breadcrumbs'][] = $this->title; <p> <?= "<?= " ?>Html::a('Update', ['update', <?= $urlParams ?>], ['class' => 'btn btn-primary']) ?> - <?= "<?php " ?>echo Html::a('Delete', ['delete', <?= $urlParams ?>], [ + <?= "<?= " ?>Html::a('Delete', ['delete', <?= $urlParams ?>], [ 'class' => 'btn btn-danger', 'data' => [ 'confirm' => Yii::t('app', 'Are you sure to delete this item?'), 'method' => 'post', ], - ]); ?> + ]) ?> </p> - <?= "<?php " ?>echo DetailView::widget([ + <?= "<?= " ?>DetailView::widget([ 'model' => $model, 'attributes' => [ <?php @@ -56,6 +56,6 @@ if (($tableSchema = $generator->getTableSchema()) === false) { } ?> ], - ]); ?> + ]) ?> </div> diff --git a/extensions/gii/generators/model/Generator.php b/extensions/gii/generators/model/Generator.php index 538637c..893cd7f 100644 --- a/extensions/gii/generators/model/Generator.php +++ b/extensions/gii/generators/model/Generator.php @@ -471,7 +471,7 @@ class Generator extends \yii\gii\Generator */ public function validateTableName() { - if (($pos = strpos($this->tableName, '*')) !== false && substr($this->tableName, -1) !== '*') { + if (strpos($this->tableName, '*') !== false && substr($this->tableName, -1) !== '*') { $this->addError('tableName', 'Asterisk is only allowed as the last character.'); return; } diff --git a/extensions/gii/views/default/view/files.php b/extensions/gii/views/default/view/files.php index 947c8f8..fbe5e69 100644 --- a/extensions/gii/views/default/view/files.php +++ b/extensions/gii/views/default/view/files.php @@ -81,7 +81,14 @@ use yii\gii\CodeFile; <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> - <h4><a class="modal-refresh glyphicon glyphicon-refresh" href="#"></a> <span class="modal-title">Modal title</span></h4> + <div class="btn-group pull-left"> + <a class="modal-previous btn btn-xs btn-default" href="#" title="Previous File (Left Arrow)"><span class="glyphicon glyphicon-arrow-left"></span></a> + <a class="modal-next btn btn-xs btn-default" href="#" title="Next File (Right Arrow)"><span class="glyphicon glyphicon-arrow-right"></span></a> + <a class="modal-refresh btn btn-xs btn-default" href="#" title="Refresh File (R)"><span class="glyphicon glyphicon-refresh"></span></a> + + </div> + <strong class="modal-title pull-left">Modal title</strong> + <div class="clearfix"></div> </div> <div class="modal-body"> <p>Please wait ...</p> diff --git a/extensions/imagine/composer.json b/extensions/imagine/composer.json index e032ff9..84f227c 100644 --- a/extensions/imagine/composer.json +++ b/extensions/imagine/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-imagine", "description": "The Imagine integration for the Yii framework", - "keywords": ["yii", "imagine", "image", "helper"], + "keywords": ["yii2", "imagine", "image", "helper"], "type": "yii2-extension", "license": "BSD-3-Clause", "support": { diff --git a/extensions/jui/assets/jquery.ui.datepicker-i18n.js b/extensions/jui/assets/jquery.ui.datepicker-i18n.js old mode 100755 new mode 100644 diff --git a/extensions/jui/assets/jquery.ui.effect-all.js b/extensions/jui/assets/jquery.ui.effect-all.js old mode 100755 new mode 100644 diff --git a/extensions/jui/assets/theme/images/animated-overlay.gif b/extensions/jui/assets/theme/images/animated-overlay.gif old mode 100755 new mode 100644 Binary files a/extensions/jui/assets/theme/images/animated-overlay.gif and b/extensions/jui/assets/theme/images/animated-overlay.gif differ diff --git a/extensions/jui/assets/theme/images/ui-bg_flat_0_aaaaaa_40x100.png b/extensions/jui/assets/theme/images/ui-bg_flat_0_aaaaaa_40x100.png old mode 100755 new mode 100644 Binary files a/extensions/jui/assets/theme/images/ui-bg_flat_0_aaaaaa_40x100.png and b/extensions/jui/assets/theme/images/ui-bg_flat_0_aaaaaa_40x100.png differ diff --git a/extensions/jui/assets/theme/images/ui-bg_flat_75_ffffff_40x100.png b/extensions/jui/assets/theme/images/ui-bg_flat_75_ffffff_40x100.png old mode 100755 new mode 100644 Binary files a/extensions/jui/assets/theme/images/ui-bg_flat_75_ffffff_40x100.png and b/extensions/jui/assets/theme/images/ui-bg_flat_75_ffffff_40x100.png differ diff --git a/extensions/jui/assets/theme/images/ui-bg_glass_55_fbf9ee_1x400.png b/extensions/jui/assets/theme/images/ui-bg_glass_55_fbf9ee_1x400.png old mode 100755 new mode 100644 Binary files a/extensions/jui/assets/theme/images/ui-bg_glass_55_fbf9ee_1x400.png and b/extensions/jui/assets/theme/images/ui-bg_glass_55_fbf9ee_1x400.png differ diff --git a/extensions/jui/assets/theme/images/ui-bg_glass_65_ffffff_1x400.png b/extensions/jui/assets/theme/images/ui-bg_glass_65_ffffff_1x400.png old mode 100755 new mode 100644 Binary files a/extensions/jui/assets/theme/images/ui-bg_glass_65_ffffff_1x400.png and b/extensions/jui/assets/theme/images/ui-bg_glass_65_ffffff_1x400.png differ diff --git a/extensions/jui/assets/theme/images/ui-bg_glass_75_dadada_1x400.png b/extensions/jui/assets/theme/images/ui-bg_glass_75_dadada_1x400.png old mode 100755 new mode 100644 Binary files a/extensions/jui/assets/theme/images/ui-bg_glass_75_dadada_1x400.png and b/extensions/jui/assets/theme/images/ui-bg_glass_75_dadada_1x400.png differ diff --git a/extensions/jui/assets/theme/images/ui-bg_glass_75_e6e6e6_1x400.png b/extensions/jui/assets/theme/images/ui-bg_glass_75_e6e6e6_1x400.png old mode 100755 new mode 100644 Binary files a/extensions/jui/assets/theme/images/ui-bg_glass_75_e6e6e6_1x400.png and b/extensions/jui/assets/theme/images/ui-bg_glass_75_e6e6e6_1x400.png differ diff --git a/extensions/jui/assets/theme/images/ui-bg_glass_95_fef1ec_1x400.png b/extensions/jui/assets/theme/images/ui-bg_glass_95_fef1ec_1x400.png old mode 100755 new mode 100644 Binary files a/extensions/jui/assets/theme/images/ui-bg_glass_95_fef1ec_1x400.png and b/extensions/jui/assets/theme/images/ui-bg_glass_95_fef1ec_1x400.png differ diff --git a/extensions/jui/assets/theme/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/extensions/jui/assets/theme/images/ui-bg_highlight-soft_75_cccccc_1x100.png old mode 100755 new mode 100644 Binary files a/extensions/jui/assets/theme/images/ui-bg_highlight-soft_75_cccccc_1x100.png and b/extensions/jui/assets/theme/images/ui-bg_highlight-soft_75_cccccc_1x100.png differ diff --git a/extensions/jui/assets/theme/images/ui-icons_222222_256x240.png b/extensions/jui/assets/theme/images/ui-icons_222222_256x240.png old mode 100755 new mode 100644 Binary files a/extensions/jui/assets/theme/images/ui-icons_222222_256x240.png and b/extensions/jui/assets/theme/images/ui-icons_222222_256x240.png differ diff --git a/extensions/jui/assets/theme/images/ui-icons_2e83ff_256x240.png b/extensions/jui/assets/theme/images/ui-icons_2e83ff_256x240.png old mode 100755 new mode 100644 Binary files a/extensions/jui/assets/theme/images/ui-icons_2e83ff_256x240.png and b/extensions/jui/assets/theme/images/ui-icons_2e83ff_256x240.png differ diff --git a/extensions/jui/assets/theme/images/ui-icons_454545_256x240.png b/extensions/jui/assets/theme/images/ui-icons_454545_256x240.png old mode 100755 new mode 100644 Binary files a/extensions/jui/assets/theme/images/ui-icons_454545_256x240.png and b/extensions/jui/assets/theme/images/ui-icons_454545_256x240.png differ diff --git a/extensions/jui/assets/theme/images/ui-icons_888888_256x240.png b/extensions/jui/assets/theme/images/ui-icons_888888_256x240.png old mode 100755 new mode 100644 Binary files a/extensions/jui/assets/theme/images/ui-icons_888888_256x240.png and b/extensions/jui/assets/theme/images/ui-icons_888888_256x240.png differ diff --git a/extensions/jui/assets/theme/images/ui-icons_cd0a0a_256x240.png b/extensions/jui/assets/theme/images/ui-icons_cd0a0a_256x240.png old mode 100755 new mode 100644 Binary files a/extensions/jui/assets/theme/images/ui-icons_cd0a0a_256x240.png and b/extensions/jui/assets/theme/images/ui-icons_cd0a0a_256x240.png differ diff --git a/extensions/jui/assets/theme/jquery.ui.css b/extensions/jui/assets/theme/jquery.ui.css old mode 100755 new mode 100644 diff --git a/extensions/jui/composer.json b/extensions/jui/composer.json index 126df39..f129fef 100644 --- a/extensions/jui/composer.json +++ b/extensions/jui/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-jui", "description": "The Jquery UI extension for the Yii framework", - "keywords": ["yii", "Jquery UI", "renderer"], + "keywords": ["yii2", "Jquery UI", "renderer"], "type": "yii2-extension", "license": "BSD-3-Clause", "support": { diff --git a/extensions/mongodb/Collection.php b/extensions/mongodb/Collection.php index 38144bc..6f595f8 100644 --- a/extensions/mongodb/Collection.php +++ b/extensions/mongodb/Collection.php @@ -260,7 +260,7 @@ class Collection extends Object } /** - * Returns a a single document. + * Returns a single document. * @param array $condition query condition * @param array $fields fields to be selected * @return array|null the single document. Null is returned if the query results in nothing. @@ -272,6 +272,32 @@ class Collection extends Object } /** + * Updates a document and returns it. + * @param array $condition query condition + * @param array $update update criteria + * @param array $fields fields to be returned + * @param array $options list of options in format: optionName => optionValue. + * @return array|null the original document, or the modified document when $options['new'] is set. + * @throws Exception on failure. + * @see http://www.php.net/manual/en/mongocollection.findandmodify.php + */ + public function findAndModify($condition, $update, $fields = [], $options = []) + { + $condition = $this->buildCondition($condition); + $token = $this->composeLogToken('findAndModify', [$condition, $update, $fields, $options]); + Yii::info($token, __METHOD__); + try { + Yii::beginProfile($token, __METHOD__); + $result = $this->mongoCollection->findAndModify($condition, $update, $fields, $options); + Yii::endProfile($token, __METHOD__); + return $result; + } catch (\Exception $e) { + Yii::endProfile($token, __METHOD__); + throw new Exception($e->getMessage(), (int)$e->getCode(), $e); + } + } + + /** * Inserts new data into collection. * @param array|object $data data to be inserted. * @param array $options list of options in format: optionName => optionValue. diff --git a/extensions/mongodb/composer.json b/extensions/mongodb/composer.json index d69a1a1..6556bd0 100644 --- a/extensions/mongodb/composer.json +++ b/extensions/mongodb/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-mongodb", "description": "MongoDb extension for the Yii framework", - "keywords": ["yii", "mongo", "mongodb", "active-record"], + "keywords": ["yii2", "mongo", "mongodb", "active-record"], "type": "yii2-extension", "license": "BSD-3-Clause", "support": { diff --git a/extensions/redis/composer.json b/extensions/redis/composer.json index 3740013..7561028 100644 --- a/extensions/redis/composer.json +++ b/extensions/redis/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-redis", "description": "Redis Cache, Session and ActiveRecord for the Yii framework", - "keywords": ["yii", "redis", "active-record", "cache", "session"], + "keywords": ["yii2", "redis", "active-record", "cache", "session"], "type": "yii2-extension", "license": "BSD-3-Clause", "support": { diff --git a/extensions/smarty/composer.json b/extensions/smarty/composer.json index 16b48bf..7d32b6d 100644 --- a/extensions/smarty/composer.json +++ b/extensions/smarty/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-smarty", "description": "The Smarty integration for the Yii framework", - "keywords": ["yii", "smarty", "renderer"], + "keywords": ["yii2", "smarty", "renderer"], "type": "yii2-extension", "license": "BSD-3-Clause", "support": { diff --git a/extensions/sphinx/composer.json b/extensions/sphinx/composer.json index 9f31226..db3e928 100644 --- a/extensions/sphinx/composer.json +++ b/extensions/sphinx/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-sphinx", "description": "Sphinx full text search engine extension for the Yii framework", - "keywords": ["yii", "sphinx", "active-record", "search", "fulltext"], + "keywords": ["yii2", "sphinx", "active-record", "search", "fulltext"], "type": "yii2-extension", "license": "BSD-3-Clause", "support": { diff --git a/extensions/swiftmailer/Mailer.php b/extensions/swiftmailer/Mailer.php index 891f2b5..8a87ba2 100644 --- a/extensions/swiftmailer/Mailer.php +++ b/extensions/swiftmailer/Mailer.php @@ -19,7 +19,7 @@ use yii\mail\BaseMailer; * ~~~ * 'components' => [ * ... - * 'email' => [ + * 'mail' => [ * 'class' => 'yii\swiftmailer\Mailer', * 'transport' => [ * 'class' => 'Swift_SmtpTransport', diff --git a/extensions/swiftmailer/composer.json b/extensions/swiftmailer/composer.json index 4c9e831..f248942 100644 --- a/extensions/swiftmailer/composer.json +++ b/extensions/swiftmailer/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-swiftmailer", "description": "The SwiftMailer integration for the Yii framework", - "keywords": ["yii", "swift", "swiftmailer", "mail", "email", "mailer"], + "keywords": ["yii2", "swift", "swiftmailer", "mail", "email", "mailer"], "type": "yii2-extension", "license": "BSD-3-Clause", "support": { diff --git a/extensions/twig/composer.json b/extensions/twig/composer.json index 1638058..ee7b0f8 100644 --- a/extensions/twig/composer.json +++ b/extensions/twig/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-twig", "description": "The Twig integration for the Yii framework", - "keywords": ["yii", "twig", "renderer"], + "keywords": ["yii2", "twig", "renderer"], "type": "yii2-extension", "license": "BSD-3-Clause", "support": { diff --git a/framework/BaseYii.php b/framework/BaseYii.php index 9152afc..c70808e 100644 --- a/framework/BaseYii.php +++ b/framework/BaseYii.php @@ -356,7 +356,7 @@ class BaseYii $config = array_merge(static::$objectConfig[$class], $config); } - if (($n = func_num_args()) > 1) { + if (func_num_args() > 1) { /** @var \ReflectionClass $reflection */ if (isset($reflections[$class])) { $reflection = $reflections[$class]; diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index e705811..06eb826 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -49,6 +49,9 @@ Yii Framework 2 Change Log - Bug #2502: Unclear error message when `$_SERVER['DOCUMENT_ROOT']` is empty (samdark) - Bug #2519: MessageSource removed translation messages when event handler was bound to `missingTranslation`-event (cebe) - Bug #2527: Source language for `app` message category was always `en` no matter which application `sourceLanguage` was used (samdark) +- Bug #2559: Going back on browser history breaks GridView filtering with `Pjax` (tonydspaniard) +- Bug #2607: `yii message` tool wasn't updating `message` table (mitalcoi) +- Bug #2624: Html::textArea() should respect "name" option. (qiangxue) - Bug: Fixed `Call to a member function registerAssetFiles() on a non-object` in case of wrong `sourcePath` for an asset bundle (samdark) - Bug: Fixed incorrect event name for `yii\jui\Spinner` (samdark) - Bug: Json::encode() did not handle objects that implement JsonSerializable interface correctly (cebe) @@ -68,6 +71,7 @@ Yii Framework 2 Change Log - Enh #1293: Replaced Console::showProgress() with a better approach. See Console::startProgress() for details (cebe) - Enh #1406: DB Schema support for Oracle Database (p0larbeer, qiangxue) - Enh #1437: Added ListView::viewParams (qiangxue) +- Enh #1467: Added support for organizing controllers in subdirectories (qiangxue) - Enh #1469: ActiveRecord::find() now works with default conditions (default scope) applied by createQuery (cebe) - Enh #1476: Add yii\web\Session::handler property (nineinchnick) - Enh #1499: Added `ActionColumn::controller` property to support customizing the controller for handling GridView actions (qiangxue) diff --git a/framework/assets/pjax/LICENSE b/framework/assets/pjax/LICENSE deleted file mode 100644 index 42c0317..0000000 --- a/framework/assets/pjax/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) Chris Wanstrath - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -Software), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/framework/assets/pjax/jquery.pjax.js b/framework/assets/pjax/jquery.pjax.js deleted file mode 100644 index 1934d80..0000000 --- a/framework/assets/pjax/jquery.pjax.js +++ /dev/null @@ -1,839 +0,0 @@ -// jquery.pjax.js -// copyright chris wanstrath -// https://github.com/defunkt/jquery-pjax - -(function($){ - -// When called on a container with a selector, fetches the href with -// ajax into the container or with the data-pjax attribute on the link -// itself. -// -// Tries to make sure the back button and ctrl+click work the way -// you'd expect. -// -// Exported as $.fn.pjax -// -// Accepts a jQuery ajax options object that may include these -// pjax specific options: -// -// -// container - Where to stick the response body. Usually a String selector. -// $(container).html(xhr.responseBody) -// (default: current jquery context) -// push - Whether to pushState the URL. Defaults to true (of course). -// replace - Want to use replaceState instead? That's cool. -// -// For convenience the second parameter can be either the container or -// the options object. -// -// Returns the jQuery object - function fnPjax(selector, container, options) { - var context = this - return this.on('click.pjax', selector, function(event) { - var opts = $.extend({}, optionsFor(container, options)) - if (!opts.container) - opts.container = $(this).attr('data-pjax') || context - handleClick(event, opts) - }) - } - -// Public: pjax on click handler -// -// Exported as $.pjax.click. -// -// event - "click" jQuery.Event -// options - pjax options -// -// Examples -// -// $(document).on('click', 'a', $.pjax.click) -// // is the same as -// $(document).pjax('a') -// -// $(document).on('click', 'a', function(event) { -// var container = $(this).closest('[data-pjax-container]') -// $.pjax.click(event, container) -// }) -// -// Returns nothing. - function handleClick(event, container, options) { - options = optionsFor(container, options) - - var link = event.currentTarget - - if (link.tagName.toUpperCase() !== 'A') - throw "$.fn.pjax or $.pjax.click requires an anchor element" - - // Middle click, cmd click, and ctrl click should open - // links in a new tab as normal. - if ( event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey ) - return - - // Ignore cross origin links - if ( location.protocol !== link.protocol || location.hostname !== link.hostname ) - return - - // Ignore anchors on the same page - if (link.hash && link.href.replace(link.hash, '') === - location.href.replace(location.hash, '')) - return - - // Ignore empty anchor "foo.html#" - if (link.href === location.href + '#') - return - - var defaults = { - url: link.href, - container: $(link).attr('data-pjax'), - target: link - } - - var opts = $.extend({}, defaults, options) - var clickEvent = $.Event('pjax:click') - $(link).trigger(clickEvent, [opts]) - - if (!clickEvent.isDefaultPrevented()) { - pjax(opts) - event.preventDefault() - $(link).trigger('pjax:clicked', [opts]) - } - } - -// Public: pjax on form submit handler -// -// Exported as $.pjax.submit -// -// event - "click" jQuery.Event -// options - pjax options -// -// Examples -// -// $(document).on('submit', 'form', function(event) { -// var container = $(this).closest('[data-pjax-container]') -// $.pjax.submit(event, container) -// }) -// -// Returns nothing. - function handleSubmit(event, container, options) { - options = optionsFor(container, options) - - var form = event.currentTarget - - if (form.tagName.toUpperCase() !== 'FORM') - throw "$.pjax.submit requires a form element" - - var defaults = { - type: form.method.toUpperCase(), - url: form.action, - data: $(form).serializeArray(), - container: $(form).attr('data-pjax'), - target: form - } - - pjax($.extend({}, defaults, options)) - - event.preventDefault() - } - -// Loads a URL with ajax, puts the response body inside a container, -// then pushState()'s the loaded URL. -// -// Works just like $.ajax in that it accepts a jQuery ajax -// settings object (with keys like url, type, data, etc). -// -// Accepts these extra keys: -// -// container - Where to stick the response body. -// $(container).html(xhr.responseBody) -// push - Whether to pushState the URL. Defaults to true (of course). -// replace - Want to use replaceState instead? That's cool. -// -// Use it just like $.ajax: -// -// var xhr = $.pjax({ url: this.href, container: '#main' }) -// console.log( xhr.readyState ) -// -// Returns whatever $.ajax returns. - function pjax(options) { - options = $.extend(true, {}, $.ajaxSettings, pjax.defaults, options) - - if ($.isFunction(options.url)) { - options.url = options.url() - } - - var target = options.target - - var hash = parseURL(options.url).hash - - var context = options.context = findContainerFor(options.container) - - // We want the browser to maintain two separate internal caches: one - // for pjax'd partial page loads and one for normal page loads. - // Without adding this secret parameter, some browsers will often - // confuse the two. - if (!options.data) options.data = {} - options.data._pjax = context.selector - - function fire(type, args) { - var event = $.Event(type, { relatedTarget: target }) - context.trigger(event, args) - return !event.isDefaultPrevented() - } - - var timeoutTimer - - options.beforeSend = function(xhr, settings) { - // No timeout for non-GET requests - // Its not safe to request the resource again with a fallback method. - if (settings.type !== 'GET') { - settings.timeout = 0 - } - - xhr.setRequestHeader('X-PJAX', 'true') - xhr.setRequestHeader('X-PJAX-Container', context.selector) - - if (!fire('pjax:beforeSend', [xhr, settings])) - return false - - if (settings.timeout > 0) { - timeoutTimer = setTimeout(function() { - if (fire('pjax:timeout', [xhr, options])) - xhr.abort('timeout') - }, settings.timeout) - - // Clear timeout setting so jquerys internal timeout isn't invoked - settings.timeout = 0 - } - - options.requestUrl = parseURL(settings.url).href - } - - options.complete = function(xhr, textStatus) { - if (timeoutTimer) - clearTimeout(timeoutTimer) - - fire('pjax:complete', [xhr, textStatus, options]) - - fire('pjax:end', [xhr, options]) - } - - options.error = function(xhr, textStatus, errorThrown) { - var container = extractContainer("", xhr, options) - - var allowed = fire('pjax:error', [xhr, textStatus, errorThrown, options]) - if (options.type == 'GET' && textStatus !== 'abort' && allowed) { - locationReplace(container.url) - } - } - - options.success = function(data, status, xhr) { - // If $.pjax.defaults.version is a function, invoke it first. - // Otherwise it can be a static string. - var currentVersion = (typeof $.pjax.defaults.version === 'function') ? - $.pjax.defaults.version() : - $.pjax.defaults.version - - var latestVersion = xhr.getResponseHeader('X-PJAX-Version') - - var container = extractContainer(data, xhr, options) - - // If there is a layout version mismatch, hard load the new url - if (currentVersion && latestVersion && currentVersion !== latestVersion) { - locationReplace(container.url) - return - } - - // If the new response is missing a body, hard load the page - if (!container.contents) { - locationReplace(container.url) - return - } - - pjax.state = { - id: options.id || uniqueId(), - url: container.url, - title: container.title, - container: context.selector, - fragment: options.fragment, - timeout: options.timeout - } - - if (options.push || options.replace) { - window.history.replaceState(pjax.state, container.title, container.url) - } - - // Clear out any focused controls before inserting new page contents. - document.activeElement.blur() - - if (container.title) document.title = container.title - context.html(container.contents) - - // FF bug: Won't autofocus fields that are inserted via JS. - // This behavior is incorrect. So if theres no current focus, autofocus - // the last field. - // - // http://www.w3.org/html/wg/drafts/html/master/forms.html - var autofocusEl = context.find('input[autofocus], textarea[autofocus]').last()[0] - if (autofocusEl && document.activeElement !== autofocusEl) { - autofocusEl.focus(); - } - - executeScriptTags(container.scripts) - - // Scroll to top by default - if (typeof options.scrollTo === 'number') - $(window).scrollTop(options.scrollTo) - - // If the URL has a hash in it, make sure the browser - // knows to navigate to the hash. - if ( hash !== '' ) { - // Avoid using simple hash set here. Will add another history - // entry. Replace the url with replaceState and scroll to target - // by hand. - // - // window.location.hash = hash - var url = parseURL(container.url) - url.hash = hash - - pjax.state.url = url.href - window.history.replaceState(pjax.state, container.title, url.href) - - var target = $(url.hash) - if (target.length) $(window).scrollTop(target.offset().top) - } - - fire('pjax:success', [data, status, xhr, options]) - } - - - // Initialize pjax.state for the initial page load. Assume we're - // using the container and options of the link we're loading for the - // back button to the initial page. This ensures good back button - // behavior. - if (!pjax.state) { - pjax.state = { - id: uniqueId(), - url: window.location.href, - title: document.title, - container: context.selector, - fragment: options.fragment, - timeout: options.timeout - } - window.history.replaceState(pjax.state, document.title) - } - - // Cancel the current request if we're already pjaxing - var xhr = pjax.xhr - if ( xhr && xhr.readyState < 4) { - xhr.onreadystatechange = $.noop - xhr.abort() - } - - pjax.options = options - var xhr = pjax.xhr = $.ajax(options) - - if (xhr.readyState > 0) { - if (options.push && !options.replace) { - // Cache current container element before replacing it - cachePush(pjax.state.id, context.clone().contents()) - - window.history.pushState(null, "", stripPjaxParam(options.requestUrl)) - } - - fire('pjax:start', [xhr, options]) - fire('pjax:send', [xhr, options]) - } - - return pjax.xhr - } - -// Public: Reload current page with pjax. -// -// Returns whatever $.pjax returns. - function pjaxReload(container, options) { - var defaults = { - url: window.location.href, - push: false, - replace: true, - scrollTo: false - } - - return pjax($.extend(defaults, optionsFor(container, options))) - } - -// Internal: Hard replace current state with url. -// -// Work for around WebKit -// https://bugs.webkit.org/show_bug.cgi?id=93506 -// -// Returns nothing. - function locationReplace(url) { - window.history.replaceState(null, "", "#") - window.location.replace(url) - } - - - var initialPop = true - var initialURL = window.location.href - var initialState = window.history.state - -// Initialize $.pjax.state if possible -// Happens when reloading a page and coming forward from a different -// session history. - if (initialState && initialState.container) { - pjax.state = initialState - } - -// Non-webkit browsers don't fire an initial popstate event - if ('state' in window.history) { - initialPop = false - } - -// popstate handler takes care of the back and forward buttons -// -// You probably shouldn't use pjax on pages with other pushState -// stuff yet. - function onPjaxPopstate(event) { - var state = event.state - - if (state && state.container) { - // When coming forward from a separate history session, will get an - // initial pop with a state we are already at. Skip reloading the current - // page. - if (initialPop && initialURL == state.url) return - - // If popping back to the same state, just skip. - // Could be clicking back from hashchange rather than a pushState. - if (pjax.state.id === state.id) return - - var container = $(state.container) - if (container.length) { - var direction, contents = cacheMapping[state.id] - - if (pjax.state) { - // Since state ids always increase, we can deduce the history - // direction from the previous state. - direction = pjax.state.id < state.id ? 'forward' : 'back' - - // Cache current container before replacement and inform the - // cache which direction the history shifted. - cachePop(direction, pjax.state.id, container.clone().contents()) - } - - var popstateEvent = $.Event('pjax:popstate', { - state: state, - direction: direction - }) - container.trigger(popstateEvent) - - var options = { - id: state.id, - url: state.url, - container: container, - push: false, - fragment: state.fragment, - timeout: state.timeout, - scrollTo: false - } - - if (contents) { - container.trigger('pjax:start', [null, options]) - - if (state.title) document.title = state.title - container.html(contents) - pjax.state = state - - container.trigger('pjax:end', [null, options]) - } else { - pjax(options) - } - - // Force reflow/relayout before the browser tries to restore the - // scroll position. - container[0].offsetHeight - } else { - locationReplace(location.href) - } - } - initialPop = false - } - -// Fallback version of main pjax function for browsers that don't -// support pushState. -// -// Returns nothing since it retriggers a hard form submission. - function fallbackPjax(options) { - var url = $.isFunction(options.url) ? options.url() : options.url, - method = options.type ? options.type.toUpperCase() : 'GET' - - var form = $('<form>', { - method: method === 'GET' ? 'GET' : 'POST', - action: url, - style: 'display:none' - }) - - if (method !== 'GET' && method !== 'POST') { - form.append($('<input>', { - type: 'hidden', - name: '_method', - value: method.toLowerCase() - })) - } - - var data = options.data - if (typeof data === 'string') { - $.each(data.split('&'), function(index, value) { - var pair = value.split('=') - form.append($('<input>', {type: 'hidden', name: pair[0], value: pair[1]})) - }) - } else if (typeof data === 'object') { - for (key in data) - form.append($('<input>', {type: 'hidden', name: key, value: data[key]})) - } - - $(document.body).append(form) - form.submit() - } - -// Internal: Generate unique id for state object. -// -// Use a timestamp instead of a counter since ids should still be -// unique across page loads. -// -// Returns Number. - function uniqueId() { - return (new Date).getTime() - } - -// Internal: Strips _pjax param from url -// -// url - String -// -// Returns String. - function stripPjaxParam(url) { - return url - .replace(/\?_pjax=[^&]+&?/, '?') - .replace(/_pjax=[^&]+&?/, '') - .replace(/[\?&]$/, '') - } - -// Internal: Parse URL components and returns a Locationish object. -// -// url - String URL -// -// Returns HTMLAnchorElement that acts like Location. - function parseURL(url) { - var a = document.createElement('a') - a.href = url - return a - } - -// Internal: Build options Object for arguments. -// -// For convenience the first parameter can be either the container or -// the options object. -// -// Examples -// -// optionsFor('#container') -// // => {container: '#container'} -// -// optionsFor('#container', {push: true}) -// // => {container: '#container', push: true} -// -// optionsFor({container: '#container', push: true}) -// // => {container: '#container', push: true} -// -// Returns options Object. - function optionsFor(container, options) { - // Both container and options - if ( container && options ) - options.container = container - - // First argument is options Object - else if ( $.isPlainObject(container) ) - options = container - - // Only container - else - options = {container: container} - - // Find and validate container - if (options.container) - options.container = findContainerFor(options.container) - - return options - } - -// Internal: Find container element for a variety of inputs. -// -// Because we can't persist elements using the history API, we must be -// able to find a String selector that will consistently find the Element. -// -// container - A selector String, jQuery object, or DOM Element. -// -// Returns a jQuery object whose context is `document` and has a selector. - function findContainerFor(container) { - container = $(container) - - if ( !container.length ) { - throw "no pjax container for " + container.selector - } else if ( container.selector !== '' && container.context === document ) { - return container - } else if ( container.attr('id') ) { - return $('#' + container.attr('id')) - } else { - throw "cant get selector for pjax container!" - } - } - -// Internal: Filter and find all elements matching the selector. -// -// Where $.fn.find only matches descendants, findAll will test all the -// top level elements in the jQuery object as well. -// -// elems - jQuery object of Elements -// selector - String selector to match -// -// Returns a jQuery object. - function findAll(elems, selector) { - return elems.filter(selector).add(elems.find(selector)); - } - - function parseHTML(html) { - return $.parseHTML(html, document, true) - } - -// Internal: Extracts container and metadata from response. -// -// 1. Extracts X-PJAX-URL header if set -// 2. Extracts inline <title> tags -// 3. Builds response Element and extracts fragment if set -// -// data - String response data -// xhr - XHR response -// options - pjax options Object -// -// Returns an Object with url, title, and contents keys. - function extractContainer(data, xhr, options) { - var obj = {} - - // Prefer X-PJAX-URL header if it was set, otherwise fallback to - // using the original requested url. - obj.url = stripPjaxParam(xhr.getResponseHeader('X-PJAX-URL') || options.requestUrl) - - // Attempt to parse response html into elements - if (/<html/i.test(data)) { - var $head = $(parseHTML(data.match(/<head[^>]*>([\s\S.]*)<\/head>/i)[0])) - var $body = $(parseHTML(data.match(/<body[^>]*>([\s\S.]*)<\/body>/i)[0])) - } else { - var $head = $body = $(parseHTML(data)) - } - - // If response data is empty, return fast - if ($body.length === 0) - return obj - - // If there's a <title> tag in the header, use it as - // the page's title. - obj.title = findAll($head, 'title').last().text() - - if (options.fragment) { - // If they specified a fragment, look for it in the response - // and pull it out. - if (options.fragment === 'body') { - var $fragment = $body - } else { - var $fragment = findAll($body, options.fragment).first() - } - - if ($fragment.length) { - obj.contents = $fragment.contents() - - // If there's no title, look for data-title and title attributes - // on the fragment - if (!obj.title) - obj.title = $fragment.attr('title') || $fragment.data('title') - } - - } else if (!/<html/i.test(data)) { - obj.contents = $body - } - - // Clean up any <title> tags - if (obj.contents) { - // Remove any parent title elements - obj.contents = obj.contents.not(function() { return $(this).is('title') }) - - // Then scrub any titles from their descendants - obj.contents.find('title').remove() - - // Gather all script[src] elements - obj.scripts = findAll(obj.contents, 'script[src]').remove() - obj.contents = obj.contents.not(obj.scripts) - } - - // Trim any whitespace off the title - if (obj.title) obj.title = $.trim(obj.title) - - return obj - } - -// Load an execute scripts using standard script request. -// -// Avoids jQuery's traditional $.getScript which does a XHR request and -// globalEval. -// -// scripts - jQuery object of script Elements -// -// Returns nothing. - function executeScriptTags(scripts) { - if (!scripts) return - - var existingScripts = $('script[src]') - - scripts.each(function() { - var src = this.src - var matchedScripts = existingScripts.filter(function() { - return this.src === src - }) - if (matchedScripts.length) return - - var script = document.createElement('script') - script.type = $(this).attr('type') - script.src = $(this).attr('src') - document.head.appendChild(script) - }) - } - -// Internal: History DOM caching class. - var cacheMapping = {} - var cacheForwardStack = [] - var cacheBackStack = [] - -// Push previous state id and container contents into the history -// cache. Should be called in conjunction with `pushState` to save the -// previous container contents. -// -// id - State ID Number -// value - DOM Element to cache -// -// Returns nothing. - function cachePush(id, value) { - cacheMapping[id] = value - cacheBackStack.push(id) - - // Remove all entires in forward history stack after pushing - // a new page. - while (cacheForwardStack.length) - delete cacheMapping[cacheForwardStack.shift()] - - // Trim back history stack to max cache length. - while (cacheBackStack.length > pjax.defaults.maxCacheLength) - delete cacheMapping[cacheBackStack.shift()] - } - -// Shifts cache from directional history cache. Should be -// called on `popstate` with the previous state id and container -// contents. -// -// direction - "forward" or "back" String -// id - State ID Number -// value - DOM Element to cache -// -// Returns nothing. - function cachePop(direction, id, value) { - var pushStack, popStack - cacheMapping[id] = value - - if (direction === 'forward') { - pushStack = cacheBackStack - popStack = cacheForwardStack - } else { - pushStack = cacheForwardStack - popStack = cacheBackStack - } - - pushStack.push(id) - if (id = popStack.pop()) - delete cacheMapping[id] - } - -// Public: Find version identifier for the initial page load. -// -// Returns String version or undefined. - function findVersion() { - return $('meta').filter(function() { - var name = $(this).attr('http-equiv') - return name && name.toUpperCase() === 'X-PJAX-VERSION' - }).attr('content') - } - -// Install pjax functions on $.pjax to enable pushState behavior. -// -// Does nothing if already enabled. -// -// Examples -// -// $.pjax.enable() -// -// Returns nothing. - function enable() { - $.fn.pjax = fnPjax - $.pjax = pjax - $.pjax.enable = $.noop - $.pjax.disable = disable - $.pjax.click = handleClick - $.pjax.submit = handleSubmit - $.pjax.reload = pjaxReload - $.pjax.defaults = { - timeout: 650, - push: true, - replace: false, - type: 'GET', - dataType: 'html', - scrollTo: 0, - maxCacheLength: 20, - version: findVersion - } - $(window).on('popstate.pjax', onPjaxPopstate) - } - -// Disable pushState behavior. -// -// This is the case when a browser doesn't support pushState. It is -// sometimes useful to disable pushState for debugging on a modern -// browser. -// -// Examples -// -// $.pjax.disable() -// -// Returns nothing. - function disable() { - $.fn.pjax = function() { return this } - $.pjax = fallbackPjax - $.pjax.enable = enable - $.pjax.disable = $.noop - $.pjax.click = $.noop - $.pjax.submit = $.noop - $.pjax.reload = function() { window.location.reload() } - - $(window).off('popstate.pjax', onPjaxPopstate) - } - - -// Add the state property to jQuery's event object so we can use it in -// $(window).bind('popstate') - if ( $.inArray('state', $.event.props) < 0 ) - $.event.props.push('state') - -// Is pjax supported by this browser? - $.support.pjax = - window.history && window.history.pushState && window.history.replaceState && - // pushState isn't reliable on iOS until 5. - !navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]|WebApps\/.+CFNetwork)/) - - $.support.pjax ? enable() : disable() - -})(jQuery); diff --git a/framework/assets/yii.gridView.js b/framework/assets/yii.gridView.js index 496e3cd..ca2b99a 100644 --- a/framework/assets/yii.gridView.js +++ b/framework/assets/yii.gridView.js @@ -26,17 +26,18 @@ filterSelector: undefined }; + var gridData = {}; + var methods = { init: function (options) { return this.each(function () { var $e = $(this); var settings = $.extend({}, defaults, options || {}); - $e.data('yiiGridView', { - settings: settings - }); + gridData[$e.prop('id')] = {settings: settings}; var enterPressed = false; - $(settings.filterSelector).on('change.yiiGridView keydown.yiiGridView', function (event) { + $(document).off('change.yiiGridView keydown.yiiGridView', settings.filterSelector) + .on('change.yiiGridView keydown.yiiGridView', settings.filterSelector, function (event) { if (event.type === 'keydown') { if (event.keyCode !== 13) { return; // only react to enter key @@ -60,7 +61,7 @@ applyFilter: function () { var $grid = $(this); - var settings = $grid.data('yiiGridView').settings; + var settings = gridData[$grid.prop('id')].settings; var data = {}; $.each($(settings.filterSelector).serializeArray(), function () { data[this.name] = this.value; @@ -85,15 +86,16 @@ setSelectionColumn: function (options) { var $grid = $(this); - var data = $grid.data('yiiGridView'); - data.selectionColumn = options.name; + var id = $(this).prop('id'); + gridData[id].selectionColumn = options.name; if (!options.multiple) { return; } - $grid.on('click.yiiGridView', "input[name='" + options.checkAll + "']", function () { + var inputs = "#" + id + " input[name='" + options.checkAll + "']"; + $(document).off('click.yiiGridView', inputs).on('click.yiiGridView', inputs, function () { $grid.find("input[name='" + options.name + "']:enabled").prop('checked', this.checked); }); - $grid.on('click.yiiGridView', "input[name='" + options.name + "']:enabled", function () { + $(document).off('click.yiiGridView', inputs + ":enabled").on('click.yiiGridView', inputs + ":enabled", function () { var all = $grid.find("input[name='" + options.name + "']").length == $grid.find("input[name='" + options.name + "']:checked").length; $grid.find("input[name='" + options.checkAll + "']").prop('checked', all); }); @@ -101,7 +103,7 @@ getSelectedRows: function () { var $grid = $(this); - var data = $grid.data('yiiGridView'); + var data = gridData[$grid.prop('id')]; var keys = []; if (data.selectionColumn) { $grid.find("input[name='" + data.selectionColumn + "']:checked").each(function () { @@ -118,8 +120,9 @@ }); }, - data: function() { - return this.data('yiiGridView'); + data: function () { + var id = $(this).prop('id'); + return gridData[id]; } }; })(window.jQuery); diff --git a/framework/base/Formatter.php b/framework/base/Formatter.php index 78fdac8..80c08e1 100644 --- a/framework/base/Formatter.php +++ b/framework/base/Formatter.php @@ -442,17 +442,17 @@ class Formatter extends Component switch($position) { case 0: - return $verbose ? Yii::t('yii','{n, plural, =1{# byte} other{# bytes}}', $params) : Yii::t('yii', '{n} B', $params); + return $verbose ? Yii::t('yii', '{n, plural, =1{# byte} other{# bytes}}', $params) : Yii::t('yii', '{n} B', $params); case 1: - return $verbose ? Yii::t('yii','{n, plural, =1{# kilobyte} other{# kilobytes}}', $params) : Yii::t('yii','{n} KB', $params); + return $verbose ? Yii::t('yii', '{n, plural, =1{# kilobyte} other{# kilobytes}}', $params) : Yii::t('yii', '{n} KB', $params); case 2: - return $verbose ? Yii::t('yii','{n, plural, =1{# megabyte} other{# megabytes}}', $params) : Yii::t('yii','{n} MB', $params); + return $verbose ? Yii::t('yii', '{n, plural, =1{# megabyte} other{# megabytes}}', $params) : Yii::t('yii', '{n} MB', $params); case 3: - return $verbose ? Yii::t('yii','{n, plural, =1{# gigabyte} other{# gigabytes}}', $params) : Yii::t('yii','{n} GB', $params); + return $verbose ? Yii::t('yii', '{n, plural, =1{# gigabyte} other{# gigabytes}}', $params) : Yii::t('yii', '{n} GB', $params); case 4: - return $verbose ? Yii::t('yii','{n, plural, =1{# terabyte} other{# terabytes}}', $params) : Yii::t('yii','{n} TB', $params); + return $verbose ? Yii::t('yii', '{n, plural, =1{# terabyte} other{# terabytes}}', $params) : Yii::t('yii', '{n} TB', $params); default: - return $verbose ? Yii::t('yii','{n, plural, =1{# petabyte} other{# petabytes}}', $params) : Yii::t('yii','{n} PB', $params); + return $verbose ? Yii::t('yii', '{n, plural, =1{# petabyte} other{# petabytes}}', $params) : Yii::t('yii', '{n} PB', $params); } } } diff --git a/framework/base/Module.php b/framework/base/Module.php index 2f31e88..cba919d 100644 --- a/framework/base/Module.php +++ b/framework/base/Module.php @@ -596,12 +596,21 @@ class Module extends Component } /** - * Creates a controller instance based on the controller ID. + * Creates a controller instance based on the given route. * - * The controller is created within this module. The method first attempts to - * create the controller based on the [[controllerMap]] of the module. If not available, - * it will look for the controller class under the [[controllerPath]] and create an - * instance of it. + * The route should be relative to this module. The method implements the following algorithm + * to resolve the given route: + * + * 1. If the route is empty, use [[defaultRoute]]; + * 2. If the first segment of the route is a valid module ID as declared in [[modules]], + * call the module's `createController()` with the rest part of the route; + * 3. If the first segment of the route is found in [[controllerMap]], create a controller + * based on the corresponding configuration found in [[controllerMap]]; + * 4. The given route is in the format of `abc/def/xyz`. Try either `abc\DefController` + * or `abc\def\XyzController` class within the [[controllerNamespace|controller namespace]]. + * + * If any of the above steps resolves into a controller, it is returned together with the rest + * part of the route which will be treated as the action ID. Otherwise, false will be returned. * * @param string $route the route consisting of module, controller and action IDs. * @return array|boolean If the controller is created successfully, it will be returned together @@ -613,6 +622,13 @@ class Module extends Component if ($route === '') { $route = $this->defaultRoute; } + + // double slashes or leading/ending slashes may cause substr problem + $route = trim($route, '/'); + if (strpos($route, '//') !== false) { + return false; + } + if (strpos($route, '/') !== false) { list ($id, $route) = explode('/', $route, 2); } else { @@ -620,29 +636,73 @@ class Module extends Component $route = ''; } + // module and controller map take precedence $module = $this->getModule($id); if ($module !== null) { return $module->createController($route); } - if (isset($this->controllerMap[$id])) { $controller = Yii::createObject($this->controllerMap[$id], $id, $this); - } elseif (preg_match('/^[a-z0-9\\-_]+$/', $id) && strpos($id, '--') === false && trim($id, '-') === $id) { - $className = str_replace(' ', '', ucwords(str_replace('-', ' ', $id))) . 'Controller'; - $classFile = $this->controllerPath . DIRECTORY_SEPARATOR . $className . '.php'; - if (!is_file($classFile)) { - return false; - } - $className = ltrim($this->controllerNamespace . '\\' . $className, '\\'); - Yii::$classMap[$className] = $classFile; - if (is_subclass_of($className, 'yii\base\Controller')) { - $controller = new $className($id, $this); - } elseif (YII_DEBUG) { - throw new InvalidConfigException("Controller class must extend from \\yii\\base\\Controller."); - } + return [$controller, $route]; + } + + if (($pos = strrpos($route, '/')) !== false) { + $id .= '/' . substr($route, 0, $pos); + $route = substr($route, $pos + 1); + } + + $controller = $this->createControllerByID($id); + if ($controller === null && $route !== '') { + $controller = $this->createControllerByID($id . '/' . $route); + $route = ''; + } + + return $controller === null ? false : [$controller, $route]; + } + + /** + * Creates a controller based on the given controller ID. + * + * The controller ID is relative to this module. The controller class + * should be located under [[controllerPath]] and namespaced under [[controllerNamespace]]. + * + * Note that this method does not check [[modules]] or [[controllerMap]]. + * + * @param string $id the controller ID + * @return Controller the newly created controller instance, or null if the controller ID is invalid. + * @throws InvalidConfigException if the controller class and its file name do not match. + * This exception is only thrown when in debug mode. + */ + public function createControllerByID($id) + { + if (!preg_match('%^[a-z0-9\\-_/]+$%', $id)) { + return null; } - return isset($controller) ? [$controller, $route] : false; + $pos = strrpos($id, '/'); + if ($pos === false) { + $prefix = ''; + $className = $id; + } else { + $prefix = substr($id, 0, $pos + 1); + $className = substr($id, $pos + 1); + } + + $className = str_replace(' ', '', ucwords(str_replace('-', ' ', $className))) . 'Controller'; + $classFile = $this->controllerPath . '/' . $prefix . $className . '.php'; + $className = ltrim($this->controllerNamespace . '\\' . str_replace('/', '\\', $prefix) . $className, '\\'); + if (strpos($className, '-') !== false || !is_file($classFile)) { + return null; + } + + Yii::$classMap[$className] = $classFile; + if (is_subclass_of($className, 'yii\base\Controller')) { + return new $className($id, $this); + } elseif (YII_DEBUG) { + throw new InvalidConfigException("Controller class must extend from \\yii\\base\\Controller."); + } else { + return null; + } } /** diff --git a/framework/base/Request.php b/framework/base/Request.php index b76886e..eb9f805 100644 --- a/framework/base/Request.php +++ b/framework/base/Request.php @@ -6,6 +6,7 @@ */ namespace yii\base; + use Yii; /** diff --git a/framework/base/Theme.php b/framework/base/Theme.php index 01a6964..63382ad 100644 --- a/framework/base/Theme.php +++ b/framework/base/Theme.php @@ -13,7 +13,7 @@ use yii\helpers\FileHelper; /** * Theme represents an application theme. * - * When [[View]] renders a view file, it will check the [[Application::theme|active theme]] + * When [[View]] renders a view file, it will check the [[View::theme|active theme]] * to see if there is a themed version of the view file exists. If so, the themed version will be rendered instead. * * A theme is a directory consisting of view files which are meant to replace their non-themed counterparts. diff --git a/framework/caching/FileDependency.php b/framework/caching/FileDependency.php index 11afde3..200cdde 100644 --- a/framework/caching/FileDependency.php +++ b/framework/caching/FileDependency.php @@ -6,6 +6,7 @@ */ namespace yii\caching; + use yii\base\InvalidConfigException; /** diff --git a/framework/caching/GroupDependency.php b/framework/caching/GroupDependency.php index 1cf7869..bcac858 100644 --- a/framework/caching/GroupDependency.php +++ b/framework/caching/GroupDependency.php @@ -6,6 +6,7 @@ */ namespace yii\caching; + use yii\base\InvalidConfigException; /** diff --git a/framework/composer.json b/framework/composer.json index bd11fc7..5a34ab0 100644 --- a/framework/composer.json +++ b/framework/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2", "description": "Yii PHP Framework Version 2", - "keywords": ["yii", "framework"], + "keywords": ["yii2", "framework"], "homepage": "http://www.yiiframework.com/", "type": "library", "license": "BSD-3-Clause", @@ -54,6 +54,7 @@ "lib-pcre": "*", "yiisoft/yii2-composer": "*", "yiisoft/jquery": "~2.0 | ~1.10", + "yiisoft/jquery-pjax": "*", "ezyang/htmlpurifier": "4.6.*", "cebe/markdown": "0.9.*" }, diff --git a/framework/console/controllers/FixtureController.php b/framework/console/controllers/FixtureController.php index 858f08f..c72efd2 100644 --- a/framework/console/controllers/FixtureController.php +++ b/framework/console/controllers/FixtureController.php @@ -64,7 +64,7 @@ class FixtureController extends Controller public function globalOptions() { return array_merge(parent::globalOptions(), [ - 'namespace','globalFixtures' + 'namespace', 'globalFixtures' ]); } @@ -74,6 +74,7 @@ class FixtureController extends Controller * whitespace between names. Note that if you are loading fixtures to storage, for example: database or nosql, * storage will not be cleared, data will be appended to already existed. * @param array $fixtures + * @param array $except * @throws \yii\console\Exception */ public function actionLoad(array $fixtures, array $except = []) @@ -99,7 +100,7 @@ class FixtureController extends Controller } $filtered = array_diff($foundFixtures, $except); - $fixtures = $this->getFixturesConfig(array_merge($this->globalFixtures ,$filtered)); + $fixtures = $this->getFixturesConfig(array_merge($this->globalFixtures, $filtered)); if (!$fixtures) { throw new Exception('No fixtures were found in namespace: "' . $this->namespace . '"' . ''); @@ -317,5 +318,4 @@ class FixtureController extends Controller { return Yii::getAlias('@' . str_replace('\\', '/', $this->namespace)); } - } diff --git a/framework/console/controllers/MessageController.php b/framework/console/controllers/MessageController.php index 0345b69..cb34a38 100644 --- a/framework/console/controllers/MessageController.php +++ b/framework/console/controllers/MessageController.php @@ -134,11 +134,14 @@ class MessageController extends Controller throw new Exception('The "db" option must refer to a valid database application component.'); } $sourceMessageTable = isset($config['sourceMessageTable']) ? $config['sourceMessageTable'] : '{{%source_message}}'; + $messageTable = isset($config['messageTable']) ? $config['messageTable'] : '{{%message}}'; $this->saveMessagesToDb( $messages, $db, $sourceMessageTable, - $config['removeUnused'] + $messageTable, + $config['removeUnused'], + $config['languages'] ); } } @@ -149,9 +152,11 @@ class MessageController extends Controller * @param array $messages * @param \yii\db\Connection $db * @param string $sourceMessageTable + * @param string $messageTable * @param boolean $removeUnused + * @param array $languages */ - protected function saveMessagesToDb($messages, $db, $sourceMessageTable, $removeUnused) + protected function saveMessagesToDb($messages, $db, $sourceMessageTable, $messageTable, $removeUnused, $languages) { $q = new \yii\db\Query; $current = []; @@ -190,12 +195,17 @@ class MessageController extends Controller echo "Inserting new messages..."; $savedFlag = false; - foreach ($new as $category => $msgs) { + foreach ($new as $category => $msgs) { foreach ($msgs as $m) { $savedFlag = true; $db->createCommand() - ->insert($sourceMessageTable, ['category' => $category, 'message' => $m])->execute(); + ->insert($sourceMessageTable, ['category' => $category, 'message' => $m])->execute(); + $lastId = $db->getLastInsertID(); + foreach ($languages as $language) { + $db->createCommand() + ->insert($messageTable, ['id' => $lastId, 'language' => $language])->execute(); + } } } @@ -207,15 +217,20 @@ class MessageController extends Controller } else { if ($removeUnused) { $db->createCommand() - ->delete($sourceMessageTable, ['in', 'id', $obsolete])->execute(); - echo "deleted.\n"; + ->delete($sourceMessageTable, ['in', 'id', $obsolete])->execute(); + echo "deleted.\n"; } else { + $last_id = $db->getLastInsertID(); $db->createCommand() - ->update( + ->update( $sourceMessageTable, ['message' => new \yii\db\Expression("CONCAT('@@',message,'@@')")], ['in', 'id', $obsolete] )->execute(); + foreach ($languages as $language) { + $db->createCommand() + ->insert($messageTable, ['id' => $last_id, 'language' => $language])->execute(); + } echo "updated.\n"; } } @@ -268,7 +283,7 @@ class MessageController extends Controller { echo "Saving messages to $fileName..."; if (is_file($fileName)) { - if($format === 'po'){ + if ($format === 'po') { $translated = file_get_contents($fileName); preg_match_all('/(?<=msgid ").*(?="\n(#*)msgstr)/', $translated, $keys); preg_match_all('/(?<=msgstr ").*(?="\n\n)/', $translated, $values); @@ -285,7 +300,7 @@ class MessageController extends Controller $merged = []; $untranslated = []; foreach ($messages as $message) { - if($format === 'po'){ + if ($format === 'po') { $message = preg_replace('/\"/', '\"', $message); } if (array_key_exists($message, $translated) && strlen($translated[$message]) > 0) { @@ -317,9 +332,9 @@ class MessageController extends Controller if (false === $overwrite) { $fileName .= '.merged'; } - if ($format === 'po'){ + if ($format === 'po') { $output = ''; - foreach ($merged as $k => $v){ + foreach ($merged as $k => $v) { $k = preg_replace('/(\")|(\\\")/', "\\\"", $k); $v = preg_replace('/(\")|(\\\")/', "\\\"", $v); if (substr($v, 0, 2) === '@@' && substr($v, -2) === '@@') { @@ -338,7 +353,7 @@ class MessageController extends Controller if ($format === 'po') { $merged = ''; sort($messages); - foreach($messages as $message) { + foreach ($messages as $message) { $message = preg_replace('/(\")|(\\\")/', '\\\"', $message); $merged .= "msgid \"$message\"\n"; $merged .= "msgstr \"\"\n"; diff --git a/framework/db/ActiveQuery.php b/framework/db/ActiveQuery.php index ee92f22..23e7f1f 100644 --- a/framework/db/ActiveQuery.php +++ b/framework/db/ActiveQuery.php @@ -120,7 +120,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface $this->findWith($this->with, $models); } if (!$this->asArray) { - foreach($models as $model) { + foreach ($models as $model) { $model->afterFind(); } } diff --git a/framework/db/ActiveRecord.php b/framework/db/ActiveRecord.php index e7461c6..539508b 100644 --- a/framework/db/ActiveRecord.php +++ b/framework/db/ActiveRecord.php @@ -35,9 +35,6 @@ use yii\helpers\StringHelper; * * class Customer extends \yii\db\ActiveRecord * { - * /** - * * @return string the name of the table associated with this ActiveRecord class. - * * / * public static function tableName() * { * return 'tbl_customer'; diff --git a/framework/db/ActiveRecordInterface.php b/framework/db/ActiveRecordInterface.php index 47cdb75..737abbf 100644 --- a/framework/db/ActiveRecordInterface.php +++ b/framework/db/ActiveRecordInterface.php @@ -87,6 +87,13 @@ interface ActiveRecordInterface public function getOldPrimaryKey($asArray = false); /** + * Returns a value indicating whether the given set of attributes represents the primary key for this model + * @param array $keys the set of attributes to check + * @return boolean whether the given set of attributes represents the primary key for this model + */ + public static function isPrimaryKey($keys); + + /** * Creates an [[ActiveQueryInterface|ActiveQuery]] instance for query purpose. * * This method is usually ment to be used like this: diff --git a/framework/db/ActiveRelationTrait.php b/framework/db/ActiveRelationTrait.php index ab06c16..32f6953 100644 --- a/framework/db/ActiveRelationTrait.php +++ b/framework/db/ActiveRelationTrait.php @@ -288,7 +288,7 @@ trait ActiveRelationTrait foreach ($primaryModels as $i => $primaryModel) { if ($primaryModels[$i][$primaryName] instanceof ActiveRecordInterface) { $primaryModels[$i][$primaryName]->populateRelation($name, $primaryModel); - } elseif (!empty($primaryModels[$i][$primaryName])) { + } elseif (!empty($primaryModels[$i][$primaryName])) { $primaryModels[$i][$primaryName][$name] = $primaryModel; } } diff --git a/framework/db/BaseActiveRecord.php b/framework/db/BaseActiveRecord.php index 4436545..69bc1da 100644 --- a/framework/db/BaseActiveRecord.php +++ b/framework/db/BaseActiveRecord.php @@ -19,6 +19,8 @@ use yii\base\InvalidCallException; /** * ActiveRecord is the base class for classes representing relational data in terms of objects. * + * See [[yii\db\ActiveRecord]] for a concrete implementation. + * * @property array $dirtyAttributes The changed attribute values (name-value pairs). This property is * read-only. * @property boolean $isNewRecord Whether the record is new and should be inserted when calling [[save()]]. @@ -342,7 +344,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface */ public function hasOne($class, $link) { - /** @var ActiveRecord $class */ + /** @var ActiveRecordInterface $class */ return $class::createQuery([ 'modelClass' => $class, 'primaryModel' => $this, @@ -383,7 +385,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface */ public function hasMany($class, $link) { - /** @var ActiveRecord $class */ + /** @var ActiveRecordInterface $class */ return $class::createQuery([ 'modelClass' => $class, 'primaryModel' => $this, @@ -396,7 +398,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface * Populates the named relation with the related records. * Note that this method does not check if the relation exists or not. * @param string $name the relation name (case-sensitive) - * @param ActiveRecord|array|null $records the related records to be populated into the relation. + * @param ActiveRecordInterface|array|null $records the related records to be populated into the relation. */ public function populateRelation($name, $records) { @@ -936,7 +938,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface * Returns a value indicating whether the given active record is the same as the current one. * The comparison is made by comparing the table names and the primary key values of the two active records. * If one of the records [[isNewRecord|is new]] they are also considered not equal. - * @param ActiveRecord $record record to compare to + * @param ActiveRecordInterface $record record to compare to * @return boolean whether the two active records refer to the same row in the same database table. */ public function equals($record) @@ -1104,7 +1106,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface * Note that this method requires that the primary key value is not null. * * @param string $name the case sensitive name of the relationship - * @param ActiveRecord $model the model to be linked with the current one. + * @param ActiveRecordInterface $model the model to be linked with the current one. * @param array $extraColumns additional column values to be saved into the pivot table. * This parameter is only meaningful for a relationship involving a pivot table * (i.e., a relation set with [[ActiveRelationTrait::via()]] or `[[ActiveQuery::viaTable()]]`.) @@ -1139,8 +1141,8 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface $columns[$k] = $v; } if (is_array($relation->via)) { - /** @var $viaClass ActiveRecord */ - /** @var $record ActiveRecord */ + /** @var $viaClass ActiveRecordInterface */ + /** @var $record ActiveRecordInterface */ $record = new $viaClass(); foreach ($columns as $column => $value) { $record->$column = $value; @@ -1191,7 +1193,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface * Otherwise, the foreign key will be set null and the model will be saved without validation. * * @param string $name the case sensitive name of the relationship. - * @param ActiveRecord $model the model to be unlinked from the current one. + * @param ActiveRecordInterface $model the model to be unlinked from the current one. * @param boolean $delete whether to delete the model that contains the foreign key. * If false, the model's foreign key will be set null and saved. * If true, the model containing the foreign key will be deleted. @@ -1219,7 +1221,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface $columns[$b] = $model->$a; } if (is_array($relation->via)) { - /** @var $viaClass ActiveRecord */ + /** @var $viaClass ActiveRecordInterface */ if ($delete) { $viaClass::deleteAll($columns); } else { @@ -1231,6 +1233,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface } } else { /** @var $viaTable string */ + /** @var Command $command */ $command = static::getDb()->createCommand(); if ($delete) { $command->delete($viaTable, $columns)->execute(); @@ -1263,7 +1266,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface if (!$relation->multiple) { unset($this->_related[$name]); } elseif (isset($this->_related[$name])) { - /** @var ActiveRecord $b */ + /** @var ActiveRecordInterface $b */ foreach ($this->_related[$name] as $a => $b) { if ($model->getPrimaryKey() == $b->getPrimaryKey()) { unset($this->_related[$name][$a]); diff --git a/framework/db/BatchQueryResult.php b/framework/db/BatchQueryResult.php index 774d416..3a1ba11 100644 --- a/framework/db/BatchQueryResult.php +++ b/framework/db/BatchQueryResult.php @@ -108,6 +108,7 @@ class BatchQueryResult extends Object implements \Iterator { if ($this->_batch === null || !$this->each || $this->each && next($this->_batch) === false) { $this->_batch = $this->fetchData(); + reset($this->_batch); } if ($this->each) { diff --git a/framework/db/QueryBuilder.php b/framework/db/QueryBuilder.php index e6b6e01..124848b 100644 --- a/framework/db/QueryBuilder.php +++ b/framework/db/QueryBuilder.php @@ -599,7 +599,7 @@ class QueryBuilder extends \yii\base\Object if (strpos($column, '(') === false) { $column = $this->db->quoteColumnName($column); } - $columns[$i] = "$column AS " . $this->db->quoteColumnName($i);; + $columns[$i] = "$column AS " . $this->db->quoteColumnName($i); } elseif (strpos($column, '(') === false) { if (preg_match('/^(.*?)(?i:\s+as\s+|\s+)([\w\-_\.]+)$/', $column, $matches)) { $columns[$i] = $this->db->quoteColumnName($matches[1]) . ' AS ' . $this->db->quoteColumnName($matches[2]); diff --git a/framework/db/oci/Schema.php b/framework/db/oci/Schema.php index e29a77b..1edbf6b 100644 --- a/framework/db/oci/Schema.php +++ b/framework/db/oci/Schema.php @@ -242,7 +242,7 @@ EOD; } elseif (strpos($dbType, 'NUMBER') !== false || strpos($dbType, 'INTEGER') !== false) { if (strpos($dbType, '(') && preg_match('/\((.*)\)/', $dbType, $matches)) { $values = explode(',', $matches[1]); - if (isset($values[1]) and (((int)$values[1]) > 0)) { + if (isset($values[1]) && (((int)$values[1]) > 0)) { $column->type = 'double'; } else { $column->type = 'integer'; diff --git a/framework/grid/ActionColumn.php b/framework/grid/ActionColumn.php index ffcfe0a..7d42bec 100644 --- a/framework/grid/ActionColumn.php +++ b/framework/grid/ActionColumn.php @@ -88,6 +88,7 @@ class ActionColumn extends Column $this->buttons['view'] = function ($url, $model) { return Html::a('<span class="glyphicon glyphicon-eye-open"></span>', $url, [ 'title' => Yii::t('yii', 'View'), + 'data-pjax' => '0', ]); }; } @@ -95,6 +96,7 @@ class ActionColumn extends Column $this->buttons['update'] = function ($url, $model) { return Html::a('<span class="glyphicon glyphicon-pencil"></span>', $url, [ 'title' => Yii::t('yii', 'Update'), + 'data-pjax' => '0', ]); }; } @@ -104,6 +106,7 @@ class ActionColumn extends Column 'title' => Yii::t('yii', 'Delete'), 'data-confirm' => Yii::t('yii', 'Are you sure to delete this item?'), 'data-method' => 'post', + 'data-pjax' => '0', ]); }; } diff --git a/framework/grid/DataColumn.php b/framework/grid/DataColumn.php index a8ef9ad..7b0f493 100644 --- a/framework/grid/DataColumn.php +++ b/framework/grid/DataColumn.php @@ -152,7 +152,7 @@ class DataColumn extends Column return parent::getDataCellContent($model, $key, $index); } return $value; - } + } /** * @inheritdoc diff --git a/framework/helpers/BaseFileHelper.php b/framework/helpers/BaseFileHelper.php index c544a91..6da4712 100644 --- a/framework/helpers/BaseFileHelper.php +++ b/framework/helpers/BaseFileHelper.php @@ -147,6 +147,7 @@ class BaseFileHelper * @param string $src the source directory * @param string $dst the destination directory * @param array $options options for directory copy. Valid options are: + * @throws \yii\base\InvalidParamException if unable to open directory * * - dirMode: integer, the permission to be set for newly copied directories. Defaults to 0775. * - fileMode: integer, the permission to be set for newly copied files. Defaults to the current environment setting. @@ -280,14 +281,14 @@ class BaseFileHelper $options['basePath'] = realpath($dir); // this should also be done only once if (isset($options['except'])) { - foreach($options['except'] as $key=>$value) { + foreach ($options['except'] as $key => $value) { if (is_string($value)) { $options['except'][$key] = static::parseExcludePattern($value); } } } if (isset($options['only'])) { - foreach($options['only'] as $key=>$value) { + foreach ($options['only'] as $key => $value) { if (is_string($value)) { $options['only'][$key] = static::parseExcludePattern($value); } @@ -397,7 +398,7 @@ class BaseFileHelper if ($pattern === $baseName) { return true; } - } else if ($flags & self::PATTERN_ENDSWITH) { + } elseif ($flags & self::PATTERN_ENDSWITH) { /* "*literal" matching against "fooliteral" */ $n = StringHelper::byteLength($pattern); if (StringHelper::byteSubstr($pattern, 1, $n) === StringHelper::byteSubstr($baseName, -$n, $n)) { @@ -472,7 +473,7 @@ class BaseFileHelper */ private static function lastExcludeMatchingFromList($basePath, $path, $excludes) { - foreach(array_reverse($excludes) as $exclude) { + foreach (array_reverse($excludes) as $exclude) { if (is_string($exclude)) { $exclude = self::parseExcludePattern($exclude); } @@ -508,13 +509,14 @@ class BaseFileHelper if (!is_string($pattern)) { throw new InvalidParamException('Exclude/include pattern must be a string.'); } - $result = array( + $result = [ 'pattern' => $pattern, 'flags' => 0, 'firstWildcard' => false, - ); - if (!isset($pattern[0])) + ]; + if (!isset($pattern[0])) { return $result; + } if ($pattern[0] == '!') { $result['flags'] |= self::PATTERN_NEGATIVE; @@ -526,11 +528,13 @@ class BaseFileHelper $len--; $result['flags'] |= self::PATTERN_MUSTBEDIR; } - if (strpos($pattern, '/') === false) + if (strpos($pattern, '/') === false) { $result['flags'] |= self::PATTERN_NODIR; + } $result['firstWildcard'] = self::firstWildcardInPattern($pattern); - if ($pattern[0] == '*' && self::firstWildcardInPattern(StringHelper::byteSubstr($pattern, 1, StringHelper::byteLength($pattern))) === false) + if ($pattern[0] == '*' && self::firstWildcardInPattern(StringHelper::byteSubstr($pattern, 1, StringHelper::byteLength($pattern))) === false) { $result['flags'] |= self::PATTERN_ENDSWITH; + } $result['pattern'] = $pattern; return $result; } @@ -542,8 +546,8 @@ class BaseFileHelper */ private static function firstWildcardInPattern($pattern) { - $wildcards = array('*','?','[','\\'); - $wildcardSearch = function($r, $c) use ($pattern) { + $wildcards = ['*', '?', '[', '\\']; + $wildcardSearch = function ($r, $c) use ($pattern) { $p = strpos($pattern, $c); return $r===false ? $p : ($p===false ? $r : min($r, $p)); }; diff --git a/framework/helpers/BaseHtml.php b/framework/helpers/BaseHtml.php index 01151ec..f0fe5b4 100644 --- a/framework/helpers/BaseHtml.php +++ b/framework/helpers/BaseHtml.php @@ -120,7 +120,7 @@ class BaseHtml * For example when using `['class' => 'my-class', 'target' => '_blank', 'value' => null]` it will result in the * html attributes rendered like this: `class="my-class" target="_blank"`. * - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * * @return string the generated HTML tag * @see beginTag() @@ -138,7 +138,7 @@ class BaseHtml * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. * If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated start tag * @see endTag() * @see tag() @@ -167,7 +167,7 @@ class BaseHtml * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. * If a value is null, the corresponding attribute will not be rendered. * If the options does not contain "type", a "type" attribute with value "text/css" will be used. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated style tag */ public static function style($content, $options = []) @@ -182,7 +182,7 @@ class BaseHtml * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. * If a value is null, the corresponding attribute will not be rendered. * If the options does not contain "type", a "type" attribute with value "text/javascript" will be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated script tag */ public static function script($content, $options = []) @@ -196,7 +196,7 @@ class BaseHtml * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. * If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated link tag * @see url() */ @@ -215,7 +215,7 @@ class BaseHtml * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. * If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated script tag * @see url() */ @@ -235,7 +235,7 @@ class BaseHtml * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. * If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated form start tag. * @see endForm() */ @@ -304,7 +304,7 @@ class BaseHtml * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. * If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated hyperlink * @see url() */ @@ -326,7 +326,7 @@ class BaseHtml * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. * If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated mailto link */ public static function mailto($text, $email = null, $options = []) @@ -341,7 +341,7 @@ class BaseHtml * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. * If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated image tag */ public static function img($src, $options = []) @@ -363,7 +363,7 @@ class BaseHtml * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. * If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated label tag */ public static function label($content, $for = null, $options = []) @@ -380,7 +380,7 @@ class BaseHtml * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. * If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated button tag */ public static function button($content = 'Button', $options = []) @@ -396,7 +396,7 @@ class BaseHtml * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. * If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated submit button tag */ public static function submitButton($content = 'Submit', $options = []) @@ -413,7 +413,7 @@ class BaseHtml * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. * If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated reset button tag */ public static function resetButton($content = 'Reset', $options = []) @@ -430,7 +430,7 @@ class BaseHtml * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. * If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated input tag */ public static function input($type, $name = null, $value = null, $options = []) @@ -447,7 +447,7 @@ class BaseHtml * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. * If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated button tag */ public static function buttonInput($label = 'Button', $options = []) @@ -463,7 +463,7 @@ class BaseHtml * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. * If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated button tag */ public static function submitInput($label = 'Submit', $options = []) @@ -478,7 +478,7 @@ class BaseHtml * @param string $label the value attribute. If it is null, the value attribute will not be generated. * @param array $options the attributes of the button tag. The values will be HTML-encoded using [[encode()]]. * Attributes whose value is null will be ignored and not put in the tag returned. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated button tag */ public static function resetInput($label = 'Reset', $options = []) @@ -495,7 +495,7 @@ class BaseHtml * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. * If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated button tag */ public static function textInput($name, $value = null, $options = []) @@ -510,7 +510,7 @@ class BaseHtml * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. * If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated button tag */ public static function hiddenInput($name, $value = null, $options = []) @@ -525,7 +525,7 @@ class BaseHtml * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. * If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated button tag */ public static function passwordInput($name, $value = null, $options = []) @@ -543,7 +543,7 @@ class BaseHtml * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. * If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated button tag */ public static function fileInput($name, $value = null, $options = []) @@ -558,7 +558,7 @@ class BaseHtml * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. * If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated text area tag */ public static function textarea($name, $value = '', $options = []) @@ -586,7 +586,7 @@ class BaseHtml * * The rest of the options will be rendered as the attributes of the resulting radio button tag. The values will * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * * @return string the generated radio button tag */ @@ -636,7 +636,7 @@ class BaseHtml * * The rest of the options will be rendered as the attributes of the resulting checkbox tag. The values will * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * * @return string the generated checkbox tag */ @@ -697,7 +697,7 @@ class BaseHtml * * The rest of the options will be rendered as the attributes of the resulting tag. The values will * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * * @return string the generated drop-down list tag */ @@ -744,7 +744,7 @@ class BaseHtml * * The rest of the options will be rendered as the attributes of the resulting tag. The values will * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * * @return string the generated list box tag */ @@ -800,7 +800,7 @@ class BaseHtml * is the label for the checkbox; and $name, $value and $checked represent the name, * value and the checked status of the checkbox input, respectively. * - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * * @return string the generated checkbox list */ @@ -871,7 +871,7 @@ class BaseHtml * is the label for the radio button; and $name, $value and $checked represent the name, * value and the checked status of the radio button input, respectively. * - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * * @return string the generated radio button list */ @@ -930,7 +930,7 @@ class BaseHtml * where $index is the array key corresponding to `$item` in `$items`. The callback should return * the whole list item tag. * - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * * @return string the generated unordered list. An empty string is returned if `$items` is empty. */ @@ -974,7 +974,7 @@ class BaseHtml * where $index is the array key corresponding to `$item` in `$items`. The callback should return * the whole list item tag. * - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * * @return string the generated ordered list. An empty string is returned if `$items` is empty. */ @@ -999,7 +999,7 @@ class BaseHtml * If this is not set, [[Model::getAttributeLabel()]] will be called to get the label for display * (after encoding). * - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * * @return string the generated label tag */ @@ -1025,7 +1025,7 @@ class BaseHtml * * - tag: this specifies the tag name. If not set, "div" will be used. * - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * * @return string the generated label tag */ @@ -1048,7 +1048,7 @@ class BaseHtml * about attribute expression. * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated input tag */ public static function activeInput($type, $model, $attribute, $options = []) @@ -1070,7 +1070,7 @@ class BaseHtml * about attribute expression. * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated input tag */ public static function activeTextInput($model, $attribute, $options = []) @@ -1087,7 +1087,7 @@ class BaseHtml * about attribute expression. * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated input tag */ public static function activeHiddenInput($model, $attribute, $options = []) @@ -1104,7 +1104,7 @@ class BaseHtml * about attribute expression. * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated input tag */ public static function activePasswordInput($model, $attribute, $options = []) @@ -1121,7 +1121,7 @@ class BaseHtml * about attribute expression. * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated input tag */ public static function activeFileInput($model, $attribute, $options = []) @@ -1140,12 +1140,12 @@ class BaseHtml * about attribute expression. * @param array $options the tag options in terms of name-value pairs. These will be rendered as * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]]. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * @return string the generated textarea tag */ public static function activeTextarea($model, $attribute, $options = []) { - $name = static::getInputName($model, $attribute); + $name = isset($options['name']) ? $options['name'] : static::getInputName($model, $attribute); $value = static::getAttributeValue($model, $attribute); if (!array_key_exists('id', $options)) { $options['id'] = static::getInputId($model, $attribute); @@ -1173,7 +1173,7 @@ class BaseHtml * The rest of the options will be rendered as the attributes of the resulting tag. The values will * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered. * - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * * @return string the generated radio button tag */ @@ -1216,7 +1216,7 @@ class BaseHtml * * The rest of the options will be rendered as the attributes of the resulting tag. The values will * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * * @return string the generated checkbox tag */ @@ -1272,7 +1272,7 @@ class BaseHtml * * The rest of the options will be rendered as the attributes of the resulting tag. The values will * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * * @return string the generated drop-down list tag */ @@ -1324,7 +1324,7 @@ class BaseHtml * * The rest of the options will be rendered as the attributes of the resulting tag. The values will * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered. - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * * @return string the generated list box tag */ @@ -1369,7 +1369,7 @@ class BaseHtml * is the label for the checkbox; and $name, $value and $checked represent the name, * value and the checked status of the checkbox input. * - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * * @return string the generated checkbox list */ @@ -1413,7 +1413,7 @@ class BaseHtml * is the label for the radio button; and $name, $value and $checked represent the name, * value and the checked status of the radio button input. * - * See [[renderTagAttributes()]] for details on how these are beeing rendered. + * See [[renderTagAttributes()]] for details on how these are being rendered. * * @return string the generated radio button list */ @@ -1579,7 +1579,7 @@ class BaseHtml { if (isset($options['class'])) { $classes = ' ' . $options['class'] . ' '; - if (($pos = strpos($classes, ' ' . $class . ' ')) === false) { + if (strpos($classes, ' ' . $class . ' ') === false) { $options['class'] .= ' ' . $class; } } else { diff --git a/framework/helpers/BaseInflector.php b/framework/helpers/BaseInflector.php index f9f19a8..3865588 100644 --- a/framework/helpers/BaseInflector.php +++ b/framework/helpers/BaseInflector.php @@ -275,7 +275,18 @@ class BaseInflector 'Ā' => 'A', 'Č' => 'C', 'Ē' => 'E', 'Ģ' => 'G', 'Ī' => 'i', 'Ķ' => 'k', 'Ļ' => 'L', 'Ņ' => 'N', 'Š' => 'S', 'Ū' => 'u', 'Ž' => 'Z', 'ā' => 'a', 'č' => 'c', 'ē' => 'e', 'ģ' => 'g', 'ī' => 'i', 'ķ' => 'k', 'ļ' => 'l', 'ņ' => 'n', - 'š' => 's', 'ū' => 'u', 'ž' => 'z' + 'š' => 's', 'ū' => 'u', 'ž' => 'z', + //Vietnamese + 'Ấ' => 'A', 'Ầ' => 'A', 'Ẩ' => 'A', 'Ẫ' => 'A', 'Ậ' => 'A', + 'Ắ' => 'A', 'Ằ' => 'A', 'Ẳ' => 'A', 'Ẵ' => 'A', 'Ặ' => 'A', + 'Ố' => 'O', 'Ồ' => 'O', 'Ổ' => 'O', 'Ỗ' => 'O', 'Ộ' => 'O', + 'Ớ' => 'O', 'Ờ' => 'O', 'Ở' => 'O', 'Ỡ' => 'O', 'Ợ' => 'O', + 'Ế' => 'E', 'Ề' => 'E', 'Ể' => 'E', 'Ễ' => 'E', 'Ệ' => 'E', + 'ấ' => 'a', 'ầ' => 'a', 'ẩ' => 'a', 'ẫ' => 'a', 'ậ' => 'a', + 'ắ' => 'a', 'ằ' => 'a', 'ẳ' => 'a', 'ẵ' => 'a', 'ặ' => 'a', + 'ố' => 'o', 'ồ' => 'o', 'ổ' => 'o', 'ỗ' => 'o', 'ộ' => 'o', + 'ớ' => 'o', 'ờ' => 'o', 'ở' => 'o', 'ỡ' => 'o', 'ợ' => 'o', + 'ế' => 'e', 'ề' => 'e', 'ể' => 'e', 'ễ' => 'e', 'ệ' => 'e' ]; /** diff --git a/framework/helpers/BaseMarkdown.php b/framework/helpers/BaseMarkdown.php index a22e45e..c72e079 100644 --- a/framework/helpers/BaseMarkdown.php +++ b/framework/helpers/BaseMarkdown.php @@ -86,7 +86,7 @@ class BaseMarkdown /** @var \cebe\markdown\Markdown $parser */ if (!isset(static::$flavors[$flavor])) { throw new InvalidParamException("Markdown flavor '$flavor' is not defined.'"); - } elseif(!is_object($config = static::$flavors[$flavor])) { + } elseif (!is_object($config = static::$flavors[$flavor])) { $parser = Yii::createObject($config); if (is_array($config)) { foreach ($config as $name => $value) { diff --git a/framework/helpers/BaseSecurity.php b/framework/helpers/BaseSecurity.php index d9459d9..8750a54 100644 --- a/framework/helpers/BaseSecurity.php +++ b/framework/helpers/BaseSecurity.php @@ -107,10 +107,10 @@ class BaseSecurity */ protected static function stripPadding($data) { - $end = StringHelper::byteSubstr($data, -1, NULL); + $end = StringHelper::byteSubstr($data, -1, null); $last = ord($end); $n = StringHelper::byteLength($data) - $last; - if (StringHelper::byteSubstr($data, $n, NULL) == str_repeat($end, $last)) { + if (StringHelper::byteSubstr($data, $n, null) == str_repeat($end, $last)) { return StringHelper::byteSubstr($data, 0, $n); } return false; diff --git a/framework/i18n/GettextMessageSource.php b/framework/i18n/GettextMessageSource.php index 8da8edc..fc6d87f 100644 --- a/framework/i18n/GettextMessageSource.php +++ b/framework/i18n/GettextMessageSource.php @@ -70,9 +70,9 @@ class GettextMessageSource extends MessageSource if ($messages === null && $fallbackMessages === null && $fallbackLanguage != $this->sourceLanguage) { Yii::error("The message file for category '$category' does not exist: $messageFile Fallback file does not exist as well: $fallbackMessageFile", __METHOD__); - } else if (empty($messages)) { + } elseif (empty($messages)) { return $fallbackMessages; - } else if (!empty($fallbackMessages)) { + } elseif (!empty($fallbackMessages)) { foreach ($fallbackMessages as $key => $value) { if (!empty($value) && empty($messages[$key])) { $messages[$key] = $fallbackMessages[$key]; diff --git a/framework/i18n/I18N.php b/framework/i18n/I18N.php index d0bbfcc..6be3899 100644 --- a/framework/i18n/I18N.php +++ b/framework/i18n/I18N.php @@ -126,7 +126,7 @@ class I18N extends Component } $p = []; - foreach($params as $name => $value) { + foreach ($params as $name => $value) { $p['{' . $name . '}'] = $value; } return strtr($message, $p); diff --git a/framework/i18n/MessageFormatter.php b/framework/i18n/MessageFormatter.php index 4ea7083..c3d8c56 100644 --- a/framework/i18n/MessageFormatter.php +++ b/framework/i18n/MessageFormatter.php @@ -143,7 +143,7 @@ class MessageFormatter extends Component return false; } $map = []; - foreach($tokens as $i => $token) { + foreach ($tokens as $i => $token) { if (is_array($token)) { $param = trim($token[0]); if (!isset($map[$param])) { @@ -169,7 +169,7 @@ class MessageFormatter extends Component return false; } else { $values = []; - foreach($result as $key => $value) { + foreach ($result as $key => $value) { $values[$map[$key]] = $value; } return $values; @@ -190,7 +190,7 @@ class MessageFormatter extends Component if (($tokens = self::tokenizePattern($pattern)) === false) { return false; } - foreach($tokens as $i => $token) { + foreach ($tokens as $i => $token) { if (!is_array($token)) { continue; } @@ -210,7 +210,7 @@ class MessageFormatter extends Component } $type = isset($token[1]) ? trim($token[1]) : 'none'; // replace plural and select format recursively - if ($type == 'plural' || $type == 'select') { + if ($type == 'plural' || $type == 'select') { if (!isset($token[2])) { return false; } @@ -244,7 +244,7 @@ class MessageFormatter extends Component $this->_errorMessage = "Message pattern is invalid."; return false; } - foreach($tokens as $i => $token) { + foreach ($tokens as $i => $token) { if (is_array($token)) { if (($tokens[$i] = $this->parseToken($token, $args, $locale)) === false) { $this->_errorCode = -1; diff --git a/framework/i18n/PhpMessageSource.php b/framework/i18n/PhpMessageSource.php index 2e611f5..7866511 100644 --- a/framework/i18n/PhpMessageSource.php +++ b/framework/i18n/PhpMessageSource.php @@ -73,9 +73,9 @@ class PhpMessageSource extends MessageSource if ($messages === null && $fallbackMessages === null && $fallbackLanguage != $this->sourceLanguage) { Yii::error("The message file for category '$category' does not exist: $messageFile Fallback file does not exist as well: $fallbackMessageFile", __METHOD__); - } else if (empty($messages)) { + } elseif (empty($messages)) { return $fallbackMessages; - } else if (!empty($fallbackMessages)) { + } elseif (!empty($fallbackMessages)) { foreach ($fallbackMessages as $key => $value) { if (!empty($value) && empty($messages[$key])) { $messages[$key] = $fallbackMessages[$key]; diff --git a/framework/mail/BaseMailer.php b/framework/mail/BaseMailer.php index 139b4af..01f6635 100644 --- a/framework/mail/BaseMailer.php +++ b/framework/mail/BaseMailer.php @@ -348,5 +348,4 @@ abstract class BaseMailer extends Component implements MailerInterface, ViewCont $event = new MailEvent(['message' => $message, 'isSuccessful' => $isSuccessful]); $this->trigger(self::EVENT_AFTER_SEND, $event); } - } diff --git a/framework/messages/pt-PT/yii.php b/framework/messages/pt-PT/yii.php index 375b4d6..2d383c0 100644 --- a/framework/messages/pt-PT/yii.php +++ b/framework/messages/pt-PT/yii.php @@ -1,4 +1,4 @@ -<?php +<?php /** * Message translations. * diff --git a/framework/requirements/views/web/index.php b/framework/requirements/views/web/index.php index 287d4bb..a2aa59d 100644 --- a/framework/requirements/views/web/index.php +++ b/framework/requirements/views/web/index.php @@ -27,7 +27,7 @@ </p> <p> There are two kinds of requirements being checked. Mandatory requirements are those that have to be met - to allow Yii to work as expected. There are also some optional requirements beeing checked which will + to allow Yii to work as expected. There are also some optional requirements being checked which will show you a warning when they do not meet. You can use Yii framework without them but some specific functionality may be not available in this case. </p> diff --git a/framework/test/Fixture.php b/framework/test/Fixture.php index 5a38ae5..e22a139 100644 --- a/framework/test/Fixture.php +++ b/framework/test/Fixture.php @@ -82,4 +82,3 @@ class Fixture extends Component { } } - diff --git a/framework/validators/ImageValidator.php b/framework/validators/ImageValidator.php index 52fb235..fa9587d 100644 --- a/framework/validators/ImageValidator.php +++ b/framework/validators/ImageValidator.php @@ -124,7 +124,7 @@ class ImageValidator extends FileValidator } if ($this->underHeight === null) { $this->underHeight = Yii::t('yii', 'The image "{file}" is too small. The height cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.'); - } + } if ($this->overWidth === null) { $this->overWidth = Yii::t('yii', 'The image "{file}" is too large. The width cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.'); } diff --git a/framework/validators/PunycodeAsset.php b/framework/validators/PunycodeAsset.php index c0c1e2b..5f6a411 100644 --- a/framework/validators/PunycodeAsset.php +++ b/framework/validators/PunycodeAsset.php @@ -6,6 +6,7 @@ */ namespace yii\validators; + use yii\web\AssetBundle; /** diff --git a/framework/validators/ValidationAsset.php b/framework/validators/ValidationAsset.php index 14d7ad0..e9bb79d 100644 --- a/framework/validators/ValidationAsset.php +++ b/framework/validators/ValidationAsset.php @@ -6,6 +6,7 @@ */ namespace yii\validators; + use yii\web\AssetBundle; /** diff --git a/framework/web/AssetConverter.php b/framework/web/AssetConverter.php index 1b7d1c8..23062d9 100644 --- a/framework/web/AssetConverter.php +++ b/framework/web/AssetConverter.php @@ -82,7 +82,7 @@ class AssetConverter extends Component implements AssetConverterInterface $proc = proc_open($command, $descriptor, $pipes, $basePath); $stdout = stream_get_contents($pipes[1]); $stderr = stream_get_contents($pipes[2]); - foreach($pipes as $pipe) { + foreach ($pipes as $pipe) { fclose($pipe); } $status = proc_close($proc); diff --git a/framework/web/Request.php b/framework/web/Request.php index ed48401..0f9a211 100644 --- a/framework/web/Request.php +++ b/framework/web/Request.php @@ -828,7 +828,7 @@ class Request extends \yii\base\Request } /** - * @return string the password sent via HTTP authentication, null if the username is not given + * @return string the password sent via HTTP authentication, null if the password is not given */ public function getAuthPassword() { diff --git a/framework/web/User.php b/framework/web/User.php index 230f2c3..c32ae9c 100644 --- a/framework/web/User.php +++ b/framework/web/User.php @@ -175,6 +175,7 @@ class User extends Component public function setIdentity($identity) { $this->_identity = $identity; + $this->_access = []; } /** diff --git a/framework/widgets/ActiveFormAsset.php b/framework/widgets/ActiveFormAsset.php index 5acb5e1..94b00e5 100644 --- a/framework/widgets/ActiveFormAsset.php +++ b/framework/widgets/ActiveFormAsset.php @@ -6,6 +6,7 @@ */ namespace yii\widgets; + use yii\web\AssetBundle; /** diff --git a/framework/widgets/LinkPager.php b/framework/widgets/LinkPager.php index a2c905c..22cfdf0 100644 --- a/framework/widgets/LinkPager.php +++ b/framework/widgets/LinkPager.php @@ -128,7 +128,7 @@ class LinkPager extends Widget protected function registerLinkTags() { $view = $this->getView(); - foreach($this->pagination->getLinks() as $rel => $href) { + foreach ($this->pagination->getLinks() as $rel => $href) { $view->registerLinkTag(['rel' => $rel, 'href' => $href], $rel); } } diff --git a/framework/widgets/Pjax.php b/framework/widgets/Pjax.php index 1d7046c..5a60498 100644 --- a/framework/widgets/Pjax.php +++ b/framework/widgets/Pjax.php @@ -14,7 +14,7 @@ use yii\helpers\Json; use yii\web\Response; /** - * Pjax is a widget integrating the [pjax](https://github.com/defunkt/jquery-pjax) jQuery plugin. + * Pjax is a widget integrating the [pjax](https://github.com/yiisoft/jquery-pjax) jQuery plugin. * * Pjax only deals with the content enclosed between its [[begin()]] and [[end()]] calls, called the *body content* of the widget. * By default, any link click or form submission (for those forms with `data-pjax` attribute) within the body content @@ -25,7 +25,9 @@ use yii\web\Response; * You may configure [[linkSelector]] to specify which links should trigger pjax, and configure [[formSelector]] * to specify which form submission may trigger pjax. * - * The following example shows how to use Pjax with the [[\yii\gridview\GridView]] widget so that the grid pagination, + * You may disable pjax for a specific link inside the container by adding `data-pjax="0"` attribute to this link. + * + * The following example shows how to use Pjax with the [[\yii\grid\GridView]] widget so that the grid pagination, * sorting and filtering can be done via pjax: * * ```php @@ -78,7 +80,7 @@ class Pjax extends Widget public $scrollTo = false; /** * @var array additional options to be passed to the pjax JS plugin. Please refer to - * [pjax project page](https://github.com/defunkt/jquery-pjax) for available options. + * [pjax project page](https://github.com/yiisoft/jquery-pjax) for available options. */ public $clientOptions; diff --git a/framework/widgets/PjaxAsset.php b/framework/widgets/PjaxAsset.php index f3e4912..3fcaf67 100644 --- a/framework/widgets/PjaxAsset.php +++ b/framework/widgets/PjaxAsset.php @@ -17,9 +17,9 @@ use yii\web\AssetBundle; */ class PjaxAsset extends AssetBundle { - public $sourcePath = '@yii/assets'; + public $sourcePath = '@vendor/yiisoft/jquery-pjax'; public $js = [ - 'pjax/jquery.pjax.js', + 'jquery.pjax.js', ]; public $depends = [ 'yii\web\YiiAsset', diff --git a/tests/unit/data/travis/cubrid-setup.sh b/tests/unit/data/travis/cubrid-setup.sh index 9c3bb74..4188e17 100755 --- a/tests/unit/data/travis/cubrid-setup.sh +++ b/tests/unit/data/travis/cubrid-setup.sh @@ -2,6 +2,11 @@ # # install CUBRID DBMS +if (php --version | grep -i HHVM > /dev/null); then + echo "Skipping CUBRID on HHVM" + exit 0 +fi + # cubrid dbms echo 'yes' | sudo add-apt-repository ppa:cubrid/cubrid sudo apt-get update diff --git a/tests/unit/data/travis/memcache-setup.sh b/tests/unit/data/travis/memcache-setup.sh index 6b623d6..adb743b 100755 --- a/tests/unit/data/travis/memcache-setup.sh +++ b/tests/unit/data/travis/memcache-setup.sh @@ -1,4 +1,8 @@ #!/bin/sh -echo "extension=memcache.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini -echo "extension=memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini +if (php --version | grep -i HHVM > /dev/null); then + echo "skipping memcache on HHVM" +else + echo "extension=memcache.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini + echo "extension=memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini +fi diff --git a/tests/unit/extensions/mongodb/CollectionTest.php b/tests/unit/extensions/mongodb/CollectionTest.php index 3eb97b6..9a0c0b4 100644 --- a/tests/unit/extensions/mongodb/CollectionTest.php +++ b/tests/unit/extensions/mongodb/CollectionTest.php @@ -187,6 +187,60 @@ class CollectionTest extends MongoDbTestCase $this->assertNotEmpty($result[0]['items']); } + public function testFindAndModify() + { + $collection = $this->getConnection()->getCollection('customer'); + $rows = [ + [ + 'name' => 'customer 1', + 'status' => 1, + 'amount' => 100, + ], + [ + 'name' => 'customer 2', + 'status' => 1, + 'amount' => 200, + ], + ]; + $collection->batchInsert($rows); + + // increment field + $result = $collection->findAndModify(['name' => 'customer 1'], ['$inc' => ['status' => 1]]); + $this->assertEquals('customer 1', $result['name']); + $this->assertEquals(1, $result['status']); + $newResult = $collection->findOne(['name' => 'customer 1']); + $this->assertEquals(2, $newResult['status']); + + // $set and return modified document + $result = $collection->findAndModify( + ['name' => 'customer 2'], + ['$set' => ['status' => 2]], + [], + ['new' => true] + ); + $this->assertEquals('customer 2', $result['name']); + $this->assertEquals(2, $result['status']); + + // Full update document + $data = [ + 'name' => 'customer 3', + 'city' => 'Minsk' + ]; + $result = $collection->findAndModify( + ['name' => 'customer 2'], + $data, + [], + ['new' => true] + ); + $this->assertEquals('customer 3', $result['name']); + $this->assertEquals('Minsk', $result['city']); + $this->assertTrue(!isset($result['status'])); + + // Test exceptions + $this->setExpectedException('\yii\mongodb\Exception'); + $collection->findAndModify(['name' => 'customer 1'], ['$wrongOperator' => ['status' => 1]]); + } + /** * @depends testBatchInsert */ @@ -240,54 +294,54 @@ class CollectionTest extends MongoDbTestCase $this->assertEquals($expectedRows, $rows); } - /** - * @depends testMapReduce - */ - public function testMapReduceInline() - { - $collection = $this->getConnection()->getCollection('customer'); - $rows = [ - [ - 'name' => 'customer 1', - 'status' => 1, - 'amount' => 100, - ], - [ - 'name' => 'customer 2', - 'status' => 1, - 'amount' => 200, - ], - [ - 'name' => 'customer 2', - 'status' => 2, - 'amount' => 400, - ], - [ - 'name' => 'customer 2', - 'status' => 3, - 'amount' => 500, - ], - ]; - $collection->batchInsert($rows); - - $result = $collection->mapReduce( - 'function () {emit(this.status, this.amount)}', - 'function (key, values) {return Array.sum(values)}', - ['inline' => true], - ['status' => ['$lt' => 3]] - ); - $expectedRows = [ - [ - '_id' => 1, - 'value' => 300, - ], - [ - '_id' => 2, - 'value' => 400, - ], - ]; - $this->assertEquals($expectedRows, $result); - } + /** + * @depends testMapReduce + */ + public function testMapReduceInline() + { + $collection = $this->getConnection()->getCollection('customer'); + $rows = [ + [ + 'name' => 'customer 1', + 'status' => 1, + 'amount' => 100, + ], + [ + 'name' => 'customer 2', + 'status' => 1, + 'amount' => 200, + ], + [ + 'name' => 'customer 2', + 'status' => 2, + 'amount' => 400, + ], + [ + 'name' => 'customer 2', + 'status' => 3, + 'amount' => 500, + ], + ]; + $collection->batchInsert($rows); + + $result = $collection->mapReduce( + 'function () {emit(this.status, this.amount)}', + 'function (key, values) {return Array.sum(values)}', + ['inline' => true], + ['status' => ['$lt' => 3]] + ); + $expectedRows = [ + [ + '_id' => 1, + 'value' => 300, + ], + [ + '_id' => 2, + 'value' => 400, + ], + ]; + $this->assertEquals($expectedRows, $result); + } public function testCreateIndex() { diff --git a/tests/unit/framework/base/ExceptionTest.php b/tests/unit/framework/base/ExceptionTest.php index 635b55c..136fc28 100644 --- a/tests/unit/framework/base/ExceptionTest.php +++ b/tests/unit/framework/base/ExceptionTest.php @@ -15,7 +15,7 @@ class ExceptionTest extends TestCase $this->assertEquals('bar', $array['message']); $this->assertEquals('foo', $array['previous']['message']); - $e = new InvalidCallException('bar', 0 ,new UserException('foo')); + $e = new InvalidCallException('bar', 0, new UserException('foo')); $array = $e->toArray(); $this->assertEquals('bar', $array['message']); $this->assertEquals('foo', $array['previous']['message']); diff --git a/tests/unit/framework/rbac/ManagerTestCase.php b/tests/unit/framework/rbac/ManagerTestCase.php index 6d80287..51c195e 100644 --- a/tests/unit/framework/rbac/ManagerTestCase.php +++ b/tests/unit/framework/rbac/ManagerTestCase.php @@ -173,7 +173,7 @@ abstract class ManagerTestCase extends TestCase $this->assertTrue($this->auth->executeBizRule(null, [], null)); $this->assertTrue($this->auth->executeBizRule('return 1 == true;', [], null)); $this->assertTrue($this->auth->executeBizRule('return $params[0] == $params[1];', [1, '1'], null)); - if (defined('HHVM_VERSION')) { // invalid code crashes on HHVM + if (!defined('HHVM_VERSION')) { // invalid code crashes on HHVM $this->assertFalse($this->auth->executeBizRule('invalid;', [], null)); } }