Drupal

Creating Drupal 6.x modules


  • Drupal makes use of the inversion of control design pattern, in which modular functionality is called by the framework at the appropriate time. These opportunities for modules to do their thing are called hooks. 
  • drupal module hook call order: To change the order by which a hook callback is executed in different modules:
    • Drupal assigns a weight to each module (that gets stored in system table). All hooks on the modules are by default invoked in order of module weights and in fact, this is the only way to control "hooking" order for modules in D6. Which means that for a module with lower weight, all hooks would be invoked before than the corresponding hooks on a module that has a higher weight. You cannot control the order of "hooking" on a per-hook basis in D6.

      But D7 brings with itself this wonderful new capability of controlling "hooking" order on a per-hook per-module basis with the new hook called: hook_module_implements_alter. Basically with this new hook, you can re-order the module hooking order for a specific hook.

function mymodule_module_implements_alter(&$implementations, $hook) {
  //Any change here requires Caches to be cleared.
 
  switch ($hook) {
    case 'form_alter':
      $m2 = $implementations['m2'];
      unset($implementations['m2']);

      $m3 = $implementations['m3'];
      unset($implementations['m3']);

      //hook_form_alter would be called on module m3 before module m2.
      $implementations['m3'] = $m3;
      $implementations['m2'] = $m2;
      break;

    case 'menu':
      $m2 = $implementations['m2'];
      unset($implementations['m2']);

      $m3 = $implementations['m3'];
      unset($implementations['m3']);

      //hook_menu would be called on module m2 before module m3.
      $implementations['m2'] = $m2;
      $implementations['m3'] = $m3;
      break;
  }
}
Module 1 dictates the order in which hook_form_alter is invoked on Module 2 and Module 3 by implementing hook_module_implements_alter.

http://www.rahulsingla.com/blog/2011/06/drupal-7-controlling-changing-order-of-execution-of-particular-hooks-for-modules
check :  attached here             hook_module_implements_alter.zip

index.php

The PHP page that serves all page requests on a Drupal installation. The routines here dispatch control to the appropriate handler, which then prints the appropriate page. In the default form, the addresses are like http://localhost/?q=user/1/help
while in the clean url rewriting mode you can pretend it is http://localhost/user/1/help But the first one is the true address. index.php is a dispatcher to build the page returned to the user based on the value of the q argument.

If you cannot find and fix the syntax error, nothing on your site will display, because Drupal will try to load your module on every page request.

maximum upload size 2M usually for development and back-up recivery purposes set it to 64M
/etc/php5/apache2/php.ini

When copying the whole source of a drupal project to a new location, you need to re-adjust the settings:
$ cd drupal_home_directory/sites/default/
$ rm settings.php
$ cp default.settings.php settings.php

$ chmod -R o+rw .       (give read and write permission to Other at the drupal_home_directory)



node
----
page
story


Good Modules
----
admin_menu
cck
fckeditor
imce
views


theme
Theme Engine: PHPTemplate
Common template files:
page.tpl.php
Main template for a page, including the <html/>, <head/> and   <body/> elements. The theme system provides this template access to over 30 variables. The main page template, then, isn't responsible for displaying individual nodes, blocks, comments, and so on. Instead, it is responsible for displaying regions.
It has access to each region,
node.tpl.php
Some variables like $title, $content, and $terms (taxonomy) of the node are sent to the template
block.tpl.php
box.tpl.php
$title, $content, and $region.
comment.tpl.php
a dozen variables, which pertain to the comment, the comment poster, and the context of the posting.
if a template is not available, e.g. if box.tpl.php is not available, Drupal will use www/include/theme.inc theme_box() to render the box.
page>region>node>block>
call theme('<hookname>', $arg1, $arg2,...) instead of directly calling
In short, theme() makes use of the full theme system, while calling theme_<hookname>() function directly may cause your application to ignore the current theme configuration and use only the default.
Invoking theme('images', $a, $b) causes the theme system to check for a function or template that overrides theme_image()




Making additional variables available to your templates
in themes/theme_name/template.php
<?php
function  _phptemplate_variables($hook, $vars) {
   switch($hook) {
     case 'comment' :
        $vars['newvar'] = 'new variable';
        $vars['title'] = 'new title';
        break;
   }
   return $vars;
}
?>
----------------
you can print contents of the blocks in a region by just <? print ?>

to theme a specific module, in the .module file have:
/**
  * Implementation of hook_theme().
  */
function philquotes_theme() {
   return array(
      'philquotes_quote' => array(    //philquotes_quote is name of the theme
         'arguments' => array('text' => NULL, 'origin' => NULL),
      ),
   );
}
OR  //if we wanted a template file (philquotes_quote.tpl.php) other than just theming in this method call
'philquotes_quote' => array(
   'template' => 'philquotes_quote',
   'arguments' => array( /* parameter info */ ), //pass arguments to the theme!
),
-------
/**
  * Theme function for theming quotes.
  *
  * @param $text
  * The quote content as a string.
  * @param $origin
  * The original source of the quote, as a string.
  * @return
  * An HTML themed string.
  */
function theme_philquotes_quote($text, $origin) {    //the same as parameters
    $output = '<div id="philquotes-text">'. t($text)
      .'</div><div id="philquotes-origin">'. t($origin) .'</div>';
    return $output;
}

------------------

Install

download drupal  6 from the web site. unzip it, copy all the content of the main directory created plain in the www directory of the apache.
Drupal needs permission to modify /var/www/

$ chgrp -R www-data /var/www
$ chmod -R g+rwX /var/www

create a database for the new drupal
mysql needs access to create a database
$ sudo chmod o+rw -R /var/lib/mysql


Enable Clean URLs Ubuntu
1)enable rewrite module on apache.
$ sudo a2enmod rewrite
check it is enabled by
$ apache2ctl -M
rewrite_module (shared)     -- should be among results
2)Allow override permissions
$ cd /etc/apache2/sites-enabled/
$ sudo vim 000-default
the directory that you will be using to serve webpages has "AllowOverride All" instead of "AllowOverride None"
both for <Directory /> and <Directory /var/www/>
3) /etc/apache2/httpd.conf
add the following lines: (suggested to put the path just /var/www and drupal plain in www)
<Directory /var/www/path_to_drupal_home>
   RewriteEngine on
   RewriteBase /path_to_drupal_home OR ?!
   RewriteCond %{REQUEST_FILENAME} !-f
   RewriteCond %{REQUEST_FILENAME} !-d
   RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
</Directory>


.htaccess file at the root of the server subdomain does the job. It's content is something like:
Options -Indexes

RewriteEngine On
#RewriteCond %{HTTP_HOST} ^accessmobile\.mobi$ [NC]
#RewriteRule ^(.*)$ http://www.accessmobile.mobi/$1 [L,R=301]


RewriteCond %{REQUEST_FILENAME} -f [NC,OR]
RewriteCond %{REQUEST_FILENAME} -d [NC]
RewriteRule .* - [L]

RewriteRule ^(.*)/?$ /index.php?q_string=$1 [QSA,L]



Windows installation issues
\includes\file.inc   line 911 change
elseif ($depth >= $min_depth && ereg($mask, $file))
TO
elseif ($depth >= $min_depth && mb_ereg($mask, $file))

enable rewrite_module (click wamp>apache>apache modules

at file sites\all\modules\admin_menu\admin_menu.inc line 107 delete ampersand (&) of the argument

in gmap.module for function gmap_gmap delete ampersand (&) of the argument

Eclipse

Add drupal module files to the list of known eclipse php files.
In eclipse menus: Window > Preferences
In left part of the Preferences window,
1. Open General > Content Types > PHP Content Type
Add the *.engine, *.theme, *.install, *.inc, *.module *.profile and *.test file
2. Open General > Workspace
Set text file encoding
UTF-8
Set new text file line delimiter
Unix
3. Open General > Editors > Text Editors
Check Insert spaces for tabs
4. Open PHP > Code Style > Formatter
Set Tab policy
Spaces 2


----------------------------------------------------------------------------------------------------------------------

omit ?> tags (I don't know why)
/**  */  comments , can be generated by doxygen to generate documents

Hooks (Interfaces)

<moduleName>_<hookName>()
Hooks are like interfaces in O.O. programming languages that provide implementation to an interface method signature.

moduleName_block()
operands:
$op
'list' : module should provide information about itself; e.g. in the module administration screen
return An associative array of block descriptions. one entry per $delta
$blocks[0]['info']=t('information'); //0: delta id, 'info': required associative array key
'view' : module should provide the content of the block
return an array which must define a 'subject' element and a 'content' element defining the block indexed by $delta.
'configure' : module should provide an administration UI to configure the block
'save' : called after 'configure' and the data provided by the user should be saved
return nothing.
$delta
if $op is 'view', $delta shows what content needs to be shown
can be used to show several blocks by ONE module
$edit
contains the data that needs to be saved (after the 'configure' is performed)
Returns an associative array containing block and content. if this hook doesn't return anything this modile (a block) is not shown to the region assigned.

t()

used to translate the text parameter. can have other parameters to enable html character escaping or including injectable content in the translation text parameter
based on the level of escaping desired
! Placeholders that begin with the exclamation point (!) are substituted into the string exactly as is.
t('Trying to access !url.', array('!url'=>'http://example.com'));
@ escaped using the check_plain() function. tags to escaped entities.
% not only escaped, like those that start with the @, but are also themed.
t('Replacing %value.', array('%value=>'test') will result in something like 'Replacing <em>test</em>'. The <em></em> tags are added by the translation function.



Page regions are theme dependent (e.g. left side bar, right, top, , center, ...)

_method_name: The leading underscore here indicates that this function is a private function of our module—it is a function not intended to be called by any piece of code outside of the module.

make http GET  request: drupal_http_request
Returns an object that contains the response code (from the server or the socket library), the HTTP headers, and the data returned by the remote server.

Drupal Logging Mechanism

watchdog(): log and store in database watchdog table
watchdog($type, $message, $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL)
$type: usually module name
$message:
$variables: an associative array of data ($vars) that should be substituted into the $msg
$severity:   WATCHDOG_EMERG, WATCHDOG_ALERT, WATCHDOG_CRITICAL, WATCHDOG_ERROR, WATCHDOG_WARNING, WATCHDOG_NOTICE, WATCHDOG_INFO, WATCHDOG_DEBUG
$link: A link to associate with the message.
<hookname>_watchdog()  to override the default behavior of watchdog

strip_tags($str): remove tags of $str
check_plain(): scape xml sensitive characters
check_url(): alerts on malicious urls like javascript: that you might receive from some other web service
l($title, $link): makes a hyperlink: adjusting the URL to the installation's URL configuration of either clean URLS: http://(sitename)/node/2 or not http://(sitename)/?q=node/2 (the path to any node is always "node/#", where # is the ID number of the node).


-------------------------------------
function _philquotes_get_quote() {
  $sql = "SELECT nid FROM {node} ".    //node table placeholder
        "WHERE status=1 AND type='quote' ORDER BY RAND() LIMIT 1";
  $res = db_query($sql);
  $item = db_fetch_object($res);
  // Do something with the $item.
}

drupal_add_js

  •   drupal_add_js("my.js"): This will cause Drupal to insert a reference to the my.js file in the header. The file will be assumed to be a module's JavaScript file, which means that it will be loaded before any theme JavaScript files are loaded.
  •   drupal_add_js('alert("Hello!")', 'inline'): The second argument in this method, inline, tells Drupal not to treat the data in the first argument as a file name, but as a script. The script is then inserted as-is inside a <script/> tag: <script>alert("Hello!")</script>.
  •   drupal_add_js(array("name" => "value"), 'settings'): When the second argument is settings, then Drupal will attempt to take the associative array passed in the first value and append the key/value pairs to the Drupal.settings object. In the above example, then, a script referencing Drupal.settings.name would get the string value.


Database Access
Table names in Drupal database queries are always enclosed in curly braces, such as {node}. This is necessary so that your module will support database table name prefixes.
Normally, all queries on nodes should employ the db_rewrite_sql() function, which makes sure the user viewing the page has permission to see each node that is returned.
db_query()
db_fetch_object()

Ajax

.module file:
/**
 * Implementaiton of hook_menu()
 */
function philquotes_menu() {
  $items['philquotes.json'] = array(  //registered address to be called at client
    'title' => 'Philquotes AJAX Gateway',  // title to be used at the menu
    'page callback' => 'philquotes_item', 
// call back method, called when the client sends a request to the address registered above

    'access arguments' => array('access content'),  
 // you can use permission roles declared at hook_perm() access content permission. This means any visitor who can access content can access this page.

    'type' => MENU_CALLBACK,  
// indicates what kind of item this registered page adddress above is. Based on the type, Drupal will determine how (and where) to display links to this item.
- twenty different bit masks define various conditions possible The bitmask we have chosen, MENU_CALLBACK, simply makes this item accessible by URL. It does not, though, automatically create links to this item in the menu or anywhere else.
  );
    return $items;
}

/**
 * Callback to handle requests for philquotes content.
 * @return string JSON data.
 */
function philquotes_item() {
  $item = _philquotes_get_quote();
 
  drupal_set_header('Content-Type: text/plain; charset: utf-8');
  //printf('<?xml version="1.0" ? ><quote><origin>%s</origin><text>%s</text></quote>', $item->title, $item->body);
  printf(
    '{ "quote": { "origin": "%s", "text": "%s"}}',
    $item->title,
    $item->body
  );
}

function theme_philquotes_quote($text, $origin) {
  $full_path = drupal_get_path('module', 'philquotes')
    .'/philquotes.css';
  drupal_add_css($full_path);
  drupal_add_js(drupal_get_path('module', 'philquotes')
    .'/philquotes.js');
  $opts = array('absolute' => TRUE);
  $json_url = url('philquotes.json', $opts);
  drupal_add_js(
    array('philquotes' =>
      array("json_url" => $json_url)), 'setting');
  $output = '<div id="philquotes-text">'. t($text)
    .'</div><div id="philquotes-origin">' . t($origin) . '</div>';
  return $output;
}














Subpages (2): Drupal 7.2 Modules
ċ
hook_module_implements_alter.zip
(2k)
Morteza Sh-,
Dec 24, 2011, 11:31 PM
Comments