You are here

forena.module in Forena Reports 6.2

File

forena.module
View source
<?php

/**
 * Implementation of hook_menu.
 *
 * @return array
 */
function forena_menu() {
  $items = array();
  $items['admin/build/reports'] = array(
    'type' => MENU_NORMAL_ITEM,
    'title' => 'Forena Reports',
    'description' => 'Build reports based on data in your sites databases.',
    'page callback' => 'forena_admin_reports',
    'access arguments' => array(
      'design any report',
    ),
    'file' => 'forena.admin.inc',
  );
  $items['admin/settings/forena'] = array(
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'forena_settings',
    ),
    'title' => 'Forena Reports',
    'description' => t('Tell Forena where to store report files and how users should access them.'),
    'access arguments' => array(
      'administer forena reports',
    ),
    'type' => MENU_NORMAL_ITEM,
    'file' => 'forena.admin.inc',
  );
  $items['admin/settings/forena/general'] = array(
    'title' => 'General',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'file' => 'forena.admin.inc',
    'weight' => -10,
  );
  $items['admin/settings/forena/data/configure'] = array(
    'title' => 'Configure data source',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'forena_data_settings_edit',
    ),
    'type' => MENU_CALLBACK,
    'file' => 'forena.admin.inc',
    'access arguments' => array(
      'administer forena reports',
    ),
  );
  $items['admin/settings/forena/data/add'] = array(
    'title' => 'Add data source',
    'type' => MENU_CALLBACK,
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'forena_data_settings_edit',
    ),
    'file' => 'forena.admin.inc',
    'access arguments' => array(
      'administer forena reports',
    ),
  );
  $items['admin/settings/forena/data'] = array(
    'title' => 'Data',
    'page callback' => 'forena_data_settings',
    'type' => MENU_LOCAL_TASK,
    'file' => 'forena.admin.inc',
    'access arguments' => array(
      'administer forena reports',
    ),
  );
  $items['admin/settings/forena/js'] = array(
    'page callback' => 'forena_settings_js',
    'access arguments' => array(
      'administer forena reports',
    ),
    'file' => 'forena.admin.inc',
    'type' => MENU_CALLBACK,
  );
  $items['admin/settings/forena/formats'] = array(
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'forena_doc_formats_settings',
    ),
    'title' => t('Document Types'),
    'access arguments' => array(
      'administer forena reports',
    ),
    'type' => MENU_LOCAL_TASK,
    'file' => 'forena.admin.inc',
  );
  $items['reports/%'] = array(
    'page callback' => 'forena_report',
    'page arguments' => array(
      1,
    ),
    'title' => t('Reports'),
    'access arguments' => array(
      'access content',
    ),
    'type' => MENU_CALLBACK,
    'file' => 'forena.common.inc',
  );
  $items['report_doc/%'] = array(
    'page callback' => 'forena_report',
    'page arguments' => array(
      1,
    ),
    'access arguments' => array(
      'access content',
    ),
    'type' => MENU_CALLBACK,
    'file' => 'forena.common.inc',
  );
  $items['reports/%/view'] = array(
    'title' => 'View',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => -10,
    'file' => 'forena.common.inc',
    'access arguments' => array(
      'design any report',
    ),
  );
  $items['reports/%/edit'] = array(
    'title' => 'Edit',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'forena_layout_form',
      1,
    ),
    'access arguments' => array(
      'design any report',
    ),
    'description' => 'Edit the layout of your report',
    'type' => MENU_LOCAL_TASK,
    'file' => 'forena.admin.inc',
  );
  if (module_exists('locale')) {
    $items['reports/%/translations'] = array(
      'page callback' => 'forena_report_translations',
      'page arguments' => array(
        1,
      ),
      'title' => 'Translate',
      'file' => 'forena.admin.inc',
      'access arguments' => array(
        'design any report',
      ),
      'type' => MENU_LOCAL_TASK,
    );
  }
  $items['reports/%/edit/params'] = array(
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'forena_admin_params_form',
      1,
    ),
    'title' => 'Parameters',
    'file' => 'forena.admin.inc',
    'access arguments' => array(
      'design any report',
    ),
    'type' => MENU_LOCAL_TASK,
  );
  $items['reports/%/edit/params/add'] = array(
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'forena_add_param_form',
      1,
    ),
    'file' => 'forena.admin.inc',
    'title' => 'Parameters',
    'access arguments' => array(
      'design any report',
    ),
    'type' => MENU_CALLBACK,
  );
  $items['reports/%/edit/layout'] = array(
    'title' => 'Layout',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'forena_layout_form',
      1,
    ),
    'access arguments' => array(
      'design any report',
    ),
    'description' => 'Edit the layout of your report',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'file' => 'forena.admin.inc',
  );
  $items['reports/%/edit/data'] = array(
    'title' => 'Data',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'forena_data_block_form',
      1,
    ),
    'access arguments' => array(
      'design any report',
    ),
    'description' => 'Add a data block to your report',
    'file' => 'forena.admin.inc',
    'type' => MENU_LOCAL_TASK,
  );
  $items['reports/%/edit/data/add'] = array(
    'title' => 'Data',
    'file' => 'forena.admin.inc',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'forena_add_data_block_form',
      1,
    ),
    'access arguments' => array(
      'design any report',
    ),
    'description' => 'Add a data block to your report',
    'type' => MENU_CALLBACK,
  );
  $items['forena/js/template'] = array(
    'page callback' => 'forena_template_info_js',
    'access arguments' => array(
      'design any report',
    ),
    'type' => MENU_CALLBACK,
    'file' => 'forena.admin.inc',
  );
  $items['forena/js/parameters'] = array(
    'page callback' => 'forena_parameters_js',
    'access arguments' => array(
      'access content',
    ),
    'type' => MENU_CALLBACK,
    'file' => 'forena.common.inc',
  );
  $items['reports/%/edit/fields'] = array(
    'title' => 'Fields',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'forena_fields_form',
      1,
    ),
    'access arguments' => array(
      'design any report',
    ),
    'description' => 'Edit the fields of your report',
    'file' => 'forena.admin.inc',
    'type' => MENU_LOCAL_TASK,
  );
  $items['reports/%/edit/format'] = array(
    'title' => 'Format',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'forena_format_form',
      1,
    ),
    'access arguments' => array(
      'design any report',
    ),
    'file' => 'forena.admin.inc',
    'description' => 'Style and document options',
    'type' => MENU_LOCAL_TASK,
  );
  $items['reports/%/delete'] = array(
    'title' => 'Delete Report',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'forena_delete_form',
      1,
    ),
    'access arguments' => array(
      'delete report',
    ),
    'type' => MENU_NORMAL_ITEM,
    'file' => 'forena.admin.inc',
  );
  $items['reports/add'] = array(
    'title' => 'Create Report',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'forena_add_report_form',
    ),
    'access arguments' => array(
      'create any report',
    ),
    'description' => 'Create a new report',
    'file' => 'forena.admin.inc',
    'type' => MENU_NORMAL_ITEM,
  );
  $items['reports/%/add'] = array(
    'title' => 'Create Report',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'forena_add_report_form',
      1,
    ),
    'access arguments' => array(
      'create any report',
    ),
    'description' => 'Create a new report from a template',
    'file' => 'forena.admin.inc',
    'type' => MENU_CALLBACK,
  );
  $items['reports/%/translate'] = array(
    'title' => 'Translate Report',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'forena_create_trans_form',
      1,
    ),
    'access arguments' => array(
      'create any report',
    ),
    'description' => 'Create a new report translation',
    'file' => 'forena.admin.inc',
    'type' => MENU_CALLBACK,
  );
  $items['forena'] = array(
    'page callback' => 'forena_user_reports',
    'page arguments' => array(),
    'title' => t('My Reports'),
    'access arguments' => array(
      'list reports',
    ),
    'type' => MENU_NORMAL_ITEM,
  );
  $items['forena/xml/%'] = array(
    'page callback' => 'forena_block_xml',
    'page arguments' => array(
      2,
    ),
    'access callback' => TRUE,
    'file' => 'forena.common.inc',
    'type' => MENU_CALLBACK,
  );
  $items['forena/fields/format/autocomplete'] = array(
    'page callback' => 'forena_fields_format_autocomplete',
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );
  $items['forena/data_block/autocomplete'] = array(
    'page callback' => 'forena_data_block_autocomplete',
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );
  $items['forena/categories/autocomplete'] = array(
    'page callback' => 'forena_categories_autocomplete',
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );
  $items['forena/reports/autocomplete'] = array(
    'page callback' => 'forena_reports_autocomplete',
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Implementation of hook_block
 */
function forena_block($op = 'list', $delta = 0, $edit = array()) {
  if ($op == 'list') {
    $blocks[0] = array(
      'info' => t('My reports'),
      'status' => 1,
      'region' => 'right',
      'visibility' => 1,
      'pages' => 'forena',
    );
    return $blocks;
  }
  if ($op == 'view') {

    // Inlcude the base library
    require_once 'forena.common.inc';
    switch ($delta) {
      case 0:
        $block = array(
          'subject' => 'My Reports',
          'content' => forena_my_reports_block(),
        );
        break;
    }
    return $block;
  }
}

/**
 * Auto complete for categories
 *
 */
function forena_categories_autocomplete($string = '') {
  require_once 'forena.admin.inc';
  $categories = forena_get_categories($string);
  print drupal_json($categories);
}

/**
 * Auto complete for data blocks
 * @param $string
 * @return unknown_type
 */
function forena_data_block_autocomplete($string = '') {
  require_once 'forena.admin.inc';
  $data_blocks = forena_user_data_blocks($string);
  if ($data_blocks) {
    $temp = array_values($data_blocks);
    $data_blocks = array_combine($temp, $temp);
  }
  else {
    $data_blocks = array();
  }
  print drupal_json($data_blocks);
}

/**
 * Auto complete for formats
 * @param $string
 * @return unknown_type
 */
function forena_fields_format_autocomplete($string = '') {
  require_once 'forena.common.inc';
  $matches = array();
  $formats = FrxReportGenerator::instance()
    ->supported_formats();
  if ($string == "*") {
    $matches = $formats;
    print drupal_json($matches);
    return;
  }
  if ($formats && $string) {
    foreach ($formats as $name => $value) {
      if (strpos(strtolower($name), strtolower($string)) !== FALSE || strpos(strtolower($value), strtolower($string)) !== FALSE) {
        $matches[$name] = $value;
      }
    }
  }
  print drupal_json($matches);
}

/**
 *  Calls forena_layout_form
 *  in forena.admin.inc
 */
function forena_layout_report() {
  require_once 'forena.admin.inc';
  return drupal_get_form('forena_layout_form');
}

/**
 *  Calls forena_admin_params_form
 *  in forena.admin.inc
 *  edit and save param values.
 */
function forena_admin_params() {
  require_once 'forena.admin.inc';
  return drupal_get_form('forena_admin_params_form');
}

/**
 *  Add a new report from scratch
 *  in forena.admin.inc
 */
function forena_add_report($new_report) {
  require_once 'forena.admin.inc';
  return drupal_get_form('forena_layout_form', $new_report);
}

/**
 * Add, preview, or delete data blocks from your report
 * @return unknown_type
 */
function forena_data_block() {
  require_once 'forena.admin.inc';
  return drupal_get_form('forena_data_block_form');
}

/**
 *  Calls forena_parameter_form
 *  in forena.common.inc
 */
function forena_parameters_report() {
  require_once 'forena.admin.inc';
  $desc = forena_report_desc();
  $name = $desc['name'];
  $filename = $desc['filename'];
  $format = $desc['format'];
  $report = forena_get_report($name);
  if ($report) {
    $r = forena_report_object();
    return drupal_get_form('forena_parameters_form');
  }
  else {
    drupal_not_found();
  }
}

/**
 *  Calls forena_fields_form
 *  in forena.admin.inc
 */
function forena_fields_report() {
  require_once 'forena.admin.inc';
  return drupal_get_form('forena_fields_form');
}

/**
 * Implementation of hook_perm
 *
 * @return unknown
 */
function forena_perm() {
  $perms = array(
    'administer forena reports',
    'list reports',
    'create any report',
    'design any report',
    'delete report',
    'perform email merge',
  );

  //@TODO: Add the ability to create subrepositories with different permissions.
  return $perms;
}

/**
 * Send report block XML
 * @param string $block_name
 */
function forena_block_xml($block_name = '') {
  $parms = $_GET;
  unset($parms['q']);
  $block_name = str_replace('.', '/', $block_name);
  $xml = forena_xml($block_name, $parms);
  if (is_object($xml)) {
    header('Content-Type: text/xml');
    print $xml
      ->asXML();
  }
}

/**
 * Block XML page
 * Enter description here ...
 */
function forena_xml($block_name, $parms = array()) {
  require_once 'forena.common.inc';
  drupal_alter('forena_parameters', $block_name, $parms);

  //now invoke the data provider with the correct params
  FrxData::instance()
    ->push($parms, 'parm');
  $xml = FrxReportGenerator::instance()
    ->invoke_data_provider($block_name, $parms);
  return $xml;
}
function forena_user_reports() {
  require_once 'forena.common.inc';
  $reports = forena_get_user_reports();
  if (!$reports) {
    $output = 'No Reports Found';
  }
  $report_repos = variable_get('forena_path', 'reports');
  foreach ($reports as $category => $reports) {
    $links .= '<li><a href="#' . urlencode($category) . '">' . $category . '</a></li> ';
    $output .= '<h3><a name="' . urlencode($category) . '"/>' . $category . '</h3>';
    $output .= '<ul>';
    foreach ($reports as $r) {
      $output .= '<li>' . l($r['title'], $report_repos . '/' . str_replace('/', '.', $r['report_name'])) . '</li>';
    }
    $output .= '</ul>';
  }
  return $output;
}
function forena_reports_autocomplete($string = '') {
  global $language;
  $reports = '';
  $string = '%' . $string . '%';
  $result = db_query("SELECT * FROM {forena_reports} where language='%s'\n\t  AND report_name like '%s'\n\t  ORDER BY category,title", $language->language, $string);
  while ($row = db_fetch_object($result)) {
    $access = TRUE;
    $cache = $row->cache;
    if ($cache) {
      $cache = unserialize($cache);

      // Check each callback function to see if we have an error.
      if ($cache['access']) {
        foreach ($cache['access'] as $callback => $args) {
          if ($callback) {
            foreach ($args as $arg) {
              $access = FALSE;
              if (function_exists($callback)) {
                $a = $callback($arg);
              }
              if ($a) {
                $access = TRUE;
              }
            }
          }
          else {
            $access = TRUE;
          }
        }
      }
    }
    if ($access) {
      $reports[$row->report_name] = $row->report_name . ' - ' . $row->title;
    }
  }
  return drupal_json($reports);
}

/**
 * Include javascript files for dataTables
 */
function forena_include_data_tables() {
  static $init = FALSE;
  if (!$init) {
    $init = TRUE;
    $lib = 'sites/all/libraries/dataTables/media/js/jquery.dataTables.min.js';
    if (file_exists($lib)) {
      drupal_add_js($lib);
    }
    $lib = 'sites/all/libraries/FixedColumns/media/js/FixedColumns.min.js';
    if (file_exists($lib)) {
      drupal_add_js($lib);
    }
  }
}

/**
 * Load and render a report based on a drupal path.
 * In this function the arglist is used to get the full path to the report.
 *
 * @return unknown
 */
function forena_report($name_in, $parms = array(), $print = TRUE) {
  require_once 'forena.common.inc';
  $desc = forena_report_desc($name_in);
  if (!$desc['exists']) {
    drupal_not_found();
    exit;
  }
  $report_name = $desc['name'];
  $output = FrxReportGenerator::instance()
    ->report($name_in, $parms, $print);
  $format = @$desc['format'];
  if (!$format || $format == 'web') {
    $output = check_markup($output, variable_get('forena_input_format', FILTER_FORMAT_DEFAULT), FALSE);
  }
  $m_path = drupal_get_path('module', 'forena');
  forena_include_data_tables();
  drupal_add_js($m_path . '/forena.js');
  $forena_js = array();
  $forena_js['form'] = preg_replace('/[^\\w\\-]+/u', '_', FrxReportGenerator::instance()->form);
  $forena_js['report'] = preg_replace('/[^\\w\\-]+/u', '_', $name_in);
  drupal_add_js(array(
    'forena' => $forena_js,
  ), 'setting');
  return $output;
}

/**
 * Render report with some data
 *
 * @param string $report
 * @param string $format
 * @param mixed $data
 * @return unknown
 */
function forena_render_report($report, $format = '', $data = '', $options = array(), $print = TRUE) {
  require_once 'forena.common.inc';
  $o = forena_report_object($report, $data);
  $output = $o
    ->render($format);

  //If a format was requested render a custom non-drupal document
  if ($format && $format != 'web') {
    $output = FrxReportGenerator::instance()
      ->generate_doc($format, $output, $options, $print);
  }
  return $output;
}

/**
 * Self register plugins with forena.
 *
 */
function forena_forena_plugins() {
  $plugins[] = array(
    'file' => 'plugins/FrxPDO.inc',
    'class' => 'FrxPDO',
  );
  $plugins[] = array(
    'file' => 'plugins/FrxOracle.inc',
    'class' => 'FrxOracle',
  );
  $plugins[] = array(
    'file' => 'plugins/FrxDrupal.inc',
    'class' => 'FrxDrupal',
  );
  $plugins[] = array(
    'file' => 'plugins/FrxFiles.inc',
    'class' => 'FrxFiles',
  );
  $plugins[] = array(
    'file' => 'plugins/FrxPostgres.inc',
    'class' => 'FrxPostgres',
  );
  $plugins[] = array(
    'file' => 'plugins/FrxMSSQL.inc',
    'class' => 'FrxMSSQL',
  );
  return $plugins;
}

/**
 * Self register controls with forena.
 *
 */
function forena_forena_controls() {
  $controls[] = array(
    'file' => 'plugins/FrxControls.inc',
    'class' => 'FrxControls',
  );
  $controls[] = array(
    'file' => 'plugins/FrxDrupalControls.inc',
    'class' => 'FrxDrupalControls',
  );
  $controls[] = array(
    'file' => 'plugins/FrxSource.inc',
    'class' => 'FrxSource',
  );
  $controls[] = array(
    'file' => 'plugins/FrxXMLSource.inc',
    'class' => 'FrxXMLSource',
  );
  $controls[] = array(
    'file' => 'plugins/FrxInclude.inc',
    'class' => 'FrxInclude',
  );
  $library_dir = FrxReportGenerator::instance()
    ->configuration('library_path');
  $library = rtrim($library_dir, '/') . '/SVGGraph/SVGGraph.php';
  if (file_exists($library)) {
    $controls[] = array(
      'file' => 'plugins/FrxSVGGraph.inc',
      'class' => 'FrxSVGGraph',
    );
  }
  return $controls;
}

/**
 * Load the report repository path
 *
 * @return unknown
 */
function forena_report_path() {
  $report_path = variable_get('forena_report_repos', '');
  if (!$report_path) {
    $report_path = drupal_get_path('module', 'forena') . '/repos/reports';
  }
  return rtrim($report_path, '/');
}

/**
 * Helper function for current user for the drupal instance
 *
 * @return unknown
 */
function forena_current_user_uid() {
  global $user;
  return $user->uid;
}

/**
 * Helper function for current user for the drupal instance
 *
 * @return unknown
 */
function forena_current_user_name() {
  global $user;
  return $user->name;
}

/**
 * Implememntation of hook_filter
 */
function forena_filter($op, $delta = 0, $format = -1, $text = '') {
  if ($op == 'list') {
    return array(
      0 => t('Insert Report'),
    );
  }
  switch ($delta) {
    case 0:
      switch ($op) {
        case 'description':
          return t('Inserts a forena report');
        case 'prepare':
          return $text;
        case 'process':
          return _forena_filter_process($text);
        case 'no cache':
          return TRUE;
      }
  }
}
function _forena_filter_process($text = '') {
  global $language;
  require_once 'forena.common.inc';

  // initial Parameters
  $in_parms = array();
  $in_parms = $_GET;

  // Find the instances of [xmlreport:view,
  if (preg_match_all("/\\[report?:?([^\\]]+)\\]/i", $text, $match)) {
    foreach ($match[1] as $idx => $value) {
      $parms = array();

      // Separate view from parmeters
      @(list($report_name, $parmsStr) = explode(':', $value));

      // Get any static parmeters
      $pairs = explode(',', $parmsStr);
      if ($pairs) {
        foreach ($pairs as $pair) {
          @(list($key, $value) = explode('=', $pair));
          $parms[$key] = $value;
        }
      }
      $parms = array_merge($parms, $in_parms);

      // Debug the result
      $r = FrxReportGenerator::instance()
        ->get_report($report_name, $parms);
      if ($r) {
        $output = $r
          ->render(null);
      }
      else {
        $output = '';
      }

      // Finally replace the parameters
      $find[] = $match[0][$idx];
      $replace[] = $output;
    }
    return str_replace($find, $replace, $text);
  }

  // If we didn't find anything return the text.
  return $text;
}

/**
 * Impementation of hook_mail
 * Builds an email to send when mailing large numbers of users.
 */
function forena_mail($key, &$message, $parms) {
  switch ($key) {
    case 'mailmerge':
      $message['subject'] = $parms['subject'];
      $body = $parms['body'];
      $message['body'] = '<html><body>' . $body . '</body></html>';
      $message['headers']['MIME-Version'] = '1.0';
      $message['headers']['Content-Type'] = 'text/html;charset=utf-8';
      break;
  }
}

Functions

Namesort descending Description
forena_add_report Add a new report from scratch in forena.admin.inc
forena_admin_params Calls forena_admin_params_form in forena.admin.inc edit and save param values.
forena_block Implementation of hook_block
forena_block_xml Send report block XML
forena_categories_autocomplete Auto complete for categories
forena_current_user_name Helper function for current user for the drupal instance
forena_current_user_uid Helper function for current user for the drupal instance
forena_data_block Add, preview, or delete data blocks from your report
forena_data_block_autocomplete Auto complete for data blocks
forena_fields_format_autocomplete Auto complete for formats
forena_fields_report Calls forena_fields_form in forena.admin.inc
forena_filter Implememntation of hook_filter
forena_forena_controls Self register controls with forena.
forena_forena_plugins Self register plugins with forena.
forena_include_data_tables Include javascript files for dataTables
forena_layout_report Calls forena_layout_form in forena.admin.inc
forena_mail Impementation of hook_mail Builds an email to send when mailing large numbers of users.
forena_menu Implementation of hook_menu.
forena_parameters_report Calls forena_parameter_form in forena.common.inc
forena_perm Implementation of hook_perm
forena_render_report Render report with some data
forena_report Load and render a report based on a drupal path. In this function the arglist is used to get the full path to the report.
forena_reports_autocomplete
forena_report_path Load the report repository path
forena_user_reports
forena_xml Block XML page Enter description here ...
_forena_filter_process