You are here

forena.common.inc in Forena Reports 6.2

Common functions used throughout the project but loaded in this file to keep the module file lean.

File

forena.common.inc
View source
<?php

/**
 * @file
 * Common functions used throughout the project but loaded in this
 * file to keep the module file lean.
 */

// Include Report renderer.
require_once 'FrxReport.inc';
require_once 'FrxDataProvider.inc';
require_once 'FrxReportGenerator.inc';
require_once 'FrxSQLQueryBuilder.inc';
require_once 'FrxDrupalApplication.inc';
require_once 'FrxData.inc';

/**
 * Get name from argument 1 or alterntaively from a file name
 *
 * @param unknown_type $name
 */
function forena_report_desc(&$name = '') {
  global $language;
  $lang = $language->language;
  $base_name = $name;
  if (module_exists('locale')) {

    //First check to see if the report allready has a language in it
    @(list($tlang, $tbase_name) = explode('.', $name, 2));

    // FInd out if the starting name of the report is an installed language.
    $lang_list = language_list();
    if (array_key_exists($tlang, $lang_list)) {
      $base_name = $tbase_name;
      if ($lang != $tlang) {
        $lang = $tlang;
        $language = $lang_list[$lang];
      }
      if ($tlang == 'en') {
        $name = $tbase_name;
        $base_name = $tlang . '.' . $tbase_name;
      }
    }
    else {
      if ($lang != 'en') {
        $name = $lang . '.' . $name;
      }
    }
  }
  $desc = FrxReportGenerator::instance()
    ->report_desc($name);
  $desc['language'] = $lang;
  $desc['base_name'] = $base_name;
  return $desc;
}
function forena_load_cache($r_xhtml) {
  $conf = array();
  $cache = array();
  $blocks = array();
  $repos = array();
  if (is_object($r_xhtml)) {
    $block_xml = $r_xhtml
      ->xpath('//*[@frx:block]');

    // Extract all the blocks and organize by provider
    foreach ($block_xml as $key => $block_node) {
      $attrs = $block_node
        ->attributes('urn:FrxReports');
      foreach ($attrs as $key => $value) {
        if ($key == 'block') {
          list($provider, $block) = explode('/', $value, 2);
          $repos[$provider][] = $block;
        }
      }
    }
    if ($repos) {
      foreach ($repos as $provider => $blocks) {
        $repos = FrxReportGenerator::instance()
          ->repository($provider);
        $provider = $repos['data'];
        if (isset($provider->conf)) {
          $conf = $provider->conf;
        }
        $access = array();
        foreach ($blocks as $block_name) {
          if ($provider && $block_name) {
            if (method_exists($provider, 'load_block')) {
              $conf = $provider->conf;
              $block = $provider
                ->load_block($block_name);
              if (isset($block['access']) && array_search($block['access'], $access) === FALSE) {
                $access[] = $block['access'];
              }
            }
          }
          else {

            //drupal_set_message('no provider found', 'error');
          }
        }
        if (isset($conf['access callback']) && $access) {
          $cache['access'][$conf['access callback']] = $access;
        }
      }
    }
  }
  return $cache;
}

/**
 * Object factory for forena report
 * When called without a report name, it returns the last created report.
 * This static caching mechanism is used for form functions that are called
 * within a page load.
 *
 * @param unknown_type $report_name
 */
function forena_report_object($report = '', $data = '') {
  static $object = '';
  if ($report) {
    $object = new FrxReport($report, $data);
  }
  return $object;
}

/**
 * Enter description here...
 *
 * @param simplexml $xml
 * @param string $tag
 * @return string
 */
function forena_inner_xml($xml, $tag) {
  if (is_object($xml) && is_object($xml->{$tag})) {
    $xml_data = $xml->{$tag}
      ->asXML();
    $xml_data = preg_replace("/<\\/?" . $tag . "(.|\\s)*?>/", "", $xml_data);
  }
  return $xml_data;
}

/**
 * Accepts the name of the html tag, and the string the tag is in.
 *
 * Returns the string within the html tag name
 *
*/
function forena_get_html($tag, $r_text) {
  $open = strpos($r_text, $tag);
  $close = strpos($r_text, '>', $open);
  $next = strpos($r_text, '<', $close + 1);
  $str = substr($r_text, $close + 1, $next - ($close + 1));
  return $str;
}

/**
 * Form to edit parameters
 * Extra features:
 * In the parameters section of the report are new attributes
 * frx:parm:
 * @data_source = data block for the parameter to values from
 * @data_field = specific field of the data block to recieve values from.
 * if no field is specified then the first column is arbitrarily chosen.
 * @type = The form element that will display the values: select, radios are supported
 * default is textfield.
 *
 * This function will evaluate each parameter, determine its type, data_source, and data_field
 * and display those values appropriately.
 *
 */
function forena_parameter_form(&$form_state, $rpt, $collapse = FALSE) {
  $parms = $_GET;
  unset($parms['q']);
  $r = new FrxReport($rpt);
  if (isset($form_state['values'])) {
    $collapse = FALSE;
    $parms = array_merge($parms, $form_state['values']['params']);
  }
  $form = array();
  if ($r) {
    drupal_set_title($r->title);
    $head = $r->rpt_xml->head;
    FrxReportGenerator::instance()
      ->alter_parameters('', $parms);
    $nodes = $head
      ->xpath('frx:parameters/frx:parm');
    if ($nodes) {
      if ($form_state['ahah_submission']) {

        // Clear the form errors.  We don't need to show any validation errors if this is an ahah submit, not a final submit
        drupal_get_messages('error');

        // Clear the form error state.
        form_set_error(null, '', true);
      }
      $form['params'] = array(
        '#tree' => TRUE,
        '#title' => t('Parameters'),
        '#type' => 'fieldset',
        '#prefix' => '<div id="parameters-wrapper">',
        '#suffix' => '</div>',
        '#collapsible' => TRUE,
        '#collapsed' => (string) $collapse,
      );
      foreach ($nodes as $node) {
        $label = (string) $node['label'];
        $id = (string) $node['id'];
        $data_source = (string) $node['data_source'];
        $data_field = (string) $node['data_field'];
        $type = (string) $node['type'];
        if (isset($parms[$id])) {
          $value = (string) $parms[$id];
          $multi_value = (array) $value;
        }
        else {
          $value = (string) $node;
          $multi_value = array();
          if (strpos($value, '|') !== FALSE) {
            $multi_value = explode('|', $value);
          }
        }
        $desc = (string) $node['desc'];
        $label_field = (string) $node['label_field'];
        strcmp((string) $node['require'], "1") == 0 ? $required = TRUE : ($required = FALSE);

        //Determine the form element type to be displayed

        //If select or radios is chosen then begin a $list array for display values.
        $multiselect = FALSE;
        $list = array();
        $ajax = FALSE;
        $add_null = FALSE;
        switch ($type) {
          case 'multiselect':
            $type = 'select';
            $multiselect = TRUE;
            $value = $multi_value;
            break;
          case 'checkboxes':
            $value = $multi_value;
            break;
          case 'selectajax':
            $ajax = TRUE;
            $type = 'select';
            break;
          case 'select':
            $add_null = TRUE;
            break;
          case 'radios':
            break;
          default:
            $type = 'textfield';
            $list = '';
        }

        //If a data_source attr was found then create an array of

        //returned values filtered against data_field attr.
        if ($data_source) {
          $list = FrxReportGenerator::instance()
            ->data_block_params($data_source, $data_field, $label_field, $parms);
          if (!$required && $add_null) {
            $list = array(
              '' => '',
            ) + $list;
          }
        }
        $form['params'][$id] = array(
          '#type' => $type,
          '#title' => $label ? t($label) : t($id),
          '#default_value' => $value,
          '#required' => $required,
          '#description' => t($desc),
        );

        //if $list is not empty then push options

        //onto the array. options will cause an error for

        //textfield elements.
        if ($type != 'textfield') {
          $form['params'][$id]['#options'] = $list;
          $form['params'][$id]['#multiple'] = $multiselect;
          if ($ajax) {
            $form['params'][$id]['#ahah'] = array(
              'path' => 'forena/js/parameters',
              'wrapper' => 'parameters-wrapper',
              'method' => 'replace',
              'effect' => 'fade',
              'event' => 'change',
            );
          }
        }
      }
      $form['params']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Submit'),
      );
    }
  }
  return $form;
}

/**
 * Ajax callback for settings pages.
 * Enter description here ...
 * @param string $part matches the form path callback
 */
function forena_parameters_js() {
  $form = forena_ahah_helper_start();
  $form = $form['params'];
  forena_ahah_helper_end($form);
}

/**
 *
 * gets the values from the params form
 * redirects to the report page with the values in
 * the querystring.
 */
function forena_parameter_form_submit($form, &$form_state) {
  $values = $form_state['values'];
  unset($values['submit']);
  foreach ($values['params'] as $key => $value) {
    if (is_array($value)) {
      foreach ($value as $k => $val) {
        if (!$val) {
          unset($values['params'][$key][$k]);
        }
      }
    }
    else {
      if (strpos($value, '|') !== FALSE) {
        $values['params'][$key] = explode('|', $value);
      }
    }
  }
  $form_state['redirect'] = array(
    $_GET['q'],
    $values['params'],
  );
}
function forena_get_user_reports() {
  global $language;
  $result = db_query("SELECT * FROM {forena_reports} where hidden=0 and language='%s' ORDER BY category,title asc", $language->language);
  $reports = array();
  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->category][] = array(
        'title' => $row->title,
        'report_name' => $row->report_name,
      );
    }
  }
  return $reports;
}

/**
 * Render the my reports category block
 *
 */
function forena_my_reports_block() {
  $reports = forena_get_user_reports();
  if (!$reports) {
    return '';
  }
  $output = '<ul>';
  foreach ($reports as $category => $reports) {
    $output .= '<li>' . l($category, 'forena', array(
      fragment => urlencode($category),
    )) . '</li>';
  }
  $output .= '</ul>';
  return $output;
}

/**
 * Email confirmation form.   Confirms an email send based on mail merge
 * @param array $docs An array of SimpleXML email documents to send
 * @param integer $count Number of documents to send.
 */
function forena_confirm_email(&$form_state, $docs, $count, $prompt_subject, $prompt_body) {
  if ($docs) {
    $values = @$form_state['values'];
    if ($prompt_subject) {
      $form['subject'] = array(
        '#type' => 'textfield',
        '#title' => t('Subject'),
        '#default_value' => @$values['subject'],
        '#required' => TRUE,
      );
    }
    if ($prompt_body) {
      $form['body'] = array(
        '#type' => 'textarea',
        '#title' => t('Message'),
        '#default_value' => @$values['body'],
        '#required' => TRUE,
      );
      $form['format'] = filter_form(variable_get('forena_mail_input_format', FILTER_FORMAT_DEFAULT));
    }
    if (!variable_get('forena_email_override', FALSE)) {
      $form['send'] = array(
        '#type' => 'radios',
        '#title' => 'Send Email',
        '#options' => array(
          'send' => 'email to users',
          'test' => 'emails to me (test mode)',
        ),
        '#default_value' => 'test',
      );
    }
    $form['max'] = array(
      '#type' => 'textfield',
      '#title' => 'Only send first',
      '#description' => 'In test mode only, limits the number of messages to send',
      '#default_value' => 1,
      '#size' => 3,
    );
    $form_state['storage']['docs'] = $docs;
    $form_state['storage']['count'] = $count;
  }
  return confirm_form($form, t('Send mail to users'), 'forena', t('Send email to %count users?', array(
    '%count' => $count,
  )));
}
function forena_confirm_email_submit($form, &$form_state) {
  global $user;
  $test_send = $form_state['values']['send'] == 'test' ? TRUE : variable_get('forena_email_override', FALSE);
  $max = (int) $form_state['values']['max'];
  if (isset($form_state['values']['body'])) {
    $body = check_markup($form_state['values']['body'], variable_get('forena_email_input_format', FILTER_FORMAT_DEFAULT), FALSE);
  }
  foreach ($form_state['storage']['docs'] as $doc) {
    $to = $test_send ? $user->mail : $doc['to'];
    if (isset($form_state['values']['body'])) {
      $doc['parms']['body'] = $body;
    }
    if (isset($form_state['values']['subject'])) {
      $doc['parms']['subject'] = $form_state['values']['subject'];
    }
    if ($test_send) {
      $i++;
    }
    if ($i <= $max) {
      drupal_mail('forena', 'mailmerge', $to, language_default(), $doc['parms'], $doc['from'], TRUE);
    }
  }
}

/**
 * Helper function to process java callbacks.
 */
function forena_ahah_helper_start() {

  // The form is generated in an include file which we need to include manually.
  // We're starting in step #3, preparing for #4.
  $form_state = array(
    'storage' => NULL,
    'rebuild' => TRUE,
  );
  $form_build_id = $_POST['form_build_id'];

  // Step #4.
  $form = form_get_cache($form_build_id, $form_state);

  // Preparing for #5.
  $args = $form['#parameters'];
  $form_id = array_shift($args);
  $form_state['post'] = $form['#post'] = $_POST;
  $form['#programmed'] = $form['#redirect'] = FALSE;

  // Step #5.
  $form_state['reuild'] = TRUE;
  drupal_process_form($form_id, $form, $form_state);

  // Step #6 and #7 and #8.
  $form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
  return $form;
}

/**
 * Helper function to render output forms
 * @param array $form
 */
function forena_ahah_helper_end(&$form) {
  unset($form['#prefix'], $form['#suffix']);
  $output = theme('status_messages') . drupal_render($form);

  // Final rendering callback.
  drupal_json(array(
    'status' => TRUE,
    'data' => $output,
  ));
}

Functions

Namesort descending Description
forena_ahah_helper_end Helper function to render output forms
forena_ahah_helper_start Helper function to process java callbacks.
forena_confirm_email Email confirmation form. Confirms an email send based on mail merge
forena_confirm_email_submit
forena_get_html Accepts the name of the html tag, and the string the tag is in.
forena_get_user_reports
forena_inner_xml Enter description here...
forena_load_cache
forena_my_reports_block Render the my reports category block
forena_parameters_js Ajax callback for settings pages. Enter description here ...
forena_parameter_form Form to edit parameters Extra features: In the parameters section of the report are new attributes frx:parm: @data_source = data block for the parameter to values from @data_field = specific field of the data block to recieve values from. if no field…
forena_parameter_form_submit gets the values from the params form redirects to the report page with the values in the querystring.
forena_report_desc Get name from argument 1 or alterntaively from a file name
forena_report_object Object factory for forena report When called without a report name, it returns the last created report. This static caching mechanism is used for form functions that are called within a page load.