FrxReport.inc 17.7 KB
Newer Older
metzlerd's avatar
metzlerd committed
1
<?php
metzlerd's avatar
metzlerd committed
2
// $Id$
metzlerd's avatar
metzlerd committed
3
/**
metzlerd's avatar
metzlerd committed
4
5
 * @file
 * Basic report provider.  Controls the rendering of the report.
metzlerd's avatar
metzlerd committed
6
 */
metzlerd's avatar
metzlerd committed
7
8
define('FRX_NS', 'urn:FrxReports');
require_once('FrxSyntaxEngine.inc');
9
require_once('FrxRenderer.inc');
metzlerd's avatar
metzlerd committed
10

metzlerd's avatar
metzlerd committed
11
12
13
class FrxReport {
  public $blocks_loaded;
  public $rpt_xml;
metzlerd's avatar
metzlerd committed
14
  public $fields;
metzlerd's avatar
metzlerd committed
15
  public $category;
16
  public $descriptor;
metzlerd's avatar
metzlerd committed
17
18
19
20
  public $form;
  public $access;
  public $parameters;
  public $options;
metzlerd's avatar
metzlerd committed
21
  public $formats;
22
23
  public $title;
  public $frx_title;
24
  public $body;
25
  public $html;
metzlerd's avatar
metzlerd committed
26
  public $skin;
27
  private $ids;
28
  public $teng;
29
  public $parms;
30
  public $missing_parms = FALSE;
31
  private $dom;
metzlerd's avatar
metzlerd committed
32
  private $format;
metzlerd's avatar
metzlerd committed
33
34


metzlerd's avatar
metzlerd committed
35
  public function __construct($xhtml, $data=array()) {
metzlerd's avatar
metzlerd committed
36
37
38
    $this->access = array();
    $this->parameters = array();
    $this->options = array();
39
40
    $this->parms = $data;
    $this->teng = new FrxSyntaxEngine(FRX_TOKEN_EXP, '{}', $this);
metzlerd's avatar
metzlerd committed
41
    if ($xhtml) {
42
43
44
45
46
47
48
49
50
      $dom = $this->dom = new DOMDocument('1.0', 'UTF-8');
      // Old assumption is an ojbect is a simplexml one
      if (is_object($xhtml)) $xhtml = $xhtml->asXML();

      // Load document and simplexml representation
      $dom->loadXML($xhtml);
      $dom->formatOutput = TRUE;
      $rpt_xml = $this->rpt_xml = simplexml_import_dom($dom);

51

52
      // Load header data
metzlerd's avatar
metzlerd committed
53
      $this->body = $rpt_xml->body;
54
      if ($rpt_xml->head) {
metzlerd's avatar
metzlerd committed
55
        $this->title = (string)$rpt_xml->head->title;
metzlerd's avatar
metzlerd committed
56
        $nodes = $rpt_xml->xpath('//frx:docgen/frx:doc');
metzlerd's avatar
metzlerd committed
57
        $this->formats = array();
metzlerd's avatar
metzlerd committed
58
        if ($nodes) foreach ($nodes as $value) {
metzlerd's avatar
metzlerd committed
59
60
          $arr = $value->attributes();
          $this->formats[] = (string)$arr['type'];
metzlerd's avatar
metzlerd committed
61
        }
metzlerd's avatar
metzlerd committed
62
63


metzlerd's avatar
metzlerd committed
64
65
66
        foreach ($rpt_xml->head->children(FRX_NS) as $name => $node) {
          switch ($name) {
            case 'fields':
67
              $this->fields = $node;
metzlerd's avatar
metzlerd committed
68
69
70
71
              break;
            case 'category':
              $this->category = (string)$node;
              break;
72

73
            case 'descriptor':
metzlerd's avatar
metzlerd committed
74
75
              $this->descriptor = (string)$node;
              break;
metzlerd's avatar
metzlerd committed
76
77
78
            case 'options':
              foreach ($node->attributes() as $key => $value) {
                $this->options[$key] = (string)$value;
79
              }
metzlerd's avatar
metzlerd committed
80
              break;
81
82
83
            case 'title':
              $this->frx_title = (string)$node;
              break;
84
            case 'form':
metzlerd's avatar
metzlerd committed
85
86
87
              $this->form = (string) $value;
              break;
            case 'parameters':
metzlerd's avatar
metzlerd committed
88
              foreach ($node->children(FRX_NS) as $key => $node) {
metzlerd's avatar
metzlerd committed
89
                $parm = array();
metzlerd's avatar
metzlerd committed
90
                foreach ($node->attributes() as $akey => $attr) {
metzlerd's avatar
metzlerd committed
91
                  $parm[$akey] = (string)$attr;
92
                }
metzlerd's avatar
metzlerd committed
93
                $id = $parm['id'];
metzlerd's avatar
metzlerd committed
94
95
                $val = isset($parm['value']) ? $parm['value'] : '';
                $parm['value']= ((string)$node) ? (string)$node : $val;
metzlerd's avatar
metzlerd committed
96
                $this->parameters[$id] = $parm;
97
              }
98
              break;
metzlerd's avatar
metzlerd committed
99
            case 'doctypes':
100
              $this->doctypes = $value;
metzlerd's avatar
metzlerd committed
101
              break;
102
          }
103
        }
metzlerd's avatar
metzlerd committed
104
105

        $this->skin = isset($this->options['skin']) ? $this->options['skin'] : @$this->options['form'];
106
107
      }
    }
metzlerd's avatar
metzlerd committed
108
  }
metzlerd's avatar
metzlerd committed
109

metzlerd's avatar
metzlerd committed
110
  function __destruct() {
metzlerd's avatar
metzlerd committed
111
112
113
    foreach ($this as $key => $value) {
      unset($this->$key);
    }
metzlerd's avatar
metzlerd committed
114
115
116
  }


metzlerd's avatar
metzlerd committed
117
  /**
metzlerd's avatar
metzlerd committed
118
   * Get the data block
metzlerd's avatar
metzlerd committed
119
120
121
   * @param $block
   * @return unknown_type
   */
122
123
  private function get_data($block, $clause='', $id='', $data_uri='') {
    if ($data_uri) {
metzlerd's avatar
metzlerd committed
124
125
126
127
      parse_str($data_uri, $data);
      if (is_array($data)) foreach ($data as $key => $value) {
        $data[$key] = $this->teng->replace($value);
      }
128
129
130

      // Merge in current_context
      $data = array_merge(Frx::Data()->currentContextArray(), $data);
metzlerd's avatar
metzlerd committed
131
132
      $id .= '-parm';
      Frx::Data()->push($data, $id);
133
134
    }

metzlerd's avatar
metzlerd committed
135
    $xml = Frx::RepoMan()->data($block, NULL);
metzlerd's avatar
metzlerd committed
136
    if ($data_uri) Frx::Data()->pop();
137

138
    if ($xml) {
metzlerd's avatar
metzlerd committed
139
      $this->blocks_loaded = TRUE;
140
141
142
    }
    return $xml;
  }
metzlerd's avatar
metzlerd committed
143

144
145
  /**
   * Recursive report renderer
metzlerd's avatar
metzlerd committed
146
   * Walks the nodes rendering the report.
147
   */
148
  public function render_section(DOMNode $dom_node) {
metzlerd's avatar
metzlerd committed
149
150
    $continue = TRUE;
    $is_data_block = FALSE;
151
    $node_type = $dom_node->nodeType;
metzlerd's avatar
metzlerd committed
152
    $o = '';
153
154

    // Shortcut process a text node
metzlerd's avatar
metzlerd committed
155
    if ($node_type == XML_TEXT_NODE
metzlerd's avatar
metzlerd committed
156
157
158
159
160
    || $node_type == XML_ENTITY_REF_NODE
    || $node_type == XML_ENTITY_NODE
    ) {     $text = $dom_node->textContent;
    $o .= $this->teng->replace($text);
    return $o;
161
162
    }

metzlerd's avatar
metzlerd committed
163
164
165
166
    //Ignore certain node types
    if ($node_type == XML_COMMENT_NODE) {
      return '';
    }
167
168
    // Continue processing non text nodes
    $node = simplexml_import_dom($dom_node);
metzlerd's avatar
metzlerd committed
169
    // Special catch to make sure we don't process bad nodes
170
    if (!is_object($node)) {
metzlerd's avatar
metzlerd committed
171
      return '';
metzlerd's avatar
metzlerd committed
172
173
    }

174

175
176
    $frx = $node->attributes(FRX_NS);
    $elements = $dom_node->childNodes->length;
177
    // Test to see if we have any nodes that contain data url
metzlerd's avatar
metzlerd committed
178
    if ($node->xpath('*//@frx:*') || $frx) {
metzlerd's avatar
metzlerd committed
179
      $attrs = $node->attributes();
180
      $id = (string)$attrs['id'];
metzlerd's avatar
metzlerd committed
181
      $frx = $node->attributes(FRX_NS);
metzlerd's avatar
metzlerd committed
182
183
      $tag = $node->getName();

metzlerd's avatar
metzlerd committed
184
      if ((string)$frx['block']) {
metzlerd's avatar
metzlerd committed
185
        $is_data_block = TRUE;
186
        $xml = $this->get_data((string)$frx['block'], (string)$frx['clause'], $id, (string)$frx['parameters']);
187
        if ($xml) {
188
          Frx::Data()->push($xml, $id);
189
        }
190
        else {
metzlerd's avatar
metzlerd committed
191
          return '';
192
        }
metzlerd's avatar
metzlerd committed
193
      }
194

metzlerd's avatar
metzlerd committed
195
196
197
      //Implment if then logic
      if ((string)$frx['if']) {
        $cond = (string)$frx['if'];
198
        if (!$this->teng->test($cond)) return '';
metzlerd's avatar
metzlerd committed
199
200
      }

201
      // Preserve non frx attributes
metzlerd's avatar
metzlerd committed
202
203
204
      $attr_text='';
      $tmp_attrs = array();
      if ($attrs) foreach ($attrs as $key => $value) {
205
        $attr_text .=  ' ' . $key . '="' . (string)$value . '"';
metzlerd's avatar
metzlerd committed
206
        $tmp_attrs[$key] = (string)$value;
metzlerd's avatar
metzlerd committed
207
      }
metzlerd's avatar
metzlerd committed
208

209
      // Determine if we have a custom renderer
metzlerd's avatar
metzlerd committed
210
      $renderer = (string)$frx['renderer'];
metzlerd's avatar
metzlerd committed
211
      // if we have a foreach in this node, we need to iterate the children
metzlerd's avatar
metzlerd committed
212
      if ((string)$frx['foreach'] ) {
metzlerd's avatar
metzlerd committed
213
        // Save xml
214
        $path = $this->teng->replace((string)$frx['foreach'], TRUE);
215
        $data = Frx::Data()->currentContext();
metzlerd's avatar
metzlerd committed
216

217
        if (is_object($data)) {
metzlerd's avatar
metzlerd committed
218
219
220
221
222
223
          if (method_exists($data, 'xpath')) {
            $nodes = $data->xpath($path);
          }
          else {
            $nodes = $data;
          }
224
225
        }
        else {
metzlerd's avatar
metzlerd committed
226
          $nodes = (array)$data;
227
        }
228
        $i=0;
metzlerd's avatar
metzlerd committed
229
230

        //$tmp_attrs = (array)$attrs;
metzlerd's avatar
metzlerd committed
231

metzlerd's avatar
metzlerd committed
232
        if ($nodes) foreach ($nodes as $x) {
233
          Frx::Data()->push($x, $id);
metzlerd's avatar
metzlerd committed
234
          $i++;
235
          $odd = $i & 1;
metzlerd's avatar
metzlerd committed
236
          $row_class = $odd ? 'odd' : 'even';
metzlerd's avatar
metzlerd committed
237
          unset($tmp_attrs['id']);
metzlerd's avatar
metzlerd committed
238
          $tmp_attrs['class'] = trim($attrs['class'] . ' ' . $row_class);
metzlerd's avatar
metzlerd committed
239
240
241
          $r_attr_text = '';

          foreach ($tmp_attrs as $key => $value) {
metzlerd's avatar
metzlerd committed
242
            $r_attr_text .=  ' ' . $key . '="' . (string)$value . '"';
243
          }
244
          $o .= $this->teng->replace('<' . $tag . $r_attr_text . '>');
245
          foreach ($dom_node->childNodes as $child) {
metzlerd's avatar
metzlerd committed
246
            $o .= $this->render_section($child);
metzlerd's avatar
metzlerd committed
247
          }
metzlerd's avatar
metzlerd committed
248
          $o .= '</' . $tag . '>';
metzlerd's avatar
metzlerd committed
249
          Frx::Data()->pop();
metzlerd's avatar
metzlerd committed
250
        }
metzlerd's avatar
metzlerd committed
251
252
      }
      elseif ($continue) {
metzlerd's avatar
metzlerd committed
253
254
        if ($renderer) {
          // Implement custom renderer.
255
          $co = Frx::Controls($renderer);
metzlerd's avatar
metzlerd committed
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
          if ($co) {
            $co->initReportNode($dom_node, $this, $this->format);
            $o = $co->render();

          }
        }
        else {
          $o .= $this->teng->replace('<' . $tag . $attr_text . '>');

          // None found, so render children
          foreach ($dom_node->childNodes as $child) {
            $o .= $this->render_section($child);
          }
          $o .= '</' . $tag . '>';
        }
metzlerd's avatar
metzlerd committed
271
      }
272
      if ($is_data_block && $continue) {
metzlerd's avatar
metzlerd committed
273
        Frx::Data()->pop();
274
      }
metzlerd's avatar
metzlerd committed
275
276
    }
    else {
277

metzlerd's avatar
metzlerd committed
278
279
      // We can render so lets do it.
      $text = $node->asXML();
280
      $o .= $this->teng->replace($text);
metzlerd's avatar
metzlerd committed
281
    }
282

metzlerd's avatar
metzlerd committed
283
    return $o;
metzlerd's avatar
metzlerd committed
284
  }
metzlerd's avatar
metzlerd committed
285

metzlerd's avatar
metzlerd committed
286
287
288
289
  /**
   * Render the report
   * @return unknown_type
   */
290
  public function render($format) {
metzlerd's avatar
metzlerd committed
291
292
    if (!$format) $format = 'web';
    Frx::Data()->push($this->parms, 'parm');
293

metzlerd's avatar
metzlerd committed
294
    $this->format = $format;
295
    $dom = $this->dom;
metzlerd's avatar
metzlerd committed
296
    $o='';
297
    $body = $dom->getElementsByTagName('body')->item(0);
298

299
    if (!$this->missing_parms || $this->rpt_xml->xpath('//*[@frx:renderer="FrxParameterForm"]')) foreach ($body->childNodes as $node) {
metzlerd's avatar
metzlerd committed
300
301
      $o .= $this->render_section($node);
    }
302
303
304
305
306
    // Default in dynamic title from head.
    if ($this->frx_title) {
      $title = check_plain($this->teng->replace($this->frx_title));
      if ($title) $title = $this->title = $title;
    }
metzlerd's avatar
metzlerd committed
307
    if (!$this->rpt_xml->xpath('//*[@frx:renderer="FrxParameterForm"]') && $format=='web') {
308
309
      $variables = array('collapse' => $this->blocks_loaded);
      $form = $this->parametersForm($variables);
metzlerd's avatar
metzlerd committed
310
311
      $o = drupal_render($form) . $o;
    }
312
    $this->html = $o;
metzlerd's avatar
metzlerd committed
313
    Frx::Data()->pop();
metzlerd's avatar
metzlerd committed
314
    return $o ;
metzlerd's avatar
metzlerd committed
315
316
317
  }
  /*
   * Formatter used by the syntax engine to alter data that gets extracted.
metzlerd's avatar
metzlerd committed
318
   * This invokes the field translation
metzlerd's avatar
metzlerd committed
319
320
   */
  public function format($value, $key, $data) {
metzlerd's avatar
metzlerd committed
321
    // Determine if there is a field overide entry
metzlerd's avatar
metzlerd committed
322
323
324
    $default='';
    $link ='';
    $format='';
metzlerd's avatar
metzlerd committed
325
326
327
328
    $format_str = '';
    $target = '';
    $class = '';
    $rel = '';
metzlerd's avatar
metzlerd committed
329
    if ($this->fields) {
metzlerd's avatar
metzlerd committed
330

metzlerd's avatar
metzlerd committed
331
      $path = 'frx:field[@id="' . $key . '"]';
metzlerd's avatar
metzlerd committed
332
333
      $formatters = $this->fields->xpath($path);
      if ($formatters) foreach ($formatters as $formatter) {
metzlerd's avatar
metzlerd committed
334
        if ((isset($formatter['block']) &&(string)$formatter['block'] == $this->block) || (!(string)$formatter['block'])) {
metzlerd's avatar
metzlerd committed
335

metzlerd's avatar
metzlerd committed
336
337
338
339
340
341
342
343
344
          //@TODO: Replace the default extraction with something that will get sub elements of the string
          $default = (string)$formatter;
          $link = (string)$formatter['link'];
          $add_query = (string)$formatter['add-query'];
          $class = (string)$formatter['class'];
          $rel = (string)$formatter['rel'];
          $format = (string) $formatter['format'];
          $format_str = (string) $formatter['format-string'];
          $target = (string) $formatter['target'];
metzlerd's avatar
metzlerd committed
345
        }
metzlerd's avatar
metzlerd committed
346
347
      }
    }
metzlerd's avatar
metzlerd committed
348
349

    if ($format) {
350
      $value = FrxReportGenerator::$instance->format_data($value, $format, $format_str, $this->teng);
metzlerd's avatar
metzlerd committed
351
    }
metzlerd's avatar
metzlerd committed
352
353
354

    if (is_array($value)) {
      $value = implode(' ', $value);
355
    }
metzlerd's avatar
metzlerd committed
356

metzlerd's avatar
metzlerd committed
357
    // Default if specified
metzlerd's avatar
metzlerd committed
358
359
    if (!$value && $default) {
      $value = $default;
metzlerd's avatar
metzlerd committed
360
    }
metzlerd's avatar
metzlerd committed
361
362

    if ($link) {
metzlerd's avatar
metzlerd committed
363
364
365
366
      $attributes = array();
      $target = $this->teng->replace($target, TRUE);
      // use the target attribute to open links in new tabs or as popups.
      if (@strpos(strtolower($target), 'popup')===0) {
367
        $opts = 'status=1';
metzlerd's avatar
metzlerd committed
368
        $options = "status=1";
369
        $attributes = array('onclick' =>
metzlerd's avatar
metzlerd committed
370
          'window.open(this.href, \'' . $target . '\', "' . $options . '"); return false;');
371
372
      }
      else {
metzlerd's avatar
metzlerd committed
373
        if ($target) $attributes['target'] = $target;
374
      }
metzlerd's avatar
metzlerd committed
375
      if ($rel) $attributes['rel'] = $this->teng->replace($rel, TRUE);
376
      if ($class) $attributes['class'] = explode(' ', trim($this->teng->replace($class, TRUE)));
377
      $link = $this->teng->replace($link, TRUE);
metzlerd's avatar
metzlerd committed
378
      @list($url, $query) = explode('?', $link);
379
380
381
      @list($query, $queryFrag) = explode('#', $query);
      @list($url, $fragment) = explode('#', $url);
      $fragment = $fragment . $queryFrag;
metzlerd's avatar
metzlerd committed
382
383
      $data = array();
      parse_str($query, $data);
384
385
386
387
388
      if ($add_query) {
        $parms = $_GET;
        unset($parms['q']);
        $data = array_merge($parms, $data);
      }
389
      if (trim($url)) $value = FrxReportGenerator::instance()->link(
metzlerd's avatar
metzlerd committed
390
391
      htmlspecialchars_decode($value), $url,
      array('fragment' => $fragment, 'query' => $data, 'attributes' => $attributes, 'absolute' => TRUE));
metzlerd's avatar
metzlerd committed
392
    }
metzlerd's avatar
metzlerd committed
393
    return $value;
metzlerd's avatar
metzlerd committed
394
  }
metzlerd's avatar
metzlerd committed
395

396
397
398
399
400
401
  /**
   * Delete a node based on id
   * @param unknown_type $id
   * @return unknown_type
   */
  public function deleteNode($id) {
metzlerd's avatar
metzlerd committed
402
    $path = '//*[@id="' . $id . '"]';
403
    $nodes = $this->rpt_xml->xpath($path);
404
405
406
407
408
    if ($nodes) {
      $node = $nodes[0];
      $dom=dom_import_simplexml($node);
      $dom->parentNode->removeChild($dom);
    }
409
  }
metzlerd's avatar
metzlerd committed
410

411
  /**
metzlerd's avatar
metzlerd committed
412
   * Return the xml data for the report.
413
414
415
   *
   * @return unknown
   */
metzlerd's avatar
metzlerd committed
416
  public function asXML() {
metzlerd's avatar
metzlerd committed
417
418
419
420
421
422
    if ($this->rpt_xml) {
      return $this->rpt_xml->asXML();
    }
    else {
      return '';
    }
423
  }
424
425
  /**
   * Make sure all xml elements have ids
metzlerd's avatar
metzlerd committed
426
   */
427
  private function parse_ids() {
metzlerd's avatar
metzlerd committed
428
429
430
431
432
433
434
435
436
437
438
439
    $i=0;
    if ($this->rpt_xml) {
      $this->rpt_xml->registerXPathNamespace('frx', FRX_NS);
      $frx_attributes = array();
      $frx_nodes = $this->rpt_xml->xpath('body//*[@frx:*]');

      if ($frx_nodes) foreach ($frx_nodes as $node) {
        $attr_nodes = $node->attributes(FRX_NS);
        if ($attr_nodes) {
          // Make sure every element has an id
          $i++;
          $id = 'forena-' . $i;
metzlerd's avatar
metzlerd committed
440

metzlerd's avatar
metzlerd committed
441
442
          if (!(string)$node['id']) {
            $node->addAttribute('id', $id);
443

metzlerd's avatar
metzlerd committed
444
445
446
447
448
          }
          else {
            if (strpos((string)$node['id'], 'forena-')===0) {
              // Reset the id to the numerically generated one
              $node['id'] = $id;
metzlerd's avatar
metzlerd committed
449
450
            }
            else {
metzlerd's avatar
metzlerd committed
451
452
              // Use the id of the element
              $id = (string)$node['id'];
453
            }
metzlerd's avatar
metzlerd committed
454
          }
metzlerd's avatar
metzlerd committed
455

metzlerd's avatar
metzlerd committed
456
457
458
459
460
          // Save away the frx attributes in case we need them later.
          $attr_nodes = $node->attributes(FRX_NS);
          $attrs = array();
          if ($attr_nodes) foreach ($attr_nodes as $key => $value) {
            $attrs[$key] = (string)$value;
461
          }
metzlerd's avatar
metzlerd committed
462
463
464
465
          // Save away the attributes
          $frx_attributes[$id] = $attrs;
        }
      }
466

metzlerd's avatar
metzlerd committed
467
468
      $this->frx_attributes = $frx_attributes;
    }
469
  }
metzlerd's avatar
metzlerd committed
470

471
  /**
metzlerd's avatar
metzlerd committed
472
473
474
   * Get the attributes by
   *
   * @return array Attributes
475
476
   *
   * This function will return an array for all of the frx attributes defined in the report body
metzlerd's avatar
metzlerd committed
477
   * These attributes can be saved away and added back in later using.
478
479
   */
  public function get_attributes_by_id() {
metzlerd's avatar
metzlerd committed
480
481
    $this->parse_ids();
    return $this->frx_attributes;
482
  }
metzlerd's avatar
metzlerd committed
483

484
485
486
487
  /**
   * Save attributes based on id match
   *
   * @param array $attributes
metzlerd's avatar
metzlerd committed
488
489
   *
   * The attributes array should be of the form
490
   * array( element_id => array( key1 => value1, key2 => value2)
metzlerd's avatar
metzlerd committed
491
   * The function restores the attributes based on the element id.
492
493
   */
  public function save_attributes_by_id($attributes) {
metzlerd's avatar
metzlerd committed
494
495
    $rpt_xml = $this->rpt_xml;
    if ($attributes) foreach ($attributes as $id => $att_list) {
metzlerd's avatar
metzlerd committed
496
      $id_search_path = '//*[@id="' . $id . '"]';
497
      $fnd = $rpt_xml->xpath($id_search_path);
metzlerd's avatar
metzlerd committed
498
499
500
      if ($fnd) {
        $node = $fnd[0];

501
        // Start attribute replacement
metzlerd's avatar
metzlerd committed
502
503
504
505
        $frx_attributes = $node->Attributes(FRX_NS);

        foreach ($att_list as $key => $value) {
          if (!$frx_attributes[$key]) {
metzlerd's avatar
metzlerd committed
506
            $node['frx:' . $key] = $value;
metzlerd's avatar
metzlerd committed
507
          }
508
          else {
metzlerd's avatar
metzlerd committed
509
            unset($frx_attributes[$key]);
metzlerd's avatar
metzlerd committed
510
            $node['frx:' . $key] = $value;
511
512
513
514
515
          }
        }
      }
    }
  }
metzlerd's avatar
metzlerd committed
516

517
518
  /**
   * Set the value of an element within the report
metzlerd's avatar
metzlerd committed
519
520
   * @param String $xpath Xpath to element being saved
   * @param string $value Value to be saved.
521
522
   * @return unknown_type
   */
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
  public function set_value($xpath, $value) {
    $xml = $this->rpt_xml;
    $i = strrpos($xpath, '/');
    $path = substr($xpath, 0, $i);
    $key = substr($xpath, $i+1);
    $nodes = $xml->xpath($path);
    if ($nodes) {
      // if the last part of the xpath is a key then assume the key
      if (strpos($key, '@')===0) {
        $key = trim($key, '@');
        if (is_null($value)) {
          unset($nodes[0][$key]);
        }
        else {
          $nodes[0][$key] = $value;
        }
metzlerd's avatar
metzlerd committed
539
      }
540
      // We must be refering to the text element of a node.
metzlerd's avatar
metzlerd committed
541
      else {
542
543
544
545
546
547
        if (is_null($value)) {
          unset($nodes[0]->$key);
        }
        else {
          $nodes[0]->$key = $value;
        }
metzlerd's avatar
metzlerd committed
548
549
      }
    }
550
551
552
553
  }

  /**
   * Default the parameters ba
metzlerd's avatar
metzlerd committed
554
555
   * @param $parms Array of parameters.
   * @return boolean indicating whether the required parameters are present.
556
   */
metzlerd's avatar
metzlerd committed
557
558
559
  public function processParameters() {
    $parms = $this->parms;
    $missing_parms = FALSE;
560

561
    foreach ($this->parameters as $key => $parm) {
metzlerd's avatar
metzlerd committed
562

563
      if ((@$parms[$key]==='' || @$parms[$key]===array() || @$parms[$key]===NULL) && @$parm['value']) {
metzlerd's avatar
metzlerd committed
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
        $value = $parm['value'];
        $options = array();
        if (@$parm['options']) {
          parse_str($parm['options'],$options);
        }
        switch ((string)@$parm['type']) {
          case 'date_text':
          case 'date_popup':
          case 'date_select':
             if ($value){

                $datetime = @strtotime($value);
                if ($datetime) {
                  $value = date($options['date_format'], $datetime);
                }

              }
            break;
          default:
            if (strpos($value, '|')!==FALSE) {
              $value = explode('|', $value);
            }
metzlerd's avatar
metzlerd committed
586
587
588
        }
        $parms[$key] = $value;
        $reload_params = TRUE;
589
      }
metzlerd's avatar
metzlerd committed
590
591
      //do not show report if a required parameter does not have a value
      //force the user to input a parameter
metzlerd's avatar
metzlerd committed
592
593

      if ((@!$parms[$key]) && (@strcmp($parm['require'], "1") == 0)) {
594
        $missing_parms = TRUE;
595
596
      }
    }
metzlerd's avatar
metzlerd committed
597
    $this->parms = $parms;
598
    $this->missing_parms = $missing_parms;
metzlerd's avatar
metzlerd committed
599
    return $missing_parms;
600
  }
metzlerd's avatar
metzlerd committed
601

metzlerd's avatar
metzlerd committed
602
603
604
  public function parametersArray() {
    $parameters = array();
    $head = $this->rpt_xml->head;
605

606
    //FrxReportGenerator::instance()->alter_parameters('', $parms);
607
608
609
    $nodes = $head->xpath('frx:parameters/frx:parm');
    if ($nodes) {
      foreach ($nodes as $node) {
metzlerd's avatar
metzlerd committed
610
611
        $parm_def=array();
        $parm_def['default'] = (string)$node;
metzlerd's avatar
metzlerd committed
612
        foreach ($node->attributes() as $key => $value) {
metzlerd's avatar
metzlerd committed
613
          $parm_def[$key] = (string)$value;
614
        }
metzlerd's avatar
metzlerd committed
615
616
        $id = @$parm_def['id'];
        $parameters[$id] = $parm_def;
617
      }
618
    }
metzlerd's avatar
metzlerd committed
619
620
621
    return $parameters;
  }

622
623
  public function parametersForm($variables = array()) {

metzlerd's avatar
metzlerd committed
624
    $parms = $this->parametersArray();
625
626

    return drupal_get_form('forena_parameter_form', $parms, $variables);
627
628
  }

metzlerd's avatar
metzlerd committed
629
630
631
}