From 3dbb3d40ddc68c67e5cada32fc09975cb66c3179 Mon Sep 17 00:00:00 2001 From: Paul Klimov Date: Thu, 28 Nov 2013 11:34:13 +0200 Subject: [PATCH 01/10] Sphinx unit tests fixed. --- extensions/sphinx/ActiveRecord.php | 2 ++ tests/unit/extensions/sphinx/ActiveRecordTest.php | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/extensions/sphinx/ActiveRecord.php b/extensions/sphinx/ActiveRecord.php index 9cf03ff..206c340 100644 --- a/extensions/sphinx/ActiveRecord.php +++ b/extensions/sphinx/ActiveRecord.php @@ -1385,6 +1385,8 @@ abstract class ActiveRecord extends Model $this->populateRelation($offset, $item); return; } + } catch (InvalidParamException $e) { + // shut down exception : has getter, but not relation } catch (UnknownMethodException $e) { throw $e->getPrevious(); } diff --git a/tests/unit/extensions/sphinx/ActiveRecordTest.php b/tests/unit/extensions/sphinx/ActiveRecordTest.php index 0bb9dbb..b167b9e 100644 --- a/tests/unit/extensions/sphinx/ActiveRecordTest.php +++ b/tests/unit/extensions/sphinx/ActiveRecordTest.php @@ -79,10 +79,10 @@ class ActiveRecordTest extends SphinxTestCase // asArray $article = ArticleIndex::find()->where('id=2')->asArray()->one(); + unset($article['add_date']); $this->assertEquals([ 'id' => '2', 'author_id' => '2', - 'add_date' => '1384466400', 'tag' => '3,4', ], $article); From f1452d3070a977e70c3e5584d6cdf08719419805 Mon Sep 17 00:00:00 2001 From: slavcodev Date: Thu, 28 Nov 2013 13:21:30 +0200 Subject: [PATCH 02/10] Remove extra var --- framework/yii/helpers/BaseVarDumper.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/framework/yii/helpers/BaseVarDumper.php b/framework/yii/helpers/BaseVarDumper.php index b11757b..36b739c 100644 --- a/framework/yii/helpers/BaseVarDumper.php +++ b/framework/yii/helpers/BaseVarDumper.php @@ -111,10 +111,9 @@ class BaseVarDumper } else { $id = array_push(self::$_objects, $var); $className = get_class($var); - $members = (array)$var; $spaces = str_repeat(' ', $level * 4); self::$_output .= "$className#$id\n" . $spaces . '('; - foreach ($members as $key => $value) { + foreach ((array)$var as $key => $value) { $keyDisplay = strtr(trim($key), ["\0" => ':']); self::$_output .= "\n" . $spaces . " [$keyDisplay] => "; self::dumpInternal($value, $level + 1); From ce4d7450be1a16f2c2549ede011526ecd30068e6 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Thu, 28 Nov 2013 15:53:17 +0400 Subject: [PATCH 03/10] Docs on autoloading and helpers --- docs/guide/basics.md | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/docs/guide/basics.md b/docs/guide/basics.md index 914797c..2fa8f59 100644 --- a/docs/guide/basics.md +++ b/docs/guide/basics.md @@ -78,9 +78,43 @@ directory and Yii will be able to autoload any class in this library. 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 -------------- -TDB \ No newline at end of file +Helper class typically contains static methods only and used as follows: + +```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 From 5d9cd76a7112b532e97be42352ef9c0ff809f0e9 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Thu, 28 Nov 2013 16:03:45 +0400 Subject: [PATCH 04/10] Provided example setting YII_DEBUG to false --- docs/guide/configuration.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/guide/configuration.md b/docs/guide/configuration.md index 5f1d8e0..11f2470 100644 --- a/docs/guide/configuration.md +++ b/docs/guide/configuration.md @@ -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. 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 -------------------------------- From 0390a998333b10755f53013999a0475dc299afea Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Thu, 28 Nov 2013 09:04:16 -0500 Subject: [PATCH 05/10] Use backquotes to quote column and table names for sqlite (related with #1318) --- framework/yii/db/sqlite/Schema.php | 22 ++++++++++++++++++++++ .../unit/framework/db/sqlite/SqliteCommandTest.php | 2 +- .../framework/db/sqlite/SqliteConnectionTest.php | 8 ++++---- .../framework/db/sqlite/SqliteQueryBuilderTest.php | 2 +- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/framework/yii/db/sqlite/Schema.php b/framework/yii/db/sqlite/Schema.php index 38fbf3a..8633650 100644 --- a/framework/yii/db/sqlite/Schema.php +++ b/framework/yii/db/sqlite/Schema.php @@ -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. * This method may be overridden by child classes to create a DBMS-specific query builder. * @return QueryBuilder query builder instance diff --git a/tests/unit/framework/db/sqlite/SqliteCommandTest.php b/tests/unit/framework/db/sqlite/SqliteCommandTest.php index 1f9ddc2..c8cb35c 100644 --- a/tests/unit/framework/db/sqlite/SqliteCommandTest.php +++ b/tests/unit/framework/db/sqlite/SqliteCommandTest.php @@ -17,6 +17,6 @@ class SqliteCommandTest extends CommandTest $sql = 'SELECT [[id]], [[t.name]] FROM {{tbl_customer}} t'; $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); } } diff --git a/tests/unit/framework/db/sqlite/SqliteConnectionTest.php b/tests/unit/framework/db/sqlite/SqliteConnectionTest.php index e1a2961..ea74f81 100644 --- a/tests/unit/framework/db/sqlite/SqliteConnectionTest.php +++ b/tests/unit/framework/db/sqlite/SqliteConnectionTest.php @@ -30,8 +30,8 @@ class SqliteConnectionTest extends ConnectionTest public function testQuoteTableName() { $connection = $this->getConnection(false); - $this->assertEquals("'table'", $connection->quoteTableName('table')); - $this->assertEquals("'schema'.'table'", $connection->quoteTableName('schema.table')); + $this->assertEquals("`table`", $connection->quoteTableName('table')); + $this->assertEquals("`schema`.`table`", $connection->quoteTableName('schema.table')); $this->assertEquals('{{table}}', $connection->quoteTableName('{{table}}')); $this->assertEquals('(table)', $connection->quoteTableName('(table)')); } @@ -39,8 +39,8 @@ class SqliteConnectionTest extends ConnectionTest public function testQuoteColumnName() { $connection = $this->getConnection(false); - $this->assertEquals('"column"', $connection->quoteColumnName('column')); - $this->assertEquals("'table'.\"column\"", $connection->quoteColumnName('table.column')); + $this->assertEquals('`column`', $connection->quoteColumnName('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)')); diff --git a/tests/unit/framework/db/sqlite/SqliteQueryBuilderTest.php b/tests/unit/framework/db/sqlite/SqliteQueryBuilderTest.php index 67cae28..a2408a6 100644 --- a/tests/unit/framework/db/sqlite/SqliteQueryBuilderTest.php +++ b/tests/unit/framework/db/sqlite/SqliteQueryBuilderTest.php @@ -85,6 +85,6 @@ class SqliteQueryBuilderTest extends QueryBuilderTest public function testBatchInsert() { $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); } } From d6f97ff4c17799e6d953038c3ff84a9b88e9d725 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Thu, 28 Nov 2013 09:08:02 -0500 Subject: [PATCH 06/10] Added Application::getMail(). --- framework/yii/base/Application.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/framework/yii/base/Application.php b/framework/yii/base/Application.php index 4f2bee2..48b526c 100644 --- a/framework/yii/base/Application.php +++ b/framework/yii/base/Application.php @@ -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. * @return \yii\rbac\Manager the auth manager for this application. */ From c22409e397fa724de5ce7e0e4582ca1093a6f2e0 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Thu, 28 Nov 2013 09:22:08 -0500 Subject: [PATCH 07/10] Fixed test break using file transport. --- tests/unit/VendorTestCase.php | 2 +- tests/unit/extensions/swiftmailer/MessageTest.php | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/unit/VendorTestCase.php b/tests/unit/VendorTestCase.php index 2002cb3..71a2648 100644 --- a/tests/unit/VendorTestCase.php +++ b/tests/unit/VendorTestCase.php @@ -27,4 +27,4 @@ class VendorTestCase extends TestCase throw new NotSupportedException("Vendor autoload file '{$vendorAutoload}' is missing."); } } -} \ No newline at end of file +} diff --git a/tests/unit/extensions/swiftmailer/MessageTest.php b/tests/unit/extensions/swiftmailer/MessageTest.php index 1f55cc6..31a5c43 100644 --- a/tests/unit/extensions/swiftmailer/MessageTest.php +++ b/tests/unit/extensions/swiftmailer/MessageTest.php @@ -56,7 +56,9 @@ class MessageTest extends VendorTestCase */ protected function createTestEmailComponent() { - $component = new Mailer(); + $component = new Mailer([ + 'useFileTransport' => true, + ]); return $component; } From eb3b2f45bcc2464b0e6fc8fcc9d782f110c92ed9 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Thu, 28 Nov 2013 09:46:20 -0500 Subject: [PATCH 08/10] refactored EmailTarget with the new mailer interfaces. --- framework/yii/BaseYii.php | 2 ++ framework/yii/log/EmailTarget.php | 70 ++++++++++++++++++++++----------------- framework/yii/log/Target.php | 2 +- 3 files changed, 43 insertions(+), 31 deletions(-) diff --git a/framework/yii/BaseYii.php b/framework/yii/BaseYii.php index ee49c8e..e56d410 100644 --- a/framework/yii/BaseYii.php +++ b/framework/yii/BaseYii.php @@ -519,12 +519,14 @@ class BaseYii * Configures an object with the initial property values. * @param object $object the object to be configured * @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) { foreach ($properties as $name => $value) { $object->$name = $value; } + return $object; } /** diff --git a/framework/yii/log/EmailTarget.php b/framework/yii/log/EmailTarget.php index 8ca3d97..69019e3 100644 --- a/framework/yii/log/EmailTarget.php +++ b/framework/yii/log/EmailTarget.php @@ -7,6 +7,10 @@ namespace yii\log; +use Yii; +use yii\base\InvalidConfigException; +use yii\mail\MailerInterface; + /** * EmailTarget sends selected log messages to the specified email addresses. * @@ -20,51 +24,57 @@ namespace yii\log; class EmailTarget extends Target { /** - * @var array list of destination email addresses. - */ - public $emails = []; - /** - * @var string email subject + * @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 $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. */ public function export() { - $body = ''; - foreach ($this->messages as $message) { - $body .= $this->formatMessage($message); - } - $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); - } + $message = $this->mail->compose(); + Yii::configure($message, $this->message); + $this->composeMessage($message); + $this->mail->send($message); } /** - * Sends an email. - * @param string $subject email subject - * @param string $body email body - * @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 + * Composes the given mail message with body content. + * The default implementation fills the text body of the message with the log messages. + * @param \yii\mail\MessageInterface $message */ - protected function sendEmail($subject, $body, $sentTo, $sentFrom, $headers) + protected function composeMessage($message) { - if ($sentFrom !== null) { - $headers[] = "From: {$sentFrom}"; - } - mail($sentTo, $subject, $body, implode("\r\n", $headers)); + $messages = array_map([$this, 'formatMessage'], $this->messages); + $body = wordwrap(implode("\n", $messages), 70); + $message->setTextBody($body); } } diff --git a/framework/yii/log/Target.php b/framework/yii/log/Target.php index c9d5d97..d5d8e5b 100644 --- a/framework/yii/log/Target.php +++ b/framework/yii/log/Target.php @@ -233,6 +233,6 @@ abstract class Target extends Component $text = var_export($text, true); } $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"; } } From bd8f74cf120aed98a1b523491da9d0d9cbb5215e Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Thu, 28 Nov 2013 09:55:35 -0500 Subject: [PATCH 09/10] Refactored MessageInterface::send(). --- framework/yii/log/EmailTarget.php | 20 ++++++++++---------- framework/yii/mail/BaseMessage.php | 15 +++++---------- framework/yii/mail/MessageInterface.php | 4 +++- tests/unit/framework/mail/BaseMessageTest.php | 9 +-------- 4 files changed, 19 insertions(+), 29 deletions(-) diff --git a/framework/yii/log/EmailTarget.php b/framework/yii/log/EmailTarget.php index 69019e3..95234d2 100644 --- a/framework/yii/log/EmailTarget.php +++ b/framework/yii/log/EmailTarget.php @@ -60,21 +60,21 @@ class EmailTarget extends Target */ public function export() { - $message = $this->mail->compose(); - Yii::configure($message, $this->message); - $this->composeMessage($message); - $this->mail->send($message); + $messages = array_map([$this, 'formatMessage'], $this->messages); + $body = wordwrap(implode("\n", $messages), 70); + $this->composeMessage($body)->send($this->mail); } /** - * Composes the given mail message with body content. - * The default implementation fills the text body of the message with the log messages. - * @param \yii\mail\MessageInterface $message + * Composes a mail message with the given body content. + * @param string $body the body content + * @return \yii\mail\MessageInterface $message */ - protected function composeMessage($message) + protected function composeMessage($body) { - $messages = array_map([$this, 'formatMessage'], $this->messages); - $body = wordwrap(implode("\n", $messages), 70); + $message = $this->mail->compose(); + Yii::configure($message, $this->message); $message->setTextBody($body); + return $message; } } diff --git a/framework/yii/mail/BaseMessage.php b/framework/yii/mail/BaseMessage.php index 208840a..f95b4fb 100644 --- a/framework/yii/mail/BaseMessage.php +++ b/framework/yii/mail/BaseMessage.php @@ -26,19 +26,14 @@ use Yii; abstract class BaseMessage extends Object implements MessageInterface { /** - * @return MailerInterface the mailer component - */ - public function getMailer() - { - return Yii::$app->getComponent('mail'); - } - - /** * {@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); } /** diff --git a/framework/yii/mail/MessageInterface.php b/framework/yii/mail/MessageInterface.php index eba9064..d70d40f 100644 --- a/framework/yii/mail/MessageInterface.php +++ b/framework/yii/mail/MessageInterface.php @@ -204,9 +204,11 @@ interface MessageInterface /** * 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. */ - public function send(); + public function send(MailerInterface $mailer = null); /** * Returns string representation of this message. diff --git a/tests/unit/framework/mail/BaseMessageTest.php b/tests/unit/framework/mail/BaseMessageTest.php index 35fa549..e9ed49e 100644 --- a/tests/unit/framework/mail/BaseMessageTest.php +++ b/tests/unit/framework/mail/BaseMessageTest.php @@ -40,18 +40,11 @@ class BaseMessageTest extends TestCase // 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(); + $message->send($mailer); $this->assertEquals($message, $mailer->sentMessages[0], 'Unable to send message!'); } From 05272b71208bceaa83923e6b71841d39a41e0055 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Thu, 28 Nov 2013 12:34:10 -0500 Subject: [PATCH 10/10] doc fix. --- framework/yii/console/controllers/MigrateController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/yii/console/controllers/MigrateController.php b/framework/yii/console/controllers/MigrateController.php index 0e36911..5651b9c 100644 --- a/framework/yii/console/controllers/MigrateController.php +++ b/framework/yii/console/controllers/MigrateController.php @@ -33,7 +33,7 @@ use yii\helpers\ArrayHelper; * * ~~~ * CREATE TABLE tbl_migration ( - * version varchar(255) PRIMARY KEY, + * version varchar(180) PRIMARY KEY, * apply_time integer * ) * ~~~