-
Notifications
You must be signed in to change notification settings - Fork 922
Lifecycle hooks for CrudPanel functionality #5687
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
Conversation
|
Playground for syntax: <?php
static::created(function (User $user) {
// ...
});
OperationHook::register(
OperationHooks::AFTER_OPERATION_SETUP,
'list',
function () { $this->runCustomViews(); }
);
// equivalent
Backpack::hook(
event: OperationHooks::AFTER_OPERATION_SETUP,
operation: 'list',
run: function() { $this->runCustomViews(); }
);
// equivalent
Backpack::hook(
event: 'afterOperationSetup',
operation: 'list',
run: function() { $this->runCustomViews(); }
);
// nah
BackpackHook::afterOperationSetup('list', function() {
$this->runCustomViews();
});
// nah
BackpackHook::on(OperationHooks::AFTER_OPERATION_SETUP)
->operation('list')
->do(function() {
$this->runCustomViews();
});
// -----
BackpackHook::moderated(
operation: 'moderate',
run: function() { $this->runCustomViews(); }
);
'moderated' => [
'operation' => 'moderate',
'closure' => (function() {})
]
// ModerateOperation
public function saveModeration() {
// do something
$args = [
$entry,
];
BackpackHook::run('moderated', $args);
}
// -----
BackpackHook::operation('list', function() {});
BackpackHook::operation('list', function() {});
Backpack::hookInto('moderated', function() {});
Backpack::hookIntoOperation('list', 'moderated', function() {});
|
|
Todo: docs for this PR (original PR, with separate PanelHooks and OperationHooks). |
OperationHooksOperationHooks are a way to hook into the operation process. They are used to modify the operation process in some way, before or after the operation is setup. There are three types of OperationHooks: BEFORE_OPERATION_SETUP, AFTER_OPERATION_SETUP and OPERATION_SETUP_CONFIGS. BEFORE_OPERATION_SETUPThis hook is called before the operation is setup. It is used to modify the operation in some way, before it is setup. AFTER_OPERATION_SETUPThis hook is called after the operation is setup. It is used to modify the operation in some way, after it is setup. OPERATION_SETUP_CONFIGSThis hook is used to modify the behavior of some setup settings, like from what file should the operation load his configs. PanelHooksPanelHooks can be seen a general purpose hooks, they are used to modify the panel, modify operations at different operation points etc. BEFORE_SETUP_ROUTES If you are creating a custom operation, you can use the PanelHooks to create a point in your operation where developers using your operation can "hook" to modify the default behavior of your operation: eg: // ModerateOperation.php
// .. setup routes, defaults etc ..
public function moderate($id)
{
// do some moderation functions ...
PanelHooks::run('after-moderation', ['id' => $id, 'moderatedEntry' => $entry]);
}
// developers can then register they own behavior for the 'after-moderation' hook
// for example in a middleware, or in the `setup()` of the controller where they use your operation:
public function setup()
{
PanelHooks::register('after-moderation', function($id, $moderatedEntry) {
// do something with the moderated entry
});
}The main point of Hooks is to reduce the amount of overwrites, promoting a more modular and reusable code without the need to catter to all different |
CRUD Lifecycle EventsAt important points in the CRUD Lifecycle, Backpack triggers what we call "lifecycle events". You can hook into those events - by registering custom code that will run when that lifecycle event happens. This allows you to customize the process, without having to override any of the core files for CRUD or an Operation. For example, in a Backpack CRUD all routes are setup on the CrudController using methods like LifecycleEvent::hookInto('crud:before_all_route_setup', function($controller, $operation) {
// do something useful
});Here are all the Lifecycle Events we currently have:
In addition to the general lifecycle events above, each operation can trigger its own lifecycle events. For example, here are the lifecycle events triggered by the Create operation:
LifecycleEvent::hookInto(['create:before_setup', 'list:before_setup', 'moderate:before_setup'], function() {
$this->crud->addButton('top', 'create', 'view', 'crud::buttons.create');
});
LifecycleEvent::trigger('moderate:after_moderation', [
'controller' => $controller,
'operation' => $operation,
]); |
tabacitu
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the details Pedro. I replied inline. I understand why you've made the decisions you've made now. And I agree with most of them.
Not sure about moving the config-loading on the CRUD side though. It really looks like it's making this something it's not supposed to be.
I think the safest thing to do would be to move that to a different PR. Then we can move this PR forward, merge it, and think about that separately as an improvement to the DX of creating operations.
0cffae1 to
8ece6d2
Compare
1253d3b to
7019815
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super-clean. Well done @pxpm .
Please:
- give this another look
- hit
mergeyourself - add docs for it, right away; for the general events; you can copy-paste from my words here; I would add it in Operations > Operations Lifecycle (level 1, so that it can have subheadings itself)
Then let's create one/more PRs for adding custom lifecycle events to certain operations, where they make sense.
[ci skip] [skip ci]
[ci skip] [skip ci]
[ci skip] [skip ci]
[ci skip] [skip ci]
[ci skip] [skip ci]
|
@tabacitu regarding docs, is this what you had in mind? Laravel-Backpack/docs#622 |
|
Not quite - I think a better place for them would be in the Operations page. After all... they are operation lifecycle hooks, right? I've moved them there, and added a section at the top which explains the operation lifecycle - what gets called when. Might be a little verbose right now, but we can polish. I think it's long overdue that we have an explanation on WHAT gets called WHEN. I'm very happy we finally do. ✅ Made the changes to the docs. Feel free to edit the texts if you feel the need. LFG!!! 💪 |
* wip * Apply fixes from StyleCI [ci skip] [skip ci] * tidy up * Apply fixes from StyleCI [ci skip] [skip ci] * panel hooks * Apply fixes from StyleCI [ci skip] [skip ci] * refactoring :broom * finish implementing hooks * Apply fixes from StyleCI [ci skip] [skip ci] * refactoring hooks * Apply fixes from StyleCI [ci skip] [skip ci] * add hook to delete * allow empty parameters * wip --------- Co-authored-by: StyleCI Bot <[email protected]>
* wip * Apply fixes from StyleCI [ci skip] [skip ci] * tidy up * Apply fixes from StyleCI [ci skip] [skip ci] * panel hooks * Apply fixes from StyleCI [ci skip] [skip ci] * refactoring :broom * finish implementing hooks * Apply fixes from StyleCI [ci skip] [skip ci] * refactoring hooks * Apply fixes from StyleCI [ci skip] [skip ci] * add hook to delete * allow empty parameters * wip --------- Co-authored-by: StyleCI Bot <[email protected]>
* wip * Apply fixes from StyleCI [ci skip] [skip ci] * tidy up * Apply fixes from StyleCI [ci skip] [skip ci] * panel hooks * Apply fixes from StyleCI [ci skip] [skip ci] * refactoring :broom * finish implementing hooks * Apply fixes from StyleCI [ci skip] [skip ci] * refactoring hooks * Apply fixes from StyleCI [ci skip] [skip ci] * add hook to delete * allow empty parameters * wip --------- Co-authored-by: StyleCI Bot <[email protected]>
* wip * Apply fixes from StyleCI [ci skip] [skip ci] * tidy up * Apply fixes from StyleCI [ci skip] [skip ci] * panel hooks * Apply fixes from StyleCI [ci skip] [skip ci] * refactoring :broom * finish implementing hooks * Apply fixes from StyleCI [ci skip] [skip ci] * refactoring hooks * Apply fixes from StyleCI [ci skip] [skip ci] * add hook to delete * allow empty parameters * wip --------- Co-authored-by: StyleCI Bot <[email protected]>
* wip * Apply fixes from StyleCI [ci skip] [skip ci] * tidy up * Apply fixes from StyleCI [ci skip] [skip ci] * panel hooks * Apply fixes from StyleCI [ci skip] [skip ci] * refactoring :broom * finish implementing hooks * Apply fixes from StyleCI [ci skip] [skip ci] * refactoring hooks * Apply fixes from StyleCI [ci skip] [skip ci] * add hook to delete * allow empty parameters * wip --------- Co-authored-by: StyleCI Bot <[email protected]>
* wip * Apply fixes from StyleCI [ci skip] [skip ci] * tidy up * Apply fixes from StyleCI [ci skip] [skip ci] * panel hooks * Apply fixes from StyleCI [ci skip] [skip ci] * refactoring :broom * finish implementing hooks * Apply fixes from StyleCI [ci skip] [skip ci] * refactoring hooks * Apply fixes from StyleCI [ci skip] [skip ci] * add hook to delete * allow empty parameters * wip --------- Co-authored-by: StyleCI Bot <[email protected]>
* Uploaders - Refactor and fixes (#5478) * add method to get ajax uploaders * Apply fixes from StyleCI [ci skip] [skip ci] * use an abstract class * wip * Apply fixes from StyleCI [ci skip] [skip ci] * refactor uploaders * Apply fixes from StyleCI [ci skip] [skip ci] * refactor rules * Apply fixes from StyleCI [ci skip] [skip ci] * move ajax to PRO, cleanup * Apply fixes from StyleCI [ci skip] [skip ci] * make attributes available for all subfields * fix tests * wip * Apply fixes from StyleCI [ci skip] [skip ci] * upload multiple and upload properly working 🙏 * fixes * Apply fixes from StyleCI [ci skip] [skip ci] * allow the configuration of valueWithoutPath call. * fix valid upload inside repeatables * Apply fixes from StyleCI [ci skip] [skip ci] * fix condition * cleanup * fix * Apply fixes from StyleCI [ci skip] [skip ci] * fix use case for enabling validation after entry is created * Apply fixes from StyleCI [ci skip] [skip ci] * dont save array keys * fix ajax validation * fix validation messages * Apply fixes from StyleCI [ci skip] [skip ci] * fixes ValidUpload * Apply fixes from StyleCI [ci skip] [skip ci] * dont json encode if casted in the model * Apply fixes from StyleCI [ci skip] [skip ci] * fix previous file identification in repeatable * Apply fixes from StyleCI [ci skip] [skip ci] * fix getting values * Apply fixes from StyleCI [ci skip] [skip ci] * add fake fields support * Apply fixes from StyleCI [ci skip] [skip ci] * wip add uploaders tests * Apply fixes from StyleCI [ci skip] [skip ci] * wip * Apply fixes from StyleCI [ci skip] [skip ci] * add pro columns * fix test suite * fix tests * ffix tests * remove unused test views * add uploaders to test coverage * Apply fixes from StyleCI [ci skip] [skip ci] * add coverage folder to gitignore * make tests run faster by not reloading db when not necessary * add coverage to validation tests * add fake tests to uploaders * Apply fixes from StyleCI [ci skip] [skip ci] * add more tests * Apply fixes from StyleCI [ci skip] [skip ci] * wip * Apply fixes from StyleCI [ci skip] [skip ci] * wip * wip * Apply fixes from StyleCI [ci skip] [skip ci] * wip * Apply fixes from StyleCI [ci skip] [skip ci] * add more upload assets * fixes * Apply fixes from StyleCI [ci skip] [skip ci] * fix single file * Apply fixes from StyleCI [ci skip] [skip ci] * add image column * fix tests * Apply fixes from StyleCI [ci skip] [skip ci] * remove hardcoded macro names * Apply fixes from StyleCI [ci skip] [skip ci] * remove double loop, fix single file uploader * Apply fixes from StyleCI [ci skip] [skip ci] * use a big increments and unsigned for primary key * handle pivot file deletion * Apply fixes from StyleCI [ci skip] [skip ci] * register events for relation models * Apply fixes from StyleCI [ci skip] [skip ci] * fix typo * Apply fixes from StyleCI [ci skip] [skip ci] * fix relationship uploaders * Apply fixes from StyleCI [ci skip] [skip ci] * wip * Apply fixes from StyleCI [ci skip] [skip ci] * wip * Apply fixes from StyleCI [ci skip] [skip ci] * update temporary time key * save objects in the macro --------- Co-authored-by: StyleCI Bot <[email protected]> * trigger testing forkflow on PR * Clean up uploaders (#5725) * wip * clean up * add get uploadedFilesFromRequest to clean up uploaders * Apply fixes from StyleCI [ci skip] [skip ci] * fix type cast * add summernote uploader * update summernote * add summernote * add more test assets --------- Co-authored-by: StyleCI Bot <[email protected]> * allow datatable url configuration (#5713) * use next branch for basset * require alpha version * bump basset version * Lifecycle hooks for CRUD operations (#5687) * wip * Apply fixes from StyleCI [ci skip] [skip ci] * tidy up * Apply fixes from StyleCI [ci skip] [skip ci] * panel hooks * Apply fixes from StyleCI [ci skip] [skip ci] * refactoring :broom * finish implementing hooks * Apply fixes from StyleCI [ci skip] [skip ci] * refactoring hooks * Apply fixes from StyleCI [ci skip] [skip ci] * add hook to delete * allow empty parameters * wip --------- Co-authored-by: StyleCI Bot <[email protected]> * "Agnostic" filters - decouple filters from datatables (#5714) * wip * wip * Apply fixes from StyleCI [ci skip] [skip ci] * wip * Apply fixes from StyleCI [ci skip] [skip ci] * remove filters navbar component --------- Co-authored-by: StyleCI Bot <[email protected]> * bump basset version * Update composer.json * Apply fixes from StyleCI [ci skip] [skip ci] * datatable component (#5688) Co-authored-by: StyleCI Bot <[email protected]> Co-authored-by: Cristian Tabacitu <[email protected]> * move the list heading to the datatable component (#5808) * add Datagrid and Datalist components (#5810) Co-authored-by: StyleCI Bot <[email protected]> * Form component (no ajax form) (#5814) Co-authored-by: StyleCI Bot <[email protected]> Co-authored-by: Cristian Tabacitu <[email protected]> * dataform component fixes (#5816) Co-authored-by: StyleCI Bot <[email protected]> * Added general chip blade file and chip widget (#5815) * Fix Form issues, Add *name* argument to forms (#5817) Co-authored-by: StyleCI Bot <[email protected]> * Drop support for Laravel 10 and 11 (#5819) * Fix hooks at setup level (#5818) Co-authored-by: StyleCI Bot <[email protected]> * install dev-next version of generators * require basset beta version (#5821) * fix scripts on table * fix the keyboard shortcuts on forms * ensure proper crud identification * fix hooks * fix crud field javacript issue * pass the form id to form content * add error page translations * fix export buttons * wip * wip * wip * map the ui files * fix table without export buttons * always focus on error field * delete button redirect * Apply fixes from StyleCI [ci skip] [skip ci] * Fix padding in name * Fix checkbox padding * Background of select2 * multiple fixes * fix form error highlight * wip * Add toggle to JSON * allow user to choose locale and timezone * fixes bulk actions * fix the filter navbar * fix line buttons dropdown * wip * wip * wip * wip * wip * DataFormModal component (#5863) Co-authored-by: StyleCI Bot <[email protected]> Co-authored-by: Cristian Tabacitu <[email protected]> Co-authored-by: Cristian Tăbăcitu <[email protected]> * wip * wip * wip * Save action classes (#5878) Enable the usage of classes to describe the save actions. This allow more flexibility and easy to extend and/or configure behaviour. * add cancel button option to modal form (#5881) * fix problem with checklist_dependency field in Update operation * fix indentation * Update src/app/Console/Commands/Install.php * Update composer.json --------- Co-authored-by: Pedro Martins <[email protected]> Co-authored-by: StyleCI Bot <[email protected]> Co-authored-by: jcastroa87 <[email protected]> Co-authored-by: zachweix <[email protected]>
The objective of this PR is to streamline the usage of "hooks" in our software, so that developer can do the most possible, without overwrites.
We have already concluded that overwrites are the pain point when updating backpack, and it also limits our options when we want to push new features. It's not uncommon to find conditionals in our codebase to account for overwritten files.
This is very very wip. I just got the liberty from @tabacitu to work on some concepts for stuff we aim to do, this is one of those.