Build a module : Prepare

In this tutorial, we will create one module for Ionize.

A module is like a little application build in Ionize. It usually brings new features but without put the hands into the core of the CMS.
One module can have its own DB tables, some admin panels and its own collection of tags to display data on the website.

The module we will build will have one backend, it will interact with articles but also display data on the visitor's website.

What will do this module ?

The module will be called "Demo" and will manage "articles's authors".

Authors are related to one or more article(s) and we want to display them at the bottom of some articles of the website.
The "author" of one article has nothing to do with the "editor" who use Ionize, and that's why we want to separate them.

On the backend, the content editor (Ionize's user) will be able to link one or more authors to each edited article.

Of course the editor will also be able to add / edit / delete authors.

Each author has a name, a gender, and one translated description for each existing language.

What you will learn

  • How to create one module for Ionize,
  • How work admin languages in ionize,
  • How to make Ajax call with Ionize's JS library,
  • How to create drag'n'drop in the backend of Ionize,
  • How to save / edit / create data by using the Ionize models,
  • How to create callbacks after save to refresh some parts of the backend,
  • How to create Ionize's front-end tags to display data,
  • How to create font-end views

Do not be afraid, if you follow this tutorial, all these tasks will become easy for you.

Prerequisites

System

  • Ionize installed on one local server (this tutorial is based on the release 1.0.2),
  • Firebug (to debug XHR (Ajax) requests)

Knowledges

  • HTML
  • Basis about PHP and CodeIgniter (routing, controllers, models, views),
  • Javascript DOM manipulation & XHR request (understanding Mootools can help, but is not mandatory. If you use jQuery, you will not be lost with Mootools)

Prepare the moduleTop of Page

Each module is located in its own folder, under the /modules folder.

Lets create the following folder structure :

modules/
Demo/
config/
controllers/
language/
en/
models/
views/

In each of these folders, copy the file from /application/config/index.html file.

The module folder is reachable through URLs, so this index.html file prevent the directory listing.

Configure the moduleTop of Page

In the /modules/Demo/config/ folder, create one configuration file called "config.php".

This file will be used by the Modules > Administration panel of Ionize, to get the name and description of the module but also the module's permissions.
You can also add your own configuration data in this file, but we will see that later.

In this file, write the following code :

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

$config['module']['demo'] = array
(
    'module' => "Demo",
    'name' => "Demo Module",
    'description' => "Demo module. Manage articles's authors.",
    'author' => "Partikule",
    'version' => "1.1",

// 'uri' should be the module's folder in lowercase.
// From 1.0.3, it is not mandatory to set 'uri'.
    'uri' => 'demo',
    'has_admin'=> TRUE,
    'has_frontend'=> TRUE,
);

return $config['module']['demo'];

Save and go to Modules > Administration in Ionize.

The panel shows you your module :

The module has one "install" link. Let's click on it.

Installing the module will work, but clicking on the "URI" link after install will output a 404 page.

That's because the module hasn't any controller and the route to the module's controllers aren't setup.

Create the website's output of the module (front-end)Top of Page

Setup the front-end Route

Add the file /modules/Demo/config/routes.php and write the following code in this file :

<?php if (!defined('BASEPATH')) exit('No direct script access allowed');

$route['default_controller'] = "demo";
$route['(.*)'] = "demo/index/$1";
$route[''] = 'demo/index';

This will setup the route to the website's module URL.

We tell the Router that the default module's controller is called "demo" and that the default method of this controller is "index".

Create the front-end controller

Create the file /modules/Demo/controllers/demo.php and write the following code in this file :

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Demo extends My_Controller
{
    public function __construct()
    {
        parent::__construct();
    }

    function index()
    {
        print "Demo module default controller output";
    }
}

In Ionize, go to Modules > Administration and click on the URI link of the module.

This will output "Demo module default controller output".

Our module has now one front-end controller which displays one nice message.

Add a view and display it

Create the file /modules/Demo/views/demo.php and add the following code:

<h1><?php echo $title; ?></h1>

Modify the controller /modules/Demo/controllers/demo.php so the code looks like :

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Demo extends My_Controller
{
    public function __construct()
    {
        parent::__construct();
    }

    function index()
    {
        $this->template['title'] = 'Demo module title';
        $this->output('demo');
    }
}

Refresh the website page, the output is now one H1 title displaying "Demo module title".

Create one basic admin panelTop of Page

In the module's config file (config/config.php) we added :

'has_admin'=> TRUE

That means the module has one admin panel.

Let's create it.

  1. Add one folder called "admin" in the folder /modules/Demo/controllers/
  2. Add one folder called "admin" in the folder /modules/Demo/views/

The folder tree looks nows like this :

modules/
Demo/
config/ controllers/ admin/ language/ en/ models/ views/ admin/

Create the backend controller

Create the file /modules/Demo/controllers/admin/demo.php and add the following code :

<?php if( ! defined('BASEPATH')) exit('No direct script access allowed');

/**
* Module Admin controller
*
*/
class Demo extends Module_Admin
{
/**
* Constructor
*
* @access public
* @return void
*/
public function construct(){}

/**
* Admin panel
* Called from the modules list.
*
* @access public
* @return parsed view
*
*/
public function index()
{
$this->output('admin/demo');
}
}

We see that the default method of the controller outputs the view "admin/demo".

Create the backend view

Create the file /modules/Demo/views/admin/demo.php and add the code :

<div id="maincolumn">

<h2 class="main"><?php echo lang('module_demo_title'); ?></h2>

<div class="subtitle">

<!-- About this module -->
<p class="lite">
<?php echo lang('module_demo_about'); ?>
</p>
</div>
</div>

<script type="text/javascript">

// Init the panel toolbox is mandatory
ION.initToolbox('empty_toolbox');

</script>

Code explanation :

  • The view calls the function lang() : This function is used in the the backend to displays one translated string.
  • The JS calls ION.initToolbox() : This loads the asked toolbox (icons on the right of the panel header) : We will see this later, for the moment, it loads one standard empty toolbox.

In Ionize, go to Modules > Administration and click on the name link of the module.

This will bring us to the module's admin panel and output :


If we refresh the backend panel, we will see that the module's admin panel is also reachable :

  • Through the Modules menu
  • On the Dashboard, under the Modules section

Create the translation files

When one backend view displays something like "#module_demo_tile", that means the term isn't translated for the current used backend language.

The folder for the language "en" is prepared (english is the default Ionize backend's language).

If you want to translate your module in several languages, you'll need to create one folder per language code and to write the corresponding language files.

Create the file /modules/Demo/language/en/demo_lang.php and add the code :

<?php
/**
* Ionize Module lang file
* Lang terms must always be prefixed by "module_<module_name>"
* to avoid conflict with core / other translations items
*
*/

$lang['module_demo_title'] = "Demo module";
$lang['module_demo_about'] = "About the Demo module...";

$lang['module_demo_label_open_window'] = "Window example";
$lang['module_demo_button_open_window'] = "Open window";
$lang['module_demo_window_title'] = "Modal window title";

$lang['module_demo_title_edit_author'] = "Edit Author";
$lang['module_demo_label_gender'] = "Gender";
$lang['module_demo_label_male'] = "Male";
$lang['module_demo_label_female'] = "Female";

$lang['module_demo_button_create_author'] = "Create Author";
$lang['module_demo_label_new_author'] = "New Author";

$lang['module_demo_title_authors'] = "Authors";
$lang['module_demo_title_link_authors'] = "Link Authors";
$lang['module_demo_button_link_authors'] = "Add Authors";
$lang['module_demo_label_drop_author'] = "Drop one author here...";
$lang['module_demo_message_author_already_linked'] = "Author already linked";

To be auto-loaded by Ionize, each module language file must be named like this : lang_<module_code>.php, where <module_code> is the module's folder name in lowercase.

All these translations terms will be usable in your code by calling : echo lang('term_key');
Example :
echo lang('module_demo_title');
will output :
Demo module

We try to keep the language terms keys easy to understand. That's why we prefix them with "label", "title", "button", "message", etc.
That's just a best practice.
Prefixing the language terms key wit the module name to avoid collision with other translations.

Add some style to the backend

What's missing is a little 40px sized icon for our module.
This icon will be used both for the dashboard icon and the administration panel of the module.

ionize demo module icon

In the folder /modules/Demo, add the folder "assets/images" and "assets/css" so the module's folder tree looks like :

modules /

Demo/
  assets/
    css/
    images/
  config/
  controllers/
    admin/
  language/
    en/
  models/
  views/
    admin/

Copy the file index.html of another folder inside the assets folder.

Copy the following icon into the folder modules/Demo/assets/images/ and name it "icon_40_module.png"

Create the file modules/Demo/assets/css/admin.css and add the following code :

h2.main.demo {
background: url(../images/icon_40_module.png) no-repeat 0 0;
}

Modify the view modules/Demo/views/admin/demo.php so it looks like :

<div id="maincolumn">

<h2 class="main demo"><?php echo lang('module_demo_title'); ?></h2>

<div class="main subtitle">

<!-- About this module -->
<p class="lite">
<?php echo lang('module_demo_about'); ?>
</p>
</div>
</div>

Reload the Ionize backend panel (refresh Ionize).

The icon is displaying on the dashboard and the CSS class we added is used in the admin panel of the module.

To understand what happened :

  1. Ionize auto-loads all the module's CSS files which are named "admin.css" and located in the path : /modules/<module_name>/assets/css/admin.css
    That's why the module's admin panel style is available.
  2. The dashboard is waiting for one 40px icon called "icon_40_module.png" and located in the path : /modules/<module_name>/assets/images/icon_40_module.png
    That's why the dashboard displays the module's icon.