franck@0
|
1 <?php |
franck@2
|
2 // $Id: views_calc_table.inc,v 1.17 2009/06/13 17:05:38 karens Exp $ |
franck@0
|
3 /** |
franck@0
|
4 * @file |
franck@0
|
5 * Copied from the table style plugin. |
franck@0
|
6 */ |
franck@0
|
7 |
franck@0
|
8 /** |
franck@0
|
9 * Style plugin to render each item as a row in a table. |
franck@0
|
10 * |
franck@0
|
11 * @ingroup views_style_plugins |
franck@0
|
12 */ |
franck@0
|
13 class views_calc_table extends views_plugin_style_table { |
franck@0
|
14 |
franck@0
|
15 function option_definition() { |
franck@0
|
16 $options = parent::option_definition(); |
franck@0
|
17 |
franck@0
|
18 $options['detailed_values'] = array('default' => 0); |
franck@0
|
19 return $options; |
franck@0
|
20 } |
franck@0
|
21 |
franck@0
|
22 /** |
franck@0
|
23 * Render the given style. |
franck@0
|
24 */ |
franck@0
|
25 function options_form(&$form, &$form_state) { |
franck@0
|
26 parent::options_form($form, $form_state); |
franck@0
|
27 $form['#theme'] = 'views_calc_ui_table'; |
franck@0
|
28 |
franck@0
|
29 $form['detailed_values'] = array( |
franck@0
|
30 '#title' => t('Show details'), |
franck@0
|
31 '#type' => 'select', |
franck@0
|
32 '#options' => array(0 => t('Yes'), 1 => t('No')), |
franck@0
|
33 '#default_value' => $this->options['detailed_values'], |
franck@0
|
34 '#description' => t("Select 'Yes' to show detailed values followed by column calculations, 'No' to surpress details and show only calculated column totals."), |
franck@0
|
35 ); |
franck@0
|
36 |
franck@0
|
37 $handlers = $this->display->handler->get_handlers('field'); |
franck@0
|
38 $columns = $this->sanitize_columns($this->options['columns']); |
franck@0
|
39 |
franck@0
|
40 foreach ($columns as $field => $column) { |
franck@0
|
41 $safe = str_replace(array('][', '_', ' '), '-', $field); |
franck@0
|
42 $id = 'edit-style-options-columns-' . $safe; |
franck@0
|
43 $form['info'][$field]['justification'] = array( |
franck@0
|
44 '#type' => 'select', |
franck@0
|
45 '#default_value' => isset($this->options['info'][$field]['justification']) ? $this->options['info'][$field]['justification'] : 'views_calc_justify_none', |
franck@0
|
46 '#options' => array( |
franck@0
|
47 'views_calc_justify_none' => t('None'), |
franck@0
|
48 'views_calc_justify_left' => t('Left'), |
franck@0
|
49 'views_calc_justify_right' => t('Right'), |
franck@0
|
50 'views_calc_justify_center' => t('Center'), |
franck@0
|
51 ), |
franck@0
|
52 '#process' => array('views_process_dependency'), |
franck@0
|
53 '#dependency' => array($id => array($field)), |
franck@0
|
54 ); |
franck@0
|
55 $form['info'][$field]['has_calc'] = array( |
franck@0
|
56 '#type' => 'checkbox', |
franck@0
|
57 '#title' => t('Display calculation'), |
franck@0
|
58 '#default_value' => isset($this->options['info'][$field]['has_calc']) ? $this->options['info'][$field]['has_calc'] : 0, |
franck@0
|
59 '#process' => array('views_process_dependency'), |
franck@0
|
60 '#dependency' => array($id => array($field)), |
franck@0
|
61 ); |
franck@0
|
62 |
franck@0
|
63 $options = _views_calc_calc_options(); |
franck@0
|
64 $form['info'][$field]['calc'] = array( |
franck@0
|
65 '#type' => 'select', |
franck@0
|
66 '#options' => $options, |
franck@0
|
67 '#default_value' => isset($this->options['info'][$field]['calc']) ? $this->options['info'][$field]['calc'] : array(), |
franck@0
|
68 '#process' => array('views_process_dependency'), |
franck@0
|
69 '#dependency' => array('edit-style-options-info-'. $safe .'-has-calc' => array(TRUE)), |
franck@0
|
70 '#multiple' => TRUE, |
franck@0
|
71 ); |
franck@0
|
72 } |
franck@0
|
73 } |
franck@0
|
74 |
franck@0
|
75 /** |
franck@0
|
76 * TODO |
franck@0
|
77 * figure out what changes are needed so Views field groups will work. |
franck@0
|
78 */ |
franck@0
|
79 function pre_render($results) { |
franck@0
|
80 parent::pre_render($results); |
franck@2
|
81 |
franck@0
|
82 // If there are no calc fields, do nothing. |
franck@0
|
83 if (!$calc_fields = $this->get_calc_fields()) { |
franck@0
|
84 return; |
franck@0
|
85 } |
franck@0
|
86 // If we're not getting a summary row, do nothing. |
franck@0
|
87 if (!empty($this->view->views_calc_calculation)) { |
franck@0
|
88 return; |
franck@0
|
89 } |
franck@0
|
90 $this->view->totals = array(); |
franck@0
|
91 $this->view->sub_totals = array(); |
franck@0
|
92 |
franck@0
|
93 // Subtotals and pager totals require a list of the specific |
franck@0
|
94 // values to include. |
franck@0
|
95 $paged = FALSE; |
franck@0
|
96 if (!empty($this->view->pager) |
franck@0
|
97 && !empty($this->view->pager['use_pager']) |
franck@0
|
98 && !empty($this->view->pager['items_per_page'])) { |
franck@0
|
99 $nids = array(); |
franck@0
|
100 foreach ($this->view->result as $delta => $value) { |
franck@0
|
101 $nids[] = $value->nid; |
franck@0
|
102 } |
franck@0
|
103 // Add sub_total rows to the results. |
franck@2
|
104 // TODO Looks like we have problems unless we |
franck@2
|
105 // force a non-page display, need to keep an eye on this. |
franck@0
|
106 foreach ($calc_fields as $calc => $field) { |
franck@0
|
107 if ($summary_view = views_get_view($this->view->name)) { |
franck@2
|
108 //$summary_view->set_display($this->view->current_display); |
franck@0
|
109 $summary_view->set_arguments($this->view->args); |
franck@0
|
110 $summary_view->views_calc_calculation = $calc; |
franck@0
|
111 $summary_view->views_calc_nids = $nids; |
franck@0
|
112 $summary_view->views_calc_sub_total = TRUE; |
franck@0
|
113 $summary_view->is_cacheable = FALSE; |
franck@2
|
114 $summary_view->preview(); |
franck@0
|
115 $this->view->sub_totals[] = array_shift($summary_view->result); |
franck@0
|
116 } |
franck@0
|
117 } |
franck@0
|
118 } |
franck@0
|
119 |
franck@0
|
120 // Add grand totals to the results. |
franck@0
|
121 foreach ($calc_fields as $calc => $field) { |
franck@0
|
122 if ($summary_view = views_get_view($this->view->name)) { |
franck@2
|
123 //$summary_view->set_display($this->view->current_display); |
franck@0
|
124 $summary_view->set_arguments($this->view->args); |
franck@0
|
125 $summary_view->pager['items_per_page'] = 0; |
franck@0
|
126 $summary_view->views_calc_calculation = $calc; |
franck@0
|
127 $summary_view->views_calc_nids = array(); |
franck@0
|
128 $summary_view->views_calc_sub_total = FALSE; |
franck@0
|
129 $summary_view->is_cacheable = FALSE; |
franck@2
|
130 $summary_view->preview(); |
franck@0
|
131 $this->view->totals[] = array_shift($summary_view->result); |
franck@0
|
132 } |
franck@0
|
133 } |
franck@0
|
134 } |
franck@0
|
135 |
franck@0
|
136 function query() { |
franck@0
|
137 parent::query(); |
franck@0
|
138 |
franck@0
|
139 // If we're not getting a summary row, do nothing. |
franck@0
|
140 if (empty($this->view->views_calc_calculation)) { |
franck@0
|
141 return; |
franck@0
|
142 } |
franck@0
|
143 // If there are no calc fields, do nothing. |
franck@0
|
144 if (!$calc_fields = $this->get_calc_fields()) { |
franck@0
|
145 return; |
franck@0
|
146 } |
franck@0
|
147 |
franck@0
|
148 if (!empty($this->view->views_calc_sub_total)) { |
franck@0
|
149 $this->query_sub_total(); |
franck@0
|
150 } |
franck@0
|
151 else { |
franck@0
|
152 $this->query_total(); |
franck@0
|
153 } |
franck@0
|
154 } |
franck@0
|
155 |
franck@0
|
156 /** |
franck@0
|
157 * |
franck@0
|
158 */ |
franck@0
|
159 function query_sub_total() { |
franck@0
|
160 // Create summary rows. |
franck@0
|
161 $calc_fields = $this->get_calc_fields(); |
franck@0
|
162 $calc = $this->view->views_calc_calculation; |
franck@0
|
163 $fields = $calc_fields[$calc]; |
franck@0
|
164 |
franck@0
|
165 // Empty out any fields that have been added to the query, |
franck@0
|
166 // we don't need them for the summary totals. |
franck@0
|
167 $this->view->query->fields = array(); |
franck@0
|
168 foreach ($this->view->field as $field) { |
franck@0
|
169 $query_field = substr($field->field, 0, 3) == 'cid' ? $field->definition['calc'] : $field->table .'.'. $field->field; |
franck@0
|
170 $query_alias = $field->field_alias; |
franck@2
|
171 // Bail if we have a broken handler. |
franck@2
|
172 if ($query_alias == 'unknown') { |
franck@2
|
173 continue; |
franck@2
|
174 } |
franck@0
|
175 if (in_array($field->field, $fields)) { |
franck@0
|
176 // Calculated fields. |
franck@0
|
177 $this->view->query->add_field(NULL, "$calc($query_field)", $query_alias); |
franck@0
|
178 $this->view->query->add_table($field->table, NULL, NULL, $field->table); |
franck@0
|
179 } |
franck@0
|
180 else { |
franck@0
|
181 // Empty fields that have no calculations. |
franck@0
|
182 $this->view->query->add_field(NULL, "MAX('')", $query_alias); |
franck@0
|
183 } |
franck@0
|
184 // Add a dummy field for the groupby. |
franck@0
|
185 $this->view->query->add_field(NULL, "MAX('". $calc ."')", "TOTAL_". $calc); |
franck@0
|
186 } |
franck@0
|
187 // TODO This won't work right with relationships, need a fix here. |
franck@0
|
188 if (!empty($this->view->views_calc_nids)) { |
franck@0
|
189 $this->view->query->add_where(NULL, "node.nid IN (%s)", implode(',', $this->view->views_calc_nids)); |
franck@0
|
190 } |
franck@0
|
191 } |
franck@0
|
192 |
franck@0
|
193 /** |
franck@0
|
194 * The grand total can be computed using GROUPBY without regard |
franck@0
|
195 * to pager values. |
franck@0
|
196 */ |
franck@0
|
197 function query_total() { |
franck@0
|
198 // Create summary rows. |
franck@0
|
199 $calc_fields = $this->get_calc_fields(); |
franck@0
|
200 $calc = $this->view->views_calc_calculation; |
franck@0
|
201 $fields = $calc_fields[$calc]; |
franck@0
|
202 |
franck@0
|
203 // Empty out any fields that have been added to the query, |
franck@0
|
204 // we don't need them for the summary totals. |
franck@0
|
205 $this->view->query->fields = array(); |
franck@0
|
206 // Clear out any sorting and grouping, it can create unexpected results |
franck@0
|
207 // when Views adds aggregation values for the sorts. |
franck@0
|
208 $this->view->query->orderby = array(); |
franck@0
|
209 $this->view->query->groupby = array(); |
franck@0
|
210 |
franck@0
|
211 foreach ($this->view->field as $field) { |
franck@0
|
212 $query_field = substr($field->field, 0, 3) == 'cid' ? $field->definition['calc'] : $field->table .'.'. $field->field; |
franck@0
|
213 $query_alias = $field->field_alias; |
franck@2
|
214 // Bail if we have a broken handler. |
franck@2
|
215 if ($query_alias == 'unknown') { |
franck@2
|
216 continue; |
franck@2
|
217 } |
franck@0
|
218 $this->view->query->add_table($field->table, NULL, NULL, $field->table); |
franck@0
|
219 if (!empty($fields) && in_array($field->field, $fields)) { |
franck@0
|
220 // Calculated fields. |
franck@0
|
221 $this->view->query->add_field(NULL, "$calc($query_field)", $query_alias); |
franck@0
|
222 } |
franck@0
|
223 else { |
franck@0
|
224 // Empty fields that have no calculations. |
franck@0
|
225 $this->view->query->add_field(NULL, "MAX('')", $query_alias); |
franck@0
|
226 } |
franck@0
|
227 // Add a dummy field for the groupby. |
franck@0
|
228 $this->view->query->add_field(NULL, "MAX('". $calc ."')", "TOTAL_". $calc); |
franck@0
|
229 } |
franck@0
|
230 } |
franck@0
|
231 |
franck@0
|
232 function get_calc_fields() { |
franck@0
|
233 $options = $this->view->style_plugin->options; |
franck@0
|
234 $handler = $this->view->style_plugin; |
franck@0
|
235 $fields = $this->view->field; |
franck@0
|
236 $columns = $handler->sanitize_columns($options['columns'], $fields); |
franck@0
|
237 $calcs = array_keys(_views_calc_calc_options()); |
franck@0
|
238 |
franck@0
|
239 $calc_fields = array(); |
franck@0
|
240 foreach ($columns as $field => $column) { |
franck@0
|
241 if ($field == $column && empty($fields[$field]->options['exclude'])) { |
franck@0
|
242 if ($options['info'][$field]['has_calc']) { |
franck@0
|
243 foreach ($calcs as $calc) { |
franck@0
|
244 if (isset($this->options['info'][$field]['calc'][$calc])) { |
franck@0
|
245 $calc_fields[$calc][] = $field; |
franck@0
|
246 } |
franck@0
|
247 } |
franck@0
|
248 } |
franck@0
|
249 } |
franck@0
|
250 } |
franck@0
|
251 return $calc_fields; |
franck@0
|
252 } |
franck@0
|
253 } |