8000 [9.x] Unify trait set up/tear down and other hooks under a `Hook` implementation by inxilpro · Pull Request #39947 · laravel/framework · GitHub
[go: up one dir, main page]

Skip to content

[9.x] Unify trait set up/tear down and other hooks under a Hook implementation #39947

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

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Refactor to interface
  • Loading branch information
inxilpro committed Dec 8, 2021
commit 4f1b50f8b9088bf2f5f4c4bfa31ff7c2ad1256d9
43 changes: 43 additions & 0 deletions src/Illuminate/Contracts/Support/Hook.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace Illuminate\Contracts\Support;

interface Hook
{
/**
* Indicates this hook should be run with higher priority.
*
* @var int
*/
public const PRIORITY_HIGH = 100;

/**
* Indicates this hook should be run with normal priority.
*
* @var int
*/
public const PRIORITY_NORMAL = 200;

/**
* Indicates this hook should be run with lower priority.
*
* @var int
*/
public const PRIORITY_LOW = 300;

/**
* Run the hook.
*
* @param object|string $instance
* @param array $arguments
*/
public function run($instance, array $arguments = []);

/**
* Clean up after the hook.
*
* @param object|string $instance
* @param array $arguments
*/
public function cleanup($instance, array $arguments = []);
}
19 changes: 14 additions & 5 deletions src/Illuminate/Database/Console/Seeds/WithoutModelEvents.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,26 @@
namespace Illuminate\Database\Console\Seeds;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Events\NullDispatcher;
use Illuminate\Support\Hooks\Hook;

trait WithoutModelEvents
{
/**
* Prevent model events from being dispatched by the given callback.
* Prevent model events from being dispatched when the seeder is invoked.
*
* @param callable $callback
* @return callable
* @return Hook
*/
public function withoutModelEvents(callable $callback)
public static function withoutModelEvents(): Hook
{
return fn () => Model::withoutEvents($callback);
return Hook::make('invoke', static function () {
if (! $dispatcher = Model::getEventDispatcher()) {
return null;
}

Model::setEventDispatcher(new NullDispatcher($dispatcher));

return static fn() => Model::setEventDispatcher($dispatcher);
});
}
}
19 changes: 8 additions & 11 deletions src/Illuminate/Database/Seeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@
use Illuminate\Container\Container;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Support\Arr;
use Illuminate\Support\Hookable;
use InvalidArgumentException;

abstract class Seeder
{
use Hookable;

/**
* The container instance.
*
Expand Down Expand Up @@ -171,16 +174,10 @@ public function __invoke(array $parameters = [])
throw new InvalidArgumentException('Method [run] missing from '.get_class($this));
}

$callback = fn () => isset($this->container)
? $this->container->call([$this, 'run'], $parameters)
: $this->run(...$parameters);

$uses = array_flip(class_uses_recursive(static::class));

if (isset($uses[WithoutModelEvents::class])) {
$callback = $this->withoutModelEvents($callback);
}

return $callback();
return $this->runHooks('invoke', $this, function() use ($parameters) {
return isset($this->container)
? $this->container->call([$this, 'run'], $parameters)
: $this->run(...$parameters);
});
}
}
50 changes: 46 additions & 4 deletions src/Illuminate/Support/Hookable.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,59 @@

namespace Illuminate\Support;

use Closure;
use Illuminate\Support\Hooks\HookCollection;
use Illuminate\Support\Hooks\TraitHook;

trait Hookable
{
protected static function runStaticHooks($name, ...$arguments)
/**
* Run hooks statically.
*
* @param string $name
* @param array $arguments
* @param \Closure|null $callback
* @return mixed
*/
protected static function runStaticHooks($name, $arguments = [], Closure $callback = null)
{
HookCollection::for(static::class)->run($name, null, $arguments);
return HookCollection::for(static::class)->run($name, static::class, $arguments, $callback);
}

protected function runHooks($name, ...$arguments)
/**
* Run trait hooks statically.
*
* @param string $prefix
* @param array $arguments
* @return void
*/
protected static function runStaticTraitHooks($prefix, $arguments = [])
{
HookCollection::for(static::class)->run($name, $this, $arguments);
(new TraitHook($prefix))->run(static::class, $arguments);
}

/**
* Run hooks non-statically.
*
* @param string $name
* @param array $arguments
* @param \Closure|null $callback
* @return mixed
*/
protected function runHooks($name, $arguments = [], Closure $callback = null)
{
return HookCollection::for(static::class)->run($name, $this, $arguments, $callback);
}

/**
* Run trait hooks.
*
* @param string $prefix
* @param array $arguments
* @return void
*/
protected function runTraitHooks($prefix, $arguments = [])
{
(new TraitHook($prefix))->run($this, $arguments);
}
}
91 changes: 79 additions & 12 deletions src/Illuminate/Support/Hooks/Hook.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,105 @@
namespace Illuminate\Support\Hooks;

use Closure;
use Illuminate\Contracts\Support\Hook as HookContract;

class Hook
class Hook implements HookContract
{
public const PRIORITY_HIGH = 100;
public const PRIORITY_NORMAL = 200;
public const PRIORITY_LOW = 300;
/**
* A cleanup function that should be run after the hooks are run.
*
* @var \Closure|null
*/
protected ?Closure $cleanup = null;

/**
* Instantiate a new high-priority hook.
*
* @param string $name
* @param \Closure $callback
* @return \Illuminate\Support\Hooks\Hook
*/
public static function highPriority(string $name, Closure $callback): Hook
{
return new static($name, $callback, self::PRIORITY_HIGH);
return new static($name, $callback, HookContract::PRIORITY_HIGH);
}

/**
* Instantiate a new hook.
*
* @param string $name
* @param \Closure $callback
* @return \Illuminate\Support\Hooks\Hook
*/
public static function make(string $name, Closure $callback): Hook
{
return new static($name, $callback, self::PRIORITY_NORMAL);
return new static($name, $callback, HookContract::PRIORITY_NORMAL);
}

/**
* Instantiate a new low-priority hook.
*
* @param string $name
* @param \Closure $callback
* @return \Illuminate\Support\Hooks\Hook
*/
public static function lowPriority(string $name, Closure $callback): Hook
{
return new static($name, $callback, self::PRIORITY_LOW);
return new static($name, $callback, HookContract::PRIORITY_LOW);
}

/**
* Constructor
*
* @param string $name
* @param \Closure $callback
* @param int $priority
* @return void
*/
public function __construct(
public string $name,
public Closure $callback,
public int $priority = self::PRIORITY_NORMAL
public int $priority = HookContract::PRIORITY_NORMAL
) { }

public function run($instance = null, array $arguments = [])
/**
* @inheritdoc
*/
public function run($instance, array $arguments = [])
{
return $instance
? $this->callback->call($instance, ...$arguments)
: call_user_func_array($this->callback, $arguments);
$this->cleanup = null;

$result = $this->runCallback($this->callback, $instance, $arguments);

if ($result instanceof Closure) {
$this->cleanup = $result;
}
}

/**
* @inheritdoc
*/
public function cleanup($instance, array $arguments = [])
{
if (is_null($this->cleanup)) {
return;
}

$this->runCallback($this->cleanup, $instance, $arguments);
}

/**
* Run a callback that may or may not be static.
*
* @param Closure $callback
* @param object|string $instance
* @param array $arguments
* @return mixed
*/
protected function runCallback($callback, $instance, $arguments = [])
{
return is_object($instance)
? $callback->call($instance, $arguments)
: $callback(...$arguments);
}
}
Loading
0