FOSP For Developers Part 3: Build a custom module step 1

Building modules on the ootp open web platform is a fast way to get right to building the type of tool you want to create. For the third part of the oowp developer tutorials, I am going to demonstrate this by creating a simple custom Team Stats Listing module that will have:

  • An admin dashboard settings page to manage a single yes/no option
  • Permissions that will restrict access to the settings page to only the site admin
  • A public page that displays team information, batting and pitching stats for a single team and season.

The Bonfire library provides a standard workflow to help us accomplish this effort. We are going to start with the Admin Dashboard portion first as we’ll want our optional setting in place before we start to code the front end portion.

To follow along with this tutorial you’ll need a working copy of the OOWP setup on a web server. You can view the completed StatsList module on the nablleague.com demo site, but you will not be able to complete the steps listed in this exercise.


One of the first basic rules of the Bonfire admin dashboard is that if you want a tool to appear listed under one of the dashboard contexts menu, you need to have two things:

  • controller placed in the bonfire/modules/[MODULE NAME]/controllers folder named to match the context you wish to place it in.So if you want an option to appear in the Settings context menu, you would put a controller called settings.php that extends the Admin_Controller class in your controller’s folder.
  • view file (or files) inside a folder named to match the context within the bonfire/modules/[MODULE NAME]/views folder. Each view file should be named match the names of the functions within the context controller file.So for example if you have a function index() in the above mentioned settings.php controller, you should have a view called index.php in the views/settings folder as well. There is a way to manually change this, and I’ll demonstrate it later.

Another important rule to note is that modules that will have content that is accessible from the public side of the site (URL requests without the “admin” portion of the path) should have a controller that extends the Front_Controller class and be named to exactly match the module name.

So if we wanted to visit our module via a www.sitename.com/statslist/ URL, we would need a controller named statslist.php in the controllers folder. The same rule for views applies as above and there should be view files to match each function name in that public accessible controller (I.E. index.php for an index() function, liststats.php for a liststats() function and so on). Don’t worry about this so much though as we’ll cover this portion more in depth in part 2, however.

Let’s dive into our example module to demonstrate how this all works from a practical standpoint.


For this example, we will use Bonfires built in Module Builder tool.

NOTE: The module builder is not the “be all/end all” tool for module creation as it’s more suited to building content driven modules like my Bonfire News module, but I’ll use it here to demonstrate what it spits out. For some cases copying existing modules can provide the right start for your project.

To access and use the Module Builder Tool:

  • Login to the admin dashboard and click Developer ->; Module Builder.
  • On that page click the New Module button in the top right nav bar.
  • On the Module Builder page, enter the ID “StatsList”.
  • Click the Toggle Advanced Options link to show the options.
  • In the description field, enter “A simple stat display module”.
  • Under Contexts Required, check Public and Settings.
  • Scroll down and click Build the Module.

If all went well, Bonfire should have created a new module for you.


So Bonfire has spit out a new module for us. Problem is, it is only the skeleton, not a working module yet. So we need to add some custom code to it to get it working.

So if the module builder doesn’t get the module working, why use it? Well, each class used by the module has a particular setup in terms of where it gets placed in the folder hierarchy and what it extends from the Bonfire library. The Module Builder class takes care of all these small details so that you can begin working on your custom functionality right away. It’s good to know what is what and where it all goes, and a quick module created by the module builder can help provide an example of this and save some up front headaches for you as you become familiar with the process.

Open your FTP client, browse to the bonfire/modules folder on your web server and download the “statslist” folder to your local computer. Select your code editor of your choice and open the “bonfire/modules/statslist/” directory.


Let’s now edit the modules Migration file.

  1. Open the file bonfire/statslist/migrations/001_Install_statslist_permissions.php.
  2. In the up(), or database upgrade function, add the following code:
    // permissions
    $data = array(
    	'name'        =>; 'OOLM.StatsList.Manage' ,
    	'description' =>; 'Manage OOTP Team Stats Settings'
    $this->;db->;insert("{$prefix}permissions", $data);
    $permission_id = $this->;db->;insert_id();
    $this->;db->;query("INSERT INTO {$prefix}role_permissions VALUES(1, ".$permission_id.")");

    This code:

    • Creates a new permission called OOLM.StatsList.Manage (lines 2-5)
    • Inserts it into the permissions table (line 6)
    • Grabs the permissions index number (line 8)
    • Assigns the permission to the site admin (user index 1, line 10).
  3. Below that, we add this code:
    // Default Settings
    $default_settings = "
    	INSERT INTO `{$prefix}settings` (`name`, `module`, `value`) VALUES
    	('statslist.limit_to_primary', 'statslist', '1');

    This adds a new setting called “statslist.limit_to_primary” to the Bonfire settings table and assigns a default value of 1 (which equals true as we’ll see later on).

  4. Now in the down() function, add the following code:
    // permissions
    $query = $this->;db->;query("SELECT permission_id FROM {$prefix}permissions WHERE name = 'OOLM.StatsList.Manage'");
    foreach ($query->;result_array() as $row)
    	$permission_id = $row['permission_id'];
    	$this->;db->;query("DELETE FROM {$prefix}role_permissions WHERE permission_id='$permission_id';");
    //delete the permission
    $this->;db->;query("DELETE FROM {$prefix}permissions WHERE (name = 'OOLM.StatsList.Manage')");
    $this->;db->;query("DELETE FROM {$prefix}settings WHERE (module = 'statslist')");

    This block essentially undoes everything we did in the up() function by querying for and removing the StatList manage permission and deleting all statslist module settings from the Bonfire Settings table.

  5. Save the migration module and close it.


We will now add a page where an admin can limit the list of teams to choose from on the modules public page to only the primary league (specified in the OOTP League Manager settings page) or all leagues in the database. We will do this by creating a custom admin settings page.

If you remember our Bonfire context rules above, you know we do this by editing the settings controller and the settings/index.php view file.

The Settings Controller

    • Open the file bonire/modules/statslist/controllers/settings.php.
    • Edit the _construct() function to match the following code:
      public function __construct()
      	 if (!class_exists('Activity_model'))
                  $this->;load->;model('activities/Activity_model', 'activity_model', true);

      Here we are:

      • Creating the basic class constructor and calling up to the parent controller _construct function (line 3)
      • We then assure we have the right permissions to access this class (line 5)
      • Load the Bonfire Activity Model to log actions (lines 6-9)
      • Load the statslist language file (line 11).
The module builder generates a default English language file which enables easy translations of your sites content into other languages. We’ll visit that language file a little further down.
  • Under the _construct function, create a new public function called index() and paste the following code:
    public function index()
    	if ($this->;input->;post('submit'))
                if ($this->;save_settings())
                    Template::set_message(lang('sl_settings_saved'), 'success');
                    Template::set_message('There was an error saving your settings.', 'error');
    	Template::set('settings', $this->;settings_lib->;find_all_by('module','statslist'));
    	Template::set('toolbar_title', lang('statslist_manage'));

    This function:

    • Checks if we’ve submitted a form (using the CodeIgniters input->;post object to look for the submit field) and if so, calls the save_settings() function. Otherwise it skips the section entirely. (line 3)
    • It then sets a success or error message to the view Template object. (Lines 5-14)
    • It loads and applies a settings variable to the template containing the settings value that either already exists or was just applied (Lines 16-17)
    • Selects a view file using a path relative from the “bonfire/modules” folder (line 18)
    • Renders the template to the user using the Bonfire Template::render() function. This is the standard way to generate the HTM output back to the browser. (Line 19)
  • Let’s stop with the settings for one moment and open the English language file mentioned earlier (“statslist/language/english/statslist_lang.php”). The language files are simply key/value pairs that enable for the substitution of content for non-English languages. The Module Builder generates a number of default strings for us, but we are going to delete the contents and replace it with the following code which adds strings that will be used in our settings controller and view.
    ;Go; to continue.';

    Save the changes but leave the file open, just in case we think of any more strings to add.

  • Return to the settings.php file and replace the module builder generated save_settings() function with the following code:
    private function save_settings()
            $this->;form_validation->;set_rules('limit_to_primary', lang('sl_limit_to_primary'), 'numeric|trim|strip_tags|maxlength[1]|xss_clean');
            if ($this->;form_validation->;run() === false)
                return false;
    		$data = array(
            array('name' =>; 'statslist.limit_to_primary', 'value' =>; ($this->;input->;post('limit_to_primary') ? $this->;input->;post('limit_to_primary') : 0)),
            //destroy the saved update message in case they changed update preferences.
            if ($this->;cache->;get('update_message'))
                if (!is_writeable(FCPATH.APPPATH.'cache/'))
            // Log the activity
            $this->;activity_model->;log_activity($this->;auth->;user_id(), lang('sl_settings_saved').': ' . $this->;input->;ip_address(), 'StatsList');
            // save the settings to the DB
            $updated = $this->;settings_model->;update_batch($data, 'name');
            return $updated;

There’s a bunch happening here, but it’s pretty straightforward.

  • We load the CodeIgniter form validation library
  • Set a validation test and run the form validation.
  • If it fails, we return false. If not, we create a new $data array variable and add a name/value pair to update the database using the settings name we defined in our migration and the form field value from the CodeIgniter Input->;Post object.
  • We then wipe any previous update messages from the cache
  • Log the action in the activity log
  • Update the settings table via the settings_models->;update_batch function
  • Return the result of that function call (True or False).

And that’s it. We now have a settings controller and English language file setup. You can save the controller file and close it.

The Settings View

Now it’s time to create the file that will serve to draw the actual form the admin will use in the dashboard. Since CodeIgnitner separates the display logic from the page logic, this code is defined in the modules views folder. And following Bonfire context conventions, any views that will be used by out settings controller, must be stored in a settings folder. OK, less talk, more code.

If it doesn’t already exist, create the file statslist/views/settings/index.php.

Paste the following code below into the file.

uri->uri_string(), 'class="form-horizontal"'); ?>

This view file is almost pure HTML markup. It also utilizes the Twitter Boostrap library for much of the structure and CSS classes that are defined. So let’s break it down:

  • Lines 1-5 deal with displaying form validation errors if they are found on form submission. This block is standard to most Bonfire settings and form modules.
  • On Line 7 we define the Admin Box class which is what our form will be displayed in.
  • On Line 9 we add the box title (displayed as a blue header bar) in an H3 using one of the strings from out English statslist_lang.php file.
When using CodeIgniter by itself, you would use $this->;lang->;line(‘string_name’) to pull a string from the lang libraries. The Bonfire team created the langshortcut helper function to shorten the call down to just lang(‘string_name’).Thanks guys!
  • On Line 11 we defined the form via the CodeIgniter form_open function from the form helper file
  • Defined inside the fieldset tags is the forms label and check box controls. They are wrapped in a block of div classes bootstrap will recognize and let us apply error messaging and styles in case of an invalid submission.
  • The form-actions class block adds the Save and Cancel action buttons and links
  • On the last line we use the CodeIgniter form_close() function to finish the form.


At this point, you can save and then upload your module code back to your server. To use our new settings page, we browse to the Dashboard, click Developer ->; Database Tools ->; Migrations and then click the Modules tab.

  • If the Installed Version for StatsList matches the Latest Version, Assure “Uninstall” is displayed in the drop down and click the Migrate Module button.
  • Choose the modules tab again and choose the “001_Install_statslist_permissions.php” migration file and click Migrate Module again.
  • On the dashboard top nav, click Settings ->; StatsList. You should see a screen similar to the screen grab below.
  • You can now edit the Limit to Primary League value and save it.

And that will do it for the first part of building our own custom module. I hope this wasn’t too terrible an initial walk-through. But in a short amount of time we:

  • Created a module skeleton with the Module Builder
  • Downloaded the code
  • Edited the migration to add admin only permissions to manage the settings and add a setting to the database
  • Edited the settings controller to handle a form submission and save the setting choice
  • Created a view file with the HTML needed to draw the settings form in the Bonfire look and feel

You can view the completed settings demo by logging onto the OOWP demo site, NABL League and using the username and password demo. You can also look at the complete source code for the module on the projects Github page.

Good news is we’re now half of the way done. In the next part of the tutorial, we finish off the module with a public view file that will access three standard Open Sports Toolkit data models to draw our page of team player stats.

Download the FOSP Today!
Download the latest stable release version from the official FOSP web page. All the documentation you need is available in the installation and setup guide.

Contribute to the development and help the FOSP grow
The FOSP is a 100% free and open source project. The source code is publicly available on GitHub.com. If you want to contribute to the development, simply head over to my official Github page, fork the related projects, hack the code and send pull request with your updates. It’s that simple.

If you’ve built an FOSP module let me know and I’ll add it to the "Built on the FOSP" list.

Want to help test?
Testing assures everything works as expected and that everyone gets the best fantasy experience possible. Simply download and test the site and log issues on the official Github issues pages. Each portion of the site has its own page and issues list so be sure to log the issue in the appropriate module portion of the site.

While the FOSP is free to download and use, we do very much appreciate any donations made towards its development.


Jeff Fox is an over twenty-year web developer and digital user experience technology leader. Jeff cut his teeth in the Web's early days and is mainly self-taught in his professional skills. Having worked for a broad number of companies has helped build skills in development, organization and public speaking. In addition to being a passionate developer and technical speaker, Jeff is a dedicated tech and sci-fi geek gladly indulging in Doctor Who and Star Wars marathons. He is also a talented musician, writer and proud father of three little Foxies. And don't get him started about his San Francisco Giants.

One Comment

Leave a Reply

Your email address will not be published.


This site uses Akismet to reduce spam. Learn how your comment data is processed.