Professional Documents
Culture Documents
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
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
Introduction
Extend Fields
Content Elements
Tutorials
User registration,
Build one module
Build one module
Build one module
Build one module
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
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
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
Downloading Ionize
Zip fileTop of Page
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
RewriteCond $1 !^(index.php|themes|install|files|modules|robots.txt)
RewriteRule ^(.*)$ index.php/$1 [L]
8
/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.
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
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=" • "/>
<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
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
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.
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 :
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
<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
Yes
/install
/themes
content medias
Installer program
Theme folder
No
/themes/default
/themes/default/config
/themes/default/helpers
No
/themes/default/views
Website views
No
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" />
</ion:page:articles>
36
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").
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
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
<li>About us</li>
</ul>
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
45
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"
Field
Title
Yes
Page's title
Subtitle
Yes
Page's subtitle
URL
Yes
Windows title
Yes
Options : Attributes
Field
Can be
translated
Default
Description
48
Display in
nav
No
Checked
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
First look for one view called page.php in the website theme
core/page
folder
Single
article
No
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
50
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
Options : SEO
Field
Can be
translated
Description
51
Sitemap
priority
No
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
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
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)
<!-- 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 :
55
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:
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"
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
Field
Can be
translated
Description
Online in
<Lang>
Yes
Title
Yes
Article's title
Subtiutle
Yes
Article's subtitle
URL
Yes
Windows
Yes
Browser's window title, displayed when the article is standalone displayed, for
58
title
Options : Attributes
Field
Default
Description
Indexed
unchecked
If checked, this article will be available for search functionnality (through the search
module)
Categories
Parents
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
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
<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" />
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 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
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
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
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.
66
68
</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
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,
Users
100
This group has no access to Ionize, but can have access to restricted part of the website.
Pending
50
Guest
10
Banned
-10
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 :
72
74
View type
Page
views
Description
Linked to one page through Ionize.
Used to display all pages elements :
Article
views
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.
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 :
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>
› <ion:breadcrumb level="1" />
27
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
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 :
Save
84
</ion:articles>
</ion:page>
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 :
<!-- Displays the title of the page : short write mode -->
<ion:page:title tag="h2">
<!-- Displays the language name and links to the current content for each language -->
<li><ion:language:url /><ion:language:name /></li>
</ion:languages>
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
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 />
<ion:subtitle /
page, article, media
>
<ion:index />
<ion:date />
<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>
<ion:email />
</ion:article:writer>
Special Tags
partialTop of Page
Returns the result of a view used as partial.
1
/themes/your_theme/views/default/header.php -->
2
<ion:partial view="default/header" />
Attribute Optional
Values
view
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>
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
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" />
<!-- Checks the typography with the CodeIgniter's auto_typography helper -->
<ion:article:content helper="typography:auto_typography" />
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 : " />
101
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" />
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
</ion:article:title>
<ion:article:else>
</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>
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
</ion:browser>
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
yes
settingTop of Page
Returns one website setting value
<ion:setting key="theme" />
key
no
meta_titleTop of Page
Displays the window's browser's title of the displayed page.
This title can be set :
Attribute
Optional Values
Description
with_site_title yes
true / false
Default value :
false
position
before / after
Default value :
before
yes
112
separator
yes
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
<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=" • " />
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
<li<ion:is_active> class="active"</ion:is_active>>
</li>
</ion:navigation>
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
menu
yes
helper
yes
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
119
level
yes
depth
yes
menu
yes
yes
helper
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 :
languagesTop of Page
Iterator for languages.
This tag is commonly used to display the languages menu.
<ion:languages tag="ul">
121
</li>
</ion:languages>
Children tags
Tag
Returns
<ion:language:code />
<ion:language:name />
<ion:language:url />
translationTop of Page
<ion:translation term="..." /> is deprecated from Ionize 0.9.9.
122
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
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>
</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 />
</ion:page>
Tag
Usage
<ion:page:title />
Page title
<ion:page:date />
<ion:page:medias />
<ion:page:articles />
<ion:page:next />
<ion:page:prev />
</ion:page:next>
Articles
articlesTop of Page
Iterator tags for articles.
Tag : <ion:articles />
128
</ion:article>
</ion:articles>
129
</ion:page>
Display articles from page named "news"
<ion:page id="news">
<ion:articles >
<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
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
Example
<ion:articles type="side-box">
...
</ion:articles>
<ion:articles limit="3">
...
</ion:articles>
filter
<ion:articles
filter="author='admin'">
131
...
</ion:articles>
Children tags
Tag
Returns
Example
articleTop of Page
Tag : <ion:article />
Can be used in 2 contexts :
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 :
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
User the attribute render="true" so the <ion:article /> tag uses the defined view.
Tag
Returns
Example
<ion:articles>
<ion:article:index />
</ion:articles>
<ion:index />
<ion:date />
Creation date or
Logical date if set in Ionize
<ion:articles>
<ion:article:date format="d.m.Y" />
</ion:articles>
<ion:articles>
<ion:article:content
auto_link="false" />
</ion:articles>
<ion:url />
<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>
to true
<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>
<ion:article:next >
<ion:title tag="span" class="link" />
</ion:article:next>
<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
</ion:medias>
</ion:page:articles>
medias attributes
type
no
extension yes
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
size
yes
<ion:medias type="picture"
size="300" >
<img
src="<ion:media:src />" />
</ion:medias>
method
yes
limit
range
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.
yes
method
yes
Example
<ion:medias type="picture" >
<img src="<ion:media:src
size='300' />" />
</ion:medias>
141
Tag
<ion:src />
Returns
Example
<ion:medias
size="300" />
<ion:media:src />
</ion:medias>
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:media:file_name /
>
<ion:alt />
<ion:media:alt />
<ion:title />
<ion:media:title />
<ion:description/
Description
>
<ion:media:description
/>
<ion:copyright /
>
Copyright
<ion:media:copyright /
>
<ion:link />
<ion:media:link />
<ion:date />
<ion:media:date
format="d.m.Y" />
<ion:media:extension
143
is="jpg">
... displayed if file is
.jpg
</ion:media:extension
>
>
<ion:mime />
<ion:media:mime />
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 :
The square crop preference is set on each picture in Ionize, in the "options" tab of the linked picture.
146
paginationTop of Page
Pagination consist of 3 things :
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
1
2
3
4
5
6
7
3
4
5
6
7
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.
• "/>
</ion:page:articles>
<ion:page:articles>
Number of categories this article is linked to :
<ion:article:categories:count />
</ion:page:articles>
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
Tag
Description
<ion:title />
Example
<ion:category:title />
<ion:category:active_class />
</ion:category:is_active>
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
Tag
Returns
<ion:logged />
Example
<ion:user:logged is="true">
... display this ...
</ion:user:logged>
<ion:user:firstname />
<ion:lastname />
User's lastname
<ion:user:lastname />
<ion:name />
<ion:user:name />
<ion:email />
<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: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 :
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
succeed
</ion:form:my_form:validation:success>
<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 />
<ion:form:my_form:field />
<ion:form:my_form:error />
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" />
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
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
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
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
55
56
// ... Do something here ...
57
}
58
*/
59
}
60
}
61
176
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
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
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
42
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 :
... 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
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 />
<ion:extend:myfield:value />
<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
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 />
<ion:element:myelement:items />
</ion:items>
</ion:element:my-element>
<ion:element:myelement:items:my-field />
<ion:element:myelement:items:index />
<ion:element:myelement:items:my-field:label />
<ion:element:my-element>
<ion:items>
<ion:my-field>
...
</ion:my-field>
</ion:items>
</ion:element:my-element>
<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>
<ion:element:my-element>
<ion:items>
<ion:my-field:label />
</ion:items>
</ion:element:my-element>
<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 />
<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>
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 :
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:
194
Setting
Description
Parent
195
Label
Name
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
Default value
Description
196
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:
200
201
202
203
204
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
28
<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
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
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
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
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
58
59
221
How
How
How
How
How
How
How
How
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)
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
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>
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 :
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
The icon is displaying on the dashboard and the CSS class we added is used in the admin panel of the
module.
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
<sql>
<version>1.0</version>
<!--
Module's tables
-->
10 <tables>
11 <!-12 Author table
240
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
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
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
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
* 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
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
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 :
257
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
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
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
87
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 :
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.
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.
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" :
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 :
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
28
29{
30'confirm': true,
31'message': Lang.get('ionize_confirm_element_delete')
32}
33);
34});
35</script>
*
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
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
On article and page edition panels, they are 3 available module placeholders :
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 :
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
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
296
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 :
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
{
'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
1
2
3
4
We see that the droppable area has the parent code ('article') and the parent ID as HTML attributes.
307
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
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
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
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.
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.
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 :
loops through the article medias if pictures are linked to the article,
display for each found picture one 200px sized picture.
321
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
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
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
<ion:demo />
This tag must exists to declare the parent scope of all tags of this module.
Gets all the authors and for each author, set the tag local variable called
"author" to the current looped 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
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
339