Stonemind WEB A Few Drupal Recipes

A Few Drupal Recipes

I am finishing a Drupal based project which required that I explore areas of Drupal that were new to me. The result is that I have some snippets of code to share for certain situations that might be generally useful. In these, I tried to use what I understand to be Drupal best practices, such as wrapping SQL in db_query(db_rewrite_sql(…)) for example. But, I am still learning these best practices, so let me know if you see code that could be written in a more Drupal-ish manner.

Problem
I found that occassionally, Drupal would essentially try to include a PHP file twice, resulting in function being redeclared and making PHP spit out an ugly error. In my case, this happened under certain circumstances with functions declared in file based Contemplate templates. To solve the problem, I wrapped every method call in this type of check:

Solution

if (!function_exists(‘my_function’)) {function my_function { // my function code}}


Problem
Some content on the site required that a person purchase a paid subscription in order to view it. The content type definition had a field that contained references to product nodes that could be selected when the content was created, so when it comes time to display that content, I can get the node ids of the required subscription products and call this function to see if the logged in user has purchased any of those subscriptions.

Solution

function has_user_subscribed($uid, $subIDs) {$has_subscribed = FALSE;$sql = ” SELECT t.txnidFROM ec_transaction t, ec_transaction_product tpWHERE t.txnid = tp.txnidAND t.uid = %d AND tp.nid = %d AND t.payment_status = %d”;foreach ($subIDs as $subID) {$result = db_query(db_rewrite_sql($sql), $uid, $subID, payment_get_status_id(‘completed’));while ($data = db_fetch_object($result)) { $has_subscribed = TRUE; break 2;}}return $has_subscribed;}

Description
One thing in particular to pay attention to in the code above is the payment_get_status_id(‘completed’) call, which returns the primary key value for the indicated status.

This code is a little query-heavy, and for your purposes, you may be able to streamline it considerably, so that the foreach loop isn’t necessary. Also, before calling this, make sure you can get a $uid value and that the content being accessed even has any subscription products specified for it. If the content doesn’t have subscriptions specified, then you obviously don’t need to call this method, and if you don’t have a user id, then the user will need to log in to Drupal in order to see if that user has already purchased subscriptions. You get the object representing the logged in user like this:

global $user;$uid = $user->uid;


Problem
I wanted to customize the default Drupal “simple” search form to limit results by content type and vocabulary term, and I found that there are several ways of doing this, either through your theme, a module, or using something like the Views Fast Search module. In my particular case, it made the most sense to do it through the theme.

Following advice from the Drupal.org forums, I looked at the rendered page source for the advanced search screen and with a little trial and error, came up with the following addition to my theme’s template.php file.

Solution

function my_search_get_keys() {$search_string = ”;$tokens = preg_split(“/[s]+/”, search_get_keys());foreach($tokens as $token) {if (! preg_match(“/[:]/”, $token)) { if ($search_string != ”) { $search_string .= ‘ ‘; }$search_string .= $token;}}return $search_string;}/** * Theme the search form * * @param $form * The form built by the search.module * @return * The form as generated by theme_search_theme_form */function phptemplate_search_theme_form($form) { $form[‘search_theme_form_keys’] = array( ‘#title’ => t(“Search”), ‘#type’ => ‘textfield’, ‘#name’ => “keys”, ‘#value’ => my_search_get_keys()); $form[‘content-type’]= array( ‘#name’ => ‘type[story]’, ‘#value’ => ‘story’, ‘#type’ => ‘hidden’); if (isset($_SESSION[‘audience_id’])) { $form[‘category’]= array( ‘#name’ => ‘category[‘ . $_SESSION[‘audience_id’] . ‘]’, ‘#value’ => $_SESSION[‘audience_id’], ‘#type’ => ‘hidden’); } $form[‘form_id’] = array( ‘#name’ => ‘form_id’, ‘#value’ => ‘search_form’, ‘#type’ => ‘hidden’); $form[‘form_token’][‘#value’] = drupal_get_token(‘search_form’); $form[‘submit’][‘#value’] = t(‘Go’); // Now process as normal return theme_search_theme_form($form);}

Description
In this case, I store a session variable elsewhere called audience_id that contains a vocabulary term identifier, and I only limit the search by that term if I find it in the session. Also note that I am limiting the search to “story” content types.

But I found that adding these is not enough, and that I also needed to make sure the search field itself was called “keys” and that the form_id and form_token fields were explicitly added. Note that the form_token value is based on the form_id value (“search_form”); if these don’t match, Drupal spits out a validation error.

Finally, when the results screen is displayed, I didn’t want the search box to be empty, but I also didn’t want it to dispplay something like “my search terms type:story category:1” which is what the search module’s search_get_keys() function returns. So, I wrapped a call to that function in my own version called my_search_get_keys() above, which cuts out the type and category information, displaying only the search terms the user entered. Because the type and category information is always supplied via hidden fields in the form, its not necessary to display it in the search box.

Related Post