Creating a custom Drupal module that provides a Save This Page functionality

admin's picture

In this blog I will explain how I created a custom drupal 5.x module that provides Save This Page functionality. This function is quite simple, although we haven't found any modules that provide this feature. The main functionality we had to achieve is:

1) Save any page on the site

2) Create a My Saved Pages page for users where they are able to manage their saved pages The module is really lightweight, but it uses the most important drupal hooks, so it might be useful for developers planning to create their first drupal module.

You'll definitely need to create 2 files for a drupal module to work.
1) The .module file itself
2) An .info file that will show information about your module
3) Optionally, if your module needs to install new tables in the database, you'll need to create an .install file as well that will run the database operations when you enable the module.
Important note: make sure that the parent directory of the module, the function names and the file names are exactly the same, otherwise the module won't work when you upload it.

This example module does create a new database table, so let's start with the .install file first (so we won't get confused later).
1) Create a new file called saved_pages.install
2) Copy paste this code
This code will run the first time you enable the module on your site. It will create all necessary tables for our module. Save it.

Let's create the module now.
1) Create a new file called saved_pages.module
2) Now we will add some default drupal hooks to our module. First we want to have some access control on our module, since this functionality will only work for registered users as it will check the user ID (explained later). This drupal hook will create those permission check boxes on the Access control page, enable it later for authenticated users (plus others if you have other user types), but not for anonymous users.

Now we will register some menu items in the menu system. There is a great handbook page that explains what the menu system is, how it works and how you can register items http://api.drupal.org/api/group/menu/5

'saved_pages', 'title' => t('My Saved Pages'), 'callback' => 'saved_pages_page', 'access' => user_access('access saved pages')); // Register a callback that won't be a proper page, it will be a path to a function we will create later $items[] = array( 'path' => 'saved_pages/clear', 'callback' => 'saved_pages_clear', 'type' => MENU_CALLBACK, 'access' => user_access('access saved pages'), ); } return $items; } ?>

Now we will create the function that will show the content on the page we registered in the previous step. We used 'callback' => 'saved_pages_page' so we will create this function.

t('Title'), 'field' => 'name'), array('data' => t('Date Saved'), 'field' => 'time'), array('data' => t('Clear')) ); $sql = db_query("SELECT * FROM saved_pages WHERE uid = %d", $user->uid); while ($result = db_fetch_array($sql)){ $pages = l($result['name'], $result['url']); $time = $result['time']; $sid = $result['sid']; $clear = l(t('Clear'), "saved_pages/clear/$sid"); $rows[] = array( 'data' => array_merge( array($pages), array(format_date($time, 'custom', 'Y-m-d H:i ')), array($clear) ), ); } if ( count($rows) ) { $output = theme('table', $header, $rows); } else { $output = "You don't have any saved searches."; } print theme('page', $output); } ?>

So what this function does step by step. It sends a query to the database to check the saved_pages table and fetch all values that are created by the currently logged in user. That's all we will need to show on the My Saved Pages page. We want users to be able to delete saved pages, so we need to create another function that does that. Now I'm going back to the hook_menu section, where we registered a menu callback to this function.

'saved_pages/clear', //The registered URL 'callback' => 'saved_pages_clear', // The function to run when URL is hit 'type' => MENU_CALLBACK, 'access' => user_access('access saved pages'), ); ?>

We created a link in our table output: $clear = l(t('Clear'), "saved_pages/clear/$sid"); , that will show in each row and will link to the function that removes that particular row from the database. So let's create the function itself. Basically, delete the entry that has the same ID as the URL we clicked. Then confirm that it was deleted and go back to the My Saved Pages page.

That's all nice, but how do people actually save pages? Let's have our module create a block with a form, that will have a text field and a submit button. In the text field users can give a title to their saved pages so it's easier for them to find again what they want.

So we created a simple block with name Save This Page (this will show up in the block list on the block admin page), title Save This Page (this will show on all pages when you enable the block) and we told our block to get the content via another function ('saved_pages_contents()'). We can't directly create the form in the block, so we need this extra step. So let's create the form itself.

'textfield', '#title' => t('Title'), '#description' => t('Type a title and save this page'), '#size' => 20 ); $form['url'] = array( '#type' => 'value', '#value' => $pageURL ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Save this page'), ); return $form; } ?>

So basically the first bit of this function grabs the actual URL of the page we're currently on and the second part creates the form and stores the URL value. Now we need to know what to do when the form is submitted.

uid, time()); return 'saved_pages'; } ?>

Find out the ID of the currently logged in user, use the next available ID for the 'sid' and insert into the table, insert the title, the URL, the user ID and the time into the table. Then go to the My Saved Pages page. Now the only thing left is to actually display this form in our block. If we scroll up a bit we told our block to get the content via another function:

$block['content'] = saved_pages_contents;

Let's create the function and call the form we created in it: The only thing left is to create the .info file. Create a new file called saved_pages.info

name = Saved Pages description = "Provides Save This Page functionality" version = "5.x-1.0" project = "saved_pages"

Voila. You should have a working module now. Enable the Save This Page block on the block admin page and start using the module.

62 people like this