Thursday, April 26, 2012

Create your own CMS-Part 11

Sorry for the delay!
We are getting into advanced features from this post onwards.
In this post we will learn to create a custom module class.So lets begin...
  • Before we begin to create the class file , let us see the structure of a module directory.The structure given below is created by taking 'blog' module as reference.


The following files are necessary for a module to be valid.
  • 'start.php'
  • 'manifest.xml'
  • 'install.php'
The module class will contain various methods to control a module.The page to be executed (called as base file) depends on the query string in the url.The structure of our url is
http://localhost/stupid/index.php?module=val1&sub=val2&action=val3
val1 =====> any valid module  eg: blog,photos etc
val2 =====> name of sub module  eg: editblog ,viewblog,deleteblog etc
val3 =====> action filename for actions like save,edit etc

Let us create our modules class
  • Open stupid >> include directory.
  • Create a file named 'module_class.php'.
  • Open the file in an editor and write the following code.
<?php
/*
THE STRUCTURE OF OUR MODULE IS AS FOLLOWS.
FOR BETTER UNDERSTANDING BLOG MODULE IS USED AS
A REFERENCE.
NOTE: FILES WITH PREFIX * ARE ESSENTIALLY REQUIRED.

modules/
blog/
extras/
editblog.php
createblog.php
viewblog.php
actions/
save.php
create.php
delete.php
*install.php
*start.php
view.php
menu_left.php
*manifest.xml
image.png

*/

/*
The module class will contain various methods for 
controlling a module.
The structure of our url will be

"http://localhost/stupid/module=val1&sub=val2&action=val3"

val1 =====> any valid module  eg: blog,photos etc
val2 =====> name of sub module  eg: editblog ,viewblog,deleteblog etc
val3 =====> action filename for actions like save,edit etc

*/
?>

<?php
class Modules
{
    
    /**
    $module     : An array with keys name,sub and action.The values is obtained from url through $_GET method.
    $module_dir   : The path of current module  eg: modules/blogs , modules/photos.
    $module_data  : An array used to store the details of the module (obtained from database) .
    $base_file   : The file to fetch and execute .
    $logged_out_menu : The menu for a anonymous user.This will be present in the theme.
    **/
    
    var $module = array();
    var $module_dir;
    var $module_data = array();
    var $module_menu;
    var $base_file;
    var $logged_out_menu;
    
    /**
    Constructor for the modules class.
    The value of base file changes with the values in the query string.
    Have a look at the if else statement for better understanding. 
    **/
    
    function __construct()
    {
        global $theme;
        if (isset($_GET['module'])) {
            $this->module['name'] = $_GET['module'];
        } else {
            $this->module['name'] = 'home';
        }
        $this->module_dir = MODULESPATH . '/' . $this->module['name'];
        if (isset($_GET['sub'])) {
            $this->module['sub'] = $_GET['sub'];
            if (isset($_GET['action'])) {
                $this->module['action'] = $_GET['action'];
                $this->base_file        = $this->module_dir . '/extras/actions/' . $this->module['action'] . '.php';
            } else {
                $this->base_file = $this->module_dir . '/extras/' . $this->module['sub'] . '.php';
            }
        } else {
            $this->module['sub'] = NULL;
            $this->base_file     = $this->module_dir . '/view.php';
        }
        $this->module_data     = $this->get_module_data();
        $this->logged_out_menu = $theme->active_theme . '/menu.php';
    }
    
    /********************************************
    This method is used to get the data of the 
    current module.
    ********************************************/
    
    function get_module_data()
    {
        global $db;
        $res = $db->query("SELECT * FROM `modules` WHERE `name` = '" . $this->module['name'] . "' LIMIT 1");
        return $db->fetch_array($res);
    }
    
    /********************************************
    Returns true if the module is enabled
    $name : The name of the module.
    *********************************************/
    
    function is_active($name)
    {
        global $db;
        $res  = $db->query("SELECT * FROM `modules` WHERE `name` = '" . $name . "' LIMIT 1");
        $data = $db->fetch_array($res);
        if ($data['active'] == 1)
            return true;
        else
            return false;
    }
    
    /******************************************
    Checks whether the module is installed or not
    $name : The name of the module.
    ********************************************/
    
    function is_module_installed($name)
    {
        global $db;
        $res = $db->query("SELECT * FROM `modules` WHERE `name` = '" . $name . "'");
        if ($db->fetch_num($res) == 1)
            return true;
        else
            return false;
    }
    
    /******************************************
    Returs an array of all enabled modules
    ******************************************/
    
    function get_all_enabled_modules()
    {
        global $db;
        $res = $db->query("SELECT * FROM `modules` WHERE `active` = 1");
        while ($all = $db->fetch_array($res)) {
            $enabled_modules[] = $all['name'];
        }
        return $enabled_modules;
    }
    
    /*****************************************
    This is the starter for all enabled modules.
    start.php file from every enabled modules is
    included by this method.
    ******************************************/
    
    function start_all_enabled_modules()
    {
        global $db;
        $enabled_modules = $this->get_all_enabled_modules();
        foreach ($enabled_modules as $e) {
            if ($e != 'admin' && $e != 'home')
                include_once MODULESPATH . '/' . $e . '/start.php';
        }
    }
    
    /*
    This method will be called in engine.php.
    Used to view the module content by building 
    menu.
    */
    
    function view_module()
    {
        if ($this->is_module_installed($this->module['name']) && $this->is_active($this->module['name'])) {
            $this->build_menu();
            $this->view_app();
        } else {
            redirect_to(BASE);
        }
    }
    
    /**
    Builds the necessary menu for the module.
    Includes the menu_left.php
    */
    
    function build_menu()
    {
        if (file_exists($leftmenufile = $this->module_dir . '/menu_left.php')) {
            $this->module_menu = $leftmenufile;
        } else {
            $this->module_menu = MODULESPATH . '/home/menu_left.php';
        }
        
    }
    
    /*
    Views the app in the app block.
    */
    
    function view_app()
    {
        if (is_logged_in()) {
            echo '<div id="canvas">';
            echo '<div id="left">';
            include_once $this->module_menu;
            echo '</div>';
            echo '<div id="app_block">';
            include_once $this->base_file;
            echo '</div>';
            echo '<div class="clear"></div>';
            echo '</div>';
            
        } else {
            if ($this->module['name'] == 'home') {
                global $theme;
                include_once $theme->active_theme . '/homepage.php';
            } else {
                echo '<div id="canvas">';
                echo '<div id="app_block">';
                include_once $this->base_file;
                echo '</div>';
                echo '<div id="left">';
                include_once $this->logged_out_menu;
                echo '</div>';
                echo '<div class="clear"></div>';
                echo '</div>';
            }
        }
    }
    
    /********************************************
    Returns an array of all modules ( enabled and disabled ).
    Obtained by reading the modules directory.
    *********************************************/
    
    function get_modules_list()
    {
        $plugins = array();
        if ($handle = opendir(MODULESPATH)) {
            while ($mod = readdir($handle)) {
                // must be directory and not begin with a .
                if (substr($mod, 0, 1) !== '.' && is_dir(MODULESPATH . "/" . $mod)) {
                    $plugins[] = $mod;
                }
            }
        }
        sort($plugins);
        return $plugins;
    }
    
    // to activate a module
    
    function activate($name)
    {
        global $db;
        $sql = "UPDATE modules SET active='1' WHERE name = '" . $name . "'";
        $db->query($sql);
    }
    
    // to deactivate a module
    
    function deactivate($name)
    {
        global $db;
        $sql = "UPDATE modules SET active='0' WHERE name = '" . $name . "'";
        $db->query($sql);
    }
    
    /*
    To install a module.
    Before installing the installing module is checked for validity.
    */
    
    function install_module($name)
    {
        $valid = $this->check_module($name);
        if ($valid) {
            include_once MODULESPATH . '/' . $name . '/install.php';
        } else {
            show_msg('Invalid', 'This module is not valid');
        }
    }
    
    // To uninstall a module
    
    function uninstall_module($name)
    {
        global $db;
        $sql = 'DROP TABLE IF EXISTS ' . $name . '';
        $db->query($sql);
        $sql = "DELETE FROM modules WHERE name = '" . $name . "'";
        $db->query($sql);
        $sql = "DELETE FROM module_settings WHERE module_name = '" . $name . "'";
        $db->query($sql);
    }
    
    /*
    This method inserts the module into modules table in the database.
    */
    
    function register_module($name)
    {
        global $db;
        $sql = "INSERT INTO modules(name) VALUES('" . $name . "')";
        $db->query($sql);
    }
    
    /**
    Returns true if module is valid.
    A module is valid if it contains the 
    required files.
    **/
    
    function check_module($name, $valid = false)
    {
        if (file_exists(MODULESPATH . '/' . $name . '/install.php') && file_exists(MODULESPATH . '/' . $name . '/view.php') && file_exists(MODULESPATH . '/' . $name . '/manifest.xml'))
            $valid = true;
        return $valid;
    }
    
    // to enable a module
    
    function enable_module($name)
    {
        $this->activate($name);
    }
    
    // to disable module
    
    function disable_module($name)
    {
        $this->deactivate($name);
    }
    
}
?>  
All the methods are named in such way that you can specify the function it does easily.
Also the functions can be easily understood from the comments in the file.So I am skiiping the explanation of each methods specifically.You can just comment below if you need an explanation of any methods.
So we have created our class file successfully.Now its time to create an object of the class.As usual class instantiation is done in 'engine.php' in 'main' folder.The modified 'engine.php' looks like below

<?php
include_once('functions.php');
include_once('config/base.php');
include_once(CLASSPATH . '/database_class.php');
include_once(CLASSPATH . '/session_class.php');
include_once(CLASSPATH . '/user_class.php');
include_once(CLASSPATH . '/theme_class.php');
include_once(CLASSPATH . '/module_class.php');
global $db, $ss, $user, $theme, $module;

$db     = new Database();
$ss     = new Session();
$user   = new User();
$theme  = new Theme();
$module = new Modules();

/**********************************/

/*******************************/
$theme->load_css();
$theme->load_index();

/******************************
to view the module
*******************************/

$module->view_module();
$theme->load_footer();

/*******************************
 *******************************/
include_once('/actions/actions.php');
?>

In the next post , we will be creating our first module 'home'.



3 comments:

  1. a small correction is made in register_module method.

    ReplyDelete
  2. A small update in check_module method in Modules class file.

    ====================================
    function check_module($name,$valid=false)
    {
    if(file_exists(MODULESPATH.'/'.$name.'/install.php') && file_exists(MODULESPATH.'/'.$name.'/start.php') && file_exists(MODULESPATH.'/'.$name.'/manifest.xml'))
    $valid=true;
    return $valid;
    }
    ===================================

    ReplyDelete
  3. i must thank you for the efforts you've put in penning this blog. excellent blog post .

    www.n8fan.net

    ReplyDelete