• No results found

5   Case study 59

5.3   Drupal case study 64

5.3.1   Development environment 64

Drupal does not have an IDE specifically designed to develop new code for Drupal, therefore any IDE 

capable of developing PHP code can be used. For the use cases in this research, the choice was made to 

use Eclipse with the PHP development tools extension [56], since there was previous positive experience 

with developing in Eclipse. 

Extending Drupal is done by making extensions called modules. All that has to be done to make a new 

Drupal module is to create a folder containing two files, a .info with information about the module, like 

its name and description, and a .module file with the actual code. The folder containing the files must be 

uploaded to the server in order to be used.  

 

Figure 21: Drupal module file structure 

The following setup was used to implement the use cases for Drupal: Pentium D 2x3Ghz, 2G Ram, Linux 

Debian 2.6.32‐5‐amd64, Apache 2.2.16, PHP 5.3.3.7, MySQL 5.1.61, Drupal Commons 6.x‐2.4. 

5.3.2

Usecases

This section implements the use cases described in section 5.2 implemented in Drupal. The work 

required implementing these use cases, and the results of the implementation are given.   

Use case 1: Create an extension

This use case gives some basic static information to the user. The goal of this use case is to determine 

how to make a module and to discover any problems when developing new modules.  

To show content at a page in Drupal using a module, a predefined function has to be implemented to 

display this content. This function expects the developer to return an array containing the content to be 

displayed by this module. The line “Hello world” is added to this array, and the array is returned. The 

code from the file usecase1.module used to implement use case 1 is shown below. The $block array is 

used to return the output of this module. The variable $op contains the operation, in this case there are 

2 options: ‘list’ and any operation that is not ‘list’ . The code inside the if($op==”list”) is used by Drupal 

to display the name of a module when displaying the list of available modules for a block. Inside the 

$block[‘content’] is the actual content of the module.   

 

After the module is uploaded to the server, it needs to be enabled at the module configuration page. 

Finally, after the module is enabled, it needs to be placed in a block on the website. Each Drupal page is 

divided into multiple blocks, for example header, sidebar and content. For each page, the content of a 

block can be specified. A block can contain static information, but also modules. There are 2 ways to add 

modules to the blocks. At the blocks page, /admin/build/block, modules can be added to blocks that 

need to be displayed on every page, for example in the menu. Adding a module to a single page can be 

done by creating a custom context for that page that contains the module, and use this context to add 

the module to that page. Custom contexts can be used to trigger certain actions on certain conditions. In 

this case an action is triggered to add the use case 1 module to the sidebar last block when the node 

type is group. This adds the module to the group pages.   

 

Figure 23: A Simple hello world use case in Drupal 

Creating a new module in Drupal was straightforward with the available tutorials. The amount of code 

required to only display one line is relatively high, 10 lines of code just to echo one line. Adding a 

module to a single page using custom contexts was relatively complex. 

function usecase1_block($op = 'list', $delta = 0, $edit = array()) { $block = array();

if ($op == "list") {

$block[0]["info"] = t('Use Case 1');

}else{

$block['subject'] = 'Use case 1'; $block['content'] = 'Hello world'; }

return $block;

}

Use case 2: Underlying platform functionality

The goal of this use case is determining how to use the functions of the underlying platform concerning 

the currently logged in user. To achieve this goal, a module will be made which displays the username of 

the currently logged in user. In this section, the steps required to achieve the goal are given. 

A global variable containing information about the currently logged in user is available to the developer. 

One piece of information is the username. The username is displayed in the same way as use case 1. The 

following piece of code displays the username of the currently logged in user:   

 

Implementing this use case was simple for Drupal, the username was available from the global object 

$user. Drupal has a set of global variables and functions available, ranging from user information to 

configuration variables, which makes accessing underlying platform functionality simple. 

Use case 3: Access restriction

The goal of this use case is to restrict access to an extension to a certain role. To achieve this goal, only a 

user with the role “usecase_viewer” is able to see the content of the module “usecase3”.  Drupal offers 

the possibility to create custom permissions, and an API function to check if a user has a role that 

contains that permission. By calling this function with the required role as a parameter the platform 

checks if the user has the required role, and if this is the case, access is granted. This allows access 

restriction to the module. Once the custom permission is created at the administrator panel and the 

check is added to the code, the next step that needs to be done is to create a role that contains that 

permission, and assign this role to the user, which can be done from the configuration menu. In this case 

the permission “view use case” was given, which grants permission to view the module. This permission 

was given to the role “usecase_viewer”. Finally, the role “usecase_viewer” was given to the user.   

 

Figure 25: Drupal roles 

function usecase2_block($op = 'list', $delta = 0, $edit = array()) {

global $user;

$username = $user->name; $block = array(); if ($op == "list") {

$block[0]["info"] = t('Use Case 2');

}else{

$block['subject'] = 'Use Case 2'; $blockcontent = 'Hello '.$username;

$block['content'] = $blockcontent;

}

return $block;

}

It is not possible to give different permissions per instantiation of the module. It is however possible to 

create a custom role for a user for a community, and assign permissions for a module to this role. This 

way, since the role is only relevant for the instantiation of the module, permissions can be given to a 

user per instantiation of the module, unless of course when there are multiple instances of a module 

within community. So restricting access to a module is relatively easy, but limited. 

Use case 4: Group data

The goal of this use case is to display the name of the community, the users and their roles for the 

community the module is used in. After retrieving the group node id, which is a unique identifier for a 

group, a query can be used to determine the group members. Displaying the group members and their 

roles is done the same way as use case 1. 

The code below shows a query to get the usernames from a certain group, and the code required to get 

the current group id.   

   

 

After the users from a group are known, the next step is to get the roles for the users for that group. For 

each user this is done with a query: 

Summary

Once the underlying functionality to retrieve the current group was known, implementing this use case 

was straightforward.   

Use case 5: External data consumption

The goal of this use case is to consume data from an external source using web services. To achieve this 

goal, a SOAP client has to be implemented and integrated into a module. This SOAP client gets the local 

time provided by a web service. The most straightforward to consume web services with Drupal is to use 

the SOAP client from PHP [57].  This client takes the WSDL file from the web service, and creates a class 

with the same functions as defined in this WSDL file.   

 

$groupid =og_get_group_context()->nid;

$query = "SELECT users.name,users.uid FROM {users} users, {og_uid} og WHERE og.nid='%d' AND og.uid=users.uid";

$query_result = db_query($query,$groupid); 

$zipcode = "10001";

$soapclient = @new SoapClient(

"http://www.ripedevelopment.com/webservices/LocalTime.asmx?wsdl=0" ,array("cache_wsdl"=>WSDL_CACHE_NONE));

$result = $soapclient->LocalTimeByZipCode( array("ZipCode"=>$zipcode)); $time = $result->LocalTimeByZipCodeResult;

Figure 28: Drupal use case 5 implementation 

$query2 = "SELECT roles.name FROM {role} roles, {og_users_roles} our WHERE our.gid='%d' AND our.uid='%d' AND our.rid=roles.rid";

$query_result2 = db_query($query2,$groupid,$users->uid);

Figure 26: Drupal use case 4 implementation, getting group users

The syntax of the functions which should be called was not always clear due to bad documentation and 

code  complexity of  the  web service  specification, so implementing this  use  case  proved  more 

challenging than expected. After the correct syntax was determined, the information could be retrieved 

from the SOAP call and this information was displayed the same way as use case 1. The code used to 

acquire data from the web service called functions from the PHP API, not from the Drupal API. 

Therefore, the difficulties that arose while implementing this use case do not give any indication about 

the development in Drupal.   

Use case 6: Automated tasks

The goal of this use case is to create an automated task that runs at a fixed time without user 

interaction. This goal is achieved by creating CRON like functionality, in other words to assign some 

scheduling functionality to call a predefined job at certain times. To create a CRON like function in 

Drupal, the modulename_cron hook can be implemented. This function is called every time cron.php is 

run. Running cron.php is up to the developer, by either using system crontabs, or by using a module that 

calls cron.php on access. 

The code shown below retrieves the local time from the web service from use case 4 and stores this 

time in the database:   

   

 

To our current knowledge, there is only 1 function which calls the hook_cron functions on all modules. 

There is a function to check when the hook_cron was last called. It is up to the module developer to 

determine if interval between the last function call and this function call was large enough and if any 

action should be taken 

Another thing to consider is the following: If – for some reason‐ a Cron job with a very short interval is 

required, then cron.php must be called at a very short interval. The Cron functions of all the modules 

will be called often; even when this might not be required since their interval is large, thereby creating 

significant overhead.   

Use case 7: Configuration page

The goal of this use case is to store settings for module. To achieve this goal, a configuration page where 

these settings can be created and stored will be made. In Drupal, there are two places to place a 

configuration page: As a subpage of the extension or at the configuration menu. The configuration menu 

allows centralized access to all configuration pages, allowing easier management of the platform. 

However, it does require that the user wanting to access to this administration page to have access to 

the configuration menu. This configuration page should only be used to store settings relevant to every 

instance of the module.  

function usecase6_cron(){

$zipcode = variable_get("usecase5_greeting", "10001"); $soapclient = @new SoapClient(

"http://www.ripedevelopment.com/webservices/LocalTime.asmx?wsdl=0" ,array("cache_wsdl"=>WSDL_CACHE_NONE));

$result = $soapclient->LocalTimeByZipCode( array("ZipCode"=>$zipcode)); $time = $result->LocalTimeByZipCodeResult;

$query = "INSERT INTO {hoekie_usecase6}(time,adddate) VALUES('%d',NOW())"; db_query($query,$time);

To add a configuration page to the configuration menu in Drupal, the modulename_admin() hook has to 

be implemented to create a configuration page. Also, the modulename_menu() hook has to be 

implemented to create a menu item linking to the configuration page. This configuration page can be 

used to set global settings for the module, not user/group specific settings. When storing configurations 

per instance of the module/per group that uses the module, a subpage of the module should be 

created. In this case, storing the information set in the configuration page is up to the developer. 

The creation of this configuration page and creation of a link to this page is up to the developer. The 

code below shows a simple form with 1 field where you can set a zip code:   

   

 

Implementing a configuration page is easy in Drupal, there is functionality to retrieve and store the 

information entered, as well as put restrictions on the values entered.   

Summary

In this section, the results of the use case evaluation for Drupal were discussed. For each use case, the 

implementation of that use case was given, along with some code examples. When the implementation 

was not straightforward, or when limitations of the platform arose, these were also given in the report. 

A summary of the results can be found in the evaluation per use case in section 5.5.2.   

In the next section, the same use cases will be evaluated for Liferay. 

5.4

Liferay

The previous section implemented the use cases created in section 5.2 using Drupal, and gave the 

results. This section does the same for Liferay. First it discusses the development environment used to 

implement the use cases for Liferay, followed by the results of the implementation of the use cases. 

5.4.1

Developmentenvironment

Liferay Inc has created an IDE to develop new functionality for the Liferay portal, Liferay IDE. Liferay IDE 

is an extension to the Eclipse IDE in the form of a set of Eclipse plug‐ins and offers functionality to create 

Liferay extensions such as portlets and themes. For every use case in this chapter a new portlet will be 

created, a more detailed description about creating portlets will be given later. Before a portlet can be 

created, a project to contain the portlets must be created.  

When creating a new Liferay project, several files will be generated. Among these files are several XML 

files containing project settings and properties. Several folders are created where the files generated 

function usecase7_admin() { $form = array(); $form['usecase7_greeting'] = array( '#type' => 'textfield', '#title' => t('Zipcode'), '#default_value' => variable_get('usecase7_zipcode','10001'), '#size' => 20, '#maxlength' => 20,

'#description' => t("The zipcode"), '#required' => TRUE,

);

return system_settings_form($form); }

when creating a new portlet will be placed. Finally, multiple libraries containing support functionality, 

such as logging, axis and WSDL are included. 

When creating a new portlet using the Liferay API, several things happen. Information about the portlet 

is added to the projects settings XML files. A java class is created where the implementation of the 

functionality of the portlet should be placed. The file view.jsp is created where the code to display the 

content of a portlet should be placed. 

 

Figure 31: File structure of a Liferay project with 1 portlet 

The Liferay IDE has several ant scripts to deploy the created portlet on the server. Using these scripts 

requires the server to be able to remotely deploy new portlets, or for the server to run locally.   

To deploy the portlets containing the code for the use cases, the following server setup was used: AMD 

Phenom 2x 3Ghz, 4GB Ram, Windows 7 64 bit, Tomcat 7.0.23, MySQL 5.5.22, Liferay Portal Community 

Edition 6.1.0 CE   

5.4.2

Usecases

This section implements the use cases described in section 5.2 in Liferay. It gives the work required 

implementing these use cases, and the results of the implementation. 

Use case 1: Create an extension

This use case gives some simple static information to the user. The goal of this use case is to determine 

how to make a portlet and to discover any problems while developing a new portlet. To develop a 

portlet, the steps from section 5.4.1 describing the creation of a new portlet must be followed. After the 

portlet is created, the line “Hello World” to the can be added to the file that is displayed when calling 

the portlet. The file that needs to be called on portal initialization can be changed at the portlets 

configuration file, portlet.xml. By default when using the Liferay IDE to create portlets this file is view.jsp. 

After adding the “Hello world” line the portlet is finished and can be deployed to the server. To show 

this portlet to a user, a new page designated to contain the portlet should be created at the control 

panel and the deployed portlet must be drag‐and‐dropped to this page.   

 

Figure 32: A simple Liferay portlet 

For this use case, the data to be shown was “Hello world” and to achieve this, the line “Hello world” was 

added to the file view.jsp. Implementing this use case was straightforward.   

Use case 2: Underlying platform functionality

The goal of this use case is figuring out how to use the functions of the underlying platform concerning 

the currently logged in user. To achieve this goal, a portlet will be made which displays the username of 

the currently logged in user. In this section, the steps required to achieve the goal are given. 

To find the username of the currently logged in user, several steps are required. First, the id of the 

currently logged in user must be retrieved. This user id can be retrieved from the renderRequest object, 

which represents the request sent to the portlet to handle a render. This id can then be used to get a 

User object from the Liferay class providing user information. This User object contains information 

about the user, including its name. Displaying the name was done the same way as displaying hello 

world from use case 1. The jsp code to be created by the developer to display the username of the 

currently logged in user is shown below:    

   

 

Implementing this use case proved more challenging than expected. Using the renderRequest to get the 

user id was not straightforward, and this solution was only found after doing some research on the 

Liferay forums. This is a typical issue when developing with Liferay and only using the API, for every class 

the functions are given, but can be hard to find to correct class. The classes used concerning User and 

Related documents