Commit a0384498 by Klimov Paul

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

parents 9da7a80f 05272b71
...@@ -78,9 +78,43 @@ directory and Yii will be able to autoload any class in this library. ...@@ -78,9 +78,43 @@ directory and Yii will be able to autoload any class in this library.
Autoloading Autoloading
----------- -----------
TBD All classes, interfaces and traits are loaded automatically at the moment they are used. There's no need to use
`include` or `require`. It is, as well, true for Composer-loaded packages and Yii extensions.
Autoloader works according to [PSR-0](). That means namespaces and class, interface and trait
names should correspond to file system paths except root namespace path that is defined by an alias.
For example, if standard alias `@app` refers to `/var/www/example.com/` then `\app\models\User` will be loaded from
`/var/www/example.com/app/models/User.php`.
Custom alias may be added using the following code:
```php
Yii::setAlias('shared', realpath('~/src/shared'));
```
Additional autoloaders may be registered using standard PHP `spl_autoload_register`.
Helper classes Helper classes
-------------- --------------
TDB Helper class typically contains static methods only and used as follows:
\ No newline at end of file
```php
use \yii\helpers\Html;
echo Html::encode('Test > test');
```
There are several classes provided by framework:
- ArrayHelper
- Console
- FileHelper
- Html
- HtmlPurifier
- Inflector
- Json
- Markdown
- Security
- StringHelper
- VarDumper
\ No newline at end of file
...@@ -21,7 +21,11 @@ console applications it's `yii`. Both are doing nearly the same job: ...@@ -21,7 +21,11 @@ console applications it's `yii`. Both are doing nearly the same job:
5. Creating new application instance using `$config` and running it. 5. Creating new application instance using `$config` and running it.
The Bootstrap file is not the part of framework but your application so it's OK to adjust it to fit your application. Typical The Bootstrap file is not the part of framework but your application so it's OK to adjust it to fit your application. Typical
adjustments are the value of `YII_DEBUG` that should never be `true` on production and the way config is read. adjustments are the value of `YII_DEBUG` that should never be `true` on production and the way config is read:
```php
defined('YII_DEBUG') or define('YII_DEBUG', false);
```
Configuring application instance Configuring application instance
-------------------------------- --------------------------------
......
...@@ -1385,6 +1385,8 @@ abstract class ActiveRecord extends Model ...@@ -1385,6 +1385,8 @@ abstract class ActiveRecord extends Model
$this->populateRelation($offset, $item); $this->populateRelation($offset, $item);
return; return;
} }
} catch (InvalidParamException $e) {
// shut down exception : has getter, but not relation
} catch (UnknownMethodException $e) { } catch (UnknownMethodException $e) {
throw $e->getPrevious(); throw $e->getPrevious();
} }
......
...@@ -519,12 +519,14 @@ class BaseYii ...@@ -519,12 +519,14 @@ class BaseYii
* Configures an object with the initial property values. * Configures an object with the initial property values.
* @param object $object the object to be configured * @param object $object the object to be configured
* @param array $properties the property initial values given in terms of name-value pairs. * @param array $properties the property initial values given in terms of name-value pairs.
* @return object the object itself
*/ */
public static function configure($object, $properties) public static function configure($object, $properties)
{ {
foreach ($properties as $name => $value) { foreach ($properties as $name => $value) {
$object->$name = $value; $object->$name = $value;
} }
return $object;
} }
/** /**
......
...@@ -459,6 +459,15 @@ abstract class Application extends Module ...@@ -459,6 +459,15 @@ abstract class Application extends Module
} }
/** /**
* Returns the mailer component.
* @return \yii\mail\MailerInterface the mailer interface
*/
public function getMail()
{
return $this->getComponent('mail');
}
/**
* Returns the auth manager for this application. * Returns the auth manager for this application.
* @return \yii\rbac\Manager the auth manager for this application. * @return \yii\rbac\Manager the auth manager for this application.
*/ */
......
...@@ -33,7 +33,7 @@ use yii\helpers\ArrayHelper; ...@@ -33,7 +33,7 @@ use yii\helpers\ArrayHelper;
* *
* ~~~ * ~~~
* CREATE TABLE tbl_migration ( * CREATE TABLE tbl_migration (
* version varchar(255) PRIMARY KEY, * version varchar(180) PRIMARY KEY,
* apply_time integer * apply_time integer
* ) * )
* ~~~ * ~~~
......
...@@ -50,6 +50,28 @@ class Schema extends \yii\db\Schema ...@@ -50,6 +50,28 @@ class Schema extends \yii\db\Schema
]; ];
/** /**
* Quotes a table name for use in a query.
* A simple table name has no schema prefix.
* @param string $name table name
* @return string the properly quoted table name
*/
public function quoteSimpleTableName($name)
{
return strpos($name, "`") !== false ? $name : "`" . $name . "`";
}
/**
* Quotes a column name for use in a query.
* A simple column name has no prefix.
* @param string $name column name
* @return string the properly quoted column name
*/
public function quoteSimpleColumnName($name)
{
return strpos($name, '`') !== false || $name === '*' ? $name : '`' . $name . '`';
}
/**
* Creates a query builder for the MySQL database. * Creates a query builder for the MySQL database.
* This method may be overridden by child classes to create a DBMS-specific query builder. * This method may be overridden by child classes to create a DBMS-specific query builder.
* @return QueryBuilder query builder instance * @return QueryBuilder query builder instance
......
...@@ -111,10 +111,9 @@ class BaseVarDumper ...@@ -111,10 +111,9 @@ class BaseVarDumper
} else { } else {
$id = array_push(self::$_objects, $var); $id = array_push(self::$_objects, $var);
$className = get_class($var); $className = get_class($var);
$members = (array)$var;
$spaces = str_repeat(' ', $level * 4); $spaces = str_repeat(' ', $level * 4);
self::$_output .= "$className#$id\n" . $spaces . '('; self::$_output .= "$className#$id\n" . $spaces . '(';
foreach ($members as $key => $value) { foreach ((array)$var as $key => $value) {
$keyDisplay = strtr(trim($key), ["\0" => ':']); $keyDisplay = strtr(trim($key), ["\0" => ':']);
self::$_output .= "\n" . $spaces . " [$keyDisplay] => "; self::$_output .= "\n" . $spaces . " [$keyDisplay] => ";
self::dumpInternal($value, $level + 1); self::dumpInternal($value, $level + 1);
......
...@@ -7,6 +7,10 @@ ...@@ -7,6 +7,10 @@
namespace yii\log; namespace yii\log;
use Yii;
use yii\base\InvalidConfigException;
use yii\mail\MailerInterface;
/** /**
* EmailTarget sends selected log messages to the specified email addresses. * EmailTarget sends selected log messages to the specified email addresses.
* *
...@@ -20,51 +24,57 @@ namespace yii\log; ...@@ -20,51 +24,57 @@ namespace yii\log;
class EmailTarget extends Target class EmailTarget extends Target
{ {
/** /**
* @var array list of destination email addresses. * @var array the configuration array for creating a [[\yii\mail\MessageInterface|message]] object.
*/ * Note that the "to" option must be set, which specifies the destination email address(es).
public $emails = [];
/**
* @var string email subject
*/ */
public $subject; public $message = [];
/** /**
* @var string email sent-from address * @var MailerInterface|string the mailer object or the application component ID of the mailer object.
* After the EmailTarget object is created, if you want to change this property, you should only assign it
* with a mailer object.
*/ */
public $sentFrom; public $mail = 'mail';
/** /**
* @var array list of additional headers to use when sending an email. * @inheritdoc
*/ */
public $headers = []; public function init()
{
parent::init();
if (empty($this->message['to'])) {
throw new InvalidConfigException('The "to" option must be set for EmailTarget::message.');
}
if (empty($this->message['subject'])) {
$this->message['subject'] = Yii::t('yii', 'Application Log');
}
if (is_string($this->mail)) {
$this->mail = Yii::$app->getComponent($this->mail);
}
if (!$this->mail instanceof MailerInterface) {
throw new InvalidConfigException("EmailTarget::mailer must be either a mailer object or the application component ID of a mailer object.");
}
}
/** /**
* Sends log messages to specified email addresses. * Sends log messages to specified email addresses.
*/ */
public function export() public function export()
{ {
$body = ''; $messages = array_map([$this, 'formatMessage'], $this->messages);
foreach ($this->messages as $message) { $body = wordwrap(implode("\n", $messages), 70);
$body .= $this->formatMessage($message); $this->composeMessage($body)->send($this->mail);
}
$body = wordwrap($body, 70);
$subject = $this->subject === null ? \Yii::t('yii', 'Application Log') : $this->subject;
foreach ($this->emails as $email) {
$this->sendEmail($subject, $body, $email, $this->sentFrom, $this->headers);
}
} }
/** /**
* Sends an email. * Composes a mail message with the given body content.
* @param string $subject email subject * @param string $body the body content
* @param string $body email body * @return \yii\mail\MessageInterface $message
* @param string $sentTo sent-to email address
* @param string $sentFrom sent-from email address
* @param array $headers additional headers to be used when sending the email
*/ */
protected function sendEmail($subject, $body, $sentTo, $sentFrom, $headers) protected function composeMessage($body)
{ {
if ($sentFrom !== null) { $message = $this->mail->compose();
$headers[] = "From: {$sentFrom}"; Yii::configure($message, $this->message);
} $message->setTextBody($body);
mail($sentTo, $subject, $body, implode("\r\n", $headers)); return $message;
} }
} }
...@@ -233,6 +233,6 @@ abstract class Target extends Component ...@@ -233,6 +233,6 @@ abstract class Target extends Component
$text = var_export($text, true); $text = var_export($text, true);
} }
$ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1'; $ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1';
return date('Y/m/d H:i:s', $timestamp) . " [$ip] [$level] [$category] $text\n"; return date('Y/m/d H:i:s', $timestamp) . " [$ip] [$level] [$category] $text";
} }
} }
...@@ -26,19 +26,14 @@ use Yii; ...@@ -26,19 +26,14 @@ use Yii;
abstract class BaseMessage extends Object implements MessageInterface abstract class BaseMessage extends Object implements MessageInterface
{ {
/** /**
* @return MailerInterface the mailer component
*/
public function getMailer()
{
return Yii::$app->getComponent('mail');
}
/**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function send() public function send(MailerInterface $mailer = null)
{ {
return $this->getMailer()->send($this); if ($mailer === null) {
$mailer = Yii::$app->getMail();
}
return $mailer->send($this);
} }
/** /**
......
...@@ -204,9 +204,11 @@ interface MessageInterface ...@@ -204,9 +204,11 @@ interface MessageInterface
/** /**
* Sends this email message. * Sends this email message.
* @param MailerInterface $mailer the mailer that should be used to send this message.
* If null, the "mail" application component will be used instead.
* @return boolean whether this message is sent successfully. * @return boolean whether this message is sent successfully.
*/ */
public function send(); public function send(MailerInterface $mailer = null);
/** /**
* Returns string representation of this message. * Returns string representation of this message.
......
...@@ -79,10 +79,10 @@ class ActiveRecordTest extends SphinxTestCase ...@@ -79,10 +79,10 @@ class ActiveRecordTest extends SphinxTestCase
// asArray // asArray
$article = ArticleIndex::find()->where('id=2')->asArray()->one(); $article = ArticleIndex::find()->where('id=2')->asArray()->one();
unset($article['add_date']);
$this->assertEquals([ $this->assertEquals([
'id' => '2', 'id' => '2',
'author_id' => '2', 'author_id' => '2',
'add_date' => '1384466400',
'tag' => '3,4', 'tag' => '3,4',
], $article); ], $article);
......
...@@ -56,7 +56,9 @@ class MessageTest extends VendorTestCase ...@@ -56,7 +56,9 @@ class MessageTest extends VendorTestCase
*/ */
protected function createTestEmailComponent() protected function createTestEmailComponent()
{ {
$component = new Mailer(); $component = new Mailer([
'useFileTransport' => true,
]);
return $component; return $component;
} }
......
...@@ -17,6 +17,6 @@ class SqliteCommandTest extends CommandTest ...@@ -17,6 +17,6 @@ class SqliteCommandTest extends CommandTest
$sql = 'SELECT [[id]], [[t.name]] FROM {{tbl_customer}} t'; $sql = 'SELECT [[id]], [[t.name]] FROM {{tbl_customer}} t';
$command = $db->createCommand($sql); $command = $db->createCommand($sql);
$this->assertEquals("SELECT \"id\", 't'.\"name\" FROM 'tbl_customer' t", $command->sql); $this->assertEquals("SELECT `id`, `t`.`name` FROM `tbl_customer` t", $command->sql);
} }
} }
...@@ -30,8 +30,8 @@ class SqliteConnectionTest extends ConnectionTest ...@@ -30,8 +30,8 @@ class SqliteConnectionTest extends ConnectionTest
public function testQuoteTableName() public function testQuoteTableName()
{ {
$connection = $this->getConnection(false); $connection = $this->getConnection(false);
$this->assertEquals("'table'", $connection->quoteTableName('table')); $this->assertEquals("`table`", $connection->quoteTableName('table'));
$this->assertEquals("'schema'.'table'", $connection->quoteTableName('schema.table')); $this->assertEquals("`schema`.`table`", $connection->quoteTableName('schema.table'));
$this->assertEquals('{{table}}', $connection->quoteTableName('{{table}}')); $this->assertEquals('{{table}}', $connection->quoteTableName('{{table}}'));
$this->assertEquals('(table)', $connection->quoteTableName('(table)')); $this->assertEquals('(table)', $connection->quoteTableName('(table)'));
} }
...@@ -39,8 +39,8 @@ class SqliteConnectionTest extends ConnectionTest ...@@ -39,8 +39,8 @@ class SqliteConnectionTest extends ConnectionTest
public function testQuoteColumnName() public function testQuoteColumnName()
{ {
$connection = $this->getConnection(false); $connection = $this->getConnection(false);
$this->assertEquals('"column"', $connection->quoteColumnName('column')); $this->assertEquals('`column`', $connection->quoteColumnName('column'));
$this->assertEquals("'table'.\"column\"", $connection->quoteColumnName('table.column')); $this->assertEquals("`table`.`column`", $connection->quoteColumnName('table.column'));
$this->assertEquals('[[column]]', $connection->quoteColumnName('[[column]]')); $this->assertEquals('[[column]]', $connection->quoteColumnName('[[column]]'));
$this->assertEquals('{{column}}', $connection->quoteColumnName('{{column}}')); $this->assertEquals('{{column}}', $connection->quoteColumnName('{{column}}'));
$this->assertEquals('(column)', $connection->quoteColumnName('(column)')); $this->assertEquals('(column)', $connection->quoteColumnName('(column)'));
......
...@@ -85,6 +85,6 @@ class SqliteQueryBuilderTest extends QueryBuilderTest ...@@ -85,6 +85,6 @@ class SqliteQueryBuilderTest extends QueryBuilderTest
public function testBatchInsert() public function testBatchInsert()
{ {
$sql = $this->getQueryBuilder()->batchInsert('{{tbl_customer}} t', ['t.id','t.name'], array(array(1,'a'), array(2,'b'))); $sql = $this->getQueryBuilder()->batchInsert('{{tbl_customer}} t', ['t.id','t.name'], array(array(1,'a'), array(2,'b')));
$this->assertEquals("INSERT INTO {{tbl_customer}} t ('t'.\"id\", 't'.\"name\") SELECT 1, 'a' UNION ALL 2, 'b'", $sql); $this->assertEquals("INSERT INTO {{tbl_customer}} t (`t`.`id`, `t`.`name`) SELECT 1, 'a' UNION ALL 2, 'b'", $sql);
} }
} }
...@@ -40,18 +40,11 @@ class BaseMessageTest extends TestCase ...@@ -40,18 +40,11 @@ class BaseMessageTest extends TestCase
// Tests : // Tests :
public function testGetMailer()
{
$mailer = $this->getMailer();
$message = $mailer->compose();
$this->assertEquals($mailer, $message->getMailer());
}
public function testSend() public function testSend()
{ {
$mailer = $this->getMailer(); $mailer = $this->getMailer();
$message = $mailer->compose(); $message = $mailer->compose();
$message->send(); $message->send($mailer);
$this->assertEquals($message, $mailer->sentMessages[0], 'Unable to send message!'); $this->assertEquals($message, $mailer->sentMessages[0], 'Unable to send message!');
} }
......
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