diff --git a/apps/advanced/environments/dev/common/config/main-local.php b/apps/advanced/environments/dev/common/config/main-local.php index dc1233a..d488438 100644 --- a/apps/advanced/environments/dev/common/config/main-local.php +++ b/apps/advanced/environments/dev/common/config/main-local.php @@ -11,6 +11,9 @@ return [ 'mail' => [ 'class' => 'yii\swiftmailer\Mailer', 'viewPath' => '@common/mail', + // send all mails to a file by default. You have to set + // 'useFileTransport' to false and configure a transport + // for the mailer to send real emails. 'useFileTransport' => true, ], ], diff --git a/apps/basic/config/web.php b/apps/basic/config/web.php index f9013d8..7fee63a 100644 --- a/apps/basic/config/web.php +++ b/apps/basic/config/web.php @@ -19,6 +19,9 @@ $config = [ ], 'mail' => [ 'class' => 'yii\swiftmailer\Mailer', + // send all mails to a file by default. You have to set + // 'useFileTransport' to false and configure a transport + // for the mailer to send real emails. 'useFileTransport' => true, ], 'log' => [ diff --git a/docs/guide/tutorial-mailing.md b/docs/guide/tutorial-mailing.md index 0ee16df..7f386ff 100644 --- a/docs/guide/tutorial-mailing.md +++ b/docs/guide/tutorial-mailing.md @@ -204,6 +204,23 @@ Then inside view file you can use following code: ``` +Testing and debugging +--------------------- + +Developer often a to check, what actual emails are sent by application, what was their content and so on. +Such ability is granted by Yii via `yii\mail\BaseMailer::useFileTransport`. If enabled, this option enforces +saving mail message data into the local files instead of regular sending. These files will be saved under +`yii\mail\BaseMailer::fileTransportPath`, which is '@runtime/mail' by default. + +> Note: you can either save messages to the file or send them to actual recipients, but can not do both simultaneously. + +Mail message file can be opened by regular text file editor, so you can browse actual message headers, content and so on. +This mechanism amy prove itself, while debugging application or running unit test. + +> Note: mail message file content is composed via `\yii\mail\MessageInterface::toString()`, so it depends on actual + mail extension you are using in your application. + + Creating your own mail solution ------------------------------- diff --git a/extensions/elasticsearch/CHANGELOG.md b/extensions/elasticsearch/CHANGELOG.md index ceaa33f..60ab3fe 100644 --- a/extensions/elasticsearch/CHANGELOG.md +++ b/extensions/elasticsearch/CHANGELOG.md @@ -4,11 +4,12 @@ Yii Framework 2 elasticsearch extension Change Log 2.0.0-rc under development -------------------------- +- Bug #3587: Fixed an issue with storing empty records (cebe) +- Enh #3520: Added `unlinkAll()`-method to active record to remove all records of a model relation (NmDimas, samdark, cebe) +- Enh #3527: Added `highlight` property to Query and ActiveRecord. (Borales) - Chg: asArray in ActiveQuery is now equal to using the normal Query. This means, that the output structure has changed and `with` is supported anymore. (cebe) - Chg: Deletion of a record is now also considered successful if the record did not exist. (cebe) - Chg: Requirement changes: Yii now requires elasticsearch version 1.0 or higher (cebe) -- Enh #3520: Added `unlinkAll()`-method to active record to remove all records of a model relation (NmDimas, samdark, cebe) -- Enh #3527: Added `highlight` property to Query and ActiveRecord. (Borales) 2.0.0-beta April 13, 2014 @@ -27,7 +28,9 @@ Yii Framework 2 elasticsearch extension Change Log All relational queries are now directly served by `ActiveQuery` allowing to use custom scopes in relations (cebe) + 2.0.0-alpha, December 1, 2013 ----------------------------- - Initial release. + diff --git a/extensions/elasticsearch/Command.php b/extensions/elasticsearch/Command.php index 7528f0f..6654efd 100644 --- a/extensions/elasticsearch/Command.php +++ b/extensions/elasticsearch/Command.php @@ -80,7 +80,11 @@ class Command extends Component */ public function insert($index, $type, $data, $id = null, $options = []) { - $body = is_array($data) ? Json::encode($data) : $data; + if (empty($data)) { + $body = '{}'; + } else { + $body = is_array($data) ? Json::encode($data) : $data; + } if ($id !== null) { return $this->db->put([$index, $type, $id], $options, $body); diff --git a/extensions/gii/CHANGELOG.md b/extensions/gii/CHANGELOG.md index bc2818e..69510d2 100644 --- a/extensions/gii/CHANGELOG.md +++ b/extensions/gii/CHANGELOG.md @@ -6,6 +6,7 @@ Yii Framework 2 gii extension Change Log - Bug #1263: Fixed the issue that Gii and Debug modules might be affected by incompatible asset manager configuration (qiangxue) - Bug #3265: Fixed incorrect controller class name validation (suralc) +- Bug #3693: Fixed broken Gii preview when a file is unchanged (cebe) - Enh #2018: Search model is not required anymore in CRUD generator (johonunu) - Enh #3088: The gii module will manage their own URL rules now (qiangxue) - Enh #3222: Added `useTablePrefix` option to the model generator for Gii (horizons2) diff --git a/extensions/gii/assets/gii.js b/extensions/gii/assets/gii.js index ad07252..0790770 100644 --- a/extensions/gii/assets/gii.js +++ b/extensions/gii/assets/gii.js @@ -45,7 +45,14 @@ yii.gii = (function ($) { $modal.find('.modal-title').text($link.data('title')); $modal.find('.modal-body').html('Loading ...'); $modal.modal('show'); - var checked = $('a.' + $modal.data('action') + '[href="' + $link.attr('href') + '"]').closest('tr').find('input').get(0).checked; + var checkbox = $('a.' + $modal.data('action') + '[href="' + $link.attr('href') + '"]').closest('tr').find('input').get(0); + var checked = false; + if (checkbox) { + checked = checkbox.checked; + $modal.find('.modal-checkbox').removeClass('disabled'); + } else { + $modal.find('.modal-checkbox').addClass('disabled'); + } $modal.find('.modal-checkbox span').toggleClass('glyphicon-check', checked).toggleClass('glyphicon-unchecked', !checked); $.ajax({ type: 'POST', diff --git a/tests/unit/data/ar/Order.php b/tests/unit/data/ar/Order.php index 8252b59..56701c1 100644 --- a/tests/unit/data/ar/Order.php +++ b/tests/unit/data/ar/Order.php @@ -32,6 +32,11 @@ class Order extends ActiveRecord return $this->hasMany(OrderItem::className(), ['order_id' => 'id']); } + public function getOrderItemsWithNullFK() + { + return $this->hasMany(OrderItemWithNullFK::className(), ['order_id' => 'id']); + } + public function getItems() { return $this->hasMany(Item::className(), ['id' => 'item_id']) @@ -72,7 +77,7 @@ class Order extends ActiveRecord public function getBooksWithNullFK() { return $this->hasMany(Item::className(), ['id' => 'item_id']) - ->via('orderItemsWithNullFk') + ->via('orderItemsWithNullFK') ->where(['category_id' => 1]); } diff --git a/tests/unit/extensions/elasticsearch/ActiveRecordTest.php b/tests/unit/extensions/elasticsearch/ActiveRecordTest.php index 045f112..4b05aa2 100644 --- a/tests/unit/extensions/elasticsearch/ActiveRecordTest.php +++ b/tests/unit/extensions/elasticsearch/ActiveRecordTest.php @@ -186,6 +186,16 @@ class ActiveRecordTest extends ElasticSearchTestCase $db->createCommand()->flushIndex('yiitest'); } + public function testSaveNoChanges() + { + // this should not fail with exception + $customer = new Customer(); + // insert + $customer->save(false); + // update + $customer->save(false); + } + public function testFindAsArray() { // asArray diff --git a/tests/unit/framework/ar/ActiveRecordTestTrait.php b/tests/unit/framework/ar/ActiveRecordTestTrait.php index beaa9f0..34f2fa0 100644 --- a/tests/unit/framework/ar/ActiveRecordTestTrait.php +++ b/tests/unit/framework/ar/ActiveRecordTestTrait.php @@ -773,23 +773,23 @@ trait ActiveRecordTestTrait /** @var Order $order */ $order = $orderClass::findOne(1); $this->assertEquals(2, count($order->books)); - $this->assertEquals(6, $orderItemClass::find()->count()); + $orderItemCount = $orderItemClass::find()->count(); $this->assertEquals(5, $itemClass::find()->count()); $order->unlinkAll('books', true); $this->afterSave(); $this->assertEquals(5, $itemClass::find()->count()); - $this->assertEquals(4, $orderItemClass::find()->count()); + $this->assertEquals($orderItemCount - 2, $orderItemClass::find()->count()); $this->assertEquals(0, count($order->books)); // via model without delete $this->assertEquals(2, count($order->booksWithNullFK)); - $this->assertEquals(6, $orderItemsWithNullFKClass::find()->count()); + $orderItemCount = $orderItemsWithNullFKClass::find()->count(); $this->assertEquals(5, $itemClass::find()->count()); $order->unlinkAll('booksWithNullFK',false); $this->afterSave(); $this->assertEquals(0, count($order->booksWithNullFK)); - $this->assertEquals(2,$orderItemsWithNullFKClass::find()->where(['AND', ['item_id' => [1, 2]], ['order_id' => null]])->count()); - $this->assertEquals(6, $orderItemsWithNullFKClass::find()->count()); + $this->assertEquals(2, $orderItemsWithNullFKClass::find()->where(['AND', ['item_id' => [1, 2]], ['order_id' => null]])->count()); + $this->assertEquals($orderItemCount, $orderItemsWithNullFKClass::find()->count()); $this->assertEquals(5, $itemClass::find()->count()); // via table is covered in \yiiunit\framework\db\ActiveRecordTest::testUnlinkAllViaTable() diff --git a/tests/unit/framework/db/ActiveRecordTest.php b/tests/unit/framework/db/ActiveRecordTest.php index dcbd96d..e29f97c 100644 --- a/tests/unit/framework/db/ActiveRecordTest.php +++ b/tests/unit/framework/db/ActiveRecordTest.php @@ -543,30 +543,30 @@ class ActiveRecordTest extends DatabaseTestCase /** @var \yii\db\ActiveRecordInterface $orderItemClass */ $orderItemClass = $this->getOrderItemClass(); /** @var \yii\db\ActiveRecordInterface $itemClass */ - $itemClass = $this->getOrderItemClass(); + $itemClass = $this->getItemClass(); /** @var \yii\db\ActiveRecordInterface $orderItemsWithNullFKClass */ $orderItemsWithNullFKClass = $this->getOrderItemWithNullFKmClass(); // via table with delete /** @var Order $order */ $order = $orderClass::findOne(1); - $this->assertEquals(2, count($order->books)); - $this->assertEquals(6, $orderItemClass::find()->count()); + $this->assertEquals(2, count($order->booksViaTable)); + $orderItemCount = $orderItemClass::find()->count(); $this->assertEquals(5, $itemClass::find()->count()); $order->unlinkAll('booksViaTable', true); $this->afterSave(); $this->assertEquals(5, $itemClass::find()->count()); - $this->assertEquals(4, $orderItemClass::find()->count()); - $this->assertEquals(0, count($order->books)); + $this->assertEquals($orderItemCount - 2, $orderItemClass::find()->count()); + $this->assertEquals(0, count($order->booksViaTable)); // via table without delete - $this->assertEquals(2, count($order->booksWithNullFK)); - $this->assertEquals(6, $orderItemsWithNullFKClass::find()->count()); + $this->assertEquals(2, count($order->booksWithNullFKViaTable)); + $orderItemCount = $orderItemsWithNullFKClass::find()->count(); $this->assertEquals(5, $itemClass::find()->count()); $order->unlinkAll('booksWithNullFKViaTable',false); - $this->assertEquals(0, count($order->booksWithNullFK)); + $this->assertEquals(0, count($order->booksWithNullFKViaTable)); $this->assertEquals(2,$orderItemsWithNullFKClass::find()->where(['AND', ['item_id' => [1, 2]], ['order_id' => null]])->count()); - $this->assertEquals(6, $orderItemsWithNullFKClass::find()->count()); + $this->assertEquals($orderItemCount, $orderItemsWithNullFKClass::find()->count()); $this->assertEquals(5, $itemClass::find()->count()); } }