Skip to content

Commit

Permalink
Sync to master. (#20012)
Browse files Browse the repository at this point in the history
* 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 <pawel.bizley@gmail.com>

* 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 <pawel.bizley@gmail.com>

* 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 yiisoft/yii2#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 <schmunk@usrbin.de>
Co-authored-by: Tim Fischer <tf@maschinensucher.de>
Co-authored-by: Tim Fischer <35448254+tim-fischer-maschinensucher@users.noreply.github.com>
Co-authored-by: Alexander Makarov <sam@rmcreative.ru>
Co-authored-by: Oleg Poludnenko <ua.oleg@gmail.com>
Co-authored-by: Bizley <pawel.bizley@gmail.com>
Co-authored-by: Sonia Zorba <zonia3000@gmail.com>
Co-authored-by: Tobias Munk <t.munk@herzogkommunikation.de>
Co-authored-by: Akbar Herlambang <akbar6393222@yahoo.com>
Co-authored-by: lubosdz <lubosdz@gmail.com>
Co-authored-by: Yuriy Bachevskiy <Materik-r@yandex.ru>
Co-authored-by: Robert Korulczyk <robert@korulczyk.pl>
Co-authored-by: salehhashemi1992 <81674631+salehhashemi1992@users.noreply.github.com>
Co-authored-by: PowerGamer1 <PowerGamer1@users.noreply.github.com>
Co-authored-by: Brad Bell <brad@pixelandtonic.com>
Co-authored-by: Alexandru Trandafir Catalin <alex@heavydots.com>
Co-authored-by: Nabi KaramAliZadeh <NabiKAZ@gmail.com>
  • Loading branch information
18 people authored Oct 19, 2023
1 parent ab8a9fe commit 50f12e2
Show file tree
Hide file tree
Showing 15 changed files with 199 additions and 77 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions assets/yii.activeForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -563,6 +565,9 @@
return;
}

if (currentAjaxRequest !== null) {
currentAjaxRequest.abort();
}
if (data.settings.timer !== undefined) {
clearTimeout(data.settings.timer);
}
Expand Down Expand Up @@ -929,4 +934,7 @@
$form.find(attribute.input).attr('aria-invalid', hasError ? 'true' : 'false');
}
}

var currentAjaxRequest = null;

})(window.jQuery);
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
161 changes: 96 additions & 65 deletions console/controllers/MessageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [];

Expand All @@ -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");
}

/**
Expand Down
2 changes: 1 addition & 1 deletion console/controllers/ServeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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\"");
}

/**
Expand Down
53 changes: 53 additions & 0 deletions db/BaseActiveRecord.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
4 changes: 2 additions & 2 deletions db/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand All @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions helpers/mimeAliases.php
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
3 changes: 3 additions & 0 deletions helpers/mimeExtensions.php
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
3 changes: 3 additions & 0 deletions helpers/mimeTypes.php
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
3 changes: 1 addition & 2 deletions log/FileTarget.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
Loading

0 comments on commit 50f12e2

Please sign in to comment.