I created a custom module that redirects the user based on various custom rules. My problem is figuring out where to place the code. Right now, I have:
function mymodule_init() {
mymodule_redirect_now();
}
The "mymodule_redirect_now" generally does not do anything in most cases, but sometimes it may result in "drupal_goto" being fired off. This works in practice, but causes other issues:
Where would be the most correct place to put redirect logic like this, to avoid failing unit tests and failing cron jobs?
UPDATE
I've tried to simplify this question, by rather bringing it down to one more simple question. Basically, I want to know how to stop cron from executing the following code:
function mymodule_init() {
mymodule_redirect_now();
}
Cron always executes anything in init, but in this case, let's imagine that the redirect has the following logic:
function mymodule_redirect_now()
{
if (!$currentPathIsUS && $ipIsUS) { // lets pretend for now this always happens...
drupal_goto("us");
}
}
Basically, if the use has a US IP and the current path is not the US path, it must redirect them to the /us path.
The problem is, if I run cron from the command line, or from a browser, it hits the above code before moving on to any other function, but because of the "drupal_goto", it doesnt ever actually execute the cron code.
hook_init()
will always run at the start of the request as you have noticed.
When you say "… redirects the user based on various custom rules." what do you mean? Is the user being redirected when submitting a form with some content? Is the user being redirected if visiting a (or a set of) specific URL's? What conditions are there? Is it the Rules module?
Depending on which custom rules you mean there will be different answers. For example if the rules has something to do with nodes (loading, viewing, editing, …) you have to use hook_node_$op()
where $op
can be e.g. "view", or "load", or "submit". As an example:
// Redirect user when submitting a node of type 'book'
function mymodule_node_submit($node, $form, &$form_state) {
if ($node->type === 'book') {
drupal_goto("some/place/else");
}
}
There are two issues at play here as I see it. One is where in the code to place redirect logic which in Drupal 7 (and 6) does not really have a good short answer, it all depends on the context. It could be in response to a form loading or a form submitting or a node loading or viewing or editing (et.c.) or a number of other conditions. These conditions necessitate that the redirect logic be on different places in your code. This is what I was concentrating on answering above.
The second issue, which upon reading your clarifications seems to be the main culprit, is of a different type. Cron and unit tests will not have all the info a regular web browser visitor have.
You will have to detect if cron is running and not redirect when that happens. As you see on in the link above cron creates a temporary (anonymous) user and won't save any session data. This has a tendency to break many cron runs. Because drupal_exit()
more or less kills everything.
As for unit testing drupal_goto()
, I am less sure here, but I believe it breaks for the same reason. You could try to mock part of the function to actually not redirect.
And as a side note you may want to consider using hook_url_inbound_alter() (more info). It might or might not be compatible with exactly what you want to do. Look at what the Redirect module does, especially the function redirect_can_redirect()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With