diff --git a/composer.json b/composer.json index 8ec2fa76..440a4a52 100644 --- a/composer.json +++ b/composer.json @@ -1,45 +1,52 @@ -{ - "name": "venturecraft/revisionable", - "license": "MIT", - "description": "Keep a revision history for your models without thinking, created as a package for use with Laravel", - "keywords": ["model", "laravel", "ardent", "revision", "audit", "history"], - "homepage": "http://github.com/venturecraft/revisionable", - "authors": [ - { - "name": "Chris Duell", - "email": "me@chrisduell.com" - } - ], - "support": { - "issues": "https://github.com/VentureCraft/revisionable/issues", - "source": "https://github.com/VentureCraft/revisionable" - }, - "require": { - "php": ">=5.4.0", - "illuminate/support": "~4.0|~5.0|~5.1|^6.0|^7.0|^8.0", - "laravel/framework": "~5.4|^6.0|^7.0|^8.0" - }, - "autoload": { - "classmap": [ - "src/migrations" - ], - "psr-0": { - "Venturecraft\\Revisionable": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "Venturecraft\\Revisionable\\Tests\\": "tests/" - } - }, - "require-dev": { - "orchestra/testbench": "~3.0" - }, - "extra": { - "laravel": { - "providers": [ - "Venturecraft\\Revisionable\\RevisionableServiceProvider" - ] - } - } -} +{ + "name": "venturecraft/revisionable", + "license": "MIT", + "description": "Keep a revision history for your models without thinking, created as a package for use with Laravel", + "keywords": [ + "model", + "laravel", + "ardent", + "revision", + "audit", + "history" + ], + "homepage": "http://github.com/venturecraft/revisionable", + "authors": [ + { + "name": "Chris Duell", + "email": "me@chrisduell.com" + } + ], + "support": { + "issues": "https://github.com/VentureCraft/revisionable/issues", + "source": "https://github.com/VentureCraft/revisionable" + }, + "require": { + "php": ">=5.4.0", + "illuminate/support": "~4.0|~5.0|~5.1|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", + "laravel/framework": "~5.4|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0" + }, + "autoload": { + "classmap": [ + "src/migrations" + ], + "psr-0": { + "Venturecraft\\Revisionable": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Venturecraft\\Revisionable\\Tests\\": "tests/" + } + }, + "require-dev": { + "orchestra/testbench": "~3.0|^8.0|^9.0" + }, + "extra": { + "laravel": { + "providers": [ + "Venturecraft\\Revisionable\\RevisionableServiceProvider" + ] + } + } +} diff --git a/readme.md b/readme.md index 46ba578d..0e85c25b 100644 --- a/readme.md +++ b/readme.md @@ -162,6 +162,18 @@ To better format the output for `deleted_at` entries, you can use the `isEmpty` +### Storing Force Delete +By default the Force Delete of a model is not stored as a revision. + +If you want to store the Force Delete as a revision you can override this behavior by setting `revisionForceDeleteEnabled ` to `true` by adding the following to your model: +```php +protected $revisionForceDeleteEnabled = true; +``` + +In which case, the `created_at` field will be stored as a key with the `oldValue()` value equal to the model creation date and the `newValue()` value equal to `null`. + +**Attention!** Turn on this setting carefully! Since the model saved in the revision, now does not exist, so you will not be able to get its object or its relations. + ### Storing Creations By default the creation of a new model is not stored as a revision. Only subsequent changes to a model is stored. @@ -271,7 +283,7 @@ Analogous to "boolean", only any text or numeric values can act as a source valu Look at this as an associative array in which the key is separated from the value by a dot. Array elements are separated by a vertical line. ``` -options: search.On the search|network.In networks +options:search.On the search|network.In networks ``` ### DateTime @@ -332,7 +344,7 @@ If you have enabled revisions of creations as well you can display it like this: ### userResponsible() -Returns the User that was responsible for making the revision. A user model is returned, or null if there was no user recorded. +Returns the User that was responsible for making the revision. A user model is returned, or false if there was no user recorded. The user model that is loaded depends on what you have set in your `config/auth.php` file for the `model` variable. diff --git a/src/Venturecraft/Revisionable/Revisionable.php b/src/Venturecraft/Revisionable/Revisionable.php index 04e5986e..21f7f4e4 100644 --- a/src/Venturecraft/Revisionable/Revisionable.php +++ b/src/Venturecraft/Revisionable/Revisionable.php @@ -72,6 +72,7 @@ public static function boot() static::deleted(function ($model) { $model->preSave(); $model->postDelete(); + $model->postForceDelete(); }); } /** @@ -80,7 +81,12 @@ public static function boot() */ public static function newModel() { - $model = \Config::get('revisionable.model', 'Venturecraft\Revisionable\Revision'); + $model = app('config')->get('revisionable.model'); + + if (! $model) { + $model = 'Venturecraft\Revisionable\Revision'; + } + return new $model; } @@ -164,7 +170,8 @@ public function postSave() if (count($revisions) > 0) { $revision = static::newModel(); - \DB::table($revision->getTable())->insert($revisions); + // \DB::table($revision->getTable())->insert($revisions); + $revision->insert($revisions); } } } @@ -197,7 +204,8 @@ public function postCreate() ); $revision = static::newModel(); - \DB::table($revision->getTable())->insert($revisions); + // \DB::table($revision->getTable())->insert($revisions); + $revision->insert($revisions); } } @@ -220,7 +228,40 @@ public function postDelete() 'updated_at' => new \DateTime(), ); $revision = static::newModel(); - \DB::table($revision->getTable())->insert($revisions); + // \DB::table($revision->getTable())->insert($revisions); + $revision->insert($revisions); + } + } + + /** + * If forcedeletes are enabled, set the value created_at of model to null + * + * @return void|bool + */ + public function postForceDelete() + { + if (empty($this->revisionForceDeleteEnabled)) { + return false; + } + + if ((!isset($this->revisionEnabled) || $this->revisionEnabled) + && (($this->isSoftDelete() && $this->isForceDeleting()) || !$this->isSoftDelete())) { + + $revisions[] = array( + 'revisionable_type' => $this->getMorphClass(), + 'revisionable_id' => $this->getKey(), + 'key' => self::CREATED_AT, + 'old_value' => $this->{self::CREATED_AT}, + 'new_value' => null, + 'user_id' => $this->getSystemUserId(), + 'created_at' => new \DateTime(), + 'updated_at' => new \DateTime(), + ); + + $revision = Revisionable::newModel(); + // \DB::table($revision->getTable())->insert($revisions); + $revision->insert($revisions); + \Event::dispatch('revisionable.deleted', array('model' => $this, 'revisions' => $revisions)); } } diff --git a/src/Venturecraft/Revisionable/RevisionableTrait.php b/src/Venturecraft/Revisionable/RevisionableTrait.php index 4f6fe2b6..a56fde57 100644 --- a/src/Venturecraft/Revisionable/RevisionableTrait.php +++ b/src/Venturecraft/Revisionable/RevisionableTrait.php @@ -84,6 +84,7 @@ public static function bootRevisionableTrait() static::deleted(function ($model) { $model->preSave(); $model->postDelete(); + $model->postForceDelete(); }); } @@ -125,7 +126,8 @@ public function preSave() // we can only safely compare basic items, // so for now we drop any object based items, like DateTime foreach ($this->updatedData as $key => $val) { - if (isset($this->casts[$key]) && in_array($this->casts[$key], ['object', 'array']) && isset($this->originalData[$key])) { + $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 @@ -208,7 +210,8 @@ public function postSave() } } $revision = Revisionable::newModel(); - \DB::table($revision->getTable())->insert($revisions); + // \DB::table($revision->getTable())->insert($revisions); + $revision->insert($revisions); \Event::dispatch('revisionable.saved', array('model' => $this, 'revisions' => $revisions)); } } @@ -246,7 +249,8 @@ public function postCreate() $revisions = array_merge($revisions[0], $this->getAdditionalFields()); $revision = Revisionable::newModel(); - \DB::table($revision->getTable())->insert($revisions); + // \DB::table($revision->getTable())->insert($revisions); + $revision->insert($revisions); \Event::dispatch('revisionable.created', array('model' => $this, 'revisions' => $revisions)); } @@ -276,7 +280,40 @@ public function postDelete() $revisions = array_merge($revisions[0], $this->getAdditionalFields()); $revision = Revisionable::newModel(); - \DB::table($revision->getTable())->insert($revisions); + // \DB::table($revision->getTable())->insert($revisions); + $revision->insert($revisions); + \Event::dispatch('revisionable.deleted', array('model' => $this, 'revisions' => $revisions)); + } + } + + /** + * If forcedeletes are enabled, set the value created_at of model to null + * + * @return void|bool + */ + public function postForceDelete() + { + if (empty($this->revisionForceDeleteEnabled)) { + return false; + } + + if ((!isset($this->revisionEnabled) || $this->revisionEnabled) + && (($this->isSoftDelete() && $this->isForceDeleting()) || !$this->isSoftDelete())) { + + $revisions[] = array( + 'revisionable_type' => $this->getMorphClass(), + 'revisionable_id' => $this->getKey(), + 'key' => self::CREATED_AT, + 'old_value' => $this->{self::CREATED_AT}, + 'new_value' => null, + 'user_id' => $this->getSystemUserId(), + 'created_at' => new \DateTime(), + 'updated_at' => new \DateTime(), + ); + + $revision = Revisionable::newModel(); + // \DB::table($revision->getTable())->insert($revisions); + $revision->insert($revisions); \Event::dispatch('revisionable.deleted', array('model' => $this, 'revisions' => $revisions)); } } @@ -293,6 +330,8 @@ public function getSystemUserId() || class_exists($class = '\Cartalyst\Sentinel\Laravel\Facades\Sentinel') ) { return ($class::check()) ? $class::getUser()->id : null; + } elseif (function_exists('backpack_auth') && backpack_auth()->check()) { + return backpack_user()->id; } elseif (\Auth::check()) { return \Auth::user()->getAuthIdentifier(); } diff --git a/src/migrations/2013_04_09_062329_create_revisions_table.php b/src/migrations/2013_04_09_062329_create_revisions_table.php index fdd5b1e8..8d3d2d2a 100644 --- a/src/migrations/2013_04_09_062329_create_revisions_table.php +++ b/src/migrations/2013_04_09_062329_create_revisions_table.php @@ -12,10 +12,10 @@ class CreateRevisionsTable extends Migration public function up() { Schema::create('revisions', function ($table) { - $table->increments('id'); + $table->bigIncrements('id'); $table->string('revisionable_type'); - $table->integer('revisionable_id'); - $table->integer('user_id')->nullable(); + $table->unsignedBigInteger('revisionable_id'); + $table->unsignedBigInteger('user_id')->nullable(); $table->string('key'); $table->text('old_value')->nullable(); $table->text('new_value')->nullable(); @@ -32,6 +32,6 @@ public function up() */ public function down() { - Schema::drop('revisions'); + Schema::dropIfExists('revisions'); } }