Commit 1ea6e76e by Qiang Xue

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

parents bb93ccf5 0208f289
...@@ -11,6 +11,9 @@ return [ ...@@ -11,6 +11,9 @@ return [
'mail' => [ 'mail' => [
'class' => 'yii\swiftmailer\Mailer', 'class' => 'yii\swiftmailer\Mailer',
'viewPath' => '@common/mail', '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, 'useFileTransport' => true,
], ],
], ],
......
...@@ -19,6 +19,9 @@ $config = [ ...@@ -19,6 +19,9 @@ $config = [
], ],
'mail' => [ 'mail' => [
'class' => 'yii\swiftmailer\Mailer', '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, 'useFileTransport' => true,
], ],
'log' => [ 'log' => [
......
...@@ -204,6 +204,23 @@ Then inside view file you can use following code: ...@@ -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 Creating your own mail solution
------------------------------- -------------------------------
......
...@@ -4,11 +4,12 @@ Yii Framework 2 elasticsearch extension Change Log ...@@ -4,11 +4,12 @@ Yii Framework 2 elasticsearch extension Change Log
2.0.0-rc under development 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: 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: 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) - 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 2.0.0-beta April 13, 2014
...@@ -27,7 +28,9 @@ Yii Framework 2 elasticsearch extension Change Log ...@@ -27,7 +28,9 @@ Yii Framework 2 elasticsearch extension Change Log
All relational queries are now directly served by `ActiveQuery` allowing to use All relational queries are now directly served by `ActiveQuery` allowing to use
custom scopes in relations (cebe) custom scopes in relations (cebe)
2.0.0-alpha, December 1, 2013 2.0.0-alpha, December 1, 2013
----------------------------- -----------------------------
- Initial release. - Initial release.
...@@ -80,7 +80,11 @@ class Command extends Component ...@@ -80,7 +80,11 @@ class Command extends Component
*/ */
public function insert($index, $type, $data, $id = null, $options = []) 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) { if ($id !== null) {
return $this->db->put([$index, $type, $id], $options, $body); return $this->db->put([$index, $type, $id], $options, $body);
......
...@@ -6,6 +6,7 @@ Yii Framework 2 gii extension Change Log ...@@ -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 #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 #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 #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 #3088: The gii module will manage their own URL rules now (qiangxue)
- Enh #3222: Added `useTablePrefix` option to the model generator for Gii (horizons2) - Enh #3222: Added `useTablePrefix` option to the model generator for Gii (horizons2)
......
...@@ -45,7 +45,14 @@ yii.gii = (function ($) { ...@@ -45,7 +45,14 @@ yii.gii = (function ($) {
$modal.find('.modal-title').text($link.data('title')); $modal.find('.modal-title').text($link.data('title'));
$modal.find('.modal-body').html('Loading ...'); $modal.find('.modal-body').html('Loading ...');
$modal.modal('show'); $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); $modal.find('.modal-checkbox span').toggleClass('glyphicon-check', checked).toggleClass('glyphicon-unchecked', !checked);
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
......
...@@ -32,6 +32,11 @@ class Order extends ActiveRecord ...@@ -32,6 +32,11 @@ class Order extends ActiveRecord
return $this->hasMany(OrderItem::className(), ['order_id' => 'id']); return $this->hasMany(OrderItem::className(), ['order_id' => 'id']);
} }
public function getOrderItemsWithNullFK()
{
return $this->hasMany(OrderItemWithNullFK::className(), ['order_id' => 'id']);
}
public function getItems() public function getItems()
{ {
return $this->hasMany(Item::className(), ['id' => 'item_id']) return $this->hasMany(Item::className(), ['id' => 'item_id'])
...@@ -72,7 +77,7 @@ class Order extends ActiveRecord ...@@ -72,7 +77,7 @@ class Order extends ActiveRecord
public function getBooksWithNullFK() public function getBooksWithNullFK()
{ {
return $this->hasMany(Item::className(), ['id' => 'item_id']) return $this->hasMany(Item::className(), ['id' => 'item_id'])
->via('orderItemsWithNullFk') ->via('orderItemsWithNullFK')
->where(['category_id' => 1]); ->where(['category_id' => 1]);
} }
......
...@@ -186,6 +186,16 @@ class ActiveRecordTest extends ElasticSearchTestCase ...@@ -186,6 +186,16 @@ class ActiveRecordTest extends ElasticSearchTestCase
$db->createCommand()->flushIndex('yiitest'); $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() public function testFindAsArray()
{ {
// asArray // asArray
......
...@@ -773,23 +773,23 @@ trait ActiveRecordTestTrait ...@@ -773,23 +773,23 @@ trait ActiveRecordTestTrait
/** @var Order $order */ /** @var Order $order */
$order = $orderClass::findOne(1); $order = $orderClass::findOne(1);
$this->assertEquals(2, count($order->books)); $this->assertEquals(2, count($order->books));
$this->assertEquals(6, $orderItemClass::find()->count()); $orderItemCount = $orderItemClass::find()->count();
$this->assertEquals(5, $itemClass::find()->count()); $this->assertEquals(5, $itemClass::find()->count());
$order->unlinkAll('books', true); $order->unlinkAll('books', true);
$this->afterSave(); $this->afterSave();
$this->assertEquals(5, $itemClass::find()->count()); $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)); $this->assertEquals(0, count($order->books));
// via model without delete // via model without delete
$this->assertEquals(2, count($order->booksWithNullFK)); $this->assertEquals(2, count($order->booksWithNullFK));
$this->assertEquals(6, $orderItemsWithNullFKClass::find()->count()); $orderItemCount = $orderItemsWithNullFKClass::find()->count();
$this->assertEquals(5, $itemClass::find()->count()); $this->assertEquals(5, $itemClass::find()->count());
$order->unlinkAll('booksWithNullFK',false); $order->unlinkAll('booksWithNullFK',false);
$this->afterSave(); $this->afterSave();
$this->assertEquals(0, count($order->booksWithNullFK)); $this->assertEquals(0, count($order->booksWithNullFK));
$this->assertEquals(2,$orderItemsWithNullFKClass::find()->where(['AND', ['item_id' => [1, 2]], ['order_id' => null]])->count()); $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()); $this->assertEquals(5, $itemClass::find()->count());
// via table is covered in \yiiunit\framework\db\ActiveRecordTest::testUnlinkAllViaTable() // via table is covered in \yiiunit\framework\db\ActiveRecordTest::testUnlinkAllViaTable()
......
...@@ -543,30 +543,30 @@ class ActiveRecordTest extends DatabaseTestCase ...@@ -543,30 +543,30 @@ class ActiveRecordTest extends DatabaseTestCase
/** @var \yii\db\ActiveRecordInterface $orderItemClass */ /** @var \yii\db\ActiveRecordInterface $orderItemClass */
$orderItemClass = $this->getOrderItemClass(); $orderItemClass = $this->getOrderItemClass();
/** @var \yii\db\ActiveRecordInterface $itemClass */ /** @var \yii\db\ActiveRecordInterface $itemClass */
$itemClass = $this->getOrderItemClass(); $itemClass = $this->getItemClass();
/** @var \yii\db\ActiveRecordInterface $orderItemsWithNullFKClass */ /** @var \yii\db\ActiveRecordInterface $orderItemsWithNullFKClass */
$orderItemsWithNullFKClass = $this->getOrderItemWithNullFKmClass(); $orderItemsWithNullFKClass = $this->getOrderItemWithNullFKmClass();
// via table with delete // via table with delete
/** @var Order $order */ /** @var Order $order */
$order = $orderClass::findOne(1); $order = $orderClass::findOne(1);
$this->assertEquals(2, count($order->books)); $this->assertEquals(2, count($order->booksViaTable));
$this->assertEquals(6, $orderItemClass::find()->count()); $orderItemCount = $orderItemClass::find()->count();
$this->assertEquals(5, $itemClass::find()->count()); $this->assertEquals(5, $itemClass::find()->count());
$order->unlinkAll('booksViaTable', true); $order->unlinkAll('booksViaTable', true);
$this->afterSave(); $this->afterSave();
$this->assertEquals(5, $itemClass::find()->count()); $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)); $this->assertEquals(0, count($order->booksViaTable));
// via table without delete // via table without delete
$this->assertEquals(2, count($order->booksWithNullFK)); $this->assertEquals(2, count($order->booksWithNullFKViaTable));
$this->assertEquals(6, $orderItemsWithNullFKClass::find()->count()); $orderItemCount = $orderItemsWithNullFKClass::find()->count();
$this->assertEquals(5, $itemClass::find()->count()); $this->assertEquals(5, $itemClass::find()->count());
$order->unlinkAll('booksWithNullFKViaTable',false); $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(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()); $this->assertEquals(5, $itemClass::find()->count());
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment