FUEL CMS User Guide : Version 1.3


Simple Modules

Modules in FUEL can range from simple forms to a complex, interactive, multi-page interface. Simple modules don't require additional views and controllers to be created. Common examples of simple modules include events, news and job postings.

For more on creating a simple module, view the user guide's tutorial.

Configuring

A simple module usually contains a single model that maps to a database table (e.g. news). It is recommended that you create your model first (click here for an example). After your model has been created, you can activate and configure the module in the config/MY_fuel_modules.php file like so:

$config['modules']['example'] = array();

This will create a module that maps to the model named example_model and will have the friendly name of Example.

The above could actually be written a longer way as follows:

$config['modules']['example'] = array(
    'module_name' => 'Example',
    'module_uri' => 'example',
    'model_name' => 'example_model',
    'model_location' => '',
    'display_field' => 'name',
    'preview_path' => '',
    'permission' => 'example',
    'instructions' => 'Here you can manage the examples for your site.',
    'archivable' => TRUE,
    'nav_selected' => 'example'
);

Additional Configuration Parameters

Below is a list of all the parameters you can specify to further customize your module. Many of them base their default values on the key value specified in the config (e.g. example):

Preference Default Value Options Description
module_name The default value is a humanized version of the module key (e.g. a key of example = Example) None the friendly name of the module.
module_uri The default is the module key (e.g. example) None the URI path to the module that will appear after fuel.
model_name The default is the module key with the suffix of _model (e.g. example_model) None the name of the model
model_location By default it will look in the application/model folder. If a value is given it will look in the modules/{model_location}/model folder None The module folder location of the model.
view_location By default it will look in the application/views folder. If a value is given it will look in the modules/{view_location}/views folder None the location of the view files
display_field The default is the field name. If you do not have a field of name, you must specify a new field None The model field to be used for display purposes
js_controller The default is BaseFuelController None The name of the javascript controller. If an array is given, then the key of the array is considered the module folder to look in and the value the name of the controller. The js_controller_path will automatically be changed to the module's assets folder if no js_controller_path is provided. For more information on creating javascript controllers, visit the section on the javascript jqx Framework
js_controller_path The default is the path to the fuel module's asset folder (e.g. fuel/modules/fuel/assets/js/ None The base path of where to look for the controller file.
js_controller_params None None Parameters to pass to the jqx controller. They must be in the form of a json object
js None None additional javascript files to include for the module
preview_path None None The URI path to preview the information from the module in the website
views Built in FUEL pages None View files for the list, form and delete pages
permission The default is the module key (e.g. example) None The name of the permission that users must be subscribed to to have access to the module.
edit_method The default is find_one_array filtered on the id value passed to the form None The model's method to retrieve the information to edit.
instructions None None The instructions to provide users when creating or editing
filters None None Fields to filter the values in the list view
archivable TRUE Boolean Value TRUE/FALSE Saves to the archive table for later retrieval if you need to revert back
table_actions EDIT, VIEW, DELETE None The actions per row to include in the table view
item_actions save, view, publish, activate, delete, duplicate, create save, view, publish, activate, delete, duplicate, create, others The form level actions to include in the toolbar. The others action is a key / value array with the key being the FUEL URI and the value being the button label. It can be used to create additional custom buttons. Each button will submit the form information on the page to the link path of the button.
list_actions None None Other HTML to be displayed at the top above the list table
rows_selectable TRUE Boolean Value TRUE/FALSE A boolean value that will set the whole row to be clickable
precedence_col precedence None The name of the column to contain the custom precedence sorting information
clear_cache_on_save TRUE Boolean Value TRUE/FALSE Clears the cache upon saving new or updated values to a record
create_action_name Create None The name of the button to be used for creating an item
configuration None None Additional configuration files to load
nav_selected None None The left navigation item to be selected
table_headers None None The columns to use for the table view
default_col The default is the second column of the table (e.g. the one normally after the id column) None The default field to sort on
default_order asc asc, desc The default field ordering
sanitize_input TRUE Boolean TRUE/FALSE, string of "xss", "php", "template" OR "entities", OR an array for multiple values e.g. array('xss', 'php', 'template', 'entities'). See the FUEL configuration for changing the different sanitization callbacks. Cleans the input before inserting or updating the data source
sanitize_files (was sanitize_images) TRUE Boolean Value TRUE/FALSE uses xss_clean function on images
displayonly None Boolean Value TRUE/FALSE Will only display the data and not allow you to save it
language None None Additional language files to load
language_col language None The column name that contains the language key value
hidden FALSE Boolean Value TRUE/FALSE If set to TRUE, it will hide the module in the admin menu
disabled FALSE Boolean Value TRUE/FALSE If set to TRUE, it will hide the module in the admin menu as well as show a 404
icon_class None None The CSS icon class to associate with the module
folder None None The advanced module folder in which it lives in
exportable FALSE Boolean Value TRUE/FALSE Will display an "Export" button on the list view page that will allow users to export the currently filtered list data
limit_options array('25' => '25', '50' => '50', '100' => '100') array The "Show" options displayed in the list view
advanced_search FALSE Boolean Value TRUE/FALSE If TRUE, this will display model filters in an advanced search menu
disable_heading_sort FALSE Boolean Value TRUE/FALSE If TRUE, this will disable heading sorting on the list view
description None None A description value that can be used in the site docs
pages array None Can automatically generate pages for your module including list pages, detail pages, related category and tag pages, search pages and your own custom pages. Leverages by default the fuel/application/views/_posts/ view files but that can be overwritten.
'pages' => array(
'base_uri' => 'media',
'layout' => 'posts',
'list' => 'media/list',
'post' => 'media/detail',
'archive' => array('route' => 'media/archive(/$year:\d{4})(/$month:\d{1,2})?(/$day:\d{1,2})?', 'view' => 'media/list', 'layout' => 'main', 'method' => 'my_test_method', 'empty_data_show_404' => TRUE),
'tag' => array('route' => 'media/tag/($tag:.+)', 'layout' => 'main', 'view' => 'media/list', 'empty_data_show_404' => TRUE),
'custom' =>array('route' => 'media/custom', 'view' => 'media/list', 'method' => 'my_custom_method'));

The Model

The module's model is the most important piece of a module. It is what drives the the saving, form and extra interactions needed for the module to work. A module should extend the abstract Base_module_model class which is a child of the MY_Model class and is found in the modules/fuel/model folder. Custom record object should extend the Base_module_record

There are several methods that you can add/overwrite to give you greater functionality for your module (view the tutorial for more information).

Additionally, there are several hooks you may want to use that allow you to insert functionality during the saving and deleting process of a modules record.

The Views

Simple modules are made up of several views:

Filtering the List View

The list_items() method provides some ways to make it easier to search and filter your list results. By default, a simple module comes with a single search field that will use the module's display_field configuration parameter to search in. If you want the primary search field to be different then the display_field, you must specify the search_field parameter in the module's configuration (most of the time, these will be the same so you will not need to use the search_field configuration).

$config['modules']['articles'] = array(
	...
	'display_field' => 'title',
	'search_field' => 'content',
	...
);

To search in multiple fields, use the module model's filter property as shown here:

	public $filters = array('title', 'slug', 'content');

Filtering Form Fields

If a single search field isn't enough, you can specify a form using the Form_builder array syntax in the module's configuration:

$config['modules']['articles'] = array(
	...
	'filters' => array(
			'post_date' => array('type' => 'datetime'),
			'published' => array('type' => 'enum', array('yes', 'no')),
			),
	...
);

Or, you can create a filters() method on the module's model like so to create the form fields:

public function filters()
{
	$fields['post_date'] = array('type' => 'datetime');
	$fields['published'] = array('type' => 'enum', array('yes', 'no'));
	return $fields;
}

Operator Suffixes

The default operator is LIKE %{term}% however, you can use the following suffixes for your filter names to use different operators:

public function filters()
{
	$fields['post_date_to'] = array('type' => 'datetime');
	$fields['post_date_from'] = array('type' => 'datetime');
	return $fields;
}

Additionally, using _having will perform a having condition on the SQL which is helpful for filtering on values generated in the SELECT of the SQL.

Advanced Search

The filter fields will by default be put to the left of the search box. However, if you have a lot of filter fields that area will get crowded quickly. To help with this issue, there is an advanced_search module configuration that can have the following values:

$config['modules']['articles'] = array(
	...
	'advanced_search' => 'collapse',
	...
);

AND & OR

The SQL generated will by default use "OR". To use "AND", change the module model's filter_join property like so:

	public $filter_join = 'and';

To combine AND and OR, you can use an array like so:

	public $filter_join = array('title' => 'or', 'content' => 'or', published' => 'and');

Joins

Often, you'll need to join one or more tables together. You can use CodeIgniter's active record and add it to the list_items method like so:

public function list_items($limit = NULL, $offset = NULL, $col = 'statement_date', $order = 'asc', $just_count = FALSE)
{
	$this->db->join('fuel_categories', 'fuel_categories.id = articles.category_id', 'LEFT');
	$this->db->select('articles.id, article.title, fuel_categories.name as category, articles.published');
	$data = parent::list_items($limit, $offset, $col, $order, $just_count);
	return $data;
}

Or you can add a _common_joins() method (new to 1.3). The _common_joins method will be used for all "find_", options_list and list_item methods on the module's model.

public function _common_joins()
{
	$this->db->join('fuel_categories', 'fuel_categories.id = articles.category_id', 'LEFT');
}

Sometimes joins will require you to prefix the field with the table name. Periods can be problematic so you can substitute it using a ":".

public function filters()
{
	$fields['fuel_categories:name'] = array('label' => 'Category name');
	$fields['post_date_to'] = array('type' => 'datetime');
	$fields['post_date_from'] = array('type' => 'datetime');
	return $fields;
}

Friendly Filter Text

When multiple filters are being used to filter the list view, there is friendly text that appears above the list as of 1.3. This is controlled by the Base_module_model::friendly_filter_info() method. To alter the returned value you can simply overwrite this method in your module's model.

Remember, you can always simply just overwrite the list_items() method on the module's model with your own logic to filter the results.

Module Overwrites

Module overwrites allow for you to overwrite existing module parameters. For example, if you'd like to overwrite the built-in FUEL fuel_pages_model to incorporate your own model hook you've added to the MY_pages_model, you can do so like so:

$config['module_overwrites']['pages']['model_name'] = 'MY_pages_model';

Generated Post Pages

New to FUEL CMS 1.3 is the ability to create post type pages automatically from your modules. This is a very powerful feature that allows you to map routes to post pages that have specific behaviors. This means each module can now have blog like features (minus the commenting). It uses the Fuel_posts class to do so. There are a number of types of pages automatically created for you (basically the ones we were tired of creating over and over again) including, slug, archive, list, post, tag and archive pages. For example, if you have a module's model that has a foreign_key property to the fuel_categories_model and a has_many to the fuel_tags_model, tag and category pages can be automatically generated using the pages parameter. To make it easier, there is a Base_posts_model class that your module's model can inherit from (which already inherits from the Base_module_model class).

Below is an example of an "articles" module with the pages parameter being used in a module's configuration:

The articles SQL:

CREATE TABLE `articles` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  `slug` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  `content` text COLLATE utf8_unicode_ci NOT NULL,
  `excerpt` text COLLATE utf8_unicode_ci NOT NULL,
  `image` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  `featured` enum('yes','no') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'yes',
  `publish_date` datetime NOT NULL,
  `category_id` int(10) unsigned NOT NULL,
  `published` enum('yes','no') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'yes',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

The module's model (note that it inherits from the Base_posts_model):

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

require_once(FUEL_PATH.'models/base_posts_model.php');

class Articles_model extends Base_posts_model {

	public $name = 'articles';

	
	function list_items($limit = NULL, $offset = NULL, $col = 'publish_date', $order = 'desc', $just_count = FALSE)
	{
		// add any $this->db->select('....') or $this->db->join(...) here
		$data  = parent::list_items($limit, $offset, $col, $order, $just_count);
		return $data;
	}
	
	function form_fields($values = array(), $related = array())
	{	
		$fields = parent::form_fields($values, $related);
		
		// put in your own specific code to manipulate the fields here
		return $fields;
	}
}

class Articles_item_model extends Base_post_item_model {

}

The following global page parameters can be used with the pages parameter for your module:


Additionally, each slug, archive, list, post, tag and archive page can have it's own parameters specified like so:


Lastly, you can of course create your own custom set of pages generated by your module and are not limited to the default. To do this, take advantage of the method parameter and specify a method on your model to generate the data you want to pass to your view and specify a relevant route parameter.

Below is an example of the pages parameter being used in a module's configuration with an example of a way to define "custom" generated pages:

...
'pages' => array(
	'base_uri' => 'media',
	'per_page' => 10,
	'layout' => 'posts',
	'list' => 'media/list',
	'post' => 'media/detail',
	'archive' => array('route' => 'media/archive(/$year:\d{4})(/$month:\d{1,2})?(/$day:\d{1,2})?', 'view' => 'media/list', 'layout' => 'main', 'method' => 'my_test_method', 'empty_data_show_404' => TRUE),
	'tag' => array('view' => 'media/list', 'empty_data_show_404' => TRUE, 'per_page' => 5),
	'custom' => array('route' => 'media/custom', 'view' => 'media/list', 'method' => 'my_custom_method')
),
...

Separate Classes for Model Logic

For larger models, things like the form_fields method and the validation logic and even the related items area can become a bit much to have in one model. FUEL 1.3 added the ability to inherit from three new classes to make it easier to separate that logic out. To add this functionality, there are now three new properties that can be utilized on a module model:

public $list_items_class = '';  // a class that can extend Base_model_list_fields and manipulate the list_items method
public $form_fields_class = '';  // a class that can extend Base_model_fields and manipulate the form_fields method
public $validation_class = ''; // a class that can extend Base_model_validation and manipulate the validate method by adding additional validation to the model
public $related_items_class = ''; // a class that can extend Base_model_related_items and manipulate what is displayed in the related items area (right side of page)

Custom Classes

All custom classes come with the following methods that can be used with the class

Custom List Items Class

To create your own custom form fields class, specify the class name for the model's $list_items_class property, and then create a class that inherits from Base_model_list_items (see below). In the initialize method, you can specify your field logic or even break it out into additional methods to keep it better organized. The example below does this and creates separate "Info" and "Meta" tabs.

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

require_once(FUEL_PATH.'models/base_module_model.php');

class Articles_model extends Base_module_model {
	...
	public $list_items_class = 'Article_list_items';  // a class that can extend Base_model_list_items and manipulate the list_items method
	...
}

// --------------------------------------------------------------------

class Article_model extends Base_module_record {
	
	// put your record model code here
}

// --------------------------------------------------------------------

class Article_fields extends Base_model_list_items {

	public function fields($values = array())
	{
		$f = $this->get_parent_model()->form_fields();
		$fields =& $this->fields;

		$fields['title'] = $f['title'];
		$fields['slug'] = $f['slug'];
		$fields['category_id'] = $f['category_id']
		$fields['publish_date_from'] = array('type' => 'date');
		$fields['publish_date_to'] = array('type' => 'date');
		return $fields;
	}

	public function process($data)
	{
		foreach($data as $key => $val)
		{
			$data[$key]['title'] = htmlentities($val['title']);
		}
		return $data;
	}
}

The Base_model_list_items class provides the follow additional methods:

Custom Form Fields Class

To create your own custom form fields class, specify the class name for the model's $form_fields_class property, and then create a class that inherits from Base_model_fields (see below). In the initialize method, you can specify your field logic or even break it out into additional methods to keep it better organized. The example below does this and creates separate "Info" and "Meta" tabs.

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

require_once(FUEL_PATH.'models/base_module_model.php');

class Articles_model extends Base_module_model {
	...
	public $form_fields_class = 'Article_fields';  // a class that can extend Base_model_fields and manipulate the form_fields method
	...
}

// --------------------------------------------------------------------

class Article_model extends Base_module_record {
	
	// put your record model code here
}

// --------------------------------------------------------------------

class Article_fields extends Base_model_fields {

	public function initialize($fields = array(), $values = array(), $parent_model = NULL)
	{
		$fields =& $this->fields;

		$this->set_label('title', 'Headline');
	
		$this->remove(array('date_added'));

		$this->info_tab();
		$this->meta_tab();
	}

	public function info_tab()
	{
		$info_fields = array('title', 'slug', 'content', 'excerpt', 'image');
		$this->tab('Info', $info_fields);
	}

	public function meta_tab()
	{
		$meta_fields = array('tags', 'category_id');
		$this->tab('Meta', $meta_fields);
	}
}

The Base_model_fields class provides the follow additional methods:

Note that in the example above the various ways to conveniently set field properties using the "set_" magic method. You can mass assign values to multiple fields. Below is an example of how to hide multiple fields at once:

	$this->set_type(array('field1', 'field2'), 'hidden');

Additionally you can specify a single property by passing an array:

	$this->set_comment(array('field1' => 'Comment 1', 'field2' => 'Comment 2'));

Lastly, you can just create a single field value using just the set method:

	$this->set('field1', array('label' => 'Field 1 label', 'type' => 'textarea'));

Custom Validation Class

A custom validation class is convenient for separating your model validation logic outside of your model class. The following are additional methods that can be used on the validation class:

Custom Related Items Class

The custom relatd items class can be used to display information that appears to the right of the form fields.

...
class Article_related_items extends Base_model_related_items {

	public function initialize($values, $parent_model)
	{
		// if view is in an advanced module
		$this->view(array(MY_MODULE_FOLDER => '_admin/article_related_items'));

		// OR ... if view is in the main application folder
		$this->view('_admin/article_related_items');
	}
}