Mercurial > defr > drupal > views_calc
comparison views_calc_plugin_style_chart.inc @ 0:0651c02e6ed7
views_calc 1.3
| author | Franck Deroche <franck@defr.org> |
|---|---|
| date | Wed, 05 Aug 2009 18:20:29 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:0651c02e6ed7 |
|---|---|
| 1 <?php | |
| 2 // $Id: views_calc_plugin_style_chart.inc,v 1.7 2009/04/20 19:38:42 karens Exp $ | |
| 3 | |
| 4 /** | |
| 5 * @file | |
| 6 * Contains the chart style plugin. | |
| 7 */ | |
| 8 | |
| 9 /** | |
| 10 * Style plugin to render view as a chart. | |
| 11 * | |
| 12 * @ingroup views_style_plugins | |
| 13 */ | |
| 14 class views_calc_plugin_style_chart extends views_plugin_style { | |
| 15 // Set default options. | |
| 16 function options(&$options) { | |
| 17 $options['format'] = 'pie2D'; | |
| 18 $options['height'] = 200; | |
| 19 $options['width'] = 400; | |
| 20 $options['color'] = 'ffffff'; | |
| 21 $options['aggregation_field'] = ''; | |
| 22 $options['calc_fields'] = array(); | |
| 23 $options['calc'] = 'COUNT'; | |
| 24 $options['precision'] = 2; | |
| 25 } | |
| 26 | |
| 27 // Generate a form for setting options. | |
| 28 function options_form(&$form, &$form_state) { | |
| 29 parent::options_form($form, $form_state); | |
| 30 | |
| 31 $form['format'] = array( | |
| 32 '#type' => 'select', | |
| 33 '#title' => t('Chart format'), | |
| 34 '#options' => array( | |
| 35 'line2D' => t('Line 2D'), | |
| 36 'hbar2D' => t('Horizontal Bar 2D'), | |
| 37 'vbar2D' => t('Vertical Bar 2D'), | |
| 38 'pie2D' => t('Pie 2D'), | |
| 39 'pie3D' => t('Pie 3D'), | |
| 40 'venn' => t('Venn'), | |
| 41 'scatter' => t('Scatter Plot') | |
| 42 ), | |
| 43 '#default_value' => $this->options['format'], | |
| 44 ); | |
| 45 $form['height'] = array( | |
| 46 '#type' => 'textfield', | |
| 47 '#title' => t('Chart height'), | |
| 48 '#default_value' => $this->options['height'], | |
| 49 '#required' => TRUE, // Google charts breaks if it is empty. | |
| 50 '#description' => t('An integer value, the number of pixels of height for this chart.'), | |
| 51 ); | |
| 52 $form['width'] = array( | |
| 53 '#type' => 'textfield', | |
| 54 '#title' => t('Chart width'), | |
| 55 '#default_value' => $this->options['width'], | |
| 56 '#required' => TRUE, // Google charts breaks if it is empty. | |
| 57 '#description' => t('An integer value, the number of pixels of width for this chart.'), | |
| 58 ); | |
| 59 $form['color'] = array( | |
| 60 '#type' => 'textfield', | |
| 61 '#title' => t('Background color'), | |
| 62 '#default_value' => $this->options['color'], | |
| 63 '#description' => t('In hexadecimal format (RRGGBB). Do not use the # symbol.'), | |
| 64 '#required' => TRUE, // Google charts breaks if it is empty. | |
| 65 ); | |
| 66 $form['show_legend'] = array( | |
| 67 '#type' => 'checkbox', | |
| 68 '#title' => t('Show legend'), | |
| 69 '#default_value' => $this->options['show_legend'], | |
| 70 '#description' => t('Display legend next to the chart.'), | |
| 71 ); | |
| 72 | |
| 73 $form['aggregation_field'] = array( | |
| 74 '#type' => 'select', | |
| 75 '#title' => t('Aggregation field'), | |
| 76 '#options' => $this->aggregated_field_options(), | |
| 77 '#default_value' => $this->options['aggregation_field'], | |
| 78 '#description' => t('Select a field to aggreagate the results on.') | |
| 79 ); | |
| 80 // TODO Charts module cannot currently handle more than one series, | |
| 81 // update Multiple to TRUE if that changes. | |
| 82 $form['calc_fields'] = array( | |
| 83 '#type' => 'select', | |
| 84 '#title' => t('Computation field'), | |
| 85 '#options' => $this->aggregated_field_options(), | |
| 86 '#default_value' => $this->calc_fields(), | |
| 87 '#multiple' => FALSE, | |
| 88 '#description' => t('Select field to perform computations on.') | |
| 89 ); | |
| 90 $form['calc'] = array( | |
| 91 '#type' => 'select', | |
| 92 '#title' => t('Computation to perform'), | |
| 93 '#options' => $this->calc_options(), | |
| 94 '#default_value' => $this->options['calc'], | |
| 95 ); | |
| 96 $form['precision'] = array( | |
| 97 '#type' => 'select', | |
| 98 '#title' => t('Precision'), | |
| 99 '#options' => range(0, 4), | |
| 100 '#default_value' => $this->options['precision'], | |
| 101 '#description' => t('Decimal points to use in computed values.'), | |
| 102 ); | |
| 103 } | |
| 104 | |
| 105 function calc_options() { | |
| 106 return array( | |
| 107 '' => t('None'), | |
| 108 'SUM' => t('Sum'), | |
| 109 'COUNT' => t('Count'), | |
| 110 'AVG' => t('Average'), | |
| 111 'MIN' => t('Minimum'), | |
| 112 'MAX' => t('Maximum'), | |
| 113 ); | |
| 114 } | |
| 115 | |
| 116 /** | |
| 117 * Create an options array of available fields from this view. | |
| 118 */ | |
| 119 function aggregated_field_options() { | |
| 120 $field_names = array(); | |
| 121 $handlers = $this->display->handler->get_handlers('field'); | |
| 122 foreach ($handlers as $field => $handler) { | |
| 123 if ($label = $handler->label()) { | |
| 124 $field_names[$field] = $label; | |
| 125 } | |
| 126 else { | |
| 127 $field_names[$field] = $handler->ui_name(); | |
| 128 } | |
| 129 } | |
| 130 return $field_names; | |
| 131 } | |
| 132 | |
| 133 /** | |
| 134 * Make sure calc_fields is always an array, even when not multiple. | |
| 135 */ | |
| 136 function calc_fields() { | |
| 137 $calc_fields = (array) $this->options['calc_fields']; | |
| 138 return array_values($calc_fields); | |
| 139 } | |
| 140 | |
| 141 // Define and display a chart from the grouped values. | |
| 142 function render() { | |
| 143 // Scan all Views data and insert them into a series. | |
| 144 $data = array(); | |
| 145 | |
| 146 // Get values from rows. | |
| 147 foreach ($this->calc_fields() as $calc) { | |
| 148 foreach ($this->view->result as $row) { | |
| 149 foreach ($this->view->field as $key => $field) { | |
| 150 if ($key == $this->options['aggregation_field']) { | |
| 151 $legend_field = array_key_exists($calc, $this->view->field) ? $this->view->field[$calc] : NULL; | |
| 152 $legend = !empty($legend_field->options['label']) ? $legend_field->options['label'] : NULL; | |
| 153 if ($this->options['show_legend']) { | |
| 154 $data[$calc]['#legend'] = $legend; | |
| 155 } | |
| 156 $value['#label'] = strip_tags(theme_views_view_field($this->view, $this->view->field[$key], $row)); // .': '. $row->$calc; | |
| 157 $value['#value'] = $row->$calc; | |
| 158 $data[$calc][] = $value; | |
| 159 } | |
| 160 } | |
| 161 } | |
| 162 } | |
| 163 | |
| 164 // Get chart settings from options form. | |
| 165 $legend_field = $this->view->field[$this->options['aggregation_field']]; | |
| 166 $chart = array( | |
| 167 '#type' => $this->options['format'], | |
| 168 '#height' => $this->options['height'], | |
| 169 '#width' => $this->options['width'], | |
| 170 '#color' => $this->options['color'], | |
| 171 ); | |
| 172 | |
| 173 // Use the view title as the chart title. | |
| 174 $chart['#title'] = $this->view->get_title(); | |
| 175 | |
| 176 // Insert series into the chart array. | |
| 177 foreach ($data as $series) { | |
| 178 $chart[] = $series; | |
| 179 } | |
| 180 | |
| 181 // Print the chart. | |
| 182 return charts_chart($chart); | |
| 183 } | |
| 184 | |
| 185 function query() { | |
| 186 parent::query(); | |
| 187 | |
| 188 // Clear the fields out, we'll replace them with calculated values. | |
| 189 $this->view->query->clear_fields(); | |
| 190 // Clear out any sorting, it can create unexpected results | |
| 191 // when Views adds aggregation values for the sorts. | |
| 192 $this->view->query->orderby = array(); | |
| 193 | |
| 194 // Add the grouping information to the query. | |
| 195 // Field setting of array('aggregate' => TRUE) tells Views not to force | |
| 196 // another aggregation in for this field. | |
| 197 | |
| 198 foreach ($this->view->field as $field) { | |
| 199 $query_field = substr($field->field, 0, 3) == 'cid' ? $field->definition['calc'] : $field->table .'.'. $field->field; | |
| 200 $query_alias = $field->field_alias; | |
| 201 | |
| 202 // Add the aggregation. | |
| 203 if ($field->field == $this->options['aggregation_field']) { | |
| 204 $this->view->query->add_orderby(NULL, NULL, 'asc', $query_alias); | |
| 205 $this->view->query->add_groupby($query_field); | |
| 206 if (substr($field->field, 0, 3) == 'cid') { | |
| 207 $this->view->query->add_field(NULL, $query_field, $field->field, array('aggregate' => TRUE)); | |
| 208 } | |
| 209 else { | |
| 210 $this->view->query->add_field($field->table, $field->field, NULL, array('aggregate' => TRUE)); | |
| 211 } | |
| 212 } | |
| 213 // Add computed values. | |
| 214 if (in_array($field->field, $this->calc_fields())) { | |
| 215 $sql = "ROUND(". $this->options['calc'] ."($query_field), ". $this->options['precision'] .")"; | |
| 216 $this->view->query->add_field(NULL, $sql, $field->field, array('aggregate' => TRUE)); | |
| 217 | |
| 218 // TODO This part is not relationship-safe, needs additional work | |
| 219 // to join in the right table if the computation is done | |
| 220 // on a field that comes from a relationship. | |
| 221 | |
| 222 // Make sure the table with the right alias name is available | |
| 223 // (it might have been dropped during Views optimizations.) | |
| 224 $this->view->query->add_table($field->table); | |
| 225 } | |
| 226 } | |
| 227 } | |
| 228 } |
