Wednesday, December 21, 2011

What is the use of hook_enable?

To show a message after a module gets installed we can use the hook_enable.

For example:

If a module requires a necessary permission to access that module, as soon as the admin installed that module in the drupal admin, we need to show them a message to enable the necessary access permission to access this module at the top.

/**
 * Implementation of hook_enable().
 */
function module_name_enable() {
  drupal_set_message(t('Your module enabled. Don\'t forget to <a href="@link">set permissions</a>.', array('@link' => url('admin/user/permissions', array('fragment' => 'your_custom_module')))));
}




Tuesday, November 22, 2011

How to theme a CCK input form?

NOTE: CCK2 makes theming easier, for CCK2 and Drupal 6 please read here: Theme a CCK input form for CCK2
(Originally posted at http://drupal.org/node/98253)
The reason I have come up with this step by step overview of themeing input forms was that I was working with CCK created content types myself and was trying to figure out how to change the order of the fields of the input form. What I found in the forums was very technical (pointers to the API in 'developer speak') or incomplete, or simply did not cover input forms. There was a lot of help for people looking to modify/theme output, but nothing clear and concise for theming input forms.
So, as a non-developer, semi-technical, marketing/business type person, I set out to discover how to 'theme' my input forms. (All those developers and others that are better informed than I, please feel free to correct me where I am wrong!) I found there are at least two different ways to theme input forms:
  1. Using the Form API (creating new .module files programmed in php and using things like 'hook_form_alter')
  2. Creating tpl.php files
I have found that it is far easier to use the second method. You actually end up having to do a little more than create a custom tpl.php file - you have to modify template.php, which requires a little bit of PHP knowledge as well as work with stylesheets (either edit style.css or create a new one and link it to your theme - more on this later).
First off, there are a couple people who are responsible for the bulk of the content in the tutorial and deserve proper credit: Lyal (http://www.harostreetmedia.com) - thanks for emailing code snippets in the middle of the night. Dublin Drupaller (http://www.dublindrupaller.com) - thanks for the rich depth of knowledge you share with others on the forums from which I have gleaned and repurposed much. jghyde - who has helped out others on this very same quest. Nick Lewis (http://www.nicklewis.org) - whose website is full of helpful and insightful Drupal information.
Now on with the show.

How do you theme a CCK input form?

Assumptions

  • You understand a little CSS (how it works, how you use class= and id= in HTML tags to style the output)
  • You understand a little PHP (nothing serious, at least the ability to understand what a PHP code snippet is doing so you can copy it and modify it a little)
  • You have CCK installed and know how to create content types with it (although I am referring to CCK input forms in this tutorial, I am pretty sure these are the same steps you would use for any custom node type)

Steps

Step 1: Create your CCK content type
Step 2: Create a [yourcontenttype].tpl.php file
Step 3: Modify template.php
Step 4: Modify style.css
You should be able to modify the input form, pretty much anyway you want with this method. For this example, I am going to do the following: Not show some of the automatically generated 'location' fields (I have 'location' module installed and enabled for my CCK content type), then create my own 'collapsible' group and put the elements that I want to in that group, and put some of the input fields side by side instead of each one being on a new line.
Even with the method I am using, there are different ways to accomplish the same thing; for example, I am using tpl.php to order the fields and .css to style them. I think I could just as easily use .css to do everything (but I am no CSS guru) and only use the custom tpl.php file to assign new <div>'s.

Step 1: Create your CCK content type

Create a CCK content type called 'event_listing' and add some fields to it. I have added contact information, location, event information fields etc.
Create at least one node (create an event listing with your new content type).
Screenshot 1

Step 2: Create a [yourcontenttype].tpl.php file

Now create a text file called 'event_listing_edit.tpl.php' and put it in the directory of your selected theme (which is somewhere under the '/theme/' directory. For example, my template.php file is found here: /theme/internet_jobs/). You could call this pretty much anything, but it will make a lot more sense and be easier to manage if you call it something like this.
Now add the following PHP code snippet to the tpl.php file - this is simply sample text to prove that your 'next step' (modifying template.php) is actually working.
<?phpprint("yahoo, it works!"); ?>

Step 3: Modify template.php

Now the hard part - we need to open and edit your template.php file which is again in the directory of your selected theme (in my case it is located here: /theme/internet_jobs/template.php)
You will need to add two seperate functions in this file, one to call your custom event_listing_edit.tpl.php file when the form is being edited and another one to call it when a NEW node is to be created (you only need one tpl.php file, but as the template.php file modifications are overriding default functionality, it is necessary to instruct drupal to use the custom file for each case.
At the end of the template.php file, add the following snippets which you should be able to see is two seperate override functions:
<?php// Add Form Start (jghyde)if ((arg(0) == 'node') && (arg(1) == 'add') && (arg(2) == 'content_event_listing')){
  function
phptemplate_node_form($form) {
    return
_phptemplate_callback('event_listing_edit', array('user' => $user, 'form' => $form));
  }
}
// Add Form End

// Edit Form Start (Dublin Drupaller)
if ((arg(0) == 'node') && (arg(2) == 'edit')){
 
$node = node_load(array('nid' => arg(1)));
  function
phptemplate_node_form($form) {
    return
_phptemplate_callback('event_listing_edit', array('user' => $user, 'form' => $form));
  }
}
// Edit Form End?>
You can see from the snippets who actually wrote them (although I have modified them slightly from their original) - thank you jghyde and Dublin Drupaller (http://drupal.org/node/85908).
Now try to edit your event_listing node you should see the text 'yahoo, it works' on the page - see screenshot. If you don't get the 'yahoo' message, there a couple of 'suspects' to look at: go check out your naming convention in the template.php file, I tripped up and referred to my tpl.php file incorrectly a few times before I got it right.
Screenshot 2
The next step is to add all the fields you want back onto the input form. You can find out what fields are available to your form by putting the following line of code in your custom tpl.php file (Tip from goose2000 for outputting data into a nicer format)
<?phpprint("yahoo, it works!<br>");
print(
"<pre>");print_r(array_values($form));
print(
"</pre>");?>
You will see a great big long list of information describing the fields available to your input form, the part you are interested in looks like this (there will be a section like this for every field and object on the form):
[field_website] => Array
  (
    [0] => Array
      (
        [value] => Array
          (
            [link] => www.janze.com            [title] => Janze.com
            [attributes] =>
          )
      )
  )
In this example, if I want to refer to the website URL, I would refer to it like this:
<?php['field_website']['0']['value']['link'] ?>
. So if I want to add the website URL to my input form I would add the following line to my tpl.php file:
<div id="jpj8"><?php print form_render($form['field_website']['0']['value']['link']); ?></div>
(I have wrapped the line in a 'div id=' tag so I can style it using CSS)
Now if I edit my event_listing node, I will get something that looks like this:
Screenshot 3
Don't forget to delete the test line that adds 'yahoo, it works!'.
Now go ahead and add the rest of the fields you want to the form.
If you want to make a group of fields that collapse, all you have to do is wrap those particular fields with <fieldset class=" collapsible"></fieldset> and if you want the Group to have a name add <legend>Contact Info</legend> right after the opening fieldset. Here is an example:
<div class="jpj8aa">
  <fieldset class=" collapsible">
    <legend>Contact Info</legend>
    <div id="jpj8"><?php print form_render($form['field_name']); ?></div>
    <div id="jpj8a"><?php print form_render($form['field_email']); ?></div>
    <div id="jpj8b"><?php print form_render($form['field_phone_0']); ?></div>
    <div id="jpj8c"><?php print form_render($form['field_website']['0']['value']['link']); ?></div>
    <div id="jpj8e"><?php print form_render($form['field_description']); ?></div>
  </fieldset>
</div>
This will look like:
Screenshot 4

Interesting bits

It is a bit odd, but at the end of your tpl.php file you put the
<?phpprint form_render($form); ?>
line which will render all remaining form objects (fields and buttons) that have not previously been referred to. That means it will now display all fields that you have not explicitly added in previous lines of code. Now, if you are like me, the reason you didn't explicity add them to the form is because you DON'T want them to be there!
So, to get rid of the fields that have now been automatically added back in, I have found two methods, one that worked for me (that I am sure is 'wrong' because it isn't very elegant) and another that is very elegant, but didnt' work for me. I would definitely try the 'elegant' route first......which is, you have to override unwanted fields explicity in your template.php file. For example, if I do not want to display the website, I put this text
<?php
$form
['field_website'] = ''; ?>
in the template.php file, inside your override function (before the callback). Reading this line of code shows us that we identify the field on the form and set its value to '' - nothing. Here is what the function would look like:
<?php// Add Form Start (jghyde)if ((arg(0) == 'node') && (arg(1) == 'add') && (arg(2) == 'content_event_listing')){
  function
phptemplate_node_form($form) {
   
$form['field_website'] = '';
    return
_phptemplate_callback('event_listing_edit', array('user' => $user, 'form' => $form));
  }
}
// Add Form End

// Edit Form Start (Dublin Drupaller)
if ((arg(0) == 'node') && (arg(2) == 'edit')){
 
$node = node_load(array('nid' => arg(1)));
  if (
$node->type == 'content_event_listing'){
    function
phptemplate_node_form($form) {
     
$form['field_website'] = '';
      return
_phptemplate_callback('event_listing_edit', array('user' => $user, 'form' => $form));
    }
  }
}
// Edit Form End?>

How to restrict user roles to access specific categories only in Taxonomy?

Access to content can be restricted by category using the Taxononmy Access:
http://drupal.org/project/taxonomy_access

How to disable modules manually in the database?

MySQL command line

To disable a module using the MySQL command line, run the following SELECT to look at the state of your data before the change. This will help you to find the full name of the module too.

SELECT name,status FROM system WHERE type='module';

Then to disable your module, set the status to 0 for the module name that you want to disable.

UPDATE system SET status='0' WHERE name='module_name';

Check your handiwork using the SELECT statement again.

How to log in once you have turned your site off-line for maintenance?

Once you have turned your site off-line using admin » settings » site maintenance(admin/settings), you can log back in by visiting:

http://example.com/?q=user
Note: Use the literal word user, not your username or user id. Do, however, replace example.com with the proper URL parts pointing to your website.

You need to enter the username and password of an account with permission to administer site configuration. User 1 has this ability as a safety net, should you not have this turned on in other administrator account(s).

If you attempted to log in with a username that does not have the "administer site configuration" permission you will be stuck in that user account until you clear the browser's cookies. Simply instruct your browser to delete cookies for the site and visit the referenced URL above again. You can also use another browser to access the URL.

To return the site to online mode visit the following page:

Drupal 4: administer » settings (admin/settings)
Drupal 5&6: Administer » Site configuration » Site maintenance (admin/settings/site-maintenance).

Friday, November 18, 2011

Expire a specific user role exactly 7 days after the user was created?


In User management, go to the Roles administration and create a new user role. Call it trial user, for instance.

Creating a rule set as a scheduling action

  • Go to "admin/rules/rule_sets" and click on the tab "Add a new rule set".
  • Fill out the label with "Expire user role {rule_set}".
  • In the Arguments fieldset, on the first row select "User" as data type, enter "User {argument}" as the label and "user_argument" as the machine name.
  • Press the "Save" button to continue.
  • You are redirected now to the rule sets overview page and your freshly created rule set is listed.
  • Click on the "Expire user role {rule set}" label and add a new rule by clicking the "Add new rule" tab.
  • Fill out the label of the new rule with "Expire action {rule}" and click on "Save changes".
  • You are now on the edit page of this rule. We want to add an action by clicking on "Add an action".
  • Click on the "Select an action to add" drop down, choose "Remove user role" and then click Next.
  • Select the role you created in the initial preparations - trial user, and click Save.

Creating a triggered rule

  • Our simple rule set is now completed and is ready for scheduling.
  • To trigger the rule set we need to invoke it on a certain event, so we go to the triggered rules page ("admin/rules/trigger") and click on "Add a new rule".
  • Fill out the label with "Expire rule {triggered rule}" and select "User account has been created" from the event drop down box.
  • Hit "Save changes" to create the rule. On the resulting page click "Add an action", where we will schedule our rule set.
  • Select "Schedule Expire user role {rule set}" from the select box and confirm the action by clicking Next.
  • Now we adjust the scheduling information: Append "{action}" to the label at the top.
  • Under "Arguments configuration", select "registered user" from the drop down. The difference between "registered user" and "acting user" is registered user is the actual new user account that is created upon signup whereas acting user is the user account that is used to perform the task. In the case of a new signup, this user is the Anonymous user.
  • You must enter a value in the Identifier text field. This will show up in the scheduled rule sets task list and so you can enter a value that will refer to the user. Enter "User [account:user]" which will result in the new user's login name being listed in the scheduled rules task list.
  • Enter a date or value in the "Scheduled evaluation date" text box below. You could put a value such as "+7 days" to schedule the expire role task to run in 7 days time.
  • Click save and your triggered rule is now set up.

Testing

At this point we are ready to do a little test.
  • Either logout of your Drupal installation or fire up another browser and go to the signup page (user/register).
  • Create your new user and return back to your administration account to confirm.
  • go to the rule set scheduling page ("admin/rules/rule_sets/scheduling"). You can see now a task entry in the task list that contains a scheduling date in 7 days and the identifier is set to the username of the new user.