-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Getting recusrive cloning working with functional tests
- Loading branch information
Showing
13 changed files
with
372 additions
and
13 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
/vendor/ | ||
composer.lock | ||
.DS_Store | ||
.DS_Store | ||
node_modules |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,32 @@ | ||
{ | ||
"name": "bkwld/cloner", | ||
"description": "A trait for Laravel Eloquent models that allows for recursive (via relationships) cloning of a model, including files (via BKWLD/upchuck)", | ||
"require-dev": { | ||
"illuminate/database": "^4.0" | ||
}, | ||
"license": "MIT", | ||
"authors": [ | ||
{ | ||
"name": "Robert Reinhard", | ||
"email": "[email protected]" | ||
} | ||
] | ||
"name": "bkwld/cloner", | ||
"description": "A trait for Laravel Eloquent models that allows for recursive (via relationships) cloning of a model, including files (via BKWLD/upchuck)", | ||
"require": { | ||
"php": ">=5.4.0", | ||
"illuminate/support": "~4.0" | ||
}, | ||
"require-dev": { | ||
"phpunit/phpunit": "~4.7", | ||
"illuminate/database": "~4.0" | ||
}, | ||
"suggest": { | ||
"bkwld/upchuck": "Required for replicating of files." | ||
}, | ||
"autoload": { | ||
"psr-4": { | ||
"Bkwld\\Cloner\\": "src/" | ||
} | ||
}, | ||
"autoload-dev": { | ||
"psr-4": { | ||
"Bkwld\\Cloner\\Stubs\\": "stubs/" | ||
} | ||
}, | ||
"license": "MIT", | ||
"authors": [ | ||
{ | ||
"name": "Robert Reinhard", | ||
"email": "[email protected]" | ||
} | ||
] | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
var gulp = require('gulp') | ||
, phpunit = require('gulp-phpunit') | ||
; | ||
|
||
// PHPunit | ||
gulp.task('phpunit', function() { | ||
var options = { | ||
debug: false | ||
, clear: true | ||
}; | ||
gulp | ||
.src('phpunit.xml') | ||
.pipe(phpunit('./vendor/phpunit/phpunit/phpunit', options)) | ||
.on('error', function(){}) | ||
; | ||
}); | ||
|
||
// Watch files | ||
gulp.task('watch', function () { | ||
gulp.watch('**/*.php', ['phpunit']); | ||
}); | ||
|
||
// Default task | ||
gulp.task('default', ['watch']); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"name": "Cloner", | ||
"version": "1.0.0", | ||
"license": "MIT", | ||
"devDependencies": { | ||
"gulp": "^3.9.0", | ||
"gulp-phpunit": "^0.8.1" | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<phpunit backupGlobals="false" | ||
backupStaticAttributes="false" | ||
bootstrap="vendor/autoload.php" | ||
colors="true" | ||
convertErrorsToExceptions="true" | ||
convertNoticesToExceptions="true" | ||
convertWarningsToExceptions="true" | ||
processIsolation="false" | ||
stopOnFailure="false" | ||
syntaxCheck="false" | ||
> | ||
<testsuites> | ||
<testsuite name="Package Test Suite"> | ||
<directory suffix=".php">./tests/</directory> | ||
</testsuite> | ||
</testsuites> | ||
</phpunit> |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<?php namespace Bkwld\Cloner; | ||
|
||
interface AttachmentAdapter { | ||
|
||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<?php namespace Bkwld\Cloner; | ||
|
||
trait Cloneable { | ||
|
||
/** | ||
* Return the list of attributes on this model that should be cloned | ||
* | ||
* @return array | ||
*/ | ||
public function getCloneExemptAttributes() { | ||
if (!isset($this->clone_except_attributes)) return []; | ||
return $this->clone_except_attributes; | ||
} | ||
|
||
/** | ||
* Return the list of relations on this model that should be cloned | ||
* | ||
* @return array | ||
*/ | ||
public function getCloneableRelations() { | ||
if (!isset($this->cloneable_relations)) return []; | ||
return $this->cloneable_relations; | ||
} | ||
|
||
/** | ||
* A no-op callback that gets fired when a model is cloning but before it gets | ||
* committed to the database | ||
* | ||
* @return void | ||
*/ | ||
public function onCloning() {} | ||
|
||
/** | ||
* A no-op callback that gets fired when a model is cloned and saved to the | ||
* database | ||
* | ||
* @return void | ||
*/ | ||
public function onCloned() {} | ||
|
||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
<?php namespace Bkwld\Cloner; | ||
|
||
/** | ||
* Core class that traverses a model's relationships and replicates model | ||
* attributes | ||
*/ | ||
class Cloner { | ||
|
||
/** | ||
* @var AttachmentAdapter | ||
*/ | ||
private $attachment_adapter; | ||
|
||
/** | ||
* DI | ||
* | ||
* @param AttachmentAdapter $attachment_adapter | ||
*/ | ||
public function __construct( | ||
AttachmentAdapter $attachment_adapter = null) { | ||
$this->attachment_adapter = $attachment_adapter; | ||
} | ||
|
||
/** | ||
* Clone a model instance and all of it's files and relations | ||
* | ||
* @param Illuminate\Database\Eloquent\Model $model | ||
* @param Illuminate\Database\Eloquent\Relations\Relation $relation | ||
* @return Illuminate\Database\Eloquent\Model The new model instance | ||
*/ | ||
public function duplicate($model, $relation = null) { | ||
|
||
// Duplicate the model | ||
$clone = $model->replicate($model->getCloneExemptAttributes()); | ||
$clone->onCloning(); | ||
if ($relation) $relation->save($clone); | ||
else $clone->save(); | ||
$clone->onCloned(); | ||
|
||
// Loop though all of it's cloneable relationshsips and duplicate the | ||
// relationship | ||
foreach($model->getCloneableRelations() as $relation_name) { | ||
$this->duplicateRelation($model, $relation_name, $clone); | ||
} | ||
|
||
// Return the duplicated model | ||
return $clone; | ||
|
||
} | ||
|
||
/** | ||
* Duplicate relationships to the clone | ||
* | ||
* @param Illuminate\Database\Eloquent\Model $model | ||
* @param string $relation_name | ||
* @param Illuminate\Database\Eloquent\Model $clone | ||
* @return void | ||
*/ | ||
public function duplicateRelation($model, $relation_name, $clone) { | ||
$relation = call_user_func([$model, $relation_name]); | ||
if (is_a($relation, 'Illuminate\Database\Eloquent\Relations\BelongsToMany')) { | ||
$this->duplicatePivotedRelation($relation, $relation_name, $clone); | ||
} else $this->duplicateDirectRelation($relation, $relation_name, $clone); | ||
} | ||
|
||
/** | ||
* Duplicate a many-to-many style relation where we are just attaching the | ||
* relation to the dupe | ||
* | ||
* @param Illuminate\Database\Eloquent\Relations\Relation $relation | ||
* @param string $relation_name | ||
* @param Illuminate\Database\Eloquent\Model $clone | ||
* @return void | ||
*/ | ||
public function duplicatePivotedRelation($relation, $relation_name, $clone) { | ||
$relation->get()->each(function($foreign) use ($clone, $relation_name) { | ||
$clone->$relation_name()->attach($foreign); | ||
}); | ||
} | ||
|
||
/** | ||
* Duplicate a one-to-many style relation where the foreign model is ALSO | ||
* cloned and then associated | ||
* | ||
* @param Illuminate\Database\Eloquent\Relations\Relation $relation | ||
* @param string $relation_name | ||
* @param Illuminate\Database\Eloquent\Model $clone | ||
* @return void | ||
*/ | ||
public function duplicateDirectRelation($relation, $relation_name, $clone) { | ||
$relation->get()->each(function($foreign) use ($clone, $relation_name) { | ||
$this->duplicate($foreign, $clone->$relation_name()); | ||
}); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<?php namespace Bkwld\Cloner\Stubs; | ||
|
||
use Bkwld\Cloner\Cloneable as Cloneable; | ||
use Illuminate\Database\Eloquent\Model; | ||
|
||
class Article extends Model { | ||
use Cloneable; | ||
|
||
public $clone_except_attributes; | ||
public $cloneable_relations = ['photos', 'authors']; | ||
|
||
public function photos() { | ||
return $this->hasMany('Bkwld\Cloner\Stubs\Photo'); | ||
} | ||
|
||
public function authors() { | ||
return $this->belongsToMany('Bkwld\Cloner\Stubs\Author'); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?php namespace Bkwld\Cloner\Stubs; | ||
|
||
use Bkwld\Cloner\Cloneable as Cloneable; | ||
use Illuminate\Database\Eloquent\Model; | ||
|
||
class Author extends Model { | ||
use Cloneable; | ||
|
||
public $clone_except_attributes; | ||
|
||
public function articles() { | ||
return $this->belongsToMany('Bkwld\Cloner\Stubs\Article'); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?php namespace Bkwld\Cloner\Stubs; | ||
|
||
use Bkwld\Cloner\Cloneable as Cloneable; | ||
use Illuminate\Database\Eloquent\Model; | ||
|
||
class Photo extends Model { | ||
use Cloneable; | ||
|
||
public $clone_except_attributes; | ||
|
||
public function article() { | ||
return $this->belongsTo('Bkwld\Cloner\Stubs\Article'); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Models to run automated tests against. | ||
|
||
I went this approach so that I could test the trait. |
Oops, something went wrong.