Set Conditions in CakePHP pagination

In this article, we are going to discuss about How to set conditions in CakePHP pagination. CakePHP is an open source web application framework. It follows the Model-View-Controller (MVC) approach and is written in PHP, modeled after the concepts of Ruby on Rails, and distributed under the MIT License. CakePHP uses well-known software engineering concepts and software design patterns, as Convention over configuration, Model-View-Controller, Active Record, Association Data Mapping, and Front Controller.

Pagination is the process of dividing (content) into discrete pages, either electronic pages or printed pages. To get custom result in CakePHP pagination, we can set conditions. To set condition in pagination we can pass it by 'conditions' tag.

Example of set conditions in pagination:

//Ready the conditions array()
$conditions = array();
if(isset($districtID)){
          $conditions[] = array('Subscriberpost.district_id' => $districtID);
}
if(isset($categoryID)){
          $conditions[] = array('Subscriberpost.service_category_id' => $categoryID);
}
$this->Subscriberpost->recursive = 1;
//Set the conditions for pagination
$this->paginate = array('conditions' => $conditions);
//Pass the pagination value to view file
$this->set('subscriberposts', $this->paginate()); 

Steps to create Image Gallery in CodeIgniter

In this article, we are going to discuss about How to create an image gallery in CodeIgniter. CodeIgniter is quite mature framework to creating web application, the built in libraries and helper very helpful to creating most feature in web application. This article is describes about How to create a very basic image gallery using CodeIgniter, the built in libraries that I used are File Uploading, Image Manipulation and Pagination, whereas the used helper is URL Helper.

Step 1:

Open the "config.php" file which is in the folder "system/application/config/" and set the CodeIgniter base_url

$config['base_url'] = "http://localhost/ci_gallery/";

Step 2:

Load the URL Helper in "autoload.php" file which is in the same folder as above file

$autoload['helper'] = array('url');

Step 3:

Create an image controller in file "image.php" which is in the folder "system/application/controller" and add the below attribute inside the image class

private $data = array(
    'dir' => array(
        'original' => 'assets/uploads/original/',
        'thumb' => 'assets/uploads/thumbs/'
    ),
    'total' => 0,
    'images' => array(),
    'error' => ''
);

Step 4:

The variable which is created in the above file is to store the default directory path, total images inside the folder, and error message while uploading the image, the value of those variables will set in the next function.

Add the function index inside the Image class

public function index($start = 0)
{
    if ($this->input->post('btn_upload')) {
        $this->upload();
    }

    $this->load->library('pagination');

    $c_paginate['base_url'] = site_url('image/index');
    $c_paginate['per_page'] = '9';
    $finish = $start + $c_paginate['per_page'];

    if (is_dir($this->data['dir']['thumb']))
    {
        $i = 0;
        if ($dh = opendir($this->data['dir']['thumb'])) {
            while (($file = readdir($dh)) !== false) {
                // get file extension
                $ext = strrev(strstr(strrev($file), ".", TRUE));
                if ($ext == 'jpg' || $ext == 'jpeg' || $ext == 'png') {
                    if ($start <= $this->data['total'] && $this->data['total'] < $finish) {
                        $this->data['images'][$i]['thumb'] = $file;
                        $this->data['images'][$i]['original'] = str_replace('thumb_', '', $file);
                        $i++;
                    }
                    $this->data['total']++;
                }
            }
            closedir($dh);
        }
    }

    $c_paginate['total_rows'] = $this->data['total'];

    $this->pagination->initialize($c_paginate);

    $this->load->view('images/index', $this->data);
}

Inside the index function it will call the upload function when the upload button is clicked by the user, and the pagination class is configured, the script is looping through the folder find whether the file is image or not, and now the upload function.

private function upload()
{
    $c_upload['upload_path']    = $this->data['dir']['original'];
    $c_upload['allowed_types']  = 'gif|jpg|png|jpeg|x-png';
    $c_upload['max_size']       = '500';
    $c_upload['max_width']      = '1600';
    $c_upload['max_height']     = '1200';
    $c_upload['remove_spaces']  = TRUE;

    $this->load->library('upload', $c_upload);

    if ($this->upload->do_upload()) {

        $img = $this->upload->data();

        // create thumbnail
        $new_image = $this->data['dir']['thumb'].'thumb_'.$img['file_name'];

        $c_img_lib = array(
            'image_library'     => 'gd2',
            'source_image'      => $img['full_path'],
            'maintain_ratio'    => TRUE,
            'width'             => 100,
            'height'            => 100,
            'new_image'         => $new_image
        );

        $this->load->library('image_lib', $c_img_lib);
        $this->image_lib->resize();
    } else {
        $this->data['error'] = $this->upload->display_errors();
    }
}

You can see on the code above, thumbnail is created every time image is uploaded to maximum size 100 x 100 pixels, and putted in the different folder , the last function is delete image

public function delete($ori_img)
{
    unlink($this->data['dir']['original'].$ori_img);
    unlink($this->data['dir']['thumb'].'thumb_'.$ori_img);
    redirect('/');
}

The function getting the parameter as image name and deleted the orginal and thumbnail image, and now the view file "index.php" which is in the folder "system/application/views/images/"

<!-- the javascript code to load clicked image and changing the class-->
<script type="text/javascript">
    function changepic(img_src, obj) {
        document["img_tag"].src = img_src;
        var thumbs = document.getElementsByName("thumb");
        for (var i = 0; i < thumbs.length; i++) {
            var tmp_id = "thumb_" + i;
            document.getElementById(tmp_id).setAttribute("class", "thumb");
        }
        document.getElementById(obj).setAttribute("class", "thumbclick");
        var ori_img = img_src.replace("thumb_", "");
        document.getElementById("detimglink").setAttribute("href", ori_img);
    }
</script>

<!-- the view file -->
<div id="container">
    <div id="imgshow">
        <?php if (isset($images[0])) { ?>
        <a href="<?php echo base_url().$dir['original'].$images[0]['original']; ?>" target="_blank" id="detimglink">
            <img class="imgdet" name="img_tag" src="<?php echo base_url().$dir['original'].$images[0]['original']; ?>" width="500"/>
        </a>
        <?php } ?>
    </div>

    <div id="imglist">
        <form enctype="multipart/form-data" id="fupload" method="post" action="<?php echo site_url('image/'); ?>">
            <input name="userfile" type="file" size="20"/>
            <input type="submit" name="btn_upload" value="Upload &uarr;" class="btnupload"/>
            <?php if (isset ($error)) { ?>
            <div class="error"><?php echo $error; ?></div>
            <?php } ?>
        </form>

        <div class="clear"></div>

        <div class="imgfor">
        <!-- Looping Array Image -->
        <?php foreach($images as $key => $img) { ?>
        <div class="imgbox">
            <div>
                <a href="javascript:" onclick="changepic('<?php echo base_url().$dir['original'].$img['original']; ?>', 'thumb_<?php echo $key; ?>');">
                <img class="thumb" name="thumb" id="thumb_<?php echo $key; ?>" src="<?php echo base_url().$dir['thumb'].$img['thumb']; ?>"/>
                </a>
            </div>
            <div class="dadel">
            <a class="adel" href="<?php echo site_url('image/delete/'.$img['original']); ?>">
                delete
            </a>
            </div>
        </div>
        <?php } ?>
        <div class="clear"></div>
        </div>
        <div class="clear"></div>

        <div class="bottom">
            <?php echo $total; ?> Image(s)
        </div>

        <div class="bottom">
            <?php echo $this->pagination->create_links(); ?>
        </div>
    </div>

    <div class="clear"></div>

</div> <!-- end div container -->

Steps to install Zend Framework on Ubuntu 12.04 VPS

In this article, we are going to discuss about the step by step procedure to install Zend Framework on Ubuntu 12.04 VPS. Zend is one of the best PHP Framework. Zend Framework (ZF) is a powerful web application framework that is sponsored by Zend Technologies. ZF has lots of features like support for multiple database systems, a nice caching system, a "loosely coupled" architecture (meaning components have minimal dependency on each other), and is enterprise ready as advertised.

Prerequisites:

LAMP stack should be installed on your Ubuntu VPS. It should work equally well on other Linux distros with LAMP stack. We will be installing with Zend Framework 1 as it is more widely used and has more educational material available.

ZF requires that you have enabled mod_rewrite. You can do it by typing this command:

a2enmod rewrite

Installation:

Latest version of ZF1 branch is 1.12.7.

Change into home directory:

cd /home

and get the ZF1 installation,

wget https://packages.zendframework.com/releases/ZendFramework-1.12.7/ZendFramework-1.12.7.tar.gz

Extract the archive with the command:

tar -xvzf ZendFramework-1.12.7.tar.gz

After this, we should inform php5 interpreter of our Zend library by changing php.ini. It is located in: /etc/php5/apache2:

nano /etc/php5/apache2/php.ini

Find the line:

;include_path = ".:/usr/share/php"

and change it with:

include_path = ".:/home/ZendFramework-1.12.7/library"

Then save the changes and exit.

ZF1 comes with a command line tool to easily create projects, models, controllers, and other useful actions related to your Zend application. We should make our terminal aware of this tool. We will change into root directory and edit our .bashrc file then source it.

cd /root
nano .bashrc

Now, add the line below to the end of the file:

alias zf=/home/ZendFramework-1.12.7/bin/zf.sh

Save the file and exit.

Source your .bashrc file so that the terminal is now aware of our ZF tool and zf command.

source .bashrc

Creating Your First Application

We will begin to create our first project. Change into /var/www directory.

cd /var/www

Let's create our first project named ZendApp. We have a few steps until we can see our project is running, so don't worry if you don't see anything when you visit http://youripadress

zf create project ZendApp

This command creates the related project files for our project "ZendApp". It has several subdirectories and one of them, "public", is where our web server should be pointed to.

This is done by changing our settings as the default web root directory. Go to your Apache settings directory which has the settings for the currently enabled sites:

cd /etc/apache2/sites-enabled

You can optionally backup your default settings file with the command:

cp 000-default 000-default.bck

Now change the contents of "000-default":

nano 000-default

with the lines below:

<VirtualHost *:80>
    ServerName localhost
    DocumentRoot /var/www/ZendApp/public

    SetEnv APPLICATION_ENV "development"

    <Directory /var/www/ZendApp/public>
        DirectoryIndex index.php
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>

We are done. Restart apache:

service apache2 restart

Thats all... !

YII PHP Framework - Introduction

The Yii PHP project started on January 1, 2008, in order to fix some drawbacks of the PRADO framework. For example, in its early versions PRADO was slow when handling complex pages, had a steep learning curve and many controls were difficult to customize, while Yii was much more efficient at that time. In October 2008, after ten months of private development, the first alpha version of Yii was released. On December 3, 2008, Yii 1.0 was formally released.

Features:

  1. Model-View-Controller (MVC) design pattern.
  2. Generation of complex WSDL service specifications and management of Web service request handling.
  3. Internationalization and localization (I18N and L10N). It supports message translation, date and time formatting, number formatting, and interface localization.
  4. Layered caching scheme. It supports data caching, page caching, fragment caching and dynamic content. The storage medium of caching can be changed.
  5. Error handling and logging. Errors are handled and presented more nicely, and log messages can be categorized, filtered and routed to different destinations.
  6. Security measures include cross-site scripting (XSS) prevention, cross-site request forgery (CSRF) prevention, cookie tampering prevention, etc.
  7. Unit and functionality testing based on PHPUnit and Selenium.
  8. Automatic code generation for the skeleton application, CRUD applications, etc.
  9. Code generated by Yii components and command line tools complies to the XHTML standard.
  10. Carefully designed to work well with third-party code. For example, it's possible to use code from PEAR or Zend Framework in a Yii application.

Create an API for TV Show Tracker app in cakephp

In this article, we are going to discuss about How to create an API for TV Show tracker app in cakephp. There is 2 parts to the API, one is the server part on my app and the other is the client which requests information and displays it. As the TV Show Tracker app is built using CakePHP I created an ApiController which deals with all the requests for information.

I have got an episodes method, which processes all the requests for episode information, currently the only action available is last_watched which gets the recently watched episodes for that user.

Below is some sample code so that you know what I'm talking about

<?php
class ApiController extends AppController {
        /**
* Get Episode information
* $params[0] = api key
* $params[1] = action (last_watched)
* $params[2] = options (last_watched = limit)
*/
function episodes() {
// get params
$params = $this->params['pass'];
// switch based on action
switch($params[1])
{
/**
* Last Watched
* @param int limit 
*/
case 'last_watched':
                            // get episodes
break;
}
        echo json_encode($json);
        }
}

For authentication I have created an API key for each user, this is a salted hash and is unique to that User so we know we are only going to return their information. This was easier than I thought and works quite well. All calls are logged so that I know who is using it and if it is being abused.

Using the API

To use the API you will need to query the following URL:

http://www.tvshowtracker.co.uk/api/episodes/API_KEY/last_watched

This will bring back a JSON encoded string with all the Episode & Show information which can then be used in you application. I'm using it on the blog by sending a ajax request to one of my Controller actions, this is then using cURL to request the API URL and bring back any results. This is then passed back to the Javascript file where I loop through the Episodes and display the Show Posters and info.

The PHP code

/**
 * Ajax call to TV Show Tracker
 */
public function ajax_tv_show_tracker() {
if(!$this->request->is('ajax')) {
throw new NotFoundException('Action not allowed');
}

if (function_exists('curl_init')) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://www.tvshowtracker.co.uk/api/episodes/API_KEY/last_watched/8");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$output = curl_exec($ch);
curl_close($ch);

echo $output;
exit;
}

echo json_encode(array('success'=>FALSE));
exit;
}

The Javascript code

(function ($) {

$.ajax({
type: "GET",
url: "/posts/ajax_tv_show_tracker",
dataType: "json",
success: function(episodes){
// call was successful
if(episodes.success) {
// build up HTML
var html = '<h3>Recently Watched Shows <span style="font-size:14px;">(tracked with <a href="http://www.tvshowtracker.co.uk" target="_blank">TV Show Tracker</a>)</span></h3><div id="tv_show_tracker" class="row">';

// loop through episodes
$(episodes.episodes).each(function(k,v){
// deal with first & last in row
var class_name = '';
if(k==0) {
class_name = ' alpha';
} else if(episodes.episodes.length==8 && k==3) {
class_name = ' omega';
} else if(k==7) {
class_name = ' omega';
}

// build up episode image & link
html += '<div class="two columns show'+class_name+'">';
 html += '<a href="'+v.Show.link+'" target="_blank">';
   html += '<img src="'+v.Show.poster.small+'" alt="'+v.Show.name+' Poster" style="width:100%; display:block;"/>';
 html += '</a>';
 html += '<small>Episode '+v.Episode.season_number+'x'+v.Episode.episode_number+'</small>';
html += '</div>';
});

html += '</div>';

// inject into page
$('.site_images').after(html);
}
}
});

})(jQuery);

Steps to create JQuery form in Zend Framework

In this tutorial, we are going to discuss about How to create jQuery form in Zend framework. I'm here to show you how to use JQuery extension provide with latest version of Zend Framework for creating wonderful JQuery form. You will need to follow the steps bellow to create JQuery form.

  1. Placing ZendX directory in right place
  2. Make necessary configuration in bootstrap file
  3. Write necessary code in your layout.phtml file.
  4. Create JQuery form
  5. Show that form in the template.

Step 1 : Placing ZendX directory in right place

When you download latest version of Zend Framework and extract the zip file. You will see a directory called "extras". When open that directory you will find ZendX folder. Copy this to your Library/ folder at the same level of your Zend directory. You directory structure will be like this.

Library/
    Zend/
    ZendX/
   
Step 2 : Making necessary configuration in bootstrap

After placing the directory you will need to add a bit of code in your bootstrap file. Add the following lines to your bootstrap file.

$view = new Zend_View();
$view->addHelperPath("ZendX/JQuery/View/Helper", "ZendX_JQuery_View_Helper");
$viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer();
$viewRenderer->setView($view);
Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);

In the code above, we instantiate our Zend_View object, set helper path, add view to the viewRenderer and finally add viewRenderer the helper broker. Keep in mind that if you have already instantiate Zend view in your bootstrap, you don't need to instantiate it twice.

Step 3: Write necessary code in your layout.phtml file

The only line you will need to include in your layout file is

echo $this->jQuery();

If you don't use two step view, you can include this line at the top of each of your view template file instead.

Step 4: Create JQuery form

Now you have done all the necessary configuration, its time to create the actual form. Create JQuery form in Zend framework is piece of cake. If you want to create form in your controller, write the following code.

$form = new ZendX_JQuery_Form();
$date1 = new ZendX_JQuery_Form_Element_DatePicker(
                        'date1',
                        array('label' => 'Date:')
        );
$form->addElement($date1);
$elem = new ZendX_JQuery_Form_Element_Spinner(
                    "spinner1", 
                    array('label' => 'Spinner:')
        );
$elem->setJQueryParams(array(
                'min' => 0,
                'max' => 1000,
                'start' => 100)
        );
$form->addElement($elem);
$this->view->form = $form;

In the code above we have created our JQuery form object, and add two element date and spinner to it. And then assigned the form to the view template file. Although you can create the form in your controller, however I will strongly discourage it. I will prefer using separate php file and add following code to that file.

class JQueryForm extends ZendX_JQuery_Form
{
    public function init()
    {
        $this->setMethod('post');
        $this->setName('frm');
        $this->setAction('path/to/action');
        
        $date1 = new ZendX_JQuery_Form_Element_DatePicker(
                'date1',
                array('label' => 'Date:')
             );
             
        $this->addElement($date1);
        
        $elem = new ZendX_JQuery_Form_Element_Spinner(
                "spinner1", 
                array('label' => 'Spinner:')
        );
        
        $elem->setJQueryParams(array('min' => 0, 'max' => 1000, 'start' => 100));
        $this->addElement($elem);
    }
}

We have extended our form from ZendX_JQuery_Form, set its method, name and action and add two elements date and spinner. Now in your controller/action

$form = new JQueryForm();
$this->view->form = $form;

Step 5 : Showing form in the template

In your view template file add only the following line.

<?php
echo $this->form;
?>

Zend Form - Existing Email Address checking in Database

In this tutorial, we are going to discuss about How to check the existing email address in database in zend form. If you are creating a user registration form, you will either want to check if a username or an email address is already exist in the database. This is very easy to do, assuming you are familiar with using Zend_Form:

$validator = new Zend_Validate_Db_NoRecordExists('user', 'email'); // user is the table name, and email is the column
    $validator->setMessage("Error: The e-mail has already been registered"); // set your own error message
    $this->addElement('text', 'email', array(
       'label' => 'E-mail Address',
       'required' => true,
       'filters' => array('StringTrim'),
       'validators' => array(
           'EmailAddress',
           $validator
       )
));

That's all.

NOTE: This might be obvious but you cannot chain the setMessage(…) function directly to the end of new Zend_Validate_Db_NoRecordExists('user', 'email');

If you are not familiar Zend_Form, here's a full example:

/* application/forms/Register.php */
class Default_Form_Register extends Zend_Form {
public function init($options = null) {
$this->setMethod('post');
$this->addElement('text', 'firstName', array(
'label' => 'First Name',
'required' => true,
'filters' => array('StringTrim'),
'validators' => array(
array('validator' => 'StringLength', 'options' => array(1, 255))
)
));
$this->addElement('text', 'lastName', array(
'label' => 'Last Name',
'required' => true,
'filters' => array('StringTrim'),
'validators' => array(
array('validator' => 'StringLength', 'options' => array(1, 255))
)
));

        $validator = new Zend_Validate_Db_NoRecordExists('user', 'email');
$validator->setMessage("Error: The e-mail has already been registered");
$this->addElement('text', 'email', array(
'label' => 'E-mail Address',
'required' => true,
'filters' => array('StringTrim'),
'validators' => array(
'EmailAddress',
$validator
)
));

$password = $this->addElement('password', 'password', array(
'filters' => array('StringTrim'),
'validators' => array(
array('StringLength', false, array(8, 20)),
),
'required' => true,
'label' => 'Password',
'id' => 'password'
));

$register = $this->addElement('submit', 'register', array(
'required' => false,
'ignore' => true,
'label' => 'Register Now',
));
}

Steps to use Wordpress like pager in Drupal

In this article, we are going to discuss about How to use the WordPress like pager in Drupal website. Most of the people preferred the Wordpress kind of pagination in drupal based site. But by default, Drupal provides the number pagination < 1 2 3..> . so here is the snippet to get the Wordpress kind of pagination which overrides the default pagination of drupal.

<?php
function yourtheme_pager($tags = array(), $limit = 10, $element = 0, $parameters = array(), $quantity = 9) {
  global $pager_total;

  $li_previous = theme('pager_previous', (isset($tags[1]) ? $tags[1] : t('‹ previous')), $limit, $element, 1, $parameters);
  $li_next = theme('pager_next', (isset($tags[3]) ? $tags[3] : t('next ›')), $limit, $element, 1, $parameters);

  if ($pager_total[$element] > 1) {

    if ($li_previous) {
      $items[] = array(
        'class' => 'pager-previous', 
        'data' => $li_previous,
      );
    }

    // End generation.
    if ($li_next) {
      $items[] = array(
        'class' => 'pager-next', 
        'data' => $li_next,
      );
    }
    return theme('item_list', $items, NULL, 'ul', array('class' => 'pager'));
  }

?>

Add the above code snippet in your theme's template.php file and clear the cache and then check it. It will work.

The above code will solve someone's headache.

Drupal - G2W (Goto Webinar) integration

In this article, we are going to discuss about How to integrate the G2W (Goto Webinar) module with Drupal. G2W is useful for the User to signup for the webinars (payment based) through our site. Once the user completed the payment, it will registering the user to the registrants list in G2W (Goto Webinar) ( where actually they are hosting the webinars).

The Most important thing that you know when you registering in gotowebinar is about the webinar key (Which is available after you schedule a webinar). Check details on how to schedule and host a webinar here. http://www.gotomeeting.com/fec/webinar. I decided to write a curl function to the registration URL and submit the values collected from my order information.

I used hook_order API to check whether the order is Completed and based on the Status i'm submitting the User Details to the gotowebinar registrant URL.

Below is my completed process/code to submit user information in G2W.

1. Created a new field in your product class "goto_webinars_key"( you will find out this,once you scheduled a webinar in go to webinar)

2. Create a custom module with the following functions

function YOURMODULE_order($opt, &$arg1, $arg2){
$order = &$arg1;
$user = user_load($order->uid); // user info from the Order.
switch($op){
//We only care about completed updates and that needs to be execute once in the System
case 'update':
if ($arg1->order_status == 'payment_received' && arg2 == 'completed'){

//loop through each product item in the cart
foreach ($order->products as $product){
$n = node_load($product->nid);
if ($n->field_goto_webinars_key[0][value]){
YOURMODULE_gotowebinar($n->field_goto_webinars_key[0][value], $user);
}}
break;
}}

// curl operation to submit the users into go to webinar registration.
function YOURMODULE_gotowebinar($WebinarKey, $account){
$gtwPost = "";

//Create string for GoToWebinar from same form POST data
$Form = "webinarRegistrationForm";
$gtwPost = "WebinarKey=" . urlencode($WebinarKey)
. "&Form=" . urlencode($Form)
. "&Name_First=" . urlencode($account->profile_firstname)
. "&Name_Last=" . urlencode($account->profile_lastname)
. "&Email=" . urlencode($account->mail)
. "&Company=" . urlencode($account->profile_company)
. "&Title=" . urlencode($account->profile_title);

//Set POST URL for GoToWebinar
$gtw_url = "https://attendee.gotowebinar.com/register/$WebinarKey&#8221;;// This URl will be got from the registration url after you scheduled a webinar

//Start GoToWebinar submission
$curl = curl_init();
curl_setopt($curl, CURLOPT_POSTFIELDS, $gtwPost);
curl_setopt($curl, CURLOPT_URL, $gtw_url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // it skips the curl version check if your curl is different.
$er = curl_exec($curl);
$info = curl_getinfo($curl);
curl_close($curl);
}

3. Enable the module and now it will submit users in the Go to Webinar.

The above code is sample to do with the normal Ubercart Product. I used signup module also to track webinars in my drupal system( Let me know if you want me to post the workflow of that too)