Exemple #1
0
 /**
  * Load the Fusion chart lib
  *
  * @return  string
  */
 public function getFusionchart()
 {
     $this->cantTrendLine = array();
     $document = JFactory::getDocument();
     $params = $this->getParams();
     $worker = new FabrikWorker();
     $fc_version = $params->get('fusionchart_version', 'free_old');
     $free22 = $this->pathBase . 'fusionchart/libs/FusionChartsFree/Code/PHPClass/Includes/FusionCharts_Gen.php';
     $pro30 = $this->pathBase . 'fusionchart/libs/FusionCharts/Code/PHPClass/Includes/FusionCharts_Gen.php';
     if ($fc_version == 'free_22' && JFile::exists($free22)) {
         require_once $free22;
         $document->addScript($this->srcBase . "fusionchart/libs/FusionChartsFree/JSClass/FusionCharts.js");
         $fc_swf_path = COM_FABRIK_LIVESITE . $this->srcBase . "fusionchart/libs/FusionChartsFree/Charts/";
     } elseif ($fc_version == 'pro_30' && JFile::exists($pro30)) {
         require_once $pro30;
         $document->addScript($this->srcBase . "fusionchart/libs/FusionCharts/Charts/FusionCharts.js");
         $fc_swf_path = COM_FABRIK_LIVESITE . $this->srcBase . "fusionchart/libs/FusionCharts/Charts/";
     } else {
         require_once $this->pathBase . 'fusionchart/libs/FCclass/FusionCharts_Gen.php';
         $document->addScript($this->srcBase . "fusionchart/libs/FCcharts/FusionCharts.js");
         $fc_swf_path = COM_FABRIK_LIVESITE . $this->srcBase . "fusionchart/libs/FCcharts/";
     }
     $calc_prefixes = array('sum___', 'avg___', 'med___', 'cnt___');
     $calc_prefixmap = array('sum___' => 'sums', 'avg___' => 'avgs', 'med___' => 'medians', 'cnt___' => 'count');
     $w = $params->get('fusionchart_width');
     $h = $params->get('fusionchart_height');
     $chartType = $params->get('fusionchart_type', '');
     if ($chartType == '') {
         throw new InvalidArgumentException('Not chart type selected');
     }
     // Create new chart
     $this->FC = new FusionCharts($chartType, $w, $h);
     // If we are pro lets use the new JavaScript Library
     if ($fc_version === 'pro_30') {
         $this->FC->setRenderer('javascript');
     }
     // Define path to FC's SWF
     $this->FC->setSWFPath($fc_swf_path);
     $this->setChartMessages();
     // Setting Param string
     $strParam = $this->getChartParams();
     $label_step_ratios = (array) $params->get('fusion_label_step_ratio');
     $x_axis_label = (array) $params->get('fusion_x_axis_label');
     $chartElements = (array) $params->get('fusionchart_elementList');
     $chartColours = (array) $params->get('fusionchart_elcolour');
     $listid = (array) $params->get('fusionchart_table');
     $chartCumulatives = (array) $params->get('fusionchart_cumulative');
     $elTypes = (array) $params->get('fusionchart_element_type');
     $this->setAxisLabels();
     $dual_y_parents = $params->get('fusionchart_dual_y_parent');
     $chartWheres = (array) $params->get('fusionchart_where');
     $limits = (array) $params->get('fusionchart_limit');
     $this->c = 0;
     $gdata = array();
     $glabels = array();
     $gcolours = array();
     $gfills = array();
     $this->max = array();
     $this->min = array();
     $calculationLabels = array();
     $calculationData = array();
     $calcfound = false;
     $tmodels = array();
     $labelStep = 0;
     foreach ($listid as $tid) {
         $this->min[$this->c] = 0;
         $this->max[$this->c] = 0;
         if (!array_key_exists($tid, $tmodels)) {
             $listModel = null;
             $listModel = JModelLegacy::getInstance('list', 'FabrikFEModel');
             $listModel->setId($tid);
             $tmodels[$tid] = $listModel;
         } else {
             $listModel = $tmodels[$tid];
         }
         $table = $listModel->getTable();
         $form = $listModel->getForm();
         // $$$ hugh - adding plugin query, 2012-02-08
         if (array_key_exists($this->c, $chartWheres) && !empty($chartWheres[$this->c])) {
             $chartWhere = $this->_replaceRequest($chartWheres[$this->c]);
             $chartWhere = $worker->replaceWithUserData($chartWhere);
             $listModel->setPluginQueryWhere('fusionchart', $chartWhere);
         } else {
             // If no where clause, explicitly clear any previously set clause
             $listModel->unsetPluginQueryWhere('fusionchart');
         }
         /* $$$ hugh - remove pagination BEFORE calling render().  Otherwise render() applies
          * session state/defaults when it calls getPagination, which is then returned as a cached
          * object if we call getPagination after render().  So call it first, then render() will
          * get our cached pagination, rather than vice versa.
          */
         $limit = (int) FArrayHelper::getValue($limits, $this->c, 0);
         $listModel->setLimits(0, $limit);
         $nav = $listModel->getPagination(0, 0, $limit);
         $listModel->render();
         $alldata = $listModel->getData();
         $cals = $listModel->getCalculations();
         $column = $chartElements[$this->c];
         $pref = substr($column, 0, 6);
         $label = FArrayHelper::getValue($x_axis_label, $this->c, '');
         $tmpgdata = array();
         $tmpglabels = array();
         $colour = array_key_exists($this->c, $chartColours) ? str_replace("#", '', $chartColours[$this->c]) : '';
         $gcolours[] = $colour;
         if (in_array($pref, $calc_prefixes)) {
             /* you shouldn't mix calculation elements with normal elements when creating the chart
              * so if ONE calculation element is found we use the calculation data rather than normal element data
              * this is because a calculation element only generates one value, if want to compare two averages then
              * they get rendered as tow groups of data and on bar charts this overlays one average over the other, rather than next to it
              */
             $calcfound = true;
             $column = JString::substr($column, 6);
             $calckey = $calc_prefixmap[$pref];
             $caldata = FArrayHelper::getValue($cals[$calckey], $column . '_obj');
             if (is_array($caldata)) {
                 foreach ($caldata as $k => $o) {
                     if ($k !== 'Total') {
                         $calculationData[] = (double) $o->value;
                         $calculationLabels[] = trim(strip_tags($o->label));
                     }
                 }
             }
             if (!empty($calculationData)) {
                 $this->max[$this->c] = max($calculationData);
                 $this->min[$this->c] = min($calculationData);
             }
             $gdata[$this->c] = implode(',', $tmpgdata);
             $glabels[$this->c] = implode('|', $tmpglabels);
             /* $$$ hugh - playing around with pie charts
              * $gsums[$this->c] = array_sum($tmpgdata);
              */
             $gsums[$this->c] = array_sum($calculationData);
         } else {
             $origColumn = $column;
             // _raw fields are most likely to contain the value
             $column = $column . '_raw';
             foreach ($alldata as $group) {
                 foreach ($group as $row) {
                     if (!array_key_exists($column, $row)) {
                         // Didn't find a _raw column - revert to orig
                         $column = $origColumn;
                         if (!array_key_exists($column, $row)) {
                             JError::raiseWarning(E_NOTICE, $column . ': NOT FOUND - PLEASE CHECK IT IS PUBLISHED');
                             continue;
                         }
                     }
                     $tmpgdata[] = trim($row->{$column}) == '' ? -1 : (double) $row->{$column};
                     $tmpglabels[] = !empty($label) ? html_entity_decode(strip_tags($row->{$label})) : '';
                 }
                 if (!empty($tmpgdata)) {
                     $this->max[$this->c] = max($tmpgdata);
                     $this->min[$this->c] = min($tmpgdata);
                 }
                 $gdata[$this->c] = implode(',', $tmpgdata);
                 $glabels[$this->c] = implode('|', $tmpglabels);
                 // $$$ hugh - playing around with pie charts
                 $gsums[$this->c] = array_sum($tmpgdata);
                 // $$$ hugh - playing with 'cumulative' option
                 $this->gcumulatives[$this->c] = array();
                 while (!empty($tmpgdata)) {
                     $this->gcumulatives[$this->c][] = array_sum($tmpgdata);
                     array_pop($tmpgdata);
                 }
                 $this->gcumulatives[$this->c] = array_reverse($this->gcumulatives[$this->c]);
             }
         }
         $this->c++;
     }
     if ($calcfound) {
         $calculationLabels = array_reverse($calculationLabels);
         $glabels = array(implode('|', array_reverse($calculationLabels)));
         $gdata = array(implode(',', $calculationData));
     }
     /* $$$ hugh - pie chart data has to be summed - the API only takes a
      * single dataset for pie charts.  And it doesn't make sense trying to
      * chart individual row data for multiple elements in a pie chart.
      * Also, labels need to be axisLabels, not $glabels
      */
     switch ($chartType) {
         // Single Series Charts
         case 'AREA2D':
         case 'BAR2D':
         case 'COLUMN2D':
         case 'COLUMN3D':
         case 'DOUGHNUT2D':
         case 'DOUGHNUT3D':
         case 'LINE':
             /* $$$ tom - for now I'm enabling Pie charts here so that it displays
              * something until we do it properly as you said hugh
              * Well maybe there's something I don't get but in fact FC already draw
              * the pies by "percenting" the values of each data... if you know what I mean Hugh;)
              */
         /* $$$ tom - for now I'm enabling Pie charts here so that it displays
          * something until we do it properly as you said hugh
          * Well maybe there's something I don't get but in fact FC already draw
          * the pies by "percenting" the values of each data... if you know what I mean Hugh;)
          */
         case 'PIE2D':
         case 'PIE3D':
         case 'SCATTER':
             // Adding specific params for Pie charts
             if ($chartType == 'PIE2D' || $chartType == 'PIE3D') {
                 $strParam .= ';pieBorderThickness=' . $params->get('fusionchart_borderthick', '');
                 $strParam .= ';pieBorderAlpha=' . $params->get('fusionchart_cnvalpha', '');
                 $strParam .= ';pieFillAlpha=' . FArrayHelper::getValue($params->get('fusionchart_elalpha', array()), 0);
             }
             if ($this->c > 1) {
                 $arrCatNames = array();
                 foreach ($this->axisLabels as $alkey => $al) {
                     $arrCatNames[] = $al;
                 }
                 $arrData = array();
                 $i = 0;
                 foreach ($gsums as $gd) {
                     $arrData[$i][0] = $this->axisLabels[$i];
                     $arrData[$i][1] = $gd;
                     $i++;
                 }
                 $this->FC->addChartDataFromArray($arrData, $arrCatNames);
             } else {
                 // Single table/elements, so use the row data
                 $labels = explode('|', $glabels[0]);
                 // $gsums = !array_key_exists(0, $chartCumulatives) || $chartCumulatives[0] == '0' ? explode(',', $gdata[0]) : explode(',', $gcumulatives[0]);
                 $gsums = FArrayHelper::getValue($chartCumulatives, 0, '0') == '0' ? explode(',', $gdata[0]) : $this->gcumulatives[0];
                 // Scale to percentages
                 $tot_sum = array_sum($gsums);
                 $arrData = array();
                 $labelStep = 0;
                 $label_step_ratio = (int) FArrayHelper::getValue($label_step_ratios, 0, 1);
                 if ($label_step_ratio > 1) {
                     $labelStep = (int) (count($gsums) / $label_step_ratio);
                     $strParam .= ';labelStep=' . $labelStep;
                 }
                 /* $$$tom: inverting array_combine as identical values in gsums will be
                  * dropped otherwise. Should I do that differently?
                  * $$$ hugh - can't use array_combine, as empty labels end up dropping values
                  * $arrComb = array_combine($labels, $gsums);
                  * foreach ($arrComb as $key => $value) {
                  */
                 if ($elTypes[0] == 'trendonly') {
                     $str_params = '';
                     $min = min($gsums);
                     $max = max($gsums);
                     list($min, $max) = $this->getTrendMinMax($min, $max, 0);
                     $this->FC->addChartData($min, $str_params);
                     $this->FC->addChartData($max, $str_params);
                 } else {
                     $data_count = 0;
                     foreach ($gsums as $key => $value) {
                         $data_count++;
                         if ($value == '-1') {
                             $value = null;
                         }
                         $label = $labels[$key];
                         $str_params = 'name=' . $label;
                         if ($labelStep) {
                             if ($data_count != 1 && $data_count % $labelStep != 0) {
                                 $str_params .= ';showName=0';
                             }
                         }
                         $this->FC->addChartData($value, $str_params);
                     }
                 }
             }
             break;
         case 'MSBAR2D':
         case 'MSBAR3D':
         case 'MSCOLUMN2D':
         case 'MSCOLUMN3D':
         case 'MSLINE':
         case 'MSAREA2D':
         case 'MSCOMBIDY2D':
         case 'MULTIAXISLINE':
         case 'STACKEDAREA2D':
         case 'STACKEDBAR2D':
         case 'STACKEDCOLUMN2D':
         case 'STACKEDCOLUMN3D':
         case 'SCROLLAREA2D':
         case 'SCROLLCOLUMN2D':
         case 'SCROLLLINE2D':
         case 'SCROLLSTACKEDCOLUMN2D':
             if ($this->c > 1) {
                 if ($chartType == 'SCROLLAREA2D' || $chartType == 'SCROLLCOLUMN2D' || $chartType == 'SCROLLLINE2D') {
                     $strParam .= ';numVisiblePlot=' . $params->get('fusionchart_scroll_numvisible', 0);
                 }
                 // $$$ hugh - Dual-Y types
                 if ($chartType == 'MSCOMBIDY2D' || $chartType == 'MULTIAXISLINE') {
                     $p_parents = array();
                     $s_parents = array();
                     foreach ($dual_y_parents as $dual_y_key => $dual_y_parent) {
                         if ($dual_y_parent == "P") {
                             $p_parents[] = $this->axisLabels[$dual_y_key];
                         } else {
                             $s_parents[] = $this->axisLabels[$dual_y_key];
                         }
                     }
                     $strParam .= ';PYAxisName=' . implode(' ', $p_parents);
                     $strParam .= ';SYaxisName=' . implode(' ', $s_parents);
                 }
                 $label_step_ratio = (int) FArrayHelper::getValue($label_step_ratios, 0, 1);
                 if ($label_step_ratio > 1) {
                     $labelStep = (int) (count(explode(',', $gdata[0])) / $label_step_ratio);
                     $strParam .= ';labelStep=' . $labelStep;
                 }
                 // Start tom's changes
                 $labels = explode('|', $glabels[0]);
                 $data_count = 0;
                 foreach ($labels as $catLabel) {
                     $data_count++;
                     $catParams = '';
                     if ($labelStep) {
                         if ($data_count == 1 || $data_count % $labelStep == 0) {
                             $catParams = 'ShowLabel=1';
                         } else {
                             $catParams = 'ShowLabel=0';
                             $catLabel = '';
                         }
                     }
                     $this->FC->addCategory($catLabel, $catParams);
                 }
                 foreach ($gdata as $key => $chartdata) {
                     $cdata = FArrayHelper::getValue($chartCumulatives, $key, '0') == '0' ? explode(',', $gdata[$key]) : $this->gcumulatives[$key];
                     $dataset = $this->axisLabels[$key];
                     $extras = 'parentYAxis=' . $dual_y_parents[$key];
                     $color = FArrayHelper::getValue($gcolours, $key, '');
                     if (!empty($color)) {
                         $extras .= ";color=" . $color;
                     }
                     $this->FC->addDataset($dataset, $extras);
                     if ($elTypes[$key] == 'trendonly') {
                         $str_params = '';
                         $strParam .= ';connectNullData=1';
                         $min = min($cdata);
                         $max = max($cdata);
                         list($min, $max) = $this->getTrendMinMax($min, $max, $key);
                         $max_datapoints = $this->getMaxDatapoints($gdata);
                         $this->FC->addChartData($min, $str_params);
                         for ($x = 0; $x < $max_datapoints - 2; $x++) {
                             $this->FC->addChartData('', $str_params);
                         }
                         $this->FC->addChartData($max, $str_params);
                     } else {
                         $data_count = 0;
                         foreach ($cdata as $value) {
                             $data_count++;
                             if ($value == '-1') {
                                 $value = null;
                             }
                             $this->FC->addChartData($value);
                         }
                     }
                 }
             }
     }
     $this->c > 1 ? $this->trendLine($gdata) : $this->trendLine();
     $colours = implode($calcfound ? '|' : ',', $gcolours);
     // Set chart attributes
     if ($params->get('fusionchart_custom_attributes', '')) {
         $strParam .= ';' . trim($params->get('fusionchart_custom_attributes'));
     }
     $strParam = "{$strParam}";
     $this->FC->setChartParams($strParam);
     // Render Chart
     if ($chartType == 'MULTIAXISLINE') {
         // Nasty, nasty hack for MULTIAXIS, as the FC class doesn't support it.  So need to get the chart XML,
         // split out the <dataset>...</dataset> and wrap them in <axis>...</axis>
         $axis_attrs = (array) $params->get('fusionchart_mx_attributes');
         $dataXML = $this->FC->getXML();
         $matches = array();
         if (preg_match_all('#(<\\s*dataset[^>]*>.*?<\\s*/dataset\\s*>)#', $dataXML, $matches)) {
             $index = 0;
             foreach ($gdata as $key => $chartdata) {
                 $axis = "<axis " . $axis_attrs[$index] . ">" . $matches[0][$index] . "</axis>";
                 $dataXML = str_replace($matches[0][$index], $axis, $dataXML);
                 $index++;
             }
         }
         return $this->FC->renderChartFromExtXML($dataXML);
     } else {
         return $this->FC->renderChart(false, false);
     }
 }
Exemple #2
0
 /**
  * iterates through string to replace every
  * {placeholder} with posted data
  * @param string text to parse
  * @param array data to search for placeholders (default $_REQUEST)
  * @param bool if no data found for the place holder do we keep the {...} string in the message
  * @param bool add slashed to the text?
  * @param object user to use in replaceWithUserData (defaults to logged in user)
  */
 public function parseMessageForPlaceHolder($msg, $searchData = null, $keepPlaceholders = true, $addslashes = false, $theirUser = null)
 {
     $this->_parseAddSlases = $addslashes;
     if ($msg == '' || is_array($msg) || strpos($msg, '{') === false) {
         return $msg;
     }
     $msg = str_replace(array('%7B', '%7D'), array('{', '}'), $msg);
     if (is_object($searchData)) {
         $searchData = JArrayHelper::fromObject($searchData);
     }
     //$post	= JRequest::get('post');
     //$$$ rob changed to allow request variables to be parsed as well. I have a sneaky feeling this
     // was set to post for a good reason, but I can't see why now.
     // $$$ hugh - for reasons I don't understand, merging request just doesn't seem to work
     // in some situations, so I'm adding a replaceRequest call here as a bandaid.
     // @TODO $$$ rob can you remember what those situations where? Because doing this is messing up form plugins (e.g redirect) when they do replace on getEmailData()
     // as having the line below commented in causes the request to be used before searchData.
     // FabrikWorker::replaceRequest($msg);
     $post = JRequest::get('request');
     $this->_searchData = is_null($searchData) ? $post : array_merge($post, $searchData);
     $this->_searchData['JUtility::getToken'] = JUtility::getToken();
     $msg = FabrikWorker::replaceWithUserData($msg);
     if (!is_null($theirUser)) {
         $msg = FabrikWorker::replaceWithUserData($msg, $theirUser, 'your');
     }
     $msg = FabrikWorker::replaceWithGlobals($msg);
     $msg = preg_replace("/{}/", "", $msg);
     /* replace {element name} with form data */
     $msg = preg_replace_callback("/{[^}\\s]+}/i", array($this, 'replaceWithFormData'), $msg);
     if (!$keepPlaceholders) {
         $msg = preg_replace("/{[^}\\s]+}/i", '', $msg);
     }
     return $msg;
 }
Exemple #3
0
 /**
  * Iterates through string to replace every
  * {placeholder} with row data
  * (added by hugh, does the same thing as parseMessageForPlaceHolder in parent
  * class, but for rows instead of forms)
  *
  * NOTE - I can't remember why I added this way back when in 2.x, instead of using the helper function,
  * I just know there was a good reason, to do with the helper func making assumptions about something
  * (I think to do with how form data is formatted) which weren't true when rendering list data.  I have
  * a suspicion that in the intervening years, the helper func and the way we format data may now be
  * copacetic, and we could do away with this separation, and just use the normal helper func.  Might be
  * worth testing, as this code looks like it has suffered bitrot, and doesn't do a number of things the main
  * helper func now does.
  *
  * @param   string  $msg         text to parse
  * @param   array   &$row        of row data
  * @param   bool    $addSlashes  add slashes to the replaced data (default = false) set to true in fabrikcalc element
  *
  * @return  string  parsed message
  */
 public function parseMessageForRowHolder($msg, &$row, $addSlashes = false)
 {
     $this->aRow = $row;
     if (!strstr($msg, '{')) {
         return $msg;
     }
     $this->parseAddSlases = $addSlashes;
     $msg = FabrikWorker::replaceWithUserData($msg);
     $msg = FabrikWorker::replaceWithGlobals($msg);
     $msg = preg_replace("/{}/", "", $msg);
     $this->rowIdentifierAdded = false;
     /* replace {element name} with form data */
     /* $$$ hugh - testing changing the regex so we don't blow away PHP structures!  Added the \s so
      * we only match non-space chars in {}'s.  So unless you have some code like "if (blah) {foo;}", PHP
      * block level {}'s should remain unmolested.
      */
     $msg = preg_replace_callback("/{[^}\\s]+}/i", array($this, 'replaceWithRowData'), $msg);
     $lang = $this->lang->getTag();
     $lang = str_replace('-', '_', $lang);
     $msg = str_replace('{lang}', $lang, $msg);
     return $msg;
 }