Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
database/Eloquent/Concerns/HasEvents.php
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
354 lines (313 sloc)
8.56 KB
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
<?php | |
namespace Illuminate\Database\Eloquent\Concerns; | |
use Illuminate\Support\Arr; | |
use Illuminate\Contracts\Events\Dispatcher; | |
trait HasEvents | |
{ | |
/** | |
* The event map for the model. | |
* | |
* Allows for object-based events for native Eloquent events. | |
* | |
* @var array | |
*/ | |
protected $dispatchesEvents = []; | |
/** | |
* User exposed observable events. | |
* | |
* These are extra user-defined events observers may subscribe to. | |
* | |
* @var array | |
*/ | |
protected $observables = []; | |
/** | |
* Register observers with the model. | |
* | |
* @param object|array|string $classes | |
* @return void | |
*/ | |
public static function observe($classes) | |
{ | |
$instance = new static; | |
foreach (Arr::wrap($classes) as $class) { | |
$instance->registerObserver($class); | |
} | |
} | |
/** | |
* Register a single observer with the model. | |
* | |
* @param object|string $class | |
* @return void | |
*/ | |
protected function registerObserver($class) | |
{ | |
$className = is_string($class) ? $class : get_class($class); | |
// When registering a model observer, we will spin through the possible events | |
// and determine if this observer has that method. If it does, we will hook | |
// it into the model's event system, making it convenient to watch these. | |
foreach ($this->getObservableEvents() as $event) { | |
if (method_exists($class, $event)) { | |
static::registerModelEvent($event, $className.'@'.$event); | |
} | |
} | |
} | |
/** | |
* Get the observable event names. | |
* | |
* @return array | |
*/ | |
public function getObservableEvents() | |
{ | |
return array_merge( | |
[ | |
'retrieved', 'creating', 'created', 'updating', 'updated', | |
'saving', 'saved', 'restoring', 'restored', | |
'deleting', 'deleted', 'forceDeleted', | |
], | |
$this->observables | |
); | |
} | |
/** | |
* Set the observable event names. | |
* | |
* @param array $observables | |
* @return $this | |
*/ | |
public function setObservableEvents(array $observables) | |
{ | |
$this->observables = $observables; | |
return $this; | |
} | |
/** | |
* Add an observable event name. | |
* | |
* @param array|mixed $observables | |
* @return void | |
*/ | |
public function addObservableEvents($observables) | |
{ | |
$this->observables = array_unique(array_merge( | |
$this->observables, is_array($observables) ? $observables : func_get_args() | |
)); | |
} | |
/** | |
* Remove an observable event name. | |
* | |
* @param array|mixed $observables | |
* @return void | |
*/ | |
public function removeObservableEvents($observables) | |
{ | |
$this->observables = array_diff( | |
$this->observables, is_array($observables) ? $observables : func_get_args() | |
); | |
} | |
/** | |
* Register a model event with the dispatcher. | |
* | |
* @param string $event | |
* @param \Closure|string $callback | |
* @return void | |
*/ | |
protected static function registerModelEvent($event, $callback) | |
{ | |
if (isset(static::$dispatcher)) { | |
$name = static::class; | |
static::$dispatcher->listen("eloquent.{$event}: {$name}", $callback); | |
} | |
} | |
/** | |
* Fire the given event for the model. | |
* | |
* @param string $event | |
* @param bool $halt | |
* @return mixed | |
*/ | |
protected function fireModelEvent($event, $halt = true) | |
{ | |
if (! isset(static::$dispatcher)) { | |
return true; | |
} | |
// First, we will get the proper method to call on the event dispatcher, and then we | |
// will attempt to fire a custom, object based event for the given event. If that | |
// returns a result we can return that result, or we'll call the string events. | |
$method = $halt ? 'until' : 'dispatch'; | |
$result = $this->filterModelEventResults( | |
$this->fireCustomModelEvent($event, $method) | |
); | |
if ($result === false) { | |
return false; | |
} | |
return ! empty($result) ? $result : static::$dispatcher->{$method}( | |
"eloquent.{$event}: ".static::class, $this | |
); | |
} | |
/** | |
* Fire a custom model event for the given event. | |
* | |
* @param string $event | |
* @param string $method | |
* @return mixed|null | |
*/ | |
protected function fireCustomModelEvent($event, $method) | |
{ | |
if (! isset($this->dispatchesEvents[$event])) { | |
return; | |
} | |
$result = static::$dispatcher->$method(new $this->dispatchesEvents[$event]($this)); | |
if (! is_null($result)) { | |
return $result; | |
} | |
} | |
/** | |
* Filter the model event results. | |
* | |
* @param mixed $result | |
* @return mixed | |
*/ | |
protected function filterModelEventResults($result) | |
{ | |
if (is_array($result)) { | |
$result = array_filter($result, function ($response) { | |
return ! is_null($response); | |
}); | |
} | |
return $result; | |
} | |
/** | |
* Register a retrieved model event with the dispatcher. | |
* | |
* @param \Closure|string $callback | |
* @return void | |
*/ | |
public static function retrieved($callback) | |
{ | |
static::registerModelEvent('retrieved', $callback); | |
} | |
/** | |
* Register a saving model event with the dispatcher. | |
* | |
* @param \Closure|string $callback | |
* @return void | |
*/ | |
public static function saving($callback) | |
{ | |
static::registerModelEvent('saving', $callback); | |
} | |
/** | |
* Register a saved model event with the dispatcher. | |
* | |
* @param \Closure|string $callback | |
* @return void | |
*/ | |
public static function saved($callback) | |
{ | |
static::registerModelEvent('saved', $callback); | |
} | |
/** | |
* Register an updating model event with the dispatcher. | |
* | |
* @param \Closure|string $callback | |
* @return void | |
*/ | |
public static function updating($callback) | |
{ | |
static::registerModelEvent('updating', $callback); | |
} | |
/** | |
* Register an updated model event with the dispatcher. | |
* | |
* @param \Closure|string $callback | |
* @return void | |
*/ | |
public static function updated($callback) | |
{ | |
static::registerModelEvent('updated', $callback); | |
} | |
/** | |
* Register a creating model event with the dispatcher. | |
* | |
* @param \Closure|string $callback | |
* @return void | |
*/ | |
public static function creating($callback) | |
{ | |
static::registerModelEvent('creating', $callback); | |
} | |
/** | |
* Register a created model event with the dispatcher. | |
* | |
* @param \Closure|string $callback | |
* @return void | |
*/ | |
public static function created($callback) | |
{ | |
static::registerModelEvent('created', $callback); | |
} | |
/** | |
* Register a deleting model event with the dispatcher. | |
* | |
* @param \Closure|string $callback | |
* @return void | |
*/ | |
public static function deleting($callback) | |
{ | |
static::registerModelEvent('deleting', $callback); | |
} | |
/** | |
* Register a deleted model event with the dispatcher. | |
* | |
* @param \Closure|string $callback | |
* @return void | |
*/ | |
public static function deleted($callback) | |
{ | |
static::registerModelEvent('deleted', $callback); | |
} | |
/** | |
* Remove all of the event listeners for the model. | |
* | |
* @return void | |
*/ | |
public static function flushEventListeners() | |
{ | |
if (! isset(static::$dispatcher)) { | |
return; | |
} | |
$instance = new static; | |
foreach ($instance->getObservableEvents() as $event) { | |
static::$dispatcher->forget("eloquent.{$event}: ".static::class); | |
} | |
foreach (array_values($instance->dispatchesEvents) as $event) { | |
static::$dispatcher->forget($event); | |
} | |
} | |
/** | |
* Get the event dispatcher instance. | |
* | |
* @return \Illuminate\Contracts\Events\Dispatcher | |
*/ | |
public static function getEventDispatcher() | |
{ | |
return static::$dispatcher; | |
} | |
/** | |
* Set the event dispatcher instance. | |
* | |
* @param \Illuminate\Contracts\Events\Dispatcher $dispatcher | |
* @return void | |
*/ | |
public static function setEventDispatcher(Dispatcher $dispatcher) | |
{ | |
static::$dispatcher = $dispatcher; | |
} | |
/** | |
* Unset the event dispatcher for models. | |
* | |
* @return void | |
*/ | |
public static function unsetEventDispatcher() | |
{ | |
static::$dispatcher = null; | |
} | |
} |