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 } |