diff --git a/system/Entity.php b/system/Entity.php index fa54c2dd270b..5486308b31b5 100644 --- a/system/Entity.php +++ b/system/Entity.php @@ -239,6 +239,23 @@ protected function hasPropertyChanged(string $key, $value = null) { return ! (($this->_original[$key] === null && $value === null) || $this->_original[$key] === $value); } + + //-------------------------------------------------------------------- + + /** + * Gets original property value or $defaultValue specified by parameter if original value is not set OR null + * + * @param string $key + * @param null $defaultValue + * + * @return mixed + */ + public function getOriginalValue(string $key, $defaultValue = null) + { + return $this->_original[$key] ?? $defaultValue; + } + + //-------------------------------------------------------------------- /** * Magic method to allow retrieval of protected and private @@ -373,6 +390,7 @@ public function __set(string $key, $value = null) * attribute will be reset to that default value. * * @param string $key + * @throws \ReflectionException */ public function __unset(string $key) { diff --git a/system/Model.php b/system/Model.php index eb69d717ae1a..9d3ea38bd365 100644 --- a/system/Model.php +++ b/system/Model.php @@ -443,7 +443,7 @@ public function set($key, $value = '', bool $escape = null) } //-------------------------------------------------------------------- - + /** * A convenience method that will attempt to determine whether the * data should be inserted or updated. Will work with either @@ -458,26 +458,49 @@ public function set($key, $value = '', bool $escape = null) */ public function save($data) { + $originalPrimaryKey = null; // If $data is using a custom class with public or protected // properties representing the table elements, we need to grab // them as an array. - if (is_object($data) && ! $data instanceof \stdClass) + if (is_object($data)) { - $data = static::classToArray($data, $this->primaryKey, $this->dateFormat); + if( ! $data instanceof \stdClass) + { + + $originalPrimaryKey = method_exists($data, 'getOriginalValue') ? + $data->getOriginalValue($this->primaryKey) : + ($data->{$this->primaryKey} ?? null); + + $data = static::classToArray($data, $this->primaryKey, $this->dateFormat); + } + else + { + $originalPrimaryKey = $data->{$this->primaryKey} ?? null; + } + + } + else if(is_array($data)) + { + $originalPrimaryKey = $data[$this->primaryKey] ?? null; } - if (empty($data)) + // If originalPrimaryKey is not null there is only one item in $data array and + // $data[$primaryKey] = $originalPrimaryKey + // then nothing has been changed in other case someone wants to update only primaryKey value. + // We do not have possibilities to check object here :( + if(empty($data) || ($originalPrimaryKey !== null && is_array($data) && ! empty($data[$this->primaryKey]) && count($data) === 1 && $data[$this->primaryKey] === $originalPrimaryKey)) { return true; } - if (is_object($data) && isset($data->{$this->primaryKey})) + if (is_object($data) && !empty($originalPrimaryKey)) { - $response = $this->update($data->{$this->primaryKey}, $data); + $response = $this->update($originalPrimaryKey, $data); } - elseif (is_array($data) && ! empty($data[$this->primaryKey])) + // Adding support for UPDATE table SET primaryKey = 'newVal' WHERE primaryKey = 'oldVal' + elseif (is_array($data) && ! empty($originalPrimaryKey)) { - $response = $this->update($data[$this->primaryKey], $data); + $response = $this->update($originalPrimaryKey, $data); } else { @@ -487,6 +510,7 @@ public function save($data) return $response; } + /** * Takes a class an returns an array of it's public and protected * properties as an array suitable for use in creates and updates.