Developers Guide

Including

Introduction

Forena implements custom hooks to allow the report engine to be extended in many ways. Forena does use OOP methodologies, but also leverages the observer pattern so prevalent in Drupal.

There is then a common pattern that is used to extend Forena:

  1. Implement a custom php class that lives in your module directory. You may extend any of the Forena classes, or write your own from scratch.
  2. Implement the expected registration methods in your class (e.g. templates, formats).
  3. In your module implement a hook (e.g. mymodule_forena_controls) that tells Forena the location of your class definition file.

Forena Hooks

hook_forena_controls

This hook defines controls that are always loaded during Forena. The most common uses are for implementing custom field formatters or templates. This hook should return an array of control definitions. Each control definition is represented as an associative array of the following key/value pairs.

class The name of the control class provided by the module
file The filename to include prior to instantiating the class

Forena uses its own mechanisms for advertising its controls. The following can be used as a reference implementation for this hook.

function forena_forena_controls() { 
  $controls[] = array('file' => 'plugins/FrxControls.inc', 'class' => 'FrxControls'); 
  return $controls; 
  }

hook_forena_plugins

This hook defines custom data providing plugins for Forena. The most common use is for implementing custom XML data repository types, but they can also be used for defining formatting functions that are specific to a data provider type. Like hook_forena_controls, this hook should return an array of plugin definitions. Each control definition is represented as an associative array of the following key/value pairs.

class The name of the plugin class provided by the module
file The filename to include prior to instantiating the class

Forena uses its own mechanisms for advertising its controls. The following can be used as a reference implementation for this hook.

function forena_forena_controls() { 
   $controls[] = array('file' => 'plugins/FrxControls.inc', 'class'=> 'FrxControls', ); 
   return $controls; 
}

hook_forena_repos_alter

Use this hook to advertise your own data connections and data blocks to be delivered by a custom module. Use the following implementation as a sample:

function myexample_forena_repos_alter(&$repos) {
  $m_path = drupal_get_path('module', 'myexample'); 
  $repos['myexample'] = array(
    'path' => $m_path . '/data',
    'title' => 'My Sample repository',
    'access callback' => 'user_access',
    'user callback' => 'forena_current_user_id', 
    'data provider' => 'FrxDrupal', 
  );
  }
  

In this sample, the module would provide custom SQL data blocks that access data from the drupal default database. Data would be referenced in the report using frx:block="myexample/myblock". The SQL files for this block would be in the data/myblock.sql file. The data blocks would use drupal security and the :current_user parameter in any data block would be populated with the uid of the current drupal user.

hook_forena_report_directory

Use this hook to advertise module provided report include directories. Use the following as a sample implementation:

function myexample_forena_report_directory() {
      return drupal_get_path('module', 'myexample') . '/reports';
}

In the above example any reports defined in the modules 'reports' directory would also be displayed.

hook_forena_parameters_alter

This alter hook allows you to alter the incoming parameters for any report, but also to provide additional data contexts that can be made available in your reports. A simple implementation follows:

function myexample_forena_parameters_alter($report_name, &$parms) { 
  // Set a data context for use in reports 
  $sec['admin'] = user_access('access administration pages') ? 'Y' : ''; 
  Frx::Data()->setContext('security', $sec); 
}

In the above example, you would be able to reference :security.admin in any data block or {security.admin} to reference a value of 'Y' whenever the user had access to Drupal's access administration pages right.

hook_forena_data_alter

This alter hook allows you to alter the data retrieved by any forena data block before it gets passed back to the reporting engine. A simple implementation follows:

  function myexample_forena_data_alter(&$data, $context) {
  if ($context['provider'] == 'sampledb' && $data ) {
    foreach($data as $row) {
      $row->mydata = 'foo';
    }
  }
  }

hook_forena_context

Advertise custom context objects that are loaded on demand. The hook should advertise classes that can be used for token replacement in either report contexts or data blocks. Contexts should extend \FrxContextBase

  function myexample_forena_context() {
    $m_path = drupal_get_path('module', 'myexample');
    $context['mycontext'] = array(
      'class' => 'MyCustomContextClass',
      'file' => "$m_path/MyCustomContextClass.inc"
    );
  }
  

The above example allows modules to be able to use to reference public properties of a MyCustomContextClass object instance. The constructor is called and the object is instantiated on first use of the context. See context/FrxContextBase.inc for additional information on methods that are called by this calss.

Custom Formatters

Custom formatters may be implemented either in control objects or in data plugin objects. Formatters that are implemented in plugin objects are only available within data blocks that reference data block repositories that use that plugin type. For example, formatters defined by the FrxOracle plugin will only be available fore repositories that are Oracle repositories. Formatters defined in FrxControls, however, will be available in all reports.

To implement a formatter in control or plugin class requires the implementation of two methods.

Formatter Methods

Formatter methods should take a value and a format string parameter, and should return the formatted value. The following function can be used as a reference implementation of a formatter function.

public function iso_date($value, $format_str) {
  if ($value) $date = strtotime($value);
  return $this->drupal_date_format($date, $format_str);
}

Formats Registration Function

Each class that implements formatters should also implement a formats registration function that returns an associative array that lists the function names and their appropriate user label. Forena uses its own registration mechanisms for advertising its controls. The following can be used as a reference implementation for this method.

//date formats
public function formats() {
  $formats = array('drupal_date_format' => 'Drupal Date',
                   'iso_date' => 'ISO Date',
                   );
  return $formats;
}