mirror of
https://github.com/yiisoft/yii2.git
synced 2025-11-02 21:41:19 +08:00
Merge branch 'master' of git://github.com/yiisoft/yii2 into 18585-email-validator-idn-fix
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -47,3 +47,4 @@ phpunit.phar
|
||||
# NPM packages
|
||||
/node_modules
|
||||
.env
|
||||
package-lock.json
|
||||
|
||||
@ -4,6 +4,7 @@ Yii Framework 2 Change Log
|
||||
2.0.42 under development
|
||||
------------------------
|
||||
|
||||
- Bug #18323: Fix client validation of RadioList when there are disabled items (toir427)
|
||||
- Enh #18534: Added `prepareSearchQuery` property in `yii\rest\IndexAction` (programmis)
|
||||
- Enh #18566: Throw the original exception when `yii\web\Controller::bindInjectedParams()` catches HttpException (pigochu)
|
||||
- Bug #18585: Fix `yii\validators\EmailValidator` to handle an edge case where `IDN` is enabled, but fails ascii conversion for valid email addresses (ihitbuttons)
|
||||
@ -16,6 +17,8 @@ Yii Framework 2 Change Log
|
||||
- Bug #18526: Fix `yii\caching\DbCache` to work with MSSQL, add `normalizeTableRowData()` to `yii\db\mssql\QueryBuilder::upsert()` (darkdef)
|
||||
- Bug #14343: Fix `yii\test\ActiveFixture` to use model's DB connection instead of the default one (margori, bizley)
|
||||
- Bug #17631: Fix `yii\widgets\BaseListView` to properly render custom summary (sjaakp, bizley)
|
||||
- Bug #17203: Fix `yii\db\Connection` to persist customized `queryBuilder` configuration after the `close()` → `open()` cycle (silverfire)
|
||||
- Bug #18325: Fix `yii\db\pgsql\Schema` to respect non-default PgSQL schema name for data types (theonedemon, silverfire)
|
||||
|
||||
2.0.41.1 March 04, 2021
|
||||
-----------------------
|
||||
|
||||
@ -329,7 +329,8 @@
|
||||
this.$form = $form;
|
||||
var $input = findInput($form, this);
|
||||
|
||||
if ($input.is(':disabled')) {
|
||||
var disabled = $input.toArray().reduce((result, next) => result && $(next).is(':disabled'), true);
|
||||
if (disabled) {
|
||||
return true;
|
||||
}
|
||||
// validate markup for select input
|
||||
|
||||
@ -424,6 +424,15 @@ class Connection extends Component
|
||||
*/
|
||||
public $isSybase = false;
|
||||
|
||||
/**
|
||||
* @var array An array of [[setQueryBuilder()]] calls, holding the passed arguments.
|
||||
* Is used to restore a QueryBuilder configuration after the connection close/open cycle.
|
||||
*
|
||||
* @see restoreQueryBuilderConfiguration()
|
||||
* @since 2.0.42
|
||||
*/
|
||||
private $_queryBuilderConfigurations = [];
|
||||
|
||||
/**
|
||||
* @var Transaction the currently active transaction
|
||||
*/
|
||||
@ -851,7 +860,10 @@ class Connection extends Component
|
||||
$config = !is_array($this->schemaMap[$driver]) ? ['class' => $this->schemaMap[$driver]] : $this->schemaMap[$driver];
|
||||
$config['db'] = $this;
|
||||
|
||||
return $this->_schema = Yii::createObject($config);
|
||||
$this->_schema = Yii::createObject($config);
|
||||
$this->restoreQueryBuilderConfiguration();
|
||||
|
||||
return $this->_schema;
|
||||
}
|
||||
|
||||
throw new NotSupportedException("Connection does not support reading schema information for '$driver' DBMS.");
|
||||
@ -875,6 +887,25 @@ class Connection extends Component
|
||||
public function setQueryBuilder($value)
|
||||
{
|
||||
Yii::configure($this->getQueryBuilder(), $value);
|
||||
$this->_queryBuilderConfigurations[] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores custom QueryBuilder configuration after the connection close/open cycle
|
||||
*
|
||||
* @since 2.0.42
|
||||
*/
|
||||
private function restoreQueryBuilderConfiguration()
|
||||
{
|
||||
if ($this->_queryBuilderConfigurations === []) {
|
||||
return;
|
||||
}
|
||||
|
||||
$queryBuilderConfigurations = $this->_queryBuilderConfigurations;
|
||||
$this->_queryBuilderConfigurations = [];
|
||||
foreach ($queryBuilderConfigurations as $queryBuilderConfiguration) {
|
||||
$this->setQueryBuilder($queryBuilderConfiguration);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -476,6 +476,7 @@ SELECT
|
||||
a.attname AS column_name,
|
||||
COALESCE(td.typname, tb.typname, t.typname) AS data_type,
|
||||
COALESCE(td.typtype, tb.typtype, t.typtype) AS type_type,
|
||||
(SELECT nspname FROM pg_namespace WHERE oid = COALESCE(td.typnamespace, tb.typnamespace, t.typnamespace)) AS type_scheme,
|
||||
a.attlen AS character_maximum_length,
|
||||
pg_catalog.col_description(c.oid, a.attnum) AS column_comment,
|
||||
a.atttypmod AS modifier,
|
||||
@ -592,7 +593,12 @@ SQL;
|
||||
$column->allowNull = $info['is_nullable'];
|
||||
$column->autoIncrement = $info['is_autoinc'];
|
||||
$column->comment = $info['column_comment'];
|
||||
$column->dbType = $info['data_type'];
|
||||
if ($info['type_scheme'] !== null && !in_array($info['type_scheme'], [$this->defaultSchema, 'pg_catalog'], true)
|
||||
) {
|
||||
$column->dbType = $info['type_scheme'] . '.' . $info['data_type'];
|
||||
} else {
|
||||
$column->dbType = $info['data_type'];
|
||||
}
|
||||
$column->defaultValue = $info['column_default'];
|
||||
$column->enumValues = ($info['enum_values'] !== null) ? explode(',', str_replace(["''"], ["'"], $info['enum_values'])) : null;
|
||||
$column->unsigned = false; // has no meaning in PG
|
||||
|
||||
19
tests/data/ar/EnumTypeInCustomSchema.php
Normal file
19
tests/data/ar/EnumTypeInCustomSchema.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\data\ar;
|
||||
|
||||
use yii\db\ArrayExpression;
|
||||
|
||||
/**
|
||||
* Class EnumTypeInCustomSchema
|
||||
*
|
||||
* @property int $id
|
||||
* @property ArrayExpression $test_type
|
||||
*/
|
||||
class EnumTypeInCustomSchema extends ActiveRecord
|
||||
{
|
||||
public static function tableName()
|
||||
{
|
||||
return '{{%schema2.custom_type_test_table}}';
|
||||
}
|
||||
}
|
||||
@ -424,3 +424,12 @@ CREATE TABLE "T_upsert_1"
|
||||
(
|
||||
"a" INT NOT NULL PRIMARY KEY
|
||||
);
|
||||
|
||||
CREATE TYPE "schema2"."my_type" AS enum('VAL1', 'VAL2', 'VAL3');
|
||||
CREATE TABLE "schema2"."custom_type_test_table" (
|
||||
"id" SERIAL NOT NULL PRIMARY KEY,
|
||||
"test_type" "schema2"."my_type"[]
|
||||
);
|
||||
INSERT INTO "schema2"."custom_type_test_table" ("test_type")
|
||||
VALUES (array['VAL2']::"schema2"."my_type"[]);
|
||||
|
||||
|
||||
@ -10,6 +10,9 @@ namespace yiiunit\framework\db;
|
||||
use Yii;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\caching\ArrayCache;
|
||||
use yii\db\conditions\AndCondition;
|
||||
use yii\db\conditions\ExistsConditionBuilder;
|
||||
use yii\db\conditions\OrCondition;
|
||||
use yii\db\Connection;
|
||||
use yii\db\Transaction;
|
||||
|
||||
@ -46,6 +49,50 @@ abstract class ConnectionTest extends DatabaseTestCase
|
||||
$connection->open();
|
||||
}
|
||||
|
||||
public function testQueryBuilderConfigurationAfterOpenClose()
|
||||
{
|
||||
$connection = $this->getConnection(false, false);
|
||||
$connection->setQueryBuilder([
|
||||
'expressionBuilders' => [
|
||||
// Just a dumb mapping to make sure it's applied
|
||||
'yii\db\conditions\OrCondition' => 'yii\db\conditions\ExistsConditionBuilder'
|
||||
],
|
||||
]);
|
||||
// Second call to make sure that consecutive calls are handled correctly
|
||||
$connection->setQueryBuilder([
|
||||
'expressionBuilders' => [
|
||||
'yii\db\conditions\AndCondition' => 'yii\db\conditions\InConditionBuilder'
|
||||
],
|
||||
]);
|
||||
|
||||
$orCondition = new OrCondition(['dumb']);
|
||||
$andCondition = new AndCondition(['dumb']);
|
||||
|
||||
$connection->open();
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'\yii\db\conditions\ExistsConditionBuilder',
|
||||
$connection->getQueryBuilder()->getExpressionBuilder($orCondition)
|
||||
);
|
||||
$this->assertInstanceOf(
|
||||
'\yii\db\conditions\InConditionBuilder',
|
||||
$connection->getQueryBuilder()->getExpressionBuilder($andCondition)
|
||||
);
|
||||
|
||||
$connection->close();
|
||||
$this->assertNull($connection->pdo);
|
||||
$connection->open();
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'\yii\db\conditions\ExistsConditionBuilder',
|
||||
$connection->getQueryBuilder()->getExpressionBuilder($orCondition)
|
||||
);
|
||||
$this->assertInstanceOf(
|
||||
'\yii\db\conditions\InConditionBuilder',
|
||||
$connection->getQueryBuilder()->getExpressionBuilder($andCondition)
|
||||
);
|
||||
}
|
||||
|
||||
public function testSerialize()
|
||||
{
|
||||
$connection = $this->getConnection(false, false);
|
||||
|
||||
@ -10,6 +10,7 @@ namespace yiiunit\framework\db\pgsql;
|
||||
use yii\db\conditions\ExistsConditionBuilder;
|
||||
use yii\db\Expression;
|
||||
use yiiunit\data\ar\ActiveRecord;
|
||||
use yiiunit\data\ar\EnumTypeInCustomSchema;
|
||||
use yiiunit\data\ar\Type;
|
||||
|
||||
/**
|
||||
@ -349,4 +350,20 @@ class SchemaTest extends \yiiunit\framework\db\SchemaTest
|
||||
$result['3: index'][2] = [];
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function testCustomTypeInNonDefaultSchema()
|
||||
{
|
||||
$connection = $this->getConnection();
|
||||
ActiveRecord::$db = $this->getConnection();
|
||||
|
||||
$schema = $connection->schema->getTableSchema('schema2.custom_type_test_table');
|
||||
$model = EnumTypeInCustomSchema::find()->one();
|
||||
$this->assertSame(['VAL2'], $model->test_type->getValue());
|
||||
|
||||
$model->test_type = ['VAL1'];
|
||||
$model->save();
|
||||
|
||||
$modelAfterUpdate = EnumTypeInCustomSchema::find()->one();
|
||||
$this->assertSame(['VAL1'], $modelAfterUpdate->test_type->getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,4 +34,17 @@
|
||||
<div class="help-block"></div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</form>
|
||||
|
||||
<form id="w2">
|
||||
<div class="form-group required">
|
||||
<label class="control-label">Test radio</label>
|
||||
<input type="hidden" name="Test[radio]" value="">
|
||||
<div id="radioList" aria-required="true">
|
||||
<label><input type="radio" name="Test[radio]" disabled> Test 1</label>
|
||||
<label><input type="radio" name="Test[radio]"> Test 2</label>
|
||||
<label><input type="radio" name="Test[radio]"> Test 3</label>
|
||||
</div>
|
||||
<div class="help-block"></div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@ -104,6 +104,19 @@ describe('yii.activeForm', function () {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe('if at least one of the items is disabled', function () {
|
||||
it('validate radioList', function () {
|
||||
$activeForm = $('#w2');
|
||||
$activeForm.yiiActiveForm({
|
||||
id: 'radioList',
|
||||
input: '#radioList'
|
||||
});
|
||||
$activeForm.yiiActiveForm('validate');
|
||||
|
||||
assert.isFalse($activeForm.data('yiiActiveForm').validated);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('resetForm method', function () {
|
||||
@ -228,12 +241,12 @@ describe('yii.activeForm', function () {
|
||||
$input = $('#' + inputId);
|
||||
|
||||
$activeForm = $('#w0');
|
||||
$activeForm.yiiActiveForm(
|
||||
[{
|
||||
"id": inputId,
|
||||
"name": "name",
|
||||
input: '#' + inputId
|
||||
}], []).on('afterValidate', afterValidateSpy);
|
||||
$activeForm.yiiActiveForm(
|
||||
[{
|
||||
"id": inputId,
|
||||
"name": "name",
|
||||
input: '#' + inputId
|
||||
}], []).on('afterValidate', afterValidateSpy);
|
||||
|
||||
$activeForm.yiiActiveForm('validate');
|
||||
assert.notEqual(null, eventData);
|
||||
|
||||
Reference in New Issue
Block a user