From 6f1ae9ff39b45f36f3dfa68110cdda7c9e2e8d1d Mon Sep 17 00:00:00 2001 From: Sam Feyaerts Date: Tue, 6 Oct 2020 14:40:23 +0200 Subject: [PATCH] Use order-agnostic comparison for JSON --- .../Revisionable/RevisionableTrait.php | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/Venturecraft/Revisionable/RevisionableTrait.php b/src/Venturecraft/Revisionable/RevisionableTrait.php index d57d180a..c5bfff42 100644 --- a/src/Venturecraft/Revisionable/RevisionableTrait.php +++ b/src/Venturecraft/Revisionable/RevisionableTrait.php @@ -128,13 +128,15 @@ public function preSave() foreach ($this->updatedData as $key => $val) { $castCheck = ['object', 'array']; if (isset($this->casts[$key]) && in_array(gettype($val), $castCheck) && in_array($this->casts[$key], $castCheck) && isset($this->originalData[$key])) { - // Sorts the keys of a JSON object due Normalization performed by MySQL - // So it doesn't set false flag if it is changed only order of key or whitespace after comma - + // Due to MySQL resorting JSON keys for efficiency, we'll ignore the change if + // only the order of keys was modified + + $originalData = $this->sortJsonKeys(json_decode($this->originalData[$key], true)); $updatedData = $this->sortJsonKeys(json_decode($this->updatedData[$key], true)); - - $this->updatedData[$key] = json_encode($updatedData); - $this->originalData[$key] = json_encode(json_decode($this->originalData[$key], true)); + + if ($originalData === $updatedData) { + $this->syncOriginalAttribute($key); + } } else if (gettype($val) == 'object' && !method_exists($val, '__toString')) { unset($this->originalData[$key]); unset($this->updatedData[$key]); @@ -522,17 +524,14 @@ private function sortJsonKeys($attribute) { if(empty($attribute)) return $attribute; - foreach ($attribute as $key=>$value) { + foreach ($attribute as &$value) { if(is_array($value) || is_object($value)){ $value = $this->sortJsonKeys($value); - } else { - continue; } - - ksort($value); - $attribute[$key] = $value; } + ksort($attribute); + return $attribute; } }