Skip to content

Commit bcfb2f2

Browse files
Ensure array attributes are not logged as strings and are compared correctly
1 parent 69a063b commit bcfb2f2

File tree

1 file changed

+35
-3
lines changed

1 file changed

+35
-3
lines changed

Diff for: behaviors/LoggingBehavior.php

+35-3
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ public function logChanges($event) {
104104
} elseif ($event->name === ActiveRecord::EVENT_AFTER_UPDATE) {
105105
$action = 'update';
106106
$from = $this->removeExcluded($event->changedAttributes); //hopefully this is correct - see https://stackoverflow.com/questions/51645487/yii-2-getoldattribute-method-not-working-in-aftersave
107+
$this->convertArrayAttributes($event->sender, $from);
107108
$to = [];
108109
foreach ($from as $currFromKey => $currFromValue) {
109110
$to[$currFromKey] = $event->sender->getAttribute($currFromKey);
@@ -130,10 +131,23 @@ public function logChanges($event) {
130131
$logAttributes = [];
131132

132133
if ($from || $to) {
133-
if ($this->nonStrictChangesOnly && $event->name === ActiveRecord::EVENT_AFTER_UPDATE) {
134+
if ($event->name === ActiveRecord::EVENT_AFTER_UPDATE) {
134135
foreach ($from as $currAttr => $currValue) {
135-
if ((string) $from[$currAttr] === (string) $to[$currAttr]) {
136-
unset($from[$currAttr], $to[$currAttr]);
136+
if (is_array($from[$currAttr]) && is_array($to[$currAttr])) { //compare array attributes correctly
137+
if (serialize($from[$currAttr]) === serialize($to[$currAttr])) { //see https://stackoverflow.com/questions/804045/preferred-method-to-store-php-arrays-json-encode-vs-serialize
138+
unset($from[$currAttr], $to[$currAttr]);
139+
}
140+
}
141+
}
142+
if ($this->nonStrictChangesOnly) {
143+
foreach ($from as $currAttr => $currValue) {
144+
if (is_array($from[$currAttr]) && is_array($to[$currAttr])) { //ensure array attributes are not converted to just "Array" and removed by the code below (they are handled above instead)
145+
// do nothing, they are handled above
146+
} else {
147+
if ((string) $from[$currAttr] === (string) $to[$currAttr]) {
148+
unset($from[$currAttr], $to[$currAttr]);
149+
}
150+
}
137151
}
138152
}
139153
}
@@ -175,6 +189,24 @@ public function logChanges($event) {
175189
}
176190
}
177191

192+
/**
193+
* If any attributes has been set as array attributes using winternet\yii2\behaviors\ArrayAttributesBehavior, ensure they are not strings but arrays when being logged
194+
*/
195+
public function convertArrayAttributes($model, &$changes) {
196+
if (!is_array($changes) || empty($changes)) {
197+
return;
198+
}
199+
foreach ($model->getBehaviors() as $behavior) {
200+
if ($behavior instanceOf ArrayAttributesBehavior) {
201+
$tempModel = clone $behavior->owner;
202+
$tempModel->setAttributes($changes, false);
203+
$tempModel->trigger(\yii\db\ActiveRecord::EVENT_AFTER_FIND);
204+
$changes = $tempModel->getAttributes(array_keys($changes));
205+
break;
206+
}
207+
}
208+
}
209+
178210
protected function removeExcluded($keyValueArray) {
179211
return array_diff_key($keyValueArray, array_flip($this->excludeAttributes));
180212
}

0 commit comments

Comments
 (0)