Created
March 8, 2017 18:47
-
-
Save hackel/9e2892f8609414741fee58cf7ecaaf44 to your computer and use it in GitHub Desktop.
Trait for Jenssegers/Mongodb models that will automatically unset any attributes contained in the $clearable (or $fillable) property.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use Illuminate\Database\Eloquent\Builder; | |
use Illuminate\Support\Arr; | |
/** | |
* Class DropUnsetAttributes will drop any fields contained in the model's $clearable | |
* array if they are not included in the attributes on mass-assignment (fill). | |
* | |
* @package Quirks\ModelTraits | |
*/ | |
trait DropUnsetAttributes | |
{ | |
public static function bootDropUnsetAttributes() | |
{ | |
static::saving([static::class, 'dropEmptyClearables']); | |
static::saved([static::class, 'dropAttributesToUnset']); | |
} | |
/** | |
* This does *not* currently work for embedded relations | |
* | |
* @param static $model | |
*/ | |
public static function dropEmptyClearables($model) | |
{ | |
foreach ($model->getClearable() as $key) { | |
if ($model->isDirty($key) && empty($model->$key)) { | |
unset($model->$key); | |
} | |
} | |
} | |
/** | |
* @param static $model | |
*/ | |
public static function dropAttributesToUnset($model) | |
{ | |
if (!$model->getParentRelation()) { | |
if (count($model->getAttributesToUnset())) { | |
$model->drop($model->getAttributesToUnset()); | |
} | |
} | |
} | |
/** | |
* Get the attributes that have been removed since last sync in dot notation. | |
* Compare all attributes recursively by first converting to dot notation. | |
* | |
* @return array | |
*/ | |
public function getAttributesToUnset() | |
{ | |
$dirty = []; | |
foreach (array_dot_assoc($this->original) as $key => $value) { | |
if (($value !== [] && !array_has($this->getAttributes(), $key))) { | |
$dirty[] = $key; | |
} | |
} | |
return $dirty; | |
} | |
/** | |
* Get list of clearable attributes, or use Fillable if model does not define $clearable. | |
* | |
* @return mixed | |
*/ | |
public function getClearable() | |
{ | |
return $this->clearable && count($this->clearable) ? $this->clearable : $this->fillable; | |
} | |
/** | |
* Remove any attributes from the model that are in the $clearable or | |
* $fillable array, but are not present in $attributes | |
* | |
* @param $attributes | |
*/ | |
public function unsetClearable($attributes) | |
{ | |
foreach ($this->getClearable() as $field) { | |
if (isset($this->$field) && !isset($attributes[$field])) { | |
unset($this->$field); | |
} | |
} | |
} | |
/** | |
* Remove one or more fields (immediately). | |
* Call parent::__unset instead of $this so we don't unset the field twice | |
* | |
* @param mixed $columns | |
* @return int | |
*/ | |
public function drop($columns) | |
{ | |
if (!is_array($columns)) { | |
$columns = [$columns]; | |
} | |
// Unset attributes | |
foreach ($columns as $column) { | |
parent::__unset($column); | |
} | |
// Perform unset only on current document | |
return $this->newQuery()->where($this->getKeyName(), $this->getKey())->unset($columns); | |
} | |
/** | |
* Perform a model update operation. Check attributes to unset so events are fired and timestamps are updated. | |
* | |
* @see \Illuminate\Database\Eloquent\Model::performUpdate | |
* @param Builder $query | |
* @param array $options | |
* @return bool | |
*/ | |
protected function performUpdate(Builder $query, array $options = []) | |
{ | |
$dirty = array_merge($this->getDirty(), $this->getAttributesToUnset()); | |
if (count($dirty) > 0) { | |
// If the updating event returns false, we will cancel the update operation so | |
// developers can hook Validation systems into their models and cancel this | |
// operation if the model does not pass validation. Otherwise, we update. | |
if ($this->fireModelEvent('updating') === false) { | |
return false; | |
} | |
// First we need to create a fresh query instance and touch the creation and | |
// update timestamp on the model which are maintained by us for developer | |
// convenience. Then we will just continue saving the model instances. | |
if ($this->timestamps && Arr::get($options, 'timestamps', true)) { | |
$this->updateTimestamps(); | |
} | |
// Once we have run the update operation, we will fire the "updated" event for | |
// this model instance. This will allow developers to hook into these after | |
// models are updated, giving them a chance to do any special processing. | |
$dirty = $this->getDirty(); | |
if (count($dirty) > 0) { | |
$numRows = $this->setKeysForSaveQuery($query)->update($dirty); | |
$this->fireModelEvent('updated', false); | |
} | |
} | |
return true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment