Problem Solution: Special Pythagorean triplet(projecteuler.net)

Future Technology

public class SpecialPythagoreanTriplet {

public static void main(String[] args) {
// TODO Auto-generated method stub

long sum = 0, total = 1000;

for (double a = 1; a <= total / 3; a++) {
for (double b = 1; b <= total / 2; b++) {

double c = total - a - b;
double e = Math.pow(a, 2);
double f = Math.pow(b, 2);
double g = Math.pow(c, 2);

sum = (long) (a * b * c);

if (Math.pow(a, 2) + Math.pow(b, 2) == Math.pow(c, 2)) {
System.out.println("a: " + a + " b: " + b + " c: " + c);
System.out.println("e: " + e + " f: " + f + " g: " + g);
System.out.println("Sum: " + sum);
}
}
}

}

}

View original post

Problem Solution: Special Pythagorean triplet(projecteuler.net)

public class SpecialPythagoreanTriplet {

public static void main(String[] args) {
// TODO Auto-generated method stub

long sum = 0, total = 1000;

for (double a = 1; a <= total / 3; a++) {
for (double b = 1; b <= total / 2; b++) {

double c = total - a - b;
double e = Math.pow(a, 2);
double f = Math.pow(b, 2);
double g = Math.pow(c, 2);

sum = (long) (a * b * c);

if (Math.pow(a, 2) + Math.pow(b, 2) == Math.pow(c, 2)) {
System.out.println("a: " + a + " b: " + b + " c: " + c);
System.out.println("e: " + e + " f: " + f + " g: " + g);
System.out.println("Sum: " + sum);
}
}
}

}

}

Constants php

Syntax

You can define a constant by using the define()-function or by using the const keyword outside a class definition as of PHP 5.3.0. Once a constant is defined, it can never be changed or undefined.

Note: Constants and (global) variables are in a different namespace. This implies that for example TRUE and $TRUE are generally different.

Example #1 Defining Constants

<?php
define
("CONSTANT""Hello world.");
echo 
CONSTANT// outputs "Hello world."
echo Constant// outputs "Constant" and issues a notice.
?>


Example #2 Defining Constants using the const keyword

<?php
// Works as of PHP 5.3.0
const CONSTANT 'Hello World';

echo CONSTANT;
?>

Conditional stylesheets

<!--[if lte IE 8]><link rel="stylesheet" href="lte-ie-8.css"><![endif]--> <!--[if lte IE 7]><link rel="stylesheet" href="lte-ie-7.css"><![endif]--> <!--[if lte IE 6]><link rel="stylesheet" href="lte-ie-6.css"><![endif]-->
**************************************************************************
/* Main stylesheet */ .foo { color: black; } /* lte-ie-8.css, for IE8 and older */ .foo { color: green; } /* lte-ie-7.css, for IE7 and older */ .foo { color: blue; } /* lte-ie-6.css, for IE6 and older */ .foo { color: red; }
**************************************************************************
<!--[if lt IE 7]><html><![endif]-->
<!--[if IE 7]>   <html><![endif]--> <!--[if IE 8]>   <html><![endif]--> <!--[if gt IE 8]><!--><html><!--<![endif]-->
**************************************************************************
.foo { color: black; }
.ie8 .foo { color: green; } /* IE8 */ .ie7 .foo { color: blue; } /* IE7 */ .ie6 .foo { color: red; } /* IE6 and IE5 (but who cares, right?) */
**************************************************************************
.foo {
  color: black;   color: green\9; /* IE8 and older, but there’s more… */   *color: blue; /* IE7 and older */   _color: red; /* IE6 and older */ }
**************************************************************************
 
 
 

Adding a ‘More’ link on Drupal

Main topic described: Block system, Render arrays, Menu system
Main function described: drupal_set_title()

With this last addition to the module, we will pull together what you have learned about the block system, the menu system, and render arrays, and throw in a workaround for a minor bug in the current version of Drupal 7.

It may have occurred to you that access to this page belongs not in the ‘Navigation’ menu, but through a ‘More’ link at the bottom of the ‘Current posts’ block. That was the plan all along, but we started with a menu link to show how it works.

If you looked at the Default theme implementations referenced back in Generating block content, you may have noticed the theme_more_link theme hook. We’ll use that, along with a theme hook suggestion, to theme the ‘More’ link for our block.

Child render elements

We’ll start by converting the call to theme_item_list into a render array as we did in the page function. We’ll also make it a child of block[‘content’] to allow for the ‘More’ link as a sibling. Here’s the revised code for the last section of current_posts_block_view:

<?php
else {
//Pass data through theme function.
$block[‘content’][‘posts’] = array(
‘#theme’ => ‘item_list__current_posts__block’,
‘#items’ => $items,
);
?>

Remember not to include the PHP markers in your code.

We move the item list code to $block[‘content’][‘posts’], making it a child element. You can name the child element whatever you like, as long as it doesn’t start with a hash mark (#). We convert the call to theme_item_list into a render array, then add the __current_posts theme hook suggestion. This we follow with a second suggestion in case a themer wants to render the lists in the block and page differently.

Here’s new code for the ‘More’ link to add directly after the last listing:

<?php
//Add a link to the page for more entries.
$block[‘content’][‘more’] = array(
‘#theme’ => ‘more_link__current_posts’,
‘#url’ => ‘current_posts’,
‘#title’ => t(‘See the full list of current posts.’),
);
}
?>

Here we make the ‘More’ link a sibling to the posts array and provide the two parameters this theme hook requires, the path and title. The title provides text which will appear as a tooltip when the mouse hovers over the link. We give this theme hook a suggestion as well.

Edit current_posts_menu()

At this point, we have links to the page both in our block and in the ‘Navigation’ menu. We don’t want a link in the menu, so we’ll edit current_posts_menu() to take it off. All you need to do is change the type attribute for the page item. Delete MENU_NORMAL_ITEM and replace it with MENU_CALLBACK. This type provides a path and attributes only, with no menu link. Should you have your module enabled, you’ll need to disable then re-enable it for this change to take effect.

Page title fix

Enable your module and follow the ‘More’ link in the block, then note the page title. ‘Home’? Not what we had in mind. This is caused by a bug in the first version of Drupal 7. (If you see the ‘Current posts’ title, you are using a later version that is not in release at the time of this writing.) There is a patch in the works, but we need to code for the current release. Even when the bug is fixed, we can’t be certain that our module won’t be used on an installation that has not been updated.

The workaround is to use the function drupal_set_title(). Add the following to the beginning of your _current_posts_page() function:

<?php
drupal_set_title(‘Current posts’);
?>

With this addition, you can be sure the correct title will appear on the page, no matter which version of Drupal 7 your module is installed in.

Check

Check your module functionality one final time. If you have been following along, the last thing to check is the corrected page title, ‘Current posts’. If you have problems getting your code additions to appear, try clearing the caches or disabling then re-enabling your module.

View the code

You can view all the code for the .module file here: current_posts.module

See also

Adapting the query

Main topic described: Database API

The new page function will do almost the same work as current_posts_block_view, which derives its data from our custom function, current_posts_contents. Now the benefit of writing a separate function for our database query becomes apparent. All we need to do is edit it to take an argument and adjust some of the query code, and it will be ready to go for the page.

Here’s the edited code:

<?php
function current_posts_contents($display){   //$display argument is new.
//Get today’s date.
$today = getdate();
//Calculate midnight a week ago.
$start_time = mktime(0, 0, 0,$today[‘mon’],($today[‘mday’] – 7), $today[‘year’]);
//Get all posts from one week ago to the present.
$end_time = time();

$max_num = variable_get(‘current_posts_max’, 3);

//Use Database API to retrieve current posts.
$query = db_select(‘node’, ‘n’)
->fields(‘n’, array(‘nid’, ‘title’, ‘created’))
->condition(‘status’, 1) //Published.
->condition(‘created’, array($start_time, $end_time), ‘BETWEEN’)
->orderBy(‘created’, ‘DESC’); //Most recent first. Query paused here.

if ($display == ‘block’){
// Restrict the range if called with ‘block’ argument.
$query->range(0, $max_num);
} //Now proceeds to execute().
//If called by page, query proceeds directly to execute().

return $query->execute();
}
?>

First of all, we add the $display argument to the function. Then, in the query statements, we pause building the query by adding a semi-colon after the orderBy method. We then get the function’s argument value and decide how to continue. If the argument is from the block, we pick up the query object and restrict the range, then proceed to execute. If it’s from the page, we exclude the range() method and proceed straight to execute, thus including all the available posts.

Editing current_posts_block_view

To make this code work as it did in the current_posts_block_view function before the change, we must add one word to one line of code:

<?php
$result = current_posts_contents(‘block’);
?>

Adding the word ‘block’ as an argument to the function call is all it takes.

Specifying a custom permission for a new page

Specifying a custom permission for a new page

Drupal hooks described: hook_permission(), hook_menu()

So far we have our working block and a settings form. The block displays a maximum number of links. However, there may be more links than the maximum we show. So we’ll create a page that lists all the content that was created in the last week.

Custom permission

First, we’ll create a custom permission, using hook_permission(). The permissions this hook defines can be configured at People > Permissions (tab), or http://example.com/admin/people/permissions. Only user roles with this permission granted will have access to the page we will create.

Add this to your .module file:

<?php
/**
* Implements hook_permission().
*/
function current_posts_permission(){
return array(
‘access current_posts content’ => array(
‘title’ => t(‘Access content for the Current posts module’),

); 
}
?>

This hook follows the typical Drupal pattern of attributes defined in arrays. The main key is the machine readable name of the permission, which we will use in our hook_menu() implementation. ‘title’ provides the human-readable name of the permission, to be shown on the permission administration page. This should be wrapped in the t() function for translation. See hook_permission() for all the available options.

Registering the URL and naming the page function

We’ll need to edit current_posts_menu() to establish a path and name for the new page. A quick note on function naming conventions in Drupal: If you are creating a strictly private function (i.e. no other module should rely on it being a stable function or call it), start the function name with an underscore: “_your_module_name_”. If your function is public (i.e. it would be okay for another module to call it, and you don’t intend to change its argument signature or behavior often), start the function name with “your_module_name_” (no underscore). If you are implementing a Drupal hook, you must always name the function “your_module_name_hookname”. Likewise, if you are not implementing a Drupal hook, check the hooks to be sure you have not accidentally picked a function name matching a hook.

Page callbacks are good candidates for strictly private functions, so we will start with an underscore, then the module name, and finally the word, ‘page’. Add the following code to your current_posts_menu() function as the second item in the $items array. Be sure the code, return $items; is the final line of the function, and remember not to include the php markers.

<?php
$items[‘current_posts’] = array(
‘title’ => ‘Current posts’,
‘page callback’ => ‘_current_posts_page’,
‘access arguments’ => array(‘access current_posts content’),
‘type’ => MENU_NORMAL_ITEM, //Will appear in Navigation menu.
);
?>

This listing mirrors the previous menu item with a couple of exceptions. The first needed a description for the Configuration page. That’s less important here, and we are not including it. Because we are creating a page function and not calling drupal_get_form, we have no page arguments to pass. The new permission becomes the access argument. Since we are not using the admin/config path, our item will appear in the Navigation menu.

Check

Enable your module again and check the Navigation menu. You should see a listing for Current posts. If it’s not there, try clearing the caches. Because we have not yet written the page function, the link leads to a blank page, and you may get an error message. Remember to disable your module before continuing.

See also

how to develop module for registration process drupal 7

Telling Drupal about your module

Main topic described: .info files

All modules must have a ‘modulename.info’ file, which contains meta information about the module.

The general format is:

name = Module name
description = A description of what your module does.
core = 7.x

For our module, we will replace ‘modulename’ in the example above with the name of our module, ‘current_posts’. Without this file, the module will not show up in the module listing. Here are the contents:

name = Current posts
description = A block module that lists links to recent posts.

core = 7.x

Add the source above to a file named current_posts.info and save it into the module’s directory at sites/all/modules/current_posts.

Note: If you copy and paste this code block, ensure that the description data does not contain a line break (turn off word-wrap on your text-editor to be sure). Otherwise, the .info file will not parse correctly.

.Info File Details

name (Required)
The displayed name of your module. It should follow the Drupal capitalization standard: only the first letter of the first word is capitalized (“Example module”, not “example module” or “Example Module”).
name = Current posts
description (Required)
A short, preferably one line description that will tell the administrator what this module does on the module administration page. Overly long descriptions can make this page difficult to work with, so please try to be concise. This field is limited to 255 characters.

description = A block module that lists links to recent posts.

Descriptions can contain links to documentation and sources. The following example shows a link to the author. It could be a link to a documentation node on Drupal.org. This is useful when the online documentation is better than the readme file and when you want to read about a module before switching it on.
description = Domain manager by <a href=”http://petermoulding.com”>Peter Moulding .com</a>.

core (Required)
The version of Drupal that your module is for. For Drupal 7 this would be 7.x, etc. Note that modules cannot specify the minor version of a branch of Drupal. 6.x is correct; 6.2 is not.

core = 7.x

files (Optional)
Drupal now supports a dynamic-loading code registry. To support it, all modules must now declare any code files containing class or interface declarations in the .info file, like so:

name = Example module
description = “Gives an example of a module.”

files[] = example.test

When a module is enabled, Drupal will rescan all declared files and index all the classes and interfaces that it finds. Classes will be loaded automatically by PHP when they are first accessed.

dependencies (Optional)
There are a couple of extra options that may appear in the .info file, one of which are module dependencies. If a module requires another module to be enabled, list each module (filename) required in the following syntax:

dependencies[] = taxonomy
dependencies[] = comment

For the example module, these don’t apply and we will simply omit them. If dependencies are assigned for a module, Drupal will not allow it to be activated until the required dependencies are met.

package (Optional)
If a module has a package string, on the admin/build/modules page it will be listed with other modules with the same category. If a package string is not assigned, it will simply be listed in the ‘Other’ category. Not assigning a package for your module is perfectly ok; in general packages are best used for modules that are distributed together or are meant to be used together. If in doubt, leave this field blank.

package = “Your arbitrary grouping string”

Suggested examples of appropriate items for the package field:

  • Administration
  • Commerce
  • Development
  • Fields
  • Media
  • User interface
  • Views
  • Voting (if it uses/requires VotingAPI)

.info files have several other optional categories that are rarely used or discouraged and are not relevant to this tutorial. See Writing .info files (Drupal 7.x), if you want all the details.

Check

Your module should now appear in the module list in your site. Go to Modules and scroll down to the bottom of the list in the ‘Other’ category. You should see the module ‘Current posts’.

Writing comments and implementing your first hook

Drupal hook described: hook_help()

Comments in Drupal modules

It’s always a good idea to document how your module works in comments. Drupal uses Doxygen to draw documentation from source code, so contrib modules on drupal.org follow strict comment guidelines. See Doxygen and comment formatting conventions for more details. Following these guidelines is beneficial to anyone looking at your code even if it’s not strictly necessary for your situation.

Your first comment:

<?php
/**
* @file
* A block module that displays recent blog and forum posts.
*/
?>

@file signifies that this comment pertains to the entire file. The doc block begins with a slash and two asterisks (/**) and ends with one asterisk and a slash (*/). Following Drupal guidelines, we will introduce each function in the module with such a comment.

Implementing your first hook

Hooks are fundamental to Drupal modules. They allow you to integrate your module into the actions of Drupal core. If you missed it, go back and read about hooks in Introduction to Drupal modules.

Your first hook is hook_help. This hook is recommended for inclusion in all contrib modules. hook_help provides help and additional information about the module to the user. To implement any hook in Drupal, replace “hook” in the hook name with your module’s short name, and create a function in the .module file with that name. So, to implement hook_help() in our example module, we create a function called current_posts_help() in the current_posts.module file:

<?php
function current_posts_help($path, $arg) {

}
?>

The $path parameter provides context for the help: where in Drupal or the module the user is when they are accessing help. The recommended way to process this variable is with a switch statement. This code pattern is common in Drupal modules. Here is an abbreviated implementation of this function for your module, along with its doc block comment:

<?php
/**
* Implements hook_help.
*
* Displays help and module information.
*
* @param path
*   Which path of the site we’re using to display help
* @param arg
*   Array that holds the current path as returned from arg() function
*/
function current_posts_help($path, $arg) {
switch ($path) {
case “admin/help#current_posts”:
return ‘<p>’.  t(“Displays links to nodes created on this date”) .'</p>’;
break;
}
}
?>

(Note the closing ?> should not appear in your code.)

The admin/help#modulename case is used by Drupal core to link from the main help page (/admin/help or ?q=admin/help). You will eventually want to add more text to provide a better help message to the user; see Help text standard for the complete recommendation. The t() function that wraps the text marks it for translation. This function not only allows for translation, it can give your code an added layer of security. See Localization API for more information.

Check

Look again at the module list by clicking Modules on the Toolbar in your Drupal installation. Enable the module and click ‘Save configuration’. Close and reopen the Modules page, find your module in the list, and you should see a link to ‘Help’ on the right. Click it to see the help text returned by current_posts_help. You can also follow the Help link in the toolbar (http://example.com/admin/help) and find your help link listed with the others on that page.

Disable your module and save (‘Save configuration’ button). Important: Be sure you follow that last step and disable your module and save, or new partial code in your module could break your site.

Declaring the block

Drupal hook described: hook_block_info()

Modules are created to do all sorts of things: create blocks (abbreviated content that often appears on the right or left side of multiple pages), create special content types (for full page content – such as the content you are reading right now), track back-end information, and more. You may hear the term ‘block modules’ used to describe modules that primarily create block content (such as the menu module), or ‘node modules’ used to describe modules that primarily generate full page content (such as the blog and forum modules). At this stage, this module is a ‘block module’, because it generates a block.

In Drupal 7, there are at least eight block hooks. For the purposes of this module, we will use two of them. The first is hook_block_info(). As you might suspect, this hook tells Drupal what block(s) your module creates. We will use this hook to define a block that will eventually display the most recent posts. You can use a given hook exactly once in any module, so this hook must declare all blocks the module needs. For this module, a single block is all we need.

To use this hook to define our block, go to your current_posts.module file and create the function current_posts_block_info() as follows:

<?php
/**
* Implements hook_block_info().
*/
function current_posts_block_info() {
$blocks[‘current_posts’] = array(
‘info’ => t(‘Current posts’), //The name that will appear in the block list.
‘cache’ => DRUPAL_CACHE_PER_ROLE, //Default
);
return $blocks;
}
?>

(Remember not to include the closing ?> in your code.)

The doc block simply identifies the hook. For such a straightforward implementation, that is sufficient. Anyone reading the code can easily go to the API and call up the hook for further information.

The return value takes the form of an associative array. Pay special attention to this array structure, as it is Drupal’s preferred programming structure. Arrays in PHP are well supported and very fast, and Drupal makes extensive use of them.

The only required value is ‘info’. hook_block_info can also specify configuration settings. Here we set the cache to the default. See hook_block_info for a complete list of settings available.

Don’t forget the final return statement.

Check

At this point, go to Modules, click the checkbox to enable Current posts, and save your configuration. Next, navigate to Structure > Blocks. Scroll down to the bottom of the list. Among the disabled blocks, you should find the name, ‘Current posts’. Return to Modules, disable your module and save. Important: Be sure you disable your module and save, or new partial code in your module could break your site.


See Also
hook_block_info

Retrieving data

Main topic described: Database API
Main function described: db_select()

Next we will create a custom function to retrieve the most recent posts. When a node is first created, the time of creation is stored in the database. We’ll use this database field to find our data. We could include this code in the hook we will implement in the next tutorial page. Putting this section into a separate function keeps the code cleaner, easier to read and to maintain.

We will call the function current_posts_contents. We continue to follow the naming convention by beginning with the module short name. Then we use a descriptive word that is not a Drupal hook. The function begins with getting the time numbers. Here’s the first part:

<?php
/**
* Custom content function.
*
* Set beginning and end dates, retrieve posts from database
* saved in that time period.
*
* @return
*   A result set of the targeted posts.
*/
function current_posts_contents(){
//Get today’s date.
$today = getdate();
//Calculate the date a week ago.
$start_time = mktime(0, 0, 0,$today[‘mon’],($today[‘mday’] – 7), $today[‘year’]);
//Get all posts from one week ago to the present.
$end_time = time();
?>

This code gets the current time, then calculates the time (in seconds since epoch start, see mktime for more information on time format) for midnight a week ago. These functions are straight PHP; you can look them up on the PHP website (php.net) for more details.

Next we use Drupal’s Database API to retrieve our list of current nodes. This is the second part of the custom function:

<?php
//Use Database API to retrieve current posts.
$query = db_select(‘node’, ‘n’)
->fields(‘n’, array(‘nid’, ‘title’, ‘created’))
->condition(‘status’, 1) //Published.
->condition(‘created’, array($start_time, $end_time), ‘BETWEEN’)
->orderBy(‘created’, ‘DESC’) //Most recent first.
->execute();
return $query; 
}
?>

Built into Drupal is a very robust query builder, using a special object-oriented API. INSERT, UPDATE, and DELETE queries need this special care in order to behave consistently across all different databases. Although our SELECT query doesn’t require this structure, this is a good opportunity to become familiar with it. You will see this structure used throughout Drupal.

  1. We build the query using the db_select method, which takes a table name (‘node’) and alias (‘n’) as arguments.
  2. The fields method uses the table assigned the alias ‘n’ to select the fields listed in the array in the second argument.
  3. The condition method takes three arguments. The first is the field, the second the value, the third the operator. If no operator is specified, as in ‘status’ above, = is assumed.
  4. The orderBy method sorts according to the field in the first argument, in the order specified by the second argument.
  5. The execute method compiles and runs the query and returns a result set/statement object.

Here’s the complete function:

<?php
/**
* Custom content function.
*
* Set beginning and end dates, retrieve posts from database
* saved in that time period.
*
* @return
*   A result set of the targeted posts.
*/
function current_posts_contents(){
//Get today’s date.
$today = getdate();
//Calculate the date a week ago.
$start_time = mktime(0, 0, 0,$today[‘mon’],($today[‘mday’] – 7), $today[‘year’]);
//Get all posts from one week ago to the present.
$end_time = time();

//Use Database API to retrieve current posts.
$query = db_select(‘node’, ‘n’)
->fields(‘n’, array(‘nid’, ‘title’, ‘created’))
->condition(‘status’, 1) //Published.
->condition(‘created’, array($start_time, $end_time), ‘BETWEEN’)
->orderBy(‘created’, ‘DESC’) //Most recent first.
->execute();
return $query; 
}
?>

(Remember not to include the closing ?> in your code.)

Generating block content

Drupal hook described: hook_block_view()
Main functions described: user_access(), l(), theme()

The next step in this tutorial is to take the data we generated in our custom function and turn it into content for the block. We will do this using hook_block_view. This function returns two values, ‘subject’, which is the title of the block, and ‘content’, which is self-documenting. Once again, we will use a switch structure. This structure allows for additional blocks to be added in the future if needed. The $delta parameter tells the function which block is being requested.

Access check

Here’s the first part of the code:

<?php
function current_posts_block_view($delta = ”) {
switch($delta){
case ‘current_posts’:
$block[‘subject’] = t(‘Current posts’);
if(user_access(‘access content’)){
//Retrieve and process data here.
}
?>

Best practice dictates that information displayed to the user be assessed against that user’s permissions. Here we implement the most basic of checks, ‘access content’. You can use any permission here that Drupal supplies, or even create your own. For a list of permission names, go to People > List (tab) (or http://example.com/admin/people). In the permission dropdown there, you will find a list of the machine readable names that you can use in your code. This list will include all permissions active on your site, including those created by contrib modules. The names in the Permissions tab (http://example.com/admin/people/permissions) are not the machine readable names.

Another way to find permissions set in core modules is through the API reference. Enter the module name followed by _permission, for example, node_permission. You’ll get a list of all the permissions that node defines. Knowing which one to use might be a bit tricky. For example, the access content permission we use here is actually defined in the node module, not the block module.

Coding the data as links

Here’s the next bit of code:

<?php
//Use our custom function to retrieve data.
$result = current_posts_contents();
//Array to contain items for the block to render.
$items = array();
//Iterate over the resultset and format as links.
foreach ($result as $node){
$items[] = array(
‘data’ => l($node->title, ‘node/’ . $node->nid),
);
}
?>

First we use our custom function to save the data into the $result variable. The $items variable gives us a place to store the processed data. We then iterate over the resultset, processing each item and formatting it as a link.

Notice the actual link is created by the l() function. (That’s a small case ‘L’.) The first parameter sets the link text, in this case the node’s title. The second parameter is the actual link path. The path to any node is always “node/#”, where # is the ID number of the node. l() uses this path to generate appropriate links, adjusting the URL to the installation’s URL configuration.

Theming the data

Drupal’s presentation layer is a pluggable system known as the theme layer. Each theme can take control of most of Drupal’s output, and has complete control over the CSS. Theming in Drupal is a vast subject with entire books devoted to the subject. Here we will merely touch the surface with a theme function.

Here’s the last section of code for current_posts_block_view:

<?php

if (empty($items)) { //No content in the last week.
$block[‘content’] = t(‘No posts available.’); 
} else {
//Pass data through theme function.
$block[‘content’] = theme(‘item_list’, array(
‘items’ => $items));
}
}
}
return $block;
}
?>

First, we allow for the possibility of no content that fits our criteria. Your module’s block should appear whether or not new content from the last week exists on your site.

If the $items variable contains data, it goes to the theme() function. The first argument of this function is the theme hook. Drupal includes many default theme hooks you can use with this function; see Default theme implementations for the complete list. We have chosen to theme our data as an unordered list, the theme_item_list theme hook. The second argument passes the content to be themed.

You may wonder why the code takes this form if the function is theme_item_list. theme() looks for a theme function called theme_hookname, where ‘hookname’ is the first argument, in this case, item_list. In other words, the second part of the hook name becomes the first argument when the function is called, telling the theme function which of its default versions to use.

The whole function

<?php
/**
* Implements hook_block_view().
*
* Prepares the contents of the block.
*/
function current_posts_block_view($delta = ”) {
switch($delta){
case ‘current_posts’:
$block[‘subject’] = t(‘Current posts’);
if(user_access(‘access content’)){
//Use our custom function to retrieve data.
$result = current_posts_contents();
//Array to contain items for the block to render.
$items = array();
//Iterate over the resultset and format as links.
foreach ($result as $node){
$items[] = array(
‘data’ => l($node->title, ‘node/’ . $node->nid),
);
}

if (empty($items)) { //No content in the last week.
$block[‘content’] = t(‘No posts available.’); 
}
else {
//Pass data through theme function.
$block[‘content’] = theme(‘item_list’, array(
‘items’ => $items));
}
}
}
return $block;
}
?>

(Remember not to include the opening or closing PHP tags when you add this section.)

Testing and troubleshooting the module

It’s time to enable and fully test your module!

Enable the module

Go to Modules, or http://example.com/admin/modules, and scroll down to the bottom of the list in the ‘Other’ category. You should see the module ‘Current posts.’ Click the checkbox to enable Current posts, and save your configuration. Now you should see a link to Help beside the module name. Click it to see the help text you entered in current_posts_help.

Enable the block

Next, navigate to Structure > Blocks, or http://example.com/admin/structure/block. Scroll down to the bottom of the list. Among the disabled blocks, you should find the name, ‘Current posts’. Set its location for one of the page regions and save. Navigate to another page like your homepage to see your block. Congratulations! You have written a working module.

Troubleshooting

If you get a “white screen” or a PHP error when you enable this module, it probably means you have a syntax error in your .module file. Be sure all your punctuation is correct, semi-colons, commas, etc. all in the right places, and that you have all the hook names and module short names spelled correctly. (In the case of a white screen, you may be able to find out what the PHP error was by looking in your Apache error log. Or you can try changing PHP’s error reporting level.)

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. The easiest way to get your site working again is to delete the module’s folder or move it out of the site, in which case Drupal will figure out that it shouldn’t load this module after all, and your site should work again.

Clear caches

Drupal caches a lot of data, and if you are not seeing changes appear, that could be why. In this phase of the module, the caches shouldn’t be an issue, but they will be as we proceed. To get all the troubleshooting instructions in one place, we’ll give you the instructions here that you’ll need later.

To clear the caches, go to Configuration > Performance or http://example.com/admin/config/development/performance, and click the Clear all caches button.

Preparing for a module configuration form

Drupal hook described: hook_menu()
Main function described: drupal_get_form()

Now that we have a working module, we’d like to make it more flexible. With a busy site, we might not want to display all the links to content created last week. So we’ll create a configuration form where the administrator can adjust how many links to display.

Registering the URL

We will define our form using hook_menu(). The name of this hook is a bit misleading, as it does far more than simply assign menu items. Using this hook, modules register paths to define how URL requests are handled. Paths may be registered for URL handling only, or as a link to be placed in a menu (usually the Navigation menu). In this case, we will set a path that will make the form available from the Configuration page (http://example.com/admin/config).

hook_menu() implementations return an associative array whose keys define paths and whose values are an associative array of properties for each path. The definition for each path may include a page callback function, which is invoked when the registered path is requested. After we have set up our form in hook_menu, we will create the actual form by writing the page callback function we define here.

Access check

hook_menu() also provides an important part of Drupal’s security, as it performs user access checks. We would like only administrators to be able to access this form, and we’ll check that permission here in hook_menu(). To minimize the number of permissions an administrator has to deal with, we’ll use the core administration permission instead of creating a new custom permission.

In Drupal’s menu system, ‘title’ and ‘description’ attributes are automatically translated. Throughout Drupal, you are encouraged to use the t() function on all string literals. This is one place where you must remember not to do that.

Here’s the code:

<?php
/**
* Implements hook_menu().
*/
function current_posts_menu() {
$items = array(); 

$items[‘admin/config/content/current_posts’] = array(
‘title’ => ‘Current posts’,
‘description’ => ‘Configuration for Current posts module’,
‘page callback’ => ‘drupal_get_form’,
‘page arguments’ => array(‘current_posts_form’),
‘access arguments’ => array(‘access administration pages’),
‘type’ => MENU_NORMAL_ITEM,
);

return $items;

?>

(Remember not to include the opening or closing PHP tags when you add this section.)

Setting properties

The path set as the array key for $items becomes the path to our form. It must take the form of an internal Drupal path with no leading or trailing slashes. We begin the path with admin/config to tell Drupal to include a link to this form on the site administration page (Configuration or http://example.com/admin/config). content tells Drupal which section of this page the link belongs to, in this case, Content authoring. You can choose any one of the default sections for your form by including its path name here.

Next comes the value, the associative array that lists properties of the item. title and description, as noted previously, are without the t() function. We include the administrator permission under access arguments, and the value of type is the default. This listing will not appear in any menu, only on the Configuration page.

Declaring the form

page callback tells Drupal what to call when the link is requested, in this case, drupal_get_form, the “key” function in the Form API. (Note that the trailing parentheses are not included in the call to drupal_get_form.) page arguments values are passed to that function. By assigning current_posts_form, we define that as both the form ID and the name of the function that will create our settings form. As the name of a function, it must follow PHP variable naming conventions, with no spaces or hyphens. To prevent name collision, always start the function name with the name of your module, followed by an underscore.

We’ll begin to explore the Form API as we build that function in the next part of the tutorial.

See also

Creating the configuration form

Main topic described: Form API
Main functions described: variable_get(), system_settings_form()

Next, we will build the current_posts_form() function. We build the form by adding elements to the $form array. In a pattern similar to the menu $items variable, the name of each element is its key in the array, with that key’s value being a specially formatted associative array. In this value array, we list the attributes of the element, this time preceding each key with a hash mark (#).

Add the following to your current_posts.module file:

<?php
/**
* Form function, called by drupal_get_form()
* in current_posts_menu().
*/
function current_posts_form($form, &$form_state) {
$form[‘current_posts_max’] = array(
‘#type’ => ‘textfield’,
‘#title’ => t(‘Maximum number of posts’),
‘#default_value’ => variable_get(‘current_posts_max’, 3),
‘#size’ => 2,
‘#maxlength’ => 2,
‘#description’ => t(‘The maximum number of links to display in the block.’),
‘#required’ => TRUE,
);

return system_settings_form($form);
}
?>

(Remember not to include the opening or closing PHP tags when you add this section.)

The element attributes

Here we create a text field, with a title of ‘Maximum number of posts’, and a description, which will appear below the field. Note that both of these strings are passed through the t() function for translation. Size is 2, maximum length is 2. The Form API will automatically validate the maxlength attribute when the form is submitted and throw an error if the length exceeds 2. We have also designated the field as required. The form API will mark it with an asterisk and will throw an error if the form is submitted with no value in the field. See the forms_api_reference for the complete list of available elements and properties.

Persistent variables

Certain data, like system settings and user-configurable information, needs to be saved and retrievable for a website to function properly. Drupal accomplishes this through the use of persistent variables. These variables are stored in a database table with keys provided by the implementing module.

The function variable_get() retrieves a persistent variable, and variable_set(), as you might expect, sets one. We use variable_get() above to retrieve the value of our field if it has been set. If not, we specify a default value of 3. variable_get() uses the name of the element, current_posts_max, to find the relevant data.

System settings

Drupal makes it easy for us to save the form’s data with the function system_settings_form(). By using the function in our code, we tell Drupal to provide a submit button and to save data into persistent variables using variable_set(). It will also provide a green confirmation message when data is successfully saved, and a red error message if something went wrong. If you prefer, you can create a submit function yourself, (see Form API Quickstart Guide) but for now, we will use this handy shortcut.

Editing the query

We must add two lines of code to our query function, current_posts_contents, one using variable_get() to retrieve the data from our settings form, and the other adding the range function to include this limit in the query. Here’s the revised function, with the new lines noted in comments:

<?php
function current_posts_contents() {
//Get today’s date.
$today = getdate();
//Calculate midnight a week ago.
$start_time = mktime(0, 0, 0,$today[‘mon’],($today[‘mday’] – 7), $today[‘year’]);
//Get all posts from one week ago to the present.
$end_time = time();

//NEW LINE
$max_num = variable_get(‘current_posts_max’, 3);

//Use Database API to retrieve current posts.
$query = db_select(‘node’, ‘n’)
->fields(‘n’, array(‘nid’, ‘title’, ‘created’))
->condition(‘status’, 1) //Published.
->condition(‘created’, array($start_time, $end_time), ‘BETWEEN’)
->orderBy(‘created’, ‘DESC’) //Most recent first.
->range(0, $max_num) //NEW LINE
->execute();
return $query;
}
?>

Using variable_get(), we save the configuration setting into the $max_num variable or assign a default of 3. Then we add the range method to our select query. That method’s first argument is set to zero to specify starting at the beginning of the set. The second argument, $max_num, determines how many records to return.

Check

Go ahead and again enable your module. Then you will need to clear the menu cache, so that Drupal will recognize the new URL. (Drupal caches a lot of data, including a list of all the URLs it recognizes.) To clear the cache, go to Configuration > Performance or http://example.com/admin/config/development/performance, and click the Clear all caches button.

Now you can test the settings form. Navigate to it: Configuration > Content authoring > Current posts or http://example.com/admin/config/content/current_posts. Adjust the number of links and save the configuration. The maximum number of links in the block should adjust accordingly. See how system_settings_form() has added a submit button and gives you a confirmation message when you have successfully saved.

Please note: be sure to disable your module before continuing.

See also

Validating the data

Main topic described: Form API
Main functions described: _validate(), form_set_error()

The Form API supplies excellent default validation, but it also allows us to create our own validation function. We want to be sure that the value the user enters is a number greater than 0. The validation function works much like a hook, with the form ID taking the place of the module name. Our validate function will be named current_posts_form_validate($form, &$form_state). Don’t confuse this with hook_validate(), which is part of the main hook system.

Notice the $form_state array variable, an argument here and also for our form function. $form_state is passed by reference along through each stage of form processing to capture information about the form’s workflow and its current state. Incoming $_POST data is first sanitized and checked against the structure of the form before being handed off to validate and submit handlers. The array’s values key is the default key for storing this data. See drupal_build_form() for a list of $form_state keys.

Add this function to your current_posts.module file:

<?php
/**
* Implements validation from the Form API.
*
* @param $form
*   A structured array containing the elements and properties of the form.
* @param $form_state
*   An array that stores information about the form’s current state
*   during processing.
*/
function current_posts_form_validate($form, &$form_state){
$max_num = $form_state[‘values’][‘current_posts_max’];
if (!is_numeric($max_num)){
form_set_error(‘current_posts_max’, t(‘You must enter an integer for the maximum number of posts to display.’));
}
else if ($max_num <= 0){
form_set_error(‘current_posts_max’, t(‘Maximum number of posts to display must be positive.’));      
}
}
?>

(Remember not to include the closing ?> in your code.)

Testing the data

First we retrieve the configuration setting from $form_state and save it into a variable. We then check to be sure it’s a number. If not, form_set_error() goes into action, setting the element in the first argument with an error CSS class (red by default). It also displays a red box with the error message given in the second argument.

If the data passes the first check, we make sure it’s a positive number. If not, we again call form_set_error() Notice that both our string literals for error messages are wrapped in t().

Check

Enable your module again and visit the configuration page. Experiment with entering values to see how the validation works on errors. Be sure to disable your module before you add more code.

See also