From 09e4229e16cfa174ee83c9217d1d2dbdd19e9b93 Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Thu, 30 May 2013 13:33:38 +0200 Subject: [PATCH 01/42] [WIP] RESTful routing syntax for UrlManager issue #303 Here is the proposal for RESTful routing syntax: https://gist.github.com/cebe/5674918 --- framework/yii/web/UrlManager.php | 32 ++++++++++++++++++++++++++++- tests/unit/framework/web/UrlManagerTest.php | 2 ++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/framework/yii/web/UrlManager.php b/framework/yii/web/UrlManager.php index 47f5c5d..a6ef0cf 100644 --- a/framework/yii/web/UrlManager.php +++ b/framework/yii/web/UrlManager.php @@ -43,6 +43,28 @@ class UrlManager extends Component * array, one can use the key to represent the pattern and the value the corresponding route. * For example, `'post/' => 'post/view'`. * + * For RESTful routing this shortcut also allows you to specify the [[UrlRule::verb|HTTP verb]] + * the rule should apply for by prepending it to the pattern, separated by a blank. + * For example, `'PUT post/' => 'post/update'`. + * You may specify multiple verbs by separating them with comma + * like this: `'POST,PUT post/index' => 'post/create'`. + * Note that [[UrlRule::mode|mode]] will be set to PARSING_ONLY when specifying verb in this way + * so you normally would not specify a verb for normal GET request. + * + * Here is an example configuration for RESTful CRUD controller: + * ~~~php + * array( + * 'dashboard' => 'site/index', + * + * 'POST s' => '/create', + * 's' => '/index', + * + * 'PUT /' => '/update', + * 'DELETE /' => '/delete', + * '/' => '/view', + * ); + * ~~~ + * * Note that if you modify this property after the UrlManager object is created, make sure * you populate the array with rule objects instead of rule configurations. */ @@ -115,9 +137,17 @@ class UrlManager extends Component foreach ($this->rules as $key => $rule) { if (!is_array($rule)) { $rule = array( - 'pattern' => $key, 'route' => $rule, ); + if (($pos = strpos($key, ' ')) !== false) { + $verbs = substr($key, 0, $pos); + if (preg_match('/^((GET|POST|PUT|DELETE),?)*$/', $verbs, $matches)) { + $rule['verb'] = explode(',', $verbs); + $rule['mode'] = UrlRule::PARSING_ONLY; + $key = substr($key, $pos + 1); + } + } + $rule['pattern'] = $key; } $rules[] = Yii::createObject(array_merge($this->ruleConfig, $rule)); } diff --git a/tests/unit/framework/web/UrlManagerTest.php b/tests/unit/framework/web/UrlManagerTest.php index 0f08790..d0e8775 100644 --- a/tests/unit/framework/web/UrlManagerTest.php +++ b/tests/unit/framework/web/UrlManagerTest.php @@ -248,4 +248,6 @@ class UrlManagerTest extends TestCase $result = $manager->parseRequest($request); $this->assertFalse($result); } + + // TODO test RESTful pattern syntax e.g. 'GET index' => 'site/index' } From 8ae946358949938680cf3b06be93e6f7519e8c77 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Sat, 1 Jun 2013 12:45:32 -0400 Subject: [PATCH 02/42] Fixes issue #472: doc fix. --- framework/yii/bootstrap/Nav.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/yii/bootstrap/Nav.php b/framework/yii/bootstrap/Nav.php index 548fe19..029f178 100644 --- a/framework/yii/bootstrap/Nav.php +++ b/framework/yii/bootstrap/Nav.php @@ -27,7 +27,7 @@ use yii\helpers\Html; * ), * array( * 'label' => 'Dropdown', - * 'items' => array( + * 'dropdown' => array( * array( * 'label' => 'DropdownA', * 'url' => '#', From bb0e2e84872bff1f668e54ffb737635d606f9a92 Mon Sep 17 00:00:00 2001 From: Tobias Munk Date: Sun, 2 Jun 2013 00:37:53 +0200 Subject: [PATCH 03/42] updated composer script event for setting permissions --- apps/advanced/composer.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/advanced/composer.json b/apps/advanced/composer.json index 95b3b13..cc3ec2d 100644 --- a/apps/advanced/composer.json +++ b/apps/advanced/composer.json @@ -19,10 +19,7 @@ "yiisoft/yii2-composer": "dev-master" }, "scripts": { - "post-install-cmd": [ - "yii\\composer\\InstallHandler::setPermissions" - ], - "post-update-cmd": [ + "post-create-project-cmd": [ "yii\\composer\\InstallHandler::setPermissions" ] }, From 607f3a59873167f18e8f9fb74455982c899d6dd0 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Sun, 2 Jun 2013 07:11:27 -0400 Subject: [PATCH 04/42] Fixes issue #476 --- framework/yii/caching/FileCache.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/framework/yii/caching/FileCache.php b/framework/yii/caching/FileCache.php index 0c6d119..1dbcb09 100644 --- a/framework/yii/caching/FileCache.php +++ b/framework/yii/caching/FileCache.php @@ -25,8 +25,9 @@ class FileCache extends Cache { /** * @var string the directory to store cache files. You may use path alias here. + * If not set, it will use the "cache" subdirectory under the application runtime path. */ - public $cachePath = '@app/runtime/cache'; + public $cachePath; /** * @var string cache file suffix. Defaults to '.bin'. */ @@ -51,7 +52,11 @@ class FileCache extends Cache public function init() { parent::init(); - $this->cachePath = Yii::getAlias($this->cachePath); + if ($this->cachePath === null) { + $this->cachePath = Yii::$app->getRuntimePath() . DIRECTORY_SEPARATOR . 'cache'; + } else { + $this->cachePath = Yii::getAlias($this->cachePath); + } if (!is_dir($this->cachePath)) { mkdir($this->cachePath, 0777, true); } From 36bbfd54caaa4a43c6634475b51f776c7d9af9d7 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Sun, 2 Jun 2013 07:29:29 -0400 Subject: [PATCH 05/42] Implemented "@app/runtime" alias. --- framework/yii/base/Application.php | 46 ++++++++++++++++++++++++++----------- framework/yii/caching/FileCache.php | 8 ++----- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/framework/yii/base/Application.php b/framework/yii/base/Application.php index d38f6a9..95993a4 100644 --- a/framework/yii/base/Application.php +++ b/framework/yii/base/Application.php @@ -67,35 +67,53 @@ class Application extends Module * Constructor. * @param array $config name-value pairs that will be used to initialize the object properties. * Note that the configuration must contain both [[id]] and [[basePath]]. - * @throws InvalidConfigException if either [[id]] or [[basePath]] configuration is missing. */ public function __construct($config = array()) { Yii::$app = $this; + $this->preInit($config); + + $this->registerErrorHandlers(); + $this->registerCoreComponents(); + + Component::__construct($config); + } + + /** + * Pre-initializes the application. + * This method is called at the beginning of the application constructor. + * When this method is called, none of the application properties are initialized yet. + * The default implementation will initialize a few important properties + * that may be referenced during the initialization of the rest of the properties. + * @param array $config the application configuration + * @throws InvalidConfigException if either [[id]] or [[basePath]] configuration is missing. + */ + public function preInit($config) + { if (!isset($config['id'])) { throw new InvalidConfigException('The "id" configuration is required.'); } - - if (isset($config['basePath'])) { - $this->setBasePath($config['basePath']); - Yii::setAlias('@app', $this->getBasePath()); - unset($config['basePath']); - } else { + if (!isset($config['basePath'])) { throw new InvalidConfigException('The "basePath" configuration is required.'); } - + + $this->setBasePath($config['basePath']); + Yii::setAlias('@app', $this->getBasePath()); + unset($config['basePath']); + + if (isset($config['runtime'])) { + $this->setRuntimePath($config['runtime']); + unset($config['runtime']); + } + Yii::setAlias('@app/runtime', $this->getRuntimePath()); + if (isset($config['timeZone'])) { $this->setTimeZone($config['timeZone']); unset($config['timeZone']); } elseif (!ini_get('date.timezone')) { $this->setTimeZone('UTC'); - } - - $this->registerErrorHandlers(); - $this->registerCoreComponents(); - - Component::__construct($config); + } } /** diff --git a/framework/yii/caching/FileCache.php b/framework/yii/caching/FileCache.php index 1dbcb09..8d6a704 100644 --- a/framework/yii/caching/FileCache.php +++ b/framework/yii/caching/FileCache.php @@ -27,7 +27,7 @@ class FileCache extends Cache * @var string the directory to store cache files. You may use path alias here. * If not set, it will use the "cache" subdirectory under the application runtime path. */ - public $cachePath; + public $cachePath = '@app/runtime/cache'; /** * @var string cache file suffix. Defaults to '.bin'. */ @@ -52,11 +52,7 @@ class FileCache extends Cache public function init() { parent::init(); - if ($this->cachePath === null) { - $this->cachePath = Yii::$app->getRuntimePath() . DIRECTORY_SEPARATOR . 'cache'; - } else { - $this->cachePath = Yii::getAlias($this->cachePath); - } + $this->cachePath = Yii::getAlias($this->cachePath); if (!is_dir($this->cachePath)) { mkdir($this->cachePath, 0777, true); } From 5c56c0fc02e54bf1ab73c172ce0e0577ccab57a8 Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Sun, 2 Jun 2013 16:05:11 +0200 Subject: [PATCH 06/42] Better flexibility for abstract db types Feature was requested in yiisoft/yii#765 --- framework/yii/db/QueryBuilder.php | 6 ++ framework/yii/db/mysql/QueryBuilder.php | 2 +- tests/unit/framework/db/QueryBuilderTest.php | 109 +++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 tests/unit/framework/db/QueryBuilderTest.php diff --git a/framework/yii/db/QueryBuilder.php b/framework/yii/db/QueryBuilder.php index c0b4223..3e7f95a 100644 --- a/framework/yii/db/QueryBuilder.php +++ b/framework/yii/db/QueryBuilder.php @@ -464,6 +464,8 @@ class QueryBuilder extends \yii\base\Object * the first part will be converted, and the rest of the parts will be appended to the converted result. * For example, 'string NOT NULL' is converted to 'varchar(255) NOT NULL'. * + // TODO documentation + * * If a type cannot be found in [[typeMap]], it will be returned without any change. * @param string $type abstract column type * @return string physical column type. @@ -472,6 +474,10 @@ class QueryBuilder extends \yii\base\Object { if (isset($this->typeMap[$type])) { return $this->typeMap[$type]; + } elseif ((preg_match('/^(\w+)\((.+?)\)(.*)$/', $type, $matches))) { + if (isset($this->typeMap[$matches[1]])) { + return preg_replace('/\(.+\)/', '(' . $matches[2] . ')', $this->typeMap[$matches[1]]) . $matches[3]; + } } elseif (preg_match('/^(\w+)\s+/', $type, $matches)) { if (isset($this->typeMap[$matches[1]])) { return preg_replace('/^\w+/', $this->typeMap[$matches[1]], $type); diff --git a/framework/yii/db/mysql/QueryBuilder.php b/framework/yii/db/mysql/QueryBuilder.php index 70c6d64..4b35e24 100644 --- a/framework/yii/db/mysql/QueryBuilder.php +++ b/framework/yii/db/mysql/QueryBuilder.php @@ -29,7 +29,7 @@ class QueryBuilder extends \yii\db\QueryBuilder Schema::TYPE_INTEGER => 'int(11)', Schema::TYPE_BIGINT => 'bigint(20)', Schema::TYPE_FLOAT => 'float', - Schema::TYPE_DECIMAL => 'decimal', + Schema::TYPE_DECIMAL => 'decimal(10,0)', Schema::TYPE_DATETIME => 'datetime', Schema::TYPE_TIMESTAMP => 'timestamp', Schema::TYPE_TIME => 'time', diff --git a/tests/unit/framework/db/QueryBuilderTest.php b/tests/unit/framework/db/QueryBuilderTest.php new file mode 100644 index 0000000..355f080 --- /dev/null +++ b/tests/unit/framework/db/QueryBuilderTest.php @@ -0,0 +1,109 @@ +driverName) + { + case 'mysql': + return new MysqlQueryBuilder($this->getConnection()); + case 'sqlite': + return new SqliteQueryBuilder($this->getConnection()); + case 'mssql': + return new MssqlQueryBuilder($this->getConnection()); + } + throw new \Exception('Test is not implemented for ' . $this->driverName); + } + + /** + * this is not used as a dataprovider for testGetColumnType to speed up the test + * when used as dataprovider every single line will cause a reconnect with the database which is not needed here + */ + public function columnTypes() + { + return array( + array(Schema::TYPE_PK, 'int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY'), + array(Schema::TYPE_PK . '(8)', 'int(8) NOT NULL AUTO_INCREMENT PRIMARY KEY'), + array(Schema::TYPE_PK . ' CHECK (value > 5)', 'int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY CHECK (value > 5)'), + array(Schema::TYPE_PK . '(8) CHECK (value > 5)', 'int(8) NOT NULL AUTO_INCREMENT PRIMARY KEY CHECK (value > 5)'), + array(Schema::TYPE_STRING, 'varchar(255)'), + array(Schema::TYPE_STRING . '(32)', 'varchar(32)'), + array(Schema::TYPE_STRING . ' CHECK (value LIKE "test%")', 'varchar(255) CHECK (value LIKE "test%")'), + array(Schema::TYPE_STRING . '(32) CHECK (value LIKE "test%")', 'varchar(32) CHECK (value LIKE "test%")'), + array(Schema::TYPE_STRING . ' NOT NULL', 'varchar(255) NOT NULL'), + array(Schema::TYPE_TEXT, 'text'), + array(Schema::TYPE_TEXT . '(255)', 'text'), + array(Schema::TYPE_TEXT . ' CHECK (value LIKE "test%")', 'text CHECK (value LIKE "test%")'), + array(Schema::TYPE_TEXT . '(255) CHECK (value LIKE "test%")', 'text CHECK (value LIKE "test%")'), + array(Schema::TYPE_TEXT . ' NOT NULL', 'text NOT NULL'), + array(Schema::TYPE_TEXT . '(255) NOT NULL', 'text NOT NULL'), + array(Schema::TYPE_SMALLINT, 'smallint(6)'), + array(Schema::TYPE_SMALLINT . '(8)', 'smallint(8)'), + array(Schema::TYPE_INTEGER, 'int(11)'), + array(Schema::TYPE_INTEGER . '(8)', 'int(8)'), + array(Schema::TYPE_INTEGER . ' CHECK (value > 5)', 'int(11) CHECK (value > 5)'), + array(Schema::TYPE_INTEGER . '(8) CHECK (value > 5)', 'int(8) CHECK (value > 5)'), + array(Schema::TYPE_INTEGER . ' NOT NULL', 'int(11) NOT NULL'), + array(Schema::TYPE_BIGINT, 'bigint(20)'), + array(Schema::TYPE_BIGINT . '(8)', 'bigint(8)'), + array(Schema::TYPE_BIGINT . ' CHECK (value > 5)', 'bigint(20) CHECK (value > 5)'), + array(Schema::TYPE_BIGINT . '(8) CHECK (value > 5)', 'bigint(8) CHECK (value > 5)'), + array(Schema::TYPE_BIGINT . ' NOT NULL', 'bigint(20) NOT NULL'), + array(Schema::TYPE_FLOAT, 'float'), + array(Schema::TYPE_FLOAT . '(16,5)', 'float'), + array(Schema::TYPE_FLOAT . ' CHECK (value > 5.6)', 'float CHECK (value > 5.6)'), + array(Schema::TYPE_FLOAT . '(16,5) CHECK (value > 5.6)', 'float CHECK (value > 5.6)'), + array(Schema::TYPE_FLOAT . ' NOT NULL', 'float NOT NULL'), + array(Schema::TYPE_DECIMAL, 'decimal(10,0)'), + array(Schema::TYPE_DECIMAL . '(12,4)', 'decimal(12,4)'), + array(Schema::TYPE_DECIMAL . ' CHECK (value > 5.6)', 'decimal(10,0) CHECK (value > 5.6)'), + array(Schema::TYPE_DECIMAL . '(12,4) CHECK (value > 5.6)', 'decimal(12,4) CHECK (value > 5.6)'), + array(Schema::TYPE_DECIMAL . ' NOT NULL', 'decimal(10,0) NOT NULL'), + array(Schema::TYPE_DATETIME, 'datetime'), + array(Schema::TYPE_DATETIME . " CHECK(value BETWEEN '2011-01-01' AND '2013-01-01')", "datetime CHECK(value BETWEEN '2011-01-01' AND '2013-01-01')"), + array(Schema::TYPE_DATETIME . ' NOT NULL', 'datetime NOT NULL'), + array(Schema::TYPE_TIMESTAMP, 'timestamp'), + array(Schema::TYPE_TIMESTAMP . " CHECK(value BETWEEN '2011-01-01' AND '2013-01-01')", "timestamp CHECK(value BETWEEN '2011-01-01' AND '2013-01-01')"), + array(Schema::TYPE_TIMESTAMP . ' NOT NULL', 'timestamp NOT NULL'), + array(Schema::TYPE_TIME, 'time'), + array(Schema::TYPE_TIME . " CHECK(value BETWEEN '12:00:00' AND '13:01:01')", "time CHECK(value BETWEEN '12:00:00' AND '13:01:01')"), + array(Schema::TYPE_TIME . ' NOT NULL', 'time NOT NULL'), + array(Schema::TYPE_DATE, 'date'), + array(Schema::TYPE_DATE . " CHECK(value BETWEEN '2011-01-01' AND '2013-01-01')", "date CHECK(value BETWEEN '2011-01-01' AND '2013-01-01')"), + array(Schema::TYPE_DATE . ' NOT NULL', 'date NOT NULL'), + array(Schema::TYPE_BINARY, 'blob'), + array(Schema::TYPE_BOOLEAN, 'tinyint(1)'), + array(Schema::TYPE_BOOLEAN . ' NOT NULL DEFAULT 1', 'tinyint(1) NOT NULL DEFAULT 1'), + array(Schema::TYPE_MONEY, 'decimal(19,4)'), + array(Schema::TYPE_MONEY . '(16,2)', 'decimal(16,2)'), + array(Schema::TYPE_MONEY . ' CHECK (value > 0.0)', 'decimal(19,4) CHECK (value > 0.0)'), + array(Schema::TYPE_MONEY . '(16,2) CHECK (value > 0.0)', 'decimal(16,2) CHECK (value > 0.0)'), + array(Schema::TYPE_MONEY . ' NOT NULL', 'decimal(19,4) NOT NULL'), + ); + } + + /** + * + */ + public function testGetColumnType() + { + $qb = $this->getQueryBuilder(); + foreach($this->columnTypes() as $item) { + list ($column, $expected) = $item; + $this->assertEquals($expected, $qb->getColumnType($column)); + } + } +} From 22357befadbb1ab920f67c9557dff6c0b295e2f0 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Sun, 2 Jun 2013 15:19:29 -0400 Subject: [PATCH 07/42] Added "@runtime" and "@vendor" aliases. --- extensions/smarty/yii/smarty/ViewRenderer.php | 4 ++-- extensions/twig/yii/twig/ViewRenderer.php | 2 +- framework/yii/base/Application.php | 8 +++++++- framework/yii/caching/FileCache.php | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/extensions/smarty/yii/smarty/ViewRenderer.php b/extensions/smarty/yii/smarty/ViewRenderer.php index d8c5d30..164ae8c 100644 --- a/extensions/smarty/yii/smarty/ViewRenderer.php +++ b/extensions/smarty/yii/smarty/ViewRenderer.php @@ -26,12 +26,12 @@ class ViewRenderer extends BaseViewRenderer /** * @var string the directory or path alias pointing to where Smarty cache will be stored. */ - public $cachePath = '@app/runtime/Smarty/cache'; + public $cachePath = '@runtime/Smarty/cache'; /** * @var string the directory or path alias pointing to where Smarty compiled templates will be stored. */ - public $compilePath = '@app/runtime/Smarty/compile'; + public $compilePath = '@runtime/Smarty/compile'; /** * @var Smarty diff --git a/extensions/twig/yii/twig/ViewRenderer.php b/extensions/twig/yii/twig/ViewRenderer.php index 7498d86..76bee95 100644 --- a/extensions/twig/yii/twig/ViewRenderer.php +++ b/extensions/twig/yii/twig/ViewRenderer.php @@ -25,7 +25,7 @@ class ViewRenderer extends BaseViewRenderer /** * @var string the directory or path alias pointing to where Twig cache will be stored. */ - public $cachePath = '@app/runtime/Twig/cache'; + public $cachePath = '@runtime/Twig/cache'; /** * @var array Twig options diff --git a/framework/yii/base/Application.php b/framework/yii/base/Application.php index 95993a4..495c1f8 100644 --- a/framework/yii/base/Application.php +++ b/framework/yii/base/Application.php @@ -102,11 +102,17 @@ class Application extends Module Yii::setAlias('@app', $this->getBasePath()); unset($config['basePath']); + if (isset($config['vendor'])) { + $this->setVendorPath($config['vendor']); + unset($config['vendorPath']); + } + Yii::setAlias('@vendor', $this->getVendorPath()); + if (isset($config['runtime'])) { $this->setRuntimePath($config['runtime']); unset($config['runtime']); } - Yii::setAlias('@app/runtime', $this->getRuntimePath()); + Yii::setAlias('@runtime', $this->getRuntimePath()); if (isset($config['timeZone'])) { $this->setTimeZone($config['timeZone']); diff --git a/framework/yii/caching/FileCache.php b/framework/yii/caching/FileCache.php index 8d6a704..a15751e 100644 --- a/framework/yii/caching/FileCache.php +++ b/framework/yii/caching/FileCache.php @@ -27,7 +27,7 @@ class FileCache extends Cache * @var string the directory to store cache files. You may use path alias here. * If not set, it will use the "cache" subdirectory under the application runtime path. */ - public $cachePath = '@app/runtime/cache'; + public $cachePath = '@runtime/cache'; /** * @var string cache file suffix. Defaults to '.bin'. */ From c28b0183a5188adf1cbb574e4dbb33bb62817ca4 Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Sun, 2 Jun 2013 22:12:37 +0200 Subject: [PATCH 08/42] whitespace --- tests/unit/framework/db/QueryBuilderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/framework/db/QueryBuilderTest.php b/tests/unit/framework/db/QueryBuilderTest.php index 355f080..7dc4731 100644 --- a/tests/unit/framework/db/QueryBuilderTest.php +++ b/tests/unit/framework/db/QueryBuilderTest.php @@ -96,7 +96,7 @@ class QueryBuilderTest extends DatabaseTestCase } /** - * + * */ public function testGetColumnType() { From 7117a6752b6927038b62e2366d9034b282b3ced0 Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Sun, 2 Jun 2013 22:58:42 +0200 Subject: [PATCH 09/42] Added phpdoc about precision constraints for abstract db types --- framework/yii/db/QueryBuilder.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/framework/yii/db/QueryBuilder.php b/framework/yii/db/QueryBuilder.php index 3e7f95a..46457c6 100644 --- a/framework/yii/db/QueryBuilder.php +++ b/framework/yii/db/QueryBuilder.php @@ -464,7 +464,11 @@ class QueryBuilder extends \yii\base\Object * the first part will be converted, and the rest of the parts will be appended to the converted result. * For example, 'string NOT NULL' is converted to 'varchar(255) NOT NULL'. * - // TODO documentation + * For some of the abstract types you can also specify a length or precision constraint + * by prepending it in round brackets directly to the type. + * For example `string(32)` will be converted into "varchar(32)" on a MySQL database. + * If the underlying DBMS does not support these kind of constraints for a type it will + * be ignored. * * If a type cannot be found in [[typeMap]], it will be returned without any change. * @param string $type abstract column type From 64e5911b5e1ea27d14334da60aa82e00718b47f8 Mon Sep 17 00:00:00 2001 From: Tobias Munk Date: Sun, 2 Jun 2013 23:42:11 +0200 Subject: [PATCH 10/42] added updated composer script event for setting permissions --- apps/basic/composer.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/basic/composer.json b/apps/basic/composer.json index 29b05d1..b01c56c 100644 --- a/apps/basic/composer.json +++ b/apps/basic/composer.json @@ -19,10 +19,7 @@ "yiisoft/yii2-composer": "dev-master" }, "scripts": { - "post-install-cmd": [ - "yii\\composer\\InstallHandler::setPermissions" - ], - "post-update-cmd": [ + "post-create-project-cmd": [ "yii\\composer\\InstallHandler::setPermissions" ] }, From 5615afab2195975261d26926e19ab35fa67e206e Mon Sep 17 00:00:00 2001 From: Tobias Munk Date: Sun, 2 Jun 2013 23:42:31 +0200 Subject: [PATCH 11/42] updated deps --- apps/advanced/composer.lock | 10 +++++----- apps/basic/composer.lock | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/advanced/composer.lock b/apps/advanced/composer.lock index 516ae32..3022597 100644 --- a/apps/advanced/composer.lock +++ b/apps/advanced/composer.lock @@ -3,7 +3,7 @@ "This file locks the dependencies of your project to a known state", "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" ], - "hash": "05f7bcd0e99931b52415eaeb62d54daf", + "hash": "2d1053fbaaf2044054f273a71d0ccde0", "packages": [ { "name": "yiisoft/yii2", @@ -11,12 +11,12 @@ "source": { "type": "git", "url": "https://github.com/yiisoft/yii2-framework.git", - "reference": "2d93f20ba6044ac3f1957300c4ae85fd98ecf47d" + "reference": "3ad6334be076a80df3b2ea0b57f38bd0c6901989" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/yiisoft/yii2-framework/zipball/2d93f20ba6044ac3f1957300c4ae85fd98ecf47d", - "reference": "2d93f20ba6044ac3f1957300c4ae85fd98ecf47d", + "url": "https://api.github.com/repos/yiisoft/yii2-framework/zipball/3ad6334be076a80df3b2ea0b57f38bd0c6901989", + "reference": "3ad6334be076a80df3b2ea0b57f38bd0c6901989", "shasum": "" }, "require": { @@ -97,7 +97,7 @@ "framework", "yii" ], - "time": "2013-05-29 02:55:14" + "time": "2013-06-02 19:19:29" }, { "name": "yiisoft/yii2-composer", diff --git a/apps/basic/composer.lock b/apps/basic/composer.lock index fe87399..a1cb48d 100644 --- a/apps/basic/composer.lock +++ b/apps/basic/composer.lock @@ -3,7 +3,7 @@ "This file locks the dependencies of your project to a known state", "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" ], - "hash": "0411dbbd774aa1c89256c77c68023940", + "hash": "91ba258de768b93025f86071f3bb4b84", "packages": [ { "name": "yiisoft/yii2", @@ -11,12 +11,12 @@ "source": { "type": "git", "url": "https://github.com/yiisoft/yii2-framework.git", - "reference": "2d93f20ba6044ac3f1957300c4ae85fd98ecf47d" + "reference": "3ad6334be076a80df3b2ea0b57f38bd0c6901989" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/yiisoft/yii2-framework/zipball/2d93f20ba6044ac3f1957300c4ae85fd98ecf47d", - "reference": "2d93f20ba6044ac3f1957300c4ae85fd98ecf47d", + "url": "https://api.github.com/repos/yiisoft/yii2-framework/zipball/3ad6334be076a80df3b2ea0b57f38bd0c6901989", + "reference": "3ad6334be076a80df3b2ea0b57f38bd0c6901989", "shasum": "" }, "require": { @@ -97,7 +97,7 @@ "framework", "yii" ], - "time": "2013-05-29 02:55:14" + "time": "2013-06-02 19:19:29" }, { "name": "yiisoft/yii2-composer", From af68ee9d2745bf7b3fd27ea786c0d9add221e17b Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Mon, 3 Jun 2013 00:24:39 +0200 Subject: [PATCH 12/42] Sqlite unit test for abstract db types --- framework/yii/db/sqlite/QueryBuilder.php | 4 +- .../framework/db/sqlite/SqliteQueryBuilderTest.php | 74 ++++++++++++++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 tests/unit/framework/db/sqlite/SqliteQueryBuilderTest.php diff --git a/framework/yii/db/sqlite/QueryBuilder.php b/framework/yii/db/sqlite/QueryBuilder.php index 72d48f4..52c101b 100644 --- a/framework/yii/db/sqlite/QueryBuilder.php +++ b/framework/yii/db/sqlite/QueryBuilder.php @@ -30,13 +30,13 @@ class QueryBuilder extends \yii\db\QueryBuilder Schema::TYPE_INTEGER => 'integer', Schema::TYPE_BIGINT => 'bigint', Schema::TYPE_FLOAT => 'float', - Schema::TYPE_DECIMAL => 'decimal', + Schema::TYPE_DECIMAL => 'decimal(10,0)', Schema::TYPE_DATETIME => 'datetime', Schema::TYPE_TIMESTAMP => 'timestamp', Schema::TYPE_TIME => 'time', Schema::TYPE_DATE => 'date', Schema::TYPE_BINARY => 'blob', - Schema::TYPE_BOOLEAN => 'tinyint(1)', + Schema::TYPE_BOOLEAN => 'boolean', Schema::TYPE_MONEY => 'decimal(19,4)', ); diff --git a/tests/unit/framework/db/sqlite/SqliteQueryBuilderTest.php b/tests/unit/framework/db/sqlite/SqliteQueryBuilderTest.php new file mode 100644 index 0000000..c36628f --- /dev/null +++ b/tests/unit/framework/db/sqlite/SqliteQueryBuilderTest.php @@ -0,0 +1,74 @@ + 5)', 'integer PRIMARY KEY AUTOINCREMENT NOT NULL CHECK (value > 5)'), + array(Schema::TYPE_PK . '(8) CHECK (value > 5)', 'integer PRIMARY KEY AUTOINCREMENT NOT NULL CHECK (value > 5)'), + array(Schema::TYPE_STRING, 'varchar(255)'), + array(Schema::TYPE_STRING . '(32)', 'varchar(32)'), + array(Schema::TYPE_STRING . ' CHECK (value LIKE "test%")', 'varchar(255) CHECK (value LIKE "test%")'), + array(Schema::TYPE_STRING . '(32) CHECK (value LIKE "test%")', 'varchar(32) CHECK (value LIKE "test%")'), + array(Schema::TYPE_STRING . ' NOT NULL', 'varchar(255) NOT NULL'), + array(Schema::TYPE_TEXT, 'text'), + array(Schema::TYPE_TEXT . '(255)', 'text'), + array(Schema::TYPE_TEXT . ' CHECK (value LIKE "test%")', 'text CHECK (value LIKE "test%")'), + array(Schema::TYPE_TEXT . '(255) CHECK (value LIKE "test%")', 'text CHECK (value LIKE "test%")'), + array(Schema::TYPE_TEXT . ' NOT NULL', 'text NOT NULL'), + array(Schema::TYPE_TEXT . '(255) NOT NULL', 'text NOT NULL'), + array(Schema::TYPE_SMALLINT, 'smallint'), + array(Schema::TYPE_SMALLINT . '(8)', 'smallint'), + array(Schema::TYPE_INTEGER, 'integer'), + array(Schema::TYPE_INTEGER . '(8)', 'integer'), + array(Schema::TYPE_INTEGER . ' CHECK (value > 5)', 'integer CHECK (value > 5)'), + array(Schema::TYPE_INTEGER . '(8) CHECK (value > 5)', 'integer CHECK (value > 5)'), + array(Schema::TYPE_INTEGER . ' NOT NULL', 'integer NOT NULL'), + array(Schema::TYPE_BIGINT, 'bigint'), + array(Schema::TYPE_BIGINT . '(8)', 'bigint'), + array(Schema::TYPE_BIGINT . ' CHECK (value > 5)', 'bigint CHECK (value > 5)'), + array(Schema::TYPE_BIGINT . '(8) CHECK (value > 5)', 'bigint CHECK (value > 5)'), + array(Schema::TYPE_BIGINT . ' NOT NULL', 'bigint NOT NULL'), + array(Schema::TYPE_FLOAT, 'float'), + array(Schema::TYPE_FLOAT . '(16,5)', 'float'), + array(Schema::TYPE_FLOAT . ' CHECK (value > 5.6)', 'float CHECK (value > 5.6)'), + array(Schema::TYPE_FLOAT . '(16,5) CHECK (value > 5.6)', 'float CHECK (value > 5.6)'), + array(Schema::TYPE_FLOAT . ' NOT NULL', 'float NOT NULL'), + array(Schema::TYPE_DECIMAL, 'decimal(10,0)'), + array(Schema::TYPE_DECIMAL . '(12,4)', 'decimal(12,4)'), + array(Schema::TYPE_DECIMAL . ' CHECK (value > 5.6)', 'decimal(10,0) CHECK (value > 5.6)'), + array(Schema::TYPE_DECIMAL . '(12,4) CHECK (value > 5.6)', 'decimal(12,4) CHECK (value > 5.6)'), + array(Schema::TYPE_DECIMAL . ' NOT NULL', 'decimal(10,0) NOT NULL'), + array(Schema::TYPE_DATETIME, 'datetime'), + array(Schema::TYPE_DATETIME . " CHECK(value BETWEEN '2011-01-01' AND '2013-01-01')", "datetime CHECK(value BETWEEN '2011-01-01' AND '2013-01-01')"), + array(Schema::TYPE_DATETIME . ' NOT NULL', 'datetime NOT NULL'), + array(Schema::TYPE_TIMESTAMP, 'timestamp'), + array(Schema::TYPE_TIMESTAMP . " CHECK(value BETWEEN '2011-01-01' AND '2013-01-01')", "timestamp CHECK(value BETWEEN '2011-01-01' AND '2013-01-01')"), + array(Schema::TYPE_TIMESTAMP . ' NOT NULL', 'timestamp NOT NULL'), + array(Schema::TYPE_TIME, 'time'), + array(Schema::TYPE_TIME . " CHECK(value BETWEEN '12:00:00' AND '13:01:01')", "time CHECK(value BETWEEN '12:00:00' AND '13:01:01')"), + array(Schema::TYPE_TIME . ' NOT NULL', 'time NOT NULL'), + array(Schema::TYPE_DATE, 'date'), + array(Schema::TYPE_DATE . " CHECK(value BETWEEN '2011-01-01' AND '2013-01-01')", "date CHECK(value BETWEEN '2011-01-01' AND '2013-01-01')"), + array(Schema::TYPE_DATE . ' NOT NULL', 'date NOT NULL'), + array(Schema::TYPE_BINARY, 'blob'), + array(Schema::TYPE_BOOLEAN, 'boolean'), + array(Schema::TYPE_BOOLEAN . ' NOT NULL DEFAULT 1', 'boolean NOT NULL DEFAULT 1'), + array(Schema::TYPE_MONEY, 'decimal(19,4)'), + array(Schema::TYPE_MONEY . '(16,2)', 'decimal(16,2)'), + array(Schema::TYPE_MONEY . ' CHECK (value > 0.0)', 'decimal(19,4) CHECK (value > 0.0)'), + array(Schema::TYPE_MONEY . '(16,2) CHECK (value > 0.0)', 'decimal(16,2) CHECK (value > 0.0)'), + array(Schema::TYPE_MONEY . ' NOT NULL', 'decimal(19,4) NOT NULL'), + ); + } +} \ No newline at end of file From 9b6df54c7df061e08cce580dc9cba4e7c2c80e4f Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Mon, 3 Jun 2013 00:28:32 +0200 Subject: [PATCH 13/42] Adjusted type map in MSSQL Querybuilder MSSQL seems to support limits for decimal type, so we add a default limit. --- framework/yii/db/mssql/QueryBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/yii/db/mssql/QueryBuilder.php b/framework/yii/db/mssql/QueryBuilder.php index 45a7507..e7f8f80 100644 --- a/framework/yii/db/mssql/QueryBuilder.php +++ b/framework/yii/db/mssql/QueryBuilder.php @@ -28,7 +28,7 @@ class QueryBuilder extends \yii\db\QueryBuilder Schema::TYPE_INTEGER => 'int(11)', Schema::TYPE_BIGINT => 'bigint(20)', Schema::TYPE_FLOAT => 'float', - Schema::TYPE_DECIMAL => 'decimal', + Schema::TYPE_DECIMAL => 'decimal(10,0)', Schema::TYPE_DATETIME => 'datetime', Schema::TYPE_TIMESTAMP => 'timestamp', Schema::TYPE_TIME => 'time', From 8435285c1944675a47cdfb4af7f41843d1393227 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Sun, 2 Jun 2013 22:19:38 -0400 Subject: [PATCH 14/42] doc fix. --- framework/yii/base/Module.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/yii/base/Module.php b/framework/yii/base/Module.php index ec3001e..060d321 100644 --- a/framework/yii/base/Module.php +++ b/framework/yii/base/Module.php @@ -409,11 +409,11 @@ abstract class Module extends Component * ~~~ * array( * 'comment' => array( - * 'class' => 'app\modules\CommentModule', + * 'class' => 'app\modules\comment\CommentModule', * 'db' => 'db', * ), * 'booking' => array( - * 'class' => 'app\modules\BookingModule', + * 'class' => 'app\modules\booking\BookingModule', * ), * ) * ~~~ From 21160338d7a2dbad04228028b00172ae3fb6602a Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Sun, 2 Jun 2013 22:31:17 -0400 Subject: [PATCH 15/42] Implemented default controller namespace. --- apps/basic/config/main.php | 1 - framework/yii/base/Module.php | 16 +++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/apps/basic/config/main.php b/apps/basic/config/main.php index 9adfba6..054259e 100644 --- a/apps/basic/config/main.php +++ b/apps/basic/config/main.php @@ -4,7 +4,6 @@ return array( 'id' => 'bootstrap', 'basePath' => dirname(__DIR__), 'preload' => array('log'), - 'controllerNamespace' => 'app\controllers', 'modules' => array( // 'debug' => array( // 'class' => 'yii\debug\Module', diff --git a/framework/yii/base/Module.php b/framework/yii/base/Module.php index 060d321..fac4164 100644 --- a/framework/yii/base/Module.php +++ b/framework/yii/base/Module.php @@ -88,7 +88,11 @@ abstract class Module extends Component */ public $controllerMap = array(); /** - * @var string the namespace that controller classes are in. Default is to use global namespace. + * @var string the namespace that controller classes are in. If not set, + * it will use the "controllers" sub-namespace under the namespace of this module. + * For example, if the namespace of this module is "foo\bar", then the default + * controller namespace would be "foo\bar\controllers". + * If the module is an application, it will default to "app\controllers". */ public $controllerNamespace; /** @@ -178,6 +182,16 @@ abstract class Module extends Component public function init() { $this->preloadComponents(); + if ($this->controllerNamespace === null) { + if ($this instanceof Application) { + $this->controllerNamespace = 'app\\controllers'; + } else { + $class = get_class($this); + if (($pos = strrpos($class, '\\')) !== false) { + $this->controllerNamespace = substr($class, 0, $pos) . '\\controllers'; + } + } + } } /** From cf47a71db7ffa997478d461330850f71f565f73a Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Sun, 2 Jun 2013 22:47:02 -0400 Subject: [PATCH 16/42] Fixes issue #478: Improved the generation of secret key --- framework/yii/helpers/base/SecurityHelper.php | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/framework/yii/helpers/base/SecurityHelper.php b/framework/yii/helpers/base/SecurityHelper.php index 3f69fee..f646a24 100644 --- a/framework/yii/helpers/base/SecurityHelper.php +++ b/framework/yii/helpers/base/SecurityHelper.php @@ -131,15 +131,30 @@ class SecurityHelper $keys = is_file($keyFile) ? require($keyFile) : array(); } if (!isset($keys[$name])) { - // generate a 32-char random key - $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - $keys[$name] = substr(str_shuffle(str_repeat($chars, 5)), 0, $length); + $keys[$name] = static::generateRandomKey($length); file_put_contents($keyFile, " Date: Mon, 3 Jun 2013 08:28:14 +0200 Subject: [PATCH 17/42] removed unneccessary brackets --- framework/yii/db/QueryBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/yii/db/QueryBuilder.php b/framework/yii/db/QueryBuilder.php index 46457c6..04f1969 100644 --- a/framework/yii/db/QueryBuilder.php +++ b/framework/yii/db/QueryBuilder.php @@ -478,7 +478,7 @@ class QueryBuilder extends \yii\base\Object { if (isset($this->typeMap[$type])) { return $this->typeMap[$type]; - } elseif ((preg_match('/^(\w+)\((.+?)\)(.*)$/', $type, $matches))) { + } elseif (preg_match('/^(\w+)\((.+?)\)(.*)$/', $type, $matches)) { if (isset($this->typeMap[$matches[1]])) { return preg_replace('/\(.+\)/', '(' . $matches[2] . ')', $this->typeMap[$matches[1]]) . $matches[3]; } From fbb93d0b63f8fa91ee9068dc563f27ddae4a530c Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Mon, 3 Jun 2013 08:42:50 +0200 Subject: [PATCH 18/42] doc enhancements for #461 --- framework/yii/web/UrlManager.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/framework/yii/web/UrlManager.php b/framework/yii/web/UrlManager.php index a6ef0cf..d7135c5 100644 --- a/framework/yii/web/UrlManager.php +++ b/framework/yii/web/UrlManager.php @@ -43,15 +43,18 @@ class UrlManager extends Component * array, one can use the key to represent the pattern and the value the corresponding route. * For example, `'post/' => 'post/view'`. * - * For RESTful routing this shortcut also allows you to specify the [[UrlRule::verb|HTTP verb]] - * the rule should apply for by prepending it to the pattern, separated by a blank. + * For RESTful routing the mentioned shortcut format also allows you to specify the + * [[UrlRule::verb|HTTP verb]] that the rule should apply for. + * You can do that by prepending it to the pattern, separated by a space. * For example, `'PUT post/' => 'post/update'`. * You may specify multiple verbs by separating them with comma * like this: `'POST,PUT post/index' => 'post/create'`. + * The supported verbs in the shortcut format are: GET, POST, PUT and DELETE. * Note that [[UrlRule::mode|mode]] will be set to PARSING_ONLY when specifying verb in this way * so you normally would not specify a verb for normal GET request. * * Here is an example configuration for RESTful CRUD controller: + * * ~~~php * array( * 'dashboard' => 'site/index', From 11923064810be47ed24888efcd53a36674e83fd2 Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Mon, 3 Jun 2013 08:59:41 +0200 Subject: [PATCH 19/42] improved UrlManager RESTful syntax regex --- framework/yii/web/UrlManager.php | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/framework/yii/web/UrlManager.php b/framework/yii/web/UrlManager.php index d7135c5..44c63c5 100644 --- a/framework/yii/web/UrlManager.php +++ b/framework/yii/web/UrlManager.php @@ -45,11 +45,11 @@ class UrlManager extends Component * * For RESTful routing the mentioned shortcut format also allows you to specify the * [[UrlRule::verb|HTTP verb]] that the rule should apply for. - * You can do that by prepending it to the pattern, separated by a space. + * You can do that by prepending it to the pattern, separated by space. * For example, `'PUT post/' => 'post/update'`. * You may specify multiple verbs by separating them with comma * like this: `'POST,PUT post/index' => 'post/create'`. - * The supported verbs in the shortcut format are: GET, POST, PUT and DELETE. + * The supported verbs in the shortcut format are: GET, HEAD, POST, PUT and DELETE. * Note that [[UrlRule::mode|mode]] will be set to PARSING_ONLY when specifying verb in this way * so you normally would not specify a verb for normal GET request. * @@ -142,13 +142,10 @@ class UrlManager extends Component $rule = array( 'route' => $rule, ); - if (($pos = strpos($key, ' ')) !== false) { - $verbs = substr($key, 0, $pos); - if (preg_match('/^((GET|POST|PUT|DELETE),?)*$/', $verbs, $matches)) { - $rule['verb'] = explode(',', $verbs); - $rule['mode'] = UrlRule::PARSING_ONLY; - $key = substr($key, $pos + 1); - } + if (preg_match('/^((?:(GET|HEAD|POST|PUT|DELETE),)*(GET|HEAD|POST|PUT|DELETE))\s+(.*)$/', $key, $matches)) { + $rule['verb'] = explode(',', $matches[1]); + $rule['mode'] = UrlRule::PARSING_ONLY; + $key = $matches[4]; } $rule['pattern'] = $key; } From e94cc6bb9ea56886975827ee41087569438d2bb9 Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Mon, 3 Jun 2013 09:32:14 +0200 Subject: [PATCH 20/42] unit test for UrlManager RESTful routing syntax removed test param 'appClass' as it does not make sense to configure application class for all tests, some explicitly need webapp where some might explicitly need console app. --- tests/unit/TestCase.php | 3 +- tests/unit/data/config.php | 2 -- tests/unit/framework/web/UrlManagerTest.php | 54 ++++++++++++++++++++++++++++- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/tests/unit/TestCase.php b/tests/unit/TestCase.php index 479f85d..efcedf0 100644 --- a/tests/unit/TestCase.php +++ b/tests/unit/TestCase.php @@ -38,14 +38,13 @@ abstract class TestCase extends \yii\test\TestCase * The application will be destroyed on tearDown() automatically. * @param array $config The application configuration, if needed */ - protected function mockApplication($config=array()) + protected function mockApplication($config = array(), $appClass = '\yii\console\Application') { static $defaultConfig = array( 'id' => 'testapp', 'basePath' => __DIR__, ); - $appClass = $this->getParam( 'appClass', '\yii\web\Application' ); new $appClass(array_merge($defaultConfig,$config)); } diff --git a/tests/unit/data/config.php b/tests/unit/data/config.php index 88c8127..a2cc445 100644 --- a/tests/unit/data/config.php +++ b/tests/unit/data/config.php @@ -1,8 +1,6 @@ '\yii\web\Application', - 'appClass' => '\yii\console\Application', 'databases' => array( 'mysql' => array( 'dsn' => 'mysql:host=127.0.0.1;dbname=yiitest', diff --git a/tests/unit/framework/web/UrlManagerTest.php b/tests/unit/framework/web/UrlManagerTest.php index d0e8775..7da8f34 100644 --- a/tests/unit/framework/web/UrlManagerTest.php +++ b/tests/unit/framework/web/UrlManagerTest.php @@ -249,5 +249,57 @@ class UrlManagerTest extends TestCase $this->assertFalse($result); } - // TODO test RESTful pattern syntax e.g. 'GET index' => 'site/index' + public function testParseRESTRequest() + { + $manager = new UrlManager(array( + 'cache' => null, + )); + $request = new Request; + + // pretty URL rules + $manager = new UrlManager(array( + 'enablePrettyUrl' => true, + 'cache' => null, + 'rules' => array( + 'PUT,POST post//' => 'post/create', + 'DELETE post/<id>' => 'post/delete', + 'post/<id>/<title>' => 'post/view', + 'POST/GET' => 'post/get', + ), + )); + // matching pathinfo GET request + $_SERVER['REQUEST_METHOD'] = 'GET'; + $request->pathInfo = 'post/123/this+is+sample'; + $result = $manager->parseRequest($request); + $this->assertEquals(array('post/view', array('id' => '123', 'title' => 'this+is+sample')), $result); + // matching pathinfo PUT/POST request + $_SERVER['REQUEST_METHOD'] = 'PUT'; + $request->pathInfo = 'post/123/this+is+sample'; + $result = $manager->parseRequest($request); + $this->assertEquals(array('post/create', array('id' => '123', 'title' => 'this+is+sample')), $result); + $_SERVER['REQUEST_METHOD'] = 'POST'; + $request->pathInfo = 'post/123/this+is+sample'; + $result = $manager->parseRequest($request); + $this->assertEquals(array('post/create', array('id' => '123', 'title' => 'this+is+sample')), $result); + + // no wrong matching + $_SERVER['REQUEST_METHOD'] = 'POST'; + $request->pathInfo = 'POST/GET'; + $result = $manager->parseRequest($request); + $this->assertEquals(array('post/get', array()), $result); + + // createUrl should ignore REST rules + $this->mockApplication(array( + 'components' => array( + 'request' => array( + 'hostInfo' => 'http://localhost/', + 'baseUrl' => '/app' + ) + ) + ), \yii\web\Application::className()); + $this->assertEquals('/app/post/delete?id=123', $manager->createUrl('post/delete', array('id' => 123))); + $this->destroyApplication(); + + unset($_SERVER['REQUEST_METHOD']); + } } From 8157ea58048a080fa3755627aafe78015435db12 Mon Sep 17 00:00:00 2001 From: Qiang Xue <qiang.xue@gmail.com> Date: Mon, 3 Jun 2013 09:45:41 -0400 Subject: [PATCH 21/42] Fixes issue #481. --- framework/yii/validators/DateValidator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/yii/validators/DateValidator.php b/framework/yii/validators/DateValidator.php index 7370b78..2f3ce2d 100644 --- a/framework/yii/validators/DateValidator.php +++ b/framework/yii/validators/DateValidator.php @@ -58,7 +58,7 @@ class DateValidator extends Validator $date = DateTime::createFromFormat($this->format, $value); if ($date === false) { $this->addError($object, $attribute, $this->message); - } elseif ($this->timestampAttribute !== false) { + } elseif ($this->timestampAttribute !== null) { $object->{$this->timestampAttribute} = $date->getTimestamp(); } } From 5596e50bf3378be11867777c6e87922d3d44ac05 Mon Sep 17 00:00:00 2001 From: Qiang Xue <qiang.xue@gmail.com> Date: Mon, 3 Jun 2013 10:40:09 -0400 Subject: [PATCH 22/42] Fixes issue #472. --- framework/yii/bootstrap/Nav.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/framework/yii/bootstrap/Nav.php b/framework/yii/bootstrap/Nav.php index 029f178..6c091a4 100644 --- a/framework/yii/bootstrap/Nav.php +++ b/framework/yii/bootstrap/Nav.php @@ -128,8 +128,10 @@ class Nav extends Widget $this->addCssClass($urlOptions, 'dropdown-toggle'); $label .= ' ' . Html::tag('b', '', array('class' => 'caret')); if (is_array($dropdown)) { - $dropdown['clientOptions'] = false; - $dropdown = Dropdown::widget($dropdown); + $dropdown = Dropdown::widget(array( + 'items' => $dropdown, + 'clientOptions' => false, + )); } } From 8a25953f1c5405621f66eb17b2562a999dea5834 Mon Sep 17 00:00:00 2001 From: Tobias Munk <schmunk@usrbin.de> Date: Mon, 3 Jun 2013 18:22:59 +0200 Subject: [PATCH 23/42] updated docs added installation from dev repo section --- apps/advanced/README.md | 11 +++++++++++ apps/basic/README.md | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/apps/advanced/README.md b/apps/advanced/README.md index c443c90..cca2451 100644 --- a/apps/advanced/README.md +++ b/apps/advanced/README.md @@ -79,6 +79,17 @@ php composer.phar create-project --stability=dev yiisoft/yii2-app-advanced yii-a This is not currently available. We will provide it when Yii 2 is formally released. +### Install from development repository + +If you've cloned the [Yii 2 framework main development reop](https://github.com/yiisoft/yii2) you +can bootstrap your application with: + +~~~ +cd yii2/apps/advanced +php composer.phar create-project +~~~ + + GETTING STARTED --------------- diff --git a/apps/basic/README.md b/apps/basic/README.md index 5300448..ebe2bfe 100644 --- a/apps/basic/README.md +++ b/apps/basic/README.md @@ -59,3 +59,14 @@ assuming `yii-basic` is directly under the document root of your Web server. ### Install from an Archive File This is not currently available. We will provide it when Yii 2 is formally released. + + +### Install from development repository + +If you've cloned the [Yii 2 framework main development reop](https://github.com/yiisoft/yii2) you +can bootstrap your application with: + +~~~ +cd yii2/apps/basic +php composer.phar create-project +~~~ \ No newline at end of file From a2bfdcac187bf6cf3ab3c05d0b62bd471d6a9d99 Mon Sep 17 00:00:00 2001 From: Tobias Munk <schmunk@usrbin.de> Date: Mon, 3 Jun 2013 18:22:59 +0200 Subject: [PATCH 24/42] updated docs added installation from dev repo section --- apps/advanced/README.md | 15 +++++++++++++++ apps/basic/README.md | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/apps/advanced/README.md b/apps/advanced/README.md index c443c90..f021f81 100644 --- a/apps/advanced/README.md +++ b/apps/advanced/README.md @@ -79,6 +79,21 @@ php composer.phar create-project --stability=dev yiisoft/yii2-app-advanced yii-a This is not currently available. We will provide it when Yii 2 is formally released. +### Install from development repository + +If you've cloned the [Yii 2 framework main development reop](https://github.com/yiisoft/yii2) you +can bootstrap your application with: + +~~~ +cd yii2/apps/advanced +php composer.phar create-project +~~~ + +*Note: If the above command fails with `[RuntimeException] Not enough arguments.` run +`php composer.phar self-update` to obtain an updated version of composer which supports creating projects +from local packages.* + + GETTING STARTED --------------- diff --git a/apps/basic/README.md b/apps/basic/README.md index 5300448..f6f7f45 100644 --- a/apps/basic/README.md +++ b/apps/basic/README.md @@ -59,3 +59,18 @@ assuming `yii-basic` is directly under the document root of your Web server. ### Install from an Archive File This is not currently available. We will provide it when Yii 2 is formally released. + + +### Install from development repository + +If you've cloned the [Yii 2 framework main development reop](https://github.com/yiisoft/yii2) you +can bootstrap your application with: + +~~~ +cd yii2/apps/basic +php composer.phar create-project +~~~ + +*Note: If the above command fails with `[RuntimeException] Not enough arguments.` run +`php composer.phar self-update` to obtain an updated version of composer which supports creating projects +from local packages.* \ No newline at end of file From 6c179ef3a7fc0dfc787dfc5318ed554cd5124791 Mon Sep 17 00:00:00 2001 From: Klimov Paul <klimov.paul@gmail.com> Date: Mon, 3 Jun 2013 20:47:37 +0300 Subject: [PATCH 25/42] File creation checks at "AssetController" have been updated to use Exceptions. --- .../yii/console/controllers/AssetController.php | 25 +++++++++++++--------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/framework/yii/console/controllers/AssetController.php b/framework/yii/console/controllers/AssetController.php index 8e3de29..0d09570 100644 --- a/framework/yii/console/controllers/AssetController.php +++ b/framework/yii/console/controllers/AssetController.php @@ -159,7 +159,7 @@ class AssetController extends Controller } } - $this->getAssetManager(); // check asset manager configuration + $this->getAssetManager(); // check asset manager configuration is correct } /** @@ -420,7 +420,7 @@ class AssetController extends Controller } $array = var_export($array, true); $version = date('Y-m-d H:i:s', time()); - $bytesWritten = file_put_contents($bundleFile, <<<EOD + $bundleFileContent = <<<EOD <?php /** * This file is generated by the "yii script" command. @@ -428,9 +428,8 @@ class AssetController extends Controller * @version $version */ return $array; -EOD - ); - if ($bytesWritten <= 0) { +EOD; + if (!file_put_contents($bundleFile, $bundleFileContent)) { throw new Exception("Unable to write output bundle configuration at '{$bundleFile}'."); } echo "Output bundle configuration created at '{$bundleFile}'.\n"; @@ -498,6 +497,7 @@ EOD * Combines Java Script files into a single one. * @param array $inputFiles source file names. * @param string $outputFile output file name. + * @throws \yii\console\Exception on failure. */ public function combineJsFiles($inputFiles, $outputFile) { @@ -507,13 +507,16 @@ EOD . file_get_contents($file) . "/*** END FILE: $file ***/\n"; } - file_put_contents($outputFile, $content); + if (!file_put_contents($outputFile, $content)) { + throw new Exception("Unable to write output Java Script file '{$outputFile}'."); + } } /** * Combines CSS files into a single one. * @param array $inputFiles source file names. * @param string $outputFile output file name. + * @throws \yii\console\Exception on failure. */ public function combineCssFiles($inputFiles, $outputFile) { @@ -523,7 +526,9 @@ EOD . $this->adjustCssUrl(file_get_contents($file), dirname($file), dirname($outputFile)) . "/*** END FILE: $file ***/\n"; } - file_put_contents($outputFile, $content); + if (!file_put_contents($outputFile, $content)) { + throw new Exception("Unable to write output CSS file '{$outputFile}'."); + } } /** @@ -590,6 +595,7 @@ EOD /** * Creates template of configuration file for [[actionCompress]]. * @param string $configFile output file name. + * @throws \yii\console\Exception on failure. */ public function actionTemplate($configFile) { @@ -622,9 +628,8 @@ EOD; return; } } - $bytesWritten = file_put_contents($configFile, $template); - if ($bytesWritten<=0) { - echo "Error: unable to write file '{$configFile}'!\n\n"; + if (!file_put_contents($configFile, $template)) { + throw new Exception("Unable to write template file '{$configFile}'."); } else { echo "Configuration file template created at '{$configFile}'.\n\n"; } From 5172dbd4c4748f2913b08768e651522499bc5ccb Mon Sep 17 00:00:00 2001 From: Klimov Paul <klimov.paul@gmail.com> Date: Mon, 3 Jun 2013 21:25:04 +0300 Subject: [PATCH 26/42] Additional comments have been added to the "AssetController::actionTemplate" output. --- framework/yii/console/controllers/AssetController.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/framework/yii/console/controllers/AssetController.php b/framework/yii/console/controllers/AssetController.php index 0d09570..d794b30 100644 --- a/framework/yii/console/controllers/AssetController.php +++ b/framework/yii/console/controllers/AssetController.php @@ -601,13 +601,17 @@ EOD; { $template = <<<EOD <?php - +/** + * Configuration file for the "yii asset" console command. + * Note: in the console environment some path aliases like "@wwwroot" and "@www" may not exist, + * so corresponding paths should be specified directly. + */ return array( - // + // The list of asset bundles, which files should be included to compression: 'bundles' => require('path/to/bundles.php'), - // + // The list of extensions, which asset files should be included to compression: 'extensions' => require('path/to/namespaces.php'), - // + // Compression result asset bundle: 'targets' => array( 'all' => array( 'basePath' => __DIR__, @@ -616,7 +620,7 @@ return array( 'css' => 'all-{ts}.css', ), ), - + // Asset manager configuration: 'assetManager' => array( 'basePath' => __DIR__, 'baseUrl' => '/test', From 9b8b285eb1b3b639324994f72c6c64d47a5aa09e Mon Sep 17 00:00:00 2001 From: Klimov Paul <klimov.paul@gmail.com> Date: Mon, 3 Jun 2013 21:43:54 +0300 Subject: [PATCH 27/42] Doc comments at "AssetController" have been extended. --- framework/yii/console/controllers/AssetController.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/framework/yii/console/controllers/AssetController.php b/framework/yii/console/controllers/AssetController.php index d794b30..dab7e90 100644 --- a/framework/yii/console/controllers/AssetController.php +++ b/framework/yii/console/controllers/AssetController.php @@ -14,6 +14,20 @@ use yii\console\Controller; /** * This command allows you to combine and compress your JavaScript and CSS files. * + * Usage: + * 1. Create a configuration file using 'template' action: + * yii asset/template /path/to/myapp/config.php + * 2. Edit the created config file, adjusting it for your web application needs. + * 3. Run the 'compress' action, using created config: + * yii asset /path/to/myapp/config.php /path/to/myapp/config/assets_compressed.php + * 4. Adjust your web application config to use compressed assets. + * + * Note: in the console environment some path aliases like '@wwwroot' and '@www' may not exist, + * so corresponding paths inside the configuration should be specified directly. + * + * Note: by default this command relies on an external tools to perform actual files compression, + * check [[jsCompressor]] and [[cssCompressor]] for more details. + * * @property array|\yii\web\AssetManager $assetManager asset manager, which will be used for assets processing. * * @author Qiang Xue <qiang.xue@gmail.com> From 1f68becb61767fb83cc1310404572ff99d244b3e Mon Sep 17 00:00:00 2001 From: Klimov Paul <klimov.paul@gmail.com> Date: Mon, 3 Jun 2013 21:46:56 +0300 Subject: [PATCH 28/42] Doc comments at "AssetController" have been updated. --- framework/yii/console/controllers/AssetController.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/yii/console/controllers/AssetController.php b/framework/yii/console/controllers/AssetController.php index dab7e90..61e54e9 100644 --- a/framework/yii/console/controllers/AssetController.php +++ b/framework/yii/console/controllers/AssetController.php @@ -57,7 +57,7 @@ class AssetController extends Controller * ~~~ * 'all' => array( * 'css' => 'all.css', - * 'js' => 'js.css', + * 'js' => 'all.js', * 'depends' => array( ... ), * ) * ~~~ @@ -322,7 +322,7 @@ class AssetController extends Controller /** * Builds output asset bundle. * @param \yii\web\AssetBundle $target output asset bundle - * @param string $type either "js" or "css". + * @param string $type either 'js' or 'css'. * @param \yii\web\AssetBundle[] $bundles source asset bundles. * @param integer $timestamp current timestamp. * @throws Exception on failure. @@ -617,7 +617,7 @@ EOD; <?php /** * Configuration file for the "yii asset" console command. - * Note: in the console environment some path aliases like "@wwwroot" and "@www" may not exist, + * Note: in the console environment some path aliases like '@wwwroot' and '@www' may not exist, * so corresponding paths should be specified directly. */ return array( From dfe2d00785d0bc86a1ac92a8f9bbb7a7f8aaea4f Mon Sep 17 00:00:00 2001 From: Klimov Paul <klimov.paul@gmail.com> Date: Mon, 3 Jun 2013 21:53:07 +0300 Subject: [PATCH 29/42] Output of "AssetController::actionCompress" have been adjusted to hold the action id. --- framework/yii/console/controllers/AssetController.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/yii/console/controllers/AssetController.php b/framework/yii/console/controllers/AssetController.php index 61e54e9..e525ef1 100644 --- a/framework/yii/console/controllers/AssetController.php +++ b/framework/yii/console/controllers/AssetController.php @@ -437,11 +437,11 @@ class AssetController extends Controller $bundleFileContent = <<<EOD <?php /** - * This file is generated by the "yii script" command. + * This file is generated by the "yii {$this->id}" command. * DO NOT MODIFY THIS FILE DIRECTLY. - * @version $version + * @version {$version} */ -return $array; +return {$array}; EOD; if (!file_put_contents($bundleFile, $bundleFileContent)) { throw new Exception("Unable to write output bundle configuration at '{$bundleFile}'."); From ec8fecb8b079b3eec4a66df67e91cc3412fc77e5 Mon Sep 17 00:00:00 2001 From: Klimov Paul <klimov.paul@gmail.com> Date: Mon, 3 Jun 2013 21:56:03 +0300 Subject: [PATCH 30/42] Check output bundle file format has been added to "AssetControllerTest::testActionCompress()" unit test. --- tests/unit/framework/console/controllers/AssetControllerTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/framework/console/controllers/AssetControllerTest.php b/tests/unit/framework/console/controllers/AssetControllerTest.php index db6d2a7..9d7dd28 100644 --- a/tests/unit/framework/console/controllers/AssetControllerTest.php +++ b/tests/unit/framework/console/controllers/AssetControllerTest.php @@ -239,6 +239,7 @@ class AssetControllerTest extends TestCase // Then : $this->assertTrue(file_exists($bundleFile), 'Unable to create output bundle file!'); + $this->assertTrue(is_array(require($bundleFile)), 'Output bundle file has incorrect format!'); $compressedCssFileName = $this->testAssetsBasePath . DIRECTORY_SEPARATOR . 'all.css'; $this->assertTrue(file_exists($compressedCssFileName), 'Unable to compress CSS files!'); From 152e5a0e15f1f6edf9106adf61dbaa1e0423d366 Mon Sep 17 00:00:00 2001 From: Klimov Paul <klimov.paul@gmail.com> Date: Mon, 3 Jun 2013 22:34:15 +0300 Subject: [PATCH 31/42] Doc comments and descriptive output at"AssetController" has been adjusted. --- framework/yii/console/controllers/AssetController.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/framework/yii/console/controllers/AssetController.php b/framework/yii/console/controllers/AssetController.php index e525ef1..4c759de 100644 --- a/framework/yii/console/controllers/AssetController.php +++ b/framework/yii/console/controllers/AssetController.php @@ -71,7 +71,7 @@ class AssetController extends Controller */ private $_assetManager = array(); /** - * @var string|callback Java Script file compressor. + * @var string|callback JavaScript file compressor. * If a string, it is treated as shell command template, which should contain * placeholders {from} - source file name - and {to} - output file name. * Otherwise, it is treated as PHP callback, which should perform the compression. @@ -173,7 +173,7 @@ class AssetController extends Controller } } - $this->getAssetManager(); // check asset manager configuration is correct + $this->getAssetManager(); // check if asset manager configuration is correct } /** @@ -450,7 +450,7 @@ EOD; } /** - * Compresses given Java Script files and combines them into the single one. + * Compresses given JavaScript files and combines them into the single one. * @param array $inputFiles list of source file names. * @param string $outputFile output file name. * @throws \yii\console\Exception on failure @@ -508,7 +508,7 @@ EOD; } /** - * Combines Java Script files into a single one. + * Combines JavaScript files into a single one. * @param array $inputFiles source file names. * @param string $outputFile output file name. * @throws \yii\console\Exception on failure. @@ -522,7 +522,7 @@ EOD; . "/*** END FILE: $file ***/\n"; } if (!file_put_contents($outputFile, $content)) { - throw new Exception("Unable to write output Java Script file '{$outputFile}'."); + throw new Exception("Unable to write output JavaScript file '{$outputFile}'."); } } @@ -621,11 +621,11 @@ EOD; * so corresponding paths should be specified directly. */ return array( - // The list of asset bundles, which files should be included to compression: + // The list of asset bundles to compress: 'bundles' => require('path/to/bundles.php'), - // The list of extensions, which asset files should be included to compression: + // The list of extensions to compress: 'extensions' => require('path/to/namespaces.php'), - // Compression result asset bundle: + // Asset bundle for compression output: 'targets' => array( 'all' => array( 'basePath' => __DIR__, From 084d709e44f8e0b4985e52ac3aa1f4db319d849e Mon Sep 17 00:00:00 2001 From: Alexander Makarov <sam@rmcreative.ru> Date: Mon, 3 Jun 2013 23:39:08 +0400 Subject: [PATCH 32/42] fixed typo in app readmes --- apps/advanced/README.md | 2 +- apps/basic/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/advanced/README.md b/apps/advanced/README.md index f021f81..d8c1e17 100644 --- a/apps/advanced/README.md +++ b/apps/advanced/README.md @@ -81,7 +81,7 @@ This is not currently available. We will provide it when Yii 2 is formally relea ### Install from development repository -If you've cloned the [Yii 2 framework main development reop](https://github.com/yiisoft/yii2) you +If you've cloned the [Yii 2 framework main development repository](https://github.com/yiisoft/yii2) you can bootstrap your application with: ~~~ diff --git a/apps/basic/README.md b/apps/basic/README.md index c7f6abe..2f8f1e8 100644 --- a/apps/basic/README.md +++ b/apps/basic/README.md @@ -63,7 +63,7 @@ This is not currently available. We will provide it when Yii 2 is formally relea ### Install from development repository -If you've cloned the [Yii 2 framework main development reop](https://github.com/yiisoft/yii2) you +If you've cloned the [Yii 2 framework main development repository](https://github.com/yiisoft/yii2) you can bootstrap your application with: ~~~ From 5ecb5e3bd0617b0c291d9ce3b3c59eebd6c3704f Mon Sep 17 00:00:00 2001 From: Qiang Xue <qiang.xue@gmail.com> Date: Tue, 4 Jun 2013 17:08:26 -0400 Subject: [PATCH 33/42] Fixed Formatter doc. --- framework/yii/i18n/Formatter.php | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/framework/yii/i18n/Formatter.php b/framework/yii/i18n/Formatter.php index d688a15..4a93397 100644 --- a/framework/yii/i18n/Formatter.php +++ b/framework/yii/i18n/Formatter.php @@ -30,19 +30,28 @@ class Formatter extends \yii\base\Formatter */ public $locale; /** - * @var string the default format string to be used to format a date using PHP date() function. + * @var string the default format string to be used to format a date. + * This can be "short", "medium", "long", or "full", which represents a preset format of different lengths. + * It can also be a custom format as specified in the [ICU manual](http://userguide.icu-project.org/formatparse/datetime). */ public $dateFormat = 'short'; /** - * @var string the default format string to be used to format a time using PHP date() function. + * @var string the default format string to be used to format a time. + * This can be "short", "medium", "long", or "full", which represents a preset format of different lengths. + * It can also be a custom format as specified in the [ICU manual](http://userguide.icu-project.org/formatparse/datetime). */ public $timeFormat = 'short'; /** - * @var string the default format string to be used to format a date and time using PHP date() function. + * @var string the default format string to be used to format a date and time. + * This can be "short", "medium", "long", or "full", which represents a preset format of different lengths. + * It can also be a custom format as specified in the [ICU manual](http://userguide.icu-project.org/formatparse/datetime). */ public $datetimeFormat = 'short'; /** * @var array the options to be set for the NumberFormatter objects. Please refer to + * [PHP manual](http://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants.unumberformatattribute) + * for the possible options. This property is used by [[createNumberFormatter]] when + * creating a new number formatter to format decimals, currencies, etc. */ public $numberFormatOptions = array(); @@ -81,8 +90,11 @@ class Formatter extends \yii\base\Formatter * - a PHP DateTime object * * @param string $format the format used to convert the value into a date string. - * If null, [[dateFormat]] will be used. The format string should be the one - * that can be recognized by the PHP `date()` function. + * If null, [[dateFormat]] will be used. + * + * This can be "short", "medium", "long", or "full", which represents a preset format of different lengths. + * It can also be a custom format as specified in the [ICU manual](http://userguide.icu-project.org/formatparse/datetime). + * * @return string the formatted result * @see dateFormat */ @@ -111,8 +123,11 @@ class Formatter extends \yii\base\Formatter * - a PHP DateTime object * * @param string $format the format used to convert the value into a date string. - * If null, [[dateFormat]] will be used. The format string should be the one - * that can be recognized by the PHP `date()` function. + * If null, [[dateFormat]] will be used. + * + * This can be "short", "medium", "long", or "full", which represents a preset format of different lengths. + * It can also be a custom format as specified in the [ICU manual](http://userguide.icu-project.org/formatparse/datetime). + * * @return string the formatted result * @see timeFormat */ @@ -141,8 +156,11 @@ class Formatter extends \yii\base\Formatter * - a PHP DateTime object * * @param string $format the format used to convert the value into a date string. - * If null, [[dateFormat]] will be used. The format string should be the one - * that can be recognized by the PHP `date()` function. + * If null, [[dateFormat]] will be used. + * + * This can be "short", "medium", "long", or "full", which represents a preset format of different lengths. + * It can also be a custom format as specified in the [ICU manual](http://userguide.icu-project.org/formatparse/datetime). + * * @return string the formatted result * @see datetimeFormat */ @@ -213,7 +231,7 @@ class Formatter extends \yii\base\Formatter /** * Creates a number formatter based on the given type and format. * @param integer $type the type of the number formatter - * @param string $format the format to be used + * @param string $format the format to be used. Please refer to [ICU manual](http://www.icu-project.org/apiref/icu4c/classDecimalFormat.html#_details) * @return NumberFormatter the created formatter instance */ protected function createNumberFormatter($type, $format) From cbf642d93147442daffdd5eb4e8b184480ab1313 Mon Sep 17 00:00:00 2001 From: Qiang Xue <qiang.xue@gmail.com> Date: Tue, 4 Jun 2013 17:21:40 -0400 Subject: [PATCH 34/42] Added support for locale-dependent decimal and grouping separators. --- framework/yii/base/Formatter.php | 18 +++++++++++++----- framework/yii/i18n/Formatter.php | 20 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/framework/yii/base/Formatter.php b/framework/yii/base/Formatter.php index d15e5f2..e62039e 100644 --- a/framework/yii/base/Formatter.php +++ b/framework/yii/base/Formatter.php @@ -39,17 +39,19 @@ class Formatter extends Component public $datetimeFormat = 'Y/m/d h:i:s A'; /** * @var array the text to be displayed when formatting a boolean value. The first element corresponds - * to the text display for false, the second element for true. Defaults to <code>array('No', 'Yes')</code>. + * to the text display for false, the second element for true. Defaults to `array('No', 'Yes')`. */ public $booleanFormat; /** * @var string the character displayed as the decimal point when formatting a number. + * If not set, "." will be used. */ - public $decimalSeparator = '.'; + public $decimalSeparator; /** * @var string the character displayed as the thousands separator character when formatting a number. + * If not set, "," will be used. */ - public $thousandSeparator = ','; + public $thousandSeparator; /** @@ -273,7 +275,11 @@ class Formatter extends Component */ public function asDouble($value, $decimals = 2) { - return str_replace('.', $this->decimalSeparator, sprintf("%.{$decimals}f", $value)); + if ($this->decimalSeparator === null) { + return sprintf("%.{$decimals}f", $value); + } else { + return str_replace('.', $this->decimalSeparator, sprintf("%.{$decimals}f", $value)); + } } /** @@ -287,6 +293,8 @@ class Formatter extends Component */ public function asNumber($value, $decimals = 0) { - return number_format($value, $decimals, $this->decimalSeparator, $this->thousandSeparator); + $ds = isset($this->decimalSeparator) ? $this->decimalSeparator: '.'; + $ts = isset($this->thousandSeparator) ? $this->thousandSeparator: ','; + return number_format($value, $decimals, $ds, $ts); } } diff --git a/framework/yii/i18n/Formatter.php b/framework/yii/i18n/Formatter.php index 4a93397..8fa29dd 100644 --- a/framework/yii/i18n/Formatter.php +++ b/framework/yii/i18n/Formatter.php @@ -54,6 +54,16 @@ class Formatter extends \yii\base\Formatter * creating a new number formatter to format decimals, currencies, etc. */ public $numberFormatOptions = array(); + /** + * @var string the character displayed as the decimal point when formatting a number. + * If not set, the decimal separator corresponding to [[locale]] will be used. + */ + public $decimalSeparator; + /** + * @var string the character displayed as the thousands separator character when formatting a number. + * If not set, the thousand separator corresponding to [[locale]] will be used. + */ + public $thousandSeparator; /** @@ -70,6 +80,16 @@ class Formatter extends \yii\base\Formatter if ($this->locale === null) { $this->locale = Yii::$app->language; } + if ($this->decimalSeparator === null || $this->thousandSeparator === null) { + $formatter = new NumberFormatter($this->locale, NumberFormatter::DECIMAL); + if ($this->decimalSeparator === null) { + $this->decimalSeparator = $formatter->getSymbol(NumberFormatter::GROUPING_SEPARATOR_SYMBOL); + } + if ($this->thousandSeparator === null) { + $this->thousandSeparator = $formatter->getSymbol(NumberFormatter::DECIMAL_SEPARATOR_SYMBOL); + } + } + parent::init(); } From 23767304527a989c2e664f2522c0acacc857b615 Mon Sep 17 00:00:00 2001 From: Qiang Xue <qiang.xue@gmail.com> Date: Tue, 4 Jun 2013 18:11:50 -0400 Subject: [PATCH 35/42] better check of existence of tables. --- framework/yii/db/ActiveRecord.php | 8 +++++++- framework/yii/db/mysql/Schema.php | 8 ++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/framework/yii/db/ActiveRecord.php b/framework/yii/db/ActiveRecord.php index 58411f0..6faebbf 100644 --- a/framework/yii/db/ActiveRecord.php +++ b/framework/yii/db/ActiveRecord.php @@ -275,10 +275,16 @@ class ActiveRecord extends Model /** * Returns the schema information of the DB table associated with this AR class. * @return TableSchema the schema information of the DB table associated with this AR class. + * @throws InvalidConfigException if the table for the AR class does not exist. */ public static function getTableSchema() { - return static::getDb()->getTableSchema(static::tableName()); + $schema = static::getDb()->getTableSchema(static::tableName()); + if ($schema !== null) { + return $schema; + } else { + throw new InvalidConfigException("The table does not exist: " . static::tableName()); + } } /** diff --git a/framework/yii/db/mysql/Schema.php b/framework/yii/db/mysql/Schema.php index 501149a..e7b34e0 100644 --- a/framework/yii/db/mysql/Schema.php +++ b/framework/yii/db/mysql/Schema.php @@ -181,12 +181,12 @@ class Schema extends \yii\db\Schema */ protected function findColumns($table) { - $sql = 'SHOW FULL COLUMNS FROM ' . $this->quoteSimpleTableName($table->name); - try { - $columns = $this->db->createCommand($sql)->queryAll(); - } catch (\Exception $e) { + $rows = $this->db->createCommand("SHOW TABLES LIKE " . $this->quoteValue($table->name))->queryAll(); + if (count($rows) === 0) { return false; } + $sql = 'SHOW FULL COLUMNS FROM ' . $this->quoteSimpleTableName($table->name); + $columns = $this->db->createCommand($sql)->queryAll(); foreach ($columns as $info) { $column = $this->loadColumnSchema($info); $table->columns[$column->name] = $column; From b311b6ecf3b0168024dbe0241faa6c5dea9184fd Mon Sep 17 00:00:00 2001 From: Qiang Xue <qiang.xue@gmail.com> Date: Tue, 4 Jun 2013 18:13:32 -0400 Subject: [PATCH 36/42] typo fix. --- framework/yii/i18n/Formatter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/yii/i18n/Formatter.php b/framework/yii/i18n/Formatter.php index 8fa29dd..948e277 100644 --- a/framework/yii/i18n/Formatter.php +++ b/framework/yii/i18n/Formatter.php @@ -83,10 +83,10 @@ class Formatter extends \yii\base\Formatter if ($this->decimalSeparator === null || $this->thousandSeparator === null) { $formatter = new NumberFormatter($this->locale, NumberFormatter::DECIMAL); if ($this->decimalSeparator === null) { - $this->decimalSeparator = $formatter->getSymbol(NumberFormatter::GROUPING_SEPARATOR_SYMBOL); + $this->decimalSeparator = $formatter->getSymbol(NumberFormatter::DECIMAL_SEPARATOR_SYMBOL); } if ($this->thousandSeparator === null) { - $this->thousandSeparator = $formatter->getSymbol(NumberFormatter::DECIMAL_SEPARATOR_SYMBOL); + $this->thousandSeparator = $formatter->getSymbol(NumberFormatter::GROUPING_SEPARATOR_SYMBOL); } } From 9d6f11d5d524afeacd9cb702612d8667c15a6e3c Mon Sep 17 00:00:00 2001 From: Qiang Xue <qiang.xue@gmail.com> Date: Tue, 4 Jun 2013 19:34:51 -0400 Subject: [PATCH 37/42] new way of detecting if table exists. --- framework/yii/db/mysql/Schema.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/framework/yii/db/mysql/Schema.php b/framework/yii/db/mysql/Schema.php index e7b34e0..b42ef15 100644 --- a/framework/yii/db/mysql/Schema.php +++ b/framework/yii/db/mysql/Schema.php @@ -178,15 +178,21 @@ class Schema extends \yii\db\Schema * Collects the metadata of table columns. * @param TableSchema $table the table metadata * @return boolean whether the table exists in the database + * @throws \Exception if DB query fails */ protected function findColumns($table) { - $rows = $this->db->createCommand("SHOW TABLES LIKE " . $this->quoteValue($table->name))->queryAll(); - if (count($rows) === 0) { - return false; - } $sql = 'SHOW FULL COLUMNS FROM ' . $this->quoteSimpleTableName($table->name); - $columns = $this->db->createCommand($sql)->queryAll(); + try { + $columns = $this->db->createCommand($sql)->queryAll(); + } catch (\Exception $e) { + $previous = $e->getPrevious(); + if ($previous instanceof \PDOException && $previous->getCode() == '42S02') { + // table does not exist + return false; + } + throw $e; + } foreach ($columns as $info) { $column = $this->loadColumnSchema($info); $table->columns[$column->name] = $column; From 7e111e92e2865a94359962fe323b5b759441b4f6 Mon Sep 17 00:00:00 2001 From: Qiang Xue <qiang.xue@gmail.com> Date: Wed, 5 Jun 2013 06:15:31 -0400 Subject: [PATCH 38/42] Fixes issue #496 --- framework/yii/logging/Target.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/framework/yii/logging/Target.php b/framework/yii/logging/Target.php index fac8b53..7be7001 100644 --- a/framework/yii/logging/Target.php +++ b/framework/yii/logging/Target.php @@ -204,11 +204,9 @@ abstract class Target extends Component if ($matched) { foreach ($this->except as $category) { $prefix = rtrim($category, '*'); - foreach ($messages as $i => $message) { - if (strpos($message[2], $prefix) === 0 && ($message[2] === $category || $prefix !== $category)) { - $matched = false; - break; - } + if (strpos($message[2], $prefix) === 0 && ($message[2] === $category || $prefix !== $category)) { + $matched = false; + break; } } } From b7c1f949776bb9f4b55b0ac2d55429e8ab3a681a Mon Sep 17 00:00:00 2001 From: Qiang Xue <qiang.xue@gmail.com> Date: Wed, 5 Jun 2013 08:28:36 -0400 Subject: [PATCH 39/42] Fixed bug about setting default path aliases. --- framework/yii/base/Application.php | 62 +++++++++++++++++--------------------- framework/yii/base/Module.php | 3 ++ 2 files changed, 31 insertions(+), 34 deletions(-) diff --git a/framework/yii/base/Application.php b/framework/yii/base/Application.php index 495c1f8..09951bd 100644 --- a/framework/yii/base/Application.php +++ b/framework/yii/base/Application.php @@ -67,10 +67,20 @@ class Application extends Module * Constructor. * @param array $config name-value pairs that will be used to initialize the object properties. * Note that the configuration must contain both [[id]] and [[basePath]]. + * @throws InvalidConfigException if either [[id]] or [[basePath]] configuration is missing. */ public function __construct($config = array()) { Yii::$app = $this; + if (!isset($config['id'])) { + throw new InvalidConfigException('The "id" configuration is required.'); + } + if (isset($config['basePath'])) { + $this->setBasePath($config['basePath']); + unset($config['basePath']); + } else { + throw new InvalidConfigException('The "basePath" configuration is required.'); + } $this->preInit($config); @@ -83,37 +93,24 @@ class Application extends Module /** * Pre-initializes the application. * This method is called at the beginning of the application constructor. - * When this method is called, none of the application properties are initialized yet. - * The default implementation will initialize a few important properties - * that may be referenced during the initialization of the rest of the properties. * @param array $config the application configuration - * @throws InvalidConfigException if either [[id]] or [[basePath]] configuration is missing. */ - public function preInit($config) + public function preInit(&$config) { - if (!isset($config['id'])) { - throw new InvalidConfigException('The "id" configuration is required.'); - } - if (!isset($config['basePath'])) { - throw new InvalidConfigException('The "basePath" configuration is required.'); - } - - $this->setBasePath($config['basePath']); - Yii::setAlias('@app', $this->getBasePath()); - unset($config['basePath']); - - if (isset($config['vendor'])) { - $this->setVendorPath($config['vendor']); + if (isset($config['vendorPath'])) { + $this->setVendorPath($config['vendorPath']); unset($config['vendorPath']); + } else { + // set "@vendor" + $this->getVendorPath(); } - Yii::setAlias('@vendor', $this->getVendorPath()); - - if (isset($config['runtime'])) { - $this->setRuntimePath($config['runtime']); - unset($config['runtime']); + if (isset($config['runtimePath'])) { + $this->setRuntimePath($config['runtimePath']); + unset($config['runtimePath']); + } else { + // set "@runtime" + $this->getRuntimePath(); } - Yii::setAlias('@runtime', $this->getRuntimePath()); - if (isset($config['timeZone'])) { $this->setTimeZone($config['timeZone']); unset($config['timeZone']); @@ -202,7 +199,8 @@ class Application extends Module /** * Returns the directory that stores runtime files. - * @return string the directory that stores runtime files. Defaults to 'protected/runtime'. + * @return string the directory that stores runtime files. + * Defaults to the "runtime" subdirectory under [[basePath]]. */ public function getRuntimePath() { @@ -215,16 +213,11 @@ class Application extends Module /** * Sets the directory that stores runtime files. * @param string $path the directory that stores runtime files. - * @throws InvalidConfigException if the directory does not exist or is not writable */ public function setRuntimePath($path) { - $path = Yii::getAlias($path); - if (is_dir($path) && is_writable($path)) { - $this->_runtimePath = $path; - } else { - throw new InvalidConfigException("Runtime path must be a directory writable by the Web server process: $path"); - } + $this->_runtimePath = Yii::getAlias($path); + Yii::setAlias('@runtime', $this->_runtimePath); } private $_vendorPath; @@ -232,7 +225,7 @@ class Application extends Module /** * Returns the directory that stores vendor files. * @return string the directory that stores vendor files. - * Defaults to 'vendor' directory under applications [[basePath]]. + * Defaults to "vendor" directory under [[basePath]]. */ public function getVendorPath() { @@ -249,6 +242,7 @@ class Application extends Module public function setVendorPath($path) { $this->_vendorPath = Yii::getAlias($path); + Yii::setAlias('@vendor', $this->_vendorPath); } /** diff --git a/framework/yii/base/Module.php b/framework/yii/base/Module.php index fac4164..5f5c376 100644 --- a/framework/yii/base/Module.php +++ b/framework/yii/base/Module.php @@ -236,6 +236,9 @@ abstract class Module extends Component $p = realpath($path); if ($p !== false && is_dir($p)) { $this->_basePath = $p; + if ($this instanceof Application) { + Yii::setAlias('@app', $p); + } } else { throw new InvalidParamException("The directory does not exist: $path"); } From 67d677b21e5693cf0f96c600d3035aba398f5381 Mon Sep 17 00:00:00 2001 From: Qiang Xue <qiang.xue@gmail.com> Date: Wed, 5 Jun 2013 13:26:01 -0400 Subject: [PATCH 40/42] Renamed Request::getRequestMethod() to Request::getMethod(). --- framework/yii/web/AccessRule.php | 2 +- framework/yii/web/HttpCache.php | 2 +- framework/yii/web/Request.php | 14 +++++++------- framework/yii/web/UrlRule.php | 2 +- framework/yii/web/VerbFilter.php | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/framework/yii/web/AccessRule.php b/framework/yii/web/AccessRule.php index 3897769..9bd52ce 100644 --- a/framework/yii/web/AccessRule.php +++ b/framework/yii/web/AccessRule.php @@ -99,7 +99,7 @@ class AccessRule extends Component if ($this->matchAction($action) && $this->matchRole($user) && $this->matchIP($request->getUserIP()) - && $this->matchVerb($request->getRequestMethod()) + && $this->matchVerb($request->getMethod()) && $this->matchController($action->controller) && $this->matchCustom($action) ) { diff --git a/framework/yii/web/HttpCache.php b/framework/yii/web/HttpCache.php index 0a3bb86..5b7682d 100644 --- a/framework/yii/web/HttpCache.php +++ b/framework/yii/web/HttpCache.php @@ -60,7 +60,7 @@ class HttpCache extends ActionFilter */ public function beforeAction($action) { - $verb = Yii::$app->request->getRequestMethod(); + $verb = Yii::$app->request->getMethod(); if ($verb !== 'GET' && $verb !== 'HEAD' || $this->lastModified === null && $this->etagSeed === null) { return true; } diff --git a/framework/yii/web/Request.php b/framework/yii/web/Request.php index a857926..9b1e91c 100644 --- a/framework/yii/web/Request.php +++ b/framework/yii/web/Request.php @@ -49,7 +49,7 @@ class Request extends \yii\base\Request /** * @var string|boolean the name of the POST parameter that is used to indicate if a request is a PUT or DELETE * request tunneled through POST. Default to '_method'. - * @see getRequestMethod + * @see getMethod * @see getRestParams */ public $restVar = '_method'; @@ -81,7 +81,7 @@ class Request extends \yii\base\Request * @return string request method, such as GET, POST, HEAD, PUT, DELETE. * The value returned is turned into upper case. */ - public function getRequestMethod() + public function getMethod() { if (isset($_POST[$this->restVar])) { return strtoupper($_POST[$this->restVar]); @@ -96,7 +96,7 @@ class Request extends \yii\base\Request */ public function getIsPostRequest() { - return $this->getRequestMethod() === 'POST'; + return $this->getMethod() === 'POST'; } /** @@ -105,7 +105,7 @@ class Request extends \yii\base\Request */ public function getIsDeleteRequest() { - return $this->getRequestMethod() === 'DELETE'; + return $this->getMethod() === 'DELETE'; } /** @@ -114,7 +114,7 @@ class Request extends \yii\base\Request */ public function getIsPutRequest() { - return $this->getRequestMethod() === 'PUT'; + return $this->getMethod() === 'PUT'; } /** @@ -141,7 +141,7 @@ class Request extends \yii\base\Request /** * Returns the request parameters for the RESTful request. * @return array the RESTful request parameters - * @see getRequestMethod + * @see getMethod */ public function getRestParams() { @@ -772,7 +772,7 @@ class Request extends \yii\base\Request if (!$this->enableCsrfValidation) { return; } - $method = $this->getRequestMethod(); + $method = $this->getMethod(); if ($method === 'POST' || $method === 'PUT' || $method === 'DELETE') { $cookies = $this->getCookies(); switch ($method) { diff --git a/framework/yii/web/UrlRule.php b/framework/yii/web/UrlRule.php index b1e74da..fc19ea3 100644 --- a/framework/yii/web/UrlRule.php +++ b/framework/yii/web/UrlRule.php @@ -171,7 +171,7 @@ class UrlRule extends Object return false; } - if ($this->verb !== null && !in_array($request->getRequestMethod(), $this->verb, true)) { + if ($this->verb !== null && !in_array($request->getMethod(), $this->verb, true)) { return false; } diff --git a/framework/yii/web/VerbFilter.php b/framework/yii/web/VerbFilter.php index 9b475e3..ca6d47d 100644 --- a/framework/yii/web/VerbFilter.php +++ b/framework/yii/web/VerbFilter.php @@ -76,7 +76,7 @@ class VerbFilter extends Behavior { $action = $event->action->id; if (isset($this->actions[$action])) { - $verb = Yii::$app->getRequest()->getRequestMethod(); + $verb = Yii::$app->getRequest()->getMethod(); $allowed = array_map('strtoupper', $this->actions[$action]); if (!in_array($verb, $allowed)) { $event->isValid = false; From 70e973129da2beaa4608175e08526e7b96952853 Mon Sep 17 00:00:00 2001 From: Gevik Babakhani <gevik@ext4yii.com> Date: Thu, 6 Jun 2013 11:29:28 +0200 Subject: [PATCH 41/42] Added foreign keys and cleanup internal pg types --- framework/yii/db/pgsql/QueryBuilder.php | 10 +--- framework/yii/db/pgsql/Schema.php | 99 +++++++++++++++++++++++---------- 2 files changed, 71 insertions(+), 38 deletions(-) diff --git a/framework/yii/db/pgsql/QueryBuilder.php b/framework/yii/db/pgsql/QueryBuilder.php index c0d5089..0cd9d94 100644 --- a/framework/yii/db/pgsql/QueryBuilder.php +++ b/framework/yii/db/pgsql/QueryBuilder.php @@ -8,9 +8,6 @@ namespace yii\db\pgsql; -use yii\db\Exception; -use yii\base\InvalidParamException; - /** * QueryBuilder is the query builder for PostgreSQL databases. * @@ -24,7 +21,7 @@ class QueryBuilder extends \yii\db\QueryBuilder { */ public $typeMap = array( Schema::TYPE_PK => 'bigserial not null primary key', - Schema::TYPE_STRING => 'varchar(255)', + Schema::TYPE_STRING => 'varchar', Schema::TYPE_TEXT => 'text', Schema::TYPE_SMALLINT => 'smallint', Schema::TYPE_INTEGER => 'integer', @@ -40,9 +37,4 @@ class QueryBuilder extends \yii\db\QueryBuilder { Schema::TYPE_MONEY => 'numeric(19,4)', ); - public function insert($table, $columns, &$params) { - $sql = parent::insert($table, $columns, $params); - return $sql . ' RETURNING *'; - } - } diff --git a/framework/yii/db/pgsql/Schema.php b/framework/yii/db/pgsql/Schema.php index 5203ceb..1e19383 100644 --- a/framework/yii/db/pgsql/Schema.php +++ b/framework/yii/db/pgsql/Schema.php @@ -33,31 +33,24 @@ class Schema extends \yii\db\Schema { */ public $typeMap = array( 'abstime' => self::TYPE_TIMESTAMP, - //'aclitem' => self::TYPE_STRING, 'bit' => self::TYPE_STRING, 'boolean' => self::TYPE_BOOLEAN, 'box' => self::TYPE_STRING, 'character' => self::TYPE_STRING, 'bytea' => self::TYPE_BINARY, 'char' => self::TYPE_STRING, - //'cid' => self::TYPE_STRING, 'cidr' => self::TYPE_STRING, 'circle' => self::TYPE_STRING, 'date' => self::TYPE_DATE, - //'daterange' => self::TYPE_STRING, 'real' => self::TYPE_FLOAT, 'double precision' => self::TYPE_DECIMAL, - //'gtsvector' => self::TYPE_STRING, 'inet' => self::TYPE_STRING, 'smallint' => self::TYPE_SMALLINT, 'integer' => self::TYPE_INTEGER, - //'int4range' => self::TYPE_STRING, //unknown 'bigint' => self::TYPE_BIGINT, - //'int8range' => self::TYPE_STRING, // unknown 'interval' => self::TYPE_STRING, 'json' => self::TYPE_STRING, 'line' => self::TYPE_STRING, - //'lseg' => self::TYPE_STRING, 'macaddr' => self::TYPE_STRING, 'money' => self::TYPE_MONEY, 'name' => self::TYPE_STRING, @@ -65,38 +58,49 @@ class Schema extends \yii\db\Schema { 'numrange' => self::TYPE_DECIMAL, 'oid' => self::TYPE_BIGINT, // should not be used. it's pg internal! 'path' => self::TYPE_STRING, - //'pg_node_tree' => self::TYPE_STRING, 'point' => self::TYPE_STRING, 'polygon' => self::TYPE_STRING, - //'refcursor' => self::TYPE_STRING, - //'regclass' => self::TYPE_STRING, - //'regconfig' => self::TYPE_STRING, - //'regdictionary' => self::TYPE_STRING, - //'regoper' => self::TYPE_STRING, - //'regoperator' => self::TYPE_STRING, - //'regproc' => self::TYPE_STRING, - //'regprocedure' => self::TYPE_STRING, - //'regtype' => self::TYPE_STRING, - //'reltime' => self::TYPE_STRING, - //'smgr' => self::TYPE_STRING, 'text' => self::TYPE_TEXT, - //'tid' => self::TYPE_STRING, 'time without time zone' => self::TYPE_TIME, 'timestamp without time zone' => self::TYPE_TIMESTAMP, 'timestamp with time zone' => self::TYPE_TIMESTAMP, 'time with time zone' => self::TYPE_TIMESTAMP, - //'tinterval' => self::TYPE_STRING, - //'tsquery' => self::TYPE_STRING, - //'tsrange' => self::TYPE_STRING, - //'tstzrange' => self::TYPE_STRING, - //'tsvector' => self::TYPE_STRING, - //'txid_snapshot' => self::TYPE_STRING, 'unknown' => self::TYPE_STRING, 'uuid' => self::TYPE_STRING, 'bit varying' => self::TYPE_STRING, 'character varying' => self::TYPE_STRING, - //'xid' => self::TYPE_STRING, 'xml' => self::TYPE_STRING + + /* + * internal PG types + * 'aclitem' => self::TYPE_STRING, + * 'cid' => self::TYPE_STRING, + * 'daterange' => self::TYPE_STRING, + * 'gtsvector' => self::TYPE_STRING, + * 'int4range' => self::TYPE_STRING, //unknown + * 'lseg' => self::TYPE_STRING, + * 'int8range' => self::TYPE_STRING, // unknown + * 'pg_node_tree' => self::TYPE_STRING, + * 'refcursor' => self::TYPE_STRING, + * 'regclass' => self::TYPE_STRING, + * 'regconfig' => self::TYPE_STRING, + * 'regdictionary' => self::TYPE_STRING, + * 'regoper' => self::TYPE_STRING, + * 'regoperator' => self::TYPE_STRING, + * 'regproc' => self::TYPE_STRING, + * 'regprocedure' => self::TYPE_STRING, + * 'regtype' => self::TYPE_STRING, + * 'reltime' => self::TYPE_STRING, + * 'smgr' => self::TYPE_STRING, + * 'tid' => self::TYPE_STRING, + * 'xid' => self::TYPE_STRING, + * 'tinterval' => self::TYPE_STRING, + * 'tsquery' => self::TYPE_STRING, + * 'tsrange' => self::TYPE_STRING, + * 'tstzrange' => self::TYPE_STRING, + * 'tsvector' => self::TYPE_STRING, + * 'txid_snapshot' => self::TYPE_STRING + */ ); /** @@ -155,14 +159,51 @@ class Schema extends \yii\db\Schema { */ protected function findConstraints($table) { + $tableName = $this->quoteValue($table->name); + $tableSchema = $this->quoteValue($table->schemaName); + $database = $this->quoteValue($this->db->pdo->getCurrentDatabase()); + + //We need to extract the constraints de hard way since: + //http://www.postgresql.org/message-id/26677.1086673982@sss.pgh.pa.us + + $sql = <<<SQL +select + ct.conname as containst, + c.relname as table_name, + ns.nspname as table_schema, + current_database() as table_catalog, + (select string_agg(attname,',') attname from pg_attribute where attrelid=ct.conrelid and attnum = any(ct.conkey)) as columns, + fc.relname as foreign_table_name, + fns.nspname as foreign_table_schema, + current_database() as foreign_table_catalog, + (select string_agg(attname,',') attname from pg_attribute where attrelid=ct.confrelid and attnum = any(ct.confkey)) as foreign_columns +from + pg_constraint ct + inner join pg_class c on c.oid=ct.conrelid + inner join pg_namespace ns on c.relnamespace=ns.oid + left join pg_class fc on fc.oid=ct.confrelid + left join pg_namespace fns on fc.relnamespace=fns.oid + +where + ct.contype='f' + and c.relname={$tableName} + and ns.nspname={$tableSchema} + and current_database() = {$database} +SQL; + try { $constraints = $this->db->createCommand($sql)->queryAll(); } catch (\Exception $e) { return false; } foreach ($constraints as $constraint) { - $column = $this->loadColumnSchema($column); - $table->columns[$column->name] = $column; + $columns = explode(',', $constraint['columns']); + $fcolumns = explode(',', $constraint['foreign_columns']); + $citem = array($constraint['foreign_table_name']); + foreach ($columns as $idx => $column) { + $citem[] = array($fcolumns[$idx] => $column); + } + $table->foreignKeys[] = $citem; } return true; } From 5a587d16f0b70d01b42bbb6d40a1528a50bb6eaa Mon Sep 17 00:00:00 2001 From: Gevik Babakhani <gevik@ext4yii.com> Date: Thu, 6 Jun 2013 16:29:17 +0200 Subject: [PATCH 42/42] Fixed several formatting issues. Refactored == null to is_null == '' to empty(...) --- framework/yii/db/pgsql/PDO.php | 9 +++++---- framework/yii/db/pgsql/QueryBuilder.php | 3 ++- framework/yii/db/pgsql/Schema.php | 3 ++- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/framework/yii/db/pgsql/PDO.php b/framework/yii/db/pgsql/PDO.php index 67387dd..3f5996a 100644 --- a/framework/yii/db/pgsql/PDO.php +++ b/framework/yii/db/pgsql/PDO.php @@ -16,13 +16,14 @@ namespace yii\db\pgsql; * @author Gevik babakhani <gevikb@gmail.com> * @since 2.0 */ -class PDO extends \PDO { +class PDO extends \PDO +{ const OPT_SEARCH_PATH = 'search_path'; const OPT_DEFAULT_SCHEMA = 'default_schema'; const DEFAULT_SCHEMA = 'public'; - private $_currentDatabase = null; + private $_currentDatabase; /** * Returns value of the last inserted ID. @@ -53,11 +54,11 @@ class PDO extends \PDO { } if (isset($options[self::OPT_DEFAULT_SCHEMA])) { $schema = trim($options[self::OPT_DEFAULT_SCHEMA]); - if ($schema !== '') { + if (!empty($schema)) { Schema::$DEFAULT_SCHEMA = $schema; } } - if (Schema::$DEFAULT_SCHEMA === null || Schema::$DEFAULT_SCHEMA === '') { + if (is_null(Schema::$DEFAULT_SCHEMA) || empty(Schema::$DEFAULT_SCHEMA)) { Schema::$DEFAULT_SCHEMA = self::DEFAULT_SCHEMA; } } diff --git a/framework/yii/db/pgsql/QueryBuilder.php b/framework/yii/db/pgsql/QueryBuilder.php index 0cd9d94..f45c753 100644 --- a/framework/yii/db/pgsql/QueryBuilder.php +++ b/framework/yii/db/pgsql/QueryBuilder.php @@ -14,7 +14,8 @@ namespace yii\db\pgsql; * @author Gevik Babakhani <gevikb@gmail.com> * @since 2.0 */ -class QueryBuilder extends \yii\db\QueryBuilder { +class QueryBuilder extends \yii\db\QueryBuilder +{ /** * @var array mapping from abstract column types (keys) to physical column types (values). diff --git a/framework/yii/db/pgsql/Schema.php b/framework/yii/db/pgsql/Schema.php index 1e19383..07238c4 100644 --- a/framework/yii/db/pgsql/Schema.php +++ b/framework/yii/db/pgsql/Schema.php @@ -18,7 +18,8 @@ use yii\db\ColumnSchema; * @author Gevik Babakhani <gevikb@gmail.com> * @since 2.0 */ -class Schema extends \yii\db\Schema { +class Schema extends \yii\db\Schema +{ /** * The default schema used for the current session. This value is