forena.admin.inc 74.6 KB
Newer Older
1
<?php
metzlerd's avatar
metzlerd committed
2
// $Id$
metzlerd's avatar
metzlerd committed
3
4
/**
 * @file
metzlerd's avatar
metzlerd committed
5
 * Report administration forms and functions.
metzlerd's avatar
metzlerd committed
6
 */
metzlerd's avatar
metzlerd committed
7
require_once('forena.common.inc');
8

9
10
11
12
13
/**
 * Display reports to edit for admins in the structure menu
 * Enter description here ...
 */
function forena_admin_reports() {
14
  GLOBAL $language;
15
  $data = array();
16
  $output = '';
17
  $content = drupal_get_form('forena_sync_form');
18
  $sync_form = drupal_render($content);
19
  $links[] = array('href' => 'reports/add', 'title' => 'Create New Report' );
20
  $output .= theme('links',
21
22
23
24
    array(
      'links' => $links,
      'attributes' => array('class' => 'action-links'),
    )
metzlerd's avatar
metzlerd committed
25
  );
26
  // Add Data tables if it exists.
27
28
  $headers = array(t('category'), t('title'), t('name'), t('operation'));
  $result = Frx::File()->allReports();
29
  foreach ($result as $row) {
30
    $rpt = str_replace('/', '.', $row->name);
31
32
33
34
35
36
    if ($row->include) {
      $edit = l(t('Override'), 'reports/' . $rpt . '/edit');
    }
    else {
      $edit = l(t('Edit'), 'reports/' . $rpt . '/edit');
    }
metzlerd's avatar
metzlerd committed
37
    $clone = l(t('Clone'), 'reports/add/' . $rpt);
38
39
40
41
42
43
44
45
46
47
48
    // Determine the nature of the report delete link.
    if ($row->override) {
      $delete = l(t('Revert'), 'reports/' . $rpt . '/delete', array('query' => array('destination' => 'admin/structure/forena')));
    }
    else if (!$row->include) {
      $delete = l(t('Delete'), 'reports/' . $rpt . '/delete', array('query' => array('destination' => 'admin/structure/forena')));
    }
    else {
      $delete = '';
    }

49
50
    $title = l(t($row->cache['title']), 'reports/' . $rpt);
    $data[] = array($row->cache['category'], $title, $row->name, $edit . ' ' . $clone . ' ' . $delete);
51
  }
52
  $output .= '<div id="forena-reports-list">';
53
  $output .= theme('forena_data_table', array('header' => $headers, 'rows' => $data));
54
  $output .= '</div>';
55
  $output .= $sync_form;
56
57
58
  return $output;
}

59
/**
metzlerd's avatar
metzlerd committed
60
 * Remove the report from the database and file system.
61
62
 * @param string $report_name
 */
63
function forena_delete_report($report_name) {
64

65
  $filepath = $report_name . '.frx';
66
  $do = Frx::File()->delete($filepath);
67
68
}

metzlerd's avatar
metzlerd committed
69

70
71


72
function forena_filter_element($fmt, $name) {
metzlerd's avatar
metzlerd committed
73
74
75
76
  global $user;
  $element['format'] =  array(
    '#type' => 'fieldset',
    '#collapsible' => TRUE,
77
    '#collapsed' => $fmt!='',
metzlerd's avatar
metzlerd committed
78
79
    '#title' => t('Input formats'),
  );
80
  if (!$fmt) $fmt='full_html';
metzlerd's avatar
metzlerd committed
81
  // Get a list of formats that the current user has access to.
metzlerd's avatar
metzlerd committed
82
83
84
85
86
  $formats = filter_formats($user);
  foreach ($formats as $format) {
    $options[$format->format] = $format->name;
    $element['format']['guidelines'][$format->format] = array(
      '#theme' => 'filter_guidelines',
87
      '#required' => TRUE,
metzlerd's avatar
metzlerd committed
88
89
90
91
92
      '#format' => $format,
    );
  }
  $element['format']['guidelines']['#weight']=12;

93
  $element['format'][$name] = array(
metzlerd's avatar
metzlerd committed
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
    '#type' => 'select',
    '#title' => t('Text format'),
    '#options' => $options,
    '#default_value' => $fmt,
    '#access' => count($formats) > 1,
    '#weight' => 10,
    '#attributes' => array('class' => array('filter-list')),
  );

  $element['format']['help'] = array(
    '#type' => 'container',
    '#theme' => 'filter_tips_more_info',
    '#attributes' => array('class' => array('filter-help')),
    '#weight' => 11,
  );
metzlerd's avatar
metzlerd committed
109
  return $element['format'];
metzlerd's avatar
metzlerd committed
110
}
111

metzlerd's avatar
metzlerd committed
112
113


114
/**
115
116
117
 * Report syncronization form
 * @param $formid
 * @param $form_state
118
 */
119
function forena_sync_form($formid, &$form_state) {
120
121
122
123

  $form['sync_overwrite'] = array(
    '#type' => 'checkbox',
    '#title' => t('Revert all delivered reports to orignial'),
124
    '#required' => TRUE,
125
126
127
    '#description' => t('All customizations to module delivered reports will be lost.')
  );

128
129
  $form['sync'] = array(
    '#type' => 'submit',
130
    '#value' => t('Revert'),
131
132
    '#submit' => array('forena_settings_sync_submit'),
  );
133
134

  return $form;
135
136
137
138
139
140
141
142

}

/**
 * Forena admin settings form
 *
 */
function forena_settings() {
143
  $skins = Frx::File()->skins();
144
145
146

  $report_path = forena_report_path();

147

148
149
150
  $form['forena_report_repos'] = array(
    '#type' => 'textfield',
    '#title' => t('Report Repository'),
metzlerd's avatar
metzlerd committed
151
152
153
154
155
156
    '#description' => t('Indicate the directory that you want to use for your reports.  In order for you to ' .
                        'to be able to save reports, this directory should be writable by the web user. Relative' .
                        'paths should be entered relative to the base path of your drupal installation.'),
    '#default_value' => $report_path,
  );

157
158
  $form['forena_last_report_path'] = array(
    '#type' => 'value',
159
    '#value' => variable_get('forena_report_repos', '')
metzlerd's avatar
metzlerd committed
160
161
  );

162
163
164
165
166
167
168
169
170
171
172
173
174
  if (module_exists('forena_query')) {
      $form['forena_query_data_path'] = array(
        '#type' => 'textfield',
        '#title' => t('Custom Data Block Repository'),
        '#description' => t('Indicate the directory that you want to use to save custom created data blocks using
            the forena query builder tool.  These will override any module delivered data blocks.  This needs to
            be a directory that is writable by the web user but should not be browsable by the web.  It defaults to
            '),
        '#default_value' => Frx::DataFile()->dir,
      );

      $form['forena_last_query_data_path'] = array(
          '#type' => 'value',
175
          '#value' =>  variable_get('forena_query_data_path', '')
176
177
178
      );

  }
179

180
  $form['forena_input_format'] = forena_filter_element(variable_get('forena_input_format', filter_default_format()), 'forena_input_format');
181
  $form['forena_default_form'] = array(
182
    '#type' => 'select',
183
    '#title' => t('Default report skin'),
184
    '#options' => $skins,
185
    '#description' => t('Specify the default skin to be used.   New skins can be created by creating .skinfo files in your reports directory.'
metzlerd's avatar
metzlerd committed
186
    . ' Skins are basically css and javascript libraries added to your report.'),
metzlerd's avatar
metzlerd committed
187
    '#default_value' => variable_get('forena_default_form', ''),
metzlerd's avatar
metzlerd committed
188
    );
metzlerd's avatar
metzlerd committed
189

metzlerd's avatar
metzlerd committed
190
191
    $form =  system_settings_form($form);
    return $form;
metzlerd's avatar
metzlerd committed
192

193
}
194
195

function forena_settings_validate($form, &$form_state) {
metzlerd's avatar
metzlerd committed
196
  $values = $form_state['values'];
197
  $path = $values['forena_report_repos'];
198
  if ($path != $values['forena_last_report_path']) {
199
200
201
    if (!file_exists($path)) {
      try {
        if (file_exists($path)) {
202
          drupal_set_message(t('Created directory %s', array('%s' => $path))) ;
203
204
        }
        mkdir($path);
205

206
207
208
209
      } catch (Exception $e) {
        forena_error(t('Unable to create report directory'), $e->getMessage());
      }
    }
metzlerd's avatar
metzlerd committed
210
  }
211
212
213
214
215
216
217
218
219
220
221
  if (!file_exists($path) || !is_writable($path)) {
    form_set_error('forena_report_repos', 'Report Directory must be writable by the web user');
  }
  if ($values['forena_query_data_path']) {
    $path = $values['forena_query_data_path'];
    if ($path != $values['forena_last_query_data_path']) {
      if (!file_exists($path)) {
        try {

          mkdir($path);
          if (file_exists($path)) {
222
            drupal_set_message(t('Created directory %s', array('%s' => $path))) ;
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
          }

        } catch (Exception $e) {
          forena_error(t('Unable to create data directory'), $e->getMessage());
        }
      }
    }
    if (!file_exists($path) || !is_writable($path)) {
      form_set_error('forena_query_data_path', 'Data Directory must be writable by the web user');
    }
  }


}


/**
 * Added submit handler to create directories and clear menu cache
 *
 * @param unknown_type $form
 * @param unknown_type $form_state
 */
function forena_settings_submit($form, &$form_state) {
246
}
metzlerd's avatar
metzlerd committed
247

248
function forena_settings_sync_submit($form, &$form_state) {
249
  forena_sync_reports($form_state['values']['sync_overwrite']);
250
  drupal_set_message(t('Report cache cleared'));
251
}
252

253
function forena_format_form($formid, $form_state, $report_name) {
metzlerd's avatar
metzlerd committed
254
  $desc = Frx::Menu()->parseURL($report_name);
255
  $name = $desc['name'];
256

257
258
259
  $filename = $desc['filename'];
  $format = isset($desc['format']) ? $desc['format'] : '';
  if ($desc['exists']) {
260
    $r = Frx::Editor($name);
261
262
263
264
265
    drupal_set_title($r->title);
    $form = array();
    $frx_options = $r->getOptions();
    $report_form = @$frx_options['form'];

266
    $doclist = Frx::Menu()->doc_formats;
267
268
    $skins[''] = t('Use Default');
    $skins = array_merge(variable_get('forena_skins', array()), $skins);
269

metzlerd's avatar
metzlerd committed
270
271
272
273
    $form['report_name'] = array(
       '#type' => 'value',
       '#value' => $name,
    );
274

metzlerd's avatar
metzlerd committed
275
    $form['form'] = array(
276
      '#type' => 'select',
277
      '#title' => t('Skin'),
278
      '#options' => $skins,
metzlerd's avatar
metzlerd committed
279
      '#default_value' => $report_form,
metzlerd's avatar
metzlerd committed
280
      '#description' => t('The page style of your report.  The {skin}.skinfo file specifies css and js file in your report.')
metzlerd's avatar
metzlerd committed
281
    );
282

metzlerd's avatar
metzlerd committed
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
    //begin checking doc generation options
    if ($r) $nodes = $r->simplexml->head->xpath('frx:docgen/frx:doc');
    if ($doclist) {
      $form['docgen'] = array(
       '#tree' => TRUE,
       '#type' => 'fieldset',
       '#title' => t('Document Options'),
       '#description' => t('These are document transformation options. Options selected will display as links in your report view.')
      );

      //build the options and default list
      $options = array();
      $default = array();
      foreach ($doclist as $value) {
        $options[$value] = strtoupper($value);
        $doc =  isset($r) ? $r->simplexml->head->xpath('frx:docgen/frx:doc[@type="' . $value . '"]') : '';
metzlerd's avatar
metzlerd committed
299
        if ($doc && array_search($value, $doclist)!==FALSE) {
metzlerd's avatar
metzlerd committed
300
          $default[$value] = $value;
301
        }
metzlerd's avatar
metzlerd committed
302
      }
303

metzlerd's avatar
metzlerd committed
304
305
306
307
308
309
310
      //display checkboxes
      $form['docgen']['docs'] = array(
        '#type' => 'checkboxes',
        '#description' => t('If no options are selected, the system will display all of the above as available for this report.'),
        '#options' => $options,
        '#default_value' => $default
      );
311

312
313
314
315
316
      $form['update'] = array(
        '#type' => 'submit',
        '#value' => 'Update',
      );

metzlerd's avatar
metzlerd committed
317
318
319
      $form['submit'] = array(
        '#type' => 'submit',
        '#value' => 'Save',
320
        '#submit' => array('forena_format_form_submit', 'forena_save_submit'),
metzlerd's avatar
metzlerd committed
321
      );
322
323
324
325
326

      $form['cancel'] = array(
        '#type' => 'submit',
        '#value' => 'Cancel',
        '#submit' => array('forena_save_cancel'),
metzlerd's avatar
metzlerd committed
327
328
      );

metzlerd's avatar
metzlerd committed
329
    }
330
331
332
333
334
  }
  return $form;
}

function forena_format_form_submit($form, &$form_state) {
metzlerd's avatar
metzlerd committed
335
  $values = $form_state['values'];
336
337
  $name = $values['report_name'];

338
  $r = Frx::Editor();
339
340
341
342
343
344
345
346
  $options = array(
    'form' => $values['form']);
  $r->setOptions($options);


  // Doc gen settings.
  if (isset($form['docgen'])) {
    $docgen = array();
metzlerd's avatar
metzlerd committed
347
    if ($selected = array_filter(@$values['docgen']['docs'])) {
348
      if ($selected) foreach ($selected as $key => $value) {
metzlerd's avatar
metzlerd committed
349
        if ($value) $docgen[] = array('type' => $key);
350
351
352
353
354
      }
    }
    $r->setDocgen($docgen);
  }

355
  $r->update();
356
357

}
358

metzlerd's avatar
metzlerd committed
359
function forena_general_form($form, &$form_state, $report_name) {
metzlerd's avatar
metzlerd committed
360
  $name_in = $report_name;
metzlerd's avatar
metzlerd committed
361
  $desc = Frx::Menu()->parseURL($report_name);
metzlerd's avatar
metzlerd committed
362
363
364
  $name = $desc['name'];
  $filename = $desc['filename'];
  $format = @$desc['format'];
metzlerd's avatar
metzlerd committed
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
  $save_name = $name;
  //set the name to empty string for new reports
  $r = Frx::Editor($name);
  $title = (string)$r->title;
  drupal_set_title(filter_xss($r->title));
  $frx_options = $r->getOptions();
  $hidden = @$frx_options['hidden']=='1' ? 1 : 0;
  $report_form = @$frx_options['form'];
  $category = $r->getCategory();
  $menu = $r->getMenu();
  $cache = $r->getCache();
  $form['report_name'] = array(
    '#type' => 'value',
    '#value' => $name,
  );
metzlerd's avatar
metzlerd committed
380

metzlerd's avatar
metzlerd committed
381
382
383
384
385
  $form['title'] = array(
    '#type' => 'textfield',
    '#title' => t('Title'),
    '#default_value' => $title,
  );
386

metzlerd's avatar
metzlerd committed
387
388
389
390
  $form['visibility'] = array(
    '#type' => 'fieldset',
    '#title' => t('Visibility'),
  );
391

metzlerd's avatar
metzlerd committed
392
393
394
395
396
397
398
  $form['visibility']['category'] = array(
    '#type' => 'textfield',
    '#title' => t('Category'),
    '#default_value' => $category,
    '#autocomplete_path' => 'forena/categories/autocomplete',
    '#description' => t('The heading your report will be grouped under on the report list.'),
  );
metzlerd's avatar
metzlerd committed
399

metzlerd's avatar
metzlerd committed
400
401
402
403
404
405
  $form['visibility']['hidden'] = array(
    '#type' => 'checkbox',
    '#title' => t('Hidden'),
    '#default_value' => $hidden,
    '#description' => t('Hide your report from showing up on the report list.'),
  );
metzlerd's avatar
metzlerd committed
406

metzlerd's avatar
metzlerd committed
407
408
409
410
411
412
413
  $form['menu'] = array(
    '#type' => 'fieldset',
    '#title' => t('Menu'),
    '#tree' => TRUE,
    '#collapsible' => TRUE,
    '#collapsed' => empty($menu),
  );
414

metzlerd's avatar
metzlerd committed
415
416
417
418
419
420
  $form['menu']['path'] = array(
    '#type' => 'textfield',
    '#title' => t('Menu Path'),
    '#description' => t('Indicate site reletive path to menu.  Parameters may be embedded in the url using a :parm syntax (e.g. states/:state)'),
    '#default_value' => @$menu['path'],
  );
421

metzlerd's avatar
metzlerd committed
422
423
424
425
426
427
  $form['menu']['args'] = array(
    '#type' => 'textfield',
    '#title' => t('Additional Arguments'),
    '#description' => t('Indicate additonal parameters that should be extracted after the menu path using a :parm syntax (e.g. :parma/:parmb)'),
    '#default_value' => @$menu['args'],
  );
428

metzlerd's avatar
metzlerd committed
429
430
431
432
433
434
  $form['menu']['title'] = array(
    '#type' => 'textfield',
    '#title' => t('Menu Title'),
    '#description' => t('Title of menu item.  Leave blank to use the report title as the menu title.'),
    '#default_value' => @$menu['title'],
  );
435

metzlerd's avatar
metzlerd committed
436
437
438
439
440
441
  $menu_options = array(
    'normal-item' => t('Normal'),
    'local-task' => t('Tab'),
    'default-local-taks' => t('Default Tab'),
    'callback' => t('Callback'),
  );
442

metzlerd's avatar
metzlerd committed
443
444
445
446
447
448
  $form['menu']['type'] = array(
    '#type' => 'select',
    '#title' => 'Type of menu to create',
    '#options' => $menu_options,
    '#default_value' => @$menu['type'],
  );
449

metzlerd's avatar
metzlerd committed
450
451
452
453
454
455
456
  $form['cache'] = array(
    '#type' => 'fieldset',
    '#title' => t('Cache'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
    '#tree' => TRUE,
  );
457

metzlerd's avatar
metzlerd committed
458
459
460
461
462
463
  $form['cache']['duration'] = array(
    '#type' => 'textfield',
    '#title' => t('Duration'),
    '#description' => t('Specify a php strtotime relative date duration, (e.g. +1 hour, +2 days)'),
    '#default_value' => @$cache['duration'],
  );
464

metzlerd's avatar
metzlerd committed
465
466
467
468
469
  $form['cache']['per_user'] = array(
    '#type' => 'checkbox',
    '#title' => t('Per User'),
    '#default_value' => @$cache['per_user'],
  );
470

metzlerd's avatar
metzlerd committed
471
472
473
474
475
  $form['cache']['per_doctype'] = array(
    '#type' => 'checkbox',
    '#title' => t('Per Document Type'),
    '#default_value' => @$cache['per_doctype'],
  );
476

metzlerd's avatar
metzlerd committed
477
478
479
480
  $form['update'] = array(
    '#type' => 'submit',
    '#value' => 'Update',
  );
481

metzlerd's avatar
metzlerd committed
482
483
484
485
486
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Save',
    '#submit' => array('forena_general_form_submit', 'forena_save_submit'),
  );
487

metzlerd's avatar
metzlerd committed
488
489
490
491
492
  $form['cancel'] = array(
    '#type' => 'submit',
    '#value' => 'Cancel',
    '#submit' => array('forena_save_cancel'),
  );
493

metzlerd's avatar
metzlerd committed
494
  return $form;
495
}
496

metzlerd's avatar
metzlerd committed
497
function forena_general_form_validate($form, &$form_state) {
498
  $values = $form_state['values'];
metzlerd's avatar
metzlerd committed
499
500
501
502
503
  if ($values['menu']['path']) {
    if (!valid_url(str_replace(':', '', $values['menu']['path']), FALSE)) {
      form_set_error('menu][path', t('Invalid Path'));
    }
  }
504
505
506
507
508
509
510
511
  if ($values['cache']['duration']) {
    try {
      $time = @new DateTime($values['cache']['duration']);
    }
    catch (Exception $e) {
    }
    if (!$time) form_set_error('cache][duration' , t('Invalid Cache Duration'));
  }
512
}
513

metzlerd's avatar
metzlerd committed
514
function forena_general_form_submit($form, &$form_state) {
515
516
  $values = $form_state['values'];
  $report_name = $values['report_name'];
517
  $r = Frx::Editor();
metzlerd's avatar
metzlerd committed
518

519
520
521
522
523
524
525
526
  // Title and category
  $r->setTitle($values['title']);
  $r->setCategory($values['category']);
  // Form options
  $options = array(
    'hidden' => $values['hidden'],
  );
  $r->setOptions($options);
metzlerd's avatar
metzlerd committed
527
528
529
530
531
  $menu = $r->getMenu();
  if ($values['menu']!= $menu) {
    $r->setMenu($values['menu']);
    $rebuild_menu = TRUE;
  }
532

533
534
535
536
537
  $cache = $r->cache;
  if ($values['cache']!=$cache) {
    $r->setCache($values['cache']);
  }

metzlerd's avatar
metzlerd committed
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
  $r->update();
}

/**
 * Form function for the edit report form
 * @param $form_state
 * @return the form
 */
function forena_layout_form($form, &$form_state, $report_name) {
  $desc = Frx::Menu()->parseURL($report_name);
  $name = $desc['name'];
  $r = Frx::Editor($name);
  drupal_set_title(filter_xss($r->title));
  // Need to get all option attributes
  $frx_options = $r->getOptions();
  $report_form = @$frx_options['form'];
  $attributes = $r->get_attributes_by_id();
  $body = $r->simplexml->body->asXML();
  $css = @(string)$r->simplexml->head->style;

  //array of xml attributes that are required to have a value
  $required = array('id' => TRUE, 'label' => TRUE);

  $form['report_name'] = array(
    '#type' => 'value',
    '#value' => $name,
  );

  $form['attributes'] = array(
    '#type' => 'value',
    '#value' => $attributes,
  );


  $form['body'] = array(
    '#type' => 'text_format',
    '#title' => t('Body'),
    '#default_value' => $body,
    '#rows' => 25,
  '#format' => variable_get('forena_input_format', filter_default_format())
  );

  $form['style'] = array(
    '#type' => 'fieldset',
    '#title' => t('CSS Styles'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
  );

  $form['style']['css'] = array(
    '#type' => 'textarea',
    '#default_value' => $css,
    '#description' => t('Specify small css snipets that can be used in the reports.'),
    '#rows' => 10,
    '#cols' => 80,
  );

  $form['buttons']['update'] = array(
    '#type' => 'submit',
    '#value' => 'Update',
    '#submit' => array('forena_layout_form_submit'),
  );

  $form['buttons']['save'] = array(
    '#type' => 'submit',
    '#value' => 'Save',
    '#submit' => array('forena_layout_form_submit', 'forena_save_submit'),
  );

  $form['buttons']['cancel'] = array(
    '#type' => 'submit',
    '#value' => 'Cancel',
    '#submit' => array('forena_save_cancel'),
  );  return $form;

  if (user_access('delete report')) {
    $form['buttons']['delete'] = array(
      '#type' => 'submit',
      '#value' => 'Delete',
      '#submit' => array('forena_edit_delete_submit'),
    );
  }
  return $form;
}

function forena_layout_form_validate($form, &$form_state) {
  $values = $form_state['values'];
  $body = $values['body']['value'];
  $doc_prefix = '<?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE root [
    <!ENTITY nbsp "&#160;">
    ]>';
  if ($body) {
    $body_doc = new DOMDocument('1.0', 'UTF-8');
    $body_xml =  $doc_prefix . '<html xmlns:frx="urn:FrxReports">' . $body . '</html>';
    if (@$body_doc->loadXML($body_xml) === FALSE) {
      form_set_error('body', t('Invalid XHTML Document. Check for unclosed tags or stray &'));
    }
  }

}

/**
 * builds a string of the xml document,
 * submits it to forena_save_report.
 */
function forena_layout_form_submit($form, &$form_state) {
  $nodes = array();
  $rebuild_menu = FALSE;
  $values = $form_state['values'];
  $report_name = $values['report_name'];
  $r = Frx::Editor();


652
653
  // Body
  $r->setBody($values['body']['value']);
654
655
  // CSS
  $r->setStyle($values['css']);
656
  // If there are no frx attributes in the body then replace them with the old values.
657
  $frx_nodes = $r->simplexml->xpath('body//*[@frx:*]');
658
659
660
661
  if (!$frx_nodes) {
    $r->save_attributes_by_id($values['attributes']);
  }

662
  $r->update();
metzlerd's avatar
metzlerd committed
663
  // If we changed the menu we need to rebuild it.
664

665
666
667
}


668
669
670
671
672
/**
 * Handle delete buttons from edit forms.
 * @return unknown_type
 */
function forena_edit_delete_submit($form, &$form_state) {
metzlerd's avatar
metzlerd committed
673
  $link = 'reports/' . $form_state['values']['name_in'] ;
674
675
676
677
678
679
680
681
682
683
684
685
686
687
  $destination = '';
  if (isset($_REQUEST['destination'])) {
    $destination = drupal_get_destination();
    unset($_REQUEST['destination']);
  }
  $form_state['redirect'] = array('path' => $link . '/delete', 'query' => array('destination' => $destination));
}


function forena_add_report_form($formid, $form_state, $report_name='') {
  $name = '';
  $filename = '';
  $format = '';
  if ($report_name) {
metzlerd's avatar
metzlerd committed
688
    $desc = Frx::Menu()->parseURL($report_name);
689
    $name = $desc['name'];
690
691
692
    $filename = $desc['filename'];
    $format = @$desc['format'];
  }
693
694
695
696
  $form = array();
  global $language;
  //determine if this is an add new report request

697
  $r = Frx::Editor($name);
698
699
700
701
702
703
704
705
706
  $title = (string)$r->title;
  if (module_exists('locale')) {
    @list($tlang,  $tsave_name) = explode('/', $name, 2);
    // FInd out if the starting name of the report is an installed language.
    if (array_key_exists($tlang, language_list() )) {
      $lang = $tlang;
      $save_name = $tsave_name;
    }
    else {
metzlerd's avatar
metzlerd committed
707
      $lang = 'en';
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
    }
  }
  // Need to get all option attributes
  $frx_options = $r->getOptions();
  $hidden = @$frx_options['hidden']=='1' ? 1 : 0;
  $report_form = @$frx_options['form'];
  $attributes = $r->get_attributes_by_id();
  $category = $r->getCategory();
  $body = $r->simplexml->body->asXML();


  //array of xml attributes that are required to have a value
  $required = array('id' => TRUE, 'label' => TRUE);
  //list of supported document formats
  $doclist = variable_get('forena_doc_formats', array());

  $form['save_report_name'] = array(
    '#type' => 'textfield',
    '#title' => t('Report Name'),
    '#description' => t('Enter only letters, numbers, and special characters:  - _ /
                         <br/>White space is not permitted.
                         Create a directory using the format: (directory name) / (report name). Save multiple reports to the same directory
                         by referencing the same name.'),
    '#required' => TRUE,
  );


  $form['title'] = array(
    '#type' => 'textfield',
    '#title' => t('Title'),
    '#default_value' => $title,
metzlerd's avatar
metzlerd committed
739
    '#required' => TRUE,
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
  );

  $form['category'] = array(
    '#type' => 'textfield',
    '#title' => t('Category'),
    '#default_value' => $category,
    '#autocomplete_path' => 'forena/categories/autocomplete',
    '#description' => t('The heading your report will be grouped under on the report list.'),
  );

  $form['hidden'] = array(
    '#type' => 'checkbox',
    '#title' => t('Hidden'),
    '#default_value' => $hidden,
    '#description' => t('Hide your report from showing up on the report list.'),
  );

  $form['report_name'] = array(
    '#title' => t('Create from report'),
    '#type' => 'textfield',
760
    '#autocomplete_path' => 'forena/reports/autocomplete',
761
762
763
764
765
766
767
    '#default_value' => $name,
  );

  $form['save'] = array(
    '#type' => 'submit',
    '#value' => 'Create',
  );
768
769
770
771
772
  return $form;

}

function forena_add_report_form_validate($form, &$form_state) {
773
  $values = $form_state['values'];
774
  $pattern = "@^[A-Za-z0-9\/\_]$@";
775
  $save_report_name = $values['save_report_name'];
776
777
778
  if (preg_match($pattern, $save_report_name)) {
    form_set_error('save_report_name', t('Invalid characters in report name') );
  }
779
780
  //comparing the report names to see if they have changed.
  //If they have, making sure the new name does not already exist.
781
782
783
  $filename = $save_report_name . '.frx';
  if (Frx::File()->exists($filename, FALSE)) {
    form_set_error('save_report_name', t('The report ' . $save_report_name . ' already exists. Please enter another name.'));
metzlerd's avatar
metzlerd committed
784
  }
785
}
786

787
function forena_add_report_form_submit($form, &$form_state) {
788
  $values = $form_state['values'];
789
  $report_name = $values['save_report_name'];
metzlerd's avatar
metzlerd committed
790
  $desc = Frx::Menu()->parseURL($report_name);
791
  $report_name = $desc['name'];
792

793
794
795
796
797
798
799
  if ($values['report_name']) {
    $r = Frx::Editor($values['report_name']);
    $r->report_name = $values['save_report_name'];
  }
  else {
    $r = Frx::Editor($values['save_report_name']);
  }
800
801
802
803
804
805
  // Title and category
  $r->setTitle($values['title']);
  $r->setCategory($values['category']);
  // Form options
  $options = array(
    'hidden' => $values['hidden'],
806
  );
807
808
  $r->setOptions($options);

809
  //determine redirection.
810
  $filename = $desc['filename'];
metzlerd's avatar
metzlerd committed
811

812
813
814
815
816
817
818
  $r->update();
  //if this is a new report then redirect to data blocks
  if ($values['report_name']) {
    $edit = '/edit';
  }
  else {
    $edit = '/edit/data/add';
metzlerd's avatar
metzlerd committed
819
  }
820
821
  $form_state['redirect']= $desc['i_link'] . $edit;

822
823
}
function forena_create_trans_form($formid, $form_state, $report_name) {
824
825
826
  $name = '';
  $filename = '';
  $format = '';
metzlerd's avatar
metzlerd committed
827
  $desc = Frx::Menu()->parseURL($report_name);
828
829
830
831
  $name = $desc['name'];
  $filename = $desc['filename'];
  $base_name = $desc['base_name'];
  $format = @$desc['format'];
832
833
  $form = array();
  global $language;
834
  $languages = language_list();
835
836
  //determine if this is an add new report request

837
  $r = Frx::Editor($name);
838
839
840
  $title = (string)$r->title;
  $lang = @$_GET['language'];
  if ($lang) {
metzlerd's avatar
metzlerd committed
841
    $language = $languages[$lang];
842
843
844
845
846
847
848
849
850
  }
  $form['base_name'] = array(
    '#type' => 'value',
    '#value' => $base_name
  );
  $form['report_name'] = array(
    '#type' => 'value',
    '#value' => $name,
  );
851

metzlerd's avatar
metzlerd committed
852
  foreach ($languages as $key => $obj) {
853
    $languages[$key] = $obj->native;
854
  }
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
  $form['report_lang'] = array(
    '#type' => 'value',
    '#value' => $lang,
  );
  $def_lang = $lang ? $lang : 'en';
  $form['save_report_language'] = array(
    '#type' => 'select',
    '#title' => t('Language'),
    '#options' => $languages,
    '#default_value' => $def_lang,
  );


  $form['title'] = array(
    '#type' => 'textfield',
    '#title' => t('Title'),
    '#default_value' => $title,
metzlerd's avatar
metzlerd committed
872
    '#required' => TRUE,
873
874
875
876
877
878
879
880
881
  );


  $form['save'] = array(
    '#type' => 'submit',
    '#value' => 'Create',
  );
  return $form;

882
883
884
885
}

function forena_create_trans_form_submit($form, &$form_state) {
  $values = $form_state['values'];
886
  $base_name = $values['base_name'];
metzlerd's avatar
metzlerd committed
887
  $new_name = $values['save_report_language'] . '/' . $base_name;
888

metzlerd's avatar
metzlerd committed
889
  $desc = Frx::Menu()->parseURL($new_name);
890
891
  $filename = $desc['filename'];
  $report_name = $desc['name'];
892

David Metzler's avatar
David Metzler committed
893
  $r = Frx::Editor($base_name);
894
895
896

  // Title and category
  $r->setTitle($values['title']);
metzlerd's avatar
metzlerd committed
897

metzlerd's avatar
metzlerd committed
898
  //determine redirection.
899

900
  if (Frx::File()->exists($filename, FALSE)) {
metzlerd's avatar
metzlerd committed
901
    drupal_set_message(t('Report %s already exists', array('%s' => $new_name)), 'error');
902
    return;
metzlerd's avatar
metzlerd committed
903
  }
David Metzler's avatar
David Metzler committed
904
905
906
907
908
  else {
    $r->rename($new_name);
    drupal_set_message(t('Translation,  %s has been created. Switch languages to translate.', array('%s' => $values['title'])));
    $form_state['redirect']= array( $desc['i_link'] . '/edit/layout');
  }
metzlerd's avatar
metzlerd committed
909

910
  //if this is a new report then redirect to data blocks
911
}
912

913
914


915
916
917
918
/*
 * administer the settings for document format options
 */
function forena_doc_formats_settings() {
919
  // Invoke doc_type hook to see which document types are there.
920
  $supported_doctypes = Frx::documentTypes();
921

922
923
  $form['forena_doc_formats'] = array(
    '#type' => 'checkboxes',
924
    '#title' => t('Allowed Document Formats'),
925
926
927
928
    '#default_value' => variable_get('forena_doc_formats', $supported_doctypes),
    '#description' => t('check your desired document format'),
    '#options' => $supported_doctypes,
  );
929
930
931
932

  $form['forena_doc_defaults'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Default Document Formats'),
933
    '#default_value' => variable_get('forena_doc_defaults', array()),
934
935
936
937
    '#description' => t('check your desired document format'),
    '#options' => $supported_doctypes,
  );

938
939
940
  $form['forena_email_override'] = array(
    '#type' => 'checkbox',
    '#title' => 'Run email merges in test mode' ,
metzlerd's avatar
metzlerd committed
941
    '#default_value' => variable_get('forena_email_override', FALSE),
942
943
    '#description' => t('When this box is checked emails are sent to the currently logged in user.  Useful for testing environments.'),
  );
944
  $form['forena_email_input_format'] = forena_filter_element(variable_get('forena_email_input_format', 'full_text'), 'forena_email_input_format');
945
  $form['forena_email_input_format']['#title'] = t('Email Input Format');
946

947
948
  return system_settings_form($form);
}
949

950
951
952
953
/*
 * administer the settings for document format options
 */
function forena_data_settings() {
954
  $repos = Frx::RepoMan()->repositories;
955
  $r_list = array();
metzlerd's avatar
metzlerd committed
956
957
  $headers = array(t('Name'), t('Description'), t('Path'), t('Operation'));
  foreach ($repos as $name => $r) {
958
    $r_list[] = array(
metzlerd's avatar
metzlerd committed
959
960
961
962
    $name,
    $r['title'],
    $r['path'],
    l(t('configure'), 'admin/config/content/forena/data/configure/' . $name)
963
964
965
966
    );

  }

metzlerd's avatar
metzlerd committed
967
968
  $output = '<ul class="action-links"><li>' . l(t('Add data source'), 'admin/config/content/forena/data/add') . '</li></ul>';
  $output .= theme_table(array('header' => $headers, 'rows' => $r_list, 'attributes' => array(), 'caption' => '', 'sticky' => TRUE, 'colgroups' => array(), 'empty' => ''));
969
970
971
972
  return $output;
}

function forena_data_settings_edit($form, &$form_state, $source=-1) {
973
  global $databases;
974
975
976
977
978
979
980
981
982
  $adding = ($source === -1);
  if (!@$form_state['storage']) {
    if ($adding) {
      $form_state['storage'] = array(
        'name' => '',
        'title' => '',
        'path' => '',
        'config' => array(
          'source' => 'user',
davidmetzler's avatar
davidmetzler committed
983
          'data provider' => 'FrxDrupal',
984
          'database' => 'default',
985
986
          'access callback' => 'user_access',
          'user callback' => 'forena_current_user_id'
metzlerd's avatar
metzlerd committed
987
988
          ),
          );
989
990
    }
    else {
991
992
      Frx::RepoMan()->repository($source);
      $repos = Frx::RepoMan()->repositories;
993
      $r = $repos[$source];
davidmetzler's avatar
davidmetzler committed
994
      // Remove teh object from the data.
995
      unset($r['data']);
996
997
998
      $form_state['storage'] = array(
        'name' => $source,
        'title' => $r['title'],
davidmetzler's avatar
davidmetzler committed
999
        'path' => @$r['path'],
1000
        'config' => $r,
1001
1002
1003
1004
1005
1006
      );

    }
  }
  $data = $form_state['storage'];
  $config = $data['config'];
davidmetzler's avatar
davidmetzler committed
1007

davidmetzler's avatar
davidmetzler committed
1008
  $locked = !($adding || (@$config['source'] == 'user'));
1009
1010
1011
1012
1013
1014
1015
1016
1017
  $values = @$form_state['values'];

  $form['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Name'),
    '#description' => t('Machine readable name.  Used in referencing all data used by this source. must should not contain any special characters or spaces.'),
    '#disabled' => !$adding,
    '#default_value' => $data['name'],
    '#required' => TRUE,
metzlerd's avatar
metzlerd committed
1018
  );
1019
1020
1021
1022

  $form['title'] = array(
    '#type' => 'textfield',
    '#title' => t('Title'),
davidmetzler's avatar
davidmetzler committed
1023
    '#required' => TRUE,
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
    '#description' => t('Human readable name that describes the data source.  This primarily occurs in error messages where the data source cannot be accessed.'),
    '#default_value' => $data['title'],
  );

  $form['enabled'] = array(
    '#type' => 'checkbox',
    '#title' => t('Enabled'),
    '#description' => t('Disabling will cause all queries to return no data.'),
    '#default_value' => @$data['enabled']!==0,
  );

davidmetzler's avatar
davidmetzler committed
1035
1036
1037
1038
1039
1040
1041
  $form['debug'] = array(
    '#type' => 'checkbox',
    '#title' => t('Debug'),
    '#description' => t('Write information to the screen and logs for each query executed.'),
    '#default_value' => @$config['debug'],
  );

1042
1043
1044
  $form['path'] = array(
    '#type' => 'textfield',
    '#title' => t('Path'),
davidmetzler's avatar
davidmetzler committed
1045
    '#required' => TRUE,
1046
    '#disabled' => $locked,
1047
1048
1049
1050
    '#description' => t('Directory containing data block files.'),
    '#default_value' => @$data['path'],
  );

davidmetzler's avatar
davidmetzler committed
1051
1052
1053
1054
1055
1056
1057
1058
1059
  $user_options = array(
    '' => 'None',
    'forena_current_user_id' => 'UID',
    'forena_current_user_name' => 'User name',
  );

  $form['user_callback'] = array(
    '#type' => 'select',
    '#title' =>  'Current user',
1060
    '#disabled' => $locked,
davidmetzler's avatar
davidmetzler committed
1061
1062
    '#description' => t('Can be refererenced as :current_user in each data block.'),
    '#options' => $user_options,
1063
    '#default_value' => @$config['user callback'],
davidmetzler's avatar
davidmetzler committed
1064
1065
1066
1067
    '#disabled' => $locked,
  );


1068
1069
  // Access method list
  $access = array(
davidmetzler's avatar
davidmetzler committed
1070
    'callback' => t('Use drupal permissions'),
metzlerd's avatar
metzlerd committed
1071
    'block' => t('Match values provided by a data block.'),
1072
1073
1074
1075
1076
  );

  $form['access_method'] = array(
    '#type' => 'select',
    '#options' => $access,
1077
    '#disabled' => $locked,
davidmetzler's avatar
davidmetzler committed
1078
1079
    '#title' => t('Data security method'),
    '#default_value' => empty($config['access block']) ? 'callback' : 'block',
metzlerd's avatar
metzlerd committed
1080
    '#description' => t('Specify how the ACCESS defined for a data block is to be interpreted.'),
1081
1082
1083
    '#ajax' => array(
      'callback' => 'forena_access_info_callback',
      'wrapper' => 'access-details',
metzlerd's avatar
metzlerd committed
1084
  ),
1085
1086
1087
1088
1089
1090
  );

  $form['access_details'] = array(
    '#type' => 'fieldset',
    '#prefix' => '<div id="access-details">',
    '#suffix' => '</div>',
davidmetzler's avatar
davidmetzler committed
1091
    '#title' => t('Details'),
1092
1093
1094
  ) ;

  switch (!empty($values['access_method']) ? $values['access_method'] : $form['access_method']['#default_value']) {
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
    case 'block':
      $form['access_details']['access_block'] = array(
        '#type' => 'textfield',
        '#title' => 'Data block providing permissions list',
        '#disabled' => $locked,
        '#autocomplete_path' => 'forena/data_block/autocomplete',
        '#description' => t('The datablock to be used to interpret permissions.  This should return a single column of permissions based on the current user.   May be provided by another repository.'),
        '#default_value' => @$config['access block'],
      );
      break;
    default:
      $form['access_details']['access_callback'] = array(
        '#type' => 'item',
        '#title' => 'Access callback',
        '#disabled' => $locked,
        '#markup' => @$config['access callback'],
      );
1112
1113
1114
1115
1116
1117
1118
1119
  }



  // Driver list
  $drivers = array(
    'FrxDrupal' => t('Drupal'),
    'FrxOracle' => t('Oracle Database'),
metzlerd's avatar
metzlerd committed
1120
    'FrxPDO' => t('PDO other than Drupal'),
1121
1122
1123
1124
1125
    'FrxPostgres' => t('Postgres Database'),
    'FrxMSSQL' => t('MSSQL Database'),
    'FrxFiles' => t('XML Files'),
  );

davidmetzler's avatar
davidmetzler committed
1126
  $form['data_provider'] = array(
1127
1128
1129
1130
1131
    '#type' => 'select',
    '#title' => t('Driver'),
    '#description' => t('Forena data connection type'),
    '#options' => $drivers,
    '#disabled' => $locked,
davidmetzler's avatar
davidmetzler committed
1132
    '#default_value' => $config['data provider'],
1133
1134
1135
    '#ajax' => array(
      'callback' => 'forena_connection_info_callback',
      'wrapper' => 'conn-div',
metzlerd's avatar
metzlerd committed
1136
  ),
1137
1138
1139
1140
  );

  $form['connection'] = array(
    '#type' => 'fieldset',
davidmetzler's avatar
davidmetzler committed
1141
    '#tree' => TRUE,
1142
1143
1144
1145
    '#title' => 'Connection info',
   '#prefix' =>  '<div id="conn-div">',
   '#suffix' => '</div>',
  );
davidmetzler's avatar
davidmetzler committed
1146
  $data_provider = (!empty($form_state['values']['data_provider']) ? $form_state['values']['data_provider'] : $config['data provider']);
1147

davidmetzler's avatar
davidmetzler committed
1148
1149
1150
1151
1152
  // Common controls used in mulitple providers.
  $uri = array(
    '#type' => 'textfield',
    '#title' => t('uri'),
    '#descripton' => t('Connection string: see appropriate php documentation for more details.'),
1153
    '#default_value' => @$config['uri'],
davidmetzler's avatar
davidmetzler committed
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
    '#required' => TRUE,
    '#disabled' => $locked,
  );

  $user = array(
    '#type' => 'textfield',
    '#title' => t('User'),
    '#default_value' => @$config['user'],
  );
  $password= array(
    '#type' => 'password',
    '#title' => t('Password'),
    '#default_value' => @$config['password'],
metzlerd's avatar
metzlerd committed
1167
  );
davidmetzler's avatar
davidmetzler committed
1168

davidmetzler's avatar
davidmetzler committed
1169
  switch ($data_provider) {