Last active
March 14, 2020 16:09
-
-
Save palypster/100e4e0babcc4a4250811a7bdd27b7ca to your computer and use it in GitHub Desktop.
This file contains hidden or 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 | |
namespace App; | |
use Illuminate\Database\Eloquent\Factory; | |
class ExtendedFactory extends Factory { | |
/** | |
* The registered after creating callbacks. | |
* | |
* @var array | |
*/ | |
protected $beforeCreating = []; | |
/** | |
* Define a callback to run before creating a model. | |
* | |
* @param string $class | |
* @param callable $callback | |
* @param string $name | |
* @return $this | |
*/ | |
public function beforeCreating($class, callable $callback, $name = 'default') | |
{ | |
$this->beforeCreating[$class][$name][] = $callback; | |
return $this; | |
} | |
/** | |
* Define a callback to run before creating a model with given state. | |
* | |
* @param string $class | |
* @param string $state | |
* @param callable $callback | |
* @return $this | |
*/ | |
public function beforeCreatingState($class, $state, callable $callback) | |
{ | |
return $this->beforeCreating($class, $callback, $state); | |
} | |
/** | |
* Create a builder for the given model. | |
* | |
* @param string $class | |
* @return \Illuminate\Database\Eloquent\FactoryBuilder | |
*/ | |
public function of($class) | |
{ | |
return new ExtendedFactoryBuilder( | |
$class, $this->definitions, $this->states, | |
$this->afterMaking, $this->afterCreating, $this->beforeCreating, $this->faker | |
); | |
} | |
public function cascade($class, callable $callback) | |
{ | |
return $this->cascadeState($class, 'default', $callback); | |
} | |
public function reuse($class, callable $callback) | |
{ | |
return $this->reuseState($class, 'default', $callback); | |
} | |
public function cascadeState($class, $state, callable $callback) | |
{ | |
return $this->beforeCreatingState($class, 'cascade-' . $state, $callback); | |
} | |
public function reuseState($class, $state, callable $callback) | |
{ | |
return $this->afterMakingState($class, 'reuse-' . $state, $callback); | |
} | |
} |
This file contains hidden or 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 | |
namespace App; | |
use Faker\Generator as Faker; | |
use Illuminate\Database\Eloquent\FactoryBuilder; | |
use Illuminate\Database\Eloquent\Model; | |
class ExtendedFactoryBuilder extends FactoryBuilder | |
{ | |
/** | |
* @var array | |
*/ | |
private $beforeCreating = []; | |
public function __construct($class, array $definitions, array $states, | |
array $afterMaking, array $afterCreating, array $beforeCreating, Faker $faker) | |
{ | |
parent::__construct($class, $definitions, $states, $afterMaking, $afterCreating, $faker); | |
$this->beforeCreating = $beforeCreating; | |
} | |
/** | |
* Create a collection of models and persist them to the database. | |
* | |
* @param array $attributes | |
* @return \Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Eloquent\Model|mixed | |
*/ | |
public function create(array $attributes = []) | |
{ | |
$results = $this->make($attributes); | |
if ($results instanceof Model) { | |
$this->callBeforeCreating(collect([$results])); | |
$this->store(collect([$results])); | |
$this->callAfterCreating(collect([$results])); | |
} else { | |
$this->callBeforeCreating(collect([$results])); | |
$this->store($results); | |
$this->callAfterCreating($results); | |
} | |
return $results; | |
} | |
/** | |
* Run before creating callbacks on a collection of models. | |
* | |
* @param \Illuminate\Support\Collection $models | |
* @return void | |
*/ | |
public function callBeforeCreating($models) | |
{ | |
$this->callBefore($this->beforeCreating, $models); | |
} | |
/** | |
* Call before callbacks for each model and state. | |
* | |
* @param array $beforeCallbacks | |
* @param \Illuminate\Support\Collection $models | |
* @return void | |
*/ | |
protected function callBefore(array $beforeCallbacks, $models) | |
{ | |
$states = array_merge(['default'], $this->activeStates); | |
$models->each(function ($model) use ($states, $beforeCallbacks) { | |
foreach ($states as $state) { | |
$this->callBeforeCallbacks($beforeCallbacks, $model, $state); | |
} | |
}); | |
} | |
/** | |
* Call before callbacks for each model and state. | |
* | |
* @param array $beforeCallbacks | |
* @param \Illuminate\Database\Eloquent\Model $model | |
* @param string $state | |
* @return void | |
*/ | |
protected function callBeforeCallbacks(array $beforeCallbacks, $model, $state) | |
{ | |
if (! isset($beforeCallbacks[$this->class][$state])) { | |
return; | |
} | |
foreach ($beforeCallbacks[$this->class][$state] as $callback) { | |
$callback($model, $this->faker); | |
} | |
} | |
/** | |
* Determine if the given state has an "after" of "before" callback. | |
* | |
* @param string $state | |
* @return bool | |
*/ | |
protected function stateHasAfterCallback($state) | |
{ | |
return isset($this->afterMaking[$this->class][$state]) || | |
isset($this->beforeCreating[$this->class][$state]) || | |
isset($this->afterCreating[$this->class][$state]); | |
} | |
public function cascade(array $states = []) | |
{ | |
if (empty($states)) { | |
$states = ['default']; | |
} | |
$this->states(array_map(function($state){ | |
return 'cascade-' . $state; | |
}, $states)); | |
return $this; | |
} | |
public function reuse(array $states = []) | |
{ | |
if (empty($states)) { | |
$states = ['default']; | |
} | |
$this->states(array_map(function($state){ | |
return 'reuse-' . $state; | |
}, $states)); | |
return $this; | |
} | |
/** | |
* Set the states to be applied to the model. | |
* | |
* @param array|mixed $states | |
* @return $this | |
*/ | |
public function states($states) | |
{ | |
$this->activeStates = array_merge($this->activeStates, is_array($states) ? $states : func_get_args()); | |
return $this; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment