Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DEV-1859] Feature - Upgrade to Laravel 8 #2

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
/vendor
composer.lock
/.idea
.phpunit.result.cache
101 changes: 54 additions & 47 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,47 +1,54 @@
{
"name": "roomroster/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": "RoomRoster",
"email": "[email protected]"
}
],
"require": {
"php": ">=5.4.0",
"illuminate/support": "~4.0|~5.0|~5.1|^6.0|^7.0",
"laravel/framework": "~5.4|^6.0|^7.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"
]
}
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/RoomRoster/revisionable.git"
}
]
}
{
"name": "roomroster/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": "RoomRoster",
"email": "[email protected]"
}
],
"require": {
"php": ">=5.4.0",
"illuminate/support": "~4.0|~5.0|~5.1|^6.0|^7.0|^8.0|^9.0|^10.0",
"laravel/framework": "~5.4|^6.0|^7.0|^8.0|^9.0|^10.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"
},
"extra": {
"laravel": {
"providers": [
"Venturecraft\\Revisionable\\RevisionableServiceProvider"
]
}
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/RoomRoster/revisionable.git"
}
]
}
33 changes: 29 additions & 4 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
<img src="https://cdn1.wwe.com/static/ossimg/revisionableghbanner.png" style="width: 100%" alt="Revisionable for Laravel" />

[![Laravel 4.x](https://img.shields.io/badge/Laravel-4.x-yellow.svg?style=flat-square)](https://laravel.com/)
[![Laravel 5.2](https://img.shields.io/badge/Laravel-5.x-brightgreen.svg?style=flat-square)](https://laravel.com/)
[![Latest Version](https://img.shields.io/github/release/venturecraft/revisionable.svg?style=flat-square)](https://packagist.org/packages/venturecraft/revisionable)
[![Downloads](https://img.shields.io/packagist/dt/venturecraft/revisionable.svg?style=flat-square)](https://packagist.org/packages/venturecraft/revisionable)
[![License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](https://tldrlegal.com/license/mit-license)
Expand Down Expand Up @@ -164,6 +162,18 @@ To better format the output for `deleted_at` entries, you can use the `isEmpty`

<a name="control"></a>

### 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.
Expand All @@ -189,6 +199,21 @@ protected $dontKeepRevisionOf = ['category_id'];

> The `$keepRevisionOf` setting takes precedence over `$dontKeepRevisionOf`

### Storing additional fields in revisions

In some cases, you'll want additional metadata from the models in each revision. An example of this might be if you
have to keep track of accounts as well as users. Simply create your own new migration to add the fields you'd like to your revision model,
add them to your config/revisionable.php in an array like so:

```php
'additional_fields' => ['account_id', 'permissions_id', 'other_id'],
```

If the column exists in the model, it will be included in the revision.

Make sure that if you can't guarantee the column in every model, you make that column ```nullable()``` in your migrations.


### Events

Every time a model revision is created an event is fired. You can listen for `revisionable.created`,
Expand Down Expand Up @@ -258,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
Expand Down Expand Up @@ -319,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.

Expand Down
41 changes: 40 additions & 1 deletion src/Venturecraft/Revisionable/Revisionable.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public static function boot()
static::deleted(function ($model) {
$model->preSave();
$model->postDelete();
$model->postForceDelete();
});
}
/**
Expand All @@ -82,7 +83,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;
}

Expand Down Expand Up @@ -226,6 +232,37 @@ public function postDelete()
}
}

/**
* 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);
\Event::dispatch('revisionable.deleted', array('model' => $this, 'revisions' => $revisions));
}
}

/**
* Attempt to find the user id of the currently logged in user
* Supports Cartalyst Sentry/Sentinel based authentication, as well as stock Auth
Expand All @@ -236,6 +273,8 @@ private function getSystemUserId()
if (class_exists($class = '\Cartalyst\Sentry\Facades\Laravel\Sentry')
|| 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();
}
Expand Down
65 changes: 63 additions & 2 deletions src/Venturecraft/Revisionable/RevisionableTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ public static function bootRevisionableTrait()
static::deleted(function ($model) {
$model->preSave();
$model->postDelete();
$model->postForceDelete();
});
}

Expand Down Expand Up @@ -127,7 +128,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

Expand Down Expand Up @@ -188,7 +190,7 @@ public function postSave()
$revisions = array();

foreach ($changes_to_record as $key => $change) {
$revisions[] = array(
$original = array(
'revisionable_type' => $this->getMorphClass(),
'revisionable_id' => $this->getKey(),
'key' => $key,
Expand All @@ -198,6 +200,8 @@ public function postSave()
'created_at' => new \DateTime(),
'updated_at' => new \DateTime(),
);

$revisions[] = array_merge($original, $this->getAdditionalFields());
}

if (count($revisions) > 0) {
Expand Down Expand Up @@ -241,6 +245,10 @@ public function postCreate()
'updated_at' => new \DateTime(),
);

//Determine if there are any additional fields we'd like to add to our model contained in the config file, and
//get them into an array.
$revisions = array_merge($revisions[0], $this->getAdditionalFields());

$revision = Revisionable::newModel();
\DB::table($revision->getTable())->insert($revisions);
\Event::dispatch('revisionable.created', array('model' => $this, 'revisions' => $revisions));
Expand All @@ -267,6 +275,41 @@ public function postDelete()
'created_at' => new \DateTime(),
'updated_at' => new \DateTime(),
);

//Since there is only one revision because it's deleted, let's just merge into revision[0]
$revisions = array_merge($revisions[0], $this->getAdditionalFields());

$revision = Revisionable::newModel();
\DB::table($revision->getTable())->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);
\Event::dispatch('revisionable.deleted', array('model' => $this, 'revisions' => $revisions));
Expand All @@ -285,6 +328,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();
}
Expand All @@ -295,6 +340,22 @@ public function getSystemUserId()
return null;
}


public function getAdditionalFields()
{
$additional = [];
//Determine if there are any additional fields we'd like to add to our model contained in the config file, and
//get them into an array.
$fields = config('revisionable.additional_fields', []);
foreach($fields as $field) {
if(Arr::has($this->originalData, $field)) {
$additional[$field] = Arr::get($this->originalData, $field);
}
}

return $additional;
}

/**
* Get all of the changes that have been made, that are also supposed
* to have their changes recorded
Expand Down
3 changes: 3 additions & 0 deletions src/config/revisionable.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@
|--------------------------------------------------------------------------
*/
'model' => Venturecraft\Revisionable\Revision::class,

'additional_fields' => [],

];
8 changes: 4 additions & 4 deletions src/migrations/2013_04_09_062329_create_revisions_table.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -32,6 +32,6 @@ public function up()
*/
public function down()
{
Schema::drop('revisions');
Schema::dropIfExists('revisions');
}
}
Loading