drupal module redirect destination issue - drupal

I am working on yet another module idea. This module is simply supposed to redirect a user automatically to a specified node like in the following example code:
function test_module_init(){
drupal_goto('node/100');
}
The code is a mere example. But, the very really problem is the code keeps executing until the browser returns a "too many redirects" error message.
I understand why this is happening. What I need help with is the best hook to place my drupal_goto code so it executes once instead of the multiple times it currently does in hook_init.

Can't you just do something like this:
function test_module_init() {
if(isset($_GET['q') && $_GET['q'] == 'node/100') {
// skip goto statement
return;
}
drupal_goto('node/100');
}

The init hook you wrote fires on every page load including when you are on node/100. That's why you're getting a redirect. So the page is redirecting to itself. You really only need to redirect if you're not already on node/100. You can find this info in $_GET['q'] if you need to.
You don't need a different hook you just need to make sure that you don't call the drupal_goto if you're already on the destination page.

Related

Run checks on drupal_goto function

I have a strange issue with a drupal site and a custom form. I have a custom module that puts a form as a block...simple input field that posts a search query to a store locator.
The form keeps getting overridden and the action/url changes randomly at random times. I need a quick solution to this whilst we debug the real issue that's causing this.
I need to write an if statement that checks the drupal_goto function that goes along the lines of if drupal_goto == /store-locator then run else change the drupal_goto action to /store-locator.
Any help would be appreciated.

how to change form action url for contact form 7?

I'm using Contact Form 7 in a wordpress site with multiple forms.
I need to direct one form to a different form action url than the others.
I found the reply below for a previous thread but I'm not sure how to go about it.
Can someone specify what exact code needs to be included in "additional settings"
and what the code in functions.php would look like?
Thanks for your help!
reply from diff. thread, which I don't completely understand...
*Yes, you have to change the "action" attribute in the form using this Filter Hook wpcf7_form_action_url. (what would be the code?) You could add the hook into your theme's functions.php and then just process the form data in your ASP page.(code?) *
Since you're not familiar with PHP code at all, I'll give you a bit of a crash course in coding within the Wordpress API.
First off, you need to know the difference between functions and variables. A variable is a single entity that is meant to represent an arbitrary value. The value can be anything. A number, somebody's name, or complex data.
A function is something that executes a series of actions to either send back - or return - a variable, or alter a given variable.
<?php
$a = 1; //Number
$b = 'b'; //String *note the quotes around it*
$c = my_function(); //Call to a function called my_function
echo $a; //1
echo $b; //b
echo $c; //oh, hello
function my_function()
{
return 'oh, hello';
}
?>
Wordpress utilizes its own action and filter system loosely based on the Event-Driven Programming style.
What this means is that Wordpress is "listening" for a certain event to happen, and when it does, it executes a function attached to that event (also known as a callback). These are the "Actions" and "Filters". So what's the difference?
Actions are functions that do stuff
Filters are functions that return stuff
So how does this all fit in to your problem?
Contact Form 7 has its own filter that returns the URL of where information is to be sent by its forms.
So lets look at the basics of a Filter Hook
add_filter('hook_name', 'your_filter');
add_filter is the function that tells Wordpress it needs to listen
for a particular event.
'hook_name' is the event Wordpress is listening for.
'your_filter' is the function - or callback - that is called when the 'hook_name' event is fired.
The link to the previous thread states that the hook name you need to be using is 'wpcf7_form_action_url'. That means that all you have to do is make a call to add_filter, set the 'hook_name' to 'wpcf7_form_action_url', and then set 'your_filter' to the name of the function you'll be setting up as your callback.
Once that's done, you just need to define a function with a name that matches whatever you put in place of 'your_filter', and just make sure that it returns a URL to modify the form action.
Now here comes the problem: This is going to alter ALL of your forms. But first thing's first: See if you can get some working code going on your own. Just write your code in functions.php and let us know how it turns out.
UPDATE:
The fact that you were able to get it so quickly is wonderful, and shows the amount of research effort you're putting into this.
Put all of this in functions.php
add_filter('wpcf7_form_action_url', 'wpcf7_custom_form_action_url');
function wpcf7_custom_form_action_url()
{
return 'wheretopost.asp';
}
As mentioned before, that will affect ALL of your forms. If this is only supposed to affect a form on a given page, you can do something like this:
add_filter('wpcf7_form_action_url', 'wpcf7_custom_form_action_url');
function wpcf7_custom_form_action_url($url)
{
global $post;
$id_to_change = 1;
if($post->ID === $id_to_change)
return 'wheretopost.asp';
else
return $url;
}
All you would need to do is change the value of $id_to_change to a number that represents the ID of the Post/Page you're trying to affect. So if - for example - you have an About Page that you would like to change the Action URL, you can find the ID number of your About Page in the Admin Dashboard (just go to the Page editor and look in your URL for the ID number) and change the 1 to whatever the ID number is.
Hope this helps you out, and best of luck to you.
Great answer #maiorano84 but I think you should check form ID instead of Post. Here is my version.
add_filter('wpcf7_form_action_url', 'wpcf7_custom_form_action_url');
function wpcf7_custom_form_action_url($url)
{
$wpcf7 = WPCF7_ContactForm::get_current();
$wpcf7_id = $wpcf7->id();
$form_id = 123;
return $wpcf7_id == $form_id? '/action.php' : $url;
}
Another thing you might need to disable WPCF7 AJAX. That can be disabled by placing the following code in your theme functions.php
apply_filters( 'wpcf7_load_js', '__return_false' );
You can add actions after a successful submission like the documentation says
Adding a filter will work in the sense that it will change the action on the form but unfortunately it will also break the functionality of the plugin. If you add the filter like other answers suggest the form will keep the spinner state after submission.
You can make the form do something else on submit by using advanced settings such as:
on_submit: "alert('submit');"
more details about advanced settings here.
According to #abbas-arif, his solution works great, but have a limitation. This solution change the form's action on all forms present in post with that ID.
A better solution should be to use directly the form's ID. To get it, whit wordpress >5.2, you can use:
add_filter('wpcf7_form_action_url', 'wpcf7_custom_form_action_url');
function wpcf7_custom_form_action_url($url)
{
$cf7forms = WPCF7_ContactForm::get_current();
$Form = $cf7forms -> id;
switch($Form){
case 1:
return 'destination like salesforce url 1...';
case 2:
return 'destination like salesforce url 2...';
case 3:
return 'destination like salesforce url 3...';
default:
return $url;
}
}

Drupal error page

I would like to create a custom error page in Drupal 7. There are things like set_message, but they don't log the errors. So is there any hook or something similar to catch the error, log it and display a human error to my users?
You stated above that your goal is "catch the error, log it and display a human error to my users".
In that case you're probably looking for the functionality Try/Catch which allows you to try to run a block of code and if something goes wrong it will display a message.
In your particular case you can log the error to Drupal's database logging system with the watchdog function http://api.drupal.org/api/drupal/includes--bootstrap.inc/function/watchdog/7
Optionally you could also log this to the PHP error_log as well see http://php.net/manual/en/function.error-log.php
Then you could continue on displaying the message to the user using the drupal_set_message function that you already figured out.
The final code for what you're trying to accomplish would look something like this:
try {
// RUN YOUR CUSTOM CODE HERE
} catch (Exception $e) {
// Record the error Drupal's database log
watchdog('error_page', $e->getMessage());
// Record the error to PHP's error_log
error_log($e->getMessage());
// Display a message to the user
drupal_set_message("We're sorry, but we couldn't find the page you were looking for.", 'error');
}
drupal_get_messages() could be used to fetch an array to iterate through for the the error types of messages.
I'm not sure I made 100% sense of your question, but since you referenced drupal_set_message() i thought this might be what you were looking for.
You could handle it in hook_init(), check for messages there, if you find any, do something with it.
Redirecting on an error though could potentially break default drupal functionality like forms.

How do you use a view with arguments as the site front page in Drupal?

I have a Drupal site and I have setup a view to power the front page.
My goal is to be able to pass 0-2 arguments to the home page, that get passed into the view. However, I still need the normal Drupal pages to work. The list of arguments is known.
For example:
mysite.com/berlin/birds would pass in "berlin" as the first argument and "birds" as the second argument to the view that powers the front page.
mysite.com/berlin would just pass in one argument, "berlin"
mysite.com/admin would load the normal admin pages in Drupal
I'm not clear on how to achieve this. Is there a hook I can use? I can't find one or think of one. Is there a way to specify this in the argument for the view itself? Perhaps I can write a hook that interjects when the URL is being loaded, and rewrite in the background?
The solution I currently have is to add these paths (since my arguments are known) to the menu system. This works, except that when I the pages they aren't the front page, so the pages don't use the node themes I want (they use the node details theme).
I don't think you can really do this without custom code. The View needs a path before it starts taking arguments, and your URLs start with the arguments. What you can do is fake it with custom code. I've used something like this:
/**
* Implements hook_init().
*/
function mymodule_custom_init() {
$item = menu_get_item(); // Matching Drupal path
if (!$item) { // There is no matching Drupal path.
$_GET['q'] = 'view_path/' . $_GET['q']; // Fake path path.
} // if
} // mymodule_custom_init
Then you give the view a path of "view_path" and it responds to everything that doesn't match anything else in Drupal's paths.
There is a spot in the views UI for "Argument handling code" that takes a small snippet of php - http://drupal.org/node/70145
You could run some code there that checks to see if you are on the front page (or arguments are not present or whatever)and insert the arguments you want.
Another way is to set arguments via a hook_views_pre_view or hook_views_pre_build. Is better because you are sure you don't break other stuff (like another view block).
function MYMODULE_views_pre_view(&$view){
if ($view->name == 'your_view_name' && drupal_is_front_page()) {
$view->set_arguments(array('you_argument','you_second_argument'));
}
}

Drupal - Getting node id from view to customise link in block

How can I build a block in Drupal which is able to show the node ID of the view page the block is currently sitting on?
I'm using views to build a large chunk of my site, but I need to be able to make "intelligent" blocks in PHP mode which will have dynamic content depending on what the view is displaying.
How can I find the $nid which a view is currently displaying?
Here is a more-robust way of getting the node ID:
<?php
// Check that the current URL is for a specific node:
if(arg(0) == 'node' && is_numeric(arg(1))) {
return arg(1); // Return the NID
}
else { // Whatever it is we're looking at, it's not a node
return NULL; // Return an invalid NID
}
?>
This method works even if you have a custom path for your node with the path and/or pathauto modules.
Just for reference, if you don't turn on the path module, the default URLs that Drupal generates are called "system paths" in the documentation. If you do turn on the path module, you are able to set custom paths which are called "aliases" in the documentation.
Since I always have the path module turned on, one thing that confused me at first was whether it was ever possible for the arg function to return part of an alias rather than part of system path.
As it turns out, the arg function will always return a system path because the arg function is based on $_GET['q']... After a bit of research it seems that $_GET['q'] will always return a system path.
If you want to get the path from the actual page request, you need to use $_REQUEST['q']. If the path module is enabled, $_REQUEST['q'] may return either an alias or a system path.
For a solution, especially one that involves a view argument in the midst of a path like department/%/list, see the blog post Node ID as View Argument from SEO-friendly URL Path.
In the end this snippet did the job - it just stripped the clean URL and reported back the very last argument.
<?php
$refer= $_SERVER ['REQUEST_URI'];
$nid = explode("/", $refer);
$nid = $nid[3];
?>
Given the comment reply, the above was probably reduced to this, using the Drupal arg() function to get a part of the request path:
<?php
$nid = arg(3);
?>
You should considder the panels module. It is a very big module and requires some work before you really can tap into it's potential. So take that into considderation.
You can use it to setup a page containing several views/blocks that can be placed in different regions. It uses a concept called context which can be anything related to what you are viewing. You can use that context to determine which node is being viewed and not only change blocks but also layout. It is also a bit more clean since you can move the PHP code away from admin interface.
On a side note, it's also written by the views author.
There are a couple of ways to go about this:
You can make your blocks with Views and pass the nid in through an argument.
You can manually pass in the nid by accessing the $view object using the code below. It's an array at $view->result. Each row in the view is an object in that array, and the nid is in that object for each one. So you could run a foreach on that and get all of the nid of all rows in the view pretty easily.
The first option is a lot easier, so if that suits your needs I would go with that.
New about Drupal 7: The correct way to get the node id is using the function menu_get_object();
Example:
$node = menu_get_object();
$contentType = node_type_get_name($node);
Drupal 8 has another method. Check this out:
arg() is deprecated

Resources