addMenuItems($items); $items['admin/structure/forena'] = 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/structure/forena/reports'] = array( 'type' => MENU_DEFAULT_LOCAL_TASK, 'title' => '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/config/content/forena'] = array( 'page callback' => 'drupal_get_form', 'page arguments' => array('forena_settings'), 'title' => 'Forena Reports', 'description' => '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/config/content/forena/general'] = array( 'title' => 'General', 'type' => MENU_DEFAULT_LOCAL_TASK, 'file' => 'forena.admin.inc', 'weight' => -10, ); $items['admin/config/content/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/config/content/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/config/content/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/config/content/forena/formats'] = array( 'page callback' => 'drupal_get_form', 'page arguments' => array('forena_doc_formats_settings'), 'title' => 'Document Types', 'access arguments' => array('administer forena reports'), 'type' => MENU_LOCAL_TASK, 'file' => 'forena.admin.inc', ); $items['admin/structure/forena/data'] = array( 'type' => MENU_LOCAL_TASK, 'title' => 'Data', 'access arguments' => array('design any report'), 'page callback' => 'forena_display_blocks', 'file' => 'forena.data.inc', ); $items['forena/data'] = array( 'page callback' => 'forena_data_preview', 'access arguments' => array('design any report'), 'file' => 'forena.data.inc', 'type' => MENU_CALLBACK, ); $items['reports/%'] = array( 'page callback' => 'forena_report', 'page arguments' => array(1), 'title' => '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/%/edit'] = array( 'title' => 'Edit', 'page callback' => 'forena_report_preview', 'page arguments' => array(1), 'access arguments' => array('design any report'), 'description' => 'Edit the layout of your report', 'type' => MENU_CALLBACK, 'file' => 'forena.report.inc', ); if (module_exists('locale')) { $items['reports/%/translations'] = array( 'page callback' => 'forena_report_translations', 'page arguments' => array(1), 'title' => 'Translate', 'file' => 'forena.report.inc', 'access arguments' => array('design any report'), 'type' => MENU_CALLBACK, ); } $items['reports/%/edit/parameters'] = array( 'page callback' => 'drupal_get_form', 'page arguments' => array('forena_report_parameters_form', 1), 'title' => 'Parameters', 'file' => 'forena.report.inc', 'access arguments' => array('design any report'), 'type' => MENU_LOCAL_TASK, ); $items['reports/%/edit/edit-parameter'] = array( 'page callback' => 'drupal_get_form', 'page arguments' => array('forena_report_parameter_config_form', 1), 'title' => 'Edit Parameter', 'file' => 'forena.report.inc', 'access arguments' => array('design any report'), 'type' => MENU_CALLBACK, ); $items['reports/%/edit/add-parameter'] = array( 'page callback' => 'drupal_get_form', 'page arguments' => array('forena_report_add_parameter_form', 1), 'file' => 'forena.report.inc', 'title' => 'Parameters', 'access arguments' => array('design any report'), 'type' => MENU_CALLBACK, ); $items['reports/%/edit/general'] = array( 'title' => 'General', 'page callback' => 'drupal_get_form', 'page arguments' => array('forena_report_general_form',1), 'access arguments' => array('design any report'), 'description' => 'General Report Properties', 'type' => MENU_LOCAL_TASK, 'weight' => -1, 'file' => 'forena.report.inc', ); $items['reports/%/edit/layout'] = array( 'title' => 'Layout', 'page callback' => 'drupal_get_form', 'page arguments' => array('forena_report_layout_form',1), 'access arguments' => array('design any report'), 'description' => 'Edit the layout of your report', 'type' => MENU_LOCAL_TASK, 'file' => 'forena.report.inc', ); $items['reports/%/edit/edit-data/%/%'] = array( 'title' => 'Edit Block', 'file' => 'forena.report.inc', 'page callback' => 'drupal_get_form', 'page arguments' => array('forena_report_data_block_form', 1, 3, 4, 5, 'edit-data'), 'access arguments' => array('design any report'), 'description' => 'Add a data block to your report', 'type' => MENU_CALLBACK, ); $items['reports/%/edit/edit-field/%'] = array( 'title' => 'Edit Block', 'file' => 'forena.report.inc', 'page callback' => 'drupal_get_form', 'page arguments' => array('forena_report_field_form', 1, 4), 'access arguments' => array('design any report'), 'description' => 'Add a data block to your report', 'type' => MENU_CALLBACK, ); $items['reports/%/edit/select-data/%'] = array( 'title' => 'Select Data Block', 'file' => 'forena.report.inc', 'page callback' => 'forena_select_block_list', 'page arguments' => array(1, 4), 'access arguments' => array('design any report'), 'description' => 'Select the data blcok to add', 'type' => MENU_CALLBACK, ); $items['reports/%/edit/select-data/%/%'] = array( 'title' => 'Select Data Block', 'file' => 'forena.report.inc', 'page callback' => 'forena_select_block_list', 'page arguments' => array(1, 4, 5), 'access arguments' => array('design any report'), 'description' => 'Select the data blcok to add', 'type' => MENU_CALLBACK, ); $items['reports/%/edit/preview-data/%/%'] = array( 'title' => 'Preview Data Block', 'file' => 'forena.report.inc', 'page callback' => 'forena_report_block_preview', 'page arguments' => array(1, 4, 5), 'access arguments' => array('design any report'), 'description' => 'Select the data block to add', 'type' => MENU_CALLBACK, ); $items['reports/%/edit/preview-data/%/%/%'] = array( 'title' => 'Preview Data Block', 'file' => 'forena.report.inc', 'page callback' => 'forena_report_block_preview', 'page arguments' => array(1, 4, 5, 6), 'access arguments' => array('design any report'), 'description' => 'Select the data block to add', 'type' => MENU_CALLBACK, ); $items['reports/%/edit/add-data/%'] = array( 'title' => 'Data', 'file' => 'forena.report.inc', 'page callback' => 'drupal_get_form', 'page arguments' => array('forena_report_data_block_form', 1, 3, 4), 'access arguments' => array('design any report'), 'description' => 'Edit a data block on the report. ', 'type' => MENU_CALLBACK, ); $items['reports/%/edit/add-data/%/%'] = array( 'title' => 'Add Data', 'file' => 'forena.report.inc', 'page callback' => 'drupal_get_form', 'page arguments' => array('forena_report_data_block_form', 1, 3, 4, 5), 'access arguments' => array('design any report'), 'description' => 'Edit a data block on the report. ', 'type' => MENU_CALLBACK, ); $items['reports/%/edit/prepend-data/%/%'] = array( 'title' => 'Add Data', 'file' => 'forena.report.inc', 'page callback' => 'drupal_get_form', 'page arguments' => array('forena_report_data_block_form', 1, 3, 4, 5), 'access arguments' => array('design any report'), 'description' => 'Edit a data block on the report. ', 'type' => MENU_CALLBACK, ); $items['reports/%/edit/delete-data/%'] = array( 'title' => 'Delete Data', 'file' => 'forena.report.inc', 'page callback' => 'drupal_get_form', 'page arguments' => array('forena_report_delete_confirm', 1, 4), 'access arguments' => array('design any report'), 'description' => 'Delete this form', 'type' => MENU_CALLBACK, ); $items['reports/%/edit/format'] = array( 'title' => 'Document Types', 'page callback' => 'drupal_get_form', 'page arguments' => array('forena_report_format_form', 1), 'access arguments' => array('design any report'), 'file' => 'forena.report.inc', 'description' => 'Document Options', 'type' => MENU_LOCAL_TASK, ); $items['reports/%/delete'] = array( 'title' => 'Remove Custom Report', 'page callback' => 'drupal_get_form', 'page arguments' => array('forena_report_delete_form', 1), 'access arguments' => array('delete report'), 'type' => MENU_CALLBACK, 'file' => 'forena.report.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.report.inc', 'type' => MENU_SUGGESTED_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' => '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 arguments' => array('access forena block xml'), 'file' => 'forena.common.inc', 'type' => MENU_CALLBACK, ); $items['forena/json/%'] = array( 'page callback' => 'forena_json', 'page arguments' => array(2), 'access arguments' => array('access forena block xml'), '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/reports/autocomplete'] = array( 'page callback' => 'forena_reports_autocomplete', 'access callback' => TRUE, 'type' => MENU_CALLBACK, ); $items['forena/categories/autocomplete'] = array( 'page callback' => 'forena_categories_autocomplete', 'access callback' => TRUE, 'type' => MENU_CALLBACK, ); return $items; } /** * Implements hook_admin_paths_alter(). */ function forena_admin_paths_alter(&$paths) { $paths['reports/*/*'] = TRUE; $paths['reports/*/view'] = FALSE; $paths['reports/*/edit'] = FALSE; $paths['reports/add'] = TRUE; } function forena_library_file($library) { $libraries = array( 'dataTables' => 'dataTables/media/js/jquery.dataTables.min.js', 'mpdf' => 'mpdf/mpdf.php', 'SVGGraph' => 'SVGGraph/SVGGraph.php', 'prince' => 'prince/prince.php' ); $path = isset($libraries[$library]) && file_exists('sites/all/libraries/' . $libraries[$library]) ? 'sites/all/libraries/' . $libraries[$library] : ''; return $path; } /** * Implementation of hook_block_info */ function forena_block_info() { $blocks['forena_reports'] = array('info' => t('My reports'), 'status' => 1, 'region' => 'sidebar_first', 'visibility' => 1, 'pages' => 'forena', ); return $blocks; } /** * Implementation of hook_block_view */ function forena_block_view($delta = 0) { // Inlcude the base library require_once('forena.common.inc'); switch ($delta) { case 'forena_reports': $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_output($categories); } /** * Auto complete for data blocks * @param $string * @return unknown_type */ function forena_data_block_autocomplete() { require_once('forena.admin.inc'); $args = func_get_args(); $search = implode('/', $args); if (strlen($search) < 2) { $search .= '*'; } else { $search = "*$search*"; } $data_blocks = Frx::DataFile()->userBlocks($search); if ($data_blocks) { $temp = array_keys($data_blocks); $data_blocks = array_combine($temp, $temp); } else { $data_blocks = array(); } print drupal_json_output($data_blocks); } function forena_reports_autocomplete($string='', $string2='') { GLOBAL $language; $reports=''; $link = ''; // If we have two parameters. if ($string2) { $mode = $string; $string = $string2; } $string = '*' .$string .'*'; $result = Frx::File()->allReports(); foreach ($result as $row) { if (drupal_match_path($row->name, $string)) { $reports[$row->name] = $row->name . ' - ' . $row->cache['title']; } } return drupal_json_output($reports); } function forena_xml($block_name, $parms=array()) { include_once('forena.common.inc'); drupal_alter('forena_parameters', $block_name, $parms ); //now invoke the data provider with the correct params Frx::Data()->push($parms, 'parm'); return Frx::RepoMan()->data($block_name); } /** * Get the raw data from a block if supported. * Note that this may return a simplexml object or a recordset or an * array depending on the support provided by the product. * @param unknown $block_name * @param unknown $parms * @return Ambigous */ function forena_data($block_name, $parms=array()) { include_once('forena.common.inc'); drupal_alter('forena_parameters', $block_name, $parms ); //now invoke the data provider with the correct params Frx::Data()->push($parms, 'parm'); return Frx::RepoMan()->data($block_name, TRUE); } /** * Output forena data as JSON objects. * @param unknown $block_name * @param string $parms */ function forena_json($block_name, $parms= NULL) { $block_name = str_replace('.', '/', $block_name); if ($parms === NULL) { $parms = array_merge($_GET, $_POST); unset($_parms['q']); } $data = forena_data($block_name, $parms); $ret = array(); foreach($data as $row) { $ret[] = $row; } drupal_json_output($ret); } /** * 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_output($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_output($matches); } /** * Calls forena_parameter_form * in forena.common.inc */ function forena_parameters_report() { require_once('forena.admin.inc'); $m = Frx::Menu(); $name = $m->name; $filename = $m->filename; $format = $m->format; $report = forena_get_report($name); if ($report) { $r = forena_report_object(); $o = drupal_get_form('forena_parameters_form'); return $o; } else { drupal_not_found(); } } function forena_parameter_form($formid, &$form_state, $parameters, $attributes= array()) { $parms = $_GET; // Set menu parms $menu_parms = Frx::Data()->getContext('menu-parms'); if ($menu_parms) $form_state['storage']['menu-parms'] = $menu_parms; // Set Descriptors $desc = FrxData::instance()->getContext('report'); $form_state['storage']['desc'] = $desc; $desc = $form_state['storage']['desc']; $report_name = @$desc['name']; $collapse = isset($attributes['collapsed']) ? $attributes['collapsed'] : FALSE; if (isset($form_state['values'])) { $collapse=FALSE; $parms = array_merge($parms, $form_state['values']['params']); // In the case of ahah, we need to restore menu parameters from the form state. if (isset($form_state['storage']['menu-parms'])) { $menu_parms = $form_state['storage']['menu-parms']; $parms = array_merge($menu_parms,$parms); } drupal_alter('forena_parameters', $report_name, $parms); Frx::Data()->push($parms, 'parm'); } $template = @$attributes['template']; $collapsible = isset($attributes['collapsible']) ? $attributes['collapsible'] : TRUE; $title = isset($attributes['title']) ? $attributes['title'] : t('Parameters'); $submit_value = isset($attributes['submit']) ? $attributes['submit'] : t('Submit'); unset($parms['q']); $form = array(); if ($parameters) { //drupal_alter('forena_parameters', $report_name, $parms); if ($parameters) { $form['params'] = array( '#tree' => TRUE, '#title' => $title, '#type' => 'fieldset', '#collapsible' => $collapsible, '#collapsed' => $collapse, '#prefix' => '
', '#suffix' => '
', ); foreach ($parameters as $node) { $add_null = FALSE; $list=array(); $disabled = FALSE; $label = @(string)$node['label']; $id = @(string)$node['id']; $data_source = @(string)$node['data_source']; $data_field = @(string)$node['data_field']; $class = @(string)$node['class']; $type = @(string)$node['type']; $option_str = @(string)$node['options']; $options = array(); if ($option_str) { parse_str($option_str, $options); } if (isset($parms[$id])) { $value = $parms[$id]; $multi_value=(array)$parms[$id]; } else { $value = @(string)$node['default']; $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; $ctl_attrs = array(); //returned values filtered against data_field attr. if ($data_source) { $list = Frx::RepoMan()->dataBlockParams($data_source, $data_field, $label_field); if (!$required && $add_null) $list = array('' => '') + $list; } //Determine the form element type to be displayed //If select or radios is chosen then begin a $list array for display values. $multiselect = FALSE; $ajax = FALSE; $add_null = FALSE; switch ($type) { case 'multiselect': $type = 'select'; $multiselect = TRUE; $value = $multi_value; break; case 'multiselectajax': $type = 'select'; $multiselect = TRUE; $value = $multi_value; $ajax = TRUE; break; case 'checkboxes': $value = $multi_value; break; case 'selectajax': $ajax = TRUE; $type = 'select'; $add_null = TRUE; break; case 'select': $add_null = TRUE; break; case 'date_text': case 'date_select': case 'date_popup': $options['date_format'] = @$options['date_format'] ? $options['date_format'] : 'Y-m-d'; $ctl_attrs['#date_format'] = $options['date_format']; if ($value){ $datetime = @strtotime($value); if ($datetime) { $value = date('Y-m-d h:i', $datetime); } } $ctl_attrs['#forena_date_format'] = @$options['date_parm_format'] ? $options['date_parm_format'] : 'Y-m-d'; if (@$options['date_year_range']) { $ctl_attrs['#date_year_range'] = $options['date_year_range']; } if (@$options['date_label_position']) { $ctl_attrs['#date_label_position'] = $options['date_label_position']; } $list=array(); break; case 'checkbox': if (@$option_str['return_value']) { $ctl_attrs['#return_value'] = $options['return_value']; } $list=array(); break; case 'radios': break; case 'hidden': $list=array(); break; default: $type = 'textfield'; $list = array(); } if (isset($menu_parms[$id]) && $type=='textfield') { $disabled = TRUE; } //If a data_source attr was found then create an array of $form['params'][$id] = array( '#type' => $type, '#title' => ($label) ? t($label) : t($id), '#default_value' => $value, '#disabled' => $disabled, '#required' => $required, '#description' => t($desc), ); $form['params'][$id] = array_merge($form['params'][$id], $ctl_attrs); if ($type == 'item') { $form['params'][$id]['#markup'] = $value; } if ($type == 'hidden') { $form['params'][$id]['#value'] = $value; } // Add class to parmeter form. if ($class) { $form['params'][$id]['#attributes'] = array( 'class' => @explode(' ', $class), ); } //if $list is not empty then push options //onto the array. options will cause an error for //textfield elements. if ($list || $type == 'select' || $type =='radios') { if ($add_null) { $prompt = @$options['prompt']; if (!$prompt) $prompt = $required ? '-' . t('select') . '-' : '-' .t('none') . '-'; $form['params'][$id]['#empty_option'] = $prompt ; } $form['params'][$id]['#options'] = $list; $form['params'][$id]['#multiple'] = $multiselect; } if ($ajax) { $form['params'][$id]['#ajax'] = array('callback' => 'forena_parameters_callback', 'wrapper' => 'parameters-wrapper'); } } if ($template) { $form['params']['#forena-template'] = $template; $form['params']['#theme'] = 'forena_fieldset_template'; _forena_set_inline_theme($form['params']); } $form['params']['submit'] = array( '#type' => 'submit', '#value' => $submit_value, ); } return $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['params']['submit']); if (isset($values['params'])) foreach ($values['params'] as $key => $value) { $ctl = $form['params'][$key]; switch($ctl['#type']) { case 'date_popup': case 'date_select': case 'date_text': $datetime = @strtotime($value); if ($datetime) { $value = $values['params'][$key] = date($ctl['#forena_date_format'], $datetime); } break; } if (is_array($value)) { $values['params'][$key] = array(); foreach ($value as $k => $val) { if ($val) { $values['params'][$key][] = $val; } } } else { if (strpos($value, '|')!==FALSE) { $values['params'][$key] = explode('|', $value); } elseif ($value==='' || $value===NULL) { unset($values['params'][$key]); } } } $form_state['redirect']= array($_GET['q'], array('query' => @$values['params'])); } /** * Ajax form callback function * Enter description here ... * @param unknown_type $form * @param unknown_type $form_state */ function forena_parameters_callback($form, &$form_state) { return $form['params']; } /** * Implementation of hook_perm * * @return unknown */ function forena_permission() { $perms = array( 'administer forena reports' => array('title' => t('Administer Forena Reports')), 'access demo reports' => array('title' => t('Access Demo Reports')), 'list reports' => array('title' => t('List reports')), 'create any report' => array('title' => t('Create a report')), 'design any report' => array('title' => t('Design reports')), 'delete report' => array('title' => t('Delete reports')), 'perform email merge' => array('title' => t('Peform email merge')), 'access forena block xml' => array('title' => t('Access data from data blocks directly'), 'description' => t('Useful for ajax calls to data blocks')), ); foreach (Frx::RepoMan()->repositories as $repos => $conf) { $name = $conf['title'] ? $conf['title'] : $repos; $perms['access '. $repos . ' data'] = array('title' => 'Access ' . $name . ' Data'); } return $perms; } function forena_user_reports($category = '') { require_once('forena.common.inc'); $output=''; $reports = forena_get_user_reports($category); $report_repos = variable_get('forena_path', 'reports'); if (!$reports) { $output = 'No Reports Found'; } $links = ''; foreach ($reports as $category => $reports) { $links .= '
  • ' . $category . '
  • '; $output .= '

    ' . $category . '

    '; $output .= ''; } return $output; } /** * Tries to load data tables libary and other libraries that help. */ 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); } $lib = 'sites/all/libraries/FixedHeader/js/FixedHeader.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 = NULL, $print = TRUE, $filename='') { require_once('forena.common.inc'); $desc = Frx::Menu()->parseURL($name_in); $time = @new DateTime($value); $desc['time'] = date_format($time, 'Y-m-d H:i:s'); $desc['basepath'] = base_path(); if (!$desc['exists']) { watchdog('error', 'Report %s not found', array('%s' => $name_in), WATCHDOG_ERROR); if($print) { drupal_not_found(); exit; } return ''; } FrxData::instance()->setContext('cookie', $_COOKIE); FrxData::instance()->setContext('report', $desc); $report_name = $desc['name']; // Load dataTable plugin if possible. //forena_include_data_tables(); $content = Frx::Editor($name_in, FALSE)->report($parms, $print, FALSE, $filename); $m_path = drupal_get_path('module', 'forena'); if ($content) { // This has been deprecated, but we'll eave it in for now. if ($print) drupal_add_js($m_path . '/forena.js'); $forena_js = array(); $forena_js['form'] = preg_replace('/[^\w\-]+/u', '_', Frx::Skin()->name); $forena_js['report'] = preg_replace('/[^\w\-]+/u', '_', $name_in); if ($print) drupal_add_js(array('forena' => $forena_js), 'setting'); } if (!$print && is_array($content)) { return drupal_render($content['content']); } return $content; } /** * Render report as an inlcude. Don't perform the output fuctnions for the document * @param $report_name String * @param $parms array of parameters to include */ function forena_report_include($report_name, $parms=array()) { $output = ''; require_once 'forena.common.inc'; $desc= Frx::Menu()->parseURL($report_name); $name = $desc['name']; $r = @FrxReportGenerator::instance()->get_report($name, $parms); if (!$r || !$r->rpt_xml) { return ''; } //check for default parameters $r->processParameters(); $format = $desc['format']; $r->render($format, FALSE); $o = Frx::Document($format); if ($o) { $output = $o->render($r, $format, array()); } return $output; } /** * Menu callback for rendering the forena report. */ function forena_report_menu_callback() { $args = func_get_args(); $path = array_shift($args); $report_name = array_shift($args); $parms = $_GET; unset($parms['q']); $menu_parms = array(); $tokens = Frx::Menu()->tokens($path); if ($args && $tokens) { foreach ($args as $i=> $value) { @$menu_parms[$tokens[$i]] = $value; } } Frx::Data()->setContext('menu-parms', $menu_parms); $parms = array_merge($parms, $menu_parms); $output = forena_report($report_name, $parms); if ($output) return $output; } /** * Used in hook_menu to test access to menu items. * @param $checks array key value of callbacks and args to check. */ function forena_check_all_access($checks) { // Check each callback function to see if we have an error. $access = FALSE; // Check each callback function to see if we have an error. if ($checks) foreach ($checks as $provider => $callbacks) { if (user_access('access ' . $provider . ' data')) foreach ($callbacks as $callback=>$args) { if ($callback) foreach ($args as $arg) { if (function_exists($callback) && $arg) { $a = $callback($arg); if ($a) $access = TRUE; } else { $access = TRUE; } } else { $access = TRUE; } } } return $access; } /** * Callback for setting international titles * @param $report_name string name of report * @param $use_menu_title boolean indicate wether to use menu title attribute. */ function forena_report_title_callback($report_name, $use_menu_title=TRUE) { $title = ''; $info = Frx::File()->getReportCacheInfo($report_name); if ($info) { $title = $use_menu_title && $info && isset($info->cache['menu']['title']) ? $info->cache['menu']['title']: $info->cache['title']; } return $title; } /** * 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, $print); //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() { $path = drupal_get_path('module', 'forena'); $plugins['FrxPDO'] = array('file' => 'plugins/FrxPDO.inc', 'parent' => 'FrxDataSource', 'class' => 'FrxPDO', 'path' => $path, ); $plugins['FrxOracle'] = array('file' => 'plugins/FrxOracle.inc', 'parent' => 'FrxDataSource', 'class' => 'FrxOracle', 'path' => $path, ); $plugins['FrxDrupal'] = array( 'file' => 'plugins/FrxDrupal.inc', 'parent' => 'FrxDataSource', 'class' => 'FrxDrupal', 'path' => $path, ); $plugins['FrxFiles'] = array('file' => 'plugins/FrxFiles.inc', 'parent' => 'FrxDataSource', 'class' => 'FrxFiles', ); $plugins['FrxPostgres'] = array('file' => 'plugins/FrxPostgres.inc', 'class' => 'FrxPostgres', 'parent' => 'FrxDataSource' ); $plugins['FrxMSSQL'] = array('file' => 'plugins/FrxMSSQL.inc', 'parent' => 'FrxDataSource', 'class' => 'FrxMSSQL', 'path' => $path, ); // Normally you wouldn't do this but I wanted to make the FrxReport sytax work. $plugins['FrxReport'] = array( 'file' => 'plugins/FrxReportContext.inc', 'parent' => 'FrxContext', 'class' => 'FrxReportContext', 'path' => $path, ); return $plugins; } /** * Self register document formats with Forena * */ function forena_forena_document_types() { require_once 'docformats/FrxWebDoc.inc'; require_once 'docformats/FrxCSVDoc.inc'; require_once 'docformats/FrxHtmlDoc.inc'; require_once 'docformats/FrxSVGDoc.inc'; require_once 'docformats/FrxWordDoc.inc'; require_once 'docformats/FrxXLSDoc.inc'; require_once 'docformats/FrxXMLDoc.inc'; require_once 'docformats/FrxEmailMergeDoc.inc'; $items['web'] = array( 'class' => 'FrxWebDoc', 'title' => t('Themed Drupal Page'), ); $items['csv'] = array( 'class' => 'FrxCSVDoc', 'title' => t('Comma separated values'), ); $items['email'] = array( 'class' => 'FrxEmailMergeDoc', 'title' => t('Email Merge Document'), ); $items['html'] = array( 'class' => 'FrxHtmlDoc', 'title' => t('Unthemed HTML'), ); $items['svg'] = array( 'class' => 'FrxSVGDoc', 'title' => t('SVG Document'), ); $items['doc'] = array( 'class' => 'FrxWordDoc', 'title' => t('MS Word Document format'), ); $items['xls'] = array( 'class' => 'FrxXLSDoc', 'title' => t('Excel Document'), ); $items['xml'] = array( 'class' => 'FrxXMLDoc', 'title' => t('XML Document'), ); return $items; } /** * 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' => 'renderers/FrxSection.inc', 'class' => 'FrxSection', ); $controls[] = array( 'file' => 'renderers/FrxCrosstab.inc', 'class' => 'FrxCrosstab', ); $controls[] = array( 'file' => 'renderers/FrxEmailMerge.inc', 'class' => 'FrxEmailMerge', ); $controls[] = array( 'file' => 'renderers/FrxFieldTable.inc', 'class' => 'FrxFieldTable', ); $controls[] = array( 'file' => 'renderers/FrxRenderer.inc', 'class' => 'FrxRenderer', ); $controls[] = array( 'file' => 'renderers/FrxTable.inc', 'class' => 'FrxTable', ); $controls[] = array( 'file' => 'renderers/FrxMergeDocument.inc', 'class' => 'FrxMergeDocument', ); $controls[] = array( 'file' => 'renderers/FrxSource.inc', 'class' => 'FrxSource', ); $controls[] = array( 'file' => 'renderers/FrxXML.inc', 'class' => 'FrxXML', ); $controls[] = array( 'file' => 'renderers/FrxInclude.inc', 'class' => 'FrxInclude', ); $controls[] = array( 'file' => 'renderers/FrxMyReports.inc', 'class' => 'FrxMyReports', ); $controls[] = array( 'file' => 'renderers/FrxParameterForm.inc', 'class' => 'FrxParameterForm', ); $controls[] = array( 'file' => 'renderers/FrxTitle.inc', 'class' => 'FrxTitle', ); if (forena_library_file('SVGGraph')) { $controls[] = array( 'file' => 'renderers/FrxSVGGraph.inc', 'class' => 'FrxSVGGraph' ); } return $controls; } /** * Implementation of forena_report_directory hook. */ function forena_forena_report_directory() { return drupal_get_path('module', 'forena') . '/repos/reports'; } /** * Load the report repository path * * @return unknown */ function forena_report_path() { return Frx::File()->dir; } /** * Rename function for backwards compatibility */ function forena_current_user_uid() { return forena_current_user_id(); } /** * Helper function for current user for the drupal instance * * @return unknown */ function forena_current_user_id() { global $user; return $user->uid; } /** * Helper function for current user for the drupal instance * * @return unknown */ function forena_current_user_name() { global $user; if (isset($user->name)) return $user->name; } /** * Implememntation of hook_filter */ function forena_filter_info() { $filters['forena_report'] = array( 'title' => t('Embed Forena Reports'), 'description' => t('Allows you to embed a report in a text'), 'process callback' => '_forena_filter_process', 'cache' => FALSE, ); return $filters; } /** * Process tag replacement for xml filters */ function _forena_filter_process($text='') { require_once('forena.admin.inc'); GLOBAL $language; // 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); // Render it $output = forena_report($report_name, $parms, FALSE); // 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'][] = $body; if (isset($parms['headers'])) $message['headers'] += $parms['headers']; $htmlmail = FALSE; break; } } /** * Make sure a drectory exists in the report path prior to save. * * @param $fullpath Full path to the drectory to be copied * @param $recursive Whether we are in a recursive call. */ function _forena_verify_directory($fullpath, $recursive=FALSE) { static $path=''; $success = TRUE; if (!$recursive) { $path = forena_report_path(); if (!is_writable($path)) { drupal_set_message(t('Report directory %s is not modifiable', array('%s' => $path)), 'error', FALSE); return FALSE; } } @list($dir, $file) = explode('/', $fullpath, 2); $path .= '/' . $dir; // Path if (!file_exists($path) && $file) { @mkdir($path); if (!@is_writable($path)) { drupal_set_message(t('Error creating directory %path', array('%path' => $path)), 'error'); return FALSE; } } // Recurse to next file. if ($file && strpos($file, '/')) { _forena_verify_directory($file, TRUE); } return TRUE; } /** * Recursively , all report files from the source directory to the destination directory * @param $src_dir Source directory to copy files from */ function _forena_revert_reports($subdir = '') { static $cnt = 0; $cnt++; if ($cnt > 100) return 0; $i = 0; $src_dir = rtrim(Frx::File()->dir, '/'); if ($subdir) $src_dir .= '/' . $subdir; $d = dir($src_dir); while ($d && false !== ($rpt_file = $d->read())) { $src_file = $d->path . '/' . $rpt_file; if (strpos($rpt_file, '.')!==0 && is_file($src_file)) { $filename = $subdir ? "$subdir/$rpt_file" : $rpt_file; $i += Frx::File()->revert($filename); } else { if (strpos($rpt_file, '.')!==0) { // Recurse into sub directory $dir = $subdir ? $subdir . '/' . $rpt_file : $rpt_file; $i += _forena_revert_reports($dir); } } } if ($d) $d->close(); return $i; } /** * * Enter description here ... * @param $copy_reports If true, reports will by re-copied from * module source files to destination. */ function forena_sync_reports($copy_reports=FALSE) { if ($copy_reports) { $i = _forena_revert_reports(); if ($i > 0) drupal_set_message($i . ' reports reverted'); } } function forena_theme() { return array( 'forena_web_report' => array( 'variables' => array('doc_types' => NULL, 'parameters' => NULL, 'content' => NULL), ), 'forena_inline_form_element' => array( 'render element' => 'element', 'file' => 'forena.common.inc', ), 'forena_inline_field' => array( 'render element' => 'field', 'file' => 'forena.common.inc', ), 'forena_fieldset_template' => array( 'render element' => 'fieldset', 'file' => 'forena.common.inc', ), 'forena_data_table' => array( 'file' => 'forena.common.inc', 'variables' => array('header' => NULL, 'data' => NULL), ), 'forena_report_parameters_form' => array( 'file' => 'forena.report.inc', 'render element' => 'form', ), 'forena_element_draggable' => array( 'file' => 'forena.report.inc', 'render element' => 'element', ), ); } /** * Default theme function for forena web reports. * @param $variables Array of variables to theme */ function theme_forena_web_report ($variables) { $output = ''; if (@$variables['parameters']) { $output .= '
    ' . $variables['parameters'] . '
    '; } if (@$variables['doc_links']) { $output .= "'; } $output .= '
    ' . $variables['content'] . '
    '; return $output; } /** * Iemplents hook_views_api * @return multitype:number The Ambigous */ function forena_views_api() { return array( 'api' => 3, 'path' => drupal_get_path('module', 'forena') , 'template path' => drupal_get_path('module', 'forena') , ); } /** * Implements hook_feeds_plugins(). */ function forena_feeds_plugins() { module_load_include('inc', 'forena', 'feeds/forena_feeds'); return _forena_feeds_plugins(); } /** * Implements hook_bean_types_api_info(). */ function forena_bean_types_api_info() { return array('api' => 4); } /** * Implements hook_bean_types(). */ function forena_bean_types() { $plugins = array(); $plugin_path = drupal_get_path('module', 'forena') . '/bean'; $plugins['forena'] = array( 'label' => t('Forena report'), 'description' => t('Display a report.'), 'handler' => array( 'class' => 'FrxBean', 'parent' => 'bean', 'path' => $plugin_path, 'file' => 'FrxBean.inc', ), 'path' => $plugin_path, 'file' => 'FrxBean.inc', ); return $plugins; } /** * Function to reflect back forms that are built by classes * @param $formid * @param $form_state form state array * @param $form array of form elements to be reflected */ function forena_form_reflector($formid, &$form_state, $form) { return $form; } function forena_requirements($phase) { $requirements = array(); switch ($phase) { case 'runtime': $writeable = is_writable(Frx::File()->dir); if (!$writeable) { $requirements['fornea_writable'] = array( 'title' => 'Forena Report Directory', 'value' => Frx::File()->dir, 'severity' => REQUIREMENT_ERROR, 'description' => t('The directory must be writable by the web user in order to create custom reports. '), ) ; } $req = array('severity' => REQUIREMENT_INFO, 'requirement'); $libraries = array('dataTables' ,'mpdf', 'prince', 'SVGGraph' ); foreach ($libraries as $lib) { $requirements['forena_' . $lib] = $req; $requirements['forena_' . $lib]['title'] = "Forena $lib support"; $requirements['forena_' . $lib]['value'] = forena_library_file($lib) ? t('Enabled') : t('Not Enabled:'); $requirements['forena_' . $lib]['severity'] = forena_library_file($lib) ? REQUIREMENT_OK : REQUIREMENT_INFO; } if (!module_exists('forena_pdf')) { unset($requirements['forena_prince']); unset($requirements['forena_mpdf']); } break; } return $requirements; } /** * Custom override of machine_name validate that does not include * @param unknown $element * @param unknown $form_state */ function forena_machine_name_validate($element, &$form_state) { // Verify that the machine name not only consists of replacement tokens. if (preg_match('@^' . $element['#machine_name']['replace'] . '+$@', $element['#value'])) { form_error($element, t('The machine-readable name must contain unique characters.')); } // Verify that the machine name contains no disallowed characters. if (preg_match('@' . $element['#machine_name']['replace_pattern'] . '@', $element['#value'])) { if (!isset($element['#machine_name']['error'])) { // Since a hyphen is the most common alternative replacement character, // a corresponding validation error message is supported here. if ($element['#machine_name']['replace'] == '-') { form_error($element, t('The machine-readable name must contain only letters, numbers, and hyphens.')); } // Otherwise, we assume the default (underscore). else { form_error($element, t('The machine-readable name must contain only letters, numbers, and underscores.')); } } else { form_error($element, $element['#machine_name']['error']); } } } function forena_process_machine_name($element, &$form_state) { $element['#machine_name']['replace_pattern'] = '[^A-Za-z0-9_\.\/]+'; return $element; } /** * Create a derivative to the machine name field with relaxed restrictions. * @return multitype:boolean string NULL number multitype:string */ function forena_element_info() { $types['forena_machine_name'] = array( '#input' => TRUE, '#element_validate' => array('forena_machine_name_validate'), '#default_value' => NULL, '#size' => 60, '#maxlength' => 64, '#required' => TRUE, '#autocomplete_path' => FALSE, '#process' => array( 'form_process_machine_name', 'forena_process_machine_name', 'ajax_process_form', ), '#theme_wrappers' => array('form_element'), '#theme' => 'textfield', ); return $types; }