You are on page 1of 339

Table of Content

Ionize 0.9.9 - User Guide

Table of Content

Basic infos

Server Requirements
License Agreement
Change Log
Credits

Installation

Downloading Ionize
Installation Instructions
Troubleshooting
Migration from 0.9.x to 0.9.9
Development vs. Production

Introduction

Ionize at a Glance
Main Concepts
Main Ionize folders
Quickstart : Ionize in 4 steps
1

Using Ionize & Editing Content

Discover the Ionize backend


Languages
Menus
Pages
Articles
Media : Files, pictures, videos...
Static translations
Users and Groups
Content Online / Offline

Build the website

Create the theme


Create one page : Views
Articles and Types
Add PHP to views

Tags reference

Introduction to Tags
Common Tags
Special Tags
Shared attributes
Website
Navigation
Languages
2

Page
Articles
Medias
Pagination
Categories
Archives
User
Form
Extend Field
Content Element
Conditions with tags

Extend Ionize : Add your own data

Introduction
Extend Fields
Content Elements

Tutorials

User registration,
Build one module
Build one module
Build one module
Build one module

login and profile


: Part 1
: Part 2
: Part 3
: Part 4

Additional Resources
3

Community Forum
Ionize on GitHub

Server Requirements
ServerTop of Page
Ionize has the following server requirements :

Apache server,
PHP 5.2.6
MySQL 5.1

.htaccess fileTop of Page


You should be able to edit one customized .htaccess file :
RewriteEngine On

# The RewriteBase / instruction is commented. Remove the "#" to uncomment


# RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-f


RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !^(index.php|robots.txt)
RewriteRule ^(.*)$ index.php/$1

RewriteCond %{REQUEST_FILENAME} !-f


RewriteRule ^(application|modules|plugins|system|themes) index.php/$1 [L]

Change Log
Version 0.9.9Top of Page
Release Date: December 29, 2012
One big step for Ionize.

Complete rewrite of frontend tags : Basis stays the same, but the tags are more logical
"Form" and "User" tags replaces the modules Simpleform and Usermanager
Backend enhancements

Version 0.9.8Top of Page


Release date : Never released, internal use only.
5

This release was one intermediate step for Ionize.


Features :
Pages "full" URLs : URLs uses the complete nested path of pages
Standardization of backend panels

Version 0.9.7Top of Page


Release Date: September 2, 2011
Focus on tinyMCE integration
Upgrade of the backend to CodeIgniter 2 and mootools 1.3.1
Better module management
New Filemanager
Content Elements : Developpers can create their own complex data
Module : Simpleform, to create forms
Module : Usermanager, to manage advanced user's features : login, logout, profile

Version 0.9.6Top of Page


Release Date: November 28, 2010
SVN Revision:

Features
Articles can be linked to more than one page. Each article can have its own type and view,
depending on the parent page.
CKEditor and KCFinder are available as replacement for tinyMCE / tinyBrowser.
6

Articles "Drag'n'Drop" ordering directly in the tree.


No tree refreshing after articles ordering in one page.
Page and Article editing more visual.
Page and Article creation more logical.
Article and page "tab" memory. When editing an article or page in one language, navigation to
another item opens the same tab.
More tooltips in admin panel.
Static translations rewritten. The editor can add his own terms.
Views and tags
<ion:navigation /> become more simple and more flexible. The output HTML is managed by a
helper.
Extend fields now outputs the default value if the default value is set.
If no view are defined for page and articles in the theme, Ionize now uses the default one from
/application/views/default/
filters more consistent : "OR" filter correction for <ion:articles filter="name:='TOTO' OR
name:='TITI'" />
Bugs correction
Corrected removing of an external link in a Page or Article.
Articles and page internal link correction.
Connect lib group ID retrieve bug corrected.

Downloading Ionize
Zip fileTop of Page

Ionize 0.9.9 (Current version)


7

Ionize 0.9.7

Ionize on GitHub
The Ionize project sources are hosted on Github : http://www.github.com/ionize/ionize
Administration panelTop of Page
The request URL /your-domain.tld/admin was not found on this server.
Check that the .htaccess file is present at the root of your installation.
If not, rename the .htaccess.txt file to .htaccess.
The request URL /index.php/en/admin/user/login was not found on this server.
Edit the .htaccess file and add or remove the comment before the RewriteBase / instruction.
RewriteEngine On

# The RewriteBase / instruction is commented. Remove the "#" to uncomment


# RewriteBase /

RewriteCond $1 !^(index.php|themes|install|files|modules|robots.txt)
RewriteRule ^(.*)$ index.php/$1 [L]
8

Settings saving errors, no thumbnail creation...


Context: When you save settings or add some media to a content, an error message appears.
Solution: The server PHP user must have writing privileges on following folders and files:

/application/config/*
/themes/*
/files/*
/cache/*

Log on your server with SSH and execute the following commands :
chmod -R 0777 /<path_to_www>/application/config/
chmod -R 0777 /<path_to_www>/themes/
chmod -R 0777 /<path_to_www>/files/
chmod -R 0777 /<path_to_www>/cache/
"No input file specified"
Some server needs this specific configuration.
Modify the .htaccess line to add a ? after the index.php :
RewriteRule ^(.*)$ index.php?/$1 [L]
Cannot login to backofficeTop of Page

If you're not able to log to the backoffice (to the administration part of your Ionize site), check if the time
of your server and the time on your local computer are set correctly.
Admin password lostTop of Page
Make a copy of the /install folder on your website and go to :
http://your_domain.tld/install/?step=user
(see forum thread : http://www.ionizecms.com/forum/viewtopic.php?id=323)
Enabling logsTop of Page
If something weird is happening with Ionize, you may want to activate logs to be able to find where the
problem is coming from.
Edit your /application/config/config.php file and set
$config['log_threshold'] = 4;
By default log file will be created in /system/logs/ folder.
InstallationTop of Page
We consider you're doing these steps first locally, to be sure everything works fine before uploading your
new version on your server.
From the existing 0.9.x :
10

1. Get and temporary store the encryption key from /application/config.php : $config['encryption_key']
2. Save the existing database
3. Get your theme folder
In the folder containing Ionize 0.9.9 :
1. Edit /application/config.php and paste your encryption key
2. Copy your theme folder into /themes/
3. Launch the installer
After installation :
1. Delete all the /files/thumb_x folders : The new media tag doesn't need them
2. In Ionize, set the theme to your theme in Settings > Theme > Options
3. Adapt your views
Development tipsTop of Page
Page views vs. articles views
In older version of Ionize, articles have views and render itself : the <ion:article /> tag was using the view
as defined in the Ionize backend in Page Edition > Options > Articles list and Article views.
We strongly recommend to not use articles views anymore.
Use only page views.
The reasons are not technical :

Based on experience, building a website with page and articles views make edition more complicated for
users,
11

Also, the developer who maintains the website has to manage a lot of articles views
In the fact, often articles views aren't necessary.

Page views : Articles list & Single article view


Pages have 2 kind of views, which can be defined in Options > Attributes > View and Options >
Attributes > Single Article View :
If only the View if defined, the frontend will use this view in any situation.
If both View and Single Article View are set, the frontend will :

display the view defined in View when the URL asks for a page
display the view defined in Single Article View when the URL asks for one article

This behaviour makes the development of pages like blogs very easy.
TagsTop of Page
They are some changes concerning tags.
These changes were necessary to make the tags more logical and more simple to use.
<ion:language />
Before :
1<ion:languages>
2<ion:url />
12

3</ion:languages>
Now:
1<ion:languages>
2<ion:language:url />
3</ion:languages>
<ion:navigation />
If you don't want to use one helper, simply remove the "helper" attribute.
Before :
1<ion:navigation level="0" helper="false">
Now :
1<ion:navigation level="0">
<ion:articles />
This tag should be used inside one parent <ion:page /> tag, which tells the <ion:articles /> from which
page it has to get the articles.

13

To loop in a collection of elements, the use of the plural (collection) and the singular tag is mandatory. That
means all tags which loops through a collection of elements have single elemnt tag which gives access to
the element data.
Before :
1<ion:articles>
2<ion:title tag="h3" />
3</ion:articles>
Now :
1<ion:page>
2<ion:articles>
3<ion:article:title tag="h3" />
4</ion:articles>
5</ion:page>
To get the articles from a given page.
Before :

14

1<ion:articles from="footer">
2<ion:title />
3</ion:articles>
Now :
1<ion:page:articles id="footer">
2<ion:article:title />
3</ion:page:articles>
<ion:article />
The use of the <ion:article /> tag to render one article view is not recommended anymore.
In other words, prefer the use of page views only in Ionize, instead of use page AND article views.
Before :
1<ion:articles>
2<!-- Render of the article by using the "article view" defined in Ionize -->
3<ion:article />
15

4</ion:articles>
Now :
1 <ion:page>
2 <ion:articles>
3 <ion:article>
4 <ion:title tag="h3">
5 <ion:content />
6 </ion:article>
7 </ion:articles>
8 <ion:page>
9 <!-- This can also be written like this : -->
10<ion:page:articles>
11<ion:article>
12<ion:title tag="h3">
16

13
14<ion:content />
15</ion:article>
16</ion:page:articles>
17<!-- All current page articles titles : -->
18<ion:page:articles:article:title tag="h3" />
19
If you need for to render each article with its own view :
- Set the article view in Ionize
- use <ion:article render="true" /> inside the <ion:articles /> tag.
<ion:medias />
The single tag <ion:media /> must be used when looping through media.
For picture, there is no need to define thumbs sizes in Ionize. Telling the tag the wished size will create the
resized picture.
Before :
1<ion:medias type="picture" limit="1">
17

2<img src="<ion:src folder='310' />" />


3</ion:medias>
Now :
1<ion:medias type="picture" limit="1">
2<img src="<ion:media:src size='310' />" />
3</ion:medias>
<ion:translation />
This tag never exists anymore. It is replaced by <ion:lang />
Before :
1<ion:translation term="you_are_here" />
Now :
1<ion:lang key="you_are_here" />
<ion:categories />
Categories list :
18

Before :
1<ion:categories>
2<a href="<ion:url />"><ion:title /></a>
3</ion:categories>
Now :
1<ion:categories>
2<a href="<ion:category:url />"><ion:category:title /></a>
3</ion:categories
In articles, to display categories to wish this article is linked to :
Before :
1<ion:categories separator=", " />
Now :
1<ion:article:categories:list link="true" separator=" &bull; "/>
<ion:element />
19

Before :

1
2
3

<ion:elements
type="my_element">
...
</ion:elements>

Now :
<ion:element:my_element
1>
2...
3</ion:element:my_element
>
See Tag Reference > Content Element for more details
Conditions in viewsTop of Page
Before 0.9.9, creating conditions in views was mostly done with pure PHP.
Now, 2 tags are available for conditions : <ion:my_tag is="value" /> and <ion:my_tag
expression="my_expression" />
20

The tags are detailled in Tag Reference > Shared attributes.


Before :
1
<?php
2
$class= '';
3
if (<ion:index/>%3 == 0) $class = ' last';
4
if (<ion:index/>%3 == 1) $class = ' first';
5
?>
6
<div class="<?php echo($class) ;?>">
7
Now :

<div class="<ion:index is='1'>alpha</ion:index> <ion:index


expression='%4==0'>omega</ion:index>">

Before :
1<?php if ('<ion:title />' !='') :?>
2<h2><ion:title /></h2>
21

3
4<ion:content />
5<?php endif ;?>
6
Now :
1
2<ion:title expression="!=''">
3<h2><ion:title /></h2>
4<ion:content />
5</ion:title>
6
Theme filesTop of Page
Static translation files
22

Rename the files your_theme_lang.php (folder /themes/your_theme/language/xx/) to


"theme_lang.php".
Development vs. Production
EnvironmentTop of Page
The Environment gives ability to have up to 3 different settings, depending where Ionize is running.
The environment is defined by the constant "ENVIRONMENT", set in the file : /index.php.
They are 3 running environments available :

Development : Displays all PHP errors


Test : Don't displays PHP errors
Production : Don't displays PHP errors

After one fresh install, Ionize is in "Development" mode.


Usually, 2 modes can be enough, but if you need to have differences between test and production, you can
edit /index.php from line 30.
Error logTop of Page
After installation, internal error logging is set to "2", which means debug and error information are logged
in the files /application/logs/log-YYYY-MM-DD.php.
To disable the error loggin, edit the file /application/config.php, line 192 :
23

1$config['log_threshold'] = 0;
Database configurationTop of Page
If you wish to use the ENVIRONMENT constant to define one database configuration per environment,
edit the file /application/config/database.php :
1 $active_group = 'default';
2 $active_record = TRUE;
3 $db['default'] = array();
4 switch (ENVIRONMENT)
5 {
6 // Local server
7 case 'development':
8 $db['default']['hostname'] = 'localhost';
9 $db['default']['username'] = 'my_local_user';
10$db['default']['password'] = 'paSSwoRd';
24

11$db['default']['database'] = 'ionize_local';
12$db['default']['dbdriver'] = 'mysql';
13$db['default']['dbprefix'] = '';
14$db['default']['swap_pre'] = '';
15$db['default']['pconnect'] = TRUE;
16$db['default']['db_debug'] = TRUE;
17$db['default']['cache_on'] = FALSE;
18$db['default']['cachedir'] = '';
19$db['default']['char_set'] = 'utf8';
20$db['default']['dbcollat'] = 'utf8_unicode_ci';
21break;
22// Test / server
23case 'testing':
24$db['default']['hostname'] = 'test.mydomain.com';
25

25$db['default']['username'] = 'uSer';
26$db['default']['password'] = 'paSSwoRd';
27$db['default']['database'] = 'ionize_test';
28$db['default']['dbdriver'] = 'mysql';
29$db['default']['dbprefix'] = '';
30$db['default']['swap_pre'] = '';
31$db['default']['pconnect'] = TRUE;
32$db['default']['db_debug'] = TRUE;
33$db['default']['cache_on'] = FALSE;
34$db['default']['cachedir'] = '';
35$db['default']['char_set'] = 'utf8';
36$db['default']['dbcollat'] = 'utf8_unicode_ci';
37break;
38// Production server
26

39case 'production':
40$db['default']['hostname'] = 'mydomain.com';
41$db['default']['username'] = 'uSer';
42$db['default']['password'] = 'paSSwoRd';
43$db['default']['database'] = 'ionize_prod';
44$db['default']['dbdriver'] = 'mysql';
45$db['default']['dbprefix'] = '';
46$db['default']['swap_pre'] = '';
47$db['default']['pconnect'] = TRUE;
48$db['default']['db_debug'] = FALSE;
49$db['default']['cache_on'] = FALSE;
50$db['default']['cachedir'] = '';
51$db['default']['char_set'] = 'utf8';
52$db['default']['dbcollat'] = 'utf8_unicode_ci';
27

53
54
break;
55
default:
56
exit('The application environment is not set correctly.');
57
}
58
59
The file /application/config/database.alternative.php gives you one good example.
If you use this feature, never use the backend to save the database configuration : Doing this will override
/application/config/database.php with only one configuration.
Ionize at a Glance
Ionize is SimpleTop of Page
Ionize was built with 3 main basis in mind :

Usability : Based on real life user experiences, Ionize is one of the most user friendly CMS
Flexibility : Developpers can create there own tags easily
28

Openess : Ionize is open to its community. Sharing ideas is the center of our work.

Ionize is FastTop of Page


Ionize is based on CodeIgniter, one of the faster PHP Application framework.
Most of template language are slowing down performances. The template language developed for Ionize
does not.
Inspired by a famous Ruby template language, it is today the fastest known PHP template language... after
PHP itself.
Ionize is ExtensibleTop of Page
Build your own controllers, create your own tags, these tasks are just simple with Ionize.
With Ionize, you get the power of CodeIgniter in your CMS.
If you need other data than the provided ones, you can create and use your own Content Elements and
Extend Fields, without altering manually the database.
Ionize is modular : If you need one dedicated feature, modules add features to both backend and
frontend.
Ionize is Really MultilingualTop of Page
No additional stuff to install : Ionize was thought multilingual.

29

Each content, from static data like "You are here" to pages, articles, medias data, everything can be
translated.
Ionize generates SEO friendly URLsTop of Page
Ionize produce SEO friendly URLs and let you define each URL regarding the language:
http://your-domain.tld/en/about/me
http://your-domain.tld/fr/a-propos/de-moi
Ionize is Thoroughly DocumentedTop of Page
Programmers love to code and hate to write documentation. We're no different, of course, but since
documentation is as important as the code itself, we are committed to doing it. Our source code is
extremely clean and well commented as well.
Ionize has a Friendly Community of UsersTop of Page
Our growing community of users can be seen actively participating in our Community Forum.
Ionize is beautifulTop of Page
At least but not the last, Ionize provides a beautiful and user-friendly Administration panel.
Our clients dislike using ugly application. We too !
That's why we consider the user experience as one basis when we develop Ionize.
30

We try to provide the more easy and logical backend : During lessons with our clients, we noticed all the
errors they made and we didn't tried to correct them, but to find out a better backend approach. So each
panel is designed, redesigned, enhanced by user experience.
Main ConceptsTop of Page
Ionize organizes content by :
1. Languages,
2. Menus
3. Pages and articles.
The entry point is the language, which will be detected when the user enter the website.
If no language was found, the default one will be loaded (the one defined during the install process).
WebsiteTop of Page
A website made with Ionize is composed of :

One or more languages


Content, stored in database (pages, articles)
One theme, containing display items
Media files : pictures, videos, music, etc.

Ionize allow the management of one website by installation (one folder).


Several themes can be used, but only one will be displayed.
31

ThemeTop of Page
A theme defines how the content of the website will be displayed.
A theme is a folder containing all the website views, assets (CSS, javascript, design pictures) and optional
widgets used by the website.
Themes are located in subfolders of the folder /themes.
The website has one theme.
ViewTop of Page
A view is simply a web page, or a page fragment, like a header, footer, sidebar, etc.
A view is used to display data. This could also be called a template, but Ionize uses the CodeIgniter
view terminology.
Common views are articles and page views.
One view can be used to display a page but can also be called by another view, as partial content.
Views are located in the folder /themes/your_theme_name/views.
Views extension is .php.
TagsTop of Page
One tag is a template language element used to display data easily.
Tags are used in views.
All tags start with the ion prefix and is written like one XML element : <ion:my_tag />
32

Example of tag usage:


<ion:articles limit="3" >

<ion:article:title tag="h2" />

<ion:article:content paragraph="1" />

<ion:articles />
This tag will display 3 articles, with content limited to the first paragraph.
Each article's title will be enclosed by a H2 HTML tag.
Main Ionize folders
During your website conception with Ionize, you will mainly use these folders.
Knowing their role is a good start.

Folder

Usage

Can be
renamed

Description

/files

All the website

Yes

Medias add through Ionize are stored here.


33

/install

/themes

content medias

This folder can contains sub-folders, its


organization depends on your wishes.

Installer program

This folder MUST be deleted after


installation

Theme folder

Each subfolder of this folder is a theme. The


admin subfolder is the Ionize panel theme. It
must not be deleted.

No

/themes/default

Default theme filesYes

This is a very basic theme used after a fresh


install of Ionize. You can rename it or copy it to
create your own theme.

/themes/default/config

Theme config files No

Some of these files are written by Ionize

Your helpers files No

This folder is optional. If you wish to replace


some of the existing helpers or create yours,
put them in this folder.

/themes/default/helpers

/themes/default/language Translations files

No

This folder is created by Ionize when you


create static translations items.
See Static Translations for more info.
34

/themes/default/views

Website views

No

Contains all the views of your website.

Quickstart : Ionize in 4 steps


Just after installing Ionize, the first question is mainly : "And now ?"
4 first steps will help you to start your website :
1.
2.
3.
4.

Create one theme,


Create one page view,
Activate the view,
Link this page to you content

1. Create your themeTop of Page


All themes are located in the folder: /themes/.
To create your own theme :

Copy or rename the folder /themes/default.


For example, name your theme folder : /themes/my_theme
In Ionize, select this theme in the Settings > Themes panel and save.
Start editing the views files in the /themes/my_theme/views folder of your theme.

35

Important:
The 3 folders config, helpers, views must be present in your theme folder.
No spaces or special chars are allowed in the folder name.
2. Create one page viewTop of Page
In the folder /themes/my_theme/views/ :
Create the file called "my_page.php" and add the following code :
// This will display the current page title
<ion:page:title tag="h2" />

// Here, we will loops through the articles of the current page


<ion:page:articles>

// Displays the article title


<h3><ion:article:title /></h3>

// Displays the article content


<ion:article:content />

</ion:page:articles>
36

3. Activate the view in IonizeTop of Page


A view can be used in 3 ways :

For pages
For articles
As partial in another view.

Page and articles views must be activated so Ionize can add them to the "view" list in the page and article
panels.
In Ionize, go to : Settings > Themes...
This panel shows the views PHP files.
For each view, you can enter a logical name, which will be in the view list of the page edition panel, and set
the type ("article" or "page").

4. Link the view to your contentTop of Page


37

First of all create a page in Ionize, then select your view in the view list.
Once your views are activated, they will be available for editors who will create and edit the content with
Ionize.

38

Next step ?Top of Page


Add data to your page views : Have a look at the Tag Reference section of this documentation.
Discover the Ionize backend
The Ionize backend, or "Administration panel" consists of:

The structure panel on the left


The main panel on the right
The main menu

The structure panel is always displayed and show you the pages and articles of the website. From this
panel, you can order pages and article and move articles directly by drag'n'drop in the tree.
The main panel displays the content you're editing. It can be one page, one article, or any other panel.
The main menu give you access to your website settings, tools, modules and advanced content editing
tools.

39

Previous Topic : Quickstart : Ionize in 4 steps Top of Page User Guide Home Previous Topic : Quickstart :
Ionize in 4 steps
Languages
During installation, you choose one default language for the website.
40

If you want to change it or if you want to add another language, go to Settings > Languages...
To change the lang code and name, simply edit them.
Adding one language will add the corresponding language tab in all contents (pages, articles, etc.)

Menus
Menus organize the content : They are containers for pages.
41

2 menus can't be changed : "Main menu" and "System menu".


The "Main menu" is the basic menu if you only have one menu in your website.
The "System menu" contains system pages, like the 404 page.
Adding one menu
Go into the panel : Content > Manage menus...
Click on the button : Create menu
Display one menu
To display the pages of one menu in views, Ionize comes with 2 tags :
<ion:navigation /> : This tag provides a one level navigation.
<ion:tree_navigation /> : Displays the complete tree of pages.
<!-- Example of the navigation tag usage : -->
<ion:navigation level="0" tag="ul" id="my_nav" class="navigation" active_class="active" />

<!-- Result : -->


<ul id="my_nav" class="navigation">
<li class="active">Home</li>
<li>Services</li>
42

<li>About us</li>
</ul>

<!-- Example of the tree_navigation tag usage : -->


<ion:tree_navigation tag="ul" id="my_nav" class="navigation" active_class="active" />

<!-- HTML Result : -->


<ul id="my_nav" class="navigation">
<li>Home</li>
<li class="active">Services</li>
<ul>
<li class="active">Webdesign</li>
<li>Coding</li>
</ul>
<li>About us</li>
</ul>
Look at the Ionize navigation tag documentation to see complete features of these tags.
43

Pages
Quick articles links
Creating one page - Pages settings - One page as a link - Page fields - Display page in views
Pages organize the content. They are used to build the navigation.
Pages can be nested, to create a multi-level navigation.
Pages are also containers used to display content (articles) or simply links to internal content or external
URLs.
One page can only have one parent menu.
Creating one pageTop of Page
To create one page, you can :

Click on the Add Page icon on the right of the menu name OR
In the main menu, select Content > Create page...

The options of the page aren't available when creating one page.
They will be available once the page is saved.

44

Pages settingsTop of Page


A page can be totally offline or online, or only online for a defined language.
In this case, the page must be globally online and offline for the wished language.

45

One page as a linkTop of Page


A page can link to an URL.
46

For example, a navigation item can link to an external URL or to an other internal page. Because pages are
navigation items, simply add a link to a page to activate this behavior.
To create one link to another page in the website :

First save you new page, to display the right option column,
Then drag the pointed page from the structure tree to the link area of the source page.

If one page is a link to an URL (internal or external), the content of this page will never be displayed.
Clicking on its link in the website navigation menu will point to the given link.
To create one link to an external URL :

Write the complete URL in the link area of the page. Example : "http://partikule.net"
Click on "Add link"

Page fieldsTop of Page


47

Here is a description of the default fields of pages.


These fields can be set through the Ionize page edition panel and through the page options panel.
Main fields

Field

Can be translated Description

Title

Yes

Page's title

Subtitle

Yes

Page's subtitle

URL

Yes

Page's website URL.


Must be unique on the whole website.

Navigation title Yes

Title of the page in the website's navigation menu.

Windows title

Browser's window title. Useful for SEO.

Yes

Options : Attributes

Field

Can be
translated

Default

Description
48

Display in
nav

No

Checked

If unchecked, this page will not be displayed in the navigation menu.


The page URL will be reachable, even it is not in the navigation menu.
If unchecked, this page will not be in the URL.
For example with the page :
Company / Services / Customer Help

Has URL

No

Checked

If the page "Services" has the checkbox "Has URL" unchecked, the
URL of the page "Customer Help" will be :
http://domain.tld/company/customer-help
If the page "Services" has the checkbox "Has URL" checked, the URL
of the page "Customer Help" will be :
http://domain.tld/company/services/customer-help
If the page has no URL, it can't be called and will return one 404

View

No

Define the view to use for this page.


If not set, Ionize will:

First look for one view called page.php in the website theme
core/page
folder

Single
article

No

Use the default view in : /application/views/core/page.php

Define the page view to use to display one single article.

49

view
Articles
view

No

If set, define which view will be used by articles showed by this page
when more than one article is displayed.

Options : Parent
Changing the menu and/or page of one page will move the page to the selected menu / page.

Field Description
Menu Select box of the available website's menus
Page Select box of the available website's pages
Options : Dates

Field

Description

Date

Logical date of the page. Will replace the creation date when using the date tag.

Publish

Date from when the page will be published

50

Unpublish Date from when the page will be unpublished.


Options : Sub navigation
Not documented at the moment.
This feature needs to be confirmed.
Options : Advanced options

Field

Default

Description

Home

Unchecked If checked, this page will become the home page of the website.

Used by module Unckecked If checked, sub URL of this page coming from modules will not return one 404

Article / Page

Pagination : Number of articles to display per page.


0 means display all articles.

Options : SEO

Field

Can be
translated

Description
51

Sitemap
priority

No

Sitemap priority of this page. 5 is the defualt value.

Description

Yes

Meta description for this page. Will replace the website's default meta
description.

Keywords

Yes

Meta keywords for this page. Will replace the website's default meta
keywords

Options : Access authorization

Field Description

Group

Group from whom the access is allowed. Each group with one level equal or greather than the selected
group will have access to the page.

Options : Operations

Field

Description

Copy content

Copy the content of the page from one language to another.


52

Include articles If checked, the copy operation will also copy the content of the articles linked to the page
Reorder articles Reorder the articles of this page by date (descendant or ascendant)

Display page in viewsTop of Page


Here is one example on how to display page's data in views.
For a complete page tag documentation, see Page tag documentation.
<html>
<body>

<!-- Displays the current page's title -->


<h2><ion:page:title /></h2>

<ion:page:subtitle tag="h3" />

<!-- Displays the current page's date (creation date or publish date) -->
<ion:page:date format="d.M.y" />

53

</body>
</html>

Articles
Quick articles links
Create one article - Articles and parents pages - Article types - One article as link - Articles fields - Display
articles in views
Articles contains the textual content.
One article can be a :

A simple article
One blog post with publication dates
One images gallery,
Any other content... depending on the way it will be used and displayed in the view.

Parent pages
One article can have one or more parent page. That means it can be linked to more than one page.
One common usage is to be able to add one article from one internal page to one slider of the home page.
This could be done automatically, but sometimes, the editor wants to have the flexibility to add choosen
articles.
54

One article can also be orphan, without any parent. In this case, it can't be displayed but is editable
through the Ionize Dashboard "Orphan articles" list
Main parent
If one article has more than one parent page, it will always one "main parent" page.
The main parent page will be used to build the URL to the article.
Create one articleTop of Page
They are several way to create an article :

When editing one page : Click on the Create Article button,


In the Structure panel : Fly with the mouse over one page and click on the Create Article icon. The
article will be created with this page as parent.

55

Articles and parents pagesTop of Page


Articles can be linked to parents page by drag and drop its name:

From the Structure tree to another page,


From the Articles panel articles list to a page in the Structure tree,
By dragging a page from the Structure tree to the Parents list of the article when editing an article,
From the Dashboard articles lists to one page the Structure tree.

Article typesTop of Page


56

Each article can be linked to one article type in its parent page.
Article types will define the kind of article and helps the developer to display articles in the good place in
views.
Example:

Your website has one home page slider


Editors must be able to select which article will be displayed in this slider

Solution :

In Content > Articles Types, create one Article Type with the name "home-slider"
The editor links the wished article also on the home page.
-> The article will have one "main parent" and one 2nd parent, which will be the home page.
In the home page view, filter the displayed articles on the type "home-slider"

The Article type is page dependant :


Set the type "home-slider" to one article on the home page will not change its type for its original parent.
One article as linkTop of Page
One article can link to an URL.
To create one link to another page or article in the website :

First save you new article, to display the right option column,
Then drag the pointed page or article from the structure tree to the link area ("drop a link here") of
the source article.
57

To create one link to one external URL :

Write the full URL in the link area. Example : http://partikule.net


Click on "Add Link"

Articles fieldsTop of Page


Here is a description of the default fields of articles.
These fields can be set through the Ionize article edition panel and through the article options panel.

Field

Can be
translated

Description

Online in
<Lang>

Yes

If unchecked, the article will not be available for this language

Title

Yes

Article's title

Subtiutle

Yes

Article's subtitle

URL

Yes

Article's URL, built when typing the title. Can be changed.

Windows

Yes

Browser's window title, displayed when the article is standalone displayed, for
58

title

example when displaying one post of a blog page.

Options : Attributes

Field

Default

Description

Indexed

unchecked

If checked, this article will be available for search functionnality (through the search
module)

Categories

Categories to wich the articles is linked to.


It is possible to select more than one category through CTRL+click or CMD+click

Parents

List of parent pages of this article.


The main parent page has a purple icon with one "P".

Options : Dates

Field

Description

Date

Logical date of the article. If set, it will replace the "Creation date" when the date is displayed
through the <ion:date /> tag
59

Publish date

If the current date is before the publish date, the article will not be displayed on the website.
If set, the date displayed by the article's <ion:date /> will be the publish date instead of the
creation date.

Unpublish
date

If the current date is after the publish date, the article will not be displayed on the website.

Options : SEO

Field

Can be translated Description

Description Yes

Meta description for this article. Will replace the website's default meta
description.

Keywords

Meta keywords for this article. Will replace the website's default meta
keywords

Yes

Options : Operations

Field

Description

Copy content Copy the content of the article from one language to another.
60

Display articles in viewsTop of Page


Here is one example on how to display articles in one view.
Have a look at the Articles Tag Reference for the complete documentation of this tag.
The <ion:articles /> tag is an iterator tag which allows to loop through articles.
The <ion:articles /> tag must be used as child of the <ion:page /> tag to display the articles of one page.
<ion:page>

<ion:articles>

<!-- Displays the article's title in a H2 HTML tag, only if the title is set -->
<ion:title tag="h2" />

<!-- Displays the article's title in a H3 HTML tag, only if the subtitle is set -->
<ion:subtitle tag="h3" />

<!-- The article's text content-->


<ion:content />

61

<hr />

</ion:articles>

</ion:page>

// HTML Result :

<h2>My article<h2>
<h3>Article's subtitle, if any<h3>
<p>The article's content text</p>
<hr />

<h2>Another article<h2>
<p>The other article's content</p>
<hr />

Media : Files, pictures, videos...


62

Quick articles links


Allowed media - Add and link one media - Media list & linked pictures - Media meta data - Display media in
views
Pictures, music, videos, files can be uploaded through the Ionize File Manager or directly by FTP in your
media folder.
Media can be used in 2 ways :

Linked to articles or pages and displayed through ionize's tags,


Added in articles content with the embeded editor.

Media Folder
By default, the media are stored in the /files folder of your website directory.
To change the default media folder, go in the panel : Settings > Advanced Settings > Media.
Changing the files folder name through the Ionize Settings panel :
- Renames the filesystem folder
- Updates media URLs found in the database content.
Allowed mediaTop of Page
Allowed type of media can be setup in the Ionize panel : Settings > Advanced Settings > Media.
Setting up allowed media improves security by limiting file upload.

63

Add and link one mediaTop of Page


To add one media, when you're editing one page or article:

Click on the Add Media button : This will open the File Manager
Browse to the folder in which you will to add your media
Click on the Upload button : This will let you select your medi on your computer
Validate : The media is send to the server

To link one media to one article or page :

Click on the Add Media button : This opens the File Manager
Double click on the wished media : it is linked to the content

64

65

Media list & linked picturesTop of Page


We saw how to link media to pages or articles.
In some case you can ask you why to link pictures instead of putting them directly inside the article content
?
Linked media instead of adding them to the content has several advantages :

The media meta data (alternative text, title, etc.) are stored in database, for each media,
Because the media list can be looped in a view, it is easy to build a gallery from media linked to an
article,
The <ion:media /> tag automatically resizes the picture to the wished size. This preserve the design
and makes the page loading faster.

Ordering and editing linked media


To order media, simply move them in the list by drag'n'drop.
The little yellow pen will open the media data window, the little unlink icon will unlink the media from the
parent page or article

66

Media meta dataTop of Page


Once one media is attached to a page or a article, it is encouraged to add some meta data to it.
Once written, these meta data will be linked to the media and if you attach the same media to another
article or page, you will find the same data.
In other words, once set, you don't have to set again the media meta data of one medium.
To edit the meta data of one media, click on the little yellow pen icon at the bottom of the thumbnail.
67

Display media in viewsTop of Page


The <ion:medias /> tag allows to loop through media linked to a page or to an article :
<!-- This example displays the 3 first pictures linked to the current page -->
<ion:page>

68

<!-- The size of each picture will be 300px x 200px -->


<ion:medias type="picture" limit="3" size="300,200" >

<img title="<ion:media:title />" alt="<ion:media:alt />" src="<ion:media:src />" />

</ion:medias>

</ion:page>
Look at the Ionize Media Tags documentation to see complete features of this tag.
Static translations
Static translations are translated terms (words or sentences) which are not content, but which concerns
generally the website interface.
For example, terms like "Go home" or "Submit button" are static translations.
Another example is the common text "Website created by My Agency" at the bottom of the website.
This can of course be written hardly in the view, but it could be nice to make it available for each
language of the website. So if the user visit the website in french, this text will become "Site conu par
Mon Agence", which of course is nicer for french readers.
To manage static translation, go to the Ionize panel : Content > Translations
69

More about static translationsTop of Page


Static translations are stored in a language file, linked to the current theme.
This file is generated by Ionize.
Folder : /themes/your_theme/language/xxx/your_theme_lang.php
In this example, "xxx" is the language code on 2 or 3 chars, and "your_theme" is the name of your theme.
Using static translations in viewsTop of Page
1. Simply add the tag <ion:lang key=your_term /> in one of your view.
2. Go to the Ionize menu : Content > Translations
3. You will find your term and be able to translate it
Users and Groups
An Ionize user can or not connect to the website and/or to the admin part of Ionize.
Each user is in a group.
Each group has a level which define its rights in Ionize.
Users and groups are securely stored in the database. The password of each user is strongly encrypted,
make it uncrackable in case of database hack.
Groups are defined as follow.

70

Group

Level Description

Super
Admins

10000

Users in this group have all rights in Ionize. The user created during installation is member
of this group.

Admins

5000

Users in this group have all rights but no access to the Advanced settings panel (DB
modification, thumbnail edition, extended fields activation / inactivation, etc.)

Editors

Users in this group can edit all content but have no access to :

Website settings,

Users settings,
1000

Modules administration,

Some module panel depending on the module's access restriction.

Users

100

This group has no access to Ionize, but can have access to restricted part of the website.

Pending

50

Contains users waiting for registration acceptation

Guest

10

Users not logged to the website have this level.

Banned

-10

Users in this group have no access to the website.

Content Online / Offline


Content (page, articles) can be online and offline.
71

Set one content offline means this content is not reachable through its URL:
The website will return the 404 page.
When you're connected to the admin panel as "editor" or "admin", the offline content will be visible on the
website.
This gives you a simple way to see how the content will look before putting it online.
Of course not connected users will not see this content online.
What's a theme ?Top of Page
A theme is a folder containing :

Views used by the website,


Assets used by the theme (CSS, javascript, design pictures),
Helpers dedicated to the website (navigation helper for example),
Static translations files,
Optional widgets used by the website.

Themes folders are located in the /themes folder of your website.


Important: The 3 folders in red in the following picture (config, helpers, views) must be present in your
theme folder.

72

Create the themeTop of Page


To create and use one theme :

In the folder /themes, create the sub folder "my_theme"


In Ionize, go to Settings > Theme...
In the "Options" tab, select "my_theme" as theme and click on Use these themes

That's it, "my_theme" is now the theme used by your website.


73

Create one page : Views


Pages use views... But, what's a view ?Top of Page
Views are PHP file located in the folder /themes/your_theme/views/.
Views are a part of the website theme. They are used by the website to display the content.
Views files have the .php extension.
Pages and articles use views to be displayed.
Views and TagsTop of Page
A view displays the website content through tags.
We can also say that tags are used in views to display content from the database.
Each view file contains mainly HTML code and tags.
Tags retrieve data and are a quick and easy way to display them without writing PHP code.
All usable tags are documented in the Tags Reference part of the current documentation.
Kind of viewsTop of Page
They are 3 kind of views :

74

View type

Page
views

Description
Linked to one page through Ionize.
Used to display all pages elements :

Pages meta data : Website title, page title

Medias linked to the page

Partials views, like header or footer

Article
views

Linked to one article or to the "Article's views" of one page.


Used to display all articles fields.

Partial
views

These views are used as partial block in other views, for repeating content.
For example, if the header of the website is always the same, you will create an "header.php"
view and include it in a page view.

Since Ionize 0.9.9, articles views are not really used anymore.
Pages views are enough to build most of the websites without the need of using dedicated articles views.
The more views you use, the more complex will be the edition of the website. Keep it simple !
Activate pages and articles viewsTop of Page
Pages and Articles views need to be activated in order to use them in the Page and Article panels of
Ionize (to link these views to pages or articles).
To activate views :
75

In Ionize, go to : Settings > Theme... : This panel shows the views PHP files.
For each view, set a logical name, and set the type ("Article" or "Page").
Save
Edit one page : The view will be available in the Options > Attributes > Views select box.

Create one page viewTop of Page


Basically, one page view displays the navigation, the current page content (title, medias, etc.) and loops
through the articles linked to the current page.
76

A page view can also displays articles from another page, even this other page has no URL or is not in the
navigation menu of the website.
A page view can also include other views, called "partial" views.
What we will do
We will create one basic Home page for the theme called "my_theme".
This home page will :

Call 2 partial views : header and footer,


Display basic page data
Loop through the articles of the current page
For each article, display the linked pictures

1. Create the "header" view


In the folder /themes/my_theme/views/ :
Create the file called "header.php" and add the following code :
1 <!DOCTYPE html>
2 <html lang="<ion:current_lang />">
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
77

5 <!-- Website title : Will display the page or article's meta title or the site title if not set -->
6 <title><ion:meta_title /></title>
7 <meta name="description" content="<ion:meta_description />" />
8 <meta name="keywords" content="<ion:meta_keywords />" />
9 <!-- The "style.css" file will be located in /themes/my_theme/assets/css/ -->
10<link rel="stylesheet" type="text/css" media="all" href="<ion:theme_url/>assets/css/style.css" />
11</head>
12<body>
13<!-- Languages menu -->
14<ul class="lang">
15<ion:languages no_helper="true" active_class="lang_active">
16<li>
17<a href="<ion:language:url/>" class="<ion:language:code/>" title="<ion:language:name/>"></a>
18</li>
78

19
20
21
22
23
24
25
26

</ion:languages>
</ul>
<!-- Main Navigation menu -->
<ion:navigation level="0" tag="ul" class="navigation" active_class="active" />
<!-- Breadcrumb -->
<a href="<ion:base_url lang="true" />"><ion:lang key="home" /></a>
&nbsp;&#8250;&nbsp;<ion:breadcrumb level="1" />

27

This header will be called by each page of the website.


It will display :

Basic website's data, such as title, meta_description. For more information, see Website meta tags
The languages menu. For more information, see the Language Tag reference
The navigation menu. For more information, see the Navigation Tag reference
The breadcrumb. For more information, see the Breadcrumb Tag reference
79

2. Create the "footer" view


In the folder /themes/my_theme/views/ :
Create the file called "footer.php" and add the following code :
</body
1>
2</html
>
Of course the footer could be more complex, but for this example, this simple one is enough.
3. Create the "home_page" view
In the folder /themes/my_theme/views/ :
Create the file called "home_page.php" and add the following code :
1 <!-- This includes the header view -->
2 <ion:partial view="header" />
3 <!-- Display the page title -->
4 <ion:page:title tag="h2" />
5 <!-- Display the page subtitle, if one is set -->
80

6 <ion:page:subtitle tag="p" class="gray" />


7 <!-- Loop through the articles of the current page
8 <ion:page:articles>
9 // Displays the article title
10<h3><ion:article:title /></h3>
11// Displays the article content
12<ion:article:content />
13<!-- Display the article's resized pictures -->
14<ion:article:medias type="picture" size="300,200" >
15<img src="<ion:media:src />" alt="<ion:media:alt />" />
16</ion:article:medias>
17</ion:page:articles>
18<!-- This includes the footer view -->
19<ion:partial view="footer" />
81

4. Link the view to one page

In Ionize, go to : Settings > Themes...


For the file "home_page.php", set the logical name to "Home" and the type to "page"
Save
Edit your home page or create one new page
Select the view "Home" in the view list

The page uses now the view home_page to display its content
To display the page's articles, you need to create some articles linked to this page.
Articles and Types
In a page, some articles are displayed in the main column and other articles need to be displayed in a side
column.
Article Types make this possible.
Article Types are used by the editor on the articles linked to pages and by the designers in views.
To create a type :

In Ionize, go to : Content > Articles Types


Click on the button "New type"
Enter one name, one color (optional) and one description (optional)
82

Save

Using types in content editionTop of Page


The article type is set in the page articles list.
83

1. Edit one page


2. In the bottom article list, for each article, set the wished type.
One article can have one type when linked to a page and one other when linked to another page.
Article's type depends on the page context of the article.

Using type in viewsTop of Page


<ion:page>

<!-- Display the "side-bloc" articles -->


<ion:articles type="side-bloc">

84

<!-- Article's title -->


<ion:article:title tag="h3" />

<!-- Article's content -->


<ion:article:content />

</ion:articles>

</ion:page>

Add PHP to views


From release 0.9.9, PHP can mostly be avoided in views.
If you need conditional data test, have a look at the chapter Conditions with tags.
1// returns the current year
2<?php echo date('Y'); ?>
Conditional PHP
Because the PHP code is executed after the Ionize tag parsing, the tags values can be tested.
85

1
2<?php if ('<ion:page:title />' == 'About' ) :?>
3<p>This content is displayed if the title of the page is "About"</p>
4<?php endif ;?>
5
Passing data from one tag to one tag attribute

1 <?php
2 // Get the title of the page
3 $page_title = '<ion:page:get key="title" />';
4 ?>
5 <ion:page:articles>
6 <!-- For each article, we display the page title as prefix -->
7 <?php
86

8
echo '<ion:article:title prefix="'.$page_title.' : " />';
9
?>
10
</ion:page:articles>

Introduction to Tags
What are tags ?Top of Page
Ionize tags are XML entities, used in the views of the website to display data.
One tag always start with the <ion: prefix.
Each tag has a corresponding PHP method which retrieves data from database.
Tags can be nested and often, they retrieve data regarding to their direct parent.
We call that the "context" of the tag.
Context are processed from left to right.
For example <ion:page:articles:article:title /> will get first the current page data, then the articles, then
loop through each article and finaly get the title.
One tag has a name and can have some attributes, which help to return the good data.
One tag can simply return data or it can be one "Iteration" tag, used to loop through an collection of
elements, like articles or media.
87

For example, if you want to display all the articles of a page, you will need to loop through articles. The
<ion:articles /> tag will do this.
Example of one simple data tag
In this example :

<ion:page : means "I want data from the current page"


<ion:page:title /> means : "Display the title from the current page"
tag="h2" is one tag attribute (named "tag") with the value "h2". That means "Wrap the title into one
H2 HTML tag"

<!-- Displays the title of the page : short write mode -->
<ion:page:title tag="h2">

<!-- Same result, long write mode -->


<ion:page>
<ion:title tag="h2" />
</ion:page>
Example of one iteration tag
In this example, we wil iterate through all languages with the tag <ion:languages /> and display each
language name and URL.
88

<ion:languages tag="ul" id="lang" class="languages">

<!-- Displays the language name and links to the current content for each language -->
<li><ion:language:url /><ion:language:name /></li>

</ion:languages>

Ionize default tagsTop of Page


Ionize comes with several tags, which can be grouped in families :

Website tags : Data concerning the website : title, meta, URLs, settings, etc.
Navigation tags : Navigation through pages
Languages Tags : Navigation through languages
Page tags : Data from pages
Article tags : Data from articles
User tags : Data from user
Media tags : Data from media
Form tags : Display and process forms

Common Tags

89

Common data tagsTop of Page


Some data tags are the same for several parents tags.
For example, the <ion:title /> tag can be used as children of <ion:page /> but also as children of
<ion:article />

Tag

Parent tags

Example
<!-- The current page's title -->
<ion:page:title tag="h2" />
<ion:page:articles>
<!-- Article's title -->
<ion:article:title tag="h3" />

<ion:title />

page, article, media

<ion:article:medias size="400,300" type="picture">


<!-- Media title -->
<a title="<ion:media:title />"><img src="<ion:media:src />"
alt="<ion:media:alt />"/></a>
</ion:article:medias>
</ion:page:articles>

<ion:subtitle /
page, article, media
>
<ion:index />

page, article, media,


category, language
90

<ion:date />

page, article, media

<ion:created /
page, article
>
<ion:updated /
page, article
>

writerTop of Page
Displays data about the article's last editor.
Parents : <ion:page />, <ion:article />
<ion:article:writer>

<!-- Screen name of the user -->


<ion:name />

<!-- Firstname & Lastname -->


<ion:firstname /> <ion:lastname />

<!-- Email -->


91

<ion:email />

<!-- Gender. 1 : Male, 2 : Female, 0 : Not set-->


<ion:gender -->

<!-- Birth date -->


<ion:birth_date />

<!-- Join date -->


<ion:join_date -->

</ion:article:writer>

Special Tags
partialTop of Page
Returns the result of a view used as partial.
1

<!-- Returns the content of the view located in the folder :


92

/themes/your_theme/views/default/header.php -->
2
<ion:partial view="default/header" />
Attribute Optional

Values

view

The path to the view, relative to the


themes/your_theme/views folder.

no

uriTop of Page
Tag : <ion:uri />
Gives information about URI and the asked entity.
Get the URI entity type :
1<!-- Returns 'page' if the URI asks for a page, 'article' if the URI asks for one article -->
2<ion:uri:entity />
Make a test on the entity type :
1<ion:uri:entity is="page">
2This is a page
93

3</ion:uri:entity>
4<ion:else>
5This is something else
6</ion:else>
sessionTop of Page
This tag uses the Session library of CodeIgniter.
See : CodeIgniter Sessions
Set one session value
1<-- Test of the session var called "my_var" -->
2<ion:session:get key="my_var" is="false">
3<!-- Display this message if the session var isn't set -->
4<p class="red">"my_var" is not set.</p>
5<p>Reload the page to set it was just set.</p>
6<!-- Set the session var -->
94

7
<ion:session:set key="my_var" value="1" />
8
</ion:session:get>

Get one session value


1<!-- Display the session value -->
2<p>
3Session value : <b><ion:session:get key="my_var" /></b>
4</p>
set / getTop of Page
<ion:set /> and <ion:get /> can be used to set and get data.
Setting one value :
1<ion:set key="my_var" value="The Value" />
Get one value :
95

1<ion:get key="my_var" />


<ion:get /> can be used to get one field from its parent context tag data:
1
<!-- Get the ordering value of the page -->
2
<ion:page:get key="ordering" />
3
<!-- Test if the article link is one external one -->
4
<ion:article:get key="link_type" is="external">
5
... do something here
6
</ion:article:get>
7
traceTop of Page
<ion:trace /> is to be used in development, to see the content of data array.
This tag will output the data array.
1<ion:article>
2<ion:trace />
96

3</ion:article>
Shared attributes
Some commons attributes are used by all tags which returns data.
These attributes have the same behaviour for each tag, like the "class" attribute of HTML tags.
HTML Design attributes

tag : Wraps the data inside the given tag


id : Adds to the wrapping tag the given ID
class : Add to the wrapping tag the given class

Using the tag attribute is very useful because it will not return one empty tag if the value is empty.
<ion:page:title tag="h1" class="red box" id="page-title" />

<!-- Result if the page title is "Services" -->


<h1 id="page-title" class="red box">Services</h1>

<!-- Result if the page title is empty : nothing -->


Without the tag attribute :
97

<h1 id="page-title" class="red box"><ion:page:title /></h1>

<!-- Result if the page title is empty -->


<h1 id="page-title" class="red box"></h1>

Data processing attributes


These attributes are useful if you need to process the data through one simple PHP function or through one
CodeIgniter helper.

function : processes the data through the given PHP function


helper : process the data through the given CodeIgniter helper

<!-- Returns the article's title in lowercase -->


<ion:article:title function="strtolower" />

<!-- Checks the typography with the CodeIgniter's auto_typography helper -->
<ion:article:content helper="typography:auto_typography" />

<!-- Repeats the title 3 times -->


<ion:article:title helper="string:repeater:3" />
98

String processing attributes

prefix : Adds one prefix to the data


suffix : Adds one suffix to the data
paragraph : Limits the data to the given number of paragraphs
words : Limits the data to the given number of words
characters : Limits the data to the given number of characters
ellipsize : strip tags from the data, split it at a defined maximum length, and insert an ellipsis

prefix / suffix
This attribute can have one simple string as value, but also one translation.
See Static Translations for more info about lang keys.
<!-- Prefix / suffix -->
<ion:article:title prefix="Read more about : " />

<!-- Returns : -->


Read more about : My Article

<!-- Prefix / suffix with static translation -->


<ion:article:title prefix="lang('read_more_about')" />
99

<!-- Returns in french -->


Lire la suite de : Mon Article

<!-- Returns in english -->


Read more about : My Article

<!-- some fun with prefix and suffix -->


<ion:categories:list prefix="'&bull; '. lang('post_in_categories').' : '" />

<!-- Returns in english -->


Post in categories : My Category

The suffix attribute has the same behavior than prefix.


paragraph, words, characters, ellipsize
These attributes will limit the displayed content.
<!-- Display the first paragraph of the article's content -->
<ion:article:content paragraph="1" />
100

<!-- Limit the title to 4 words -->


<ion:article:title words="4" />

<!-- Limit the subtitle to 25 characters -->


<ion:page:subtitle characters="25" />

<!-- Ellipsize the content -->


<ion:article:content ellipsize="true" />

<ion:article:content ellipsize="32,.5,1" />

Date formatting attribute


This attribute works only on date tags.
One basic usage is to set one PHP date format to output the date :
<ion:article:date format="d.m.Y" />

101

Short formatted date


If one of the following format is used, the corresponding translation will be searched first in the
/themes/your_theme/language/xxx/date_lang.php file, then in the core translation file if your date
translation file isn't found :

D : Name of the day, on 3 chars.


l : Name of the day, long.
F : Name of the month, long
M : Name of the month, on 3 chars

That means the day and month names will be displayed in the according language, as translated in each
translation file.
The following code will display "Mon" if the user visit the website in english and "Lun" if he visits the
website in french.
<ion:date format="D" />
Long formatted date
But one common issue is that date format are not the same from one lang to another.
In US, one common date format is 12.31.2012, but in France, the day displayed first, so this date will look
like this : 31.12.2012.
You may also wish to display the month in words, like december 31. 2012 or 31 dcembre 2012.
To do that :
1. Copy the file /application/language/xx/date_lang.php to
/themes/your_theme/language/xx/date_lang.php in each "xx" lang folder,
102

2. Open the copied lang file and edit the keys $lang['dateformat_short'],
$lang['dateformat_medium'], $lang['dateformat_long'] or $lang['dateformat_complete']
depending on your needs.
For example :
- in en/date_lang.php: $lang['dateformat_medium'] = 'M d Y';
- in en/date_lang.php: $lang['dateformat_medium'] = 'd M Y';
3. Use the format attribute like this :
<!-- Use of the date format "medium", defined by $lang['dateformat_medium'] -->
<ion:article:date format="medium" />

<!-- This will return for french -->


31 dec 2012

<!-- This will return for english -->


dec 31 201
Be sure that the files date_lang.php are existing for each language of your website.
Test and Conditional attributes
These attributes test the value returned by the tag and display the enclosed content only if the tag value
match the test.
103

is
expression

is
Simple test against one given value.
<!-- Displays "This is the first article" if the tag "index" has the value 1 -->
<ion:article:index is="1">
This is the first article !
</ion:article:index>
expression
Equality test
<!-Each 3 picture, we add the class="last" attribute on the <li> element
This literally means "if index modulo 3 equals 0"
-->
<ion:medias type="picture" size="200" tag="ul">
<ion:media >
<li <ion:index expression="index%3==0"> class="last"</ion:index>>
104

<img src="<ion:src />" />


</li>
</ion:media>
</ion:medias>

<!-This can also be written :


-->
<ion:medias type="picture" size="200" tag="ul">
<ion:media >
<li <ion:index expression="index.eq(0)"> class="last"</ion:index>>
<img src="<ion:src />" />
</li>
</ion:media>
</ion:medias>
When the key to use isn't given in the expression, the tag value is used :
<!-- Use of the <ion:else /> tag -->
105

<ion:article:title expression=".eq('My Article')">

Yiiii, this is the article

</ion:article:title>
<ion:article:else>

... not happy... this is not the article

</ion:article:else>
Take care to the equal test "==" used against strings : the string must be wrapped into single quotes.
Greather than
<ion:article:index expression="index.gt(3)">
Wer're after the third article
</ion:article:index>

<!-- Shorter method : -->


<ion:article:index expression=".gt(3)">
106

Wer're after the third article


</ion:article:index>
Lower than
<ion:article:index expression="index.lt(3)">
Wer're before the third article
</ion:article:index>

<!-- Shorter method : -->


<ion:article:index expression=".lt(3)">
Wer're before the third article
</ion:article:index>
Multiple test
For multiple tests, the used keys must be explicitly written.
<ion:article:index expression="index.lt(3) OR index.eq(3)">
Index <= 3 !
</ion:article:index>

107

Website
These tags returns data about the website.
base_urlTop of Page
Returns the website base URL of the website.
home_urlTop of Page
Returns the website's home URL.
If more than one lang is defined, the lang code will be added to the URL for all languages which are not the
default one.
For example, if the website has 2 languages, "en" and "de" with the default language "en", if one visitor
visit one "de" page, the base URL will be http://domain.tld/de/.
If the visitor is one the "en" part of the wesbite, the base URL will be http://domain.tld/.
lang_urlTop of Page
If more than on language are defined for the website, the default lang will be added to the domain URL for
all languages.
theme_urlTop of Page
108

Returns the website theme complete URL, with trailing slash. Useful for accessing assets (CSS, images).
Examples of return : http://your_domain.tld/themes/your_theme/
<html>
<head>
<link rel="stylesheet" href="<ion:theme_url />assets/css/style.css" />
</head>

site_titleTop of Page
Returns the website title as set in Settings > Website settings...
Same as <ion:setting key="site_title" />
<ion:site_title />

browserTop of Page
Returns or makes one test on the current used browser.
<!-- Returns the current browser name -->
My browser is : <ion:browser />

109

<!-- Test on one Browser -->


<ion:browser method="browser" is="Firefox">

<!-- This is only displayed if the browser is Firefox -->


<p>You're using Firefox</p>

</ion:browser>

Attribute Optional Values

method

yes

Description

is_browser
is_mobile
is_robot
is_referral
browser
version
See http://codeigniter.com/user_guide/libraries/user_agent.html for all
mobile
available methods.
robot
platform
referrer
agent_string
accept_lang
accept_charset
110

value

To be used with methods which accepts one input value, such as


is_browser

yes

settingTop of Page
Returns one website setting value
<ion:setting key="theme" />

Attribute Optional Values

key

no

site_title : Website title


files_path : Media folder name, without trailing slash
theme : Current theme name
google_analytics : Google Analytics code

meta_titleTop of Page
Displays the window's browser's title of the displayed page.
This title can be set :

On articles : In "Window title"


One pages : In "Window title"
111

The displayed title is, in order :


1. The current article's or page's "Window Title" value if not empty,
2. else the article's or page's "Title"
If the attribute with_site_title is set to true :
The website's title defined in Settings > Website settings will be added before or after the displayed
title.
<html>
<head>
<title><ion:meta_title with_site_title="true" position="after" separator=" | " /></title>
</head>

Attribute

Optional Values

Description

with_site_title yes

true / false
Default value :
false

Adds the website title to the page or article title

position

before / after
Default value :
before

To be use with the with_site_title attribute.


Position of the website title : Before or after the page or article
window title.

yes

112

separator

yes

Default value : ' - '

Separator between the website's title and the page or article


window title.

meta_descriptionTop of Page
Displays the page or article META description set in Options > SEO > Description
If no description is set, displays the website's META description set in Settings > Website settings >
Description
<html>
<head>
<meta name="description" content="<ion:meta_description />" />
</head>

meta_keywordsTop of Page
Displays the page or article META description set in Options > SEO > Keywords
If no description is set, displays the website's META description set in Settings > Website settings >
Keywords
<html>
113

<head>
<meta name="keywords" content="<ion:meta_keywords />" />
</head>

current_langTop of Page
This tag is deprecated in 0.9.9.
You must use <ion:language:code /> instead.
See : Language Tags
google_analyticsTop of Page
Shortcut for <ion:setting item="google_analytics" />
Returns the Google Analytics code as set in the panel : Settings > Website settings > Statistics
<!-- Code in view -->

<ion:google_analytics />

114

<!-- Returns -->

<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js'
type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-0000000-00");
pageTracker._trackPageview();
</script>

Navigation
breadcrumbTop of Page
Display the breadcrumb navigation menu.
1<ion:page:breadcrumb home="true" />
2<ion:page:breadcrumb separator=" &bull; " />
115

3
4<ion:page:breadcrumb separator="" tag="ul" child-tag="li" />
5
navigationTop of Page
Displays one level of menu navigation.
This tag can use one optional helper to display the menu.
1

<!-- Sample code -->

<ion:navigation tag="ul" class="nav">

<li<ion:is_active> class="active"</ion:is_active>>

<a href="<ion:url />"><ion:title /></a>

</li>

</ion:navigation>

<!-- Example of result -->

<ul id="my_nav" class="nav">


116

9
<li class="active"><a class="active" href="http://my_domain.tld/home/">Home</a></li>
10
<li><a href="http://my_domain.tld/service/">Our Services</a></li>
11
<li><a href="http://my_domain.tld/about/">About our company</a></li>
12
</ul>
13
Attribut
Optional
e

Values

level

yes

The wished displayed level.


Default value : 0

menu

yes

The wished displayed menu.


Default value : main

helper

yes

<Name of the helper>:<function> to use to


display the navigation menu.
This is another way to implement your own helper
to display the navigation.
If your helper file is called
my_navigation_menu.php and your helper
117

function is named my_navigation_func(), you will


write : <ion:languages
helper="my_navigation_menu:my_navigation_fun
c" />
Use one helper with <ion:navigation />
When strongly encourage to not use one helper for basic navigation display. It is simpler and more
readable to use the <ion:navigation /> children tags.
If you want to use one helper to display the navigation menu :
If you wish to create your own helper to display the menu in a different way:

Copy /application/helpers/navigation_helper.php to :
/themes/your_theme/helpers/navigation_helper.php
Edit the method get_navigation()

The tag will automatically take your helper instead the default one.
Never modify the file /application/helpers/navigation_helper.php, this file will be overwritten when
migrating to a newer version.
tree_navigationTop of Page
A tree based navigation menu, as a unordered HTML list (<ul>...</ul>).

118

This tag uses one helper.


By default, it uses th helper located in /application/helpers/navigation_helper.php :
get_tree_navigation()
<!-- Sample code -->
<ion:tree_navigation active_class="active" tag="ul" id="my_nav" class="nav" />

<!-- Example of result -->


<ul id="my_nav" class="nav">
<li><a href="home">Home</a></li>
<li class="active"><a href="services">Our Services</a></li>
<ul>
<li class="active"><a class="active" href="webdesign">Webdesign</a></li>
<li><a href="coding">Coding</a></li>
</ul>
<li><a href="about">About us</a></li>
</ul>

Attribute Optional Values

119

level

yes

The wished displayed level.


Default value : 0.

depth

yes

Limit of the menu depth.


"2" means 2 levels, including the starting level.

menu

yes

The wished displayed menu.


Default value : main

yes

<Name of the helper>:<function> to use to display the navigation menu.


This is another way to implement your own helper to display the navigation.
If your helper file is called my_navigation_menu.php and your helper function is named
my_navigation_func(), you will write : <ion:languages
helper="my_navigation_menu:my_navigation_func" />

helper

Customize <ion:tree_navigation />


Navigation tags are coupled to helpers functions, located in : /application/helpers/navigation_helper.php
If you wish to create your own helper to display the menu in a different way:

Copy /application/helpers/navigation_helper.php to :
/themes/your_theme/helpers/navigation_helper.php
Edit the method get_tree_navigation()

The tag will automatically take your helper instead the default one.
120

Never modify the file /application/helpers/navigation_helper.php, this file will be overwritten when
migrating to a newer version.
languagesTop of Page
To navigation through languages, have a look at the Language Tags.
Languages
These tags let you :

Navigate through languages and display the languages menu,


Display the current language information
Display static translated items

languagesTop of Page
Iterator for languages.
This tag is commonly used to display the languages menu.
<ion:languages tag="ul">

<li <ion:language:is_active> class="active"</ion:language:is_active>>

121

<a href="<ion:language:url />">


<ion:language:code /> : <ion:language:name />
</a>

</li>

</ion:languages>
Children tags

Tag

Returns

<ion:language:code />

Lang code, as set in Ionize.

<ion:language:name />

Lang name, as set in Ionize.

<ion:language:url />

Complete URL to the current content in the looped language.

translationTop of Page
<ion:translation term="..." /> is deprecated from Ionize 0.9.9.
122

Use <ion:lang key="..." /> instead.


langTop of Page
Displays one static translation, as set in Ionize or in your views.
If the key you're asking for in your view (let's says "your_key") isn't found, it will display #your_key.
<ion:lang key="your_term" />

Attribute Optional Values


key

no

The key of the translated term, as displayed in the Content > Translation panel of Ionize.

Page
To display content other than website information or navigation menu, you will need to use the
<ion:page /> tag as entry point.
With this tag, you will be able to tell to all the children tags from which page you want the data.
pageTop of Page
Displays data from given page.
Every children tag will use this page as parent for the displayed data.
123

To display the current page title, in one H2 tag :


<ion:page>
<ion:title tag="h2" />
</ion:page>

<!-- Short write method : -->


<ion:page:title tag="h2" />
To display the title of the page with the ID 3 :
<ion:page id="3">
<ion:title />
</ion:page
To display the title of the page with the name "contact" :
<ion:page id="contact">
<ion:title />
</ion:page

124

The "name" of one page is unique and set in the page options panel.
When saving a new page, Ionize automatically sets this name, which can be changed.
Editors users don't have access to the name edition, so this name can be used in your views code.

To display the articles from the page with the name "news"
<ion:page id="news">

<ion:articles>
<ion:article:title tag="h3" />
</ion:articles>

</ion:page>
To display the pictures linked to the page with the name "home-slider"
125

<ion:page id="home-slider">

<ion:medias type="picture" size="960,240">

<img src="<ion:media:src />" data-id="<ion:media:index />" />

</ion:medias>

</ion:page
page's children tags
All these children tag can be used under the <ion:page /> tag, written in "short" or "long" mode :
<!-- Short mode -->
<ion:page:title />

<!-- Long mode -->


<ion:page>
<ion:title />
126

</ion:page>

Tag

Usage

<ion:page:title />

Page title

<ion:page:subtitle /> Page's subtitle


<ion:page:url />

URL to the page

<ion:page:date />

Date of the page. Accept the "format" attribute.


See : Shared attributes for more info on formatting dates

<ion:page:medias />

Media linked to the page.


See : Media Tags for more info on how to display media linked to one parent.

<ion:page:articles />

Articles linked to the page.


See : Articles Tags

<ion:page:next />

Returns the next page

<ion:page:prev />

Returns the previous page


127

next / previousTop of Page


These page's sub-tag returns the next and previous page.
Display the next page, if one exists :
<ion:page:next>

<ion:title tag="h2 />


<ion:subtitle tag="span" class="small" />

<a href="<ion:url /><ion:lang key="next_page" /></a>

</ion:page:next>

Articles
articlesTop of Page
Iterator tags for articles.
Tag : <ion:articles />
128

Display articles from current page


<ion:page>

<!-- Articles iterator -->


<ion:articles>

<!-- Article -->


<ion:article>

<!-- Articles data -->


<ion:title tag="h4" />

<ion:date format="medium" tag="span" />

<!-- The first paragraph -->


<ion:content paragraph="1" />

</ion:article>
</ion:articles>
129

</ion:page>
Display articles from page named "news"
<ion:page id="news">

<ion:articles >

<ion:title tag="h3" />

<ion:content />

</ion:articles>

</ion:page>
Display articles from a given type
Each article can have an optional "type".
Types are defined in Content > Articles Types
To set the type of one article :
130

Edit the parent page


Set the wished type in the article list

Types are linked to articles for a given page:


One article can have the type "side-box" on the home page and the same article can have no type in the
page "news".
Tag attributes
All these <ion:articles /> tag attribute are optional.

Attribute Values

type

Type name.
Only returns articles from the given type.
Important : type="" will return the articles which doesn't
have a type.

limit

Number of article to return.


Not compatible with use of pagination.

Example
<ion:articles type="side-box">
...
</ion:articles>
<ion:articles limit="3">
...
</ion:articles>

"SQL order by" clause


order_by Example : 'date DESC' will order the articles by date
descending

<ion:articles order_by="date ASC">


...
</ion:articles>

filter

<ion:articles
filter="author='admin'">

Logical filtering of the articles on their base data.


Base data are : title, type, author

131

...
</ion:articles>
Children tags

Tag

Returns

Example

The number of articles in this page is :


<ion:count /> Number af articles in this collection <ion:page:articles:count />
<ion:article /> Article detail

articleTop of Page
Tag : <ion:article />
Can be used in 2 contexts :

Inside the <ion:articles /> parent tag.


In this case, the tag is used to display data from the current looped article
Standalone, but only in one "Single Article" page view

Inside its parent tag


This is the common way to display article's data.
1<ion:articles>
132

2
<ion:article:title />
3
<a href="<ion:article:url />">Read the complete article</a>
4
</ion:articles>
5
In one "Single Article" view
The "Single Article" view of one page is used to display one standalone article.
One good example of this behaviour is the blog :

The main page will display the list of posts. Example URL : http://domain.tld/blog_page_url/
The article's detail page will display one post. Example of URL :
http://domain.tld/blog_page_url/blog_article_url

In this case, the page called "blog" will have 2 views defined on the backend :

In Attributes > Views : The blog page view called "Blog"


In Attributes > Single Article View : The page article's detail view, called "Blog : One post"

133

In this case, both views are pages views, declared with the type "Page" in Settings > Themes
Example :
This code will display the current URL asked article in your "Single Article view" :
134

<!-The URL called contains the article's URL : <a href="http://domain.tld/blog_page_url/"


target="_blank">http://domain.tld/blog_page_url/</a>blog_article_url
In this case, <ion:article /> will display the current asked article
-->
<ion:article>
<ion:title tag="h3" />
<ion:date format="d.m.Y" tag="span" class="post-date" />
<ion:content />
</ion:article>
Render each article with its own view
This method is not recommended any more, because it adds a lot of article views which can be confusing
for the editor.
But in some cases, it can be useful.
To add and use articles dedicated views :

Set the articles usable views in Settings > Theme...


Edit one page and set the view to the wished article in the articles list
135

User the attribute render="true" so the <ion:article /> tag uses the defined view.

In your page view :


1<ion:page:articles>
<ion:article render="true" />
</ion:page:articles>
Article children tagsTop of Page
These tags are <ion:article/> children tags.

Tag

Returns

Example
<ion:articles>
<ion:article:index />
</ion:articles>

<ion:index />

the current index of the article in one article's


list.
Start at 1.

<!-- Display one "hr" each 3 articles -->


<ion:articles>
<ion:article:index
expression="%3==0" >
<hr />
</ion:article:index>
</ion:articles>
136

Returns the article's date :

<ion:date />

Creation date or
Logical date if set in Ionize

See : Shared attributes : Date formatting


attribute

<ion:articles>
<ion:article:date format="d.m.Y" />
</ion:articles>

Returns the article's text content.


Attributes :
<ion:content />

auto_link : Set to 'false', it disables the


content anchors and email auto linking.

<ion:articles>
<ion:article:content
auto_link="false" />
</ion:articles>

See : Shared attributes : String processing


attributes

<ion:url />

Returns the URL to the article, in the context


of it's main parent page.

<ion:categories:list
Displays the categories list to which this
/>
article is linked to.
Attributes :

<ion:articles>
<ion:article:url />
</ion:articles>
<ion:articles>
<ion:article:categories:list link="true"
separator=" / " />
</ion:articles>

link : Adds the link to each category if set


137

to true

separator : HTML encoded separator char

Displays data about the article's last editor.

<ion:article:writer /
See : Common data tags for all children of
>
this tag.

<ion:article:writer>
<!-- Firstname & Lastname -->
<ion:firstname /> <ion:lastname />
...
</ion:article:writer>

Returns the next article in the tree.


<ion:article:next /> Children tags of this tag are the same than
for the <ion:article /> tag.

<ion:article:next >
<ion:title tag="span" class="link" />
</ion:article:next>

Same than <ion:article:next />, but returns


<ion:article:prev />
the previous article.

<ion:article:previous >
<ion:title tag="span" class="link" />
</ion:article:previous>

Medias
mediasTop of Page
Iterator tags for medias.
Tag : <ion:medias />
Display medias from articles
138

<!-- Iterates through articles of the current page -->


<ion:page:articles>

<ion:medias type="picture" size="400,300">

<img src="<ion:media:src />" alt="<ion:alt />" />

</ion:medias>

</ion:page:articles>

medias attributes

Attribute Optional Values

type

no

extension yes

picture, video, music, file


The file extension to filter on.
Example : extension="pdf"

Example
<ion:medias type="video">
...
</ion:medias />
<ion:medias type="file"
extension="pdf">
139

...
</ion:medias>
<ion:medias type="music"
limit="3">
...
</ion:medias>

yes

Integer.
Limits the displayed media to the given number.

yes

Start and stop index, coma separated.


<ion:medias type="picture"
Start at 1.
range="2,3" >
Example : range="2,4" displays the medias from the second ... display the
to the 4th one.
</ion:medias>

size

yes

<ion:medias type="picture"
size="300" >
<img
src="<ion:media:src />" />
</ion:medias>

method

yes

limit

range

Only availbable with the type="picture" attribute


Returns resized pictures.

Only availbable with type="picture"


Resize the picture using the given method :

adaptive : the resized picture will fill the given size,


even the original height or width doesn't fit the
proportions of the asked size,
square : will produce one square picture
border : will add one coloured border on the resized
missing side
140

width : forces the width of the resized picture


height : forces the height of the resized picture

If not set and size is set, the default behaviour will resize
the picture by using the first size argument use it on the
wider side of the picture.

mediaTop of Page
Tag : <ion:media />
Used to display data from one media of the <ion:medias /> collection.
media attributes
As the <ion:medias /> tag, the <ion:media /> tag can set the size of pictures.

Attribute Optional Values


Only availbable with the type="picture" attribute
size

yes

method

yes

Returns resized pictures.

Example
<ion:medias type="picture" >
<img src="<ion:media:src
size='300' />" />
</ion:medias>

Only availbable with type="picture"

141

Resize the picture using the given method :

adaptive : the resized picture will fill the given size,


even the original height or width doesn't fit the
proportions of the asked size,
square : will produce one square picture
border : will add one coloured border on the resized
missing side
width : forces the width of the resized picture
height : forces the height of the resized picture

If not set and size is set, the default behaviour will


resize the picture by using the first size argument use it
on the wider side of the picture.

media children tags

Tag
<ion:src />

Returns

Example

The complete URL to the media.


Example :
http://domain.tld/files/pictures/portfolio/my_work.jpg

<ion:medias
size="300" />
<ion:media:src />
</ion:medias>

If one size is asked with the size attribute of the parent


<ion:medias /> tag, this URL will be the one of the resized
version of the picture.
142

Example :
http://domain.tld/files/.thumbs/pictures/300/my_work.
jpg

<ion:path />

The complete relative path to the media, including the folder set in
Settings > Advanced Settings > Media base folder and the file
<ion:media:path />
name.
Example : files/pictures/portfolio/my_work.jpg

<ion:base_path/ Relative path to the folder of the media, with trailing slash.
>
Example : files/pictures/portfolio/

<ion:media:base_path
/>

<ion:file_name / File name of the media.


>
Example : my_work.jpg

<ion:media:file_name /
>

<ion:alt />

Media alternative text

<ion:media:alt />

<ion:title />

Title of the media

<ion:media:title />

<ion:description/
Description
>

<ion:media:description
/>

<ion:copyright /
>

Copyright

<ion:media:copyright /
>

<ion:link />

Link of this media to one external / internal content.

<ion:media:link />

<ion:date />

Logical date of the media. If not set, no date will be returned.

<ion:media:date
format="d.m.Y" />

<ion:extension / File extension of the media

<ion:media:extension
143

is="jpg">
... displayed if file is
.jpg
</ion:media:extension
>

>

<ion:mime />

Mime of the file

<ion:media:mime />

Resizing picturesTop of Page


Getting resized pictures from the <ion:medias /> tag is done through 2 attributes : size and method.
Let's discover what they return depending on the used method.
Just size, no method
The pictures will be resized based on their wider size : The wider side of the returned pictures will have the
asked size.
<ion:medias type="picture" size="150" >
<img src="<ion:media:src />" />
</ion:medias>

Method "height"
144

Sets the height as "master" size of the resized picture. the returned pictures will all have the asked height.
<ion:medias type="picture" size="150" method="height" >
<img src="<ion:media:src />" />
</ion:medias>

Method "width"
Sets the width as "master" size of the resized picture. The returned pictures will all have the asked width.
<ion:medias type="picture" size="150" method="width" >
<img src="<ion:media:src />" />
</ion:medias>

Method "border"
Resizes the pictures based on their wider side and adds one coloured border to complete one squared
rendering.
<ion:medias type="picture" size="150" method="border" color="#930031" >
<img src="<ion:media:src />" />
145

</ion:medias>

Method "adaptive"
Resizes the pictures to fill the asked size. No matter the picture orientation, each picture will fill the asked
size.
<ion:medias type="picture" size="180,140" method="adaptive" >
<img src="<ion:media:src />" />
</ion:medias>

Method "square"
Returns squared resized pictures.
The square crop of each resized picture can start :

At the top left,


at the middle (default),
At the right bottom.

The square crop preference is set on each picture in Ionize, in the "options" tab of the linked picture.
146

<ion:medias type="picture" size="200" method="square" >


<img src="<ion:media:src />" />
</ion:medias>

Media development tipsTop of Page


Refresh the pictures size at each page visit
Resize pictures are created one time, when the first user visits the page.
During development, it can be useful to refresh thumbnail at each page reload.
To do that, simply add the attribute refresh="true" to the medias tag.
1<ion:medias type="picture" size="200" method="square" refresh="true" >
2<img src="<ion:media:src />" />
3</ion:medias>
This is not recommended on production website because picture resizing needs server's CPU.
Pagination
147

paginationTop of Page
Pagination consist of 3 things :

Limit the number of display articles,


Display one menu, to navigate through pages,
Get the pages of paginated articles

Limiting the number of displayed articles can be done in 2 ways :


1. By setting the number of displayed article directly in Ionize,
2. By using one tag attribute to set the number of articles by page.
Set the number of articles through tag attribute
In this case, the number set to the pagination attribute must be the same for the <ion:articles /> tag and
for the <ion:pagination /> tag.
<!-- Articles -->
<ion:page:articles pagination="3">
<h3><ion:article:title/></h3>
<ion:article:content paragraph="1" />
</ion:page:articles>

<!-- Pagination navigation -->


148

<ion:page:articles:pagination pagination="3" />


Set the number of articles per page through Ionize
In the page options, set the value of Advanced Options > Articles / page.
"0" means no pagination.
Without the pagination attribute set, the <ion:article /> and <ion:article:pagination /> tags will try to get
the pagination value set for the page.
<!-- Articles -->
<ion:page:articles>
<h3><ion:article:title/></h3>
<ion:article:content paragraph="1" />
</ion:page:articles>

<!-- Pagination navigation -->


<ion:page:articles:pagination />

Categories
Categories of articles can be created with the Ionize menu Content > Categories or, when editing one
article, in the Options > Attributes > Categories panel, by clicking on Add one category.
149

Display all categories : <ion:categories />


By using the <ion:categories /> tag outside any parent <ion:page /> tag, it will iterate through all used
categories of the website.

1
2
3
4
5
6
7

<ion:categories tag="ul" active_class="my-active-class">


<li>
<a <ion:category:is_active> class="<ion:category:active_class />" </ion:category:is_active>
href="<ion:category:url />">
<ion:category:title /> : <ion:category:nb_articles /> articles
</a>
</li>
</ion:categories>

Display categories linked to articles of the current page


Purpose : Build on categories menu which links to the category filtering URL, but in the context of the
current page.
1<ion:page:categories tag="ul" active_class="my-active-class">
2<li>
150

3
4
5
6
7

<a <ion:category:is_active> class="<ion:category:active_class />" </ion:category:is_active>


href="<ion:category:url />">
<ion:category:title />
</a>
</li>
</ion:page:categories>

Display categories linked to one article : <ion:categories:list />


For each articles, display the categories list with one link to the category URL.
1<ion:page:articles>
2<ion:article>
3<ion:categories:list link="true" separator=", " />
4</ion:article>
5</ion:page:articles>
Children tags
151

Tag

<ion:list/>

Description

Example

<ion:page:articles>
Categories of this article, displayed in list :
Returns the current linked categories
<ion:article:categories:list link="true" separator="
in list.
&bull; "/>
</ion:page:articles>
<ion:page:articles>
Number of categories this article is linked to :
<ion:article:categories:count />
</ion:page:articles>

<ion:count/> Returns the number of categories


Number of website's used categories :
<ion:categories:count />
Number of categories used by the current page :
<ion:page:categories:count />

categoryTop of Page
Tag : <ion:category />
Displays data from one category.
Used inside one <ion:categories /> parent tag or standalone to get the current browsed category.
152

Display the current category


1<ion:category:current:title expression="!=''">
2<ion:category:current:title/>
3</ion:category:current:title>
Children tags

Tag

Description

<ion:title />

Returns the category title

Example
<ion:category:title />

Returns the number of articles linked to this category.


<ion:nb_articles /> The returned value depends on the context of usage of the <ion:category:nb_articles />
tag.
<ion:category:is_active>
<ion:is_active />

Displays the content between the open and closing tag if


the current category is currently been displayed.

<ion:category:active_class />
</ion:category:is_active>

<ion:active_class/> Returns "active" by default.


<ion:url />

URL to the category.


This is a link to the special URL which displays categories.
153

This URL is build depending of the context of the category.


<ion:current

Get the current category if the URL is one category filtering


URL

Archives
archivesTop of Page
Archives works like categories, except that they are based on the date of each article.
Archives are only displayed on page which have articles linked to, and consider the current or the asked
page.
To display archives from all website :
1<ion:archives month="true" tag="ul">
2<li>
3<a class="<ion:archive:active_class />" href="<ion:archive:url />">
4<ion:archive:period /> - (<ion:archive:nb_articles /> articles)
5</a>
6</li>
154

7</ion:archives>
User
These tags display data about the current connected user.
The <ion:user /> tag can also be used with the <ion:form /> tag to create login / register / profile edition
forms.
Usage
1 <ion:user:logged is="true">
2 <h2>User <ion:user:name /> logged
in</h2>
3
<!-- User -->
4
<p>
5
First name : <ion:user:firstname />
6
Last name : <ion:user:lastname />
7
Email : <ion:user:email />
8
155

9 Birthdate : <ion:user:birthdate />


10Gender : <ion:user:gender />
11</p>
12<!-- Group information -->
13<p>
14Group : <ion:user:group:name />
15Group Title : <ion:user:group:title />
16Group Level : <ion:user:group:level />
17</p>
18</ion:user:logged>
19<!-- No user is logged in -->
20<ion:user:logged is="false">
21<h2>User not logged in</h2>
</ion:user:logged>
156

User children tags

Tag

Returns

<ion:logged />

Test tag on the "logged in" status of the user.


If logged in, displays the data between the open and
closing tag.

Example
<ion:user:logged is="true">
... display this ...
</ion:user:logged>

<ion:firstname /> User's first name

<ion:user:firstname />

<ion:lastname />

User's lastname

<ion:user:lastname />

<ion:name />

User's screen name (Choosen displayed name) or


firtname + lastname if the screen name isn't set.

<ion:user:name />

<ion:email />

User's email address

<ion:user:email />

<ion:gender

User's gender :
1 : Male
2 : Female

<ion:user:gender />

<ion:birthdate

User's birthdate

<ion:user:birthdate
format="d.m.Y" />

<ion:group />

Nothing.
Enclosing tag for the group sub tags.

<ion:group:name /
Name of the user's group
>

<ion:user:group:name />

157

<ion:group:level /
Level of the user's group
>

<ion:user:group:level />

<ion:group:title /> Title of the user's group

<ion:user:group:title
tag="h3" />

Form
Quick articles links
Declare the form - Create the form's view - Process the form - Send emails after form processing
The <ion:form /> tag manages forms.
With simple children tags, this tag :

Display the form


Display form validation messages (errors on fields, success)
Sends data to one form processing custom library

We will create one example form to illustrate this tag usage.


To create this form, we will need to:
1. Declare and configure the form in the theme "forms" config file.
Location of the config file : /themes/your_theme/config/forms.php
2. Create one view containing the form (it can be a page view which displays other data from website)
Location of the view: /themes/your_theme/views/contact.php
158

3. Create your own Tagmanager library which will process the form data.
Location of the library: /themes/your_theme/libraries/Tagmanager/Contact.php
Form children tags
The <ion:form /> tag is a little bit special : All its children tags must be used in the context of the wished
form.
In other words, if one form called "my_form" in declared in the forms.php config file, all children tags will
be used with the tag <ion:form:my_form /> as parent.
In this table, we consider one form called "my_form".

Tag

Returns

<ion:form:my_form:validation />

Nothing.
Parent tag for the
validation children
tags

Global
<ion:form:my_form:validation:success/>
validation
success
message.
Can be used in
conditional
mode.

Example

<!-- Displays the validation success message -->


<ion:form:my_form:validation:success tag="p"
class="green" />
<!-- Custom message by testing the result -->
<ion:form:my_form:validation:success
is="true">
... this will be displayed if the validation
159

succeed
</ion:form:my_form:validation:success>

<ion:form:my_form:validation:error/>

<!-- Displays the validation error message -->


<ion:form:my_form:validation:error tag="p"
Global validation
class="green" />
error message.
<!-- Custom message by testing the result -->
Can be used in
<ion:form:my_form:validation:error is="true">
conditional mode.
... this will be displayed if the validation fails
</ion:form:my_form:validation:error>

<ion:form:my_form:validation:result/>

Nothing.
<ion:form:my_form:validation:result is="true">
Conditional tag to
... displayed if validation was done
test validation
</ion:form:my_form:validation:result>
result.

<ion:form:my_form:posted />

Conditional tag to <ion:form:my_form:posted is="false">


test if the form
Please fill in our form...
was posted.
<ion:form:my_form:posted>

<ion:form:my_form:field />

Parent field tag.


Used to refill the
form fields after
unsuccessful
validation

<ion:form:my_form:error />

<input type="text" name="firstname"


value="<ion:form:my_form:field:firstname
/>" />

Parent tag to
<!-- Display of one error message under the
display one given input if the validation failed -->
validation error
<input type="text" name="firstname"
value="<ion:form:my_form:field:firstname
160

/>" />
<ion:form:my_form:error:firstname tag="p"
class="input-error" />

Declare the formTop of Page


Create the file /themes/your_theme/config/forms.php with this content :
1 <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
2 /*
3 |-------------------------------------------------------------------------4 | Theme Forms configuration
5 |-------------------------------------------------------------------------6 |
7 | This forms config array will be merged with /application/config/forms.php
8 | You can overwrite standard forms definition by creating your own deifnition
9 | for the form you wish to overwrite.
10|
161

11*/
12$config['forms'] = array
13(
14// Contact form
15'contact' => array
16(
17// The method which will process the form
18// The function name has no importance, it must only be in the declared Tagmanager class
19// and be "public static"
20'process' => 'TagManager_Contact::process_data',
21// Redirection after process. Can be 'home' or 'referer' for the $_SERVER['HTTP_REFERER'] value.
22// If not set, doesn't redirect
23'redirect' => 'referer',
24// Messages Language index, as set in language/xx/form_lang.php
162

25'messages' => array(


26'success' => 'form_message_success',
27'error' => 'form_message_error',
28),
29// Form definition: fields and rules
30'fields' => array
31(
32'name' => array
33(
34// CI validation rules
35'rules' => 'trim|required|min_length[3]|xss_clean',
36// Label translated index, as set in language/xx/form_lang.php
37// Will be used to display the label name in error messages
38'label' => 'form_label_name',
163

39),
40'company' => array(
41'rules' => 'trim|required|xss_clean',
42'label' => 'form_myform_label_company',
43),
44'email' => array(
45'rules' => 'trim|required|valid_email|xss_clean',
46'label' => 'form_label_email',
47),
48// Example of radio inputs : "You heard about our company on..."
49'heard' => array(
50// Can be 'radio', 'checkbox', 'select' or not set for input and textarea
51'type' => 'radio',
52'rules' => 'required',
164

53
54
55'label' => 'form_label_heard_on',
56)
57)
58),
59);
60
61
Create the form's viewTop of Page
In the forms.php config file, we declared one form called "contact".
Create the file /themes/your_theme/views/contact.php with this content :
1 <h2>Contact form</h2>
2 <!-165

3 Success message
4 Displayed if the form was successfully validated
5 -->
6 <ion:form:contact:validation:success tag="p" class="green" />
7 <!-8 Error message
9 Displayed if the form doesn't pass the validation
10the 'form_message_error' key is located in : themes/your_theme/language/xx/tags_lang.php
11-->
12<ion:form:contact:validation:error is="true" >
13<span class="red">
14Error : Some form data are missing or seem to be incorrect.
15</span>
16</ion:form:contact:validation:error>
166

17<!-18Form has no action because the same page will process the data.
19POST data are catched by the global Tagmanager and processed by the Tagmanager's library method
'process_data'
20
defined in : /themes/your_theme/libraries/Tagmanager/Contact.php
21
as declared in the form config file : /themes/your_theme/config/forms.php
22
-->
23
<form method="post" action="">
24
<!-25
The form name must be set so the tags identify it.
26
Same name than the one declared in forms.php
27
-->
28
<input type="hidden" name="form" value="contact" />
29
<!-30
Input : Name
167

31-->
32<label for="name">Name</label>
33<!-- Fills again the user input in case of failed validation -->
34<input type="text" id="name" name="name" value="<ion:form:contact:field:name />"/>
35<!-- Displays the error linked to this input in the validation fails -->
36<ion:form:contact:error:name tag="p" class="input-error" />
37<!-38Input : Company
39-->
40<label for="company">Company</label>
41<input type="text" id="company" name="company" value="<ion:form:contact:field:company />"/>
42<ion:form:contact:error:company tag="p" class="input-error" />
43<!-44Input : Email
168

45-->
46<label for="email">
47Email
48<span class="note">The form data will be send to this email address.</span>
49</label>
50<input type="text" id="email" name="email" value="<ion:form:contact:field:email />"/>
51<ion:form:contact:error:email tag="p" class="input-error" />
52<!-53Input : You heard about our company...
54-->
55<label>You heard about our company on...</label>
56<div>
57<!-- Fills again the user input in case of failed validation -->
58<input type="radio" name="heard" id="heard-contact-facebook" value="Facebook" class="left"
<ion:form:contact:radio:heard value="Facebook" /> />
169

59<label for="heard-contact-facebook">
60<ion:lang key="form_label_heard_facebook" />
61</label>
62<input type="radio" name="heard" id="heard-contact-friend" value="one very good friend" class="clear
left" <ion:form:contact:radio:heard value="one very good friend" default="true" /> />
63
<label for="heard-contact-friend" >
64
<ion:lang key="form_label_heard_friend" />
65
</label>
66
<input type="radio" name="heard" id="heard-contact-website" value="another website" class="clear left"
67<ion:form:contact:radio:heard value="another website" /> />
68<label for="heard-contact-website" >
69<ion:lang key="form_label_heard_website" />
70</label>
71<ion:form:contact:error:heard tag="p" class="error" />
72</div>
170

73
74
75
76
<!-77
Submit button
78
-->
79
<input type="submit" value="Send the data" />
80
</form>
81
82
83

Process the formTop of Page

171

In the file /themes/your_theme/config/forms.php, we declare that the form wille be processed by the
method "process_data" of the class "TagManager_Contact".
Create the file /themes/your_theme/libraries/Tagmanager/Contact.php and write the following code :
1 <?php
2 /**
3 * Contact Form TagManager
4 *
5 */
6 class TagManager_Contact extends TagManager
7 {
8 /**
9 * Processes the form POST data.
10*
11* @param FTL_Binding
12*
172

13* @return void


14*
15*/
16public static function process_data(FTL_Binding $tag)
17{
18// Name of the form : Must be send to identify the form.
19$form_name = self::$ci->input->post('form');
20// Because Form are processed before any tag rendering, we have to run the validation
21if (TagManager_Form::validate($form_name))
22{
23// Posted data
24// To see the posted array, uncomment trace($posted)
25// If you prefer to see these data through one log file,
26// uncomment log_message(...) and be sure /application/config/config.php contains :
173

27// $config['log_threshold'] = 1;
28// The log files are located in : /application/logs/log-YYYY-MM-DD.php
29// We prefer to log our 'dev' data as 'error' to not see the all CodeIgniter 'debug' messages.
30$posted = self::$ci->input->post();
31// trace($posted);
32// log_message('error', print_r($posted, TRUE));
33// ... Here ... you do what you want with the data ...
34// Add one custom Success message
35// Get the messages key defined in : /themes/your_theme/config/forms.php
36// You can also set directly one lang translated key
37$message = TagManager_Form::get_form_message('success');
38TagManager_Form::set_additional_success($form_name, $message);
39// Alternative : Set the message by using directly one lang translated key :
40// TagManager_Form::set_additional_success($form_name, lang('form_message_success'));
174

41// Use of the 'redirect' option of the form config.


42// If no redirect after processing, the form data can be send again if the user refreshes the page
43// To avoid that, we use the redirection directive as set in the config file:
44// /themes/your_theme/config/forms.php
45$redirect = TagManager_Form::get_form_redirect();
46if ($redirect !== FALSE) redirect($redirect);
47}
48/*
49// Normally, nothing should be done here, because the validation process refill the form
50// and doesn't redirect, so the user's filled in data can be used to fill the form again.
51// Remember : If you redirect here, the form refill will not be done, as the data are lost
52// (no access to the posted data anymore after redirection)
53else
54{
175

55
56
// ... Do something here ...
57
}
58
*/
59
}
60
}
61

Send emails after form processingTop of Page


If you want to send one email after form processing, you will also need to:

Create one email view.


Location is up to you, but as convention, we put the emails views in the folder : themes/your_theme/mail/
Declare the email in /themes/your_theme/config/forms.php

Using this method is optional :


You can also directly send the emails you want in the process_data() method.

176

Declare the email


Edit the file /themes/your_theme/config/forms.php and add the key "emails" as following:
1 $config['forms'] = array
2 (
3 // Contact form
4 'contact' => array
5 (
6 'process' => 'TagManager_Contact::process_data',
7 'redirect' => 'referer',
8 'messages' => array(
9 'success' => 'form_message_success',
10'error' => 'form_message_error',
11),
12'emails' => array
13(
177

14array
15(
16// Send the mail to the address filled in in the 'email' input of the form
17// Values can be :
18// - One plain email address
19// - 'form' to send it to the email of the form data
20// - 'website' to send it to the Email set in Ionize under Settings > Advanced > Email > Website
21'email' => 'form',
22// Subject : Translation item index of the subject
23'subject' => 'mail_contact_subject',
24// Used view : Located in /themes/your_theme/mail/contact.php
25'view' => 'mail/contact',
26),
27),
178

28'fields' => array


29(
30'name' => array
31(
32'rules' => 'trim|required|min_length[3]|xss_clean',
33'label' => 'form_label_name',
34),
35'company' => array(
36'rules' => 'trim|required|xss_clean',
37'label' => 'form_myform_label_company',
38),
39'email' => array(
40'rules' => 'trim|required|valid_email|xss_clean',
41'label' => 'form_label_email',
179

42
43
44),
45'heard' => array(
46'type' => 'radio',
47'rules' => 'required',
48'label' => 'form_label_heard_on',
49)
50)
51),
52);
53
54
Create the email view
180

This view will be used as template for the email.


Create the file themes/your_theme/mail/contact.php :
1 <html xmlns="http://www.w3.org/1999/xhtml">
2 <head>
3 <title><ion:data:subject /></title>
4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
5 <meta http-equiv="Content-Language" content="<ion:current_lang />" />
6 </head>
7 <body>
8 <table border="0" width="100%" cellpadding="0" cellspacing="0">
9 <tr>
10<td class="bg_fade">
11<table border="0" width="880">
12<tr>
13<td>
181

14<!-15Dear %s,
16-->
17<h1><ion:data:lang key="mail_contact_dear" swap="data::name" /></h1>
18<!-19Message
20Important : to swap text in the translated string, the 'lang' tag must be called
21with the 'data' tag as parent.
22-->
23<p><ion:data:lang key="mail_contact_message" swap="global::site_title, data::heard, data::email"
autolink="false"/></p>
24
<p><ion:lang key="mail_contact_message2" /></p>
25
<p>
26
<ion:lang key="form_label_name"/> : <b><ion:data:name /></b>,
27
<ion:lang key="form_label_company"/> : <b><ion:data:company /></b>
182

28<ion:lang key="form_label_email"/> : <b><ion:data:email /></b>


29</p>
30<p>
31<ion:lang key="mail_contact_thanks" swap="global::site_title" />
32</p>
33</td>
34</tr>
35</table>
36</td>
37</tr>
38</table>
39</body>
40</html>
41
183

42

Modify the TagManager_Contact process() method


Edit the file /themes/your_theme/libraries/Tagmanager/Contact.php and add the call to
TagManager_Email::send_form_emails() :
1 <?php
2 /**
3 * Contact Form TagManager
4 *
5 */
6 class TagManager_Contact extends TagManager
7 {
8 /**
9 * Processes the form POST data.
184

10*
11* @param FTL_Binding
12*
13* @return void
14*
15*/
16public static function process_data(FTL_Binding $tag)
17{
18$form_name = self::$ci->input->post('form');
19if (TagManager_Form::validate($form_name))
20{
21$posted = self::$ci->input->post();
22// ... Here ... you do what you want with the data ...
23// Send the posted data to the Email library and send the Email
185

24
// as defined in /themes/your_theme/config/forms.php
25
TagManager_Email::send_form_emails($tag, $form_name, $posted);
26
$message = TagManager_Form::get_form_message('success');
27
TagManager_Form::set_additional_success($form_name, $message);
28
$redirect = TagManager_Form::get_form_redirect();
29
if ($redirect !== FALSE)
30
redirect($redirect);
31
}
32
}
33
}

Explanation
To send the form declared emails, we called TagManager_Email::send_form_emails($tag,
$form_name, $posted);

186

This method receives the form name ($form_name) and the posted data ($posted) and send each email
as declared in the "emails" key of the forms.php config file.
In the view, the form posted data are available with the tag <ion:data />
Email view and language translated terms
The email view displays translated sentences, and "swaps" inside them the data received by the form.
For example :

<h1><ion:data:lang key="mail_contact_dear" swap="data::name"


/></h1>

... retrieves the translation term key "mail_contact_dear" and replaces %s by the field "name" filled up
in the form.
The lang file /themes/your_theme/languages/xx/form_lang.php contains :
1<?php
2// Translated strings used in the contact form sent email
3$lang['mail_contact_subject'] = 'Thanks for your interest on %s';
4$lang['mail_contact_dear'] = 'Dear %s,';
5$lang['mail_contact_message'] = 'You heard about <b>%s</b> through <b>%s</b> and we thank you very
much for your interest. Your email is %s.';
6
187

7$lang['mail_contact_message2'] = 'Here are the data you just send us:';


8$lang['mail_contact_thanks'] = 'The whole team of <b>%s</b> thanks you.';
It is possible to get translated sentences containing more than one data :

<ion:data:lang key="mail_contact_message" swap="global::site_title, data::heard, data::email"


autolink="false"/>

In this case, we see that we swapped 3 data in the string "mail_contact_message".


We also said to the tag it must not create links with emails.
Extend Field
extend tagTop of Page
Tag : <ion:extend />
This tag is to be used as children of the tags : <ion:page />, <ion:article /> or <ion:media />
It must be used with its Extend Field children tag.
If you have defined one Extend Field which has the name "color", the tag <ion:extend:color /> will give
you access to this field.
Extend children tags
In this table, we consider one Extend Field called "my-field".
188

Tag

Returns

<ion:extend:my-field />

Nothing.
Parent tag for the asked Extend field

Example

<ion:extend:my-field>
<ion:label />
</ion:extend:my-field>

<ion:extend:myfield:label />

Label as defined in the definition of the field

<ion:extend:myfield:value />

Value of the Extend Field in the context of its parent.


Returns the default value if set in the field definition.

<ion:extend:myfield:options />

<ion:extend:my-field>
<ion:options>
Available options for Extend Fields with multiple choices
<ion:value/> :
(Radio, Checkboxes, Select).
<ion:label/>,
</ion:options>
</ion:extend:my-field>

<ion:extend:myfield:values />

<ion:extend:my-field>
<ion:values>
Sleected values for Extend Fields with multiple possible
<ion:value/> :
values (Radio, Checkboxes, Select)
<ion:label/>,
</ion:values>
</ion:extend:my-field>

<ion:extend:my-field>
<ion:value />
</ion:extend:my-field>

Content Element
189

element tagTop of Page


Tag : <ion:element />
This tag is to be used as children of the tags : <ion:page />, <ion:article /> or <ion:media />
It must be used with its element definition children tag.
If you have defined one Element which has the name "concert", the tag <ion:extend:concert /> will give
you access to this element.
Parents (page, article) can have several instances of one Content Element linked to them.
Element children tags
In this table, we consider one Content Element called "my-element", which has one field called "myfield".

Tag

Returns

<ion:element:my-element />

Nothing.
Parent tag for the element.

Example

<ion:element:my-element>
<ion:title tag="h3" />
</ion:element:my-element>

<ion:element:myelement:title />

Title of the element, as defined in the


definition of the Content Element

<ion:element:myelement:items />

Instances created by the editor for this


<ion:element:my-element>
Content Element in the context of its parent
<ion:items>
element.
...
190

</ion:items>
</ion:element:my-element>

<ion:element:myelement:items:my-field />

<ion:element:myelement:items:index />

<ion:element:myelement:items:my-field:label />

Field data for the current Content Element


instance

<ion:element:my-element>
<ion:items>
<ion:my-field>
...
</ion:my-field>
</ion:items>
</ion:element:my-element>

Index of the item in the list.


Starts at 1.

<ion:element:my-element>
<ion:items>
<ion:index is="1">
... display this if the
item is the first one
</ion:index>
</ion:items>
</ion:element:my-element>

Label of the field as defined in the Content


Element

<ion:element:my-element>
<ion:items>
<ion:my-field:label />
</ion:items>
</ion:element:my-element>

<ion:element:myValue of the field


element:items:my-field:value />

<ion:element:my-element>
<ion:items>
<ion:my-field:value />
</ion:items>
191

</ion:element:my-element>
<ion:element:my-element>
<ion:items>
<ion:my-field>
<ion:options>
<ion:value/> :
<ion:label/>
</ion:options>
</ion:my-field>
</ion:items>
</ion:element:my-element>

<ion:element:myelement:items:myfield:options />

Available options for one field with multiple


choices (Radio, Checkboxes, Select).

<ion:element:myelement:items:myfield:values />

<ion:element:my-element>
<ion:items>
<ion:my-field>
<ion:values>
Selected values for one field with multiple
<ion:value/> :
possible values (Radio, Checkboxes, Select) <ion:label/>
</ion:values>
</ion:my-field>
</ion:items>
</ion:element:my-element>

Conditions with tags


See : Shared attributes > Test and Conditional attributes
192

Introduction
If you wish to add some data which aren't provided by Ionize, like for example one field "color" on each
article or one more complex data called "concerts" with several fields like a date, a place, one map...
Extending the Ionize data model is the solution.
They are 2 ways to extend the Ionize data model :

Create "Extend Fields"


Create "Content Elements"

Extend Fields
"Extend Fields" extends the data model by adding fields to page, article and media.
Extend Fields creation (definition) is available in the menu Content > Extend fields
When one Extend Field is created for pages, articles or media, it will be available for each page, article or
media created or already existing.
Content Elements
"Content Elements" is a complex structure. One Content Element has a name and contains one or more
fields.
Content Elements creation (definition) is available in the menu Content > Content Elements
Once created, one Content Element will be available for each page, article.
193

The editor will be able to add several instances of each Content Element to one parent page or article.
For example, if you plan to build one "concerts" page, you have 2 choices :
1. Consider than each concert is one article and use the existing article's fields,
2. Create one Content Element called "concert" containing the fields "date", "city", "place", "information"
and then let the editor link as much "concert" as he needs to the page "concerts"
Extend Fields
Create one Extend FieldTop of Page
To create one Content Field:

In Ionize, go to Content > Extend Fields


Click on the button "New Extend Field"

194

Setting

Description

Parent

Parent type for wich this Extend Field will be available

195

Label

Displayed label of the extend field

Name

Name of the extended field.


Must be lowercase and unique

Type

Kind of data.
Input : A simple text input
Textarea : A simple textarea
Textarea + Editor : The textarea will be displayed with a Wysiwyg texteditor
Checkbox, Radio, Select : List of values

Can be translated When activated, this extended field can have values for each installed language

Values

Need to be used when checkbox, radio or select type is chosen.


Format : <value>:<label>
Example : 1:Red
Will be displayed :

Default value

Used value when no value is set by the Editor.


In case of checkbox, radio or select, the value must be used.

Description

Help displayed on the backend label.

196

Set the Extend Field valueTop of Page


Once created, the extended field will appear in its context panel.
An article extended field will appear on the article edition panel.

Display Extend Fields in viewsTop of Page


Extend Fields are displayed in views through a dedicated tag : <ion:extend />
This tag must be used in the context of the parent type for which the Extend Field is defined.
In other words, if you have defined one extend field which has the name "color", the tag <ion:extend:color
/> will give you access to this field.
In case of radio, checkbox or select, the returned value will be the key.
197

1 <!-- Current page -->


2 <ion:page>
3 <!-- Articles linked to the current page -->
4 <ion:articles>
5 <ion:article>
6 <!-- Display one simple Extend Field (input or textarea type) -->
7 <ion:extend:description>
8 <!-- Label of the Extend Field -->
9 <ion:label/>
10<!-- Value of the Extend Field -->
11<ion:value />
12</ion:extend:description>
13<!-- Display one checkbox, radio or select Extend Field -->
14<ion:extend:difficulty>
198

15<!-- Display all the available options -->


16<p>
17Available options:
18<ion:options>
19<ion:value/> : <ion:label/>
20</ion:options>
21</p>
22<!-- Display the values selected by the editor -->
23<p>
24Values:
25<ion:values>
26<ion:value/> : <ion:label/>
27</ion:values>
28</p>
199

29
</ion:extend:difficulty>
30
</ion:article>
31
</ion:articles>
32
</ion:page>

Content Elements
Content Elements are multiple fields data containers.
Each parent (page or article) can have more than one instance of one Content Element.
Create one Content ElementTop of Page
To create one Content Element:

In Ionize, go to Content > Content Elements,


Click on the button "Create Element",
Set one name to your Content Element and click on save,
Once saved, you can change the title of the Content Element and add fields

200

201

Add fieldsTop of Page


One Content Element can have one or more fields.

202

Add one Content Element to one parentTop of Page


When editing one article or page :

Click on the button Add Element


Select one element in the list of available elements
Feed the element and save it

One element is now added to your page or article.


The list of elements is displayed in one new dedicated tab, which has the name of the Content Element (in
our example : "Concert")

203

204

Display Content Elements in viewsTop of Page


Extend Fields are displayed in views through a dedicated tag : <ion:element />
This tag must be used in the context of the parent type for which the Extend Field is defined.
In case of radio, checkbox or select, the returned value will be the key.
205

The following example displays one Content Element named "concert" and its items.
1 <!-- Display one Content Element from articles of the current page -->
2 <ion:page:articles:article>
3 <!-- Article title -->
4 <ion:title tag="h3" />
5 <!-- Display the Element which has the name "concert" -->
6 <ion:element:concert>
7 <!-- Title of the Element (as set in definition of the Content Element) -->
8 <ion:title tag="h3" />
9 <!-- Items (or "instances") of this element linked to the article -->
10<ion:items tag="ul">
11<!-- Field called "place" -->
12<li>
13Field : <ion:place:label />
206

14Type : <ion:place:type />


15Value : <ion:place:value />
16Default value : <ion:place:default_value />
17</li>
18<!-- Field called "private" (radiobox) -->
19<ion:private>
20<!-- Display the available options -->
21Options :
22<ion:options>
23&nbsp;<ion:value/> : <ion:label/>
24</ion:options>
25<!-- Display the user's selected options -->
26Selected values :
27<ion:values>
207

28
&nbsp;<ion:value/> : <ion:label/>
29
</ion:values>
30
</ion:private>
31
</ion:items>
32
</ion:element:concert>
33
</ion:page:articles:article>
For the complete doc on this tag, see Tag Reference : Element
User registration, login and profile
Quick articles links
Form declaration - Prepare the page - Login / Logout form - Registration form - Password back form
In this tutorial, we will build a complete user registration, login, and profile application.
What you will learn

Use the <ion:form /> and <ion:user /> tags to login / logout user on the frontend,
Create registration and profile editing forms
208

Create the "Get password back" feature.

Prerequisites

Know how to build views with Ionize : Build the website > Create one page : Views
Had a first look at the <ion:user /> tag : Tag reference > User
Had a first look at the <ion:form /> tag : Tag reference > Form

Form declarationTop of Page


In this tutorial, we will use 5 forms :

login : Logs the user in


logout : Logs the user out
register : Register one new account
profile : User's profile edition
password : Get the password back

As described in the chapter Tag Reference > Form, all forms need to be declared to be able to be used
through the <ion:form /> tag.
These forms are provided with Ionize and are declared in the configuration file : /config/forms.php
If you want to override these core forms, do not modify the /config/forms.php file. You can override one
form by declaring it in your own /themes/your_theme/config/forms.php configuration file.
Prepare the pageTop of Page
209

We will mainly work in one page view for this tutorial but of course, the tags we will use can be used in
each view you want (header partial view for example).
Create the file /themes/your_theme/views/page_user.php :
1 <!-2 We suppose you have one header, containing the website navigation menu
3 and other nice stuff.
4 -->
5 <ion:partial view="header" />
6 <!-- We will put our tutorial code after this comment -->
7 <h2>User login, logout, registration, profile</h2>
8 <!-9 One page has a footer
10-->
11<ion:partial view="footer" />
12
210

13
In Ionize, declare this view as "page" in Settings > Theme > Current Theme views list.
Finally, link this view to the page of your choice and navigate to it : It displays the title "User login,
logout, registration, profile"
In the next chapters of this tutorial, we will write the main code of each chapter, but not the whole view, to
make the code more clear.
If the view described looks strange to you, have a look at : Build the website > Create one page : Views
Login / Logout formTop of Page
In the file /themes/your_theme/views/page_user.php, add the following code :
1 <h2>Login</h2>
2 <!-3 Global Success message
4 Displayed if the user successfully logged in
5 -->
6 <ion:form:login:validation:success tag="p" class="green" />
211

7 <!-8 Global Error message


9 Validation wasn't OK or credentials aren't good
10-->
11<ion:form:login:validation:error tag="p" class="input-error" />
12<!-13Login Form
14Only displayed if the user isn't logged in
15-->
16<ion:user:logged is="false">
17<form method="post" action="">
18<!-- Name of the form : login -->
19<input type="hidden" name="form" value="login" />
20<!-- The email is used to log in the user -->
212

21<label for="email">Email</label>
22<input type="text" id="email" name="email" value="<ion:form:login:field:email />"/>
23<ion:form:login:error:email tag="p" class="input-error" />
24<label for="password">Password</label>
25<input type="password" id="password" name="password" />
26<ion:form:login:error:password tag="p" class="input-error" />
27<input type="submit" value="Login" />
28</form>
29</ion:user:logged>
30<!-31This is displayed if the user is already logged in .
32-->
33<ion:else>
34<p>User <ion:user:name tag="span" class="green" /> logged in.</p>
213

35
<p>First logout to be able to login.</p>
36
</ion:else>

Logout
Logout is easier than login.
Simply add the following code to your view to display one logout form.
You may style it so it look like one simple link if you wish.
1 <!-2 Logout
3 -->
4 <h2>Logout</h2>
5 <ion:user:logged is="true">
6 <form method="post" action="">
7 <input type="hidden" name="form" value="logout" />

214

8
9
<input type="submit" value="Logout" />
10
</form>
11
</ion:user:logged>
12
<ion:else>
13
<span class="red">User not logged in</span>
14
<p>First login to be able to logout.</p>
15
</ion:else>
16
17
Registration formTop of Page
When the user register, one email with one activation link will be sent to the user.
In the file /themes/your_theme/views/page_user.php, add the following code :
1 <!-215

2 Form validation SUCCESS


3 "validation:result" is a conditional tag.
4 If the attribute "is" is not set, the tag suppose we ask for is="true"
5 -->
6 <ion:form:register:validation:result>
7 <!-- Success validation message test -->
8 <ion:form:register:validation:success is="true">
9 <!-- Success message display -->
10<ion:form:register:validation:success tag="p" class="green"/>
11</ion:form:register:validation:success>
12</ion:form:register:validation:result>
13<!-14Form validation errors OR Form not validated (first display)
15-->
216

16<ion:form:register:validation:result is="false">
17<!-18Errors during validation ?
19Conditional tag : Expands if true
20-->
21<ion:form:register:validation:error is="true">
22<p class="red"><b>Errors during validation</b></p>
23</ion:form:register:validation:error>
24<!-25Only display the Registration Form if the user isn't looged in.
26-->
27<ion:user:logged is="false">
28<!-29Displayed if the form wasn't posted
217

30-->
31<ion:form:register:posted is="false">
32<p>Please fill in the registration form to create one account.</p>
33</ion:form:register:posted>
34<!-35Form
36-->
37<form method="post" action="">
38<input type="hidden" name="form" value="register" />
39<label for="firstname-reg">First Name</label>
40<input type="text" id="firstname-reg" name="firstname" value="<ion:form:register:field:firstname />" />
41<ion:form:register:error:firstname tag="p" class="input-error" />
42<label for="lastname-reg">Last Name</label>
43<input type="text" id="lastname-reg" name="lastname" value="<ion:form:register:field:lastname />" />
218

44<ion:form:register:error:lastname tag="p" class="input-error" />


45<label for="screen_name-reg">Displayed Screen name</label>
46<input type="text" id="screen_name-reg" name="screen_name"
value="<ion:form:register:field:screen_name />" />
47
<ion:form:register:error:screen_name tag="p" class="input-error" />
48
<label for="email-reg">Email</label>
49
<input type="text" id="email-reg" name="email" value="<ion:form:register:field:email />"/>
50
<ion:form:register:error:email tag="p" class="input-error" />
51
<label for="password-reg">Password</label>
52
<input type="password" id="password-reg" name="password" value=""/>
53
<input type="submit" value="Register" />
54
</form>
55
</ion:user:logged>
56
</ion:form:register:validation:result>
57
219

58
59

Password back formTop of Page


The "password back" form is available only for non logged in users.
This form will send one email to the user only if his/her email exists in the database.
One new password and one account activation link will be sent to the user.
In the file /themes/your_theme/views/page_user.php, add the following code :
1 <ion:user:logged is="false">
2 <!-- Success / Error messages -->
3 <ion:form:password:validation:success tag="p" class="green" />
4 <ion:form:password:validation:error tag="p" class="input-error" />
5 <form method="post" action="">
6 <input type="hidden" name="form" value="password" />
220

7 <label for="email-back"><ion:lang key="form_label_email" /></label>


8 <input type="text" name="email" id="email-back" />
9 <input type="submit" value="Get Password back" />
10</form>
19</ion:user:logged>

Build one module : Part 1


Quick articles links
Prepare the module - Configure the module - Create the website's output of the module (front-end) - Create
one basic admin panel
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.

221

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
How
How
How
How
How
How
How

to create one module for Ionize,


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

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

Prerequisites
System

Ionize installed on one local server (this tutorial is based on the release 0.9.9),
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/
223

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 folder, create one configuration file called "config.xml".
This file will be used by the Modules > Administration panel of Ionize, to get the name and description
of the module but also to install the optional database tables.
In this file, write the following code :
1<?xml version="1.0" encoding="UTF-8"?>
2<module>
3<name>Demo Module</name>
4<description>Authors Demo module</description>
5<uri_segment>demo</uri_segment>
224

<!-- Has this module an admin panel ? -->


6
<has_admin>true</has_admin>
7
<!-- Group who can access to the admin panel of the module -->
8
<access_group>editors</access_group>
</module>
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 :
225

1
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
2
$route['default_controller'] = "demo";
3
$route['(.*)'] = "demo/index/$1";
4
$route[''] = 'demo/index';
5
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 :
1 <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
2 class Demo extends My_Controller
3 {
4 public function __construct()
5 {
226

6
7 parent::__construct();
8 }
9 function index()
10{
11print "Demo module default controller output";
12}
13}
14
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:
1<h1><?php echo $title; ?
227

></h1>
Modify the controller /modules/Demo/controllers/demo.php so the code looks like :
1 <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
2 class Demo extends My_Controller
3 {
4 public function __construct()
5 {
6 parent::__construct();
7 }
8 function index()
9 {
10$this->template['title'] = 'Demo module title';
11$this->output('demo');
12}
228

13
14}
15
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.xml) we added :

<has_admin>true</has_admi
n>

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/

229

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 :
1 <?php if( ! defined('BASEPATH')) exit('No direct script access allowed');
2 /**
3 * Module Admin controller
4 *
5 */
6 class Demo extends Module_Admin
230

7 {
8 /**
9 * Constructor
10*
11* @access public
12* @return void
13*/
14public function construct(){}
15/**
16* Admin panel
17* Called from the modules list.
18*
19* @access public
20* @return parsed view
231

21
22*
23*/
24public function index()
25{
26$this->output('admin/demo');
27}
28}
29
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 :
1 <div id="maincolumn">
2 <h2 class="main"><?php echo lang('module_demo_title'); ?></h2>
232

<div class="subtitle">
3
<!-- About this module -->
4
<p class="lite">
5
<?php echo lang('module_demo_about'); ?>
6
</p>
7
</div>
8
</div>
9
<script type="text/javascript">
10
// Init the panel toolbox is mandatory
11
ION.initToolbox('empty_toolbox');
</script>
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 :

233

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 :
1 <?php
2 /**
3 * Ionize Module lang file
4 * Lang terms must always be prefixed by "module_<module_name>"
5 * to avoid conflict with core / other translations items
6 *
7 */
234

8 $lang['module_demo_title'] = "Demo module";


9 $lang['module_demo_about'] = "About the Demo module...";
10$lang['module_demo_label_open_window'] = "Window example";
11$lang['module_demo_button_open_window'] = "Open window";
12$lang['module_demo_window_title'] = "Modal window title";
13$lang['module_demo_title_edit_author'] = "Edit Author";
14$lang['module_demo_label_gender'] = "Gender";
15$lang['module_demo_label_male'] = "Male";
16$lang['module_demo_label_female'] = "Female";
17$lang['module_demo_button_create_author'] = "Create Author";
18$lang['module_demo_label_new_author'] = "New Author";
19$lang['module_demo_title_authors'] = "Authors";
20$lang['module_demo_title_link_authors'] = "Link Authors";
21$lang['module_demo_button_link_authors'] = "Add Authors";
235

22
$lang['module_demo_label_drop_author'] = "Drop one author here...";
23
$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 48px sized icon for our module.
This icon will be used both for the dashboard icon and the administration panel of the module.

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

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_48_module.png"
Create the file modules/Demo/assets/css/admin.css and add the following code :
1h2.main.demo {
237

2background: url(../images/icon_48_module.png) no-repeat 0 0;


3padding-left:68px;
4}
Modify the view modules/Demo/views/admin/demo.php so it looks like :
<div id="maincolumn">
1
2
3
4
5
6
7

<h2 class="main demo"><?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>

Reload the Ionize backend panel (refresh Ionize).


238

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 48px icon called "icon_48_module.png" and located in the path :
/modules/<module_name>/assets/images/icon_48_module.png
That's why the dashboard displays the module's icon.
Build one module : Part 2
Quick articles links
Add the database tables - Display the authors list - Edit and save one author - Create one author - Delete one
author
Our module is supposed to manage authors and links between authors and articles.
We will need some database tables to do this properly.
Add the database tablesTop of Page
Remember, one of our first task was to create the config.xml file, which gives infos about the module and
makes the backend able to install it.
239

The config.xml file can also contains a reference to a database.xml file, which contains the SQL script to
install the tables and the first content.
Create the file /modules/Demo/database.xml and write the code :
1

<?xml version="1.0" encoding="UTF-8"?>

<sql>

<name>Ionize Demo Module Database Creation</name>

<version>1.0</version>

<license>Open Source MIT license</license>

<!--

Module's tables

Prefixed by module_<module name> to avoid collision

-->

10 <tables>
11 <!-12 Author table
240

13 One author has a name and a gender


14 -->
15 <query>
16 CREATE TABLE IF NOT EXISTS module_demo_author (
17 id_author INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
18 gender TINYINT(1) UNSIGNED NOT NULL DEFAULT 1,
19 name VARCHAR(255) NOT NULL,
20 PRIMARY KEY (id_author)
21 )
22 ENGINE = InnoDB
23 AUTO_INCREMENT = 1
24 DEFAULT CHARACTER SET = utf8
25 COLLATE = utf8_unicode_ci;
26 </query>
241

27 <!-28 Author lang table


29 The author's bio or description should be available
30 for each language
31 -->
32 <query>
33 CREATE TABLE IF NOT EXISTS module_demo_author_lang (
34 id_author INT UNSIGNED NOT NULL,
35 lang VARCHAR(3) NOT NULL,
36 description VARCHAR(3000) NULL,
37 PRIMARY KEY (id_author,lang)
38 )
39 ENGINE = InnoDB
40 DEFAULT CHARACTER SET = utf8
242

41 COLLATE = utf8_unicode_ci;
42 </query>
43 <!-44 Author media table
45 One author can have a photo
46 -->
47 <query>
48 CREATE TABLE IF NOT EXISTS module_demo_author_media (
49 id_author INT(11) UNSIGNED NOT NULL,
50 id_media INT(11) UNSIGNED NOT NULL DEFAULT 1,
51 ordering INT(11) UNSIGNED NULL DEFAULT 9999,
52 PRIMARY KEY (id_author, id_media)
53 )
54 ENGINE = InnoDB
243

55 DEFAULT CHARACTER SET = utf8


56 COLLATE = utf8_unicode_ci;
57 </query>
58 <!-59 Link table
60 One author is linked to one page, article, other parent
61 -->
62 <query>
63 CREATE TABLE IF NOT EXISTS module_demo_links (
64 parent CHAR(25) NOT NULL,
65 id_parent INT(11) UNSIGNED NOT NULL,
66 id_author INT UNSIGNED NOT NULL,
67 ordering INT(11) UNSIGNED NULL DEFAULT 9999,
68 PRIMARY KEY (parent,id_parent,id_author)
244

69 )
70 ENGINE = InnoDB
71 DEFAULT CHARACTER SET = utf8
72 COLLATE = utf8_unicode_ci;
73 </query>
74 </tables>
75 <!-76 Content inserted at module's installation
77 -->
78 <content>
79 <query>
80 INSERT IGNORE INTO module_demo_author (id_author,name,gender)
81 VALUES
82 (1, 'Roberto Chansez', 1),
245

83 (2, 'Elisabeth Fueller', 2),


84 (3, 'Emile Durand', 1);
85 </query>
86 <query>
87 INSERT IGNORE INTO module_demo_author_lang (id_author,lang,description)
88 VALUES
89 (1, 'en', 'Known as a famous explorator, he discovered more than 50 new kind of animals'),
90 (2, 'en', 'World known artist and designer'),
91 (3, 'en', 'Famous TV speakering in Marioland');
92 </query>
93 </content>
94 </sql>
95
96
246

97
98
99
100
101
102
103
104
Edit now the /modules/Demo/config.xml file and add the code so it looks like :
1 <?xml version="1.0" encoding="UTF-8"?>
2 <module>
3 <name>Demo Module</name>
4 <description>Authors Demo module</description>
5 <uri_segment>demo</uri_segment>
247

6 <!-- Has this module an admin panel ? -->


7 <has_admin>true</has_admin>
8 <!-- Group who can access to the admin panel of the module -->
9 <access_group>editors</access_group>
10<!-- Module's Database installation script. -->
11<database script="database.xml"></database>
</module>
Go to Ionize, in Modules > Administration, uninstall the module and install it again.
Open your favorite database editor, have a look to your Ionize's database : The installer has created the 4
tables :

module_demo_author
module_demo_author_lang
module_demo_author_media
module_demo_links

If you look to the tables content, you will see that some basic content already exists in the tables
module_demo_author and module_demo_author_lang.
Display the authors listTop of Page
248

When we click on the module's dashboard icon, it calls the module's admin default controller
(admin/demo.php), which loads the view /modules/Demo/views/admin/demo.php.
We will now create :

One controller to manage the authors (display list, edit, save, delete),
One model to get and set data in our tables,
The views to display the authors list and edit one author on the backend

Create the file /modules/Demo/models/demo_author_model.php containing the code :


1 <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
2 class Demo_author_model extends Base_model
3 {
4 // Author tables
5 protected $_author_table = 'module_demo_author';
6 protected $_author_lang_table = 'module_demo_author_lang';
7 // Link table between authors and parents (page, article)
8 protected $_link_table = 'module_demo_links';
9 /**
249

* Model Constructor
10
*
11
* @access public
12
*/
13
public function __construct()
14
{
15
$this->set_table($this->_author_table);
16
$this->set_lang_table($this->_author_lang_table);
17
$this->set_pk_name('id_author');
18
parent::__construct();
19
}
}
The model extends Base_model, which has good generic methods to set and retrieve data fro Ionize
database.
As Demo_author_model extends Base_model, it inherits its methods.
We will enhance this model, but for the moment, this code is enough.
250

Create the file /modules/Demo/controllers/admin/author.php containing the code :


1 <?php if( ! defined('BASEPATH')) exit('No direct script access allowed');
2 class Author extends Module_Admin
3 {
4 /**
5 * Constructor
6 *
7 * @access public
8 * @return void
9 */
10public function construct()
11{
12// Loads the model as 'author_model'
13$this->load->model('demo_author_model', 'author_model', true);
251

14}
15/**
16* Outputs the authors list
17*
18*/
19public function get_list()
20{
21$conds = array(
22'order_by' => 'name ASC'
23);
24$this->template['authors'] = $this->author_model->get_list($conds);
25$this->output('admin/author_list');
26}
27/**
252

28* Outputs the detail of one author


29* @param int ID of the author
30*
31*/
32public function get($id)
33{
34/* has to be written */
35}
36/**
37* Saves one author
38*
39*/
40public function save()
41{
253

42
/* has to be written */
43
}
44
}
Create the file /modules/Demo/views/admin/author_list.php and add the code :
1 <ul class="authorPanelList list mb20 mt10">
2 <?php foreach($authors as $author) :?>
3 <?php
4 $id = $author['id_author'];
5 ?>
6 <li class="author<?php echo $id ?> pointer" id="author_<?php echo $id ?>" data-id="<?php echo $id ?
>">
7
<a class="icon drag left"></a>
8
<a class="left pl5 edit title" data-id="<?php echo $id ?>">
9
<?php echo $author['name'] ?>
254

10</a>
11</li>
12<?php endforeach ;?>
</ul>
Now, we have a view which is able to display the list of authors.
Let's modify the default admin view of the module to use this list.
Modify the view /modules/Demo/views/admin/demo.php so that the code look like this :
1 <div id="maincolumn">
2 <h2 class="main demo"><?php echo lang('module_demo_title'); ?
></h2>
3
<div class="subtitle">
4
<!-- About this module -->
5
<p class="lite">
6
<?php echo lang('module_demo_about'); ?>
7
</p>
255

8 </div>
9 <!-- Will contains the authors list -->
10<div id="moduleDemoAuthorsList"></div>
11</div>
<script type="text/javascript">
22// Init the panel toolbox is mandatory
23ION.initToolbox('empty_toolbox');
24// Update the authors list
25ION.HTML(
26'module/demo/author/get_list', // URL to the controller
27{}, // Data send by POST. Nothing
28{'update':'moduleDemoAuthorsList'} // JS request options
29);
30</script>
256

31
In Ionize, go to Modules > Demo module. Now, it displays the authors list :

To understand what happened :


1. The view admin/demo.php calls through Ajax the controller admin/demo/author/get_list
2. This controller uses the model demo_author_model to get the author list, send the data to the view
and outputs the view
3. The Ajax request receive the HTML output and updates the DIV with the ID "moduleDemoAuthorList"
Answer to common remarks :
The model "demo_author_model" hasn't any method "get_list"...
Yes, but this model extends "base_model", which has this method. Setting the tables which concerns the
model demo_author_model is enough to make most of the method of base_model working with the
authors tables.
I have to know that the JS "ION" object has a method to make HTML request
Yes, the javascript ION object has several method to make requests, open windows and load data inside
them, refreshing given DIV, init drag'n'drop and much more.
The Javascript documentation isn't written at this time (but we will write it! ), but you can have a look at
the source files or use standard mootools requests to get the same result.

257

Edit and save one authorTop of Page


To edit one author, we will use one Ionize window :

One click on the author's name will open a window containing the author's form.
This window will have 2 buttons : one to save the author, one to cancel and close the window.

Before modify the view, prepare the controller's "get" and "save" actions :
1 <?php if( ! defined('BASEPATH')) exit('No direct script access allowed');
2 /**
3 * Module Admin controller
4 *
5 *
6 */
7 class Author extends Module_Admin
8 {
9 /**
10* Constructor
258

11*
12* @access public
13* @return void
14*/
15public function construct()
16{
17$this->load->model('demo_author_model', 'author_model', TRUE);
18$this->load->model('page_model', '', TRUE);
19}
20/**
21* Outputs the authors list
22*
23*/
24public function get_list()
259

25{
26$conds = array(
27'order_by' => 'name ASC'
28);
29$this->template['authors'] = $this->author_model->get_list($conds);
30$this->output('admin/author_list');
31}
32/**
33* Outputs the detail of one author
34* @param int ID of the author
35*
36*/
37public function get($id)
38{
260

39$where = array(
40'id_author' => $id
41);
42$this->template = $this->author_model->get($where);
43$this->author_model->feed_lang_template($id, $this->template);
44$this->output('admin/author_detail');
45}
46/**
47* Saves one author
48*
49*/
50public function save()
51{
52// The name must be set
261

53if ($this->input->post('name') != '')


54{
55$id_author = $this->author_model->save($this->input->post());
56// Update the authors list
57$this->update[] = array(
58'element' => 'moduleDemoAuthorsList',
59'url' => admin_url() . 'module/demo/author/get_list'
60);
61// Send the user a message
62$this->success(lang('ionize_message_operation_ok'));
63}
64else
65{
66// Send the user a message
262

67
68$this->error(lang('ionize_message_operation_nok'));
69}
70}
71}

To be able to save the author, edit the demo_author_model and add the method save() :
1 <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
2 class Demo_author_model extends Base_model
3 {
4 // Author tables
5 protected $_author_table = 'module_demo_author';
6 protected $_author_lang_table = 'module_demo_author_lang';
7 // Link table between authors and parents (page, article)
263

8 protected $_link_table = 'module_demo_links';


9 /**
10* Model Constructor
11*
12* @access public
13*/
14public function __construct()
15{
16$this->set_table($this->_author_table);
17$this->set_lang_table($this->_author_lang_table);
18$this->set_pk_name('id_author');
19parent::__construct();
20}
21public function save($inputs)
264

22{
23// Arrays of data which will be saved
24$data = $data_lang = array();
25// Fields of the author table
26$fields = $this->list_fields();
27// Set the data to the posted value.
28foreach ($fields as $field)
29$data[$field] = $inputs[$field];
30$lang_fields = $this->list_fields($this->_author_lang_table);
31foreach(Settings::get_languages() as $language)
32{
33foreach ($lang_fields as $field)
34{
35if ($field != $this->pk_name && $field != 'lang')
265

{
36
$input_field = $field.'_'.$language['lang'];
37
if ($inputs[$input_field] !== FALSE)
38
$data_lang[$language['lang']][$field] = $inputs[$input_field];
39
}
40
}
41
}
42
return parent::save($data, $data_lang);
43
}
}
We need one view to display the author form.
Create the file /modules/Demo/views/admin/author_detail.php :
1 <?php
2 $id = $id_author;
266

3 ?>
4 <form name="authorForm<?php echo $id ?>" id="authorForm<?php echo $id ?>" action="<?php echo
admin_url() ?>module/demo/author/save">
5
<!-- Hidden fields -->
6
<input id="id_author<?php echo $id ?>" name="id_author" type="hidden" value="<?php echo $id ?>" />
7
<!-- Name -->
8
<dl class="small">
9
<dt>
10
<label for="name<?php echo $id ?>"><?php echo lang('ionize_label_name')?></label>
11
</dt>
12
<dd>
13
<!-14
The validation of this mandatory field is first done by JS
15
by adding the attribute data-validators="required"
16
see : <a href="http://mootools.net/docs/more/Forms/Form.Validator#Validators"
267

17target="_blank">http://mootools.net/docs/more/Forms/Form.Validator#Validators</a>
18-->
19<input id="name<?php echo $id ?>" name="name" class="inputtext required" type="text" value="<?php
echo $name ?>" data-validators="required"/>
20
</dd>
21
</dl>
22
<!-- Gender -->
23
<dl class="small">
24
<dt>
25
<label><?php echo lang('module_demo_label_gender')?></label>
26
</dt>
27
<dd>
28
<input id="genderMale<?php echo $id ?>" name="gender" <?php if ($gender == 1):?
29>checked="checked" <?php endif; ?>class="radio" type="radio" value="1" />
30<label for="genderMale<?php echo $id ?>">
268

31<?php echo lang('module_demo_label_male')?>


32</label>
33<input id="genderFemale<?php echo $id ?>" name="gender" <?php if ($gender == 2):?
>checked="checked" <?php endif; ?> class="radio" type="radio" value="2" />
34
<label for="genderFemale<?php echo $id ?>">
35
<?php echo lang('module_demo_label_female')?>
36
</label>
37
</dd>
38
</dl>
39
<fieldset>
40
<!-- Tabs -->
41
<div id="authorTab<?php echo $id ?>" class="mainTabs">
42
<ul class="tab-menu">
43
<?php foreach(Settings::get_languages() as $l) :?>
44
<li class="tab_edit_author<?php echo $id ?><?php if($l['def'] == '1') :?> dl<?php endif ;?
269

45>"><a><span><?php echo ucfirst($l['name']) ?></span></a></li>


46<?php endforeach ;?>
47</ul>
48<div class="clear"></div>
49</div>
50<div id="authorTabContent<?php echo $id ?>">
51<!-- Text block -->
52<?php foreach(Settings::get_languages() as $language) :?>
53<?php $lang = $language['lang']; ?>
54<div class="tabcontent<?php echo $id ?>">
55<!-- description -->
56<textarea id="description_<?php echo $lang ?><?php echo $id ?>" name="description_<?php echo
$lang ?>" class="textarea autogrow" rel="<?php echo $lang ?>"><?php echo ${$lang}['description'] ?
57></textarea>
58</div>
270

59<?php endforeach ;?>


60</div>
61</fieldset>
62</form>
63<!-- Save / Cancel buttons
64Must be named bSave[windows_id] where 'window_id' is the used ID
65or the window opening through ION.formWindow()
66-->
67<div class="buttons">
68<button id="bSaveauthor<?php echo $id ?>" type="button" class="button yes right mr40"><?php echo
lang('ionize_button_save_close') ?></button>
69
<button id="bCancelauthor<?php echo $id ?>" type="button" class="button no right"><?php echo
70lang('ionize_button_cancel') ?></button>
71</div>
72<script type="text/javascript">
271

73// Tabs init


74new TabSwapper({
75tabsContainer: 'authorTab<?php echo $id ?>',
76sectionsContainer: 'authorTabContent<?php echo $id ?>',
77selectedClass: 'selected',
78tabs: 'li',
79clickers: 'li a',
80sections: 'div.tabcontent<?php echo $id ?>'
81});
82// Autogrow textareas of the given form ID
83ION.initFormAutoGrow('authorForm<?php echo $id ?>');
84</script>
85
86
272

87

Some comments about this view :


We see that the form's HTML ID is postfixed with the author's ID : This is needed, because the "Save"
button will send the data to the controller through XHR (Ajax). The Ajax function has to know which form
to send. Also, 2 forms cannot have the same ID and more than one author edition window can be opened
in the same time.
Every form element is also postfixed : this is to be sure that no other HTML element will have the same ID.
Now, we will add the event which will open the author editing window on each author's name of the list.
Open and edit the file /modules/Demo/views/admin/author_list.php, to add some javascript :
1 <ul class="authorPanelList list mb20 mt10">
2 <?php foreach($authors as $author) :?>
3 <?php
4 $id = $author['id_author'];
5 ?>
6 <li class="author<?php echo $id ?> pointer" id="author_<?php echo $id ?>" data-id="<?php echo $id ?
>">
273

7 <a class="icon drag left"></a>


8 <a class="left pl5 edit title" data-id="<?php echo $id ?>">
9 <?php echo $author['name'] ?>
10</a>
11</li>
8 <?php endforeach ;?>
39</ul>
40<script type="text/javascript">
41// Click Event to display the details of one creator
42$$('.authorPanelList li').each(function(item, idx)
43{
44var id = item.getProperty('data-id');
45var a = item.getElement('a.title');
46a.removeEvents('click');
274

a.addEvent('click', function(e)
{
// see : /themes/admin/javascript/ionize/ionize_window.js
// ION.formWindow : function(id, form, title, wUrl, wOptions, data)
ION.formWindow(
'author' + id, // ID of the window
'authorForm' + id, // ID of the author form
'module_demo_title_edit_author', // term of the window title
'module/demo/author/get/' + id, // URL of the controller
{
'width':350,
'height':200
}
);
275

});
});
</script>
Some explanation :
The JS function ION.formWindow() will open one Ionize window, display the form by using the given
controller and automatically add the "save" / "cancel" events on the window buttons.
To be able to do that, this function has to know the ID of the form to use.
Also, the "cancel" and "save" buttons of the form must have one given ID, set in the author_detail view,
which must be :

Save button: bSave<window_id>. Example : bSaveauthor22


Cancel button : bCancel<window_id>. Example : bCancelauthor22

When saving the author, the data will be send to the form "action" URL by POST.
The save controller will :

Send the posted data to the save() method of the author model (demo_author_model)
Update the authors list and display one message to the user.
Ionize has a JS callback integrated system : Define the "update" array of the controller, set the HTML DOM
element which needs to be updated and the corresponding URL (here the controller's authors list) is enough
to execute this request after the save request.

276

Now, when we reload the module and click on one author name, one window opens and we're able to edit
the author's data and save them.

Create one authorTop of Page


To create one author, we will need :

One button to open a "Author creation" window : We will put this button on the main panel of the
module.
Modify a little the "get" method of the controller.

Add the "Create Author" button


We will add this button in the module's toolbar.
The module "toolbar" is the buttons container next to the main panel title :
When you edit one article, this toolbar contains the main actions buttons : Add media, Delete, Save, etc.
When we created the module's main view (/modules/Demo/views/demo.php) you probably noticed than we
added this little JS code:
1ION.initToolbox('empty_toolbox');
This is mandatory because the toolbar is loaded through XHR after the panel has loaded, to give each panel
the ability to load its own toolbox.
277

Note : On panels which hasn't any toolbox, it is mandatory to load the "empty_toolbox" to remove the
previous panel buttons.
Create the folder /modules/Demo/views/admin/toolboxes/
Create the file /modules/Demo/views/admin/toolboxes/demo_toolbox.php and add the code :
1 <div class="divider">
2 <a class="button light" id="newAuthorToolbarButton">
3 <i class="icon-plus"></i><?php echo lang('module_demo_button_create_author'); ?>
4 </a>
5 </div>
6 <script type="text/javascript">
7 $('newAuthorToolbarButton').addEvent('click', function(e)
8 {
9 ION.formWindow(
10'author',
11'authorForm',
278

Lang.get('module_demo_label_new_author'),
12
admin_url + 'module/demo/author/create',
13
{
14
'width':350,
15
'height':250
16
}
17
);
18
});
</script>
This little piece of code will display the button and add the "Open window form" event on the button.
We need now to use this toolbar in the main panel of the module.
Open and edit the file /modules/Demo/views/demo.php :
Replace the code :
1ION.initToolbox('empty_toolbox');
by :
279

1ION.initModuleToolbox('demo','demo_toolbox');
Reloading the module will display the button "Create Author" :

Modify the author controller


To display one empty author form, add the following method to the file
/modules/Demo/controllers/admin/authors.php :
1 /**
2 * Displays the author form
3 *
4 */
5 function create()
6 {
7 $this->author_model->feed_blank_template($this->template);
8 $this->author_model->feed_blank_lang_template($this->template);
9 $this->output('admin/author_detail');
280

10
}
11
Now, the button opens one empty form and saves the author.
Delete one authorTop of Page
To delete one author, we have 2 choices here :

Add one delete button in the author edition window


Add one delete icon on each author of the authors list.

To make things simple, we will add one delete icon to each author in the authors list (choice 2), because
this will not need to open again the author window to delete the author.
Add the delete button
Open the file /modules/Demo/views/admin/author_list.php and :
Find the code :
<a class="icon drag left"></a>
Just after, add :
<a class="icon delete right"></a>
281

Modify the javascript block of this file so it looks like :


1 <script type="text/javascript">
2 // Click Event to display the details of one creator
3 $$('.authorPanelList li').each(function(item, idx)
4 {
5 var id = item.getProperty('data-id');
6 var a = item.getElement('a.title');
7 var del = item.getElement('a.delete');
8 a.addEvent('click', function(e)
9 {
10// see : /themes/admin/javascript/ionize/ionize_window.js
11// ION.formWindow : function(id, form, title, wUrl, wOptions, data)
12ION.formWindow(
13'author' + id, // ID of the window
282

14'authorForm' + id, // ID of the author form


15'module_demo_title_edit_author', // lang term of the window title
16'module/demo/author/get/' + id, // URL of the controller
17{
18'width':350,
19'height':200
20}
21);
22});
23ION.initRequestEvent(
24del, // The item to add the event on
25admin_url + 'module/demo/author/delete/' + id, // URL to call
26{}, // Data to send. Here nothing.
27// Confirmation object
283

28
29{
30'confirm': true,
31'message': Lang.get('ionize_confirm_element_delete')
32}
33);
34});
35</script>

Modify the model


Open the file /modules/Demo/models/demo_author_model.php and add the following method:
1 /**
2 * Deletes one Author
3 * and the corresponding lang data
284

*
4
* @param int $id
5
*
6
* @return int Number of delete items in main table
7
*
8
*/
9
public function delete($id)
10
{
11
$nb_rows = parent::delete($id, $this->_author_table);
12
if ($nb_rows > 0)
13
parent::delete($id, $this->_author_lang_table);
14
return $nb_rows;
}
Modify the controller
285

Open the file /modules/Demo/controllers/admin/author.php and add the following method:


1 /**
2 * Delete one author
3 *
4 */
5 public function delete($id)
6 {
7 if ($this->author_model->delete($id) > 0)
8 {
9 // Update the authors list
10$this->update[] = array(
11'element' => 'moduleDemoAuthorsList',
12'url' => admin_url() . 'module/demo/author/get_list'
13);
286

14
// Send the user a message
15
$this->success(lang('ionize_message_operation_ok'));
16
}
17
else
18
{
19
// Send the user a message
20
$this->error(lang('ionize_message_operation_nok'));
21
}
22
}
23
Conclusion
We have now one module which is able to create, edit and delete authors.
In the next part, we will create a module addon, to be able to easily link authors to one article, simply by
using Drag'n'drop.

287

Build one module : Part 3


Quick articles links
Activate the "addons" placeholder- From article, display the authors- Drag'n'drop authors to article- Unlink
authors form articles
In the part 1 & 2 of this tutorial, we created one module which manage "authors".
Now, we want to link these authors to article.
To do that, we need one window to display the author list when we're editing one article.
From this window, we will be able to drag authors from the authors list and drop them to the article.
We will display the list of authors and one button to add authors in the options panel of the article.
Activate the "addons" placeholderTop of Page
Module placeholders & placeholders views
In the Ionize back-office, articles and pages have placeholders for modules, which can display views from
modules.
These placeholders are named, and loads the modules corresponding views if they exists.
Modules placeholders are available for panels, and each panel is considered like a "parent" for the module :

Article edition panel. Parent code : 'article',


Page edition panel. Parent code : 'page'
Media edition panel. Parent code : 'media'
288

The module placeholder views are called "add ons".

On article and page edition panels, they are 3 available module placeholders :

main_top : Displays the view after the page or article title


options_top : Displays the module view before the options accordion
options_bottom : Displays the module view after the options accordion

Activate the "addon" placeholder


One module addon is the view which will be displayed in one placeholder.
In the part 1 of this tutorial, we created the module default admin controller,
/modules/Demo/controllers/admin/demo.php.
This controller currently just outputs the "admin panel" of the module.
By adding one method to this controller, we will be able to load module's placeholder views.
First, let be organized and create one view folder for the addons :
modules /
Demo/
views/
admin/
addons/
289

article/

This folder organization is not needed, but is a good practice to organize views more logically and will help
other developers to faster understand your module.
Edit the file /modules/Demo/controllers/admin/demo.php and add the following method :
1 /**
2 * Adds "Addons" to core panels
3 * @param Array The current edited object (page, article, ...)
4 *
5 */
6 public function _addons($object = array())
7 {
8 $CI =& get_instance();
9 // Send the article to the view
10$data['article'] = $object;
290

11
12// Options panel Top Addon
13$CI->load_addon_view(
14'demo', // Module folder
15'article', // Parent panel code
16'options_top', // Placehoder code
17'admin/addons/article/options', // View to display in the placeholder
18$data // Data send to the view
19);
20}
21

Some explanation :
This method receives the current edited object as an array. If you're editing one page, it receive the page
array, if you're editing one article, it receive the article array.
291

The call to $CI->load_addon_view() loads the asked view in the wished placeholder.
In this example, we tell the loader that the module is 'demo', that the parent panel is 'article' and that the
view 'admin/addons/article/options' must be displayed in the placeholder 'options_top' of the parent
panel.
From article, display the authorsTop of Page
To do that, we will open one window which will display the authors list.
We will now need :

One view to display in the article panel placeholder.


One controller method to display the list of authors who are linked to the edited article
One model method to get the list of linked authors from the database.

Modify the controller


Modify the controller /modules/Demo/controllers/admin/author.php and add the methods :
1 /**
2 * Displays the list of linked authors
3 *
4 */
5 public function get_linked_authors()
292

6 {
7 $parent = $this->input->post('parent');
8 $id_parent = $this->input->post('id_parent');
9 $this->template['authors'] = array();
10$this->template['parent'] = $parent;
11$this->template['id_parent'] = $id_parent;
12if ($parent && $id_parent)
13{
14$this->template['authors'] = $this->author_model->get_linked_author($parent, $id_parent);
15}
16$this->output('admin/addons/article/authors');
}
Modify the model
Modify the model /modules/Demo/models/demo_author_model.php and add the method :
293

1 public function get_linked_author($parent, $id_parent)


2 {
3 // Returned data
4 $data = array();
5 // Conditions
6 $where = array(
7 'parent' => $parent,
8 'id_parent' => $id_parent,
9 $this->_author_lang_table.'.lang' => Settings::get_lang('default')
10);
11$query = $this->{$this->db_group}
12->where($where)
13->order_by('ordering ASC')
14->join(
294

15$this->_author_table,
16$this->_author_table.'.id_author = ' . $this->_link_table.'.id_author',
17'left'
18)
19->join(
20$this->_author_lang_table,
21$this->_author_lang_table.'.id_author = ' . $this->_author_table.'.id_author',
22'left'
23)
24->get($this->_link_table)
25;
26if ( $query->num_rows() > 0 )
27$data = $query->result_array();
return $data;
295

Create the view to display linked authors


Create the view /modules/Demo/views/admin/addons/article/authors.php :
This view will display the authors who are linked to the current edited article.
1<?php if ( ! empty($authors)) :?>
2<ul id="demoAuthorsList">
3<?php foreach($authors as $author) :?>
4<li class="sortme">
5<a class="title"><?php echo $author['name'] ;?></a>
6</li>
7<?php endforeach; ?>
8</ul>
<?php endif; ?>
Create the view /modules/Demo/views/admin/addons/article/options.php :
This view contains the button "Add authors" and the container for the authors list.

296

1 <h3 class="toggler toggler-options"><?php echo lang('module_demo_title_authors'); ?></h3>


2 <div class="element element-options">
3 <div class="element-content">
4 <!-- Linked Authors container -->
5 <?php if ($article['id_article'] != '') :?>
6 <div id="demoAuthorsContainer"></div>
7 <?php endif ;?>
8 <!-9 Button : Link one author
10-->
11<a id="btnDemoLinkAuthor" class="button light plus">
12<i class="icon-plus"></i>
13<?php echo lang('module_demo_button_link_authors') ?>
14</a>
297

15</div>
16</div>
17<script type="text/javascript">
18// Opens the authors window
19$('btnDemoLinkAuthor').addEvent('click', function()
20{
21// See : /themes/admin/javascript/ionize/ionize_window.js
22ION.dataWindow(
23'demoAuthors', // ID of the window
24'module_demo_title_link_authors', // Lang term used for window title
25// URL to the content of the window
26ION.adminUrl + 'module/demo/author/get_list',
27// Window options
28{
298

29'width':400,
30'height':250
31},
32// Data to send by POST to the called URL
33{
34'id_article': '<?php echo $article['id_article'] ?>'
35}
36);
37});
38// Linked creators : Called when this view is loaded
39if ($('demoAuthorsContainer'))
40{
41ION.HTML(
42admin_url + 'module/demo/author/get_linked_authors',
299

43
{
44
'parent': 'article',
45
'id_parent': '<?= $article['id_article'] ?>'
46
},
47
{'update': 'demoAuthorsContainer'}
48
);
49
}
50
</script>

Now, we have a nice "Add Authors" button in the article options panel.
One click on this button will open one window containing the list of authors.
The authors placeholder is from now also supposed to load the linked authors list.

To go further (optional) :
300

As you noticed it, we used the same controller to list the authors in this authors windows than to list the
authors in the module's administration view. For this reason, when we click on one author, it opens the
author edition window.
Unfortunately, editing or delete one author from this window will not update the window list, because this
window does not contains the "author list container" with the ID "moduleDemoAuthorsList" (this
container is in the view /modules/Demo/views/admin/demo.php).
We can modify the "save" and "delete" method of the author controller so that this list is also updated.
Using Firebug to have a look at the HTML DOM elements is strongly recommended to understand this step.
1. Get the HTML selector element
The ID of the window is "demoAuthors".
Ionize automatically adds one "w" in front of this ID to identify the window.
So we know that the window has the ID "wdemoAuthors"
The content area of each Ionize window has the class ".mochaContent"
The complete selector to the HTML container is then : "wdemoAuthors .mochaContent"
2. Add the update callback to the controller:
In the controller /modules/Demo/admin/controllers/author.php:
Replace all occurrence of :
1$this->update[] = array(
2'element' => 'moduleDemoAuthorsList',
3'url' => admin_url() . 'module/demo/author/get_list'
4);
301

3. by :
1
2
3
4

$this->update[] = array(
'element' => 'moduleDemoAuthorsList, #wdemoAuthors
.mochaContent',
'url' => admin_url() . 'module/demo/author/get_list'
);

But for the moment, we don't have any behavior to link one author to the article.
Drag'n'drop authors to articleTop of Page
We will need :

Drag event on each author from the list,


One drop area to drop the dragged author on,
One controller method to link one author to the article (called when the author is dropped on the "drop
area"
One corresponding model to create the link author / article in database.

Prepare the Drag'n'drop


Edit the file /modules/Demo/views/admin/author_list.php and add the following lines in the javascript block
:

302

<script type="text/javascript">
1
// Click Event to display the details of one creator
2
$$('.authorPanelList li').each(function(item, idx)
3
{
4
/* Existing code After a.addEvent('click', function(e) */
5
// Adds Drag'n'Drop behavior on each author name
6
ION.addDragDrop(
7
a, // DOM element to drag
8
'.dropDemoAuthor', // Selector of the drop areas.
9
'DEMO_MODULE.dropAuthorOnParent' // Method to execute when the dragged element is dropped
10
);
11
});
</script>

303

The DEMO_MODULE javascript object doesn't exists.


Let's create it !
Create the folder :
modules /
Demo/
assets/
javascript/
Create the file /modules/Demo/assets/javascript/admin.js and add the code:
1 var DEMO_MODULE = (DEMO_MODULE || {});
2 DEMO_MODULE.append = function(hash){
3 Object.append(DEMO_MODULE, hash);
4 }.bind(DEMO_MODULE);
5 DEMO_MODULE.append(
6 {
32baseUrl: base_url,
33adminUrl: admin_url,
304

moduleUrl: admin_url + 'module/demo/',


/**
* Called when one author is dropped to one droppable element
* This method receives :
*
* @param DOM element Dragged clone of the element
* @param DOM element DOM Element on which the element is
dropped
* @param event The event
*
*/
dropAuthorOnParent: function(element, droppable, event)
{
ION.JSON(
this.moduleUrl + 'author/add_link',
305

{
'parent': droppable.getProperty('data-parent'),
'id_parent': droppable.getProperty('data-parent-id'),
'id_author': element.getProperty('data-id')
}
);
}
});
Some explanation :
If it exists, the Javascript file /modules/Demo/assets/javascript/admin.js is auto loaded at Ionize backend
satrtup.
In the /modules/Demo/views/admin/author_list.php view, we added drag'n'drop capabilities to the title of
each author in the author list. This is done with the ION.addDragDrop() method which is waiting for:
1. The element to drag
2. The selector (CSS class) of droppable DOM elements
3. One callback method name. This method will be executed when the element is dropped to one
droppable DOM element.
306

The callback method DEMO_MODULE.dropAuthorOnParent() will automatically receive :


1. The dropped element
2. The droppable element
3. The drag'n'drop event
With that, we will be able to get properties from the dragged element but also from the dropped element,
exactly what is done by dropAuthorOnParent() which call the controller's method "add_link()" and
send him the needed data.
We now need to add the droppable area in the module view which is displayed in the options panel.
Edit the file /modules/Demo/views/admin/addons/article/options.php :
Before :
<!-- Linked Authors container -->
Add :

1
2
3
4

<!-- Droppable area -->


<div class="droppable dropDemoAuthor" data-parent="article" data-parent-id="<?php echo
$article['id_article'];?>">
<?php echo lang('module_demo_label_drop_author'); ?>
</div>

We see that the droppable area has the parent code ('article') and the parent ID as HTML attributes.
307

Modify the model


Edit the file /modules/Demo/models/demo_author_model.php and add the following methods:
1 /**
2 * Creates one link between one parent and one author
3 *
4 * @param string Parent code (article, page)
5 * @param int Parent ID
6 * @param int Author ID
7 *
8 * @return bool TRUE if inserted, FALSE if the link already exists
9 *
10*/
11public function link_author_to_parent($parent, $id_parent, $id_author)
12{
13$data = array(
308

14'parent' => $parent,


15'id_parent' => $id_parent,
16'id_author' => $id_author
17);
18$this->db->where($data);
19$query = $this->{$this->db_group}
20->where($data)
21->get($this->_link_table);
22if ($query->num_rows() == 0)
23{
24$this->{$this->db_group}->insert($this->_link_table, $data);
25return TRUE;
26}
27return FALSE;
309

28
29}
30
Modify the controller
Edit the file /modules/Demo/controllers/admin/author.php and add the following methods
1/**
2* Links one Author with one parent
3*
4*/
5public function add_link()
6{
7$parent = $this->input->post('parent');
8$id_parent = $this->input->post('id_parent');
9$id_author = $this->input->post('id_author');
310

if ($this->author_model->link_author_to_parent($parent, $id_parent, $id_author))


{
// Set the callbacks
$this->update_dom_linked_authors($parent, $id_parent, $id_author);
// Send the user a message
$this->success(lang('ionize_message_operation_ok'));
}
else
{
// Send the user a message
$this->error(lang('module_demo_message_author_already_linked'));
}
}
/**
311

* Send the callback to update the linked authors list


*
* @param string Parent code
* @param int Parent ID
*
*/
protected function update_dom_linked_authors($parent, $id_parent)
{
$this->callback = array(
array(
'fn' => 'ION.HTML',
'args' => array(
'module/demo/author/get_linked_authors',
array('parent' => $parent,'id_parent' => $id_parent),
312

array('update' => 'demoAuthorsContainer')


)
)
);
}
The add_link() method calls the model to create the link between the author and one article and then call
the update_dom_linked_authors() method, which returns to the XHR request the name of the callback
method to execute in order to refresh the authors list.
This refresh code is stored in a dedicated method because it will also be called when one author is unlinked
from one article.
Unlink authors form articlesTop of Page
We will now add one "unlink" button to each author.
Modify the view
Modify the view /modules/Demo/views/admin/addons/article/authors.php :
1 <?php if ( ! empty($authors)) :?>
313

2 <ul id="demoAuthorsList">
3 <?php foreach($authors as $author) :?>
4 <li class="sortme">
5 <a class="title"><?php echo $author['name'] ;?></a>
6 <!-- Unlink icon -->
7 <a class="icon unlink right" data-id="<?php echo $author['id_author'] ;?>"></a>
8 </li>
9 <?php endforeach; ?>
10</ul>
11<script type="text/javascript">
12$$('#demoAuthorsList li').each(function(item)
13{
14var unlinkIcon = item.getElement('.unlink');
15ION.initRequestEvent(
314

// Element to add the request on


16
unlinkIcon,
17
// URL to send the data
18
'<?= admin_url() ?>/module/demo/author/unlink',
19
// Data send by POST to the URL
20
{
21
'parent': '<?php echo $parent ?>',
22
'id_parent': '<?= $id_parent ?>',
23
'id_author': unlinkIcon.getProperty('data-id')
24
}
25
);
26
});
27
</script>
<?php endif; ?>
315

Here, one JS XHR request event is added to each "unlink" icon of the author list.
This request will call the method unlink() from the author controller.
Modify the controller
Modify the controller /modules/Demo/controllers/admin/author.php and add the "unlink()" method :
1public function unlink()
2{
3$parent = $this->input->post('parent');
4$id_parent = $this->input->post('id_parent');
5$id_author = $this->input->post('id_author');
6$this->author_model->unlink_author_from_parent($parent, $id_parent, $id_author);
7// Set the callbacks
8$this->update_dom_linked_authors($parent, $id_parent, $id_author);
// Direct output, without message
$this->response();
316

Modify the model


Edit the file /modules/Demo/models/demo_author_model.php and add the following methods:
1 /**
2 * Deletes on link between one author and one parent
3 *
4 * @param string Parent code (article, page)
5 * @param int Parent ID
6 * @param int Author ID
7 *
8 * @return int Number of affected rows (1 or 0)
9 *
10*/
317

11
public function unlink_author_from_parent($parent, $id_parent, $id_author)
12
{
13
$where = array(
14
'parent' => $parent,
15
'id_parent' => $id_parent,
16
'id_author' => $id_author
17
);
18
return $this->{$this->db_group}->delete($this->_link_table, $where);
19
}
20

Conclusion
That's it!
We now have a module which manage authors but which also interact with articles!
318

In the next part, we will create some tags to display the authors of each article on the website.

Build one module : Part 4


Quick articles links
Tags introduction- Display the authors- Display authors linked to one article
In this part, we will learn how to create tags for the module and of course use them to display the authors
of each article on the website.
Prerequisites

Ionize installed on one local server (this tutorial is based on the release 0.9.9),
One working website theme. It can be the "demo" default theme or one theme of your choice.

Tags introductionTop of Page


We will not go very deep in the Ionize's tag explanation, the most important to know is that one tag helps
to display data in views.
Each tag is a static method of one PHP tag library and all tags library extends the main "TagManager"
library.
Tags make data retrieving and displaying more easy.
Basic usage
319

In views, tags are used to loop in articles, media or just to display one data.
Example :
1
<ion:articles>
2
<ion:title tag=h2 />
3
<ion:content />
4
<ion:medias type=pictures tag=ul>
5
<li>
6
<img src=<ion:src size='200' /> />
7
</li>
8
<ion:medias>
9
</ion:articles>

In this example, the <ion:articles /> tag loops through articles, and for each article :

displays the title and wraps it in one H2 HTML tag,


displays the content,
320

loops through the article medias if pictures are linked to the article,
display for each found picture one 200px sized picture.

Tag and scope


Tags have a nested structure : Base tags have children tags and these children tags are used in the "scope"
of their parent tag.
For modules, the base tag is the module's folder name in lowercase.
In our example, the module folder is "Demo".
The module tag loader is awaiting for one class called "Demo_Tags" and located in the file
/modules/Demo/libraries/tags.php
The main tag of this module will be <ion:demo />, which is the parent tag for all the other tags of the
module.
Example of tag writing:
1<ion:demo>
2<ion:authors>
3<ion:author field="name" tag="p" />
4</ion:authors>
5</ion:demo>

321

The same code, but more compact :


1<ion:demo:authors:author field="name" tag="p" />
Modules's tags
Modules can:
1. Have their own tags,
2. Extend the core tags by defining new core tags children,
3. Use existing core tags as children if the core tag allows it.
Own tag
One example of module's own tag is "authors", which displays all the authors stored in the DB. This tag
displays data independently from any other tag:
1<ion:demo:authors:author />
Core tags children
When one module tag extends one existing core tag, it becomes usable like a core tag.
In this example, the<ion:authors /> tag is used as children of the <ion:article /> tag.
1 <ion:articles:article>
322

2
3
<ion:title />
4
<!-5
This tag extends the core tag article,
6
by defining authors as children of article
7
-->
8
<ion:authors>
9
<ion:author field="name" />
10
</ion:authors>
11
</ion:articles:article>
12
13
Core tags as children of the module tag
Modules can also use core tags as children of their own tags, if the core tag allows it.
323

<!-- We're here in the "authors" tag context -->


1
<ion:demo:authors>
2
<ion:medias type="picture" />
3
<!-- This core tag is used as children of the module tag -->
4
<img src="<ion:media:src size='80' />" />
5
</ion:medias>
</ion:demo:authors>
Display the authorsTop of Page
Create the tag library
In one module, tags are always located in the file libraries/tags.php
Create the folder :
modules /
Demo/
libraries/
324

Create the file /modules/Demo/libraries/tags.php and write the following code:


1 class Demo_Tags extends TagManager
2 {
3 /**
4 * Tags declaration
5 * To be available, each tag must be declared in this static array.
6 *
7 * @var array
8 *
9 */
10public static $tag_definitions = array
11(
12// <ion:demo:authors /> calls the method tag_authors
13"demo:authors" => "tag_authors",
325

14"demo:authors:author" => "tag_author"


15);
16/**
17* Base module tag
18* The index function of this class refers to the <ion:#module_name /> tag
19* In other words, this function makes the <ion:#module_name /> tag
20* available as main module parent tag for all other tags defined
21* in this class.
22*
23* @usage <ion:demo >
24* ...
25* </ion:demo>
26*
27*/
326

28public static function index(FTL_Binding $tag)


29{
30$str = $tag->expand();
31return $str;
32}
33/**
34* Loops through authors
35*
36* @param FTL_Binding $tag
37* @return string
38*
39* @usage <ion:demo:authors >
40* ...
41* </ion:demo:authors>
327

42*
43*/
44public static function tag_authors(FTL_Binding $tag)
45{
46// Returned string
47$str = '';
48// Model load
49self::load_model('demo_author_model', 'author_model');
50// Authors array
51$authors = self::$ci->author_model->get_lang_list();
52foreach($authors as $author)
53{
54// Set the local tag var "author"
55$tag->set('author', $author);
328

56// Tag expand : Process of the children tags


57$str .= $tag->expand();
58}
59return $str;
60}
61/**
62* Author tag
63*
64* @param FTL_Binding Tag object
65* @return String Tag attribute or ''
66*
67* @usage <ion:demo:authors>
68* <ion:author field="name" />
69* </ion:demo:authors>
329

70*
71*/
72public static function tag_author(FTL_Binding $tag)
73{
74// Returns the field value or NULL if the attribute is not set
75$field = $tag->getAttribute('field');
76if ( ! is_null($field))
77{
78$author = $tag->get('author');
79if ( ! empty($author[$field]))
80{
81return self::output_value($tag, $author[$field]);
82}
83// Here we have the choice :
330

84
85// - Ether return nothing if the field attribute isn't set or doesn't exist
86// - Ether silently return ''
87return self::show_tag_error(
88$tag,
89'The attribute <b>"field"</b> is not set'
90);
91// return '';
92}
93}
94}

Explanation
The property $tag_definitions defines the available tags and their nesting tree.
331

Method

Corresponding
tag

Description

Main module tag.


index

<ion:demo />

This tag must exists to declare the parent scope of all tags of this module.

tag_authors <ion:authors />

Gets all the authors and for each author, set the tag local variable called
"author" to the current looped author.

tag_author <ion:author />

Gets one field from the local variable "author" (this var was set by the
authors tag)

Important :
By convention, we name the function which are tags with the prefix "tag_".
This makes reading the code more easy.
Use the tags in views
We will display all the stored authors on the home page.
Edit the file /themes/demo/views/page_home.php and add the following code:
1<h2>Our Authors</h2>
2<ul>
332

3
<ion:demo:authors>
4
<li><ion:author field="name" /></li>
5
</ion:demo:authors>
6
</ul>
7
This will display the complete authors list.
We're now able to display all the authors stored in our database.
How it works
The <ion:authors /> tag gets the authors from database, using the Ionize model and then send each
author to potential children tags and "expands" the tag.
Let's have a closer look on how it works.
The related method, tag_authors() first declare the string which will be returned. This string will be the
HTML resulting of the expansion of the tag. It is set to an empty string before processing :
1// Returned string
2$str = '';
333

Then, the method loads the model demo_author_model and locally rename it author_model. Because the
class Demo_Tags extends TagManager, Demo_Tags inherits the load_model() method.
1// Model load
2self::load_model('demo_author_model', 'author_model');
To get the authors, we will use the get_lang_list() method. The demo_author_model extends
base_model, which provides this useful method to get data stored in one main table (here
module_demo_author) and its corresponding lang table (module_demo_author_lang). This method
joins the 2 tables and select automatically the current language, so we don't have to care about language.
Once it has the authors data, tag_authors() will "send" each author to the potential children tags.
This is done by setting the author variable :
1$tag->set('author', $author);
Just after that, the tag "expands" itself.
That means it parse and process each child tag. Each child tag method will receive the $tag object and be
able to get the data set by its parent.
If we have 3 authors in the database, the child tag <ion:author /> will be parsed 3 times and the method
tag_author() executed 3 times with 3 different values of $tag->get('author').
1foreach($authors as $author)
2{
3// Set the locals var "author"
334

4
$tag->set('author') = $author;
5
// Tag expand : Process of the children tags
6
$str .= $tag->expand();
7
}
8
This can be a little difficult to understand, but is really essential to build nested tags.
At the end of the tag_authors() method, the whole string $str is returned. In other words, it will be
displayed to the output.
1return $str;
Display authors linked to one articleTop of Page
If you installed the demo data, you have one article called "Welcome to Ionize" on the home page.
First, add some authors to this article using the Ionize backend.
Once you linked some authors, we can go further.
Authors tag behavior
As we saw it, the articles tag loops through articles.
335

Because we want to display the authors of each article, the <ion:authors/> tag must be usable inside the
<ion:article /> tag.
In the file /modules/Demo/libraries/tags.php, modify the static variable $tag_definitions so it looks like :
1 /* Tag declaration
2 * These declaration will overwrite the autoload of tags
3 *
4 * @var array
5 *
6 * @usage "<scope>" => "<method_in_this_class>"
7 * Examples :
8 * "articles:hello" => "my_hello_method"
9 * "demo:authors" => "my_authors_method"
10*/
11public static $tag_definitions = array
12(
336

13"demo:authors" => "tag_authors",


14"demo:authors:author" => "tag_author",
15"article:authors" => "core_article_authors",
16"article:authors:author" => "tag_author",
17);
We have declared 2 tags, children of the <ion:article /> tag :

<ion:authors /> : referring to the method "core_article_authors".


<ion:author /> : Child of the article's "authors" tag, referring to the method "tag_author".

Modify the file /modules/Demo/libraries/tags.php and add the following method :


1 public static function core_article_authors(FTL_Binding $tag)
2 {
3 $str = '';
4 self::load_model('demo_author_model', 'author_model');
5 // Get the article from local tag var :
6 // The 'articles' tag is a parent of this tag and has set the 'article' var.
337

7 $article = $tag->get('article');
8 $authors = self::$ci->author_model->get_linked_author(
9 'article',
10$article['id_article']
11);
12foreach($authors as $author)
13{
14// Set the locals var "author"
15$tag->set('author', $author);
16// Tag expand : Process of the children tags
17$str .= $tag->expand();
18}
19return $str;
20}
338

Use the authors tag inside one article tag


In the view /themes/demo/views/page_home.php, find the comment "<!-- Home Content -->".
Under this comment, you will find the <ion:articles limit="3" type=""> tag.
Within this tag, after :
1<ion:content />
Add :
1<ion:authors>
2<ion:author field="name" tag="p" />
3</ion:authors>
The front-end now displays the authors linked to each article.
Conclusion
In this tutorial, we learned how to create tags for our module and use them inside views.

339

You might also like