00001 <?php
00002
00020 class views_plugin_style extends views_plugin {
00024 var $row_tokens = array();
00034 function init(&$view, &$display, $options = NULL) {
00035 $this->view = &$view;
00036 $this->display = &$display;
00037
00038
00039 $this->unpack_options($this->options, isset($options) ? $options : $display->handler->get_option('style_options'));
00040
00041 if ($this->uses_row_plugin() && $display->handler->get_option('row_plugin')) {
00042 $this->row_plugin = $display->handler->get_plugin('row');
00043 }
00044
00045 $this->options += array(
00046 'grouping' => array(),
00047 );
00048
00049 $this->definition += array(
00050 'uses grouping' => TRUE,
00051 );
00052 }
00053
00054 function destroy() {
00055 parent::destroy();
00056
00057 if (isset($this->row_plugin)) {
00058 $this->row_plugin->destroy();
00059 }
00060 }
00061
00065 function uses_row_plugin() {
00066 return !empty($this->definition['uses row plugin']);
00067 }
00068
00072 function uses_row_class() {
00073 return !empty($this->definition['uses row class']);
00074 }
00075
00079 function uses_fields() {
00080
00081
00082 if ($this->uses_row_plugin() && !empty($this->row_plugin)) {
00083 return $this->row_plugin->uses_fields();
00084 }
00085
00086 return !empty($this->definition['uses fields']);
00087 }
00088
00094 function uses_tokens() {
00095 if ($this->uses_row_class()) {
00096 $class = $this->options['row_class'];
00097 if (strpos($class, '[') !== FALSE || strpos($class, '!') !== FALSE || strpos($class, '%') !== FALSE) {
00098 return TRUE;
00099 }
00100 }
00101 }
00102
00106 function get_row_class($row_index) {
00107 if ($this->uses_row_class()) {
00108 $class = $this->options['row_class'];
00109 if ($this->uses_fields() && $this->view->field) {
00110 $class = strip_tags($this->tokenize_value($class, $row_index));
00111 }
00112
00113 $classes = explode(' ', $class);
00114 foreach ($classes as &$class) {
00115 $class = drupal_clean_css_identifier($class);
00116 }
00117 return implode(' ', $classes);
00118 }
00119 }
00120
00124 function tokenize_value($value, $row_index) {
00125 if (strpos($value, '[') !== FALSE || strpos($value, '!') !== FALSE || strpos($value, '%') !== FALSE) {
00126 $fake_item = array(
00127 'alter_text' => TRUE,
00128 'text' => $value,
00129 );
00130
00131
00132 $tokens = isset($this->row_tokens[$row_index]) ? $this->row_tokens[$row_index] : array();
00133 if (!empty($this->view->build_info['substitutions'])) {
00134 $tokens += $this->view->build_info['substitutions'];
00135 }
00136
00137 if ($tokens) {
00138 $value = strtr($value, $tokens);
00139 }
00140 }
00141
00142 return $value;
00143 }
00144
00148 function even_empty() {
00149 return !empty($this->definition['even empty']);
00150 }
00151
00152 function option_definition() {
00153 $options = parent::option_definition();
00154 $options['grouping'] = array('default' => array());
00155 if ($this->uses_row_class()) {
00156 $options['row_class'] = array('default' => '');
00157 }
00158
00159 return $options;
00160 }
00161
00162 function options_form(&$form, &$form_state) {
00163 parent::options_form($form, $form_state);
00164
00165
00166
00167
00168 if ($this->uses_fields() && $this->definition['uses grouping']) {
00169 $options = array('' => t('- None -'));
00170 $field_labels = $this->display->handler->get_field_labels();
00171 $options += $field_labels;
00172
00173
00174 if (count($options) > 1) {
00175
00176 if (is_string($this->options['grouping'])) {
00177 $grouping = $this->options['grouping'];
00178 $this->options['grouping'] = array();
00179 $this->options['grouping'][0]['field'] = $grouping;
00180 }
00181 if (isset($this->options['group_rendered']) && is_string($this->options['group_rendered'])) {
00182 $this->options['grouping'][0]['rendered'] = $this->options['group_rendered'];
00183 unset($this->options['group_rendered']);
00184 }
00185
00186 $c = count($this->options['grouping']);
00187
00188 for ($i = 0; $i <= $c; $i++) {
00189 $grouping = !empty($this->options['grouping'][$i]) ? $this->options['grouping'][$i] : array();
00190 $grouping += array('field' => '', 'rendered' => TRUE, 'rendered_strip' => FALSE);
00191 $form['grouping'][$i]['field'] = array(
00192 '#type' => 'select',
00193 '#title' => t('Grouping field Nr.@number', array('@number' => $i + 1)),
00194 '#options' => $options,
00195 '#default_value' => $grouping['field'],
00196 '#description' => t('You may optionally specify a field by which to group the records. Leave blank to not group.'),
00197 );
00198 $form['grouping'][$i]['rendered'] = array(
00199 '#type' => 'checkbox',
00200 '#title' => t('Use rendered output to group rows'),
00201 '#default_value' => $grouping['rendered'],
00202 '#description' => t('If enabled the rendered output of the grouping field is used to group the rows.'),
00203 '#dependency' => array(
00204 'edit-style-options-grouping-' . $i . '-field' => array_keys($field_labels),
00205 )
00206 );
00207 $form['grouping'][$i]['rendered_strip'] = array(
00208 '#type' => 'checkbox',
00209 '#title' => t('Remove tags from rendered output'),
00210 '#default_value' => $grouping['rendered_strip'],
00211 '#dependency' => array(
00212 'edit-style-options-grouping-' . $i . '-field' => array_keys($field_labels),
00213 )
00214 );
00215 }
00216 }
00217 }
00218
00219 if ($this->uses_row_class()) {
00220 $form['row_class'] = array(
00221 '#title' => t('Row class'),
00222 '#description' => t('The class to provide on each row.'),
00223 '#type' => 'textfield',
00224 '#default_value' => $this->options['row_class'],
00225 );
00226
00227 if ($this->uses_fields()) {
00228 $form['row_class']['#description'] .= ' ' . t('You may use field tokens from as per the "Replacement patterns" used in "Rewrite the output of this field" for all fields.');
00229 }
00230 }
00231 }
00232
00233 function options_validate(&$form, &$form_state) {
00234
00235 if (isset($form_state['values']['style_options']['grouping'])) {
00236
00237 foreach ($form_state['values']['style_options']['grouping'] as $index => $grouping) {
00238 if (empty($grouping['field'])) {
00239 unset($form_state['values']['style_options']['grouping'][$index]);
00240 }
00241 }
00242 }
00243 }
00244
00250 function build_sort() { return TRUE; }
00251
00256 function build_sort_post() { }
00257
00264 function pre_render($result) {
00265 if (!empty($this->row_plugin)) {
00266 $this->row_plugin->pre_render($result);
00267 }
00268 }
00269
00273 function render() {
00274 if ($this->uses_row_plugin() && empty($this->row_plugin)) {
00275 debug('views_plugin_style_default: Missing row plugin');
00276 return;
00277 }
00278
00279
00280 $sets = $this->render_grouping(
00281 $this->view->result,
00282 $this->options['grouping'],
00283 TRUE
00284 );
00285
00286 return $this->render_grouping_sets($sets);
00287 }
00288
00303 function render_grouping_sets($sets, $level = 0) {
00304 $output = '';
00305 foreach ($sets as $set) {
00306 $row = reset($set['rows']);
00307
00308 if (is_array($row) && isset($row['group'])) {
00309 $output .= theme(views_theme_functions('views_view_grouping', $this->view, $this->display),
00310 array(
00311 'view' => $this->view,
00312 'grouping' => $this->options['grouping'][$level],
00313 'grouping_level' => $level,
00314 'rows' => $set['rows'],
00315 'title' => $set['group'])
00316 );
00317 }
00318
00319 else {
00320 if ($this->uses_row_plugin()) {
00321 foreach ($set['rows'] as $index => $row) {
00322 $this->view->row_index = $index;
00323 $set['rows'][$index] = $this->row_plugin->render($row);
00324 }
00325 }
00326
00327 $output .= theme($this->theme_functions(),
00328 array(
00329 'view' => $this->view,
00330 'options' => $this->options,
00331 'grouping_level' => $level,
00332 'rows' => $set['rows'],
00333 'title' => $set['group'])
00334 );
00335 }
00336 }
00337 unset($this->view->row_index);
00338 return $output;
00339 }
00340
00380 function render_grouping($records, $groupings = array(), $group_rendered = NULL) {
00381
00382
00383 if (is_string($groupings)) {
00384 $rendered = $group_rendered === NULL ? TRUE : $group_rendered;
00385 $groupings = array(array('field' => $groupings, 'rendered' => $rendered));
00386 }
00387
00388
00389 $this->render_fields($this->view->result);
00390 $sets = array();
00391 if ($groupings) {
00392 foreach ($records as $index => $row) {
00393
00394
00395
00396 $set = &$sets;
00397 foreach ($groupings as $info) {
00398 $field = $info['field'];
00399 $rendered = isset($info['rendered']) ? $info['rendered'] : $group_rendered;
00400 $rendered_strip = isset($info['rendered_strip']) ? $info['rendered_strip'] : FALSE;
00401 $grouping = '';
00402 $group_content = '';
00403
00404
00405
00406 if (isset($this->view->field[$field])) {
00407 $group_content = $this->get_field($index, $field);
00408 if ($this->view->field[$field]->options['label']) {
00409 $group_content = $this->view->field[$field]->options['label'] . ': ' . $group_content;
00410 }
00411 if ($rendered) {
00412 $grouping = $group_content;
00413 if ($rendered_strip) {
00414 $group_content = $grouping = strip_tags(htmlspecialchars_decode($group_content));
00415 }
00416 }
00417 else {
00418 $grouping = $this->get_field_value($index, $field);
00419
00420
00421 if (!is_scalar($grouping)) {
00422 $grouping = md5(serialize($grouping));
00423 }
00424 }
00425 }
00426
00427
00428 if (empty($set[$grouping])) {
00429 $set[$grouping]['group'] = $group_content;
00430 $set[$grouping]['rows'] = array();
00431 }
00432
00433
00434 $set = &$set[$grouping]['rows'];
00435 }
00436
00437 $set[$index] = $row;
00438 }
00439 }
00440 else {
00441
00442 $sets[''] = array(
00443 'group' => '',
00444 'rows' => $records,
00445 );
00446 }
00447
00448
00449
00450
00451 if ($group_rendered === NULL) {
00452 $old_style_sets = array();
00453 foreach ($sets as $group) {
00454 $old_style_sets[$group['group']] = $group['rows'];
00455 }
00456 $sets = $old_style_sets;
00457 }
00458
00459 return $sets;
00460 }
00461
00468 function render_fields($result) {
00469 if (!$this->uses_fields()) {
00470 return;
00471 }
00472
00473 if (!isset($this->rendered_fields)) {
00474 $this->rendered_fields = array();
00475 $this->view->row_index = 0;
00476 $keys = array_keys($this->view->field);
00477
00478
00479
00480 if (!empty($keys)) {
00481 foreach ($result as $count => $row) {
00482 $this->view->row_index = $count;
00483 foreach ($keys as $id) {
00484 $this->rendered_fields[$count][$id] = $this->view->field[$id]->theme($row);
00485 }
00486
00487 $this->row_tokens[$count] = $this->view->field[$id]->get_render_tokens(array());
00488 }
00489 }
00490 unset($this->view->row_index);
00491 }
00492
00493 return $this->rendered_fields;
00494 }
00495
00504 function get_field($index, $field) {
00505 if (!isset($this->rendered_fields)) {
00506 $this->render_fields($this->view->result);
00507 }
00508
00509 if (isset($this->rendered_fields[$index][$field])) {
00510 return $this->rendered_fields[$index][$field];
00511 }
00512 }
00513
00522 function get_field_value($index, $field) {
00523 $this->view->row_index = $index;
00524 $value = $this->view->field[$field]->get_value($this->view->result[$index]);
00525 unset($this->view->row_index);
00526 return $value;
00527 }
00528
00529 function validate() {
00530 $errors = parent::validate();
00531
00532 if ($this->uses_row_plugin()) {
00533 $plugin = $this->display->handler->get_plugin('row');
00534 if (empty($plugin)) {
00535 $errors[] = t('Style @style requires a row style but the row plugin is invalid.', array('@style' => $this->definition['title']));
00536 }
00537 else {
00538 $result = $plugin->validate();
00539 if (!empty($result) && is_array($result)) {
00540 $errors = array_merge($errors, $result);
00541 }
00542 }
00543 }
00544 return $errors;
00545 }
00546
00547 function query() {
00548 parent::query();
00549 if (isset($this->row_plugin)) {
00550 $this->row_plugin->query();
00551 }
00552 }
00553 }
00554