From 2859e46f9cface51e2318232e454e15e19ca8ea1 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Mon, 10 Jul 2023 09:48:32 -0400 Subject: [PATCH 01/31] Raised minimum PHP version to 8.1 (#19879) --- base/Object.php | 30 ------------------------------ classes.php | 1 - composer.json | 2 +- db/Schema.php | 4 ++++ 4 files changed, 5 insertions(+), 32 deletions(-) delete mode 100644 base/Object.php diff --git a/base/Object.php b/base/Object.php deleted file mode 100644 index 20b68f169..000000000 --- a/base/Object.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @since 2.0 - * @deprecated since 2.0.13, the class name `Object` is invalid since PHP 7.2, use [[BaseObject]] instead. - * @see https://wiki.php.net/rfc/object-typehint - * @see https://github.com/yiisoft/yii2/issues/7936#issuecomment-315384669 - */ -class Object extends BaseObject -{ -} diff --git a/classes.php b/classes.php index 46741e318..ebb135188 100644 --- a/classes.php +++ b/classes.php @@ -43,7 +43,6 @@ 'yii\base\ModelEvent' => YII2_PATH . '/base/ModelEvent.php', 'yii\base\Module' => YII2_PATH . '/base/Module.php', 'yii\base\NotSupportedException' => YII2_PATH . '/base/NotSupportedException.php', - 'yii\base\Object' => YII2_PATH . '/base/Object.php', 'yii\base\Request' => YII2_PATH . '/base/Request.php', 'yii\base\Response' => YII2_PATH . '/base/Response.php', 'yii\base\Security' => YII2_PATH . '/base/Security.php', diff --git a/composer.json b/composer.json index 5494cae7a..8d638df3c 100644 --- a/composer.json +++ b/composer.json @@ -63,7 +63,7 @@ "source": "https://github.com/yiisoft/yii2" }, "require": { - "php": ">=5.4.0", + "php": ">=8.1", "ext-mbstring": "*", "ext-ctype": "*", "lib-pcre": "*", diff --git a/db/Schema.php b/db/Schema.php index 53c0af988..3a8aa7650 100644 --- a/db/Schema.php +++ b/db/Schema.php @@ -516,6 +516,10 @@ protected function getTableNameParts($name) */ public function quoteColumnName($name) { + if ($name === null) { + return ''; + } + if (strpos($name, '(') !== false || strpos($name, '[[') !== false) { return $name; } From 9c1b0c8a81e48bfb3da2dbe43d62d429bace217b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BD=98=E4=BD=B3=E4=BC=9F?= <1028244674@qq.com> Date: Thu, 13 Jul 2023 15:07:07 +0800 Subject: [PATCH 02/31] Remove methods mset, mget and madd of `yii\caching\Cache`, getHasChanged of `yii\caching\Dependency` (#19892) --- caching/Cache.php | 53 ------------------------------------------ caching/Dependency.php | 11 --------- 2 files changed, 64 deletions(-) diff --git a/caching/Cache.php b/caching/Cache.php index 5e1828ef8..7900585bf 100644 --- a/caching/Cache.php +++ b/caching/Cache.php @@ -166,23 +166,6 @@ public function exists($key) return $value !== false; } - /** - * Retrieves multiple values from cache with the specified keys. - * Some caches (such as memcache, apc) allow retrieving multiple cached values at the same time, - * which may improve the performance. In case a cache does not support this feature natively, - * this method will try to simulate it. - * - * @param string[] $keys list of string keys identifying the cached values - * @return array list of cached values corresponding to the specified keys. The array - * is returned in terms of (key, value) pairs. - * If a value is not cached or expired, the corresponding array value will be false. - * @deprecated This method is an alias for [[multiGet()]] and will be removed in 2.1.0. - */ - public function mget($keys) - { - return $this->multiGet($keys); - } - /** * Retrieves multiple values from cache with the specified keys. * Some caches (such as memcache, apc) allow retrieving multiple cached values at the same time, @@ -255,25 +238,6 @@ public function set($key, $value, $duration = null, $dependency = null) return $this->setValue($key, $value, $duration); } - /** - * Stores multiple items in cache. Each item contains a value identified by a key. - * If the cache already contains such a key, the existing value and - * expiration time will be replaced with the new ones, respectively. - * - * @param array $items the items to be cached, as key-value pairs. - * @param int|null $duration default duration in seconds before the cache will expire. If not set, - * default [[defaultDuration]] value is used. - * @param Dependency|null $dependency dependency of the cached items. If the dependency changes, - * the corresponding values in the cache will be invalidated when it is fetched via [[get()]]. - * This parameter is ignored if [[serializer]] is false. - * @return array array of failed keys - * @deprecated This method is an alias for [[multiSet()]] and will be removed in 2.1.0. - */ - public function mset($items, $duration = null, $dependency = null) - { - return $this->multiSet($items, $duration, $dependency); - } - /** * Stores multiple items in cache. Each item contains a value identified by a key. * If the cache already contains such a key, the existing value and @@ -313,23 +277,6 @@ public function multiSet($items, $duration = null, $dependency = null) return $this->setValues($data, $duration); } - /** - * Stores multiple items in cache. Each item contains a value identified by a key. - * If the cache already contains such a key, the existing value and expiration time will be preserved. - * - * @param array $items the items to be cached, as key-value pairs. - * @param int $duration default number of seconds in which the cached values will expire. 0 means never expire. - * @param Dependency|null $dependency dependency of the cached items. If the dependency changes, - * the corresponding values in the cache will be invalidated when it is fetched via [[get()]]. - * This parameter is ignored if [[serializer]] is false. - * @return array array of failed keys - * @deprecated This method is an alias for [[multiAdd()]] and will be removed in 2.1.0. - */ - public function madd($items, $duration = 0, $dependency = null) - { - return $this->multiAdd($items, $duration, $dependency); - } - /** * Stores multiple items in cache. Each item contains a value identified by a key. * If the cache already contains such a key, the existing value and expiration time will be preserved. diff --git a/caching/Dependency.php b/caching/Dependency.php index e558bfef8..c4de5078a 100644 --- a/caching/Dependency.php +++ b/caching/Dependency.php @@ -57,17 +57,6 @@ public function evaluateDependency($cache) } } - /** - * Returns a value indicating whether the dependency has changed. - * @deprecated since version 2.0.11. Will be removed in version 2.1. Use [[isChanged()]] instead. - * @param CacheInterface $cache the cache component that is currently evaluating this dependency - * @return bool whether the dependency has changed. - */ - public function getHasChanged($cache) - { - return $this->isChanged($cache); - } - /** * Checks whether the dependency is changed. * @param CacheInterface $cache the cache component that is currently evaluating this dependency From 81ea5b70fa0d3d1788d8689827f88193f90271af Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Sun, 16 Jul 2023 09:45:39 -0400 Subject: [PATCH 03/31] Remove deprecated method `className()` for branch `2.2`. (#19894) --- UPGRADE.md | 5 ++--- base/BaseObject.php | 10 ---------- base/Controller.php | 4 ++-- behaviors/SluggableBehavior.php | 2 +- caching/DbCache.php | 2 +- caching/DbDependency.php | 2 +- console/controllers/CacheController.php | 2 +- console/controllers/FixtureController.php | 2 +- console/controllers/MessageController.php | 2 +- console/controllers/MigrateController.php | 4 ++-- data/BaseDataProvider.php | 4 ++-- data/DataFilter.php | 4 ++-- data/SqlDataProvider.php | 2 +- db/ActiveRecord.php | 2 +- db/Migration.php | 6 +++--- db/Query.php | 4 ++-- db/Schema.php | 4 ++-- db/cubrid/Schema.php | 2 +- db/mssql/Schema.php | 4 ++-- db/mysql/Schema.php | 4 ++-- db/oci/Schema.php | 4 ++-- db/pgsql/Schema.php | 2 +- db/sqlite/Schema.php | 4 ++-- filters/AccessControl.php | 2 +- grid/GridView.php | 4 ++-- i18n/DbMessageSource.php | 2 +- log/DbTarget.php | 2 +- mail/BaseMailer.php | 2 +- mutex/DbMutex.php | 2 +- rbac/DbManager.php | 4 ++-- rbac/PhpManager.php | 2 +- rest/Controller.php | 8 ++++---- rest/IndexAction.php | 2 +- rest/UrlRule.php | 2 +- test/DbFixture.php | 2 +- validators/UniqueValidator.php | 6 +++++- web/AssetManager.php | 4 ++-- web/CompositeUrlRule.php | 2 +- web/DbSession.php | 2 +- web/UrlManager.php | 2 +- web/UrlRule.php | 2 +- web/View.php | 2 +- widgets/BaseListView.php | 4 ++-- 43 files changed, 66 insertions(+), 73 deletions(-) diff --git a/UPGRADE.md b/UPGRADE.md index 7d2ca03eb..8286cf010 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -292,7 +292,7 @@ Upgrade from Yii 2.0.34 public function rules() { return [ - ['attribute', 'each', 'rule' => ['exist', 'targetClass' => static::className(), 'targetAttribute' => 'id']], + ['attribute', 'each', 'rule' => ['exist', 'targetClass' => static::class, 'targetAttribute' => 'id']], ]; } ``` @@ -521,9 +521,8 @@ Upgrade from Yii 2.0.13 * Log targets (like `yii\log\EmailTarget`) are now throwing `yii\log\LogRuntimeException` in case log can not be properly exported. -* You can start preparing your application for Yii 2.1 by doing the following: +* You can start preparing your application for Yii 2.2 by doing the following: - - Replace `::className()` calls with `::class` (if you’re running PHP 5.5+). - Replace usages of `yii\base\InvalidParamException` with `yii\base\InvalidArgumentException`. - Replace calls to `Yii::trace()` with `Yii::debug()`. - Remove calls to `yii\BaseYii::powered()`. diff --git a/base/BaseObject.php b/base/BaseObject.php index 174fcd1e9..2f9448efc 100644 --- a/base/BaseObject.php +++ b/base/BaseObject.php @@ -76,16 +76,6 @@ */ class BaseObject implements Configurable { - /** - * Returns the fully qualified name of this class. - * @return string the fully qualified name of this class. - * @deprecated since 2.0.14. On PHP >=5.5, use `::class` instead. - */ - public static function className() - { - return get_called_class(); - } - /** * Constructor. * diff --git a/base/Controller.php b/base/Controller.php index 2205712fb..c1e1983c7 100644 --- a/base/Controller.php +++ b/base/Controller.php @@ -102,8 +102,8 @@ public function __construct($id, $module, $config = []) public function init() { parent::init(); - $this->request = Instance::ensure($this->request, Request::className()); - $this->response = Instance::ensure($this->response, Response::className()); + $this->request = Instance::ensure($this->request, Request::class); + $this->response = Instance::ensure($this->response, Response::class); } /** diff --git a/behaviors/SluggableBehavior.php b/behaviors/SluggableBehavior.php index c18bd4fa2..369be6c37 100644 --- a/behaviors/SluggableBehavior.php +++ b/behaviors/SluggableBehavior.php @@ -243,7 +243,7 @@ protected function validateSlug($slug) /* @var $model BaseActiveRecord */ $validator = Yii::createObject(array_merge( [ - 'class' => UniqueValidator::className(), + 'class' => UniqueValidator::class, ], $this->uniqueValidator )); diff --git a/caching/DbCache.php b/caching/DbCache.php index 5bf3b02de..5003adad2 100644 --- a/caching/DbCache.php +++ b/caching/DbCache.php @@ -95,7 +95,7 @@ class DbCache extends Cache public function init() { parent::init(); - $this->db = Instance::ensure($this->db, Connection::className()); + $this->db = Instance::ensure($this->db, Connection::class); } /** diff --git a/caching/DbDependency.php b/caching/DbDependency.php index 43a51d926..525c3e02b 100644 --- a/caching/DbDependency.php +++ b/caching/DbDependency.php @@ -50,7 +50,7 @@ class DbDependency extends Dependency protected function generateDependencyData($cache) { /* @var $db Connection */ - $db = Instance::ensure($this->db, Connection::className()); + $db = Instance::ensure($this->db, Connection::class); if ($this->sql === null) { throw new InvalidConfigException('DbDependency::sql must be set.'); } diff --git a/console/controllers/CacheController.php b/console/controllers/CacheController.php index d5d0a756e..4a2fabff7 100644 --- a/console/controllers/CacheController.php +++ b/console/controllers/CacheController.php @@ -300,6 +300,6 @@ private function isCacheClass($className) */ private function canBeFlushed($className) { - return !is_a($className, ApcCache::className(), true) || PHP_SAPI !== 'cli'; + return !is_a($className, ApcCache::class, true) || PHP_SAPI !== 'cli'; } } diff --git a/console/controllers/FixtureController.php b/console/controllers/FixtureController.php index caba5d271..a210034b7 100644 --- a/console/controllers/FixtureController.php +++ b/console/controllers/FixtureController.php @@ -258,7 +258,7 @@ private function notifyLoaded($fixtures) $fixtureClassNames = []; foreach ($fixtures as $fixture) { - $fixtureClassNames[] = $fixture::className(); + $fixtureClassNames[] = $fixture::class; } $this->outputList($fixtureClassNames); diff --git a/console/controllers/MessageController.php b/console/controllers/MessageController.php index e1a735769..4650cec79 100644 --- a/console/controllers/MessageController.php +++ b/console/controllers/MessageController.php @@ -318,7 +318,7 @@ public function actionExtract($configFile = null) } } elseif ($this->config['format'] === 'db') { /** @var Connection $db */ - $db = Instance::ensure($this->config['db'], Connection::className()); + $db = Instance::ensure($this->config['db'], Connection::class); $sourceMessageTable = isset($this->config['sourceMessageTable']) ? $this->config['sourceMessageTable'] : '{{%source_message}}'; $messageTable = isset($this->config['messageTable']) ? $this->config['messageTable'] : '{{%message}}'; $this->saveMessagesToDb( diff --git a/console/controllers/MigrateController.php b/console/controllers/MigrateController.php index 17b6a7638..b2e1db3ec 100644 --- a/console/controllers/MigrateController.php +++ b/console/controllers/MigrateController.php @@ -180,7 +180,7 @@ public function optionAliases() public function beforeAction($action) { if (parent::beforeAction($action)) { - $this->db = Instance::ensure($this->db, Connection::className()); + $this->db = Instance::ensure($this->db, Connection::class); return true; } @@ -471,7 +471,7 @@ protected function generateMigrationSourceCode($params) if ($relatedColumn === null) { $relatedColumn = 'id'; try { - $this->db = Instance::ensure($this->db, Connection::className()); + $this->db = Instance::ensure($this->db, Connection::class); $relatedTableSchema = $this->db->getTableSchema($relatedTable); if ($relatedTableSchema !== null) { $primaryKeyCount = count($relatedTableSchema->primaryKey); diff --git a/data/BaseDataProvider.php b/data/BaseDataProvider.php index 82af0aa7c..5d1509662 100644 --- a/data/BaseDataProvider.php +++ b/data/BaseDataProvider.php @@ -211,7 +211,7 @@ public function getPagination() public function setPagination($value) { if (is_array($value)) { - $config = ['class' => Pagination::className()]; + $config = ['class' => Pagination::class]; if ($this->id !== null) { $config['pageParam'] = $this->id . '-page'; $config['pageSizeParam'] = $this->id . '-per-page'; @@ -252,7 +252,7 @@ public function getSort() public function setSort($value) { if (is_array($value)) { - $config = ['class' => Sort::className()]; + $config = ['class' => Sort::class]; if ($this->id !== null) { $config['sortParam'] = $this->id . '-sort'; } diff --git a/data/DataFilter.php b/data/DataFilter.php index 057509203..587b7b10a 100644 --- a/data/DataFilter.php +++ b/data/DataFilter.php @@ -288,7 +288,7 @@ public function getSearchModel() if (!is_object($this->_searchModel) || $this->_searchModel instanceof \Closure) { $model = Yii::createObject($this->_searchModel); if (!$model instanceof Model) { - throw new InvalidConfigException('`' . get_class($this) . '::$searchModel` should be an instance of `' . Model::className() . '` or its DI compatible configuration.'); + throw new InvalidConfigException('`' . get_class($this) . '::$searchModel` should be an instance of `' . Model::class . '` or its DI compatible configuration.'); } $this->_searchModel = $model; } @@ -302,7 +302,7 @@ public function getSearchModel() public function setSearchModel($model) { if (is_object($model) && !$model instanceof Model && !$model instanceof \Closure) { - throw new InvalidConfigException('`' . get_class($this) . '::$searchModel` should be an instance of `' . Model::className() . '` or its DI compatible configuration.'); + throw new InvalidConfigException('`' . get_class($this) . '::$searchModel` should be an instance of `' . Model::class . '` or its DI compatible configuration.'); } $this->_searchModel = $model; } diff --git a/data/SqlDataProvider.php b/data/SqlDataProvider.php index 5a8f9631d..1f4e9ec36 100644 --- a/data/SqlDataProvider.php +++ b/data/SqlDataProvider.php @@ -96,7 +96,7 @@ class SqlDataProvider extends BaseDataProvider public function init() { parent::init(); - $this->db = Instance::ensure($this->db, Connection::className()); + $this->db = Instance::ensure($this->db, Connection::class); if ($this->sql === null) { throw new InvalidConfigException('The "sql" property must be set.'); } diff --git a/db/ActiveRecord.php b/db/ActiveRecord.php index 130285617..29d5efe0b 100644 --- a/db/ActiveRecord.php +++ b/db/ActiveRecord.php @@ -411,7 +411,7 @@ public static function deleteAll($condition = null, $params = []) */ public static function find() { - return Yii::createObject(ActiveQuery::className(), [get_called_class()]); + return Yii::createObject(ActiveQuery::class, [get_called_class()]); } /** diff --git a/db/Migration.php b/db/Migration.php index 975898cd5..58df34b55 100644 --- a/db/Migration.php +++ b/db/Migration.php @@ -87,7 +87,7 @@ class Migration extends Component implements MigrationInterface public function init() { parent::init(); - $this->db = Instance::ensure($this->db, Connection::className()); + $this->db = Instance::ensure($this->db, Connection::class); $this->db->getSchema()->refresh(); $this->db->enableSlaves = false; } @@ -311,7 +311,7 @@ public function delete($table, $condition = '', $params = []) * * If a column is specified with definition only (e.g. 'PRIMARY KEY (name, type)'), it will be directly * put into the generated SQL. - * + * * Example usage: * ```php * class m200000_000000_create_table_fruits extends \yii\db\Migration @@ -319,7 +319,7 @@ public function delete($table, $condition = '', $params = []) * public function safeUp() * { * $this->createTable('{{%fruits}}', [ - * // ... + * // ... * 'column_name double precision null default null', * ``` diff --git a/db/Query.php b/db/Query.php index f0b215859..243d08c4a 100644 --- a/db/Query.php +++ b/db/Query.php @@ -198,7 +198,7 @@ public function prepare($builder) public function batch($batchSize = 100, $db = null) { return Yii::createObject([ - 'class' => BatchQueryResult::className(), + 'class' => BatchQueryResult::class, 'query' => $this, 'batchSize' => $batchSize, 'db' => $db, @@ -226,7 +226,7 @@ public function batch($batchSize = 100, $db = null) public function each($batchSize = 100, $db = null) { return Yii::createObject([ - 'class' => BatchQueryResult::className(), + 'class' => BatchQueryResult::class, 'query' => $this, 'batchSize' => $batchSize, 'db' => $db, diff --git a/db/Schema.php b/db/Schema.php index 3a8aa7650..43e15d99b 100644 --- a/db/Schema.php +++ b/db/Schema.php @@ -313,7 +313,7 @@ public function refreshTableSchema($name) */ public function createQueryBuilder() { - return Yii::createObject(QueryBuilder::className(), [$this->db]); + return Yii::createObject(QueryBuilder::class, [$this->db]); } /** @@ -328,7 +328,7 @@ public function createQueryBuilder() */ public function createColumnSchemaBuilder($type, $length = null) { - return Yii::createObject(ColumnSchemaBuilder::className(), [$type, $length]); + return Yii::createObject(ColumnSchemaBuilder::class, [$type, $length]); } /** diff --git a/db/cubrid/Schema.php b/db/cubrid/Schema.php index 65b6c11b9..74adba234 100644 --- a/db/cubrid/Schema.php +++ b/db/cubrid/Schema.php @@ -249,7 +249,7 @@ public function releaseSavepoint($name) */ public function createQueryBuilder() { - return Yii::createObject(QueryBuilder::className(), [$this->db]); + return Yii::createObject(QueryBuilder::class, [$this->db]); } /** diff --git a/db/mssql/Schema.php b/db/mssql/Schema.php index 005b1555f..07dbaac98 100644 --- a/db/mssql/Schema.php +++ b/db/mssql/Schema.php @@ -332,7 +332,7 @@ public function rollBackSavepoint($name) */ public function createQueryBuilder() { - return Yii::createObject(QueryBuilder::className(), [$this->db]); + return Yii::createObject(QueryBuilder::class, [$this->db]); } /** @@ -811,6 +811,6 @@ public function insert($table, $columns) */ public function createColumnSchemaBuilder($type, $length = null) { - return Yii::createObject(ColumnSchemaBuilder::className(), [$type, $length, $this->db]); + return Yii::createObject(ColumnSchemaBuilder::class, [$type, $length, $this->db]); } } diff --git a/db/mysql/Schema.php b/db/mysql/Schema.php index fa2270eb7..38dec4ca0 100644 --- a/db/mysql/Schema.php +++ b/db/mysql/Schema.php @@ -222,7 +222,7 @@ protected function loadTableDefaultValues($tableName) */ public function createQueryBuilder() { - return Yii::createObject(QueryBuilder::className(), [$this->db]); + return Yii::createObject(QueryBuilder::class, [$this->db]); } /** @@ -472,7 +472,7 @@ public function findUniqueIndexes($table) */ public function createColumnSchemaBuilder($type, $length = null) { - return Yii::createObject(ColumnSchemaBuilder::className(), [$type, $length, $this->db]); + return Yii::createObject(ColumnSchemaBuilder::class, [$type, $length, $this->db]); } /** diff --git a/db/oci/Schema.php b/db/oci/Schema.php index e0e4c05e2..05b3cb5ea 100644 --- a/db/oci/Schema.php +++ b/db/oci/Schema.php @@ -262,7 +262,7 @@ public function quoteSimpleTableName($name) */ public function createQueryBuilder() { - return Yii::createObject(QueryBuilder::className(), [$this->db]); + return Yii::createObject(QueryBuilder::class, [$this->db]); } /** @@ -270,7 +270,7 @@ public function createQueryBuilder() */ public function createColumnSchemaBuilder($type, $length = null) { - return Yii::createObject(ColumnSchemaBuilder::className(), [$type, $length]); + return Yii::createObject(ColumnSchemaBuilder::class, [$type, $length]); } /** diff --git a/db/pgsql/Schema.php b/db/pgsql/Schema.php index 154e01a38..c379176de 100644 --- a/db/pgsql/Schema.php +++ b/db/pgsql/Schema.php @@ -289,7 +289,7 @@ protected function loadTableDefaultValues($tableName) */ public function createQueryBuilder() { - return Yii::createObject(QueryBuilder::className(), [$this->db]); + return Yii::createObject(QueryBuilder::class, [$this->db]); } /** diff --git a/db/sqlite/Schema.php b/db/sqlite/Schema.php index 32b209b22..2ff7ba835 100644 --- a/db/sqlite/Schema.php +++ b/db/sqlite/Schema.php @@ -207,7 +207,7 @@ protected function loadTableDefaultValues($tableName) */ public function createQueryBuilder() { - return Yii::createObject(QueryBuilder::className(), [$this->db]); + return Yii::createObject(QueryBuilder::class, [$this->db]); } /** @@ -216,7 +216,7 @@ public function createQueryBuilder() */ public function createColumnSchemaBuilder($type, $length = null) { - return Yii::createObject(ColumnSchemaBuilder::className(), [$type, $length]); + return Yii::createObject(ColumnSchemaBuilder::class, [$type, $length]); } /** diff --git a/filters/AccessControl.php b/filters/AccessControl.php index 7ec2c5e55..a648feb77 100644 --- a/filters/AccessControl.php +++ b/filters/AccessControl.php @@ -99,7 +99,7 @@ public function init() { parent::init(); if ($this->user !== false) { - $this->user = Instance::ensure($this->user, User::className()); + $this->user = Instance::ensure($this->user, User::class); } foreach ($this->rules as $i => $rule) { if (is_array($rule)) { diff --git a/grid/GridView.php b/grid/GridView.php index 7ee0e06bb..8b5afefe7 100644 --- a/grid/GridView.php +++ b/grid/GridView.php @@ -547,7 +547,7 @@ protected function initColumns() $column = $this->createDataColumn($column); } else { $column = Yii::createObject(array_merge([ - 'class' => $this->dataColumnClass ?: DataColumn::className(), + 'class' => $this->dataColumnClass ?: DataColumn::class, 'grid' => $this, ], $column)); } @@ -572,7 +572,7 @@ protected function createDataColumn($text) } return Yii::createObject([ - 'class' => $this->dataColumnClass ?: DataColumn::className(), + 'class' => $this->dataColumnClass ?: DataColumn::class, 'grid' => $this, 'attribute' => $matches[1], 'format' => isset($matches[3]) ? $matches[3] : 'text', diff --git a/i18n/DbMessageSource.php b/i18n/DbMessageSource.php index 0686291d2..eccc7fbd1 100644 --- a/i18n/DbMessageSource.php +++ b/i18n/DbMessageSource.php @@ -96,7 +96,7 @@ class DbMessageSource extends MessageSource public function init() { parent::init(); - $this->db = Instance::ensure($this->db, Connection::className()); + $this->db = Instance::ensure($this->db, Connection::class); if ($this->enableCaching) { $this->cache = Instance::ensure($this->cache, 'yii\caching\CacheInterface'); } diff --git a/log/DbTarget.php b/log/DbTarget.php index c2c3d6a62..1ecf07f2b 100644 --- a/log/DbTarget.php +++ b/log/DbTarget.php @@ -53,7 +53,7 @@ class DbTarget extends Target public function init() { parent::init(); - $this->db = Instance::ensure($this->db, Connection::className()); + $this->db = Instance::ensure($this->db, Connection::class); } /** diff --git a/mail/BaseMailer.php b/mail/BaseMailer.php index c5f76fb75..e334d74aa 100644 --- a/mail/BaseMailer.php +++ b/mail/BaseMailer.php @@ -142,7 +142,7 @@ public function getView() protected function createView(array $config) { if (!array_key_exists('class', $config)) { - $config['class'] = View::className(); + $config['class'] = View::class; } return Yii::createObject($config); diff --git a/mutex/DbMutex.php b/mutex/DbMutex.php index 593cff4e0..a19a1adf8 100644 --- a/mutex/DbMutex.php +++ b/mutex/DbMutex.php @@ -37,6 +37,6 @@ abstract class DbMutex extends Mutex public function init() { parent::init(); - $this->db = Instance::ensure($this->db, Connection::className()); + $this->db = Instance::ensure($this->db, Connection::class); } } diff --git a/rbac/DbManager.php b/rbac/DbManager.php index 2685ad5a1..240914838 100644 --- a/rbac/DbManager.php +++ b/rbac/DbManager.php @@ -119,7 +119,7 @@ class DbManager extends BaseManager public function init() { parent::init(); - $this->db = Instance::ensure($this->db, Connection::className()); + $this->db = Instance::ensure($this->db, Connection::class); if ($this->cache !== null) { $this->cache = Instance::ensure($this->cache, 'yii\caching\CacheInterface'); } @@ -449,7 +449,7 @@ protected function getItems($type) */ protected function populateItem($row) { - $class = $row['type'] == Item::TYPE_PERMISSION ? Permission::className() : Role::className(); + $class = $row['type'] == Item::TYPE_PERMISSION ? Permission::class : Role::class; if (!isset($row['data']) || ($data = @unserialize(is_resource($row['data']) ? stream_get_contents($row['data']) : $row['data'])) === false) { $data = null; diff --git a/rbac/PhpManager.php b/rbac/PhpManager.php index 291d72976..9411a7f93 100644 --- a/rbac/PhpManager.php +++ b/rbac/PhpManager.php @@ -724,7 +724,7 @@ protected function load() $rules = $this->loadFromFile($this->ruleFile); foreach ($items as $name => $item) { - $class = $item['type'] == Item::TYPE_PERMISSION ? Permission::className() : Role::className(); + $class = $item['type'] == Item::TYPE_PERMISSION ? Permission::class : Role::class; $this->items[$name] = new $class([ 'name' => $name, diff --git a/rest/Controller.php b/rest/Controller.php index 9512ee75e..3705417ac 100644 --- a/rest/Controller.php +++ b/rest/Controller.php @@ -49,21 +49,21 @@ public function behaviors() { return [ 'contentNegotiator' => [ - 'class' => ContentNegotiator::className(), + 'class' => ContentNegotiator::class, 'formats' => [ 'application/json' => Response::FORMAT_JSON, 'application/xml' => Response::FORMAT_XML, ], ], 'verbFilter' => [ - 'class' => VerbFilter::className(), + 'class' => VerbFilter::class, 'actions' => $this->verbs(), ], 'authenticator' => [ - 'class' => CompositeAuth::className(), + 'class' => CompositeAuth::class, ], 'rateLimiter' => [ - 'class' => RateLimiter::className(), + 'class' => RateLimiter::class, ], ]; } diff --git a/rest/IndexAction.php b/rest/IndexAction.php index 81b19cab7..ab3e53293 100644 --- a/rest/IndexAction.php +++ b/rest/IndexAction.php @@ -183,7 +183,7 @@ protected function prepareDataProvider() } return Yii::createObject([ - 'class' => ActiveDataProvider::className(), + 'class' => ActiveDataProvider::class, 'query' => $query, 'pagination' => $pagination, 'sort' => $sort, diff --git a/rest/UrlRule.php b/rest/UrlRule.php index 48b1bbe79..8f32e32c4 100644 --- a/rest/UrlRule.php +++ b/rest/UrlRule.php @@ -233,7 +233,7 @@ public function parseRequest($manager, $request) Yii::debug([ 'rule' => method_exists($rule, '__toString') ? $rule->__toString() : get_class($rule), 'match' => $result !== false, - 'parent' => self::className(), + 'parent' => self::class, ], __METHOD__); } if ($result !== false) { diff --git a/test/DbFixture.php b/test/DbFixture.php index d5a6322f9..0a9b090e9 100644 --- a/test/DbFixture.php +++ b/test/DbFixture.php @@ -38,6 +38,6 @@ abstract class DbFixture extends Fixture public function init() { parent::init(); - $this->db = Instance::ensure($this->db, BaseObject::className()); + $this->db = Instance::ensure($this->db, BaseObject::class); } } diff --git a/validators/UniqueValidator.php b/validators/UniqueValidator.php index 74edcfd66..dadc8b4ed 100644 --- a/validators/UniqueValidator.php +++ b/validators/UniqueValidator.php @@ -189,7 +189,11 @@ private function modelExists($targetClass, $conditions, $model) /** @var ActiveRecordInterface|\yii\base\BaseObject $targetClass $query */ $query = $this->prepareQuery($targetClass, $conditions); - if (!$model instanceof ActiveRecordInterface || $model->getIsNewRecord() || $model::className() !== $targetClass::className()) { + if ( + !$model instanceof ActiveRecordInterface || + $model->getIsNewRecord() || + !$model instanceof $targetClass + ) { // if current $model isn't in the database yet, then it's OK just to call exists() // also there's no need to run check based on primary keys, when $targetClass is not the same as $model's class $exists = $query->exists(); diff --git a/web/AssetManager.php b/web/AssetManager.php index 0ad3a21cc..40d8ca2b1 100644 --- a/web/AssetManager.php +++ b/web/AssetManager.php @@ -394,10 +394,10 @@ protected function resolveAsset($bundle, $asset) public function getConverter() { if ($this->_converter === null) { - $this->_converter = Yii::createObject(AssetConverter::className()); + $this->_converter = Yii::createObject(AssetConverter::class); } elseif (is_array($this->_converter) || is_string($this->_converter)) { if (is_array($this->_converter) && !isset($this->_converter['class'])) { - $this->_converter['class'] = AssetConverter::className(); + $this->_converter['class'] = AssetConverter::class; } $this->_converter = Yii::createObject($this->_converter); } diff --git a/web/CompositeUrlRule.php b/web/CompositeUrlRule.php index 30d08e189..f43cbcbbc 100644 --- a/web/CompositeUrlRule.php +++ b/web/CompositeUrlRule.php @@ -60,7 +60,7 @@ public function parseRequest($manager, $request) Yii::debug([ 'rule' => method_exists($rule, '__toString') ? $rule->__toString() : get_class($rule), 'match' => $result !== false, - 'parent' => self::className(), + 'parent' => self::class, ], __METHOD__); } if ($result !== false) { diff --git a/web/DbSession.php b/web/DbSession.php index 4d4e5030d..a742885ec 100644 --- a/web/DbSession.php +++ b/web/DbSession.php @@ -90,7 +90,7 @@ class DbSession extends MultiFieldSession public function init() { parent::init(); - $this->db = Instance::ensure($this->db, Connection::className()); + $this->db = Instance::ensure($this->db, Connection::class); } /** diff --git a/web/UrlManager.php b/web/UrlManager.php index 292c4bc3e..fddb8b342 100644 --- a/web/UrlManager.php +++ b/web/UrlManager.php @@ -178,7 +178,7 @@ public function init() if ($this->normalizer !== false) { $this->normalizer = Yii::createObject($this->normalizer); if (!$this->normalizer instanceof UrlNormalizer) { - throw new InvalidConfigException('`' . get_class($this) . '::normalizer` should be an instance of `' . UrlNormalizer::className() . '` or its DI compatible configuration.'); + throw new InvalidConfigException('`' . get_class($this) . '::normalizer` should be an instance of `' . UrlNormalizer::class . '` or its DI compatible configuration.'); } } diff --git a/web/UrlRule.php b/web/UrlRule.php index fbbf6ffe1..170a2f24c 100644 --- a/web/UrlRule.php +++ b/web/UrlRule.php @@ -195,7 +195,7 @@ public function init() throw new InvalidConfigException('UrlRule::route must be set.'); } if (is_array($this->normalizer)) { - $normalizerConfig = array_merge(['class' => UrlNormalizer::className()], $this->normalizer); + $normalizerConfig = array_merge(['class' => UrlNormalizer::class], $this->normalizer); $this->normalizer = Yii::createObject($normalizerConfig); } if ($this->normalizer !== null && $this->normalizer !== false && !$this->normalizer instanceof UrlNormalizer) { diff --git a/web/View.php b/web/View.php index f2c19fc72..d9addacca 100644 --- a/web/View.php +++ b/web/View.php @@ -521,7 +521,7 @@ private function registerFile($type, $url, $options = [], $key = null) } } else { $this->getAssetManager()->bundles[$key] = Yii::createObject([ - 'class' => AssetBundle::className(), + 'class' => AssetBundle::class, 'baseUrl' => '', 'basePath' => '@webroot', (string)$type => [ArrayHelper::merge([!Url::isRelative($url) ? $url : ltrim($url, '/')], $originalOptions)], diff --git a/widgets/BaseListView.php b/widgets/BaseListView.php index cee83fcaf..4aa9b7826 100644 --- a/widgets/BaseListView.php +++ b/widgets/BaseListView.php @@ -253,7 +253,7 @@ public function renderPager() } /* @var $class LinkPager */ $pager = $this->pager; - $class = ArrayHelper::remove($pager, 'class', LinkPager::className()); + $class = ArrayHelper::remove($pager, 'class', LinkPager::class); $pager['pagination'] = $pagination; $pager['view'] = $this->getView(); @@ -272,7 +272,7 @@ public function renderSorter() } /* @var $class LinkSorter */ $sorter = $this->sorter; - $class = ArrayHelper::remove($sorter, 'class', LinkSorter::className()); + $class = ArrayHelper::remove($sorter, 'class', LinkSorter::class); $sorter['sort'] = $sort; $sorter['view'] = $this->getView(); From a944ef096e8a258a3918cd2f3752c8a79b93c1a8 Mon Sep 17 00:00:00 2001 From: "Stefano D. Mtangoo" Date: Tue, 18 Jul 2023 17:00:54 +0300 Subject: [PATCH 04/31] Fix #19902: Remove support for CUBRID --- CHANGELOG.md | 8 + behaviors/AttributeTypecastBehavior.php | 9 +- classes.php | 5 +- db/BaseActiveRecord.php | 13 +- db/ColumnSchemaBuilder.php | 5 +- db/Command.php | 15 +- db/Connection.php | 7 +- db/cubrid/ColumnSchemaBuilder.php | 72 --- db/cubrid/QueryBuilder.php | 294 ------------ db/cubrid/Schema.php | 419 ------------------ db/cubrid/conditions/LikeConditionBuilder.php | 29 -- 11 files changed, 45 insertions(+), 831 deletions(-) delete mode 100644 db/cubrid/ColumnSchemaBuilder.php delete mode 100644 db/cubrid/QueryBuilder.php delete mode 100644 db/cubrid/Schema.php delete mode 100644 db/cubrid/conditions/LikeConditionBuilder.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 9214c9204..8bd17d17e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,21 @@ Yii Framework 2 Change Log ========================== +2.2 under development +------------------------ + +- Chg #19902: Remove support for CUBRID (mtangoo) + + 2.0.49 under development ------------------------ +- Bug #19857: Fix AttributeTypecastBehavior::resetOldAttributes() causes "class has no attribute named" InvalidArgumentException (uaoleg) - Bug #18859: Fix `yii\web\Controller::bindInjectedParams()` to not throw error when argument of `ReflectionUnionType` type is passed (bizley) - Enh #19841: Allow jQuery 3.7 to be installed (wouter90) - Enh #19853: Added support for default value for `\yii\helpers\Console::select()` (rhertogh) - Bug #19868: Added whitespace sanitation for tests, due to updates in ICU 72 (schmunk42) +- Enh #19884: Added support Enums in Query Builder (sk1t0n) 2.0.48.1 May 24, 2023 diff --git a/behaviors/AttributeTypecastBehavior.php b/behaviors/AttributeTypecastBehavior.php index fc3ce9559..a418b15de 100644 --- a/behaviors/AttributeTypecastBehavior.php +++ b/behaviors/AttributeTypecastBehavior.php @@ -366,7 +366,10 @@ public function afterFind($event) $this->resetOldAttributes(); } - private function resetOldAttributes() + /** + * Resets the old values of the named attributes. + */ + protected function resetOldAttributes() { if ($this->attributeTypes === null) { return; @@ -375,7 +378,9 @@ private function resetOldAttributes() $attributes = array_keys($this->attributeTypes); foreach ($attributes as $attribute) { - $this->owner->setOldAttribute($attribute, $this->owner->{$attribute}); + if ($this->owner->canSetOldAttribute($attribute)) { + $this->owner->setOldAttribute($attribute, $this->owner->{$attribute}); + } } } } diff --git a/classes.php b/classes.php index ebb135188..3d4759ed4 100644 --- a/classes.php +++ b/classes.php @@ -1,4 +1,5 @@ YII2_PATH . '/db/conditions/OrCondition.php', 'yii\db\conditions\SimpleCondition' => YII2_PATH . '/db/conditions/SimpleCondition.php', 'yii\db\conditions\SimpleConditionBuilder' => YII2_PATH . '/db/conditions/SimpleConditionBuilder.php', - 'yii\db\cubrid\ColumnSchemaBuilder' => YII2_PATH . '/db/cubrid/ColumnSchemaBuilder.php', - 'yii\db\cubrid\QueryBuilder' => YII2_PATH . '/db/cubrid/QueryBuilder.php', - 'yii\db\cubrid\Schema' => YII2_PATH . '/db/cubrid/Schema.php', - 'yii\db\cubrid\conditions\LikeConditionBuilder' => YII2_PATH . '/db/cubrid/conditions/LikeConditionBuilder.php', 'yii\db\mssql\ColumnSchema' => YII2_PATH . '/db/mssql/ColumnSchema.php', 'yii\db\mssql\ColumnSchemaBuilder' => YII2_PATH . '/db/mssql/ColumnSchemaBuilder.php', 'yii\db\mssql\DBLibPDO' => YII2_PATH . '/db/mssql/DBLibPDO.php', diff --git a/db/BaseActiveRecord.php b/db/BaseActiveRecord.php index 06e6d7460..88fb2f11d 100644 --- a/db/BaseActiveRecord.php +++ b/db/BaseActiveRecord.php @@ -576,13 +576,24 @@ public function getOldAttribute($name) */ public function setOldAttribute($name, $value) { - if (isset($this->_oldAttributes[$name]) || $this->hasAttribute($name)) { + if ($this->canSetOldAttribute($name)) { $this->_oldAttributes[$name] = $value; } else { throw new InvalidArgumentException(get_class($this) . ' has no attribute named "' . $name . '".'); } } + /** + * Returns if the old named attribute can be set. + * @param string $name the attribute name + * @return bool whether the old attribute can be set + * @see setOldAttribute() + */ + public function canSetOldAttribute($name) + { + return (isset($this->_oldAttributes[$name]) || $this->hasAttribute($name)); + } + /** * Marks an attribute dirty. * This method may be called to force updating a record when calling [[update()]], diff --git a/db/ColumnSchemaBuilder.php b/db/ColumnSchemaBuilder.php index 756b4b8aa..8bfe2d3e3 100644 --- a/db/ColumnSchemaBuilder.php +++ b/db/ColumnSchemaBuilder.php @@ -1,4 +1,5 @@ pendingParams[$name] = [$value->getValue(), $value->getType()]; $this->params[$name] = $value->getValue(); } else { + if (version_compare(PHP_VERSION, '8.1.0') >= 0) { + if ($value instanceof \BackedEnum) { + $value = $value->value; + } elseif ($value instanceof \UnitEnum) { + $value = $value->name; + } + } $type = $schema->getPdoType($value); $this->pendingParams[$name] = [$value, $type]; $this->params[$name] = $value; @@ -631,15 +638,15 @@ public function delete($table, $condition = '', $params = []) * * The columns in the new table should be specified as name-definition pairs (e.g. 'name' => 'string'), * where name stands for a column name which will be properly quoted by the method, and definition - * stands for the column type which must contain an abstract DB type. - * + * stands for the column type which must contain an abstract DB type. + * * The method [[QueryBuilder::getColumnType()]] will be called * to convert the abstract column types to physical ones. For example, `string` will be converted * as `varchar(255)`, and `string not null` becomes `varchar(255) not null`. * * If a column is specified with definition only (e.g. 'PRIMARY KEY (name, type)'), it will be directly * inserted into the generated SQL. - * + * * Example usage: * ```php * Yii::$app->db->createCommand()->createTable('post', [ @@ -647,7 +654,7 @@ public function delete($table, $condition = '', $params = []) * 'title' => 'string', * 'text' => 'text', * 'column_name double precision null default null', - * ]); + * ]); * ``` * * @param string $table the name of the table to be created. The name will be properly quoted by the method. diff --git a/db/Connection.php b/db/Connection.php index 4df8f3af6..050b5fe9f 100644 --- a/db/Connection.php +++ b/db/Connection.php @@ -1,4 +1,5 @@ 'yii\db\oci\Schema', // Oracle driver 'mssql' => 'yii\db\mssql\Schema', // older MSSQL driver on MS Windows hosts 'dblib' => 'yii\db\mssql\Schema', // dblib drivers on GNU/Linux (and maybe other OSes) hosts - 'cubrid' => 'yii\db\cubrid\Schema', // CUBRID ]; /** * @var string|null Custom PDO wrapper class. If not set, it will use [[PDO]] or [[\yii\db\mssql\PDO]] when MSSQL is used. @@ -319,7 +319,6 @@ class Connection extends Component 'oci' => 'yii\db\oci\Command', // Oracle driver 'mssql' => 'yii\db\Command', // older MSSQL driver on MS Windows hosts 'dblib' => 'yii\db\Command', // dblib drivers on GNU/Linux (and maybe other OSes) hosts - 'cubrid' => 'yii\db\Command', // CUBRID ]; /** * @var bool whether to enable [savepoint](https://en.wikipedia.org/wiki/Savepoint). @@ -745,7 +744,7 @@ protected function initConnection() if (!$this->isSybase && in_array($this->getDriverName(), ['mssql', 'dblib'], true)) { $this->pdo->exec('SET ANSI_NULL_DFLT_ON ON'); } - if ($this->charset !== null && in_array($this->getDriverName(), ['pgsql', 'mysql', 'mysqli', 'cubrid'], true)) { + if ($this->charset !== null && in_array($this->getDriverName(), ['pgsql', 'mysql', 'mysqli'], true)) { $this->pdo->exec('SET NAMES ' . $this->pdo->quote($this->charset)); } $this->trigger(self::EVENT_AFTER_OPEN); diff --git a/db/cubrid/ColumnSchemaBuilder.php b/db/cubrid/ColumnSchemaBuilder.php deleted file mode 100644 index e3f402b03..000000000 --- a/db/cubrid/ColumnSchemaBuilder.php +++ /dev/null @@ -1,72 +0,0 @@ - - * @since 2.0.8 - */ -class ColumnSchemaBuilder extends AbstractColumnSchemaBuilder -{ - /** - * {@inheritdoc} - */ - protected function buildUnsignedString() - { - return $this->isUnsigned ? ' UNSIGNED' : ''; - } - - /** - * {@inheritdoc} - */ - protected function buildAfterString() - { - return $this->after !== null ? - ' AFTER ' . $this->db->quoteColumnName($this->after) : - ''; - } - - /** - * {@inheritdoc} - */ - protected function buildFirstString() - { - return $this->isFirst ? ' FIRST' : ''; - } - - /** - * {@inheritdoc} - */ - protected function buildCommentString() - { - return $this->comment !== null ? ' COMMENT ' . $this->db->quoteValue($this->comment) : ''; - } - - /** - * {@inheritdoc} - */ - public function __toString() - { - switch ($this->getTypeCategory()) { - case self::CATEGORY_PK: - $format = '{type}{check}{comment}{append}{pos}'; - break; - case self::CATEGORY_NUMERIC: - $format = '{type}{length}{unsigned}{notnull}{unique}{default}{check}{comment}{append}{pos}'; - break; - default: - $format = '{type}{length}{notnull}{unique}{default}{check}{comment}{append}{pos}'; - } - - return $this->buildCompleteString($format); - } -} diff --git a/db/cubrid/QueryBuilder.php b/db/cubrid/QueryBuilder.php deleted file mode 100644 index 72ac4df6e..000000000 --- a/db/cubrid/QueryBuilder.php +++ /dev/null @@ -1,294 +0,0 @@ - - * @since 2.0 - */ -class QueryBuilder extends \yii\db\QueryBuilder -{ - /** - * @var array mapping from abstract column types (keys) to physical column types (values). - */ - public $typeMap = [ - Schema::TYPE_PK => 'int NOT NULL AUTO_INCREMENT PRIMARY KEY', - Schema::TYPE_UPK => 'int UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY', - Schema::TYPE_BIGPK => 'bigint NOT NULL AUTO_INCREMENT PRIMARY KEY', - Schema::TYPE_UBIGPK => 'bigint UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY', - Schema::TYPE_CHAR => 'char(1)', - Schema::TYPE_STRING => 'varchar(255)', - Schema::TYPE_TEXT => 'varchar', - Schema::TYPE_TINYINT => 'smallint', - Schema::TYPE_SMALLINT => 'smallint', - Schema::TYPE_INTEGER => 'int', - Schema::TYPE_BIGINT => 'bigint', - Schema::TYPE_FLOAT => 'float(7)', - Schema::TYPE_DOUBLE => 'double(15)', - 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 => 'smallint', - Schema::TYPE_MONEY => 'decimal(19,4)', - ]; - - - /** - * {@inheritdoc} - */ - protected function defaultExpressionBuilders() - { - return array_merge(parent::defaultExpressionBuilders(), [ - 'yii\db\conditions\LikeCondition' => 'yii\db\cubrid\conditions\LikeConditionBuilder', - ]); - } - - /** - * {@inheritdoc} - * @see https://www.cubrid.org/manual/en/9.3.0/sql/query/merge.html - */ - public function upsert($table, $insertColumns, $updateColumns, &$params) - { - /** @var Constraint[] $constraints */ - list($uniqueNames, $insertNames, $updateNames) = $this->prepareUpsertColumns($table, $insertColumns, $updateColumns, $constraints); - if (empty($uniqueNames)) { - return $this->insert($table, $insertColumns, $params); - } - if ($updateNames === []) { - // there are no columns to update - $updateColumns = false; - } - - $onCondition = ['or']; - $quotedTableName = $this->db->quoteTableName($table); - foreach ($constraints as $constraint) { - $constraintCondition = ['and']; - foreach ($constraint->columnNames as $name) { - $quotedName = $this->db->quoteColumnName($name); - $constraintCondition[] = "$quotedTableName.$quotedName=\"EXCLUDED\".$quotedName"; - } - $onCondition[] = $constraintCondition; - } - $on = $this->buildCondition($onCondition, $params); - list(, $placeholders, $values, $params) = $this->prepareInsertValues($table, $insertColumns, $params); - $mergeSql = 'MERGE INTO ' . $this->db->quoteTableName($table) . ' ' - . 'USING (' . (!empty($placeholders) ? 'VALUES (' . implode(', ', $placeholders) . ')' : ltrim($values, ' ')) . ') AS "EXCLUDED" (' . implode(', ', $insertNames) . ') ' - . "ON ($on)"; - $insertValues = []; - foreach ($insertNames as $name) { - $quotedName = $this->db->quoteColumnName($name); - if (strrpos($quotedName, '.') === false) { - $quotedName = '"EXCLUDED".' . $quotedName; - } - $insertValues[] = $quotedName; - } - $insertSql = 'INSERT (' . implode(', ', $insertNames) . ')' - . ' VALUES (' . implode(', ', $insertValues) . ')'; - if ($updateColumns === false) { - return "$mergeSql WHEN NOT MATCHED THEN $insertSql"; - } - - if ($updateColumns === true) { - $updateColumns = []; - foreach ($updateNames as $name) { - $quotedName = $this->db->quoteColumnName($name); - if (strrpos($quotedName, '.') === false) { - $quotedName = '"EXCLUDED".' . $quotedName; - } - $updateColumns[$name] = new Expression($quotedName); - } - } - list($updates, $params) = $this->prepareUpdateSets($table, $updateColumns, $params); - $updateSql = 'UPDATE SET ' . implode(', ', $updates); - return "$mergeSql WHEN MATCHED THEN $updateSql WHEN NOT MATCHED THEN $insertSql"; - } - - /** - * Creates a SQL statement for resetting the sequence value of a table's primary key. - * The sequence will be reset such that the primary key of the next new row inserted - * will have the specified value or 1. - * @param string $tableName the name of the table whose primary key sequence will be reset - * @param mixed $value the value for the primary key of the next new row inserted. If this is not set, - * the next new row's primary key will have a value 1. - * @return string the SQL statement for resetting sequence - * @throws InvalidArgumentException if the table does not exist or there is no sequence associated with the table. - */ - public function resetSequence($tableName, $value = null) - { - $table = $this->db->getTableSchema($tableName); - if ($table !== null && $table->sequenceName !== null) { - $tableName = $this->db->quoteTableName($tableName); - if ($value === null) { - $key = reset($table->primaryKey); - $value = (int) $this->db->createCommand("SELECT MAX(`$key`) FROM " . $this->db->schema->quoteTableName($tableName))->queryScalar() + 1; - } else { - $value = (int) $value; - } - - return 'ALTER TABLE ' . $this->db->schema->quoteTableName($tableName) . " AUTO_INCREMENT=$value;"; - } elseif ($table === null) { - throw new InvalidArgumentException("Table not found: $tableName"); - } - - throw new InvalidArgumentException("There is not sequence associated with table '$tableName'."); - } - - /** - * {@inheritdoc} - */ - public function buildLimit($limit, $offset) - { - $sql = ''; - // limit is not optional in CUBRID - // https://www.cubrid.org/manual/en/9.3.0/sql/query/select.html#limit-clause - // "You can specify a very big integer for row_count to display to the last row, starting from a specific row." - if ($this->hasLimit($limit)) { - $sql = 'LIMIT ' . $limit; - if ($this->hasOffset($offset)) { - $sql .= ' OFFSET ' . $offset; - } - } elseif ($this->hasOffset($offset)) { - $sql = "LIMIT 9223372036854775807 OFFSET $offset"; // 2^63-1 - } - - return $sql; - } - - /** - * {@inheritdoc} - * @since 2.0.8 - */ - public function selectExists($rawSql) - { - return 'SELECT CASE WHEN EXISTS(' . $rawSql . ') THEN 1 ELSE 0 END'; - } - - /** - * {@inheritdoc} - * @see https://www.cubrid.org/manual/en/9.3.0/sql/schema/table.html#drop-index-clause - */ - public function dropIndex($name, $table) - { - /** @var Schema $schema */ - $schema = $this->db->getSchema(); - foreach ($schema->getTableUniques($table) as $unique) { - if ($unique->name === $name) { - return $this->dropUnique($name, $table); - } - } - - return 'DROP INDEX ' . $this->db->quoteTableName($name) . ' ON ' . $this->db->quoteTableName($table); - } - - /** - * {@inheritdoc} - * @throws NotSupportedException this is not supported by CUBRID. - */ - public function addCheck($name, $table, $expression) - { - throw new NotSupportedException(__METHOD__ . ' is not supported by CUBRID.'); - } - - /** - * {@inheritdoc} - * @throws NotSupportedException this is not supported by CUBRID. - */ - public function dropCheck($name, $table) - { - throw new NotSupportedException(__METHOD__ . ' is not supported by CUBRID.'); - } - - /** - * {@inheritdoc} - * @since 2.0.8 - */ - public function addCommentOnColumn($table, $column, $comment) - { - $definition = $this->getColumnDefinition($table, $column); - $definition = trim(preg_replace("/COMMENT '(.*?)'/i", '', $definition)); - - return 'ALTER TABLE ' . $this->db->quoteTableName($table) - . ' CHANGE ' . $this->db->quoteColumnName($column) - . ' ' . $this->db->quoteColumnName($column) - . (empty($definition) ? '' : ' ' . $definition) - . ' COMMENT ' . $this->db->quoteValue($comment); - } - - /** - * {@inheritdoc} - * @since 2.0.8 - */ - public function addCommentOnTable($table, $comment) - { - return 'ALTER TABLE ' . $this->db->quoteTableName($table) . ' COMMENT ' . $this->db->quoteValue($comment); - } - - /** - * {@inheritdoc} - * @since 2.0.8 - */ - public function dropCommentFromColumn($table, $column) - { - return $this->addCommentOnColumn($table, $column, ''); - } - - /** - * {@inheritdoc} - * @since 2.0.8 - */ - public function dropCommentFromTable($table) - { - return $this->addCommentOnTable($table, ''); - } - - - /** - * Gets column definition. - * - * @param string $table table name - * @param string $column column name - * @return string|null the column definition - * @throws Exception in case when table does not contain column - * @since 2.0.8 - */ - private function getColumnDefinition($table, $column) - { - $row = $this->db->createCommand('SHOW CREATE TABLE ' . $this->db->quoteTableName($table))->queryOne(); - if ($row === false) { - throw new Exception("Unable to find column '$column' in table '$table'."); - } - if (isset($row['Create Table'])) { - $sql = $row['Create Table']; - } else { - $row = array_values($row); - $sql = $row[1]; - } - $sql = preg_replace('/^[^(]+\((.*)\).*$/', '\1', $sql); - $sql = str_replace(', [', ",\n[", $sql); - if (preg_match_all('/^\s*\[(.*?)\]\s+(.*?),?$/m', $sql, $matches)) { - foreach ($matches[1] as $i => $c) { - if ($c === $column) { - return $matches[2][$i]; - } - } - } - - return null; - } -} diff --git a/db/cubrid/Schema.php b/db/cubrid/Schema.php deleted file mode 100644 index 74adba234..000000000 --- a/db/cubrid/Schema.php +++ /dev/null @@ -1,419 +0,0 @@ - - * @since 2.0 - */ -class Schema extends \yii\db\Schema implements ConstraintFinderInterface -{ - use ConstraintFinderTrait; - - /** - * @var array mapping from physical column types (keys) to abstract column types (values) - * Please refer to [CUBRID manual](https://www.cubrid.org/manual/en/9.3.0/sql/datatype.html) for - * details on data types. - */ - public $typeMap = [ - // Numeric data types - 'short' => self::TYPE_SMALLINT, - 'smallint' => self::TYPE_SMALLINT, - 'int' => self::TYPE_INTEGER, - 'integer' => self::TYPE_INTEGER, - 'bigint' => self::TYPE_BIGINT, - 'numeric' => self::TYPE_DECIMAL, - 'decimal' => self::TYPE_DECIMAL, - 'float' => self::TYPE_FLOAT, - 'real' => self::TYPE_FLOAT, - 'double' => self::TYPE_DOUBLE, - 'double precision' => self::TYPE_DOUBLE, - 'monetary' => self::TYPE_MONEY, - // Date/Time data types - 'date' => self::TYPE_DATE, - 'time' => self::TYPE_TIME, - 'timestamp' => self::TYPE_TIMESTAMP, - 'datetime' => self::TYPE_DATETIME, - // String data types - 'char' => self::TYPE_CHAR, - 'varchar' => self::TYPE_STRING, - 'char varying' => self::TYPE_STRING, - 'nchar' => self::TYPE_CHAR, - 'nchar varying' => self::TYPE_STRING, - 'string' => self::TYPE_STRING, - // BLOB/CLOB data types - 'blob' => self::TYPE_BINARY, - 'clob' => self::TYPE_BINARY, - // Bit string data types - 'bit' => self::TYPE_INTEGER, - 'bit varying' => self::TYPE_INTEGER, - // Collection data types (considered strings for now) - 'set' => self::TYPE_STRING, - 'multiset' => self::TYPE_STRING, - 'list' => self::TYPE_STRING, - 'sequence' => self::TYPE_STRING, - 'enum' => self::TYPE_STRING, - ]; - /** - * @var array map of DB errors and corresponding exceptions - * If left part is found in DB error message exception class from the right part is used. - */ - public $exceptionMap = [ - 'Operation would have caused one or more unique constraint violations' => 'yii\db\IntegrityException', - ]; - - /** - * {@inheritdoc} - */ - protected $tableQuoteCharacter = '"'; - - - /** - * {@inheritdoc} - */ - protected function findTableNames($schema = '') - { - $pdo = $this->db->getSlavePdo(true); - $tables = $pdo->cubrid_schema(\PDO::CUBRID_SCH_TABLE); - $tableNames = []; - foreach ($tables as $table) { - // do not list system tables - if ($table['TYPE'] != 0) { - $tableNames[] = $table['NAME']; - } - } - - return $tableNames; - } - - /** - * {@inheritdoc} - */ - protected function loadTableSchema($name) - { - $pdo = $this->db->getSlavePdo(true); - - $tableInfo = $pdo->cubrid_schema(\PDO::CUBRID_SCH_TABLE, $name); - - if (!isset($tableInfo[0]['NAME'])) { - return null; - } - - $table = new TableSchema(); - $table->fullName = $table->name = $tableInfo[0]['NAME']; - - $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; - } - - $primaryKeys = $pdo->cubrid_schema(\PDO::CUBRID_SCH_PRIMARY_KEY, $table->name); - foreach ($primaryKeys as $key) { - $column = $table->columns[$key['ATTR_NAME']]; - $column->isPrimaryKey = true; - $table->primaryKey[] = $column->name; - if ($column->autoIncrement) { - $table->sequenceName = ''; - } - } - - $foreignKeys = $pdo->cubrid_schema(\PDO::CUBRID_SCH_IMPORTED_KEYS, $table->name); - foreach ($foreignKeys as $key) { - if (isset($table->foreignKeys[$key['FK_NAME']])) { - $table->foreignKeys[$key['FK_NAME']][$key['FKCOLUMN_NAME']] = $key['PKCOLUMN_NAME']; - } else { - $table->foreignKeys[$key['FK_NAME']] = [ - $key['PKTABLE_NAME'], - $key['FKCOLUMN_NAME'] => $key['PKCOLUMN_NAME'], - ]; - } - } - - return $table; - } - - /** - * {@inheritdoc} - */ - protected function loadTablePrimaryKey($tableName) - { - $primaryKey = $this->db->getSlavePdo(true)->cubrid_schema(\PDO::CUBRID_SCH_PRIMARY_KEY, $tableName); - if (empty($primaryKey)) { - return null; - } - - ArrayHelper::multisort($primaryKey, 'KEY_SEQ', SORT_ASC, SORT_NUMERIC); - return new Constraint([ - 'name' => $primaryKey[0]['KEY_NAME'], - 'columnNames' => ArrayHelper::getColumn($primaryKey, 'ATTR_NAME'), - ]); - } - - /** - * {@inheritdoc} - */ - protected function loadTableForeignKeys($tableName) - { - static $actionTypes = [ - 0 => 'CASCADE', - 1 => 'RESTRICT', - 2 => 'NO ACTION', - 3 => 'SET NULL', - ]; - - $foreignKeys = $this->db->getSlavePdo(true)->cubrid_schema(\PDO::CUBRID_SCH_IMPORTED_KEYS, $tableName); - $foreignKeys = ArrayHelper::index($foreignKeys, null, 'FK_NAME'); - ArrayHelper::multisort($foreignKeys, 'KEY_SEQ', SORT_ASC, SORT_NUMERIC); - $result = []; - foreach ($foreignKeys as $name => $foreignKey) { - $result[] = new ForeignKeyConstraint([ - 'name' => $name, - 'columnNames' => ArrayHelper::getColumn($foreignKey, 'FKCOLUMN_NAME'), - 'foreignTableName' => $foreignKey[0]['PKTABLE_NAME'], - 'foreignColumnNames' => ArrayHelper::getColumn($foreignKey, 'PKCOLUMN_NAME'), - 'onDelete' => isset($actionTypes[$foreignKey[0]['DELETE_RULE']]) ? $actionTypes[$foreignKey[0]['DELETE_RULE']] : null, - 'onUpdate' => isset($actionTypes[$foreignKey[0]['UPDATE_RULE']]) ? $actionTypes[$foreignKey[0]['UPDATE_RULE']] : null, - ]); - } - - return $result; - } - - /** - * {@inheritdoc} - */ - protected function loadTableIndexes($tableName) - { - return $this->loadTableConstraints($tableName, 'indexes'); - } - - /** - * {@inheritdoc} - */ - protected function loadTableUniques($tableName) - { - return $this->loadTableConstraints($tableName, 'uniques'); - } - - /** - * {@inheritdoc} - * @throws NotSupportedException if this method is called. - */ - protected function loadTableChecks($tableName) - { - throw new NotSupportedException('CUBRID does not support check constraints.'); - } - - /** - * {@inheritdoc} - * @throws NotSupportedException if this method is called. - */ - protected function loadTableDefaultValues($tableName) - { - throw new NotSupportedException('CUBRID does not support default value constraints.'); - } - - /** - * {@inheritdoc} - */ - public function releaseSavepoint($name) - { - // does nothing as cubrid does not support this - } - - /** - * Creates a query builder for the CUBRID database. - * @return QueryBuilder query builder instance - */ - public function createQueryBuilder() - { - return Yii::createObject(QueryBuilder::class, [$this->db]); - } - - /** - * Loads the column information into a [[ColumnSchema]] object. - * @param array $info column information - * @return \yii\db\ColumnSchema the column schema object - */ - protected function loadColumnSchema($info) - { - $column = $this->createColumnSchema(); - - $column->name = $info['Field']; - $column->allowNull = $info['Null'] === 'YES'; - $column->isPrimaryKey = false; // primary key will be set by loadTableSchema() later - $column->autoIncrement = stripos($info['Extra'], 'auto_increment') !== false; - - $column->dbType = $info['Type']; - $column->unsigned = strpos($column->dbType, 'unsigned') !== false; - - $column->type = self::TYPE_STRING; - if (preg_match('/^([\w ]+)(?:\(([^\)]+)\))?$/', $column->dbType, $matches)) { - $type = strtolower($matches[1]); - $column->dbType = $type . (isset($matches[2]) ? "({$matches[2]})" : ''); - if (isset($this->typeMap[$type])) { - $column->type = $this->typeMap[$type]; - } - if (!empty($matches[2])) { - if ($type === 'enum') { - $values = preg_split('/\s*,\s*/', $matches[2]); - foreach ($values as $i => $value) { - $values[$i] = trim($value, "'"); - } - $column->enumValues = $values; - } else { - $values = explode(',', $matches[2]); - $column->size = $column->precision = (int) $values[0]; - if (isset($values[1])) { - $column->scale = (int) $values[1]; - } - if ($column->size === 1 && $type === 'bit') { - $column->type = 'boolean'; - } elseif ($type === 'bit') { - if ($column->size > 32) { - $column->type = 'bigint'; - } elseif ($column->size === 32) { - $column->type = 'integer'; - } - } - } - } - } - - $column->phpType = $this->getColumnPhpType($column); - - if ($column->isPrimaryKey) { - return $column; - } - - if ($column->type === 'timestamp' && $info['Default'] === 'SYS_TIMESTAMP' || - $column->type === 'datetime' && $info['Default'] === 'SYS_DATETIME' || - $column->type === 'date' && $info['Default'] === 'SYS_DATE' || - $column->type === 'time' && $info['Default'] === 'SYS_TIME' - ) { - $column->defaultValue = new Expression($info['Default']); - } elseif (isset($type) && $type === 'bit') { - $column->defaultValue = hexdec(trim($info['Default'], 'X\'')); - } else { - $column->defaultValue = $column->phpTypecast($info['Default']); - } - - return $column; - } - - /** - * Determines the PDO type for the given PHP data value. - * @param mixed $data the data whose PDO type is to be determined - * @return int the PDO type - * @see https://www.php.net/manual/en/pdo.constants.php - */ - public function getPdoType($data) - { - static $typeMap = [ - // php type => PDO type - 'boolean' => \PDO::PARAM_INT, // PARAM_BOOL is not supported by CUBRID PDO - 'integer' => \PDO::PARAM_INT, - 'string' => \PDO::PARAM_STR, - 'resource' => \PDO::PARAM_LOB, - 'NULL' => \PDO::PARAM_NULL, - ]; - $type = gettype($data); - - return isset($typeMap[$type]) ? $typeMap[$type] : \PDO::PARAM_STR; - } - - /** - * {@inheritdoc} - * @see https://www.cubrid.org/manual/en/9.3.0/sql/transaction.html#database-concurrency - */ - public function setTransactionIsolationLevel($level) - { - // translate SQL92 levels to CUBRID levels: - switch ($level) { - case Transaction::SERIALIZABLE: - $level = '6'; // SERIALIZABLE - break; - case Transaction::REPEATABLE_READ: - $level = '5'; // REPEATABLE READ CLASS with REPEATABLE READ INSTANCES - break; - case Transaction::READ_COMMITTED: - $level = '4'; // REPEATABLE READ CLASS with READ COMMITTED INSTANCES - break; - case Transaction::READ_UNCOMMITTED: - $level = '3'; // REPEATABLE READ CLASS with READ UNCOMMITTED INSTANCES - break; - } - parent::setTransactionIsolationLevel($level); - } - - /** - * {@inheritdoc} - */ - public function createColumnSchemaBuilder($type, $length = null) - { - return new ColumnSchemaBuilder($type, $length, $this->db); - } - - /** - * Loads multiple types of constraints and returns the specified ones. - * @param string $tableName table name. - * @param string $returnType return type: - * - indexes - * - uniques - * @return mixed constraints. - */ - private function loadTableConstraints($tableName, $returnType) - { - $constraints = $this->db->getSlavePdo(true)->cubrid_schema(\PDO::CUBRID_SCH_CONSTRAINT, $tableName); - $constraints = ArrayHelper::index($constraints, null, ['TYPE', 'NAME']); - ArrayHelper::multisort($constraints, 'KEY_ORDER', SORT_ASC, SORT_NUMERIC); - $result = [ - 'indexes' => [], - 'uniques' => [], - ]; - foreach ($constraints as $type => $names) { - foreach ($names as $name => $constraint) { - $isUnique = in_array((int) $type, [0, 2], true); - $result['indexes'][] = new IndexConstraint([ - 'isPrimary' => (bool) $constraint[0]['PRIMARY_KEY'], - 'isUnique' => $isUnique, - 'name' => $name, - 'columnNames' => ArrayHelper::getColumn($constraint, 'ATTR_NAME'), - ]); - if ($isUnique) { - $result['uniques'][] = new Constraint([ - 'name' => $name, - 'columnNames' => ArrayHelper::getColumn($constraint, 'ATTR_NAME'), - ]); - } - } - } - foreach ($result as $type => $data) { - $this->setTableMetadata($tableName, $type, $data); - } - - return $result[$returnType]; - } -} diff --git a/db/cubrid/conditions/LikeConditionBuilder.php b/db/cubrid/conditions/LikeConditionBuilder.php deleted file mode 100644 index 80cd27173..000000000 --- a/db/cubrid/conditions/LikeConditionBuilder.php +++ /dev/null @@ -1,29 +0,0 @@ - '!%', - '_' => '!_', - '!' => '!!', - ]; -} From ca8759834bbdadfdf72c7a23ed75a30d8bfaa1f6 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Tue, 18 Jul 2023 10:54:55 -0400 Subject: [PATCH 05/31] Remove deprecated `InvalidParamException::class` in branch `2.2`. (#19896) --- base/InvalidArgumentException.php | 2 +- base/InvalidParamException.php | 26 ----------------------- classes.php | 1 - console/controllers/FixtureController.php | 4 ++-- db/BaseActiveRecord.php | 5 ++--- db/conditions/ConditionInterface.php | 4 ++-- rbac/CheckAccessInterface.php | 2 +- rbac/ManagerInterface.php | 2 +- web/ErrorHandler.php | 2 +- 9 files changed, 10 insertions(+), 38 deletions(-) delete mode 100644 base/InvalidParamException.php diff --git a/base/InvalidArgumentException.php b/base/InvalidArgumentException.php index 20a7c6c75..428d73b58 100644 --- a/base/InvalidArgumentException.php +++ b/base/InvalidArgumentException.php @@ -13,7 +13,7 @@ * @author Qiang Xue * @since 2.0.14 */ -class InvalidArgumentException extends InvalidParamException +class InvalidArgumentException extends \BadMethodCallException { /** * @return string the user-friendly name of this exception diff --git a/base/InvalidParamException.php b/base/InvalidParamException.php deleted file mode 100644 index 0024602ec..000000000 --- a/base/InvalidParamException.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @since 2.0 - * @deprecated since 2.0.14. Use [[InvalidArgumentException]] instead. - */ -class InvalidParamException extends \BadMethodCallException -{ - /** - * @return string the user-friendly name of this exception - */ - public function getName() - { - return 'Invalid Parameter'; - } -} diff --git a/classes.php b/classes.php index 3d4759ed4..4f52f31ba 100644 --- a/classes.php +++ b/classes.php @@ -37,7 +37,6 @@ 'yii\base\InvalidArgumentException' => YII2_PATH . '/base/InvalidArgumentException.php', 'yii\base\InvalidCallException' => YII2_PATH . '/base/InvalidCallException.php', 'yii\base\InvalidConfigException' => YII2_PATH . '/base/InvalidConfigException.php', - 'yii\base\InvalidParamException' => YII2_PATH . '/base/InvalidParamException.php', 'yii\base\InvalidRouteException' => YII2_PATH . '/base/InvalidRouteException.php', 'yii\base\InvalidValueException' => YII2_PATH . '/base/InvalidValueException.php', 'yii\base\Model' => YII2_PATH . '/base/Model.php', diff --git a/console/controllers/FixtureController.php b/console/controllers/FixtureController.php index a210034b7..9187ea517 100644 --- a/console/controllers/FixtureController.php +++ b/console/controllers/FixtureController.php @@ -8,8 +8,8 @@ namespace yii\console\controllers; use Yii; +use yii\base\InvalidArgumentException; use yii\base\InvalidConfigException; -use yii\base\InvalidParamException; use yii\console\Controller; use yii\console\Exception; use yii\console\ExitCode; @@ -536,7 +536,7 @@ private function getFixturePath() { try { return Yii::getAlias('@' . str_replace('\\', '/', $this->namespace)); - } catch (InvalidParamException $e) { + } catch (InvalidArgumentException $e) { throw new InvalidConfigException('Invalid fixture namespace: "' . $this->namespace . '". Please, check your FixtureController::namespace parameter'); } } diff --git a/db/BaseActiveRecord.php b/db/BaseActiveRecord.php index 88fb2f11d..42271a144 100644 --- a/db/BaseActiveRecord.php +++ b/db/BaseActiveRecord.php @@ -11,7 +11,6 @@ use yii\base\InvalidArgumentException; use yii\base\InvalidCallException; use yii\base\InvalidConfigException; -use yii\base\InvalidParamException; use yii\base\Model; use yii\base\ModelEvent; use yii\base\NotSupportedException; @@ -1632,7 +1631,7 @@ public function getAttributeLabel($attribute) } else { try { $relation = $relatedModel->getRelation($relationName); - } catch (InvalidParamException $e) { + } catch (InvalidArgumentException $e) { return $this->generateAttributeLabel($attribute); } /* @var $modelClass ActiveRecordInterface */ @@ -1674,7 +1673,7 @@ public function getAttributeHint($attribute) } else { try { $relation = $relatedModel->getRelation($relationName); - } catch (InvalidParamException $e) { + } catch (InvalidArgumentException $e) { return ''; } /* @var $modelClass ActiveRecordInterface */ diff --git a/db/conditions/ConditionInterface.php b/db/conditions/ConditionInterface.php index fc8146940..96d63548c 100644 --- a/db/conditions/ConditionInterface.php +++ b/db/conditions/ConditionInterface.php @@ -7,7 +7,7 @@ namespace yii\db\conditions; -use yii\base\InvalidParamException; +use InvalidArgumentException; use yii\db\ExpressionInterface; /** @@ -27,7 +27,7 @@ interface ConditionInterface extends ExpressionInterface * @param array $operands array of corresponding operands * * @return $this - * @throws InvalidParamException if input parameters are not suitable for this condition + * @throws InvalidArgumentException if input parameters are not suitable for this condition */ public static function fromArrayDefinition($operator, $operands); } diff --git a/rbac/CheckAccessInterface.php b/rbac/CheckAccessInterface.php index 38d86ee7a..7f4dce00b 100644 --- a/rbac/CheckAccessInterface.php +++ b/rbac/CheckAccessInterface.php @@ -23,7 +23,7 @@ interface CheckAccessInterface * @param array $params name-value pairs that will be passed to the rules associated * with the roles and permissions assigned to the user. * @return bool whether the user has the specified permission. - * @throws \yii\base\InvalidParamException if $permissionName does not refer to an existing permission + * @throws \yii\base\InvalidArgumentException if $permissionName does not refer to an existing permission */ public function checkAccess($userId, $permissionName, $params = []); } diff --git a/rbac/ManagerInterface.php b/rbac/ManagerInterface.php index e4d2c7029..fec06fdc0 100644 --- a/rbac/ManagerInterface.php +++ b/rbac/ManagerInterface.php @@ -83,7 +83,7 @@ public function getRolesByUser($userId); * @param string $roleName name of the role to file child roles for * @return Role[] Child roles. The array is indexed by the role names. * First element is an instance of the parent Role itself. - * @throws \yii\base\InvalidParamException if Role was not found that are getting by $roleName + * @throws \yii\base\InvalidArgumentException if Role was not found that are getting by $roleName * @since 2.0.10 */ public function getChildRoles($roleName); diff --git a/web/ErrorHandler.php b/web/ErrorHandler.php index 3806c576c..cf97936e0 100644 --- a/web/ErrorHandler.php +++ b/web/ErrorHandler.php @@ -487,7 +487,7 @@ public function argumentsToString($args) */ public function getExceptionName($exception) { - if ($exception instanceof \yii\base\Exception || $exception instanceof \yii\base\InvalidCallException || $exception instanceof \yii\base\InvalidParamException || $exception instanceof \yii\base\UnknownMethodException) { + if ($exception instanceof \yii\base\Exception || $exception instanceof \yii\base\InvalidCallException || $exception instanceof \yii\base\InvalidArgumentException || $exception instanceof \yii\base\UnknownMethodException) { return $exception->getName(); } From 76a90214d585bd7aa61616447a0daf3ece0a53f6 Mon Sep 17 00:00:00 2001 From: "Stefano D. Mtangoo" Date: Mon, 24 Jul 2023 09:08:59 +0300 Subject: [PATCH 06/31] Remove XCache and ZendDataCache support (#19904) Co-authored-by: Stefano Mtangoo --- CHANGELOG.md | 1 + UPGRADE.md | 1 - caching/XCache.php | 111 -------------------------------------- caching/ZendDataCache.php | 89 ------------------------------ classes.php | 2 - 5 files changed, 1 insertion(+), 203 deletions(-) delete mode 100644 caching/XCache.php delete mode 100644 caching/ZendDataCache.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bd17d17e..06d86c145 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Yii Framework 2 Change Log ------------------------ - Chg #19902: Remove support for CUBRID (mtangoo) +- Chg #19891: Remove XCache and ZendDataCache support (mtangoo) 2.0.49 under development diff --git a/UPGRADE.md b/UPGRADE.md index 8286cf010..539873408 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -526,7 +526,6 @@ Upgrade from Yii 2.0.13 - Replace usages of `yii\base\InvalidParamException` with `yii\base\InvalidArgumentException`. - Replace calls to `Yii::trace()` with `Yii::debug()`. - Remove calls to `yii\BaseYii::powered()`. - - If you are using XCache or Zend data cache, those are going away in 2.1 so you might want to start looking for an alternative. * In case you aren't using CSRF cookies (REST APIs etc.) you should turn them off explicitly by setting `\yii\web\Request::$enableCsrfCookie` to `false` in your config file. diff --git a/caching/XCache.php b/caching/XCache.php deleted file mode 100644 index 06c305de2..000000000 --- a/caching/XCache.php +++ /dev/null @@ -1,111 +0,0 @@ - - * @since 2.0 - * @deprecated since 2.0.14. This class will be removed in 2.1.0. - */ -class XCache extends Cache -{ - /** - * Checks whether a specified key exists in the cache. - * This can be faster than getting the value from the cache if the data is big. - * Note that this method does not check whether the dependency associated - * with the cached data, if there is any, has changed. So a call to [[get]] - * may return false while exists returns true. - * @param mixed $key a key identifying the cached value. This can be a simple string or - * a complex data structure consisting of factors representing the key. - * @return bool true if a value exists in cache, false if the value is not in the cache or expired. - */ - public function exists($key) - { - $key = $this->buildKey($key); - - return xcache_isset($key); - } - - /** - * Retrieves a value from cache with a specified key. - * This is the implementation of the method declared in the parent class. - * @param string $key a unique key identifying the cached value - * @return mixed|false the value stored in cache, false if the value is not in the cache or expired. - */ - protected function getValue($key) - { - return xcache_isset($key) ? xcache_get($key) : false; - } - - /** - * Stores a value identified by a key in cache. - * This is the implementation of the method declared in the parent class. - * - * @param string $key the key identifying the value to be cached - * @param mixed $value the value to be cached. Most often it's a string. If you have disabled [[serializer]], - * it could be something else. - * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. - * @return bool true if the value is successfully stored into cache, false otherwise - */ - protected function setValue($key, $value, $duration) - { - return xcache_set($key, $value, $duration); - } - - /** - * Stores a value identified by a key into cache if the cache does not contain this key. - * This is the implementation of the method declared in the parent class. - * - * @param string $key the key identifying the value to be cached - * @param mixed $value the value to be cached. Most often it's a string. If you have disabled [[serializer]], - * it could be something else. - * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. - * @return bool true if the value is successfully stored into cache, false otherwise - */ - protected function addValue($key, $value, $duration) - { - return !xcache_isset($key) ? $this->setValue($key, $value, $duration) : false; - } - - /** - * Deletes a value with the specified key from cache - * This is the implementation of the method declared in the parent class. - * @param string $key the key of the value to be deleted - * @return bool if no error happens during deletion - */ - protected function deleteValue($key) - { - return xcache_unset($key); - } - - /** - * Deletes all values from cache. - * This is the implementation of the method declared in the parent class. - * @return bool whether the flush operation was successful. - */ - protected function flushValues() - { - for ($i = 0, $max = xcache_count(XC_TYPE_VAR); $i < $max; $i++) { - if (xcache_clear_cache(XC_TYPE_VAR, $i) === false) { - return false; - } - } - - return true; - } -} diff --git a/caching/ZendDataCache.php b/caching/ZendDataCache.php deleted file mode 100644 index 0f49501db..000000000 --- a/caching/ZendDataCache.php +++ /dev/null @@ -1,89 +0,0 @@ - - * @since 2.0 - * @deprecated since 2.0.14. This class will be removed in 2.1.0. - */ -class ZendDataCache extends Cache -{ - /** - * Retrieves a value from cache with a specified key. - * This is the implementation of the method declared in the parent class. - * @param string $key a unique key identifying the cached value - * @return mixed|false the value stored in cache, false if the value is not in the cache or expired. - */ - protected function getValue($key) - { - $result = zend_shm_cache_fetch($key); - - return $result === null ? false : $result; - } - - /** - * Stores a value identified by a key in cache. - * This is the implementation of the method declared in the parent class. - * - * @param string $key the key identifying the value to be cached - * @param mixed $value the value to be cached. Most often it's a string. If you have disabled [[serializer]], - * it could be something else. - * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. - * @return bool true if the value is successfully stored into cache, false otherwise - */ - protected function setValue($key, $value, $duration) - { - return zend_shm_cache_store($key, $value, $duration); - } - - /** - * Stores a value identified by a key into cache if the cache does not contain this key. - * This is the implementation of the method declared in the parent class. - * - * @param string $key the key identifying the value to be cached - * @param mixed $value the value to be cached. Most often it's a string. If you have disabled [[serializer]], - * it could be something else. - * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. - * @return bool true if the value is successfully stored into cache, false otherwise - */ - protected function addValue($key, $value, $duration) - { - return zend_shm_cache_fetch($key) === null ? $this->setValue($key, $value, $duration) : false; - } - - /** - * Deletes a value with the specified key from cache - * This is the implementation of the method declared in the parent class. - * @param string $key the key of the value to be deleted - * @return bool if no error happens during deletion - */ - protected function deleteValue($key) - { - return zend_shm_cache_delete($key); - } - - /** - * Deletes all values from cache. - * This is the implementation of the method declared in the parent class. - * @return bool whether the flush operation was successful. - */ - protected function flushValues() - { - return zend_shm_cache_clear(); - } -} diff --git a/classes.php b/classes.php index 4f52f31ba..c148e32ef 100644 --- a/classes.php +++ b/classes.php @@ -85,8 +85,6 @@ 'yii\caching\MemCacheServer' => YII2_PATH . '/caching/MemCacheServer.php', 'yii\caching\TagDependency' => YII2_PATH . '/caching/TagDependency.php', 'yii\caching\WinCache' => YII2_PATH . '/caching/WinCache.php', - 'yii\caching\XCache' => YII2_PATH . '/caching/XCache.php', - 'yii\caching\ZendDataCache' => YII2_PATH . '/caching/ZendDataCache.php', 'yii\captcha\Captcha' => YII2_PATH . '/captcha/Captcha.php', 'yii\captcha\CaptchaAction' => YII2_PATH . '/captcha/CaptchaAction.php', 'yii\captcha\CaptchaAsset' => YII2_PATH . '/captcha/CaptchaAsset.php', From 25e58ebeb7581371977fa3a6dcdd3f9f63c705b3 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Mon, 18 Sep 2023 09:59:16 -0300 Subject: [PATCH 07/31] Update framework/CHANGELOG.md Co-authored-by: Robert Korulczyk --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 544684837..91ff0a353 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,6 @@ Yii Framework 2 Change Log - Chg #19891: Remove XCache and ZendDataCache support (mtangoo) -2.0.49 under development 2.0.50 under development ------------------------ From bf0a0f9262d5f450a42257c8b0e98e588fafa057 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Mon, 18 Sep 2023 10:02:20 -0300 Subject: [PATCH 08/31] Apply suggestion review. --- BaseYii.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BaseYii.php b/BaseYii.php index 496f6aa12..29490b908 100644 --- a/BaseYii.php +++ b/BaseYii.php @@ -93,7 +93,7 @@ class BaseYii */ public static function getVersion() { - return '2.0.50-dev'; + return '2.2-dev'; } /** From 6109652817d80b8459c434cebcafb75803d75b9f Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Thu, 21 Sep 2023 10:26:00 -0300 Subject: [PATCH 09/31] Remove deprecated methods to `BaseYii::class`. --- BaseYii.php | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/BaseYii.php b/BaseYii.php index 29490b908..c34360beb 100644 --- a/BaseYii.php +++ b/BaseYii.php @@ -408,18 +408,6 @@ public static function debug($message, $category = 'application') } } - /** - * Alias of [[debug()]]. - * @param string|array $message the message to be logged. This can be a simple string or a more - * complex data structure, such as an array. - * @param string $category the category of the message. - * @deprecated since 2.0.14. Use [[debug()]] instead. - */ - public static function trace($message, $category = 'application') - { - static::debug($message, $category); - } - /** * Logs an error message. * An error message is typically logged when an unrecoverable error occurs @@ -494,19 +482,6 @@ public static function endProfile($token, $category = 'application') static::getLogger()->log($token, Logger::LEVEL_PROFILE_END, $category); } - /** - * Returns an HTML hyperlink that can be displayed on your Web page showing "Powered by Yii Framework" information. - * @return string an HTML hyperlink that can be displayed on your Web page showing "Powered by Yii Framework" information - * @deprecated since 2.0.14, this method will be removed in 2.1.0. - */ - public static function powered() - { - return \Yii::t('yii', 'Powered by {yii}', [ - 'yii' => '' . \Yii::t('yii', - 'Yii Framework') . '', - ]); - } - /** * Translates a message to the specified language. * From b57f3812c1579253703a5abf4e3a1826510d731d Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Thu, 21 Sep 2023 10:38:15 -0300 Subject: [PATCH 10/31] Remove deprecated methods to `Security::class`. --- base/Security.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/base/Security.php b/base/Security.php index e8281b2a6..b63ce5880 100644 --- a/base/Security.php +++ b/base/Security.php @@ -73,16 +73,6 @@ class Security extends Component * Set as high as possible to hinder dictionary password attacks. */ public $derivationIterations = 100000; - /** - * @var string strategy, which should be used to generate password hash. - * Available strategies: - * - 'password_hash' - use of PHP `password_hash()` function with PASSWORD_DEFAULT algorithm. - * This option is recommended, but it requires PHP version >= 5.5.0 - * - 'crypt' - use PHP `crypt()` function. - * @deprecated since version 2.0.7, [[generatePasswordHash()]] ignores [[passwordHashStrategy]] and - * uses `password_hash()` when available or `crypt()` when not. - */ - public $passwordHashStrategy; /** * @var int Default cost used for password hashing. * Allowed value is between 4 and 31. From 5e8d30079bb350da5b8fceb3e87ab04056ab0084 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Thu, 21 Sep 2023 11:00:42 -0300 Subject: [PATCH 11/31] Remove deprecated constant `Controller::class`. --- console/Controller.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/console/Controller.php b/console/Controller.php index 579b59778..5d1b66081 100644 --- a/console/Controller.php +++ b/console/Controller.php @@ -38,15 +38,6 @@ */ class Controller extends \yii\base\Controller { - /** - * @deprecated since 2.0.13. Use [[ExitCode::OK]] instead. - */ - const EXIT_CODE_NORMAL = 0; - /** - * @deprecated since 2.0.13. Use [[ExitCode::UNSPECIFIED_ERROR]] instead. - */ - const EXIT_CODE_ERROR = 1; - /** * @var bool whether to run the command interactively. */ From 8b2f26b718f13e9072fead706b53f8c912db87c6 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Fri, 22 Sep 2023 06:40:49 -0300 Subject: [PATCH 12/31] Remove deprecated methods to `Connection::class`. --- db/Connection.php | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/db/Connection.php b/db/Connection.php index 050b5fe9f..38f1b1e64 100644 --- a/db/Connection.php +++ b/db/Connection.php @@ -289,15 +289,6 @@ class Connection extends Component * @see pdo */ public $pdoClass; - /** - * @var string the class used to create new database [[Command]] objects. If you want to extend the [[Command]] class, - * you may configure this property to use your extended version of the class. - * Since version 2.0.14 [[$commandMap]] is used if this property is set to its default value. - * @see createCommand - * @since 2.0.7 - * @deprecated since 2.0.14. Use [[$commandMap]] for precise configuration. - */ - public $commandClass = 'yii\db\Command'; /** * @var array mapping between PDO driver names and [[Command]] classes. * The keys of the array are PDO driver names while the values are either the corresponding @@ -760,9 +751,7 @@ public function createCommand($sql = null, $params = []) { $driver = $this->getDriverName(); $config = ['class' => 'yii\db\Command']; - if ($this->commandClass !== $config['class']) { - $config['class'] = $this->commandClass; - } elseif (isset($this->commandMap[$driver])) { + if (isset($this->commandMap[$driver])) { $config = !is_array($this->commandMap[$driver]) ? ['class' => $this->commandMap[$driver]] : $this->commandMap[$driver]; } $config['db'] = $this; From 74d18b74ca73f9d302e5f5c810881eecf0054fc0 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Fri, 22 Sep 2023 06:55:44 -0300 Subject: [PATCH 13/31] Remove deprecated methods to `Query::class`. --- db/Query.php | 53 ---------------------------------------------------- 1 file changed, 53 deletions(-) diff --git a/db/Query.php b/db/Query.php index 243d08c4a..9374f9d84 100644 --- a/db/Query.php +++ b/db/Query.php @@ -715,59 +715,6 @@ protected function normalizeSelect($columns) return $select; } - /** - * Returns unique column names excluding duplicates. - * Columns to be removed: - * - if column definition already present in SELECT part with same alias - * - if column definition without alias already present in SELECT part without alias too - * @param array $columns the columns to be merged to the select. - * @since 2.0.14 - * @deprecated in 2.0.21 - */ - protected function getUniqueColumns($columns) - { - $unaliasedColumns = $this->getUnaliasedColumnsFromSelect(); - - $result = []; - foreach ($columns as $columnAlias => $columnDefinition) { - if (!$columnDefinition instanceof Query) { - if (is_string($columnAlias)) { - $existsInSelect = isset($this->select[$columnAlias]) && $this->select[$columnAlias] === $columnDefinition; - if ($existsInSelect) { - continue; - } - } elseif (is_int($columnAlias)) { - $existsInSelect = in_array($columnDefinition, $unaliasedColumns, true); - $existsInResultSet = in_array($columnDefinition, $result, true); - if ($existsInSelect || $existsInResultSet) { - continue; - } - } - } - - $result[$columnAlias] = $columnDefinition; - } - return $result; - } - - /** - * @return array List of columns without aliases from SELECT statement. - * @since 2.0.14 - * @deprecated in 2.0.21 - */ - protected function getUnaliasedColumnsFromSelect() - { - $result = []; - if (is_array($this->select)) { - foreach ($this->select as $name => $value) { - if (is_int($name)) { - $result[] = $value; - } - } - } - return array_unique($result); - } - /** * Sets the value indicating whether to SELECT DISTINCT or not. * @param bool $value whether to SELECT DISTINCT or not. From c7da77ba810df1e4a5c0fd0f38a968caabfb25de Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Fri, 22 Sep 2023 09:45:35 -0300 Subject: [PATCH 14/31] Remove deprecated methods to `QueryBuilder::class`. --- db/QueryBuilder.php | 139 -------------------------------------- db/mssql/QueryBuilder.php | 11 --- 2 files changed, 150 deletions(-) diff --git a/db/QueryBuilder.php b/db/QueryBuilder.php index 114116e67..daa40beaf 100644 --- a/db/QueryBuilder.php +++ b/db/QueryBuilder.php @@ -53,12 +53,6 @@ class QueryBuilder extends \yii\base\BaseObject */ public $typeMap = []; - /** - * @var array map of query condition to builder methods. - * These methods are used by [[buildCondition]] to build SQL conditions from array syntax. - * @deprecated since 2.0.14. Is not used, will be dropped in 2.1.0. - */ - protected $conditionBuilders = []; /** * @var array map of condition aliases to condition classes. For example: * @@ -1611,139 +1605,6 @@ public function createConditionFromArray($condition) return new HashCondition($condition); } - /** - * Creates a condition based on column-value pairs. - * @param array $condition the condition specification. - * @param array $params the binding parameters to be populated - * @return string the generated SQL expression - * @deprecated since 2.0.14. Use `buildCondition()` instead. - */ - public function buildHashCondition($condition, &$params) - { - return $this->buildCondition(new HashCondition($condition), $params); - } - - /** - * Connects two or more SQL expressions with the `AND` or `OR` operator. - * @param string $operator the operator to use for connecting the given operands - * @param array $operands the SQL expressions to connect. - * @param array $params the binding parameters to be populated - * @return string the generated SQL expression - * @deprecated since 2.0.14. Use `buildCondition()` instead. - */ - public function buildAndCondition($operator, $operands, &$params) - { - array_unshift($operands, $operator); - return $this->buildCondition($operands, $params); - } - - /** - * Inverts an SQL expressions with `NOT` operator. - * @param string $operator the operator to use for connecting the given operands - * @param array $operands the SQL expressions to connect. - * @param array $params the binding parameters to be populated - * @return string the generated SQL expression - * @throws InvalidArgumentException if wrong number of operands have been given. - * @deprecated since 2.0.14. Use `buildCondition()` instead. - */ - public function buildNotCondition($operator, $operands, &$params) - { - array_unshift($operands, $operator); - return $this->buildCondition($operands, $params); - } - - /** - * Creates an SQL expressions with the `BETWEEN` operator. - * @param string $operator the operator to use (e.g. `BETWEEN` or `NOT BETWEEN`) - * @param array $operands the first operand is the column name. The second and third operands - * describe the interval that column value should be in. - * @param array $params the binding parameters to be populated - * @return string the generated SQL expression - * @throws InvalidArgumentException if wrong number of operands have been given. - * @deprecated since 2.0.14. Use `buildCondition()` instead. - */ - public function buildBetweenCondition($operator, $operands, &$params) - { - array_unshift($operands, $operator); - return $this->buildCondition($operands, $params); - } - - /** - * Creates an SQL expressions with the `IN` operator. - * @param string $operator the operator to use (e.g. `IN` or `NOT IN`) - * @param array $operands the first operand is the column name. If it is an array - * a composite IN condition will be generated. - * The second operand is an array of values that column value should be among. - * If it is an empty array the generated expression will be a `false` value if - * operator is `IN` and empty if operator is `NOT IN`. - * @param array $params the binding parameters to be populated - * @return string the generated SQL expression - * @throws Exception if wrong number of operands have been given. - * @deprecated since 2.0.14. Use `buildCondition()` instead. - */ - public function buildInCondition($operator, $operands, &$params) - { - array_unshift($operands, $operator); - return $this->buildCondition($operands, $params); - } - - /** - * Creates an SQL expressions with the `LIKE` operator. - * @param string $operator the operator to use (e.g. `LIKE`, `NOT LIKE`, `OR LIKE` or `OR NOT LIKE`) - * @param array $operands an array of two or three operands - * - * - The first operand is the column name. - * - The second operand is a single value or an array of values that column value - * should be compared with. If it is an empty array the generated expression will - * be a `false` value if operator is `LIKE` or `OR LIKE`, and empty if operator - * is `NOT LIKE` or `OR NOT LIKE`. - * - An optional third operand can also be provided to specify how to escape special characters - * in the value(s). The operand should be an array of mappings from the special characters to their - * escaped counterparts. If this operand is not provided, a default escape mapping will be used. - * You may use `false` or an empty array to indicate the values are already escaped and no escape - * should be applied. Note that when using an escape mapping (or the third operand is not provided), - * the values will be automatically enclosed within a pair of percentage characters. - * @param array $params the binding parameters to be populated - * @return string the generated SQL expression - * @throws InvalidArgumentException if wrong number of operands have been given. - * @deprecated since 2.0.14. Use `buildCondition()` instead. - */ - public function buildLikeCondition($operator, $operands, &$params) - { - array_unshift($operands, $operator); - return $this->buildCondition($operands, $params); - } - - /** - * Creates an SQL expressions with the `EXISTS` operator. - * @param string $operator the operator to use (e.g. `EXISTS` or `NOT EXISTS`) - * @param array $operands contains only one element which is a [[Query]] object representing the sub-query. - * @param array $params the binding parameters to be populated - * @return string the generated SQL expression - * @throws InvalidArgumentException if the operand is not a [[Query]] object. - * @deprecated since 2.0.14. Use `buildCondition()` instead. - */ - public function buildExistsCondition($operator, $operands, &$params) - { - array_unshift($operands, $operator); - return $this->buildCondition($operands, $params); - } - - /** - * Creates an SQL expressions like `"column" operator value`. - * @param string $operator the operator to use. Anything could be used e.g. `>`, `<=`, etc. - * @param array $operands contains two column names. - * @param array $params the binding parameters to be populated - * @return string the generated SQL expression - * @throws InvalidArgumentException if wrong number of operands have been given. - * @deprecated since 2.0.14. Use `buildCondition()` instead. - */ - public function buildSimpleCondition($operator, $operands, &$params) - { - array_unshift($operands, $operator); - return $this->buildCondition($operands, $params); - } - /** * Creates a SELECT EXISTS() SQL statement. * @param string $rawSql the subquery in a raw form to select from. diff --git a/db/mssql/QueryBuilder.php b/db/mssql/QueryBuilder.php index 1225c466c..ee85e6ed3 100644 --- a/db/mssql/QueryBuilder.php +++ b/db/mssql/QueryBuilder.php @@ -428,17 +428,6 @@ protected function getAllColumnNames($modelClass = null) return array_keys($schema->columns); } - /** - * @return bool whether the version of the MSSQL being used is older than 2012. - * @throws \yii\base\InvalidConfigException - * @throws \yii\db\Exception - * @deprecated 2.0.14 Use [[Schema::getServerVersion]] with [[\version_compare()]]. - */ - protected function isOldMssql() - { - return version_compare($this->db->getSchema()->getServerVersion(), '11', '<'); - } - /** * {@inheritdoc} * @since 2.0.8 From ee2ab7d5b67d56b8cbd5d09d6950494be00076c3 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Fri, 22 Sep 2023 10:05:46 -0300 Subject: [PATCH 15/31] Remove deprecated methods to `ColumnSchema::class`. --- db/mysql/ColumnSchema.php | 15 ++------------ db/pgsql/ColumnSchema.php | 42 ++++----------------------------------- 2 files changed, 6 insertions(+), 51 deletions(-) diff --git a/db/mysql/ColumnSchema.php b/db/mysql/ColumnSchema.php index ca9c48703..074335688 100644 --- a/db/mysql/ColumnSchema.php +++ b/db/mysql/ColumnSchema.php @@ -18,17 +18,6 @@ */ class ColumnSchema extends \yii\db\ColumnSchema { - /** - * @var bool whether the column schema should OMIT using JSON support feature. - * You can use this property to make upgrade to Yii 2.0.14 easier. - * Default to `false`, meaning JSON support is enabled. - * - * @since 2.0.14.1 - * @deprecated Since 2.0.14.1 and will be removed in 2.1. - */ - public $disableJsonSupport = false; - - /** * {@inheritdoc} */ @@ -42,7 +31,7 @@ public function dbTypecast($value) return $value; } - if (!$this->disableJsonSupport && $this->dbType === Schema::TYPE_JSON) { + if ($this->dbType === Schema::TYPE_JSON) { return new JsonExpression($value, $this->type); } @@ -58,7 +47,7 @@ public function phpTypecast($value) return null; } - if (!$this->disableJsonSupport && $this->type === Schema::TYPE_JSON) { + if ($this->type === Schema::TYPE_JSON) { return json_decode($value, true); } diff --git a/db/pgsql/ColumnSchema.php b/db/pgsql/ColumnSchema.php index 33d97bbdf..271c5f30c 100644 --- a/db/pgsql/ColumnSchema.php +++ b/db/pgsql/ColumnSchema.php @@ -22,33 +22,6 @@ class ColumnSchema extends \yii\db\ColumnSchema * @var int the dimension of array. Defaults to 0, means this column is not an array. */ public $dimension = 0; - /** - * @var bool whether the column schema should OMIT using JSON support feature. - * You can use this property to make upgrade to Yii 2.0.14 easier. - * Default to `false`, meaning JSON support is enabled. - * - * @since 2.0.14.1 - * @deprecated Since 2.0.14.1 and will be removed in 2.1. - */ - public $disableJsonSupport = false; - /** - * @var bool whether the column schema should OMIT using PgSQL Arrays support feature. - * You can use this property to make upgrade to Yii 2.0.14 easier. - * Default to `false`, meaning Arrays support is enabled. - * - * @since 2.0.14.1 - * @deprecated Since 2.0.14.1 and will be removed in 2.1. - */ - public $disableArraySupport = false; - /** - * @var bool whether the Array column value should be unserialized to an [[ArrayExpression]] object. - * You can use this property to make upgrade to Yii 2.0.14 easier. - * Default to `true`, meaning arrays are unserialized to [[ArrayExpression]] objects. - * - * @since 2.0.14.1 - * @deprecated Since 2.0.14.1 and will be removed in 2.1. - */ - public $deserializeArrayColumnToArrayExpression = true; /** * @var string name of associated sequence if column is auto-incremental * @since 2.0.29 @@ -70,11 +43,9 @@ public function dbTypecast($value) } if ($this->dimension > 0) { - return $this->disableArraySupport - ? (string) $value - : new ArrayExpression($value, $this->dbType, $this->dimension); + return new ArrayExpression($value, $this->dbType, $this->dimension); } - if (!$this->disableJsonSupport && in_array($this->dbType, [Schema::TYPE_JSON, Schema::TYPE_JSONB], true)) { + if (in_array($this->dbType, [Schema::TYPE_JSON, Schema::TYPE_JSONB], true)) { return new JsonExpression($value, $this->dbType); } @@ -87,9 +58,6 @@ public function dbTypecast($value) public function phpTypecast($value) { if ($this->dimension > 0) { - if ($this->disableArraySupport) { - return $value; - } if (!is_array($value)) { $value = $this->getArrayParser()->parse($value); } @@ -101,9 +69,7 @@ public function phpTypecast($value) return null; } - return $this->deserializeArrayColumnToArrayExpression - ? new ArrayExpression($value, $this->dbType, $this->dimension) - : $value; + return $value; } return $this->phpTypecastValue($value); @@ -133,7 +99,7 @@ protected function phpTypecastValue($value) } return (bool) $value; case Schema::TYPE_JSON: - return $this->disableJsonSupport ? $value : json_decode($value, true); + return json_decode($value, true); } return parent::phpTypecast($value); From aaf051f167fa5068f8a8ad0355f8c38120a48cee Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Fri, 22 Sep 2023 11:13:24 -0300 Subject: [PATCH 16/31] Remove deprecated methods to `DbMessageSource::class`. --- i18n/DbMessageSource.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/i18n/DbMessageSource.php b/i18n/DbMessageSource.php index eccc7fbd1..68f183f04 100644 --- a/i18n/DbMessageSource.php +++ b/i18n/DbMessageSource.php @@ -39,12 +39,6 @@ */ class DbMessageSource extends MessageSource { - /** - * Prefix which would be used when generating cache key. - * @deprecated This constant has never been used and will be removed in 2.1.0. - */ - const CACHE_KEY_PREFIX = 'DbMessageSource'; - /** * @var Connection|array|string the DB connection object or the application component ID of the DB connection. * From 837e04aab86aa57d8193fd1e6f62e3af7043371f Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Fri, 22 Sep 2023 18:19:59 -0300 Subject: [PATCH 17/31] Remove deprecated property to `FileTarget::class`. --- log/FileTarget.php | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/log/FileTarget.php b/log/FileTarget.php index d816f73a8..29e76d470 100644 --- a/log/FileTarget.php +++ b/log/FileTarget.php @@ -20,9 +20,6 @@ * files are moved backwards by one place, i.e., '.2' to '.3', '.1' to '.2', and so on. * The property [[maxLogFiles]] specifies how many history files to keep. * - * Since 2.0.46 rotation of the files is done only by copy and the - * `rotateByCopy` property is deprecated. - * * @author Qiang Xue * @since 2.0 */ @@ -61,22 +58,6 @@ class FileTarget extends Target * but read-only for other users. */ public $dirMode = 0775; - /** - * @var bool Whether to rotate log files by copy and truncate in contrast to rotation by - * renaming files. Defaults to `true` to be more compatible with log tailers and windows - * systems which do not play well with rename on open files. Rotation by renaming however is - * a bit faster. - * - * The problem with windows systems where the [rename()](https://www.php.net/manual/en/function.rename.php) - * function does not work with files that are opened by some process is described in a - * [comment by Martin Pelletier](https://www.php.net/manual/en/function.rename.php#102274) in - * the PHP documentation. By setting rotateByCopy to `true` you can work - * around this. - * @deprecated since 2.0.46 and setting it to false has no effect anymore - * since rotating is now always done by copy. - */ - public $rotateByCopy = true; - /** * Initializes the route. From a1009a6fea88d503102cd688e54b193b1bdd6d35 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Fri, 22 Sep 2023 18:42:02 -0300 Subject: [PATCH 18/31] Remove deprecated constants `CSRF_MASK_LENGTH`. --- web/Request.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/web/Request.php b/web/Request.php index d87489ce3..a4e86e4e4 100644 --- a/web/Request.php +++ b/web/Request.php @@ -94,11 +94,6 @@ class Request extends \yii\base\Request * The name of the HTTP header for sending CSRF token. */ const CSRF_HEADER = 'X-CSRF-Token'; - /** - * The length of the CSRF token mask. - * @deprecated since 2.0.12. The mask length is now equal to the token length. - */ - const CSRF_MASK_LENGTH = 8; /** * @var bool whether to enable CSRF (Cross-Site Request Forgery) validation. Defaults to true. From 994447d0f66c17ada5a448a6ec88298187e06f4a Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Fri, 22 Sep 2023 18:48:30 -0300 Subject: [PATCH 19/31] Remove deprecated methods to `User::class`. --- web/User.php | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/web/User.php b/web/User.php index 086b3c5dc..5f80fc8bc 100644 --- a/web/User.php +++ b/web/User.php @@ -788,20 +788,6 @@ public function checkRedirectAcceptable() return false; } - /** - * Returns auth manager associated with the user component. - * - * By default this is the `authManager` application component. - * You may override this method to return a different auth manager instance if needed. - * @return \yii\rbac\ManagerInterface - * @since 2.0.6 - * @deprecated since version 2.0.9, to be removed in 2.1. Use [[getAccessChecker()]] instead. - */ - protected function getAuthManager() - { - return Yii::$app->getAuthManager(); - } - /** * Returns the access checker used for checking access. * @return CheckAccessInterface @@ -809,6 +795,6 @@ protected function getAuthManager() */ protected function getAccessChecker() { - return $this->accessChecker !== null ? $this->accessChecker : $this->getAuthManager(); + return $this->accessChecker !== null ? $this->accessChecker : Yii::$app->getAuthManager(); } } From 1905446093c2f5b9d7781752cbe853aae9c901ec Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Fri, 22 Sep 2023 18:59:21 -0300 Subject: [PATCH 20/31] Add method `className()`, don't break BC third party extensions. --- base/BaseObject.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/base/BaseObject.php b/base/BaseObject.php index 2f9448efc..84e887304 100644 --- a/base/BaseObject.php +++ b/base/BaseObject.php @@ -282,4 +282,14 @@ public function hasMethod($name) { return method_exists($this, $name); } + + /** + * Returns the fully qualified name of this class. + * + * @return string the fully qualified name of this class. + */ + public static function className(): string + { + return static::class; + } } From 50f12e2a6c09f9b3dfede1d84ba05477885e8f27 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Thu, 19 Oct 2023 12:17:15 -0300 Subject: [PATCH 21/31] Sync to master. (#20012) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * added pcntl to requirements check * Fix #13920: Fixed erroneous validation for specific cases * Fix #13920: Added my name to CHANGELOG.md * trim(): Passing null to parameter #1 ($string) of type string is deprecated * Added section about Unsafe Reflection in Security best practices doc (#19948) Co-authored-by: Bizley * Update CHANGELOG.md * Fixed tests. * Fix #13920: Add unit test * Update `bower-asset/inputmask`, `bower-asset/punycode`. * added CHANGELOG line * Fix order. * fix: #19978 - Mistake in Korean translation * fix: keep doublequote * Do not duplicate log messages in memory * Update framework/log/FileTarget.php Co-authored-by: Bizley * Update concept-di-container.md Сслка "Конфигурация приложения" была не верной, она вела на страницу "Service-locator'a" * Update CHANGELOG.md * release version 2.0.49.1 * prepare for next release * Revert changes in `mimeTypes.php` from 4a1f2c6b9bc90427e91da73f5e8c8fa33d3c53c1 restores https://github.com/yiisoft/yii2/pull/19936 * update actions/checkout to v4 * Fix mime type generator * Added note * Update structure-controllers.md (#20003) добавил пропущенное слово "как" * Update CHANGELOG.md 2.0.49.2 changelog * release version 2.0.49.2 * prepare for next release * New methods: BaseActiveRecord::loadRelations() and BaseActiveRecord::loadRelationsFor(). * Fixed a bug where the yii serve command would break if a custom router was supplied and it had a space in the path * Fix `MaskedInputAsset::class`. * Fix #19927: Fixed `console\controllers\MessageController` when saving translations to database: fixed FK error when adding new string and language at the same time, checking/regenerating all missing messages and dropping messages for unused languages * Added 'zh' into 'framework/messages/config.php' (#19995) --------- Co-authored-by: Tobias Munk Co-authored-by: Tim Fischer Co-authored-by: Tim Fischer <35448254+tim-fischer-maschinensucher@users.noreply.github.com> Co-authored-by: Alexander Makarov Co-authored-by: Oleg Poludnenko Co-authored-by: Bizley Co-authored-by: Sonia Zorba Co-authored-by: Tobias Munk Co-authored-by: Akbar Herlambang Co-authored-by: lubosdz Co-authored-by: Yuriy Bachevskiy Co-authored-by: Robert Korulczyk Co-authored-by: salehhashemi1992 <81674631+salehhashemi1992@users.noreply.github.com> Co-authored-by: PowerGamer1 Co-authored-by: Brad Bell Co-authored-by: Alexandru Trandafir Catalin Co-authored-by: Nabi KaramAliZadeh --- CHANGELOG.md | 16 +++ assets/yii.activeForm.js | 8 ++ composer.json | 4 +- console/controllers/MessageController.php | 161 +++++++++++++--------- console/controllers/ServeController.php | 2 +- db/BaseActiveRecord.php | 53 +++++++ db/Query.php | 4 +- helpers/mimeAliases.php | 3 + helpers/mimeExtensions.php | 3 + helpers/mimeTypes.php | 3 + log/FileTarget.php | 3 +- messages/config.php | 3 +- messages/ko/yii.php | 4 +- requirements/requirements.php | 7 + widgets/MaskedInputAsset.php | 2 +- 15 files changed, 199 insertions(+), 77 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91ff0a353..8306ab213 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,9 +11,25 @@ Yii Framework 2 Change Log 2.0.50 under development ------------------------ +- Bug #13920: Fixed erroneous validation for specific cases (tim-fischer-maschinensucher) +- Bug #19927: Fixed `console\controllers\MessageController` when saving translations to database: fixed FK error when adding new string and language at the same time, checking/regenerating all missing messages and dropping messages for unused languages (atrandafir) +- Enh #12743: Added new methods `BaseActiveRecord::loadRelations()` and `BaseActiveRecord::loadRelationsFor()` to eager load related models for existing primary model instances (PowerGamer1) + + +2.0.49.2 October 12, 2023 +------------------------- + - Bug #19925: Improved PHP version check when handling MIME types (schmunk42) + + +2.0.49.1 October 05, 2023 +------------------------- + - Bug #19940: File Log writer without newline (terabytesoftw) +- Bug #19950: Fix `Query::groupBy(null)` causes error for PHP 8.1: `trim(): Passing null to parameter #1 ($string) of type string is deprecated` (uaoleg) - Bug #19951: Removed unneeded MIME file tests (schmunk42) +- Bug #19984: Do not duplicate log messages in memory (lubosdz) +- Enh #19780: added pcntl to requirements check (schmunk42) 2.0.49 August 29, 2023 diff --git a/assets/yii.activeForm.js b/assets/yii.activeForm.js index b12f812c3..5b9ce4aae 100644 --- a/assets/yii.activeForm.js +++ b/assets/yii.activeForm.js @@ -395,9 +395,11 @@ data: $form.serialize() + extData, dataType: data.settings.ajaxDataType, complete: function (jqXHR, textStatus) { + currentAjaxRequest = null; $form.trigger(events.ajaxComplete, [jqXHR, textStatus]); }, beforeSend: function (jqXHR, settings) { + currentAjaxRequest = jqXHR; $form.trigger(events.ajaxBeforeSend, [jqXHR, settings]); }, success: function (msgs) { @@ -563,6 +565,9 @@ return; } + if (currentAjaxRequest !== null) { + currentAjaxRequest.abort(); + } if (data.settings.timer !== undefined) { clearTimeout(data.settings.timer); } @@ -929,4 +934,7 @@ $form.find(attribute.input).attr('aria-invalid', hasError ? 'true' : 'false'); } } + + var currentAjaxRequest = null; + })(window.jQuery); diff --git a/composer.json b/composer.json index 8d638df3c..0b27d62ff 100644 --- a/composer.json +++ b/composer.json @@ -71,8 +71,8 @@ "ezyang/htmlpurifier": "^4.6", "cebe/markdown": "~1.0.0 | ~1.1.0 | ~1.2.0", "bower-asset/jquery": "3.7.*@stable | 3.6.*@stable | 3.5.*@stable | 3.4.*@stable | 3.3.*@stable | 3.2.*@stable | 3.1.*@stable | 2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable", - "bower-asset/inputmask": "~3.2.2 | ~3.3.5", - "bower-asset/punycode": "1.3.*", + "bower-asset/inputmask": "^5.0.8 ", + "bower-asset/punycode": "^2.2", "bower-asset/yii2-pjax": "~2.0.1", "paragonie/random_compat": ">=1" }, diff --git a/console/controllers/MessageController.php b/console/controllers/MessageController.php index 4650cec79..fb4e012f5 100644 --- a/console/controllers/MessageController.php +++ b/console/controllers/MessageController.php @@ -353,17 +353,7 @@ protected function saveMessagesToDb($messages, $db, $sourceMessageTable, $messag foreach ($rows as $row) { $currentMessages[$row['category']][$row['id']] = $row['message']; } - - $currentLanguages = []; - $rows = (new Query())->select(['language'])->from($messageTable)->groupBy('language')->all($db); - foreach ($rows as $row) { - $currentLanguages[] = $row['language']; - } - $missingLanguages = []; - if (!empty($currentLanguages)) { - $missingLanguages = array_diff($languages, $currentLanguages); - } - + $new = []; $obsolete = []; @@ -372,89 +362,130 @@ protected function saveMessagesToDb($messages, $db, $sourceMessageTable, $messag if (isset($currentMessages[$category])) { $new[$category] = array_diff($msgs, $currentMessages[$category]); + // obsolete messages per category $obsolete += array_diff($currentMessages[$category], $msgs); } else { $new[$category] = $msgs; } } - + + // obsolete categories foreach (array_diff(array_keys($currentMessages), array_keys($messages)) as $category) { $obsolete += $currentMessages[$category]; } if (!$removeUnused) { foreach ($obsolete as $pk => $msg) { + // skip already marked unused if (strncmp($msg, '@@', 2) === 0 && substr($msg, -2) === '@@') { unset($obsolete[$pk]); } } - } - - $obsolete = array_keys($obsolete); + } + $this->stdout('Inserting new messages...'); - $savedFlag = false; + $insertCount = 0; foreach ($new as $category => $msgs) { foreach ($msgs as $msg) { - $savedFlag = true; - $lastPk = $db->schema->insert($sourceMessageTable, ['category' => $category, 'message' => $msg]); - foreach ($languages as $language) { - $db->createCommand() - ->insert($messageTable, ['id' => $lastPk['id'], 'language' => $language]) - ->execute(); - } - } - } - - if (!empty($missingLanguages)) { - $updatedMessages = []; - $rows = (new Query())->select(['id', 'category', 'message'])->from($sourceMessageTable)->all($db); - foreach ($rows as $row) { - $updatedMessages[$row['category']][$row['id']] = $row['message']; - } - foreach ($updatedMessages as $category => $msgs) { - foreach ($msgs as $id => $msg) { - $savedFlag = true; - foreach ($missingLanguages as $language) { - $db->createCommand() - ->insert($messageTable, ['id' => $id, 'language' => $language]) - ->execute(); - } - } + $insertCount++; + $db->schema->insert($sourceMessageTable, ['category' => $category, 'message' => $msg]); } } - - $this->stdout($savedFlag ? "saved.\n" : "Nothing to save.\n"); + + $this->stdout($insertCount ? "{$insertCount} saved.\n" : "Nothing to save.\n"); + $this->stdout($removeUnused ? 'Deleting obsoleted messages...' : 'Updating obsoleted messages...'); if (empty($obsolete)) { $this->stdout("Nothing obsoleted...skipped.\n"); - return; } - if ($removeUnused) { - $db->createCommand() - ->delete($sourceMessageTable, ['in', 'id', $obsolete]) - ->execute(); - $this->stdout("deleted.\n"); - } elseif ($markUnused) { - $rows = (new Query()) - ->select(['id', 'message']) - ->from($sourceMessageTable) - ->where(['in', 'id', $obsolete]) - ->all($db); - - foreach ($rows as $row) { - $db->createCommand()->update( - $sourceMessageTable, - ['message' => '@@' . $row['message'] . '@@'], - ['id' => $row['id']] - )->execute(); + if ($obsolete) { + if ($removeUnused) { + $affected = $db->createCommand() + ->delete($sourceMessageTable, ['in', 'id', array_keys($obsolete)]) + ->execute(); + $this->stdout("{$affected} deleted.\n"); + } elseif ($markUnused) { + $marked=0; + $rows = (new Query()) + ->select(['id', 'message']) + ->from($sourceMessageTable) + ->where(['in', 'id', array_keys($obsolete)]) + ->all($db); + + foreach ($rows as $row) { + $marked++; + $db->createCommand()->update( + $sourceMessageTable, + ['message' => '@@' . $row['message'] . '@@'], + ['id' => $row['id']] + )->execute(); + } + $this->stdout("{$marked} updated.\n"); + } else { + $this->stdout("kept untouched.\n"); } - $this->stdout("updated.\n"); - } else { - $this->stdout("kept untouched.\n"); } + + // get fresh message id list + $freshMessagesIds = []; + $rows = (new Query())->select(['id'])->from($sourceMessageTable)->all($db); + foreach ($rows as $row) { + $freshMessagesIds[] = $row['id']; + } + + $this->stdout("Generating missing rows..."); + $generatedMissingRows = []; + + foreach ($languages as $language) { + $count = 0; + + // get list of ids of translations for this language + $msgRowsIds = []; + $msgRows = (new Query())->select(['id'])->from($messageTable)->where([ + 'language'=>$language, + ])->all($db); + foreach ($msgRows as $row) { + $msgRowsIds[] = $row['id']; + } + + // insert missing + foreach ($freshMessagesIds as $id) { + if (!in_array($id, $msgRowsIds)) { + $db->createCommand() + ->insert($messageTable, ['id' => $id, 'language' => $language]) + ->execute(); + $count++; + } + } + if ($count) { + $generatedMissingRows[] = "{$count} for {$language}"; + } + } + + $this->stdout($generatedMissingRows ? implode(", ", $generatedMissingRows).".\n" : "Nothing to do.\n"); + + $this->stdout("Dropping unused languages..."); + $droppedLanguages=[]; + + $currentLanguages = []; + $rows = (new Query())->select(['language'])->from($messageTable)->groupBy('language')->all($db); + foreach ($rows as $row) { + $currentLanguages[] = $row['language']; + } + + foreach ($currentLanguages as $currentLanguage) { + if (!in_array($currentLanguage, $languages)) { + $deleted=$db->createCommand()->delete($messageTable, "language=:language", [ + 'language'=>$currentLanguage, + ])->execute(); + $droppedLanguages[] = "removed {$deleted} rows for $currentLanguage"; + } + } + + $this->stdout($droppedLanguages ? implode(", ", $droppedLanguages).".\n" : "Nothing to do.\n"); } /** diff --git a/console/controllers/ServeController.php b/console/controllers/ServeController.php index 68a7e50c2..d02c98204 100644 --- a/console/controllers/ServeController.php +++ b/console/controllers/ServeController.php @@ -80,7 +80,7 @@ public function actionIndex($address = 'localhost') } $this->stdout("Quit the server with CTRL-C or COMMAND-C.\n"); - passthru('"' . PHP_BINARY . '"' . " -S {$address} -t \"{$documentRoot}\" $router"); + passthru('"' . PHP_BINARY . '"' . " -S {$address} -t \"{$documentRoot}\" \"$router\""); } /** diff --git a/db/BaseActiveRecord.php b/db/BaseActiveRecord.php index e1bb4cc2d..7baa338ce 100644 --- a/db/BaseActiveRecord.php +++ b/db/BaseActiveRecord.php @@ -1786,4 +1786,57 @@ private function isValueDifferent($newValue, $oldValue) return $newValue !== $oldValue; } + + /** + * Eager loads related models for the already loaded primary models. + * + * Helps to reduce the number of queries performed against database if some related models are only used + * when a specific condition is met. For example: + * + * ```php + * $customers = Customer::find()->where(['country_id' => 123])->all(); + * if (Yii:app()->getUser()->getIdentity()->canAccessOrders()) { + * Customer::loadRelationsFor($customers, 'orders.items'); + * } + * ``` + * + * @param array|ActiveRecordInterface[] $models array of primary models. Each model should have the same type and can be: + * - an active record instance; + * - active record instance represented by array (i.e. active record was loaded using [[ActiveQuery::asArray()]]). + * @param string|array $relationNames the names of the relations of primary models to be loaded from database. See [[ActiveQueryInterface::with()]] on how to specify this argument. + * @param bool $asArray whether to load each related model as an array or an object (if the relation itself does not specify that). + * @since 2.0.49 + */ + public static function loadRelationsFor(&$models, $relationNames, $asArray = false) + { + // ActiveQueryTrait::findWith() called below assumes $models array is non-empty. + if (empty($models)) { + return; + } + + static::find()->asArray($asArray)->findWith((array)$relationNames, $models); + } + + /** + * Eager loads related models for the already loaded primary model. + * + * Helps to reduce the number of queries performed against database if some related models are only used + * when a specific condition is met. For example: + * + * ```php + * $customer = Customer::find()->where(['id' => 123])->one(); + * if (Yii:app()->getUser()->getIdentity()->canAccessOrders()) { + * $customer->loadRelations('orders.items'); + * } + * ``` + * + * @param string|array $relationNames the names of the relations of this model to be loaded from database. See [[ActiveQueryInterface::with()]] on how to specify this argument. + * @param bool $asArray whether to load each relation as an array or an object (if the relation itself does not specify that). + * @since 2.0.49 + */ + public function loadRelations($relationNames, $asArray = false) + { + $models = [$this]; + static::loadRelationsFor($models, $relationNames, $asArray); + } } diff --git a/db/Query.php b/db/Query.php index 9374f9d84..f44a1c447 100644 --- a/db/Query.php +++ b/db/Query.php @@ -996,7 +996,7 @@ public function rightJoin($table, $on = '', $params = []) /** * Sets the GROUP BY part of the query. - * @param string|array|ExpressionInterface $columns the columns to be grouped by. + * @param string|array|ExpressionInterface|null $columns the columns to be grouped by. * Columns can be specified in either a string (e.g. "id, name") or an array (e.g. ['id', 'name']). * The method will automatically quote the column names unless a column contains some parenthesis * (which means the column contains a DB expression). @@ -1014,7 +1014,7 @@ public function groupBy($columns) { if ($columns instanceof ExpressionInterface) { $columns = [$columns]; - } elseif (!is_array($columns)) { + } elseif (!is_array($columns) && !is_null($columns)) { $columns = preg_split('/\s*,\s*/', trim($columns), -1, PREG_SPLIT_NO_EMPTY); } $this->groupBy = $columns; diff --git a/helpers/mimeAliases.php b/helpers/mimeAliases.php index 4cd89888a..a9e677adc 100644 --- a/helpers/mimeAliases.php +++ b/helpers/mimeAliases.php @@ -3,6 +3,9 @@ * MIME aliases. * * This file contains aliases for MIME types. + * + * All extra changes made to this file must be comitted to /build/controllers/MimeTypeController.php + * otherwise they will be lost on next build. */ return [ 'text/rtf' => 'application/rtf', diff --git a/helpers/mimeExtensions.php b/helpers/mimeExtensions.php index 946d61cd0..e4936030f 100644 --- a/helpers/mimeExtensions.php +++ b/helpers/mimeExtensions.php @@ -8,6 +8,9 @@ * Its content is generated from the apache http mime.types file. * https://svn.apache.org/viewvc/httpd/httpd/trunk/docs/conf/mime.types?view=markup * This file has been placed in the public domain for unlimited redistribution. + * + * All extra changes made to this file must be comitted to /build/controllers/MimeTypeController.php + * otherwise they will be lost on next build. */ return [ 'application/andrew-inset' => 'ez', diff --git a/helpers/mimeTypes.php b/helpers/mimeTypes.php index e91f80f95..f895e8d07 100644 --- a/helpers/mimeTypes.php +++ b/helpers/mimeTypes.php @@ -7,6 +7,9 @@ * Its content is generated from the apache http mime.types file. * https://svn.apache.org/viewvc/httpd/httpd/trunk/docs/conf/mime.types?view=markup * This file has been placed in the public domain for unlimited redistribution. + * + * All extra changes made to this file must be comitted to /build/controllers/MimeTypeController.php + * otherwise they will be lost on next build. */ $mimeTypes = [ 123 => 'application/vnd.lotus-1-2-3', diff --git a/log/FileTarget.php b/log/FileTarget.php index 29e76d470..3e13278a3 100644 --- a/log/FileTarget.php +++ b/log/FileTarget.php @@ -88,9 +88,8 @@ public function init() public function export() { $text = implode("\n", array_map([$this, 'formatMessage'], $this->messages)) . "\n"; - $trimmedText = trim($text); - if (empty($trimmedText)) { + if (trim($text) === '') { return; // No messages to export, so we exit the function early } diff --git a/messages/config.php b/messages/config.php index 93845f2e0..6028328f3 100644 --- a/messages/config.php +++ b/messages/config.php @@ -15,8 +15,7 @@ 'languages' => [ 'af', 'ar', 'az', 'be', 'bg', 'bs', 'ca', 'cs', 'da', 'de', 'el', 'es', 'et', 'fa', 'fi', 'fr', 'he', 'hi', 'pt-BR', 'ro', 'hr', 'hu', 'hy', 'id', 'it', 'ja', 'ka', 'kk', 'ko', 'kz', 'lt', 'lv', 'ms', 'nb-NO', 'nl', - 'pl', 'pt', 'ru', 'sk', 'sl', 'sr', 'sr-Latn', 'sv', 'tg', 'th', 'tr', 'uk', 'uz', 'uz-Cy', 'vi', 'zh-CN', - 'zh-TW' + 'pl', 'pt', 'ru', 'sk', 'sl', 'sr', 'sr-Latn', 'sv', 'tg', 'th', 'tr', 'uk', 'uz', 'uz-Cy', 'vi', 'zh', 'zh-TW' ], // string, the name of the function for translating messages. // Defaults to 'Yii::t'. This is used as a mark to find the messages to be diff --git a/messages/ko/yii.php b/messages/ko/yii.php index 4fe82311f..b0ad872fe 100644 --- a/messages/ko/yii.php +++ b/messages/ko/yii.php @@ -75,8 +75,8 @@ '{attribute} must be greater than or equal to "{compareValue}".' => '{attribute}는 "{compareValue}" 보다 크거나 같아야 합니다.', '{attribute} must be less than "{compareValue}".' => '{attribute}는 "{compareValue}" 보다 작아야 합니다.', '{attribute} must be less than or equal to "{compareValue}".' => '{attribute}는 "{compareValue}" 보다 작거나 같아야 합니다.', - '{attribute} must be no greater than {max}.' => '{attribute}는 "{compareValue}" 보다 클 수 없습니다.', - '{attribute} must be no less than {min}.' => '{attribute}는 "{compareValue}" 보다 작을 수 없습니다.', + '{attribute} must be no greater than {max}.' => '{attribute}는 "{max}" 보다 클 수 없습니다.', + '{attribute} must be no less than {min}.' => '{attribute}는 "{min}" 보다 작을 수 없습니다.', '{attribute} must be repeated exactly.' => '{attribute}는 정확하게 반복합니다.', '{attribute} must not be equal to "{compareValue}".' => '{attribute}는 "{compareValue}"와 같을 수 없습니다.', '{attribute} should contain at least {min, number} {min, plural, one{character} other{characters}}.' => '{attribute}는 최소 {min}자 이어야합니다.', diff --git a/requirements/requirements.php b/requirements/requirements.php index 555930615..d065f6363 100644 --- a/requirements/requirements.php +++ b/requirements/requirements.php @@ -111,5 +111,12 @@ 'memo' => 'When IpValidator::expandIPv6 property is set to true, PHP must support IPv6 protocol stack. Currently PHP constant AF_INET6 is not defined and IPv6 is probably unsupported.' + ), + array( + 'name' => 'pcntl', + 'mandatory' => false, + 'condition' => extension_loaded('pcntl'), + 'by' => 'Process Control', + 'memo' => 'Recommended for yii2-queue CLI operations' ) ); diff --git a/widgets/MaskedInputAsset.php b/widgets/MaskedInputAsset.php index 57748be86..473f4315f 100644 --- a/widgets/MaskedInputAsset.php +++ b/widgets/MaskedInputAsset.php @@ -21,7 +21,7 @@ class MaskedInputAsset extends AssetBundle { public $sourcePath = '@bower/inputmask/dist'; public $js = [ - 'jquery.inputmask.bundle.js', + 'jquery.inputmask.js', ]; public $depends = [ 'yii\web\YiiAsset', From 9a4561aceb7710beb0bb817a862624a385d3d276 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Thu, 19 Oct 2023 14:21:07 -0300 Subject: [PATCH 22/31] Remove unsed package, fix error typo. (#20017) --- composer.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 0b27d62ff..4934013b6 100644 --- a/composer.json +++ b/composer.json @@ -73,8 +73,7 @@ "bower-asset/jquery": "3.7.*@stable | 3.6.*@stable | 3.5.*@stable | 3.4.*@stable | 3.3.*@stable | 3.2.*@stable | 3.1.*@stable | 2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable", "bower-asset/inputmask": "^5.0.8 ", "bower-asset/punycode": "^2.2", - "bower-asset/yii2-pjax": "~2.0.1", - "paragonie/random_compat": ">=1" + "bower-asset/yii2-pjax": "~2.0.1" }, "autoload": { "psr-4": {"yii\\": ""} From a2b9f2ad2f750aa44f8339a6c9f9322dc5dfb527 Mon Sep 17 00:00:00 2001 From: Bizley Date: Sun, 22 Oct 2023 11:39:45 +0200 Subject: [PATCH 23/31] Revert to 169c5fb --- CHANGELOG.md | 16 --- assets/yii.activeForm.js | 8 -- composer.json | 7 +- console/controllers/MessageController.php | 161 +++++++++------------- console/controllers/ServeController.php | 2 +- db/BaseActiveRecord.php | 53 ------- db/Query.php | 4 +- helpers/mimeAliases.php | 3 - helpers/mimeExtensions.php | 3 - helpers/mimeTypes.php | 3 - log/FileTarget.php | 3 +- messages/config.php | 3 +- messages/ko/yii.php | 4 +- requirements/requirements.php | 7 - widgets/MaskedInputAsset.php | 2 +- 15 files changed, 79 insertions(+), 200 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8306ab213..91ff0a353 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,25 +11,9 @@ Yii Framework 2 Change Log 2.0.50 under development ------------------------ -- Bug #13920: Fixed erroneous validation for specific cases (tim-fischer-maschinensucher) -- Bug #19927: Fixed `console\controllers\MessageController` when saving translations to database: fixed FK error when adding new string and language at the same time, checking/regenerating all missing messages and dropping messages for unused languages (atrandafir) -- Enh #12743: Added new methods `BaseActiveRecord::loadRelations()` and `BaseActiveRecord::loadRelationsFor()` to eager load related models for existing primary model instances (PowerGamer1) - - -2.0.49.2 October 12, 2023 -------------------------- - - Bug #19925: Improved PHP version check when handling MIME types (schmunk42) - - -2.0.49.1 October 05, 2023 -------------------------- - - Bug #19940: File Log writer without newline (terabytesoftw) -- Bug #19950: Fix `Query::groupBy(null)` causes error for PHP 8.1: `trim(): Passing null to parameter #1 ($string) of type string is deprecated` (uaoleg) - Bug #19951: Removed unneeded MIME file tests (schmunk42) -- Bug #19984: Do not duplicate log messages in memory (lubosdz) -- Enh #19780: added pcntl to requirements check (schmunk42) 2.0.49 August 29, 2023 diff --git a/assets/yii.activeForm.js b/assets/yii.activeForm.js index 5b9ce4aae..b12f812c3 100644 --- a/assets/yii.activeForm.js +++ b/assets/yii.activeForm.js @@ -395,11 +395,9 @@ data: $form.serialize() + extData, dataType: data.settings.ajaxDataType, complete: function (jqXHR, textStatus) { - currentAjaxRequest = null; $form.trigger(events.ajaxComplete, [jqXHR, textStatus]); }, beforeSend: function (jqXHR, settings) { - currentAjaxRequest = jqXHR; $form.trigger(events.ajaxBeforeSend, [jqXHR, settings]); }, success: function (msgs) { @@ -565,9 +563,6 @@ return; } - if (currentAjaxRequest !== null) { - currentAjaxRequest.abort(); - } if (data.settings.timer !== undefined) { clearTimeout(data.settings.timer); } @@ -934,7 +929,4 @@ $form.find(attribute.input).attr('aria-invalid', hasError ? 'true' : 'false'); } } - - var currentAjaxRequest = null; - })(window.jQuery); diff --git a/composer.json b/composer.json index 4934013b6..8d638df3c 100644 --- a/composer.json +++ b/composer.json @@ -71,9 +71,10 @@ "ezyang/htmlpurifier": "^4.6", "cebe/markdown": "~1.0.0 | ~1.1.0 | ~1.2.0", "bower-asset/jquery": "3.7.*@stable | 3.6.*@stable | 3.5.*@stable | 3.4.*@stable | 3.3.*@stable | 3.2.*@stable | 3.1.*@stable | 2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable", - "bower-asset/inputmask": "^5.0.8 ", - "bower-asset/punycode": "^2.2", - "bower-asset/yii2-pjax": "~2.0.1" + "bower-asset/inputmask": "~3.2.2 | ~3.3.5", + "bower-asset/punycode": "1.3.*", + "bower-asset/yii2-pjax": "~2.0.1", + "paragonie/random_compat": ">=1" }, "autoload": { "psr-4": {"yii\\": ""} diff --git a/console/controllers/MessageController.php b/console/controllers/MessageController.php index fb4e012f5..4650cec79 100644 --- a/console/controllers/MessageController.php +++ b/console/controllers/MessageController.php @@ -353,7 +353,17 @@ protected function saveMessagesToDb($messages, $db, $sourceMessageTable, $messag foreach ($rows as $row) { $currentMessages[$row['category']][$row['id']] = $row['message']; } - + + $currentLanguages = []; + $rows = (new Query())->select(['language'])->from($messageTable)->groupBy('language')->all($db); + foreach ($rows as $row) { + $currentLanguages[] = $row['language']; + } + $missingLanguages = []; + if (!empty($currentLanguages)) { + $missingLanguages = array_diff($languages, $currentLanguages); + } + $new = []; $obsolete = []; @@ -362,130 +372,89 @@ protected function saveMessagesToDb($messages, $db, $sourceMessageTable, $messag if (isset($currentMessages[$category])) { $new[$category] = array_diff($msgs, $currentMessages[$category]); - // obsolete messages per category $obsolete += array_diff($currentMessages[$category], $msgs); } else { $new[$category] = $msgs; } } - - // obsolete categories + foreach (array_diff(array_keys($currentMessages), array_keys($messages)) as $category) { $obsolete += $currentMessages[$category]; } if (!$removeUnused) { foreach ($obsolete as $pk => $msg) { - // skip already marked unused if (strncmp($msg, '@@', 2) === 0 && substr($msg, -2) === '@@') { unset($obsolete[$pk]); } } - } - + } + + $obsolete = array_keys($obsolete); $this->stdout('Inserting new messages...'); - $insertCount = 0; + $savedFlag = false; foreach ($new as $category => $msgs) { foreach ($msgs as $msg) { - $insertCount++; - $db->schema->insert($sourceMessageTable, ['category' => $category, 'message' => $msg]); + $savedFlag = true; + $lastPk = $db->schema->insert($sourceMessageTable, ['category' => $category, 'message' => $msg]); + foreach ($languages as $language) { + $db->createCommand() + ->insert($messageTable, ['id' => $lastPk['id'], 'language' => $language]) + ->execute(); + } + } + } + + if (!empty($missingLanguages)) { + $updatedMessages = []; + $rows = (new Query())->select(['id', 'category', 'message'])->from($sourceMessageTable)->all($db); + foreach ($rows as $row) { + $updatedMessages[$row['category']][$row['id']] = $row['message']; + } + foreach ($updatedMessages as $category => $msgs) { + foreach ($msgs as $id => $msg) { + $savedFlag = true; + foreach ($missingLanguages as $language) { + $db->createCommand() + ->insert($messageTable, ['id' => $id, 'language' => $language]) + ->execute(); + } + } } } - - $this->stdout($insertCount ? "{$insertCount} saved.\n" : "Nothing to save.\n"); - + + $this->stdout($savedFlag ? "saved.\n" : "Nothing to save.\n"); $this->stdout($removeUnused ? 'Deleting obsoleted messages...' : 'Updating obsoleted messages...'); if (empty($obsolete)) { $this->stdout("Nothing obsoleted...skipped.\n"); + return; } - if ($obsolete) { - if ($removeUnused) { - $affected = $db->createCommand() - ->delete($sourceMessageTable, ['in', 'id', array_keys($obsolete)]) - ->execute(); - $this->stdout("{$affected} deleted.\n"); - } elseif ($markUnused) { - $marked=0; - $rows = (new Query()) - ->select(['id', 'message']) - ->from($sourceMessageTable) - ->where(['in', 'id', array_keys($obsolete)]) - ->all($db); - - foreach ($rows as $row) { - $marked++; - $db->createCommand()->update( - $sourceMessageTable, - ['message' => '@@' . $row['message'] . '@@'], - ['id' => $row['id']] - )->execute(); - } - $this->stdout("{$marked} updated.\n"); - } else { - $this->stdout("kept untouched.\n"); - } - } - - // get fresh message id list - $freshMessagesIds = []; - $rows = (new Query())->select(['id'])->from($sourceMessageTable)->all($db); - foreach ($rows as $row) { - $freshMessagesIds[] = $row['id']; - } - - $this->stdout("Generating missing rows..."); - $generatedMissingRows = []; - - foreach ($languages as $language) { - $count = 0; - - // get list of ids of translations for this language - $msgRowsIds = []; - $msgRows = (new Query())->select(['id'])->from($messageTable)->where([ - 'language'=>$language, - ])->all($db); - foreach ($msgRows as $row) { - $msgRowsIds[] = $row['id']; - } - - // insert missing - foreach ($freshMessagesIds as $id) { - if (!in_array($id, $msgRowsIds)) { - $db->createCommand() - ->insert($messageTable, ['id' => $id, 'language' => $language]) - ->execute(); - $count++; + if ($removeUnused) { + $db->createCommand() + ->delete($sourceMessageTable, ['in', 'id', $obsolete]) + ->execute(); + $this->stdout("deleted.\n"); + } elseif ($markUnused) { + $rows = (new Query()) + ->select(['id', 'message']) + ->from($sourceMessageTable) + ->where(['in', 'id', $obsolete]) + ->all($db); + + foreach ($rows as $row) { + $db->createCommand()->update( + $sourceMessageTable, + ['message' => '@@' . $row['message'] . '@@'], + ['id' => $row['id']] + )->execute(); } - } - if ($count) { - $generatedMissingRows[] = "{$count} for {$language}"; - } - } - - $this->stdout($generatedMissingRows ? implode(", ", $generatedMissingRows).".\n" : "Nothing to do.\n"); - - $this->stdout("Dropping unused languages..."); - $droppedLanguages=[]; - - $currentLanguages = []; - $rows = (new Query())->select(['language'])->from($messageTable)->groupBy('language')->all($db); - foreach ($rows as $row) { - $currentLanguages[] = $row['language']; + $this->stdout("updated.\n"); + } else { + $this->stdout("kept untouched.\n"); } - - foreach ($currentLanguages as $currentLanguage) { - if (!in_array($currentLanguage, $languages)) { - $deleted=$db->createCommand()->delete($messageTable, "language=:language", [ - 'language'=>$currentLanguage, - ])->execute(); - $droppedLanguages[] = "removed {$deleted} rows for $currentLanguage"; - } - } - - $this->stdout($droppedLanguages ? implode(", ", $droppedLanguages).".\n" : "Nothing to do.\n"); } /** diff --git a/console/controllers/ServeController.php b/console/controllers/ServeController.php index d02c98204..68a7e50c2 100644 --- a/console/controllers/ServeController.php +++ b/console/controllers/ServeController.php @@ -80,7 +80,7 @@ public function actionIndex($address = 'localhost') } $this->stdout("Quit the server with CTRL-C or COMMAND-C.\n"); - passthru('"' . PHP_BINARY . '"' . " -S {$address} -t \"{$documentRoot}\" \"$router\""); + passthru('"' . PHP_BINARY . '"' . " -S {$address} -t \"{$documentRoot}\" $router"); } /** diff --git a/db/BaseActiveRecord.php b/db/BaseActiveRecord.php index 7baa338ce..e1bb4cc2d 100644 --- a/db/BaseActiveRecord.php +++ b/db/BaseActiveRecord.php @@ -1786,57 +1786,4 @@ private function isValueDifferent($newValue, $oldValue) return $newValue !== $oldValue; } - - /** - * Eager loads related models for the already loaded primary models. - * - * Helps to reduce the number of queries performed against database if some related models are only used - * when a specific condition is met. For example: - * - * ```php - * $customers = Customer::find()->where(['country_id' => 123])->all(); - * if (Yii:app()->getUser()->getIdentity()->canAccessOrders()) { - * Customer::loadRelationsFor($customers, 'orders.items'); - * } - * ``` - * - * @param array|ActiveRecordInterface[] $models array of primary models. Each model should have the same type and can be: - * - an active record instance; - * - active record instance represented by array (i.e. active record was loaded using [[ActiveQuery::asArray()]]). - * @param string|array $relationNames the names of the relations of primary models to be loaded from database. See [[ActiveQueryInterface::with()]] on how to specify this argument. - * @param bool $asArray whether to load each related model as an array or an object (if the relation itself does not specify that). - * @since 2.0.49 - */ - public static function loadRelationsFor(&$models, $relationNames, $asArray = false) - { - // ActiveQueryTrait::findWith() called below assumes $models array is non-empty. - if (empty($models)) { - return; - } - - static::find()->asArray($asArray)->findWith((array)$relationNames, $models); - } - - /** - * Eager loads related models for the already loaded primary model. - * - * Helps to reduce the number of queries performed against database if some related models are only used - * when a specific condition is met. For example: - * - * ```php - * $customer = Customer::find()->where(['id' => 123])->one(); - * if (Yii:app()->getUser()->getIdentity()->canAccessOrders()) { - * $customer->loadRelations('orders.items'); - * } - * ``` - * - * @param string|array $relationNames the names of the relations of this model to be loaded from database. See [[ActiveQueryInterface::with()]] on how to specify this argument. - * @param bool $asArray whether to load each relation as an array or an object (if the relation itself does not specify that). - * @since 2.0.49 - */ - public function loadRelations($relationNames, $asArray = false) - { - $models = [$this]; - static::loadRelationsFor($models, $relationNames, $asArray); - } } diff --git a/db/Query.php b/db/Query.php index f44a1c447..9374f9d84 100644 --- a/db/Query.php +++ b/db/Query.php @@ -996,7 +996,7 @@ public function rightJoin($table, $on = '', $params = []) /** * Sets the GROUP BY part of the query. - * @param string|array|ExpressionInterface|null $columns the columns to be grouped by. + * @param string|array|ExpressionInterface $columns the columns to be grouped by. * Columns can be specified in either a string (e.g. "id, name") or an array (e.g. ['id', 'name']). * The method will automatically quote the column names unless a column contains some parenthesis * (which means the column contains a DB expression). @@ -1014,7 +1014,7 @@ public function groupBy($columns) { if ($columns instanceof ExpressionInterface) { $columns = [$columns]; - } elseif (!is_array($columns) && !is_null($columns)) { + } elseif (!is_array($columns)) { $columns = preg_split('/\s*,\s*/', trim($columns), -1, PREG_SPLIT_NO_EMPTY); } $this->groupBy = $columns; diff --git a/helpers/mimeAliases.php b/helpers/mimeAliases.php index a9e677adc..4cd89888a 100644 --- a/helpers/mimeAliases.php +++ b/helpers/mimeAliases.php @@ -3,9 +3,6 @@ * MIME aliases. * * This file contains aliases for MIME types. - * - * All extra changes made to this file must be comitted to /build/controllers/MimeTypeController.php - * otherwise they will be lost on next build. */ return [ 'text/rtf' => 'application/rtf', diff --git a/helpers/mimeExtensions.php b/helpers/mimeExtensions.php index e4936030f..946d61cd0 100644 --- a/helpers/mimeExtensions.php +++ b/helpers/mimeExtensions.php @@ -8,9 +8,6 @@ * Its content is generated from the apache http mime.types file. * https://svn.apache.org/viewvc/httpd/httpd/trunk/docs/conf/mime.types?view=markup * This file has been placed in the public domain for unlimited redistribution. - * - * All extra changes made to this file must be comitted to /build/controllers/MimeTypeController.php - * otherwise they will be lost on next build. */ return [ 'application/andrew-inset' => 'ez', diff --git a/helpers/mimeTypes.php b/helpers/mimeTypes.php index f895e8d07..e91f80f95 100644 --- a/helpers/mimeTypes.php +++ b/helpers/mimeTypes.php @@ -7,9 +7,6 @@ * Its content is generated from the apache http mime.types file. * https://svn.apache.org/viewvc/httpd/httpd/trunk/docs/conf/mime.types?view=markup * This file has been placed in the public domain for unlimited redistribution. - * - * All extra changes made to this file must be comitted to /build/controllers/MimeTypeController.php - * otherwise they will be lost on next build. */ $mimeTypes = [ 123 => 'application/vnd.lotus-1-2-3', diff --git a/log/FileTarget.php b/log/FileTarget.php index 3e13278a3..29e76d470 100644 --- a/log/FileTarget.php +++ b/log/FileTarget.php @@ -88,8 +88,9 @@ public function init() public function export() { $text = implode("\n", array_map([$this, 'formatMessage'], $this->messages)) . "\n"; + $trimmedText = trim($text); - if (trim($text) === '') { + if (empty($trimmedText)) { return; // No messages to export, so we exit the function early } diff --git a/messages/config.php b/messages/config.php index 6028328f3..93845f2e0 100644 --- a/messages/config.php +++ b/messages/config.php @@ -15,7 +15,8 @@ 'languages' => [ 'af', 'ar', 'az', 'be', 'bg', 'bs', 'ca', 'cs', 'da', 'de', 'el', 'es', 'et', 'fa', 'fi', 'fr', 'he', 'hi', 'pt-BR', 'ro', 'hr', 'hu', 'hy', 'id', 'it', 'ja', 'ka', 'kk', 'ko', 'kz', 'lt', 'lv', 'ms', 'nb-NO', 'nl', - 'pl', 'pt', 'ru', 'sk', 'sl', 'sr', 'sr-Latn', 'sv', 'tg', 'th', 'tr', 'uk', 'uz', 'uz-Cy', 'vi', 'zh', 'zh-TW' + 'pl', 'pt', 'ru', 'sk', 'sl', 'sr', 'sr-Latn', 'sv', 'tg', 'th', 'tr', 'uk', 'uz', 'uz-Cy', 'vi', 'zh-CN', + 'zh-TW' ], // string, the name of the function for translating messages. // Defaults to 'Yii::t'. This is used as a mark to find the messages to be diff --git a/messages/ko/yii.php b/messages/ko/yii.php index b0ad872fe..4fe82311f 100644 --- a/messages/ko/yii.php +++ b/messages/ko/yii.php @@ -75,8 +75,8 @@ '{attribute} must be greater than or equal to "{compareValue}".' => '{attribute}는 "{compareValue}" 보다 크거나 같아야 합니다.', '{attribute} must be less than "{compareValue}".' => '{attribute}는 "{compareValue}" 보다 작아야 합니다.', '{attribute} must be less than or equal to "{compareValue}".' => '{attribute}는 "{compareValue}" 보다 작거나 같아야 합니다.', - '{attribute} must be no greater than {max}.' => '{attribute}는 "{max}" 보다 클 수 없습니다.', - '{attribute} must be no less than {min}.' => '{attribute}는 "{min}" 보다 작을 수 없습니다.', + '{attribute} must be no greater than {max}.' => '{attribute}는 "{compareValue}" 보다 클 수 없습니다.', + '{attribute} must be no less than {min}.' => '{attribute}는 "{compareValue}" 보다 작을 수 없습니다.', '{attribute} must be repeated exactly.' => '{attribute}는 정확하게 반복합니다.', '{attribute} must not be equal to "{compareValue}".' => '{attribute}는 "{compareValue}"와 같을 수 없습니다.', '{attribute} should contain at least {min, number} {min, plural, one{character} other{characters}}.' => '{attribute}는 최소 {min}자 이어야합니다.', diff --git a/requirements/requirements.php b/requirements/requirements.php index d065f6363..555930615 100644 --- a/requirements/requirements.php +++ b/requirements/requirements.php @@ -111,12 +111,5 @@ 'memo' => 'When IpValidator::expandIPv6 property is set to true, PHP must support IPv6 protocol stack. Currently PHP constant AF_INET6 is not defined and IPv6 is probably unsupported.' - ), - array( - 'name' => 'pcntl', - 'mandatory' => false, - 'condition' => extension_loaded('pcntl'), - 'by' => 'Process Control', - 'memo' => 'Recommended for yii2-queue CLI operations' ) ); diff --git a/widgets/MaskedInputAsset.php b/widgets/MaskedInputAsset.php index 473f4315f..57748be86 100644 --- a/widgets/MaskedInputAsset.php +++ b/widgets/MaskedInputAsset.php @@ -21,7 +21,7 @@ class MaskedInputAsset extends AssetBundle { public $sourcePath = '@bower/inputmask/dist'; public $js = [ - 'jquery.inputmask.js', + 'jquery.inputmask.bundle.js', ]; public $depends = [ 'yii\web\YiiAsset', From 01316620e9b5e14025c456e83d20b45e95801bb9 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Sun, 22 Oct 2023 07:40:27 -0300 Subject: [PATCH 24/31] Remove unsed package "paragonie/random_compat". --- composer.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 0b27d62ff..4934013b6 100644 --- a/composer.json +++ b/composer.json @@ -73,8 +73,7 @@ "bower-asset/jquery": "3.7.*@stable | 3.6.*@stable | 3.5.*@stable | 3.4.*@stable | 3.3.*@stable | 3.2.*@stable | 3.1.*@stable | 2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable", "bower-asset/inputmask": "^5.0.8 ", "bower-asset/punycode": "^2.2", - "bower-asset/yii2-pjax": "~2.0.1", - "paragonie/random_compat": ">=1" + "bower-asset/yii2-pjax": "~2.0.1" }, "autoload": { "psr-4": {"yii\\": ""} From dfd27a39cb2ba5f19e6f1e8bdae231c39decda09 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Wed, 25 Oct 2023 07:33:47 -0300 Subject: [PATCH 25/31] Fix type boolean in `MSSQL`. (#20040) --- CHANGELOG.md | 1 + db/mssql/Schema.php | 18 ++++++++---------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0dc6fbdba..a975e77a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Yii Framework 2 Change Log 2.2 under development ------------------------ +- Bug #20040: Fix type `boolean` in `MSSQL` (terabytesoftw) - Chg #19902: Remove support for CUBRID (mtangoo) - Chg #19891: Remove XCache and ZendDataCache support (mtangoo) diff --git a/db/mssql/Schema.php b/db/mssql/Schema.php index 07dbaac98..a3fe3e329 100644 --- a/db/mssql/Schema.php +++ b/db/mssql/Schema.php @@ -386,28 +386,26 @@ protected function loadColumnSchema($info) $column->isComputed = (bool)$info['is_computed']; $column->unsigned = stripos($column->dbType, 'unsigned') !== false; $column->comment = $info['comment'] === null ? '' : $info['comment']; - $column->type = self::TYPE_STRING; + if (preg_match('/^(\w+)(?:\(([^\)]+)\))?/', $column->dbType, $matches)) { $type = $matches[1]; + if (isset($this->typeMap[$type])) { $column->type = $this->typeMap[$type]; } + + if ($type === 'bit') { + $column->type = 'boolean'; + } + if (!empty($matches[2])) { $values = explode(',', $matches[2]); $column->size = $column->precision = (int) $values[0]; + if (isset($values[1])) { $column->scale = (int) $values[1]; } - if ($column->size === 1 && ($type === 'tinyint' || $type === 'bit')) { - $column->type = 'boolean'; - } elseif ($type === 'bit') { - if ($column->size > 32) { - $column->type = 'bigint'; - } elseif ($column->size === 32) { - $column->type = 'integer'; - } - } } } From 2be8715ef1d876e2d5828e02fae0ed22d86d0ee3 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Tue, 31 Oct 2023 14:41:22 -0300 Subject: [PATCH 26/31] Update `CHANGELOG.md`. --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b99a3202f..1e2ae1d83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,6 @@ Yii Framework 2 Change Log 2.2 under development ------------------------ -- Bug #20040: Fix type `boolean` in `MSSQL` (terabytesoftw) - Chg #19902: Remove support for CUBRID (mtangoo) - Chg #19891: Remove XCache and ZendDataCache support (mtangoo) From c69df63191274d121143aacc0306d59337a67c05 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Sun, 27 Apr 2025 06:25:17 -0400 Subject: [PATCH 27/31] Fix error typo. --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20d84ef95..24ad9ecce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,6 @@ Yii Framework 2 Change Log - Chg #19891: Remove XCache and ZendDataCache support (mtangoo) -2.0.50 under development 2.0.53 under development ------------------------ From 9340705677f474fa405e36f8251e9e1d4c83268b Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Tue, 29 Apr 2025 05:32:03 -0400 Subject: [PATCH 28/31] Sync master branch to 2.2. (#20365) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Максим Спирков <63721828+max-s-lab@users.noreply.github.com> fixed Psalm/PHPStan annotations for ActiveRecord and ActiveQuery (#20363) --- db/ActiveQuery.php | 41 +++++++++++++++-------------------------- db/ActiveRecord.php | 6 ++++++ di/Container.php | 11 +++++------ di/Instance.php | 6 ++++++ 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/db/ActiveQuery.php b/db/ActiveQuery.php index 67d48b98b..7bfa3b820 100644 --- a/db/ActiveQuery.php +++ b/db/ActiveQuery.php @@ -71,6 +71,21 @@ * @since 2.0 * * @template T of (ActiveRecord|array) + * + * @phpstan-method T|null one($db = null) + * @psalm-method T|null one($db = null) + * + * @phpstan-method T[] all($db = null) + * @psalm-method T[] all($db = null) + * + * @phpstan-method ($value is true ? (T is array ? self : self) : self) asArray($value = true) + * @psalm-method ($value is true ? (T is array ? self : self) : self) asArray($value = true) + * + * @phpstan-method BatchQueryResult batch($batchSize = 100, $db = null) + * @psalm-method BatchQueryResult batch($batchSize = 100, $db = null) + * + * @phpstan-method BatchQueryResult each($batchSize = 100, $db = null) + * @psalm-method BatchQueryResult each($batchSize = 100, $db = null) */ class ActiveQuery extends Query implements ActiveQueryInterface { @@ -316,32 +331,6 @@ public function one($db = null) return null; } - /** - * {@inheritdoc} - * - * @return BatchQueryResult - * @psalm-return T[][]|BatchQueryResult - * @phpstan-return T[][]|BatchQueryResult - * @codeCoverageIgnore - */ - public function batch($batchSize = 100, $db = null) - { - return parent::batch($batchSize, $db); - } - - /** - * {@inheritdoc} - * - * @return BatchQueryResult - * @psalm-return T[]|BatchQueryResult - * @phpstan-return T[]|BatchQueryResult - * @codeCoverageIgnore - */ - public function each($batchSize = 100, $db = null) - { - return parent::each($batchSize, $db); - } - /** * Creates a DB command that can be used to execute this query. * @param Connection|null $db the DB connection used to create the DB command. diff --git a/db/ActiveRecord.php b/db/ActiveRecord.php index 29d5efe0b..c34b51168 100644 --- a/db/ActiveRecord.php +++ b/db/ActiveRecord.php @@ -156,6 +156,9 @@ public static function getDb() * @param string $sql the SQL statement to be executed * @param array $params parameters to be bound to the SQL statement during execution. * @return ActiveQuery the newly created [[ActiveQuery]] instance + * + * @phpstan-return ActiveQuery + * @psalm-return ActiveQuery */ public static function findBySql($sql, $params = []) { @@ -408,6 +411,9 @@ public static function deleteAll($condition = null, $params = []) /** * {@inheritdoc} * @return ActiveQuery the newly created [[ActiveQuery]] instance. + * + * @phpstan-return ActiveQuery + * @psalm-return ActiveQuery */ public static function find() { diff --git a/di/Container.php b/di/Container.php index 817f0b0a2..1d34887f4 100644 --- a/di/Container.php +++ b/di/Container.php @@ -158,12 +158,11 @@ class Container extends Component * @throws InvalidConfigException if the class cannot be recognized or correspond to an invalid definition * @throws NotInstantiableException If resolved to an abstract class or an interface (since 2.0.9) * - * - * @template T of class-string - * @psalm-param class-string|array{class: class-string} $class - * @phpstan-param class-string|array{class: class-string} $class - * @psalm-return T - * @phpstan-return T + * @template T of object + * @psalm-param string|class-string|Instance $class + * @phpstan-param string|class-string|Instance $class + * @psalm-return ($class is class-string ? T : object) + * @phpstan-return ($class is class-string ? T : object) */ public function get($class, $params = [], $config = []) { diff --git a/di/Instance.php b/di/Instance.php index edecbe9be..020e81718 100644 --- a/di/Instance.php +++ b/di/Instance.php @@ -114,6 +114,12 @@ public static function of($id, $optional = false) * @param ServiceLocator|Container|null $container the container. This will be passed to [[get()]]. * @return object the object referenced by the Instance, or `$reference` itself if it is an object. * @throws InvalidConfigException if the reference is invalid + * + * @template T of object + * @psalm-param class-string|null $type + * @phpstan-param class-string|null $type + * @psalm-return ($type is null ? object : T) + * @phpstan-return ($type is null ? object : T) */ public static function ensure($reference, $type = null, $container = null) { From fd41f65fb0bfdc872c179702a040b04c43ffd609 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Sun, 4 May 2025 07:37:37 -0400 Subject: [PATCH 29/31] Refactor asset management: Migrate from `Bower` to `NPM` for package dependencies and update related documentation. (#20368) --- CHANGELOG.md | 1 + base/Application.php | 3 +-- composer.json | 6 +----- validators/PunycodeAsset.php | 2 +- web/JqueryAsset.php | 2 +- widgets/MaskedInputAsset.php | 2 +- widgets/PjaxAsset.php | 2 +- 7 files changed, 7 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24ad9ecce..bae37c111 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Yii Framework 2 Change Log - Chg #19902: Remove support for CUBRID (mtangoo) - Chg #19891: Remove XCache and ZendDataCache support (mtangoo) +- Enh #20368: Refactor asset management: Migrate from `Bower` to `NPM` for package dependencies and update related documentation (terabytesoftw) 2.0.53 under development diff --git a/base/Application.php b/base/Application.php index e2944b82a..fddd279b7 100644 --- a/base/Application.php +++ b/base/Application.php @@ -459,8 +459,7 @@ public function setVendorPath($path) { $this->_vendorPath = Yii::getAlias($path); Yii::setAlias('@vendor', $this->_vendorPath); - Yii::setAlias('@bower', $this->_vendorPath . DIRECTORY_SEPARATOR . 'bower'); - Yii::setAlias('@npm', $this->_vendorPath . DIRECTORY_SEPARATOR . 'npm'); + Yii::setAlias('@npm', $this->getBasePath() . DIRECTORY_SEPARATOR . 'node_modules'); } /** diff --git a/composer.json b/composer.json index ad247b928..e7612a41b 100644 --- a/composer.json +++ b/composer.json @@ -69,11 +69,7 @@ "lib-pcre": "*", "yiisoft/yii2-composer": "~2.0.4", "ezyang/htmlpurifier": "^4.17", - "cebe/markdown": "~1.0.0 | ~1.1.0 | ~1.2.0", - "bower-asset/jquery": "3.7.*@stable | 3.6.*@stable | 3.5.*@stable | 3.4.*@stable | 3.3.*@stable | 3.2.*@stable | 3.1.*@stable | 2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable", - "bower-asset/inputmask": "^5.0.8 ", - "bower-asset/punycode": "^1.4", - "bower-asset/yii2-pjax": "~2.0.1" + "cebe/markdown": "~1.0.0 | ~1.1.0 | ~1.2.0" }, "autoload": { "psr-4": {"yii\\": ""} diff --git a/validators/PunycodeAsset.php b/validators/PunycodeAsset.php index 8d928838c..0e5917a5b 100644 --- a/validators/PunycodeAsset.php +++ b/validators/PunycodeAsset.php @@ -17,7 +17,7 @@ */ class PunycodeAsset extends AssetBundle { - public $sourcePath = '@bower/punycode'; + public $sourcePath = '@npm/punycode'; public $js = [ 'punycode.js', ]; diff --git a/web/JqueryAsset.php b/web/JqueryAsset.php index df365d768..e7a534671 100644 --- a/web/JqueryAsset.php +++ b/web/JqueryAsset.php @@ -15,7 +15,7 @@ */ class JqueryAsset extends AssetBundle { - public $sourcePath = '@bower/jquery/dist'; + public $sourcePath = '@npm/jquery/dist'; public $js = [ 'jquery.js', ]; diff --git a/widgets/MaskedInputAsset.php b/widgets/MaskedInputAsset.php index 473f4315f..2a0a6a197 100644 --- a/widgets/MaskedInputAsset.php +++ b/widgets/MaskedInputAsset.php @@ -19,7 +19,7 @@ */ class MaskedInputAsset extends AssetBundle { - public $sourcePath = '@bower/inputmask/dist'; + public $sourcePath = '@npm/inputmask/dist'; public $js = [ 'jquery.inputmask.js', ]; diff --git a/widgets/PjaxAsset.php b/widgets/PjaxAsset.php index 47795f683..c084763f9 100644 --- a/widgets/PjaxAsset.php +++ b/widgets/PjaxAsset.php @@ -17,7 +17,7 @@ */ class PjaxAsset extends AssetBundle { - public $sourcePath = '@bower/yii2-pjax'; + public $sourcePath = '@npm/yii2-pjax'; public $js = [ 'jquery.pjax.js', ]; From d7ac8ecda96921128610285fe3d0ba465e26d93d Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Sat, 10 May 2025 10:17:53 -0400 Subject: [PATCH 30/31] Add `package.json` for `2.2`. (#20383) --- package.json | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 package.json diff --git a/package.json b/package.json new file mode 100644 index 000000000..09a66d2bc --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "yii2", + "description": "a modern PHP framework designed for professional Web development", + "dependencies": { + "inputmask": "^5.0.8", + "jquery-pjax": "^2.0.1", + "jquery": "~3.6.4", + "punycode": "^1.4.0", + "yii2-pjax": "^2.0.8" + }, + "keywords": [ + "php", + "framework" + ], + "license": "BSD-3-Clause", + "bugs": { + "url": "https://github.com/yiisoft/yii2/issues" + }, + "homepage": "https://github.com/yiisoft/yii2" +} From 1eaabe0c5f2b323950d52b11021394e9d002eaac Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Sat, 10 May 2025 14:57:51 -0400 Subject: [PATCH 31/31] Add "foxy" flag to extra section in `composer.json`. (#20384) --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index e7612a41b..461206ffd 100644 --- a/composer.json +++ b/composer.json @@ -80,6 +80,7 @@ "extra": { "branch-alias": { "dev-master": "2.0.x-dev" - } + }, + "foxy": true } } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy