I am trying to find out how to redirect after I insert a new node. All the answers I have been able to find discuss $form_state->setRedirectUrl(); but this is a form redirect; not a proper redirect after insertion.
The difference is that when I submit the node form; I use hook_node_insert to create another entity based on information from the node being inserted. After the parent node is inserted; I want to redirect to a path based on the entity id of the new child entity.
In hook_node_insert (for the parent; i.e. original form submit)) I set a drupal_register_shutdown_function which properly saves my child entity and I then have the ->id() of the new (child) entity.
I have seen various examples using RedirectResponse, such as this:
$redirect = new RedirectResponse(Url::fromUserInput('/admin/commerce/orders/' . $order->id() . '/payments')->toString());;
$redirect->send();
but none of these work.
EDIT
to try to line this up with @4k4's suggestion, this is where I am at:
function my_module_node_insert($node) {
$s = \Drupal::service('sia_general.redirects');
$s->createPolicyRedirect($node);
}
in my Service:
class RedirectServices implements EventSubscriberInterface {
static function getSubscribedEvents() {
$events[KernelEvents::RESPONSE] = ['gotoPolicy'];
return $events;
}
public function createPolicyRedirect($policy) {
$this->policy = $policy;
}
public function gotoPolicy(FilterResponseEvent $event) {
// We only care if this happened after policy was created.
if (!$this->policy) {
return;
}
$redirect = new RedirectResponse(Url::fromUserInput('/node/' . $this->policy->id() . '/edit')->toString());;
$event->setResponse($redirect);
}
}
when the Policy node is created; the hook_node_insert is called, which in turn calls the createPolicyRedirect() service and passes the newly created Policy object. After this it returns to the event subscriber which originally called the function which created the Policy. After that it hits the final pass of gotoPolicy(); but $this->policy is not set at this point.
Just to test that the redirect response worked as i hope; i tried setting a SESSION var in createPolicyRedirect(); but even that isn't set once i get to final gotoPolicy call.
EDIT #2
Still no luck and guessing due to the event handler within event handler that i am doing... so more context.
The complete flow is as follows:
- create App entity
- this adds items to Commerce cart
- admin adds payment
- PaymentComplete handler "places" the Order
- OrderComplete handler loads the App and sets a Workflows field and then saves the App
- during the App->save(), the change in Workflow triggers creating a Policy entity
- this triggers my hook_node_insert($policy) (note: this is still within OrderComplete event handler).
- in my insert hook i fire my 1st method above (which sets $this->policy)
- i then return to finish the OrderComplete event handler
- after the OrderComplete is finished; i hit my final run through the 2nd method (the KernelEvent); but by this time, $this->policy is no longer set.
My guess is that the ordercomplete does a page load before my kernel event is run (not sure that makes sense); so maybe this is a bug in Commerce; or at the very least i need to approach this differently, like alter what commerce is doing. Perhaps Drupal's event handling system isn't quite ready to handle situations this complex yet??
drupal_register_shutdown_function
, which seems to exist only for Batch API, you could use a symfony service, which provides two methods: One for creating the node and one for redirecting based on that node, registered as kernel response event subscriber. Similar to this service class, but you would call the first method from a hook, because you don't have an event you can subscribe to: drupal.stackexchange.com/a/291504/47547