Skip to content
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

Lifecycle hooks for CrudPanel functionality #5687

Open
wants to merge 13 commits into
base: next
Choose a base branch
from
4 changes: 4 additions & 0 deletions src/BackpackServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ public function register()
return new DatabaseSchema();
});

$this->app->scoped('lifecycle-hook', function ($app) {
return new app\Library\CrudPanel\Hooks\LifecycleHooks();
});

$this->app->singleton('BackpackViewNamespaces', function ($app) {
return new ViewNamespaces();
});
Expand Down
19 changes: 18 additions & 1 deletion src/app/Http/Controllers/CrudController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Backpack\CRUD\app\Http\Controllers;

use Backpack\CRUD\app\Library\Attributes\DeprecatedIgnoreOnRuntime;
use Backpack\CRUD\app\Library\CrudPanel\Hooks\Facades\LifecycleHook;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller;
Expand All @@ -19,6 +20,7 @@ class CrudController extends Controller
use DispatchesJobs, ValidatesRequests;

public $crud;

public $data = [];

public function __construct()
Expand All @@ -40,8 +42,14 @@ public function __construct()

$this->crud->setRequest($request);

LifecycleHook::trigger('crud:before_setup_defaults', [$this]);
$this->setupDefaults();
LifecycleHook::trigger('crud:after_setup_defaults', [$this]);

LifecycleHook::trigger('crud:before_setup', [$this]);
$this->setup();
LifecycleHook::trigger('crud:after_setup', [$this]);

$this->setupConfigurationForCurrentOperation();

return $next($request);
Expand Down Expand Up @@ -116,13 +124,22 @@ protected function setupConfigurationForCurrentOperation()
* you'd like the defaults to be applied before anything you write. That way, anything you
* write is done after the default, so you can remove default settings, etc;
*/
$this->crud->applyConfigurationFromSettings($operationName);
if (! LifecycleHook::has($operationName.':setup_operation_config')) {
LifecycleHook::hookInto($operationName.':setup_operation_config', function () use ($operationName) {
return 'backpack.operations.'.$operationName;
});
}

$this->crud->loadDefaultOperationSettingsFromConfig(LifecycleHook::trigger($operationName.':setup_operation_config', [$this, $operationName]));
pxpm marked this conversation as resolved.
Show resolved Hide resolved

LifecycleHook::trigger($operationName.':before_setup', [$this]);
/*
* THEN, run the corresponding setupXxxOperation if it exists.
*/
if (method_exists($this, $setupClassName)) {
$this->{$setupClassName}();
}

LifecycleHook::trigger($operationName.':after_setup', [$this]);
}
}
20 changes: 7 additions & 13 deletions src/app/Http/Controllers/Operations/Concerns/HasForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Backpack\CRUD\app\Http\Controllers\Operations\Concerns;

use Backpack\CRUD\app\Library\CrudPanel\Hooks\Facades\LifecycleHook;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Str;

Expand Down Expand Up @@ -38,17 +39,11 @@ protected function formDefaults(string $operationName, string $buttonStack = 'li
// Access
$this->crud->allowAccess($operationName);

// Config
$this->crud->operation($operationName, function () use ($operationName) {
// if the backpack.operations.{operationName} config exists, use that one
// otherwise, use the generic backpack.operations.form config
if (config()->has('backpack.operations.'.$operationName)) {
$this->crud->loadDefaultOperationSettingsFromConfig();
} else {
$this->crud->loadDefaultOperationSettingsFromConfig('backpack.operations.form');
}

// add a reasonable "save and back" save action
LifecycleHook::hookInto('crud:setup_operation_config', function () use ($operationName) {
return config()->has('backpack.operations.'.$operationName) ? 'backpack.operations.'.$operationName : 'backpack.operations.form';
});

LifecycleHook::hookInto($operationName.':before_setup', function () use ($operationName) {
$this->crud->addSaveAction([
'name' => 'save_and_back',
'visible' => function ($crud) use ($operationName) {
Expand All @@ -61,8 +56,7 @@ protected function formDefaults(string $operationName, string $buttonStack = 'li
]);
});

// Default Button
$this->crud->operation(['list', 'show'], function () use ($operationName, $buttonStack, $buttonMeta) {
LifecycleHook::hookInto(['list:before_setup', 'show:before_setup'], function () use ($operationName, $buttonStack, $buttonMeta) {
$this->crud->button($operationName)->view('crud::buttons.quick')->stack($buttonStack)->meta($buttonMeta);
});
}
Expand Down
6 changes: 3 additions & 3 deletions src/app/Http/Controllers/Operations/CreateOperation.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Backpack\CRUD\app\Http\Controllers\Operations;

use Backpack\CRUD\app\Library\CrudPanel\Hooks\Facades\LifecycleHook;
use Illuminate\Support\Facades\Route;

trait CreateOperation
Expand Down Expand Up @@ -35,12 +36,11 @@ protected function setupCreateDefaults()
{
$this->crud->allowAccess('create');

$this->crud->operation('create', function () {
$this->crud->loadDefaultOperationSettingsFromConfig();
LifecycleHook::hookInto('create:before_setup', function () {
$this->crud->setupDefaultSaveActions();
});

$this->crud->operation('list', function () {
LifecycleHook::hookInto('list:before_setup', function () {
$this->crud->addButton('top', 'create', 'view', 'crud::buttons.create');
});
}
Expand Down
7 changes: 2 additions & 5 deletions src/app/Http/Controllers/Operations/DeleteOperation.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Backpack\CRUD\app\Http\Controllers\Operations;

use Backpack\CRUD\app\Library\CrudPanel\Hooks\Facades\LifecycleHook;
use Illuminate\Support\Facades\Route;

trait DeleteOperation
Expand Down Expand Up @@ -29,11 +30,7 @@ protected function setupDeleteDefaults()
{
$this->crud->allowAccess('delete');

$this->crud->operation('delete', function () {
$this->crud->loadDefaultOperationSettingsFromConfig();
});
pxpm marked this conversation as resolved.
Show resolved Hide resolved

$this->crud->operation(['list', 'show'], function () {
LifecycleHook::hookInto(['list:before_setup', 'show:before_setup'], function () {
$this->crud->addButton('line', 'delete', 'view', 'crud::buttons.delete', 'end');
});
}
Expand Down
20 changes: 20 additions & 0 deletions src/app/Library/CrudPanel/Hooks/Facades/LifecycleHook.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace Backpack\CRUD\app\Library\CrudPanel\Hooks\Facades;

use Illuminate\Support\Facades\Facade;

/**
* @method static void register(string $hook, string|array $operations, callable $callback)
* @method static void run(string $hook, string|array $operations, array $parameters)
* @method static bool has(string $hook, string $operation)
*
* @see \Backpack\CRUD\app\Library\CrudPanel\Hooks\OperationHooks
*/
class LifecycleHook extends Facade
{
protected static function getFacadeAccessor()
{
return 'lifecycle-hook';
}
}
33 changes: 33 additions & 0 deletions src/app/Library/CrudPanel/Hooks/LifecycleHooks.php
tabacitu marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Backpack\CRUD\app\Library\CrudPanel\Hooks;

final class LifecycleHooks
{
public array $hooks = [];

public function hookInto(string|array $hooks, callable $callback): void
{
$hooks = is_array($hooks) ? $hooks : [$hooks];
foreach ($hooks as $hook) {
$this->hooks[$hook][] = $callback;
}
}

public function trigger(string|array $hooks, array $parameters): void
{
$hooks = is_array($hooks) ? $hooks : [$hooks];
foreach ($hooks as $hook) {
if (isset($this->hooks[$hook])) {
foreach ($this->hooks[$hook] as $callback) {
$callback(...$parameters);
}
}
}
}

public function has(string $hook): bool
{
return isset($this->hooks[$hook]);
}
}
35 changes: 17 additions & 18 deletions src/app/Library/CrudPanel/Traits/Operations.php
tabacitu marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Backpack\CRUD\app\Library\CrudPanel\Traits;

use Backpack\CRUD\app\Library\CrudPanel\Hooks\Facades\LifecycleHook;

trait Operations
{
/*
Expand Down Expand Up @@ -59,30 +61,34 @@ public function setCurrentOperation($operation_name)
* @param string|array $operation Operation name in string form
* @param bool|\Closure $closure Code that calls CrudPanel methods.
* @return void
*
* @deprecated use LifecycleHook::hookInto($operation.':before_setup', $closure) instead
*/
public function operation($operations, $closure = false)
{
return $this->configureOperation($operations, $closure);
$operations = is_array($operations) ? $operations : [$operations];
foreach ($operations as $operation) {
LifecycleHook::hookInto($operation.':before_setup', $closure);
}
}

/**
* Store a closure which configures a certain operation inside settings.
* Allc configurations are put inside that operation's namespace.
* All configurations are put inside that operation's namespace.
* Ex: show.configuration.
*
* @param string|array $operation Operation name in string form
* @param bool|\Closure $closure Code that calls CrudPanel methods.
* @return void
*
* @deprecated use LifecycleHook::hookInto($operation.':before_setup', $closure) instead
*/
public function configureOperation($operations, $closure = false)
{
$operations = (array) $operations;
$operations = is_array($operations) ? $operations : [$operations];

foreach ($operations as $operation) {
$configuration = (array) $this->get($operation.'.configuration');
$configuration[] = $closure;

$this->set($operation.'.configuration', $configuration);
LifecycleHook::hookInto($operation.':before_setup', $closure);
}
}

Expand All @@ -93,22 +99,15 @@ public function configureOperation($operations, $closure = false)
*
* @param string|array $operations [description]
* @return void
*
* @deprecated use LifecycleHook::hookInto($operation.':before_setup', $closure) instead
*/
public function applyConfigurationFromSettings($operations)
{
$operations = (array) $operations;
$operations = is_array($operations) ? $operations : [$operations];

foreach ($operations as $operation) {
$configuration = (array) $this->get($operation.'.configuration');

if (count($configuration)) {
foreach ($configuration as $closure) {
if (is_callable($closure)) {
// apply the closure
($closure)();
}
}
}
LifecycleHook::trigger($operation.':before_setup');
}
}
}