diff --git a/.styleci.yml b/.styleci.yml
deleted file mode 100644
index 247a09c5..00000000
--- a/.styleci.yml
+++ /dev/null
@@ -1 +0,0 @@
-preset: psr2
diff --git a/composer.json b/composer.json
index 884b8f8f..5838c8a6 100644
--- a/composer.json
+++ b/composer.json
@@ -14,22 +14,29 @@
"name": "Austin Stierler",
"email": "austin.stierler@gmail.com",
"role": "Developer/Maintainer"
- }
+ },
+ {
+ "name": "Tarek Adam",
+ "email": "tarek.adam@gmail.com",
+ "role": "Contributor"
+ }
],
"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"
},
"autoload": {
- "classmap": [
- "src/migrations"
- ],
- "psr-0": {
- "Venturecraft\\Revisionable": "src/"
+ "psr-4": {
+ "Venturecraft\\Revisionable\\": "src/"
+ }
+ },
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Venturecraft\\Revisionable\\ServiceProvider"
+ ]
}
}
}
diff --git a/src/config/revisionable.php b/config/main.php
similarity index 60%
rename from src/config/revisionable.php
rename to config/main.php
index 4f6666b8..2ee9fd81 100644
--- a/src/config/revisionable.php
+++ b/config/main.php
@@ -6,5 +6,7 @@
| Revision Model
|--------------------------------------------------------------------------
*/
- 'model' => Venturecraft\Revisionable\Revision::class,
+ 'route-prefix' => 'revisions',
+ 'middleware' => ['web', 'auth'],
+ 'revisionable-model-binding' => []
];
diff --git a/src/migrations/2013_04_09_062329_create_revisions_table.php b/migrations/2013_04_09_062329_create_revisions_table.php
similarity index 100%
rename from src/migrations/2013_04_09_062329_create_revisions_table.php
rename to migrations/2013_04_09_062329_create_revisions_table.php
diff --git a/migrations/2018_05_01_114345_revisionable_add_accepted_at_timestamp.php b/migrations/2018_05_01_114345_revisionable_add_accepted_at_timestamp.php
new file mode 100644
index 00000000..38c56c8b
--- /dev/null
+++ b/migrations/2018_05_01_114345_revisionable_add_accepted_at_timestamp.php
@@ -0,0 +1,33 @@
+timestamp('accepted_at')->after('new_value');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::table('revisions', function (Blueprint $table) {
+ //
+ });
+ }
+}
diff --git a/resources/lang/en/validation.php b/resources/lang/en/validation.php
new file mode 100644
index 00000000..3b524522
--- /dev/null
+++ b/resources/lang/en/validation.php
@@ -0,0 +1,6 @@
+ 'Invalid model.',
+];
diff --git a/resources/views/history.blade.php b/resources/views/history.blade.php
new file mode 100644
index 00000000..98ff5692
--- /dev/null
+++ b/resources/views/history.blade.php
@@ -0,0 +1,14 @@
+@foreach($model->revisionHistory as $history)
+ @if($history->key == 'created_at' and !$history->old_value)
+
{{ (!empty($history->userResponsible()))? $history->userResponsible()->first_name : 'system' }} created this resource at {{ $history->newValue() }}
+ @else
+ {{ $history->userResponsible()->first_name }} changed {{ $history->fieldName() }} from
+ {{ $history->oldValue() }}
+ @if(is_null($history->oldValue()))
+ null
+ @endif
+
+ to {{ $history->newValue() }}
+
+ @endif
+@endforeach
diff --git a/routes/main.php b/routes/main.php
new file mode 100644
index 00000000..91441328
--- /dev/null
+++ b/routes/main.php
@@ -0,0 +1,13 @@
+ 'Venturecraft\Revisionable',
+ 'as' => Venturecraft\Revisionable\ServiceProvider::SHORT_NAME . '::',
+ 'prefix' => config(Venturecraft\Revisionable\ServiceProvider::SHORT_NAME . '.route-prefix'),
+ 'middleware' => config(Venturecraft\Revisionable\ServiceProvider::SHORT_NAME . '.middleware')];
+
+Route::group($config, function (){
+ Route::get('{revisionable}/history', [
+ 'as' => 'model-history',
+ 'uses' => 'Controller@modelHistory'
+ ]);
+});
\ No newline at end of file
diff --git a/src/Controller.php b/src/Controller.php
new file mode 100644
index 00000000..c29c784e
--- /dev/null
+++ b/src/Controller.php
@@ -0,0 +1,14 @@
+withModel($revisionable);
+ }
+
+}
diff --git a/src/Venturecraft/Revisionable/FieldFormatter.php b/src/FieldFormatter.php
similarity index 100%
rename from src/Venturecraft/Revisionable/FieldFormatter.php
rename to src/FieldFormatter.php
diff --git a/src/Venturecraft/Revisionable/Revision.php b/src/Revision.php
similarity index 91%
rename from src/Venturecraft/Revisionable/Revision.php
rename to src/Revision.php
index 498c743b..d0909b0e 100644
--- a/src/Venturecraft/Revisionable/Revision.php
+++ b/src/Revision.php
@@ -2,8 +2,10 @@
namespace Venturecraft\Revisionable;
-use Illuminate\Database\Eloquent\Model as Eloquent;
-use Illuminate\Support\Facades\Log;
+use Carbon\Carbon;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Str;
+
/**
* Revision.
@@ -13,13 +15,16 @@
*
* (c) Venture Craft
*/
-class Revision extends Eloquent
+class Revision extends Model
{
/**
* @var string
*/
public $table = 'revisions';
+ protected $dates = ['accepted_at'];
+
+
/**
* @var array
*/
@@ -31,6 +36,10 @@ class Revision extends Eloquent
public function __construct(array $attributes = array())
{
parent::__construct($attributes);
+
+ if(empty($this->attributes['accepted_at'])){
+ $this->attributes['accepted_at'] = Carbon::now();
+ }
}
/**
@@ -96,7 +105,7 @@ private function formatFieldName($key)
*/
public function oldValue()
{
- return $this->getValue('old');
+ $this->getValue('old');
}
@@ -163,7 +172,7 @@ private function getValue($which = 'new')
// Check if model use RevisionableTrait
if(method_exists($item, 'identifiableName')) {
// see if there's an available mutator
- $mutator = 'get' . studly_case($this->key) . 'Attribute';
+ $mutator = 'get' . Str::studly($this->key) . 'Attribute';
if (method_exists($item, $mutator)) {
return $this->format($item->$mutator($this->key), $item->identifiableName());
}
@@ -179,7 +188,7 @@ private function getValue($which = 'new')
// if there was an issue
// or, if it's a normal value
- $mutator = 'get' . studly_case($this->key) . 'Attribute';
+ $mutator = 'get' . Str::studly($this->key) . 'Attribute';
if (method_exists($main_model, $mutator)) {
return $this->format($this->key, $main_model->$mutator($this->$which_value));
}
@@ -233,10 +242,10 @@ public function userResponsible()
) {
return $class::findUserById($this->user_id);
} else {
- $user_model = app('config')->get('auth.model');
+ $user_model = config('auth.model');
if (empty($user_model)) {
- $user_model = app('config')->get('auth.providers.users.model');
+ $user_model = config('auth.providers.users.model');
if (empty($user_model)) {
return false;
}
@@ -289,4 +298,14 @@ public function format($key, $value)
return $value;
}
}
+
+ public function scopeOnlyPending($q)
+ {
+ $q->whereNull('accepted_at');
+ }
+
+ public function scopeOnlyAccepted($q)
+ {
+ $q->whereNotNull('accepted_at');
+ }
}
diff --git a/src/Venturecraft/Revisionable/Revisionable.php b/src/Revisionable.php
similarity index 96%
rename from src/Venturecraft/Revisionable/Revisionable.php
rename to src/Revisionable.php
index 82348834..b09fb07c 100644
--- a/src/Venturecraft/Revisionable/Revisionable.php
+++ b/src/Revisionable.php
@@ -1,6 +1,7 @@
morphMany(get_class(static::newModel()), 'revisionable');
+ return $this->morphMany(Revision::class, 'revisionable');
}
/**
@@ -153,7 +156,7 @@ public function postSave()
'revisionable_type' => $this->getMorphClass(),
'revisionable_id' => $this->getKey(),
'key' => $key,
- 'old_value' => array_get($this->originalData, $key),
+ 'old_value' => Arr::get($this->originalData, $key),
'new_value' => $this->updatedData[$key],
'user_id' => $this->getSystemUserId(),
'created_at' => new \DateTime(),
@@ -162,7 +165,7 @@ public function postSave()
}
if (count($revisions) > 0) {
- $revision = static::newModel();
+ $revision = new Revision;
\DB::table($revision->getTable())->insert($revisions);
}
}
@@ -195,7 +198,7 @@ public function postCreate()
'updated_at' => new \DateTime(),
);
- $revision = static::newModel();
+ $revision = new Revision;
\DB::table($revision->getTable())->insert($revisions);
}
}
@@ -218,7 +221,7 @@ public function postDelete()
'created_at' => new \DateTime(),
'updated_at' => new \DateTime(),
);
- $revision = static::newModel();
+ $revision = new Revision;
\DB::table($revision->getTable())->insert($revisions);
}
}
diff --git a/src/RevisionableResolver.php b/src/RevisionableResolver.php
new file mode 100644
index 00000000..da383877
--- /dev/null
+++ b/src/RevisionableResolver.php
@@ -0,0 +1,40 @@
+route = $route;
+ $this->binding_lookup = config(\Venturecraft\Revisionable\ServiceProvider::SHORT_NAME . '.revisionable-model-binding');
+ }
+
+ public function bind($revisionable){
+ list($alias, $id)= explode('-', $revisionable);
+ if(empty($this->binding_lookup[$alias])){
+ abort(404, 'No binding instruction found.');
+ }
+
+ $class = $this->binding_lookup[$alias];
+ return $class::findOrFail($id);
+ }
+
+}
diff --git a/src/Venturecraft/Revisionable/RevisionableTrait.php b/src/RevisionableTrait.php
similarity index 86%
rename from src/Venturecraft/Revisionable/RevisionableTrait.php
rename to src/RevisionableTrait.php
index b668bc58..7590353b 100644
--- a/src/Venturecraft/Revisionable/RevisionableTrait.php
+++ b/src/RevisionableTrait.php
@@ -7,6 +7,8 @@
*
*/
+use Illuminate\Support\Arr;
+
/**
* Class RevisionableTrait
* @package Venturecraft\Revisionable
@@ -85,12 +87,28 @@ public static function bootRevisionableTrait()
});
}
+ public function getRevisionableRouteParamAttribute(){
+ return strtolower(str_replace('\\', '-',static::class) .'-'. $this->getKey());
+ }
+
+
/**
* @return mixed
*/
public function revisionHistory()
{
- return $this->morphMany(get_class(Revisionable::newModel()), 'revisionable');
+ return $this->morphMany(Revision::class, 'revisionable');
+ }
+
+ /**
+ * Restrict the result to include only records which has pending revision
+ * history which are not accepted yet.
+ */
+ public function scopeHasPendingRevisionHistory($query)
+ {
+ $query->whereHas('revisionHistory', function($q){
+ $q->whereNull('accepted_at');
+ });
}
/**
@@ -102,7 +120,7 @@ public function revisionHistory()
*/
public static function classRevisionHistory($limit = 100, $order = 'desc')
{
- $model = Revisionable::newModel();
+ $model = new Revision;
return $model->where('revisionable_type', get_called_class())
->orderBy('updated_at', $order)->limit($limit)->get();
}
@@ -118,7 +136,9 @@ public function preSave()
// if there's no revisionEnabled. Or if there is, if it's true
$this->originalData = $this->original;
+
$this->updatedData = $this->attributes;
+ $this->updating = $this->exists;
// we can only safely compare basic items,
// so for now we drop any object based items, like DateTime
@@ -144,7 +164,17 @@ public function preSave()
unset($this->attributes['keepRevisionOf']);
$this->dirtyData = $this->getDirty();
- $this->updating = $this->exists;
+
+ $changes_to_record = $this->changedRevisionableFields();
+ foreach ($changes_to_record as $key => $value) {
+ if($this->updating && !empty($this->autoAccept) && $this->autoAccept == false && !empty($this->keepRevisionOf) && in_array($key, $this->keepRevisionOf)){
+ if(isset($this->originalData[$key])){
+ \Log::debug('Changing value for key '.$key);
+ $this->attributes[$key] = $this->originalData[$key];
+ }
+ }
+ }
+
}
}
@@ -180,24 +210,31 @@ public function postSave()
'revisionable_type' => $this->getMorphClass(),
'revisionable_id' => $this->getKey(),
'key' => $key,
- 'old_value' => array_get($this->originalData, $key),
+ 'old_value' => Arr::get($this->originalData, $key),
'new_value' => $this->updatedData[$key],
'user_id' => $this->getSystemUserId(),
'created_at' => new \DateTime(),
'updated_at' => new \DateTime(),
+ 'accepted_at' => new \DateTime()
);
}
if (count($revisions) > 0) {
if($LimitReached && $RevisionCleanup){
- $toDelete = $this->revisionHistory()->orderBy('id','asc')->limit(count($revisions))->get();
+ $columns = collect($revisions)->pluck('key');
+ $toDelete = $this->revisionHistory()
+ ->whereIn('key', $columns)
+ ->orderBy('id','asc')
+ ->limit(count($revisions))
+ ->get();
+
foreach($toDelete as $delete){
$delete->delete();
}
}
- $revision = Revisionable::newModel();
+ $revision = new Revision;
\DB::table($revision->getTable())->insert($revisions);
- \Event::fire('revisionable.saved', array('model' => $this, 'revisions' => $revisions));
+ \Event::dispatch('revisionable.saved', array('model' => $this, 'revisions' => $revisions));
}
}
}
@@ -227,11 +264,13 @@ public function postCreate()
'user_id' => $this->getSystemUserId(),
'created_at' => new \DateTime(),
'updated_at' => new \DateTime(),
+ 'accepted_at' => new \DateTime()
+
);
- $revision = Revisionable::newModel();
+ $revision = new Revision;
\DB::table($revision->getTable())->insert($revisions);
- \Event::fire('revisionable.created', array('model' => $this, 'revisions' => $revisions));
+ \Event::dispatch('revisionable.created', array('model' => $this, 'revisions' => $revisions));
}
}
@@ -255,9 +294,9 @@ public function postDelete()
'created_at' => new \DateTime(),
'updated_at' => new \DateTime(),
);
- $revision = Revisionable::newModel();
+ $revision = new Revision;
\DB::table($revision->getTable())->insert($revisions);
- \Event::fire('revisionable.deleted', array('model' => $this, 'revisions' => $revisions));
+ \Event::dispatch('revisionable.deleted', array('model' => $this, 'revisions' => $revisions));
}
}
diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php
new file mode 100644
index 00000000..0b7c5046
--- /dev/null
+++ b/src/ServiceProvider.php
@@ -0,0 +1,51 @@
+loadMigrationsFrom(__DIR__ . '/../migrations');
+ $this->publishes([__DIR__ . '/../config/main.php' => config_path(SELF::SHORT_NAME . '.php')]);
+ $this->mergeConfigFrom(
+ __DIR__ . '/../config/main.php', SELF::SHORT_NAME
+ );
+
+ $this->loadViewsFrom(__DIR__ . '/../resources/views', self::SHORT_NAME);
+ $this->publishes([__DIR__ . '/../resources/views' => resource_path('views/vendor/' . self::SHORT_NAME)], 'views');
+
+ $this->loadRoutesFrom(__DIR__ . '/../routes/main.php');
+
+ $this->loadTranslationsFrom(__DIR__ . '/../resources/lang', self::SHORT_NAME);
+ $this->publishes([__DIR__ . '/../resources/lang' => resource_path('lang/vendor/' . self::SHORT_NAME)], 'lang');
+
+ Route::bind('revisionable', RevisionableResolver::class);
+
+ }
+
+ /**
+ * Register the application services.
+ *
+ * @return void
+ */
+ public function register(){
+
+ }
+
+}
diff --git a/src/Venturecraft/Revisionable/RevisionableServiceProvider.php b/src/Venturecraft/Revisionable/RevisionableServiceProvider.php
deleted file mode 100644
index fb9fec26..00000000
--- a/src/Venturecraft/Revisionable/RevisionableServiceProvider.php
+++ /dev/null
@@ -1,42 +0,0 @@
-publishes([
- __DIR__ . '/../../config/revisionable.php' => config_path('revisionable.php'),
- ], 'config');
-
- $this->publishes([
- __DIR__ . '/../../migrations/' => database_path('migrations'),
- ], 'migrations');
- }
-
- /**
- * Register the application services.
- *
- * @return void
- */
- public function register()
- {
- }
-
- /**
- * Get the services provided by the provider.
- *
- * @return string[]
- */
- public function provides()
- {
- }
-}