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