Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

## Навигация

- **Текущий месяц:** [Апрель 2026](#апрель-2026) (ниже)
- **Предыдущий месяц:** [Март 2026](#март-2026) (ниже)
- **Текущий месяц:** [Май 2026](#май-2026) (ниже)
- **Предыдущий месяц:** [Апрель 2026](#апрель-2026) (ниже)
- **Ещё раньше:** [Февраль 2026](#февраль-2026), [Январь 2026](#январь-2026) (ниже)
- **Архив по месяцам:**
- [Декабрь 2025](changelogs/2025-12.md)
Expand All @@ -15,6 +15,19 @@

---

## Май 2026

### Разработка

#### 🐛 Исправлено

**События с мутацией данных через `returnedValues` (#219):**
- `msOnBeforeSendNotification` теперь применяет `returnedValues['recipient']` и `returnedValues['channels']`, поэтому плагины могут изменить получателя и каналы перед отправкой уведомления.
- `msOnBeforeImport` и `msOnImportRow` применяют `returnedValues` к параметрам импорта и данным строки (`data`, `tvData`, `optionData`, `gallery`).
- `msOnProductsLoad` и `msOnProductPrepare` применяют `returnedValues['rows']` / `returnedValues['row']`, чтобы bulk-обогащение списка товаров и подготовка отдельной строки доходили до рендера.

---

## Апрель 2026

### [2026-04-27] 🚀 Версия 1.10.1-beta1
Expand Down
29 changes: 27 additions & 2 deletions core/components/minishop3/elements/snippets/ms3_products.php
Original file line number Diff line number Diff line change
Expand Up @@ -364,15 +364,38 @@
$usePackages = array_map('trim', explode(',', $scriptProperties['usePackages']));
}

$clearEventReturnedValues = static function () use ($modx): void {
if (isset($modx->event->returnedValues)) {
$modx->event->returnedValues = null;
}
};
$getEventReturnedValues = static function () use ($modx): array {
return isset($modx->event->returnedValues) && is_array($modx->event->returnedValues)
? $modx->event->returnedValues
: [];
};
$applyReturnedArray = static function (array $current, array $returnedValues, string $key): array {
if (!isset($returnedValues[$key]) || !is_array($returnedValues[$key])) {
return $current;
}

// Lists are complete replacements; associative arrays may patch existing keys.
return array_is_list($returnedValues[$key])
? $returnedValues[$key]
: array_replace($current, $returnedValues[$key]);
};

// Event: msOnProductsLoad - bulk loading of additional data from external packages
if (!empty($rows) && is_array($rows)) {
$productIds = array_column($rows, 'id');
$clearEventReturnedValues();
$modx->invokeEvent('msOnProductsLoad', [
'rows' => &$rows,
'rows' => $rows,
'productIds' => $productIds,
'usePackages' => $usePackages,
'scriptProperties' => $scriptProperties,
]);
$rows = $applyReturnedArray($rows, $getEventReturnedValues(), 'rows');
$pdoFetch->addTime('Invoked msOnProductsLoad event');
}

Expand Down Expand Up @@ -439,11 +462,13 @@
$opt_time += microtime(true) - $opt_time_start;

// Event: msOnProductPrepare - enrich single product data from external packages
$clearEventReturnedValues();
$modx->invokeEvent('msOnProductPrepare', [
'row' => &$rows[$k],
'row' => $rows[$k],
'productId' => $row['id'],
'idx' => $row['idx'],
]);
$rows[$k] = $applyReturnedArray($rows[$k], $getEventReturnedValues(), 'row');
$row = $rows[$k]; // Update local variable after event modifications

if ($scriptProperties['return'] == 'data') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,18 @@ public function send(Notification $notification, array $recipient, string $recip
$order = $notification->getOrder();

// Fire before event - allows plugins to modify or cancel notification
$this->clearEventReturnedValues();
$eventResult = $this->modx->invokeEvent('msOnBeforeSendNotification', [
'notification' => $notification,
'recipient' => &$recipient,
'recipient' => $recipient,
'recipientType' => $recipientType,
'channels' => &$channels,
'channels' => $channels,
]);
$returnedValues = $this->getEventReturnedValues();
$recipient = $this->applyReturnedArray($recipient, $returnedValues, 'recipient');
if (isset($returnedValues['channels']) && is_array($returnedValues['channels'])) {
$channels = $returnedValues['channels'];
}

// Check if notification was cancelled by plugin
$cancelled = false;
Expand Down Expand Up @@ -263,4 +269,30 @@ protected function isSchedulerAvailable(): bool
{
return $this->modx->services->has('scheduler');
}

protected function clearEventReturnedValues(): void
{
if (isset($this->modx->event->returnedValues)) {
$this->modx->event->returnedValues = null;
}
}

protected function getEventReturnedValues(): array
{
return isset($this->modx->event->returnedValues) && is_array($this->modx->event->returnedValues)
? $this->modx->event->returnedValues
: [];
}

protected function applyReturnedArray(array $current, array $returnedValues, string $key): array
{
if (!isset($returnedValues[$key]) || !is_array($returnedValues[$key])) {
return $current;
}

// Lists are complete replacements; associative arrays may patch existing keys.
return array_is_list($returnedValues[$key])
? $returnedValues[$key]
: array_replace($current, $returnedValues[$key]);
}
}
44 changes: 39 additions & 5 deletions core/components/minishop3/src/Utils/ImportCSV.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,12 @@ public function process(array $params): array
}

// Fire before import event
$this->clearEventReturnedValues();
$eventResult = $this->modx->invokeEvent('msOnBeforeImport', [
'file' => $this->params['file'],
'params' => &$this->params,
'params' => $this->params,
]);
$this->params = $this->applyReturnedArray($this->params, $this->getEventReturnedValues(), 'params');
if ($this->isEventCancelled($eventResult)) {
$error = $this->modx->lexicon('ms3_utilities_import_cancelled');
return $this->ms3->utils->error($error);
Expand Down Expand Up @@ -344,14 +346,20 @@ private function processRow(array $csv): bool
}

// Fire event to allow modification of row data
$this->clearEventReturnedValues();
$eventResult = $this->modx->invokeEvent('msOnImportRow', [
'row' => $this->rows,
'csv' => $csv,
'data' => &$data,
'tvData' => &$tvData,
'optionData' => &$optionData,
'gallery' => &$gallery,
'data' => $data,
'tvData' => $tvData,
'optionData' => $optionData,
'gallery' => $gallery,
]);
$returnedValues = $this->getEventReturnedValues();
$data = $this->applyReturnedArray($data, $returnedValues, 'data');
$tvData = $this->applyReturnedArray($tvData, $returnedValues, 'tvData');
$optionData = $this->applyReturnedArray($optionData, $returnedValues, 'optionData');
$gallery = $this->applyReturnedArray($gallery, $returnedValues, 'gallery');
if ($this->isEventCancelled($eventResult)) {
$this->skipped++;
return true;
Expand Down Expand Up @@ -660,6 +668,32 @@ private function isEventCancelled($eventResult): bool
return false;
}

private function clearEventReturnedValues(): void
{
if (isset($this->modx->event->returnedValues)) {
$this->modx->event->returnedValues = null;
}
}

private function getEventReturnedValues(): array
{
return isset($this->modx->event->returnedValues) && is_array($this->modx->event->returnedValues)
? $this->modx->event->returnedValues
: [];
}

private function applyReturnedArray(array $current, array $returnedValues, string $key): array
{
if (!isset($returnedValues[$key]) || !is_array($returnedValues[$key])) {
return $current;
}

// Lists are complete replacements; associative arrays may patch existing keys.
return array_is_list($returnedValues[$key])
? $returnedValues[$key]
: array_replace($current, $returnedValues[$key]);
}

/**
* Count rows in CSV file
*/
Expand Down