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

[POC] Operation hooks #5687

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open

[POC] Operation hooks #5687

wants to merge 6 commits into from

Conversation

pxpm
Copy link
Contributor

@pxpm pxpm commented Oct 10, 2024

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.

@tabacitu
Copy link
Member

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() {});
        

@tabacitu
Copy link
Member

Todo: docs for this PR (original PR, with separate PanelHooks and OperationHooks).

@pxpm
Copy link
Contributor Author

pxpm commented Oct 17, 2024

OperationHooks

OperationHooks 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.
They are also used to modify the behavior of some setup settings, like setupOperationFromConfig.

There are three types of OperationHooks: BEFORE_OPERATION_SETUP, AFTER_OPERATION_SETUP and OPERATION_SETUP_CONFIGS.

BEFORE_OPERATION_SETUP

This hook is called before the operation is setup. It is used to modify the operation in some way, before it is setup.

```php
public function setup()
{
    OperationHooks::register(OperationHooks::BEFORE_OPERATION_SETUP, function($crudController) {
        // do something with the operation
    });
}
```

AFTER_OPERATION_SETUP

This hook is called after the operation is setup. It is used to modify the operation in some way, after it is setup.

```php
public function setup()
{
    OperationHooks::register(OperationHooks::AFTER_OPERATION_SETUP, function($crudController) {
        // do something with the operation
    });
}
```

OPERATION_SETUP_CONFIGS

This hook is used to modify the behavior of some setup settings, like from what file should the operation load his configs.

```php
public function setup()
{
    OperationHooks::register(OperationHooks::OPERATION_SETUP_CONFIGS, function($crudController) {
        return 'backpack.vendor.operation.someCustomFile';
    });
}
```

PanelHooks

PanelHooks can be seen a general purpose hooks, they are used to modify the panel, modify operations at different operation points etc.
Backpack provides some default PanelHooks, but you can create your own PanelHooks.

BEFORE_SETUP_ROUTES
AFTER_SETUP_ROUTES
BEFORE_SETUP_DEFAULTS
AFTER_SETUP_DEFAULTS
BEFORE_CONTROLLER_SETUP
AFTER_CONTROLLER_SETUP

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
ways someone might want to use your operation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

3 participants