community-forum icon indicating copy to clipboard operation
community-forum copied to clipboard

[v6][Idea] Trigger events during Operations and CRUD process

Open tabacitu opened this issue 2 years ago • 3 comments

Quite a few times, we've needed to do stuff before or after Backpack is doing something. We could implement hooks (before_x_operation or before_setup etc) but I think a more long-term solution would be implementing an event system. Backpack triggering events at different touchpoints, so that Backpack itself or the developer can hook into those events, and do stuff there.

Before we do that, we need a list of events. Here's mine:

  • inside CrudController:
    • 🟡 before & after setupRoutes()
    • 🔴 before & after setupDefaults()
    • 🔴 before & after setup()
    • 🔴 before & after setupConfigurationForCurrentOperation()
  • inside each Operation:
    • I don't think this is actually needed; some operations might offer events... maybe... but it should be a requirement;
  • inside CrudPanel
    • 🔵 before & after setModel()?
    • 🔵 before & after setRoute()?
    • 🔵 before $after setRouteName()?
    • the above aren't really needed IMHO since that is done in EntityCrudController::setup() - dev already has access to them; if we move those to CrudController as properties though... then it would make sense;
    • 🔵 before & after create()?
    • 🔵 before & after createRelationsForItem()?
    • 🔵 before & after update()?
    • I don't think the above are needed either;

What else would be needed? What other events would be nice to have? What naming could we use for this? What prefixing system do events usually use, so they don't conflict with other events?

Food for thought.

tabacitu avatar Feb 28 '23 08:02 tabacitu

Ping @pxpm

tabacitu avatar Mar 07 '23 15:03 tabacitu

You know what I think about this, let's brainstorm it and get out of here with a solution we are confortable with maintaining 👍

I think a good name structure/rules could be something like:

before/afterFunctionNameEvent, eg:

  • beforeSetupEvent
  • afterSetupEvent
  • beforeSetupConfigurationForCurrentOperationEvent
  • afterSetupConfigurationForCurrentOperationEvent

I think we only need the request as the event parameter, since the crud object we can get from the container.

Another scenario is building the event system not coupled with the functions, but we create the events for our "lifecycle". So having listeners with more general names like BeforeOperationListener extends OperationListener, where you could for example define a property or have a static method or use regexed functions

class `BeforeOperationListener extends OperationListener`
{
public function listenToCreate() {
}

public function listenToUpdate() {
}

public function listenToInlineCreate() {
}
}

I need to put this event system on our "real" use case like inline create or dropzone to have a better picture of what are the real requirements.

When we are done with the uploads I will invest some time in a simple poc for the event implementation. We need to take into consideration scenarios like defining operation stuff with closures inside setup() or using the setupOperation methods.

Cheers

pxpm avatar Mar 07 '23 17:03 pxpm

I think a good name structure/rules could be something like: before/afterFunctionNameEvent, eg:

  • beforeSetupEvent
  • afterSetupEvent
  • beforeSetupConfigurationForCurrentOperationEvent
  • afterSetupConfigurationForCurrentOperationEvent

Yeah that would be the easy way out but... they're so ugly... and very different from Laravel's Eloquent event names. But honestly, I've yanked my brains and can't find a solution that would look laravelly... So let's go with these event names on the CrudPanel object, yes. Though I don't think we need Event at the end... right? So we could just do:

  • 🟡 beforeSetupRoutes & afterSetupRoutes
  • 🔴 beforeSetupDefaults & afterSetupDefaults
  • 🔴 beforeSetup & afterSetup
  • 🔴 beforeSetupConfigurationForCurrentOperation & afterSetupConfigurationForCurrentOperation

And I just realised... those are useful when you want to target ALL operations... but they aren't really useful when you want to target a particular operation. So perhaps we should also trigger some operation-specific events by default? eg.

  • 🟡 beforeSetupCreateRoutes & afterSetupCreateRoutes
  • 🟡 beforeSetupCreateDefaults & afterSetupCreateDefaults

Another scenario is building the event system not coupled with the functions, but we create the events for our "lifecycle". So having listeners with more general names like BeforeOperationListener extends OperationListener, where you could for example define a property or have a static method or use regexed functions

I... didn't understand any of this, sorry 😅 The way I see it, we shouldn't provide a way to consume/use those events. We just trigger them, like any Laravel events. And if we DO provide a custom way to use them... that way should probably be similar to using Eloquent Model events - that's what I would find most intuitive. Instead of doing Product::deleting($closure) you'd do CRUD::beforeSetupRoutes($closure) 🤷‍♂️ or if we don't want a catch-all (to minimize the potential impact) we could do CRUD::onEvent('beforeSetupRoutes', $closure) or something like that. That's what I find intuitive, at least.

tabacitu avatar Mar 10 '23 08:03 tabacitu