Browse Source

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

tags/2.0.0-beta
Paul Klimov 11 years ago
parent
commit
6934707d25
  1. 2
      .travis.yml
  2. 1
      apps/advanced/backend/config/main.php
  3. 4
      apps/advanced/common/config/params.php
  4. 1
      apps/advanced/composer.json
  5. 1
      apps/advanced/console/config/main.php
  6. 1
      apps/advanced/frontend/config/main.php
  7. 1
      apps/advanced/frontend/controllers/SiteController.php
  8. 14
      apps/advanced/frontend/models/ContactForm.php
  9. 1
      apps/basic/composer.json
  10. 3
      apps/basic/config/web.php
  11. 14
      apps/basic/models/ContactForm.php
  12. 32
      extensions/swiftmailer/LICENSE.md
  13. 158
      extensions/swiftmailer/Mailer.php
  14. 301
      extensions/swiftmailer/Message.php
  15. 49
      extensions/swiftmailer/README.md
  16. 29
      extensions/swiftmailer/composer.json
  17. 7
      framework/yii/db/ActiveQuery.php
  18. 43
      framework/yii/db/ActiveRecord.php
  19. 223
      framework/yii/mail/BaseMailer.php
  20. 59
      framework/yii/mail/BaseMessage.php
  21. 64
      framework/yii/mail/MailerInterface.php
  22. 216
      framework/yii/mail/MessageInterface.php
  23. 3
      framework/yii/web/PageCache.php
  24. 30
      tests/unit/VendorTestCase.php
  25. 69
      tests/unit/extensions/swiftmailer/MailerTest.php
  26. 311
      tests/unit/extensions/swiftmailer/MessageTest.php
  27. 345
      tests/unit/framework/mail/BaseMailerTest.php
  28. 136
      tests/unit/framework/mail/BaseMessageTest.php

2
.travis.yml

@ -18,7 +18,7 @@ before_script:
- tests/unit/data/travis/cubrid-setup.sh
script:
- phpunit --coverage-clover tests/unit/runtime/coveralls/clover.xml --verbose --exclude-group mssql,oci,wincache,xcache,zenddata,sphinx
- phpunit --coverage-clover tests/unit/runtime/coveralls/clover.xml --verbose --exclude-group mssql,oci,wincache,xcache,zenddata,vendor
after_script:
- php vendor/bin/coveralls

1
apps/advanced/backend/config/main.php

@ -22,6 +22,7 @@ return [
],
'db' => $params['components.db'],
'cache' => $params['components.cache'],
'mail' => $params['components.mail'],
'user' => [
'identityClass' => 'common\models\User',
],

4
apps/advanced/common/config/params.php

@ -12,6 +12,10 @@ return [
'class' => 'yii\caching\FileCache',
],
'components.mail' => [
'class' => 'yii\swiftmailer\Mailer',
],
'components.db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=yii2advanced',

1
apps/advanced/composer.json

@ -16,6 +16,7 @@
"require": {
"php": ">=5.4.0",
"yiisoft/yii2": "dev-master",
"yiisoft/yii2-swiftmailer": "dev-master",
"yiisoft/yii2-bootstrap": "dev-master",
"yiisoft/yii2-debug": "dev-master",
"yiisoft/yii2-gii": "dev-master"

1
apps/advanced/console/config/main.php

@ -19,6 +19,7 @@ return [
'components' => [
'db' => $params['components.db'],
'cache' => $params['components.cache'],
'mail' => $params['components.mail'],
'log' => [
'targets' => [
[

1
apps/advanced/frontend/config/main.php

@ -23,6 +23,7 @@ return [
],
'db' => $params['components.db'],
'cache' => $params['components.cache'],
'mail' => $params['components.mail'],
'user' => [
'identityClass' => 'common\models\User',
],

1
apps/advanced/frontend/controllers/SiteController.php

@ -159,6 +159,7 @@ class SiteController extends Controller
$user->password_reset_token = Security::generateRandomKey();
if ($user->save(false)) {
// todo: refactor it with mail component. pay attention to the arrangement of mail view files
$fromEmail = \Yii::$app->params['supportEmail'];
$name = '=?UTF-8?B?' . base64_encode(\Yii::$app->name . ' robot') . '?=';
$subject = '=?UTF-8?B?' . base64_encode('Password reset for ' . \Yii::$app->name) . '?=';

14
apps/advanced/frontend/models/ContactForm.php

@ -2,6 +2,7 @@
namespace frontend\models;
use Yii;
use yii\base\Model;
/**
@ -48,13 +49,12 @@ class ContactForm extends Model
public function contact($email)
{
if ($this->validate()) {
$name = '=?UTF-8?B?' . base64_encode($this->name) . '?=';
$subject = '=?UTF-8?B?' . base64_encode($this->subject) . '?=';
$headers = "From: $name <{$this->email}>\r\n" .
"Reply-To: {$this->email}\r\n" .
"MIME-Version: 1.0\r\n" .
"Content-type: text/plain; charset=UTF-8";
mail($email, $subject, $this->body, $headers);
Yii::$app->mail->compose()
->setTo($email)
->setFrom([$this->email => $this->name])
->setSubject($this->subject)
->setTextBody($this->body)
->send();
return true;
} else {
return false;

1
apps/basic/composer.json

@ -16,6 +16,7 @@
"require": {
"php": ">=5.4.0",
"yiisoft/yii2": "dev-master",
"yiisoft/yii2-swiftmailer": "dev-master",
"yiisoft/yii2-bootstrap": "dev-master",
"yiisoft/yii2-debug": "dev-master",
"yiisoft/yii2-gii": "dev-master"

3
apps/basic/config/web.php

@ -17,6 +17,9 @@ $config = [
'errorHandler' => [
'errorAction' => 'site/error',
],
'mail' => [
'class' => 'yii\swiftmailer\Mailer',
],
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [

14
apps/basic/models/ContactForm.php

@ -2,6 +2,7 @@
namespace app\models;
use Yii;
use yii\base\Model;
/**
@ -48,13 +49,12 @@ class ContactForm extends Model
public function contact($email)
{
if ($this->validate()) {
$name = '=?UTF-8?B?' . base64_encode($this->name) . '?=';
$subject = '=?UTF-8?B?' . base64_encode($this->subject) . '?=';
$headers = "From: $name <{$this->email}>\r\n" .
"Reply-To: {$this->email}\r\n" .
"MIME-Version: 1.0\r\n" .
"Content-type: text/plain; charset=UTF-8";
mail($email, $subject, $this->body, $headers);
Yii::$app->mail->compose()
->setTo($email)
->setFrom([$this->email => $this->name])
->setSubject($this->subject)
->setTextBody($this->body)
->send();
return true;
} else {
return false;

32
extensions/swiftmailer/LICENSE.md

@ -0,0 +1,32 @@
The Yii framework is free software. It is released under the terms of
the following BSD License.
Copyright © 2008-2013 by Yii Software LLC (http://www.yiisoft.com)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Yii Software LLC nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

158
extensions/swiftmailer/Mailer.php

@ -0,0 +1,158 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\swiftmailer;
use Yii;
use yii\base\InvalidConfigException;
use yii\mail\BaseMailer;
/**
* Mailer implements a mailer based on SwiftMailer.
*
* To use Mailer, you should configure it in the application configuration like the following,
*
* ~~~
* 'components' => array(
* ...
* 'email' => array(
* 'class' => 'yii\swiftmailer\Mailer',
* 'transport' => [
* 'class' => 'Swift_SmtpTransport',
* 'host' => 'localhost',
* 'username' => 'username',
* 'password' => 'password',
* 'port' => '587',
* 'encryption' => 'tls',
* ],
* ),
* ...
* ),
* ~~~
*
* You may also skip the configuration of the [[transport]] property. In that case, the default
* PHP `mail()` function will be used to send emails.
*
* To send an email, you may use the following code:
*
* ~~~
* Yii::$app->mail->compose('contact/html', ['contactForm' => $form])
* ->setFrom('from@domain.com')
* ->setTo($form->email)
* ->setSubject($form->subject)
* ->send();
* ~~~
*
* @see http://swiftmailer.org
*
* @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.0
*/
class Mailer extends BaseMailer
{
/**
* @var string message default class name.
*/
public $messageClass = 'yii\swiftmailer\Message';
/**
* @var \Swift_Mailer Swift mailer instance.
*/
private $_swiftMailer;
/**
* @var \Swift_Transport|array Swift transport instance or its array configuration.
*/
private $_transport = [];
/**
* @return array|\Swift_Mailer Swift mailer instance or array configuration.
*/
public function getSwiftMailer()
{
if (!is_object($this->_swiftMailer)) {
$this->_swiftMailer = $this->createSwiftMailer();
}
return $this->_swiftMailer;
}
/**
* @param array|\Swift_Transport $transport
* @throws InvalidConfigException on invalid argument.
*/
public function setTransport($transport)
{
if (!is_array($transport) && !is_object($transport)) {
throw new InvalidConfigException('"' . get_class($this) . '::transport" should be either object or array, "' . gettype($transport) . '" given.');
}
$this->_transport = $transport;
}
/**
* @return array|\Swift_Transport
*/
public function getTransport()
{
if (!is_object($this->_transport)) {
$this->_transport = $this->createTransport($this->_transport);
}
return $this->_transport;
}
/**
* @inheritdoc
*/
public function send($message)
{
$address = $message->getTo();
if (is_array($address)) {
$address = implode(', ', $address);
}
Yii::trace('Sending email "' . $message->getSubject() . '" to "' . $address . '"', __METHOD__);
return $this->getSwiftMailer()->send($message->getSwiftMessage()) > 0;
}
/**
* Creates Swift mailer instance.
* @return \Swift_Mailer mailer instance.
*/
protected function createSwiftMailer()
{
return \Swift_Mailer::newInstance($this->getTransport());
}
/**
* Creates email transport instance by its array configuration.
* @param array $config transport configuration.
* @throws \yii\base\InvalidConfigException on invalid transport configuration.
* @return \Swift_Transport transport instance.
*/
protected function createTransport(array $config)
{
if (isset($config['class'])) {
$className = $config['class'];
unset($config['class']);
} else {
$className = 'Swift_MailTransport';
}
/** @var \Swift_MailTransport $transport */
$transport = $className::newInstance();
if (!empty($config)) {
foreach ($config as $name => $value) {
if (property_exists($transport, $name)) {
$transport->$name = $value;
} else {
$setter = 'set' . $name;
if (method_exists($transport, $setter)) {
$transport->$setter($value);
} else {
throw new InvalidConfigException('Setting unknown property: ' . get_class($transport) . '::' . $name);
}
}
}
}
return $transport;
}
}

301
extensions/swiftmailer/Message.php

@ -0,0 +1,301 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\swiftmailer;
use yii\mail\BaseMessage;
/**
* Message implements a message class based on SwiftMailer.
*
* @see http://swiftmailer.org/docs/messages.html
* @see Mailer
*
* @method Mailer getMailer() returns mailer instance.
* @property \Swift_Message $swiftMessage vendor message instance.
*
* @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.0
*/
class Message extends BaseMessage
{
/**
* @var \Swift_Message Swift message instance.
*/
private $_swiftMessage;
/**
* @return \Swift_Message Swift message instance.
*/
public function getSwiftMessage()
{
if (!is_object($this->_swiftMessage)) {
$this->_swiftMessage = $this->createSwiftMessage();
}
return $this->_swiftMessage;
}
/**
* @inheritdoc
*/
public function getCharset()
{
$this->getSwiftMessage()->getCharset();
}
/**
* @inheritdoc
*/
public function setCharset($charset)
{
$this->getSwiftMessage()->setCharset($charset);
return $this;
}
/**
* @inheritdoc
*/
public function getFrom()
{
$this->getSwiftMessage()->getFrom();
}
/**
* @inheritdoc
*/
public function setFrom($from)
{
$this->getSwiftMessage()->setFrom($from);
return $this;
}
/**
* @inheritdoc
*/
public function getReplyTo()
{
$this->getSwiftMessage()->getReplyTo();
}
/**
* @inheritdoc
*/
public function setReplyTo($replyTo)
{
$this->getSwiftMessage()->setReplyTo($replyTo);
return $this;
}
/**
* @inheritdoc
*/
public function getTo()
{
$this->getSwiftMessage()->getTo();
}
/**
* @inheritdoc
*/
public function setTo($to)
{
$this->getSwiftMessage()->setTo($to);
return $this;
}
/**
* @inheritdoc
*/
public function getCc()
{
$this->getSwiftMessage()->getCc();
}
/**
* @inheritdoc
*/
public function setCc($cc)
{
$this->getSwiftMessage()->setCc($cc);
return $this;
}
/**
* @inheritdoc
*/
public function getBcc()
{
$this->getSwiftMessage()->getBcc();
}
/**
* @inheritdoc
*/
public function setBcc($bcc)
{
$this->getSwiftMessage()->setBcc($bcc);
return $this;
}
/**
* @inheritdoc
*/
public function getSubject()
{
$this->getSwiftMessage()->getSubject();
}
/**
* @inheritdoc
*/
public function setSubject($subject)
{
$this->getSwiftMessage()->setSubject($subject);
return $this;
}
/**
* @inheritdoc
*/
public function setTextBody($text)
{
$this->setBody($text, 'text/plain');
return $this;
}
/**
* @inheritdoc
*/
public function setHtmlBody($html)
{
$this->setBody($html, 'text/html');
return $this;
}
/**
* Sets the message body.
* If body is already set and its content type matches given one, it will
* be overridden, if content type miss match the multipart message will be composed.
* @param string $body body content.
* @param string $contentType body content type.
*/
protected function setBody($body, $contentType)
{
$message = $this->getSwiftMessage();
$oldBody = $message->getBody();
if (empty($oldBody)) {
$parts = $message->getChildren();
$partFound = false;
foreach ($parts as $key => $part) {
if (!($part instanceof \Swift_Mime_Attachment)) {
/* @var $part \Swift_Mime_MimePart */
if ($part->getContentType() == $contentType) {
unset($parts[$key]);
$partFound = true;
break;
}
}
}
if ($partFound) {
reset($parts);
$message->setChildren($parts);
$message->addPart($body, $contentType);
} else {
$message->setBody($body, $contentType);
}
} else {
$oldContentType = $message->getContentType();
if ($oldContentType == $contentType) {
$message->setBody($body, $contentType);
} else {
$message->setBody(null);
$message->setContentType(null);
$message->addPart($oldBody, $oldContentType);
$message->addPart($body, $contentType);
}
}
}
/**
* @inheritdoc
*/
public function attach($fileName, array $options = [])
{
$attachment = \Swift_Attachment::fromPath($fileName);
if (!empty($options['fileName'])) {
$attachment->setFilename($options['fileName']);
}
if (!empty($options['contentType'])) {
$attachment->setContentType($options['contentType']);
}
$this->getSwiftMessage()->attach($attachment);
return $this;
}
/**
* @inheritdoc
*/
public function attachContent($content, array $options = [])
{
$attachment = \Swift_Attachment::newInstance($content);
if (!empty($options['fileName'])) {
$attachment->setFilename($options['fileName']);
}
if (!empty($options['contentType'])) {
$attachment->setContentType($options['contentType']);
}
$this->getSwiftMessage()->attach($attachment);
return $this;
}
/**
* @inheritdoc
*/
public function embed($fileName, array $options = [])
{
$embedFile = \Swift_EmbeddedFile::fromPath($fileName);
if (!empty($options['fileName'])) {
$embedFile->setFilename($options['fileName']);
}
if (!empty($options['contentType'])) {
$embedFile->setContentType($options['contentType']);
}
return $this->getSwiftMessage()->embed($embedFile);
}
/**
* @inheritdoc
*/
public function embedContent($content, array $options = [])
{
$embedFile = \Swift_EmbeddedFile::newInstance($content);
if (!empty($options['fileName'])) {
$embedFile->setFilename($options['fileName']);
}
if (!empty($options['contentType'])) {
$embedFile->setContentType($options['contentType']);
}
return $this->getSwiftMessage()->embed($embedFile);
}
/**
* @inheritdoc
*/
public function toString()
{
return $this->getSwiftMessage()->toString();
}
/**
* Creates the Swift email message instance.
* @return \Swift_Message email message instance.
*/
protected function createSwiftMessage()
{
return new \Swift_Message();
}
}

49
extensions/swiftmailer/README.md

@ -0,0 +1,49 @@
SwiftMailer Extension for Yii 2
===============================
This extension provides a `SwiftMailer` mail solution for Yii 2.
To use this extension, simply add the following code in your application configuration:
```php
return [
//....
'components' => [
'mail' => [
'class' => 'yii\swiftmailer\Mailer',
],
],
];
```
You can then send an email as follows:
```php
Yii::$app->mail->compose('contact/html')
->from('from@domain.com')
->to($form->email)
->subject($form->subject)
->send();
```
For further instructions refer to the related section in the Yii Definitive Guide.
Installation
------------
The preferred way to install this extension is through [composer](http://getcomposer.org/download/).
Either run
```
php composer.phar require yiisoft/yii2-swiftmailer "*"
```
or add
```json
"yiisoft/yii2-swiftmailer": "*"
```
to the require section of your composer.json.

29
extensions/swiftmailer/composer.json

@ -0,0 +1,29 @@
{
"name": "yiisoft/yii2-swiftmailer",
"description": "The SwiftMailer integration for the Yii framework",
"keywords": ["yii", "swift", "swiftmailer", "mail", "email", "mailer"],
"type": "yii2-extension",
"license": "BSD-3-Clause",
"support": {
"issues": "https://github.com/yiisoft/yii2/issues?state=open",
"forum": "http://www.yiiframework.com/forum/",
"wiki": "http://www.yiiframework.com/wiki/",
"irc": "irc://irc.freenode.net/yii",
"source": "https://github.com/yiisoft/yii2"
},
"authors": [
{
"name": "Paul Klimov",
"email": "klimov.paul@gmail.com"
}
],
"minimum-stability": "dev",
"require": {
"yiisoft/yii2": "*",
"swiftmailer/swiftmailer": "@stable"
},
"autoload": {
"psr-0": { "yii\\swiftmailer\\": "" }
},
"target-dir": "yii/swiftmailer"
}

7
framework/yii/db/ActiveQuery.php

@ -182,11 +182,18 @@ class ActiveQuery extends Query
* The parameters to this method can be either one or multiple strings, or a single array
* of relation names and the optional callbacks to customize the relations.
*
* A relation name can refer to a relation defined in [[modelClass]]
* or a sub-relation that stands for a relation of a related record.
* For example, `orders.address` means the `address` relation defined
* in the model class corresponding to the `orders` relation.
*
* The followings are some usage examples:
*
* ~~~
* // find customers together with their orders and country
* Customer::find()->with('orders', 'country')->all();
* // find customers together with their orders and the orders' shipping address
* Customer::find()->with('orders.address')->all();
* // find customers together with their country and orders of status 1
* Customer::find()->with([
* 'orders' => function($query) {

43
framework/yii/db/ActiveRecord.php

@ -379,13 +379,12 @@ class ActiveRecord extends Model
} elseif ($this->hasAttribute($name)) {
return null;
} else {
$t = strtolower($name);
if (isset($this->_related[$t]) || array_key_exists($t, $this->_related)) {
return $this->_related[$t];
if (isset($this->_related[$name]) || array_key_exists($name, $this->_related)) {
return $this->_related[$name];
}
$value = parent::__get($name);
if ($value instanceof ActiveRelation) {
return $this->_related[$t] = $value->multiple ? $value->all() : $value->one();
return $this->_related[$name] = $value->multiple ? $value->all() : $value->one();
} else {
return $value;
}
@ -433,9 +432,8 @@ class ActiveRecord extends Model
if ($this->hasAttribute($name)) {
unset($this->_attributes[$name]);
} else {
$t = strtolower($name);
if (isset($this->_related[$t])) {
unset($this->_related[$t]);
if (isset($this->_related[$name])) {
unset($this->_related[$name]);
} else {
parent::__unset($name);
}
@ -523,12 +521,31 @@ class ActiveRecord extends Model
/**
* 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-insensitive)
* @param string $name the relation name (case-sensitive)
* @param ActiveRecord|array|null the related records to be populated into the relation.
*/
public function populateRelation($name, $records)
{
$this->_related[strtolower($name)] = $records;
$this->_related[$name] = $records;
}
/**
* Check whether the named relation has been populated with records.
* @param string $name the relation name (case-sensitive)
* @return bool whether relation has been populated with records.
*/
public function isRelationPopulated($name)
{
return array_key_exists($name, $this->_related);
}
/**
* Returns all populated relations.
* @return array an array of relation data indexed by relation names.
*/
public function getPopulatedRelations()
{
return $this->_related;
}
/**
@ -1286,7 +1303,7 @@ class ActiveRecord extends Model
*
* Note that this method requires that the primary key value is not null.
*
* @param string $name the name of the relationship
* @param string $name the case sensitive name of the relationship
* @param ActiveRecord $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
@ -1308,7 +1325,7 @@ class ActiveRecord extends Model
$viaClass = $viaRelation->modelClass;
$viaTable = $viaClass::tableName();
// unset $viaName so that it can be reloaded to reflect the change
unset($this->_related[strtolower($viaName)]);
unset($this->_related[$viaName]);
} else {
$viaRelation = $relation->via;
$viaTable = reset($relation->via->from);
@ -1364,7 +1381,7 @@ class ActiveRecord extends Model
* The model with the foreign key of the relationship will be deleted if `$delete` is true.
* Otherwise, the foreign key will be set null and the model will be saved without validation.
*
* @param string $name the name of the relationship.
* @param string $name the case sensitive name of the relationship.
* @param ActiveRecord $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.
@ -1382,7 +1399,7 @@ class ActiveRecord extends Model
/** @var $viaClass ActiveRecord */
$viaClass = $viaRelation->modelClass;
$viaTable = $viaClass::tableName();
unset($this->_related[strtolower($viaName)]);
unset($this->_related[$viaName]);
} else {
$viaRelation = $relation->via;
$viaTable = reset($relation->via->from);

223
framework/yii/mail/BaseMailer.php

@ -0,0 +1,223 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\mail;
use Yii;
use yii\base\Component;
use yii\base\InvalidConfigException;
use yii\base\ViewContextInterface;
use yii\web\View;
/**
* BaseMailer serves as a base class that implements the basic functions required by [[MailerInterface]].
*
* Concrete child classes should may focus on implementing the [[send()]] method.
*
* @see BaseMessage
*
* @property View|array $view view instance or its array configuration.
*
* @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.0
*/
abstract class BaseMailer extends Component implements MailerInterface, ViewContextInterface
{
/**
* @var \yii\base\View|array view instance or its array configuration.
*/
private $_view = [];
/**
* @var string directory containing view files for this email messages.
* This can be specified as an absolute path or path alias.
*/
public $viewPath = '@app/mails';
/**
* @var string|boolean HTML layout view name. This is the layout used to render HTML mail body.
* The property can take the following values:
*
* - a relative view name: a view file relative to [[viewPath]], e.g., 'layouts/html'.
* - a path alias: an absolute view file path specified as a path alias, e.g., '@app/mails/html'.
* - a boolean false: the layout is disabled.
*/
public $htmlLayout = 'layouts/html';
/**
* @var string|boolean text layout view name. This is the layout used to render TEXT mail body.
* Please refer to [[htmlLayout]] for possible values that this property can take.
*/
public $textLayout = 'layouts/text';
/**
* @var array the configuration that should be applied to any newly created
* email message instance by [[createMessage()]] or [[compose()]]. Any valid property defined
* by [[MessageInterface]] can be configured, such as `from`, `to`, `subject`, `textBody`, `htmlBody`, etc.
*
* For example:
*
* ~~~
* [
* 'charset' => 'UTF-8',
* 'from' => 'noreply@mydomain.com',
* 'bcc' => 'developer@mydomain.com',
* ]
* ~~~
*/
public $messageConfig = [];
/**
* @var string the default class name of the new message instances created by [[createMessage()]]
*/
public $messageClass = 'yii\mail\BaseMessage';
/**
* @param array|View $view view instance or its array configuration that will be used to
* render message bodies.
* @throws InvalidConfigException on invalid argument.
*/
public function setView($view)
{
if (!is_array($view) && !is_object($view)) {
throw new InvalidConfigException('"' . get_class($this) . '::view" should be either object or configuration array, "' . gettype($view) . '" given.');
}
$this->_view = $view;
}
/**
* @return View view instance.
*/
public function getView()
{
if (!is_object($this->_view)) {
$this->_view = $this->createView($this->_view);
}
return $this->_view;
}
/**
* Creates view instance from given configuration.
* @param array $config view configuration.
* @return View view instance.
*/
protected function createView(array $config)
{
if (!array_key_exists('class', $config)) {
$config['class'] = View::className();
}
return Yii::createObject($config);
}
/**
* Creates a new message instance and optionally composes its body content via view rendering.
*
* @param string|array $view the view to be used for rendering the message body. This can be:
*
* - a string, which represents the view name or path alias for rendering the HTML body of the email.
* In this case, the text body will be generated by applying `strip_tags()` to the HTML body.
* - an array with 'html' and/or 'text' elements. The 'html' element refers to the view name or path alias
* for rendering the HTML body, while 'text' element is for rendering the text body. For example,
* `['html' => 'contact-html', 'text' => 'contact-text']`.
* - null, meaning the message instance will be returned without body content.
*
* The view to be rendered can be specified in one of the following formats:
*
* - path alias (e.g. "@app/mails/contact");
* - a relative view name (e.g. "contact"): the actual view file will be resolved by [[findViewFile()]]
*
* @param array $params the parameters (name-value pairs) that will be extracted and made available in the view file.
* @return MessageInterface message instance.
*/
public function compose($view = null, array $params = [])
{
$message = $this->createMessage();
if ($view !== null) {
$params['message'] = $message;
if (is_array($view)) {
if (isset($view['html'])) {
$html = $this->render($view['html'], $params, $this->htmlLayout);
}
if (isset($view['text'])) {
$text = $this->render($view['text'], $params, $this->textLayout);
}
} else {
$html = $this->render($view, $params, $this->htmlLayout);
}
if (isset($html)) {
$message->setHtmlBody($html);
}
if (isset($text)) {
$message->setTextBody($text);
} elseif (isset($html)) {
$message->setTextBody(strip_tags($html));
}
}
return $message;
}
/**
* Creates a new message instance.
* The newly created instance will be initialized with the configuration specified by [[messageConfig]].
* If the configuration does not specify a 'class', the [[messageClass]] will be used as the class
* of the new message instance.
* @return MessageInterface message instance.
*/
protected function createMessage()
{
$config = $this->messageConfig;
if (!array_key_exists('class', $config)) {
$config['class'] = $this->messageClass;
}
return Yii::createObject($config);
}
/**
* Sends multiple messages at once.
*
* The default implementation simply calls [[send()]] multiple times.
* Child classes may override this method to implement more efficient way of
* sending multiple messages.
*
* @param array $messages list of email messages, which should be sent.
* @return integer number of messages that are successfully sent.
*/
public function sendMultiple(array $messages)
{
$successCount = 0;
foreach ($messages as $message) {
if ($this->send($message)) {
$successCount++;
}
}
return $successCount;
}
/**
* Renders the specified view with optional parameters and layout.
* The view will be rendered using the [[view]] component.
* @param string $view the view name or the path alias of the view file.
* @param array $params the parameters (name-value pairs) that will be extracted and made available in the view file.
* @param string|boolean $layout layout view name or path alias. If false, no layout will be applied.
* @return string the rendering result.
*/
public function render($view, $params = [], $layout = false)
{
$output = $this->getView()->render($view, $params, $this);
if ($layout !== false) {
return $this->getView()->render($layout, ['content' => $output], $this);
} else {
return $output;
}
}
/**
* Finds the view file corresponding to the specified relative view name.
* This method will return the view file by prefixing the view name with [[viewPath]].
* @param string $view a relative view name. The name does NOT start with a slash.
* @return string the view file path. Note that the file may not exist.
*/
public function findViewFile($view)
{
return Yii::getAlias($this->viewPath) . DIRECTORY_SEPARATOR . $view;
}
}

59
framework/yii/mail/BaseMessage.php

@ -0,0 +1,59 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\mail;
use yii\base\Object;
use Yii;
/**
* BaseMessage serves as a base class that implements the [[send()]] method required by [[MessageInterface]].
*
* By default, [[send()]] will use the "mail" application component to send the current message.
* The "mail" application component should be a mailer instance implementing [[MailerInterface]].
*
* @see BaseMailer
*
* @property BaseMailer $mailer mailer component instance. This property is read-only.
*
* @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.0
*/
abstract class BaseMessage extends Object implements MessageInterface
{
/**
* @return MailerInterface the mailer component
*/
public function getMailer()
{
return Yii::$app->getComponent('mail');
}
/**
* @inheritdoc
*/
public function send()
{
return $this->getMailer()->send($this);
}
/**
* PHP magic method that returns the string representation of this object.
* @return string the string representation of this object.
*/
public function __toString()
{
// __toString cannot throw exception
// use trigger_error to bypass this limitation
try {
return $this->toString();
} catch (\Exception $e) {
trigger_error($e->getMessage());
return '';
}
}
}

64
framework/yii/mail/MailerInterface.php

@ -0,0 +1,64 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\mail;
/**
* MailerInterface is the interface that should be implemented by mailer classes.
*
* A mailer should mainly support creating and sending [[MessageInterface|mail messages]]. It should
* also support composition of the message body through the view rendering mechanism. For example,
*
* ~~~
* Yii::$app->mail->compose('contact/html', ['contactForm' => $form])
* ->setFrom('from@domain.com')
* ->setTo($form->email)
* ->setSubject($form->subject)
* ->send();
* ~~~
*
* @see MessageInterface
*
* @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.0
*/
interface MailerInterface
{
/**
* Creates a new message instance and optionally composes its body content via view rendering.
*
* @param string|array $view the view to be used for rendering the message body. This can be:
*
* - a string, which represents the view name or path alias for rendering the HTML body of the email.
* In this case, the text body will be generated by applying `strip_tags()` to the HTML body.
* - an array with 'html' and/or 'text' elements. The 'html' element refers to the view name or path alias
* for rendering the HTML body, while 'text' element is for rendering the text body. For example,
* `['html' => 'contact-html', 'text' => 'contact-text']`.
* - null, meaning the message instance will be returned without body content.
*
* @param array $params the parameters (name-value pairs) that will be extracted and made available in the view file.
* @return MessageInterface message instance.
*/
public function compose($view = null, array $params = []);
/**
* Sends the given email message.
* @param MessageInterface $message email message instance to be sent
* @return boolean whether the message has been sent successfully
*/
public function send($message);
/**
* Sends multiple messages at once.
*
* This method may be implemented by some mailers which support more efficient way of sending multiple messages in the same batch.
*
* @param array $messages list of email messages, which should be sent.
* @return integer number of messages that are successfully sent.
*/
public function sendMultiple(array $messages);
}

216
framework/yii/mail/MessageInterface.php

@ -0,0 +1,216 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\mail;
/**
* MessageInterface is the interface that should be implemented by mail message classes.
*
* A message represents the settings and content of an email, such as the sender, recipient,
* subject, body, etc.
*
* Messages are sent by a [[MailerInterface||mailer]], like the following,
*
* ~~~
* Yii::$app->mail->compose()
* ->setFrom('from@domain.com')
* ->setTo($form->email)
* ->setSubject($form->subject)
* ->setTextBody('Plain text content')
* ->setHtmlBody('<b>HTML content</b>')
* ->send();
* ~~~
*
* @see MailerInterface
*
* @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.0
*/
interface MessageInterface
{
/**
* Returns the character set of this message.
* @return string the character set of this message.
*/
public function getCharset();
/**
* Sets the character set of this message.
* @param string $charset character set name.
* @return static self reference.
*/
public function setCharset($charset);
/**
* Returns the message sender.
* @return string the sender
*/
public function getFrom();
/**
* Sets the message sender.
* @param string|array $from sender email address.
* You may pass an array of addresses if this message is from multiple people.
* You may also specify sender name in addition to email address using format:
* `[email => name]`.
* @return static self reference.
*/
public function setFrom($from);
/**
* Returns the message recipient(s).
* @return array the message recipients
*/
public function getTo();
/**
* Sets the message recipient(s).
* @param string|array $to receiver email address.
* You may pass an array of addresses if multiple recipients should receive this message.
* You may also specify receiver name in addition to email address using format:
* `[email => name]`.
* @return static self reference.
*/
public function setTo($to);
/**
* Returns the reply-to address of this message.
* @return string the reply-to address of this message.
*/
public function getReplyTo();
/**
* Sets the reply-to address of this message.
* @param string|array $replyTo the reply-to address.
* You may pass an array of addresses if this message should be replied to multiple people.
* You may also specify reply-to name in addition to email address using format:
* `[email => name]`.
* @return static self reference.
*/
public function setReplyTo($replyTo);
/**
* Returns the Cc (additional copy receiver) addresses of this message.
* @return array the Cc (additional copy receiver) addresses of this message.
*/
public function getCc();
/**
* Sets the Cc (additional copy receiver) addresses of this message.
* @param string|array $cc copy receiver email address.
* You may pass an array of addresses if multiple recipients should receive this message.
* You may also specify receiver name in addition to email address using format:
* `[email => name]`.
* @return static self reference.
*/
public function setCc($cc);
/**
* Returns the Bcc (hidden copy receiver) addresses of this message.
* @return array the Bcc (hidden copy receiver) addresses of this message.
*/
public function getBcc();
/**
* Sets the Bcc (hidden copy receiver) addresses of this message.
* @param string|array $bcc hidden copy receiver email address.
* You may pass an array of addresses if multiple recipients should receive this message.
* You may also specify receiver name in addition to email address using format:
* `[email => name]`.
* @return static self reference.
*/
public function setBcc($bcc);
/**
* Returns the message subject.
* @return string the message subject
*/
public function getSubject();
/**
* Sets the message subject.
* @param string $subject message subject
* @return static self reference.
*/
public function setSubject($subject);
/**
* Sets message plain text content.
* @param string $text message plain text content.
* @return static self reference.
*/
public function setTextBody($text);
/**
* Sets message HTML content.
* @param string $html message HTML content.
* @return static self reference.
*/
public function setHtmlBody($html);
/**
* Attaches existing file to the email message.
* @param string $fileName full file name
* @param array $options options for embed file. Valid options are:
*
* - fileName: name, which should be used to attach file.
* - contentType: attached file MIME type.
*
* @return static self reference.
*/
public function attach($fileName, array $options = []);
/**
* Attach specified content as file for the email message.
* @param string $content attachment file content.
* @param array $options options for embed file. Valid options are:
*
* - fileName: name, which should be used to attach file.
* - contentType: attached file MIME type.
*
* @return static self reference.
*/
public function attachContent($content, array $options = []);
/**
* Attach a file and return it's CID source.
* This method should be used when embedding images or other data in a message.
* @param string $fileName file name.
* @param array $options options for embed file. Valid options are:
*
* - fileName: name, which should be used to attach file.
* - contentType: attached file MIME type.
*
* @return string attachment CID.
*/
public function embed($fileName, array $options = []);
/**
* Attach a content as file and return it's CID source.
* This method should be used when embedding images or other data in a message.
* @param string $content attachment file content.
* @param array $options options for embed file. Valid options are:
*
* - fileName: name, which should be used to attach file.
* - contentType: attached file MIME type.
*
* @return string attachment CID.
*/
public function embedContent($content, array $options = []);
/**
* Sends this email message.
* @return boolean whether this message is sent successfully.
*/
public function send();
/**
* Returns string representation of this message.
* @return string the string representation of this message.
*/
public function toString();
}

3
framework/yii/web/PageCache.php

@ -10,7 +10,6 @@ namespace yii\web;
use Yii;
use yii\base\ActionFilter;
use yii\base\Action;
use yii\base\View;
use yii\caching\Dependency;
/**
@ -69,7 +68,7 @@ class PageCache extends ActionFilter
*/
public $enabled = true;
/**
* @var View the view component to use for caching. If not set, the default application view component
* @var \yii\base\View the view component to use for caching. If not set, the default application view component
* [[Application::view]] will be used.
*/
public $view;

30
tests/unit/VendorTestCase.php

@ -0,0 +1,30 @@
<?php
namespace yiiunit;
use yii\base\NotSupportedException;
use Yii;
/**
* This is the base class for all yii framework unit tests, which requires
* external vendor libraries to function.
*/
class VendorTestCase extends TestCase
{
/**
* This method is called before the first test of this test class is run.
* Attempts to load vendor autoloader.
* @throws \yii\base\NotSupportedException
*/
public static function setUpBeforeClass()
{
$vendorDir = __DIR__ . '/vendor';
Yii::setAlias('@vendor', $vendorDir);
$vendorAutoload = $vendorDir . '/autoload.php';
if (file_exists($vendorAutoload)) {
require_once($vendorAutoload);
} else {
throw new NotSupportedException("Vendor autoload file '{$vendorAutoload}' is missing.");
}
}
}

69
tests/unit/extensions/swiftmailer/MailerTest.php

@ -0,0 +1,69 @@
<?php
namespace yiiunit\extensions\swiftmailer;
use Yii;
use yii\swiftmailer\Mailer;
use yii\swiftmailer\Message;
use yiiunit\VendorTestCase;
/**
* @group vendor
* @group mail
* @group swiftmailer
*/
class MailerTest extends VendorTestCase
{
public function setUp()
{
$this->mockApplication([
'components' => [
'email' => $this->createTestEmailComponent()
]
]);
}
/**
* @return Mailer test email component instance.
*/
protected function createTestEmailComponent()
{
$component = new Mailer();
return $component;
}
// Tests :
public function testSetupTransport()
{
$mailer = new Mailer();
$transport = \Swift_MailTransport::newInstance();
$mailer->setTransport($transport);
$this->assertEquals($transport, $mailer->getTransport(), 'Unable to setup transport!');
}
/**
* @depends testSetupTransport
*/
public function testConfigureTransport()
{
$mailer = new Mailer();
$transportConfig = [
'class' => 'Swift_SmtpTransport',
'host' => 'localhost',
];
$mailer->setTransport($transportConfig);
$transport = $mailer->getTransport();
$this->assertTrue(is_object($transport), 'Unable to setup transport via config!');
$this->assertEquals($transportConfig['class'], get_class($transport), 'Invalid transport class!');
$this->assertEquals($transportConfig['host'], $transport->getHost(), 'Invalid transport host!');
}
public function testGetSwiftMailer()
{
$mailer = new Mailer();
$this->assertTrue(is_object($mailer->getSwiftMailer()), 'Unable to get Swift mailer instance!');
}
}

311
tests/unit/extensions/swiftmailer/MessageTest.php

@ -0,0 +1,311 @@
<?php
namespace yiiunit\extensions\swiftmailer;
use Yii;
use yii\helpers\FileHelper;
use yii\swiftmailer\Mailer;
use yii\swiftmailer\Message;
use yiiunit\VendorTestCase;
/**
* @group vendor
* @group mail
* @group swiftmailer
*/
class MessageTest extends VendorTestCase
{
/**
* @var string test email address, which will be used as receiver for the messages.
*/
protected $testEmailReceiver = 'someuser@somedomain.com';
public function setUp()
{
$this->mockApplication([
'components' => [
'mail' => $this->createTestEmailComponent()
]
]);
$filePath = $this->getTestFilePath();
if (!file_exists($filePath)) {
FileHelper::createDirectory($filePath);
}
}
public function tearDown()
{
$filePath = $this->getTestFilePath();
if (file_exists($filePath)) {
FileHelper::removeDirectory($filePath);
}
}
/**
* @return string test file path.
*/
protected function getTestFilePath()
{
return Yii::getAlias('@yiiunit/runtime') . DIRECTORY_SEPARATOR . basename(get_class($this)) . '_' . getmypid();
}
/**
* @return Mailer test email component instance.
*/
protected function createTestEmailComponent()
{
$component = new Mailer();
return $component;
}
/**
* @return Message test message instance.
*/
protected function createTestMessage()
{
return Yii::$app->getComponent('mail')->compose();
}
/**
* Creates image file with given text.
* @param string $fileName file name.
* @param string $text text to be applied on image.
* @return string image file full name.
*/
protected function createImageFile($fileName = 'test.jpg', $text = 'Test Image')
{
if (!function_exists('imagecreatetruecolor')) {
$this->markTestSkipped('GD lib required.');
}
$fileFullName = $this->getTestFilePath() . DIRECTORY_SEPARATOR . $fileName;
$image = imagecreatetruecolor(120, 20);
$textColor = imagecolorallocate($image, 233, 14, 91);
imagestring($image, 1, 5, 5, $text, $textColor);
imagejpeg($image, $fileFullName);
imagedestroy($image);
return $fileFullName;
}
/**
* Finds the attachment object in the message.
* @param Message $message message instance
* @return null|\Swift_Mime_Attachment attachment instance.
*/
protected function getAttachment(Message $message)
{
$messageParts = $message->getSwiftMessage()->getChildren();
$attachment = null;
foreach ($messageParts as $part) {
if ($part instanceof \Swift_Mime_Attachment) {
$attachment = $part;
break;
}
}
return $attachment;
}
// Tests :
public function testGetSwiftMessage()
{
$message = new Message();
$this->assertTrue(is_object($message->getSwiftMessage()), 'Unable to get Swift message!');
}
/**
* @depends testGetSwiftMessage
*/
public function testSetupHeaders()
{
$charset = 'utf-16';
$subject = 'Test Subject';
$to = 'someuser@somedomain.com';
$cc = 'ccuser@somedomain.com';
$bcc = 'bccuser@somedomain.com';
$messageString = $this->createTestMessage()
->setCharset($charset)
->setSubject($subject)
->setTo($to)
->setCc($cc)
->setBcc($bcc)
->toString();
$this->assertContains('charset=' . $charset, $messageString, 'Incorrect charset!');
$this->assertContains('Subject: ' . $subject, $messageString, 'Incorrect "Subject" header!');
$this->assertContains('To: ' . $to, $messageString, 'Incorrect "To" header!');
$this->assertContains('Cc: ' . $cc, $messageString, 'Incorrect "Cc" header!');
$this->assertContains('Bcc: ' . $bcc, $messageString, 'Incorrect "Bcc" header!');
}
/**
* @depends testGetSwiftMessage
*/
public function testSetupFrom()
{
$from = 'someuser@somedomain.com';
$messageString = $this->createTestMessage()
->setFrom($from)
->toString();
$this->assertContains('From: ' . $from, $messageString, 'Incorrect "From" header!');
$this->assertContains('Reply-To: ' . $from, $messageString, 'Incorrect "Reply-To" header!');
}
/**
* @depends testGetSwiftMessage
*/
public function testSend()
{
$message = $this->createTestMessage();
$message->setTo($this->testEmailReceiver);
$message->setFrom('someuser@somedomain.com');
$message->setSubject('Yii Swift Test');
$message->setTextBody('Yii Swift Test body');
$this->assertTrue($message->send());
}
/**
* @depends testSend
*/
public function testAttachFile()
{
$message = $this->createTestMessage();
$message->setTo($this->testEmailReceiver);
$message->setFrom('someuser@somedomain.com');
$message->setSubject('Yii Swift Attach File Test');
$message->setTextBody('Yii Swift Attach File Test body');
$fileName = __FILE__;
$message->attach($fileName);
$this->assertTrue($message->send());
$attachment = $this->getAttachment($message);
$this->assertTrue(is_object($attachment), 'No attachment found!');
$this->assertContains($attachment->getFilename(), $fileName, 'Invalid file name!');
}
/**
* @depends testSend
*/
public function testAttachContent()
{
$message = $this->createTestMessage();
$message->setTo($this->testEmailReceiver);
$message->setFrom('someuser@somedomain.com');
$message->setSubject('Yii Swift Create Attachment Test');
$message->setTextBody('Yii Swift Create Attachment Test body');
$fileName = 'test.txt';
$fileContent = 'Test attachment content';
$message->attachContent($fileContent, ['fileName' => $fileName]);
$this->assertTrue($message->send());
$attachment = $this->getAttachment($message);
$this->assertTrue(is_object($attachment), 'No attachment found!');
$this->assertEquals($fileName, $attachment->getFilename(), 'Invalid file name!');
}
/**
* @depends testSend
*/
public function testEmbedFile()
{
$fileName = $this->createImageFile('embed_file.jpg', 'Embed Image File');
$message = $this->createTestMessage();
$cid = $message->embed($fileName);
$message->setTo($this->testEmailReceiver);
$message->setFrom('someuser@somedomain.com');
$message->setSubject('Yii Swift Embed File Test');
$message->setHtmlBody('Embed image: <img src="' . $cid. '" alt="pic">');
$this->assertTrue($message->send());
$attachment = $this->getAttachment($message);
$this->assertTrue(is_object($attachment), 'No attachment found!');
$this->assertContains($attachment->getFilename(), $fileName, 'Invalid file name!');
}
/**
* @depends testSend
*/
public function testEmbedContent()
{
$fileFullName = $this->createImageFile('embed_file.jpg', 'Embed Image File');
$message = $this->createTestMessage();
$fileName = basename($fileFullName);
$contentType = 'image/jpeg';
$fileContent = file_get_contents($fileFullName);
$cid = $message->embedContent($fileContent, ['fileName' => $fileName, 'contentType' => $contentType]);
$message->setTo($this->testEmailReceiver);
$message->setFrom('someuser@somedomain.com');
$message->setSubject('Yii Swift Embed File Test');
$message->setHtmlBody('Embed image: <img src="' . $cid. '" alt="pic">');
$this->assertTrue($message->send());
$attachment = $this->getAttachment($message);
$this->assertTrue(is_object($attachment), 'No attachment found!');
$this->assertEquals($fileName, $attachment->getFilename(), 'Invalid file name!');
$this->assertEquals($contentType, $attachment->getContentType(), 'Invalid content type!');
}
/**
* @depends testSend
*/
public function testSendAlternativeBody()
{
$message = $this->createTestMessage();
$message->setTo($this->testEmailReceiver);
$message->setFrom('someuser@somedomain.com');
$message->setSubject('Yii Swift Alternative Body Test');
$message->setHtmlBody('<b>Yii Swift</b> test HTML body');
$message->setTextBody('Yii Swift test plain text body');
$this->assertTrue($message->send());
$messageParts = $message->getSwiftMessage()->getChildren();
$textPresent = false;
$htmlPresent = false;
foreach ($messageParts as $part) {
if (!($part instanceof \Swift_Mime_Attachment)) {
/* @var $part \Swift_Mime_MimePart */
if ($part->getContentType() == 'text/plain') {
$textPresent = true;
}
if ($part->getContentType() == 'text/html') {
$htmlPresent = true;
}
}
}
$this->assertTrue($textPresent, 'No text!');
$this->assertTrue($htmlPresent, 'No HTML!');
}
/**
* @depends testGetSwiftMessage
*/
public function testSerialize()
{
$message = $this->createTestMessage();
$message->setTo($this->testEmailReceiver);
$message->setFrom('someuser@somedomain.com');
$message->setSubject('Yii Swift Alternative Body Test');
$message->setTextBody('Yii Swift test plain text body');
$serializedMessage = serialize($message);
$this->assertNotEmpty($serializedMessage, 'Unable to serialize message!');
$unserializedMessaage = unserialize($serializedMessage);
$this->assertEquals($message, $unserializedMessaage, 'Unable to unserialize message!');
}
}

345
tests/unit/framework/mail/BaseMailerTest.php

@ -0,0 +1,345 @@
<?php
namespace yiiunit\framework\mail;
use Yii;
use yii\base\View;
use yii\mail\BaseMailer;
use yii\mail\BaseMessage;
use yii\helpers\FileHelper;
use yiiunit\TestCase;
/**
* @group mail
*/
class BaseMailerTest extends TestCase
{
public function setUp()
{
$this->mockApplication([
'components' => [
'mail' => $this->createTestMailComponent(),
]
]);
$filePath = $this->getTestFilePath();
if (!file_exists($filePath)) {
FileHelper::createDirectory($filePath);
}
}
public function tearDown()
{
$filePath = $this->getTestFilePath();
if (file_exists($filePath)) {
FileHelper::removeDirectory($filePath);
}
}
/**
* @return string test file path.
*/
protected function getTestFilePath()
{
return Yii::getAlias('@yiiunit/runtime') . DIRECTORY_SEPARATOR . basename(get_class($this)) . '_' . getmypid();
}
/**
* @return Mailer test email component instance.
*/
protected function createTestMailComponent()
{
$component = new Mailer();
$component->viewPath = $this->getTestFilePath();
return $component;
}
/**
* @return Mailer mailer instance
*/
protected function getTestMailComponent()
{
return Yii::$app->getComponent('mail');
}
// Tests :
public function testSetupView()
{
$mailer = new Mailer();
$view = new View();
$mailer->setView($view);
$this->assertEquals($view, $mailer->getView(), 'Unable to setup view!');
$viewConfig = [
'params' => [
'param1' => 'value1',
'param2' => 'value2',
]
];
$mailer->setView($viewConfig);
$view = $mailer->getView();
$this->assertTrue(is_object($view), 'Unable to setup view via config!');
$this->assertEquals($viewConfig['params'], $view->params, 'Unable to configure view via config array!');
}
/**
* @depends testSetupView
*/
public function testGetDefaultView()
{
$mailer = new Mailer();
$view = $mailer->getView();
$this->assertTrue(is_object($view), 'Unable to get default view!');
}
public function testCreateMessage()
{
$mailer = new Mailer();
$message = $mailer->compose();
$this->assertTrue(is_object($message), 'Unable to create message instance!');
$this->assertEquals($mailer->messageClass, get_class($message), 'Invalid message class!');
}
/**
* @depends testCreateMessage
*/
public function testDefaultMessageConfig()
{
$mailer = new Mailer();
$notPropertyConfig = [
'charset' => 'utf-16',
'from' => 'from@domain.com',
'to' => 'to@domain.com',
'cc' => 'cc@domain.com',
'bcc' => 'bcc@domain.com',
'subject' => 'Test subject',
'textBody' => 'Test text body',
'htmlBody' => 'Test HTML body',
];
$propertyConfig = [
'id' => 'test-id',
'encoding' => 'test-encoding',
];
$messageConfig = array_merge($notPropertyConfig, $propertyConfig);
$mailer->messageConfig = $messageConfig;
$message = $mailer->compose();
foreach ($notPropertyConfig as $name => $value) {
$this->assertEquals($value, $message->{'_' . $name});
}
foreach ($propertyConfig as $name => $value) {
$this->assertEquals($value, $message->$name);
}
}
/**
* @depends testGetDefaultView
*/
public function testRender()
{
$mailer = $this->getTestMailComponent();
$viewName = 'test_view';
$viewFileName = $this->getTestFilePath() . DIRECTORY_SEPARATOR . $viewName . '.php';
$viewFileContent = '<?php echo $testParam; ?>';
file_put_contents($viewFileName, $viewFileContent);
$params = [
'testParam' => 'test output'
];
$renderResult = $mailer->render($viewName, $params);
$this->assertEquals($params['testParam'], $renderResult);
}
/**
* @depends testRender
*/
public function testRenderLayout()
{
$mailer = $this->getTestMailComponent();
$filePath = $this->getTestFilePath();
$viewName = 'test_view';
$viewFileName = $filePath . DIRECTORY_SEPARATOR . $viewName . '.php';
$viewFileContent = 'view file content';
file_put_contents($viewFileName, $viewFileContent);
$layoutName = 'test_layout';
$layoutFileName = $filePath . DIRECTORY_SEPARATOR . $layoutName . '.php';
$layoutFileContent = 'Begin Layout <?php echo $content; ?> End Layout';
file_put_contents($layoutFileName, $layoutFileContent);
$renderResult = $mailer->render($viewName, [], $layoutName);
$this->assertEquals('Begin Layout ' . $viewFileContent . ' End Layout', $renderResult);
}
/**
* @depends testCreateMessage
* @depends testRender
*/
public function testCompose()
{
$mailer = $this->getTestMailComponent();
$mailer->htmlLayout = false;
$mailer->textLayout = false;
$htmlViewName = 'test_html_view';
$htmlViewFileName = $this->getTestFilePath() . DIRECTORY_SEPARATOR . $htmlViewName . '.php';
$htmlViewFileContent = 'HTML <b>view file</b> content';
file_put_contents($htmlViewFileName, $htmlViewFileContent);
$textViewName = 'test_text_view';
$textViewFileName = $this->getTestFilePath() . DIRECTORY_SEPARATOR . $textViewName . '.php';
$textViewFileContent = 'Plain text view file content';
file_put_contents($textViewFileName, $textViewFileContent);
$message = $mailer->compose([
'html' => $htmlViewName,
'text' => $textViewName,
]);
$this->assertEquals($htmlViewFileContent, $message->_htmlBody, 'Unable to render html!');
$this->assertEquals($textViewFileContent, $message->_textBody, 'Unable to render text!');
$message = $mailer->compose($htmlViewName);
$this->assertEquals($htmlViewFileContent, $message->_htmlBody, 'Unable to render html by direct view!');
$this->assertEquals(strip_tags($htmlViewFileContent), $message->_textBody, 'Unable to render text by direct view!');
}
}
/**
* Test Mailer class
*/
class Mailer extends BaseMailer
{
public $messageClass = 'yiiunit\framework\mail\Message';
public $sentMessages = [];
public function send($message)
{
$this->sentMessages[] = $message;
}
}
/**
* Test Message class
*/
class Message extends BaseMessage
{
public $id;
public $encoding;
public $_charset;
public $_from;
public $_replyTo;
public $_to;
public $_cc;
public $_bcc;
public $_subject;
public $_textBody;
public $_htmlBody;
public function getCharset()
{
return $this->_charset;
}
public function setCharset($charset)
{
$this->_charset = $charset;
return $this;
}
public function getFrom()
{
return $this->_from;
}
public function setFrom($from)
{
$this->_from = $from;
return $this;
}
public function getTo()
{
return $this->_to;
}
public function setTo($to)
{
$this->_to = $to;
return $this;
}
public function getCc()
{
return $this->_cc;
}
public function setCc($cc)
{
$this->_cc = $cc;
return $this;
}
public function getBcc()
{
return $this->_bcc;
}
public function setBcc($bcc)
{
$this->_bcc = $bcc;
return $this;
}
public function getSubject()
{
return $this->_subject;
}
public function setSubject($subject)
{
$this->_subject = $subject;
return $this;
}
public function getReplyTo()
{
return $this->_replyTo;
}
public function setReplyTo($replyTo)
{
$this->_replyTo = $replyTo;
return $this;
}
public function setTextBody($text)
{
$this->_textBody = $text;
return $this;
}
public function setHtmlBody($html)
{
$this->_htmlBody = $html;
return $this;
}
public function attachContent($content, array $options = []) {}
public function attach($fileName, array $options = []) {}
public function embed($fileName, array $options = []) {}
public function embedContent($content, array $options = []) {}
public function toString()
{
return get_class($this);
}
}

136
tests/unit/framework/mail/BaseMessageTest.php

@ -0,0 +1,136 @@
<?php
namespace yiiunit\framework\mail;
use Yii;
use yii\mail\BaseMailer;
use yii\mail\BaseMessage;
use yiiunit\TestCase;
/**
* @group mail
*/
class BaseMessageTest extends TestCase
{
public function setUp()
{
$this->mockApplication([
'components' => [
'mail' => $this->createTestEmailComponent()
]
]);
}
/**
* @return Mailer test email component instance.
*/
protected function createTestEmailComponent()
{
$component = new TestMailer();
return $component;
}
/**
* @return TestMailer mailer instance.
*/
protected function getMailer()
{
return Yii::$app->getComponent('mail');
}
// Tests :
public function testGetMailer()
{
$mailer = $this->getMailer();
$message = $mailer->compose();
$this->assertEquals($mailer, $message->getMailer());
}
public function testSend()
{
$mailer = $this->getMailer();
$message = $mailer->compose();
$message->send();
$this->assertEquals($message, $mailer->sentMessages[0], 'Unable to send message!');
}
public function testToString()
{
$mailer = $this->getMailer();
$message = $mailer->compose();
$this->assertEquals($message->toString(), '' . $message);
}
}
/**
* Test Mailer class
*/
class TestMailer extends BaseMailer
{
public $messageClass = 'yiiunit\framework\mail\TestMessage';
public $sentMessages = array();
public function send($message)
{
$this->sentMessages[] = $message;
}
}
/**
* Test Message class
*/
class TestMessage extends BaseMessage
{
public $text;
public $html;
public function getCharset() {return '';}
public function setCharset($charset) {}
public function getFrom() {return '';}
public function setFrom($from) {}
public function getReplyTo() {return '';}
public function setReplyTo($replyTo) {}
public function getTo() {return '';}
public function setTo($to) {}
public function getCc() {return '';}
public function setCc($cc) {}
public function getBcc() {return '';}
public function setBcc($bcc) {}
public function getSubject() {return '';}
public function setSubject($subject) {}
public function setTextBody($text) {
$this->text = $text;
}
public function setHtmlBody($html) {
$this->html = $html;
}
public function attachContent($content, array $options = []) {}
public function attach($fileName, array $options = []) {}
public function embed($fileName, array $options = []) {}
public function embedContent($content, array $options = []) {}
public function toString()
{
return get_class($this);
}
}
Loading…
Cancel
Save