00001 <?php
00013 define('VIEWS_HANDLER_RENDER_TEXT_PHASE_SINGLE_ITEM', 0);
00014
00019 define('VIEWS_HANDLER_RENDER_TEXT_PHASE_COMPLETELY', 1);
00020
00024 define('VIEWS_HANDLER_RENDER_TEXT_PHASE_EMPTY', 2);
00025
00037 class views_handler_field extends views_handler {
00038 var $field_alias = 'unknown';
00039 var $aliases = array();
00040
00046 var $additional_fields = array();
00047
00051 function construct() {
00052 parent::construct();
00053
00054 $this->additional_fields = array();
00055 if (!empty($this->definition['additional fields'])) {
00056 $this->additional_fields = $this->definition['additional fields'];
00057 }
00058
00059 if (!isset($this->options['exclude'])) {
00060 $this->options['exclude'] = '';
00061 }
00062 }
00063
00070 function allow_advanced_render() {
00071 return TRUE;
00072 }
00073
00074 function init(&$view, &$options) {
00075 parent::init($view, $options);
00076 }
00077
00081 function query() {
00082 $this->ensure_my_table();
00083
00084 $params = $this->options['group_type'] != 'group' ? array('function' => $this->options['group_type']) : array();
00085 $this->field_alias = $this->query->add_field($this->table_alias, $this->real_field, NULL, $params);
00086
00087 $this->add_additional_fields();
00088 }
00089
00100 function add_additional_fields($fields = NULL) {
00101 if (!isset($fields)) {
00102
00103 if (empty($this->additional_fields)) {
00104 return;
00105 }
00106 $fields = $this->additional_fields;
00107 }
00108
00109 $group_params = array();
00110 if ($this->options['group_type'] != 'group') {
00111 $group_params = array(
00112 'function' => $this->options['group_type'],
00113 );
00114 }
00115
00116 if (!empty($fields) && is_array($fields)) {
00117 foreach ($fields as $identifier => $info) {
00118 if (is_array($info)) {
00119 if (isset($info['table'])) {
00120 $table_alias = $this->query->ensure_table($info['table'], $this->relationship);
00121 }
00122 else {
00123 $table_alias = $this->table_alias;
00124 }
00125
00126 if (empty($table_alias)) {
00127 debug(t('Handler @handler tried to add additional_field @identifier but @table could not be added!', array('@handler' => $this->definition['handler'], '@identifier' => $identifier, '@table' => $info['table'])));
00128 $this->aliases[$identifier] = 'broken';
00129 continue;
00130 }
00131
00132 $params = array();
00133 if (!empty($info['params'])) {
00134 $params = $info['params'];
00135 }
00136
00137 $params += $group_params;
00138 $this->aliases[$identifier] = $this->query->add_field($table_alias, $info['field'], NULL, $params);
00139 }
00140 else {
00141 $this->aliases[$info] = $this->query->add_field($this->table_alias, $info, NULL, $group_params);
00142 }
00143 }
00144 }
00145 }
00146
00150 function click_sort($order) {
00151 if (isset($this->field_alias)) {
00152
00153
00154 $params = $this->options['group_type'] != 'group' ? array('function' => $this->options['group_type']) : array();
00155 $this->query->add_orderby(NULL, NULL, $order, $this->field_alias, $params);
00156 }
00157 }
00158
00162 function click_sortable() {
00163 return !empty($this->definition['click sortable']);
00164 }
00165
00169 function label() {
00170 if (!isset($this->options['label'])) {
00171 return '';
00172 }
00173 return $this->options['label'];
00174 }
00175
00179 function element_type($none_supported = FALSE, $default_empty = FALSE, $inline = FALSE) {
00180 if ($none_supported) {
00181 if ($this->options['element_type'] === '0') {
00182 return '';
00183 }
00184 }
00185 if ($this->options['element_type']) {
00186 return check_plain($this->options['element_type']);
00187 }
00188
00189 if ($default_empty) {
00190 return '';
00191 }
00192
00193 if ($inline) {
00194 return 'span';
00195 }
00196
00197 if (isset($this->definition['element type'])) {
00198 return $this->definition['element type'];
00199 }
00200
00201 return 'span';
00202 }
00203
00207 function element_label_type($none_supported = FALSE, $default_empty = FALSE) {
00208 if ($none_supported) {
00209 if ($this->options['element_label_type'] === '0') {
00210 return '';
00211 }
00212 }
00213 if ($this->options['element_label_type']) {
00214 return check_plain($this->options['element_label_type']);
00215 }
00216
00217 if ($default_empty) {
00218 return '';
00219 }
00220
00221 return 'span';
00222 }
00223
00227 function element_wrapper_type($none_supported = FALSE, $default_empty = FALSE) {
00228 if ($none_supported) {
00229 if ($this->options['element_wrapper_type'] === '0') {
00230 return 0;
00231 }
00232 }
00233 if ($this->options['element_wrapper_type']) {
00234 return check_plain($this->options['element_wrapper_type']);
00235 }
00236
00237 if ($default_empty) {
00238 return '';
00239 }
00240
00241 return 'div';
00242 }
00243
00251 function get_elements() {
00252 static $elements = NULL;
00253 if (!isset($elements)) {
00254 $elements = variable_get('views_field_rewrite_elements', array(
00255 '' => t('- Use default -'),
00256 '0' => t('- None -'),
00257 'div' => 'DIV',
00258 'span' => 'SPAN',
00259 'h1' => 'H1',
00260 'h2' => 'H2',
00261 'h3' => 'H3',
00262 'h4' => 'H4',
00263 'h5' => 'H5',
00264 'h6' => 'H6',
00265 'p' => 'P',
00266 'strong' => 'STRONG',
00267 'em' => 'EM',
00268 ));
00269 }
00270
00271 return $elements;
00272 }
00273
00277 function element_classes($row_index = NULL) {
00278 $classes = explode(' ', $this->options['element_class']);
00279 foreach ($classes as &$class) {
00280 $class = $this->tokenize_value($class, $row_index);
00281 $class = views_clean_css_identifier($class);
00282 }
00283 return implode(' ', $classes);
00284 }
00285
00292 function tokenize_value($value, $row_index = NULL) {
00293 if (strpos($value, '[') !== FALSE || strpos($value, '!') !== FALSE || strpos($value, '%') !== FALSE) {
00294 $fake_item = array(
00295 'alter_text' => TRUE,
00296 'text' => $value,
00297 );
00298
00299
00300
00301 if (isset($row_index) && isset($this->view->style_plugin->render_tokens[$row_index])) {
00302 $tokens = $this->view->style_plugin->render_tokens[$row_index];
00303 }
00304 else {
00305
00306 $last_field = end($this->view->field);
00307 if (isset($last_field->last_tokens)) {
00308 $tokens = $last_field->last_tokens;
00309 }
00310 else {
00311 $tokens = $last_field->get_render_tokens($fake_item);
00312 }
00313 }
00314
00315 $value = strip_tags($this->render_altered($fake_item, $tokens));
00316 if (!empty($this->options['alter']['trim_whitespace'])) {
00317 $value = trim($value);
00318 }
00319 }
00320
00321 return $value;
00322 }
00323
00327 function element_label_classes($row_index = NULL) {
00328 $classes = explode(' ', $this->options['element_label_class']);
00329 foreach ($classes as &$class) {
00330 $class = $this->tokenize_value($class, $row_index);
00331 $class = views_clean_css_identifier($class);
00332 }
00333 return implode(' ', $classes);
00334 }
00335
00339 function element_wrapper_classes($row_index = NULL) {
00340 $classes = explode(' ', $this->options['element_wrapper_class']);
00341 foreach ($classes as &$class) {
00342 $class = $this->tokenize_value($class, $row_index);
00343 $class = views_clean_css_identifier($class);
00344 }
00345 return implode(' ', $classes);
00346 }
00347
00359 function get_value($values, $field = NULL) {
00360 $alias = isset($field) ? $this->aliases[$field] : $this->field_alias;
00361 if (isset($values->{$alias})) {
00362 return $values->{$alias};
00363 }
00364 }
00365
00366 function option_definition() {
00367 $options = parent::option_definition();
00368
00369 $options['label'] = array('default' => $this->definition['title'], 'translatable' => TRUE);
00370 $options['exclude'] = array('default' => FALSE, 'bool' => TRUE);
00371 $options['alter'] = array(
00372 'contains' => array(
00373 'alter_text' => array('default' => FALSE),
00374 'text' => array('default' => '', 'translatable' => TRUE),
00375 'make_link' => array('default' => FALSE),
00376 'path' => array('default' => '', 'translatable' => TRUE),
00377 'absolute' => array('default' => '', 'translatable' => FALSE),
00378 'external' => array('default' => '', 'translatable' => FALSE),
00379 'replace_spaces' => array('default' => '', 'translatable' => FALSE),
00380 'path_case' => array('default' => 'none', 'translatable' => FALSE),
00381 'trim_whitespace' => array('default' => FALSE),
00382 'alt' => array('default' => '', 'translatable' => TRUE),
00383 'rel' => array('default' => ''),
00384 'link_class' => array('default' => ''),
00385 'prefix' => array('default' => '', 'translatable' => TRUE),
00386 'suffix' => array('default' => '', 'translatable' => TRUE),
00387 'target' => array('default' => '', 'translatable' => TRUE),
00388 'nl2br' => array('default' => FALSE),
00389 'max_length' => array('default' => ''),
00390 'word_boundary' => array('default' => TRUE),
00391 'ellipsis' => array('default' => TRUE),
00392 'more_link' => array('default' => FALSE),
00393 'more_link_text' => array('default' => '', 'translatable' => TRUE),
00394 'more_link_path' => array('default' => ''),
00395 'strip_tags' => array('default' => FALSE),
00396 'trim' => array('default' => FALSE),
00397 'preserve_tags' => array('default' => ''),
00398 'html' => array('default' => FALSE),
00399 ),
00400 );
00401 $options['element_type'] = array('default' => '');
00402 $options['element_class'] = array('default' => '');
00403
00404 $options['element_label_type'] = array('default' => '');
00405 $options['element_label_class'] = array('default' => '');
00406 $options['element_label_colon'] = array('default' => TRUE);
00407
00408 $options['element_wrapper_type'] = array('default' => '');
00409 $options['element_wrapper_class'] = array('default' => '');
00410
00411 $options['element_default_classes'] = array('default' => TRUE);
00412
00413 $options['empty'] = array('default' => '', 'translatable' => TRUE);
00414 $options['hide_empty'] = array('default' => FALSE);
00415 $options['empty_zero'] = array('default' => FALSE);
00416 $options['hide_alter_empty'] = array('default' => TRUE);
00417
00418 return $options;
00419 }
00420
00424 function options_submit(&$form, &$form_state) {
00425 $options = &$form_state['values']['options'];
00426 $types = array('element_type', 'element_label_type', 'element_wrapper_type');
00427 $classes = array_combine(array('element_class', 'element_label_class', 'element_wrapper_class'), $types);
00428
00429 foreach ($types as $type) {
00430 if (!$options[$type . '_enable']) {
00431 $options[$type] = '';
00432 }
00433 }
00434
00435 foreach ($classes as $class => $type) {
00436 if (!$options[$class . '_enable'] || !$options[$type . '_enable']) {
00437 $options[$class] = '';
00438 }
00439 }
00440
00441 if (empty($options['custom_label'])) {
00442 $options['label'] = '';
00443 $options['element_label_colon'] = FALSE;
00444 }
00445 }
00446
00451 function options_form(&$form, &$form_state) {
00452 parent::options_form($form, $form_state);
00453
00454 $label = $this->label();
00455 $form['custom_label'] = array(
00456 '#type' => 'checkbox',
00457 '#title' => t('Create a label'),
00458 '#description' => t('Enable to create a label for this field.'),
00459 '#default_value' => $label !== '',
00460 '#weight' => -103,
00461 );
00462 $form['label'] = array(
00463 '#type' => 'textfield',
00464 '#title' => t('Label'),
00465 '#default_value' => $label,
00466 '#dependency' => array(
00467 'edit-options-custom-label' => array(1),
00468 ),
00469 '#weight' => -102,
00470 );
00471 $form['element_label_colon'] = array(
00472 '#type' => 'checkbox',
00473 '#title' => t('Place a colon after the label'),
00474 '#default_value' => $this->options['element_label_colon'],
00475 '#dependency' => array(
00476 'edit-options-custom-label' => array(1),
00477 ),
00478 '#weight' => -101,
00479 );
00480
00481 $form['exclude'] = array(
00482 '#type' => 'checkbox',
00483 '#title' => t('Exclude from display'),
00484 '#default_value' => $this->options['exclude'],
00485 '#description' => t('Enable to load this field as hidden. Often used to group fields, or to use as token in another field.'),
00486 '#weight' => -100,
00487 );
00488
00489 $form['style_settings'] = array(
00490 '#type' => 'fieldset',
00491 '#title' => t('Style settings'),
00492 '#collapsible' => TRUE,
00493 '#collapsed' => TRUE,
00494 '#weight' => 99,
00495 );
00496
00497 $form['element_type_enable'] = array(
00498 '#type' => 'checkbox',
00499 '#title' => t('Customize field HTML'),
00500 '#default_value' => !empty($this->options['element_type']) || (string) $this->options['element_type'] == '0' || !empty($this->options['element_class']) || (string) $this->options['element_class'] == '0',
00501 '#fieldset' => 'style_settings',
00502 );
00503 $form['element_type'] = array(
00504 '#title' => t('HTML element'),
00505 '#options' => $this->get_elements(),
00506 '#type' => 'select',
00507 '#default_value' => $this->options['element_type'],
00508 '#description' => t('Choose the HTML element to wrap around this field, e.g. H1, H2, etc.'),
00509 '#dependency' => array(
00510 'edit-options-element-type-enable' => array(1),
00511 ),
00512 '#fieldset' => 'style_settings',
00513 );
00514
00515 $form['element_class_enable'] = array(
00516 '#type' => 'checkbox',
00517 '#title' => t('Create a CSS class'),
00518 '#dependency' => array(
00519 'edit-options-element-type-enable' => array(1),
00520 ),
00521 '#default_value' => !empty($this->options['element_class']) || (string) $this->options['element_class'] == '0',
00522 '#fieldset' => 'style_settings',
00523 );
00524 $form['element_class'] = array(
00525 '#title' => t('CSS class'),
00526 '#description' => t('You may use token substitutions from the rewriting section in this class.'),
00527 '#type' => 'textfield',
00528 '#default_value' => $this->options['element_class'],
00529 '#dependency' => array(
00530 'edit-options-element-class-enable' => array(1),
00531 'edit-options-element-type-enable' => array(1),
00532 ),
00533 '#dependency_count' => 2,
00534 '#fieldset' => 'style_settings',
00535 );
00536
00537 $form['element_label_type_enable'] = array(
00538 '#type' => 'checkbox',
00539 '#title' => t('Customize label HTML'),
00540 '#default_value' => !empty($this->options['element_label_type']) || (string) $this->options['element_label_type'] == '0' || !empty($this->options['element_label_class']) || (string) $this->options['element_label_class'] == '0',
00541 '#fieldset' => 'style_settings',
00542 );
00543 $form['element_label_type'] = array(
00544 '#title' => t('Label HTML element'),
00545 '#options' => $this->get_elements(FALSE),
00546 '#type' => 'select',
00547 '#default_value' => $this->options['element_label_type'],
00548 '#description' => t('Choose the HTML element to wrap around this label, e.g. H1, H2, etc.'),
00549 '#dependency' => array(
00550 'edit-options-element-label-type-enable' => array(1),
00551 ),
00552 '#fieldset' => 'style_settings',
00553 );
00554 $form['element_label_class_enable'] = array(
00555 '#type' => 'checkbox',
00556 '#title' => t('Create a CSS class'),
00557 '#dependency' => array(
00558 'edit-options-element-label-type-enable' => array(1)
00559 ),
00560 '#default_value' => !empty($this->options['element_label_class']) || (string) $this->options['element_label_class'] == '0',
00561 '#fieldset' => 'style_settings',
00562 );
00563 $form['element_label_class'] = array(
00564 '#title' => t('CSS class'),
00565 '#description' => t('You may use token substitutions from the rewriting section in this class.'),
00566 '#type' => 'textfield',
00567 '#default_value' => $this->options['element_label_class'],
00568 '#dependency' => array(
00569 'edit-options-element-label-class-enable' => array(1),
00570 'edit-options-element-label-type-enable' => array(1),
00571 ),
00572 '#dependency_count' => 2,
00573 '#fieldset' => 'style_settings',
00574 );
00575
00576 $form['element_wrapper_type_enable'] = array(
00577 '#type' => 'checkbox',
00578 '#title' => t('Customize field and label wrapper HTML'),
00579 '#default_value' => !empty($this->options['element_wrapper_type']) || (string) $this->options['element_wrapper_type'] == '0' || !empty($this->options['element_wrapper_class']) || (string) $this->options['element_wrapper_class'] == '0',
00580 '#fieldset' => 'style_settings',
00581 );
00582 $form['element_wrapper_type'] = array(
00583 '#title' => t('Wrapper HTML element'),
00584 '#options' => $this->get_elements(FALSE),
00585 '#type' => 'select',
00586 '#default_value' => $this->options['element_wrapper_type'],
00587 '#description' => t('Choose the HTML element to wrap around this field and label, e.g. H1, H2, etc. This may not be used if the field and label are not rendered together, such as with a table.'),
00588 '#dependency' => array(
00589 'edit-options-element-wrapper-type-enable' => array(1),
00590 ),
00591 '#fieldset' => 'style_settings',
00592 );
00593
00594 $form['element_wrapper_class_enable'] = array(
00595 '#type' => 'checkbox',
00596 '#title' => t('Create a CSS class'),
00597 '#dependency' => array(
00598 'edit-options-element-wrapper-type-enable' => array(1),
00599 ),
00600 '#default_value' => !empty($this->options['element_wrapper_class']) || (string) $this->options['element_wrapper_class'] == '0',
00601 '#fieldset' => 'style_settings',
00602 );
00603 $form['element_wrapper_class'] = array(
00604 '#title' => t('CSS class'),
00605 '#description' => t('You may use token substitutions from the rewriting section in this class.'),
00606 '#type' => 'textfield',
00607 '#default_value' => $this->options['element_wrapper_class'],
00608 '#dependency' => array(
00609 'edit-options-element-wrapper-class-enable' => array(1),
00610 'edit-options-element-wrapper-type-enable' => array(1),
00611 ),
00612 '#dependency_count' => 2,
00613 '#fieldset' => 'style_settings',
00614 );
00615
00616 $form['element_default_classes'] = array(
00617 '#type' => 'checkbox',
00618 '#title' => t('Add default classes'),
00619 '#default_value' => $this->options['element_default_classes'],
00620 '#description' => t('Use default Views classes to identify the field, field label and field content.'),
00621 '#fieldset' => 'style_settings',
00622 );
00623
00624 $form['alter'] = array(
00625 '#title' => t('Rewrite results'),
00626 '#type' => 'fieldset',
00627 '#collapsible' => TRUE,
00628 '#collapsed' => TRUE,
00629 '#weight' => 100,
00630 );
00631
00632 if ($this->allow_advanced_render()) {
00633 $form['alter']['#tree'] = TRUE;
00634 $form['alter']['alter_text'] = array(
00635 '#type' => 'checkbox',
00636 '#title' => t('Rewrite the output of this field'),
00637 '#description' => t('Enable to override the output of this field with custom text or replacement tokens.'),
00638 '#default_value' => $this->options['alter']['alter_text'],
00639 );
00640
00641 $form['alter']['text'] = array(
00642 '#title' => t('Text'),
00643 '#type' => 'textarea',
00644 '#default_value' => $this->options['alter']['text'],
00645 '#description' => t('The text to display for this field. You may include HTML. You may enter data from this view as per the "Replacement patterns" below.'),
00646 '#dependency' => array(
00647 'edit-options-alter-alter-text' => array(1),
00648 ),
00649 );
00650
00651 $form['alter']['make_link'] = array(
00652 '#type' => 'checkbox',
00653 '#title' => t('Output this field as a link'),
00654 '#description' => t('If checked, this field will be made into a link. The destination must be given below.'),
00655 '#default_value' => $this->options['alter']['make_link'],
00656 );
00657 $form['alter']['path'] = array(
00658 '#title' => t('Link path'),
00659 '#type' => 'textfield',
00660 '#default_value' => $this->options['alter']['path'],
00661 '#description' => t('The Drupal path or absolute URL for this link. You may enter data from this view as per the "Replacement patterns" below.'),
00662 '#dependency' => array(
00663 'edit-options-alter-make-link' => array(1),
00664 ),
00665 '#maxlength' => 255,
00666 );
00667 $form['alter']['absolute'] = array(
00668 '#type' => 'checkbox',
00669 '#title' => t('Use absolute path'),
00670 '#default_value' => $this->options['alter']['absolute'],
00671 '#dependency' => array(
00672 'edit-options-alter-make-link' => array(1),
00673 ),
00674 );
00675 $form['alter']['replace_spaces'] = array(
00676 '#type' => 'checkbox',
00677 '#title' => t('Replace spaces with dashes'),
00678 '#default_value' => $this->options['alter']['replace_spaces'],
00679 '#dependency' => array(
00680 'edit-options-alter-make-link' => array(1)
00681 ),
00682 );
00683 $form['alter']['external'] = array(
00684 '#type' => 'checkbox',
00685 '#title' => t('External server URL'),
00686 '#default_value' => $this->options['alter']['external'],
00687 '#description' => t("Links to an external server using a full URL: e.g. 'http://www.example.com' or 'www.example.com'."),
00688 '#dependency' => array(
00689 'edit-options-alter-make-link' => array(1),
00690 ),
00691 );
00692 $form['alter']['path_case'] = array(
00693 '#type' => 'select',
00694 '#title' => t('Transform the case'),
00695 '#description' => t('When printing url paths, how to transform the case of the filter value.'),
00696 '#dependency' => array(
00697 'edit-options-alter-make-link' => array(1),
00698 ),
00699 '#options' => array(
00700 'none' => t('No transform'),
00701 'upper' => t('Upper case'),
00702 'lower' => t('Lower case'),
00703 'ucfirst' => t('Capitalize first letter'),
00704 'ucwords' => t('Capitalize each word'),
00705 ),
00706 '#default_value' => $this->options['alter']['path_case'],
00707 );
00708 $form['alter']['link_class'] = array(
00709 '#title' => t('Link class'),
00710 '#type' => 'textfield',
00711 '#default_value' => $this->options['alter']['link_class'],
00712 '#description' => t('The CSS class to apply to the link.'),
00713 '#dependency' => array(
00714 'edit-options-alter-make-link' => array(1),
00715 ),
00716 );
00717 $form['alter']['alt'] = array(
00718 '#title' => t('Title text'),
00719 '#type' => 'textfield',
00720 '#default_value' => $this->options['alter']['alt'],
00721 '#description' => t('Text to place as "title" text which most browsers display as a tooltip when hovering over the link.'),
00722 '#dependency' => array(
00723 'edit-options-alter-make-link' => array(1),
00724 ),
00725 );
00726 $form['alter']['rel'] = array(
00727 '#title' => t('Rel Text'),
00728 '#type' => 'textfield',
00729 '#default_value' => $this->options['alter']['rel'],
00730 '#description' => t('Include Rel attribute for use in lightbox2 or other javascript utility.'),
00731 '#dependency' => array(
00732 'edit-options-alter-make-link' => array(1),
00733 ),
00734 );
00735 $form['alter']['prefix'] = array(
00736 '#title' => t('Prefix text'),
00737 '#type' => 'textfield',
00738 '#default_value' => $this->options['alter']['prefix'],
00739 '#description' => t('Any text to display before this link. You may include HTML.'),
00740 '#dependency' => array(
00741 'edit-options-alter-make-link' => array(1),
00742 ),
00743 );
00744 $form['alter']['suffix'] = array(
00745 '#title' => t('Suffix text'),
00746 '#type' => 'textfield',
00747 '#default_value' => $this->options['alter']['suffix'],
00748 '#description' => t('Any text to display after this link. You may include HTML.'),
00749 '#dependency' => array(
00750 'edit-options-alter-make-link' => array(1),
00751 ),
00752 );
00753 $form['alter']['target'] = array(
00754 '#title' => t('Target'),
00755 '#type' => 'textfield',
00756 '#default_value' => $this->options['alter']['target'],
00757 '#description' => t("Target of the link, such as _blank, _parent or an iframe's name. This field is rarely used."),
00758 '#dependency' => array(
00759 'edit-options-alter-make-link' => array(1),
00760 ),
00761 );
00762
00763
00764
00765 $options = array();
00766 foreach ($this->view->display_handler->get_handlers('field') as $field => $handler) {
00767 $options[t('Fields')]["[$field]"] = $handler->ui_name();
00768
00769 if ($field == $this->options['id']) {
00770 break;
00771 }
00772 }
00773 $count = 0;
00774 foreach ($this->view->display_handler->get_handlers('argument') as $arg => $handler) {
00775 $options[t('Arguments')]['%' . ++$count] = t('@argument title', array('@argument' => $handler->ui_name()));
00776 $options[t('Arguments')]['!' . $count] = t('@argument input', array('@argument' => $handler->ui_name()));
00777 }
00778
00779 $this->document_self_tokens($options[t('Fields')]);
00780
00781
00782 $output = t('<p>You must add some additional fields to this display before using this field. These fields may be marked as <em>Exclude from display</em> if you prefer. Note that due to rendering order, you cannot use fields that come after this field; if you need a field not listed here, rearrange your fields.</p>');
00783
00784 if (!empty($options)) {
00785 $output = t('<p>The following tokens are available for this field. Note that due to rendering order, you cannot use fields that come after this field; if you need a field not listed here, rearrange your fields.
00786 If you would like to have the characters %5B and %5D please use the html entity codes \'%5B\' or \'%5D\' or they will get replaced with empty space.</p>');
00787 foreach (array_keys($options) as $type) {
00788 if (!empty($options[$type])) {
00789 $items = array();
00790 foreach ($options[$type] as $key => $value) {
00791 $items[] = $key . ' == ' . $value;
00792 }
00793 $output .= theme('item_list',
00794 array(
00795 'items' => $items,
00796 'type' => $type
00797 ));
00798 }
00799 }
00800 }
00801
00802
00803
00804
00805 $form['alter']['help'] = array(
00806 '#type' => 'fieldset',
00807 '#title' => t('Replacement patterns'),
00808 '#collapsible' => TRUE,
00809 '#collapsed' => TRUE,
00810 '#value' => $output,
00811 '#dependency' => array(
00812 'edit-options-alter-make-link' => array(1),
00813 'edit-options-alter-alter-text' => array(1),
00814 'edit-options-alter-more-link' => array(1),
00815 ),
00816 );
00817
00818 $form['alter']['trim'] = array(
00819 '#type' => 'checkbox',
00820 '#title' => t('Trim this field to a maximum length'),
00821 '#description' => t('Enable to trim the field to a maximum length of characters'),
00822 '#default_value' => $this->options['alter']['trim'],
00823 );
00824
00825 $form['alter']['max_length'] = array(
00826 '#title' => t('Maximum length'),
00827 '#type' => 'textfield',
00828 '#default_value' => $this->options['alter']['max_length'],
00829 '#description' => t('The maximum number of characters this field can be.'),
00830 '#dependency' => array(
00831 'edit-options-alter-trim' => array(1),
00832 ),
00833 );
00834
00835 $form['alter']['word_boundary'] = array(
00836 '#type' => 'checkbox',
00837 '#title' => t('Trim only on a word boundary'),
00838 '#description' => t('If checked, this field be trimmed only on a word boundary. This is guaranteed to be the maximum characters stated or less. If there are no word boundaries this could trim a field to nothing.'),
00839 '#default_value' => $this->options['alter']['word_boundary'],
00840 '#dependency' => array(
00841 'edit-options-alter-trim' => array(1),
00842 ),
00843 );
00844
00845 $form['alter']['ellipsis'] = array(
00846 '#type' => 'checkbox',
00847 '#title' => t('Add an ellipsis'),
00848 '#description' => t('If checked, a "..." will be added if a field was trimmed.'),
00849 '#default_value' => $this->options['alter']['ellipsis'],
00850 '#dependency' => array(
00851 'edit-options-alter-trim' => array(1),
00852 ),
00853 );
00854
00855 $form['alter']['more_link'] = array(
00856 '#type' => 'checkbox',
00857 '#title' => t('Add a read-more link if output is trimmed.'),
00858 '#description' => t('If checked, a read-more link will be added at the end of the trimmed output'),
00859 '#default_value' => $this->options['alter']['more_link'],
00860 '#dependency' => array(
00861 'edit-options-alter-trim' => array(1),
00862 ),
00863 );
00864
00865 $form['alter']['more_link_text'] = array(
00866 '#type' => 'textfield',
00867 '#title' => t('More link text'),
00868 '#default_value' => $this->options['alter']['more_link_text'],
00869 '#description' => t('The text which will be displayed on the more link. You may enter data from this view as per the "Replacement patterns" above.'),
00870 '#dependency_count' => 2,
00871 '#dependency' => array(
00872 'edit-options-alter-trim' => array(1),
00873 'edit-options-alter-more-link' => array(1),
00874 ),
00875 );
00876 $form['alter']['more_link_path'] = array(
00877 '#type' => 'textfield',
00878 '#title' => t('More link path'),
00879 '#default_value' => $this->options['alter']['more_link_path'],
00880 '#description' => t('The path which is used for the more link. You may enter data from this view as per the "Replacement patterns" above.'),
00881 '#dependency_count' => 2,
00882 '#dependency' => array(
00883 'edit-options-alter-trim' => array(1),
00884 'edit-options-alter-more-link' => array(1),
00885 ),
00886 );
00887
00888 $form['alter']['html'] = array(
00889 '#type' => 'checkbox',
00890 '#title' => t('Field can contain HTML'),
00891 '#description' => t('If checked, HTML corrector will be run to ensure tags are properly closed after trimming.'),
00892 '#default_value' => $this->options['alter']['html'],
00893 '#dependency' => array(
00894 'edit-options-alter-trim' => array(1),
00895 ),
00896 );
00897
00898 $form['alter']['strip_tags'] = array(
00899 '#type' => 'checkbox',
00900 '#title' => t('Strip HTML tags'),
00901 '#description' => t('If checked, all HTML tags will be stripped.'),
00902 '#default_value' => $this->options['alter']['strip_tags'],
00903 );
00904
00905 $form['alter']['preserve_tags'] = array(
00906 '#type' => 'textfield',
00907 '#title' => t('Preserve certain tags'),
00908 '#description' => t('List the tags that need to be preserved during the stripping process. example "<p> <br>" which will preserve all p and br elements'),
00909 '#default_value' => $this->options['alter']['preserve_tags'],
00910 '#dependency' => array(
00911 'edit-options-alter-strip-tags' => array(1),
00912 ),
00913 );
00914
00915 $form['alter']['trim_whitespace'] = array(
00916 '#type' => 'checkbox',
00917 '#title' => t('Remove whitespace'),
00918 '#description' => t('If checked, all whitespaces at the beginning and the end of the output will be removed.'),
00919 '#default_value' => $this->options['alter']['trim_whitespace'],
00920 );
00921
00922 $form['alter']['nl2br'] = array(
00923 '#type' => 'checkbox',
00924 '#title' => t('Convert newlines to HTML <br> tags'),
00925 '#description' => t('If checked, all newlines chars (e.g. \n) are converted into HTML <br> tags.'),
00926 '#default_value' => $this->options['alter']['nl2br'],
00927 );
00928 }
00929
00930 $form['empty_field_behavior'] = array(
00931 '#type' => 'fieldset',
00932 '#title' => t('No results behavior'),
00933 '#collapsible' => TRUE,
00934 '#collapsed' => TRUE,
00935 '#weight' => 100,
00936 );
00937
00938 $form['empty'] = array(
00939 '#type' => 'textarea',
00940 '#title' => t('No results text'),
00941 '#default_value' => $this->options['empty'],
00942 '#description' => t('Provide text to display if this field returns no results. You may include HTML. You may enter data from this view as per the "Replacement patterns" in the "Rewrite Results" section below.'),
00943 '#fieldset' => 'empty_field_behavior',
00944 );
00945
00946 $form['empty_zero'] = array(
00947 '#type' => 'checkbox',
00948 '#title' => t('Count the number 0 as empty'),
00949 '#default_value' => $this->options['empty_zero'],
00950 '#description' => t('Enable to display the "no results text" if the field contains the number 0.'),
00951 '#fieldset' => 'empty_field_behavior',
00952 );
00953
00954 $form['hide_empty'] = array(
00955 '#type' => 'checkbox',
00956 '#title' => t('Hide if empty'),
00957 '#default_value' => $this->options['hide_empty'],
00958 '#description' => t('Enable to hide this field if it is empty. Note that the field label or rewritten output may still be displayed. To hide labels, check the style or row style settings for empty fields. To hide rewritten content, check the "Hide rewriting if empty" checkbox.'),
00959 '#fieldset' => 'empty_field_behavior',
00960 );
00961
00962 $form['hide_alter_empty'] = array(
00963 '#type' => 'checkbox',
00964 '#title' => t('Hide rewriting if empty'),
00965 '#default_value' => $this->options['hide_alter_empty'],
00966 '#description' => t('Do not display rewritten content if this field is empty.'),
00967 '#fieldset' => 'empty_field_behavior',
00968 );
00969 }
00970
00974 function admin_summary() {
00975 return $this->label();
00976 }
00977
00987 function pre_render(&$values) { }
00988
00995 function render($values) {
00996 $value = $this->get_value($values);
00997 return $this->sanitize_value($value);
00998 }
00999
01006 function advanced_render($values) {
01007 if ($this->allow_advanced_render() && method_exists($this, 'render_item')) {
01008 $raw_items = $this->get_items($values);
01009 }
01010 else {
01011 $value = $this->render($values);
01012 if (is_array($value)) {
01013 $value = drupal_render($value);
01014 }
01015 $this->last_render = $value;
01016 $this->original_value = $value;
01017 }
01018
01019 if ($this->allow_advanced_render()) {
01020 $tokens = NULL;
01021 if (method_exists($this, 'render_item')) {
01022 $items = array();
01023 foreach ($raw_items as $count => $item) {
01024 $value = $this->render_item($count, $item);
01025 if (is_array($value)) {
01026 $value = drupal_render($value);
01027 }
01028 $this->last_render = $value;
01029 $this->original_value = $this->last_render;
01030
01031 $alter = $item + $this->options['alter'];
01032 $alter['phase'] = VIEWS_HANDLER_RENDER_TEXT_PHASE_SINGLE_ITEM;
01033 $items[] = $this->render_text($alter);
01034 }
01035
01036 $value = $this->render_items($items);
01037 }
01038 else {
01039 $alter = array('phase' => VIEWS_HANDLER_RENDER_TEXT_PHASE_COMPLETELY) + $this->options['alter'];
01040 $value = $this->render_text($alter);
01041 }
01042
01043 if (is_array($value)) {
01044 $value = drupal_render($value);
01045 }
01046
01047
01048 $this->last_render = $value;
01049 }
01050
01051 if (empty($this->last_render)) {
01052 if (($this->last_render !== 0 && $this->last_render !== '0') || !empty($this->options['empty_zero'])) {
01053 $alter = $this->options['alter'];
01054 $alter['alter_text'] = 1;
01055 $alter['text'] = $this->options['empty'];
01056 $alter['phase'] = VIEWS_HANDLER_RENDER_TEXT_PHASE_EMPTY;
01057 $this->last_render = $this->render_text($alter);
01058 }
01059 }
01060
01061 return $this->last_render;
01062 }
01063
01070 function render_text($alter) {
01071 $value = $this->last_render;
01072
01073 if (!empty($alter['alter_text']) && $alter['text'] !== '') {
01074 $tokens = $this->get_render_tokens($alter);
01075 $value = $this->render_altered($alter, $tokens);
01076 }
01077
01078 if (!empty($this->options['alter']['trim_whitespace'])) {
01079 $value = trim($value);
01080 }
01081
01082
01083 $no_rewrite_for_empty = $this->options['hide_alter_empty'] && empty($this->original_value);
01084
01085
01086
01087
01088 if ((($this->options['hide_empty'] && empty($value))
01089 || ($alter['phase'] != VIEWS_HANDLER_RENDER_TEXT_PHASE_EMPTY && $no_rewrite_for_empty))
01090 && (($value !== 0 && $value !== '0')
01091 || $this->options['empty_zero'])) {
01092 return '';
01093 }
01094
01095 if ($alter['phase'] == VIEWS_HANDLER_RENDER_TEXT_PHASE_EMPTY && $no_rewrite_for_empty) {
01096
01097
01098 return $value;
01099 }
01100
01101 if (!empty($alter['strip_tags'])) {
01102 $value = strip_tags($value, $alter['preserve_tags']);
01103 }
01104
01105 $suffix = '';
01106 if (!empty($alter['trim']) && !empty($alter['max_length'])) {
01107 $length = strlen($value);
01108 $value = $this->render_trim_text($alter, $value);
01109 if ($this->options['alter']['more_link'] && strlen($value) < $length) {
01110 $tokens = $this->get_render_tokens($alter);
01111 $more_link_text = $this->options['alter']['more_link_text'] ? $this->options['alter']['more_link_text'] : t('more');
01112 $more_link_text = strtr(filter_xss_admin($more_link_text), $tokens);
01113 $more_link_path = $this->options['alter']['more_link_path'];
01114 $more_link_path = strip_tags(decode_entities(strtr($more_link_path, $tokens)));
01115
01116
01117 $base_path = base_path();
01118
01119 if (strpos($more_link_path, $base_path) === 0) {
01120 $more_link_path = drupal_substr($more_link_path, drupal_strlen($base_path));
01121 }
01122
01123 $more_link = l($more_link_text, $more_link_path);
01124
01125 $suffix .= " " . $more_link;
01126 }
01127 }
01128
01129 if (!empty($alter['nl2br'])) {
01130 $value = nl2br($value);
01131 }
01132 $this->last_render_text = $value;
01133
01134 if (!empty($alter['make_link']) && !empty($alter['path'])) {
01135 if (!isset($tokens)) {
01136 $tokens = $this->get_render_tokens($alter);
01137 }
01138 $value = $this->render_as_link($alter, $value, $tokens);
01139 }
01140
01141 return $value . $suffix;
01142 }
01143
01147 function render_altered($alter, $tokens) {
01148
01149 $value = filter_xss_admin($alter['text']);
01150 $value = strtr($value, $tokens);
01151
01152 return $value;
01153 }
01154
01158 function render_trim_text($alter, $value) {
01159 if (!empty($alter['strip_tags'])) {
01160
01161
01162
01163 $this->definition['element type'] = 'span';
01164 }
01165 return views_trim_text($alter, $value);
01166 }
01167
01172 function render_as_link($alter, $text, $tokens) {
01173 $value = '';
01174
01175 if (!empty($alter['prefix'])) {
01176 $value .= filter_xss_admin(strtr($alter['prefix'], $tokens));
01177 }
01178
01179 $options = array(
01180 'html' => TRUE,
01181 'absolute' => !empty($alter['absolute']) ? TRUE : FALSE,
01182 );
01183
01184
01185
01186 $path = $alter['path'];
01187
01188
01189 if ($path != '<front>') {
01190
01191
01192
01193 $path = strip_tags(decode_entities(strtr($path, $tokens)));
01194
01195 if (!empty($alter['path_case']) && $alter['path_case'] != 'none') {
01196 $path = $this->case_transform($path, $this->options['alter']['path_case']);
01197 }
01198
01199 if (!empty($alter['replace_spaces'])) {
01200 $path = str_replace(' ', '-', $path);
01201 }
01202 }
01203
01204
01205 $url = parse_url($path);
01206
01207
01208 if (empty($url)) {
01209 return $text;
01210 }
01211
01212
01213
01214
01215 if (empty($url['path']) && empty($url['host']) && empty($url['fragment'])) {
01216 return $text;
01217 }
01218
01219
01220
01221
01222 if ($alter['external']){
01223 if (!isset($url['scheme'])) {
01224
01225 $path = "http://$path";
01226
01227 $url = parse_url($path);
01228 }
01229 }
01230
01231 if (isset($url['query'])) {
01232 $path = strtr($path, array('?' . $url['query'] => ''));
01233 $options['query'] = drupal_get_query_array($url['query']);
01234 }
01235 if (isset($url['fragment'])) {
01236 $path = strtr($path, array('#' . $url['fragment'] => ''));
01237
01238 if ($path == '') {
01239 $options['external'] = TRUE;
01240 }
01241 $options['fragment'] = $url['fragment'];
01242 }
01243
01244 $alt = strtr($alter['alt'], $tokens);
01245
01246 if ($alt && $alt != $text) {
01247 $options['attributes']['title'] = decode_entities($alt);
01248 }
01249
01250 $class = strtr($alter['link_class'], $tokens);
01251 if ($class) {
01252 $options['attributes']['class'] = array($class);
01253 }
01254
01255 if (!empty($alter['rel']) && $rel = strtr($alter['rel'], $tokens)) {
01256 $options['attributes']['rel'] = $rel;
01257 }
01258
01259 $target = check_plain(trim(strtr($alter['target'],$tokens)));
01260 if (!empty($target)) {
01261 $options['attributes']['target'] = $target;
01262 }
01263
01264
01265
01266 if (isset($alter['link_attributes']) && is_array($alter['link_attributes'])) {
01267 foreach ($alter['link_attributes'] as $key => $attribute) {
01268 if (!isset($options['attributes'][$key])) {
01269 $options['attributes'][$key] = strtr($attribute, $tokens);
01270 }
01271 }
01272 }
01273
01274
01275
01276 if (isset($alter['query'])) {
01277
01278
01279 $options['query'] = drupal_http_build_query($alter['query']);
01280 $options['query'] = strtr($options['query'], $tokens);
01281 $options['query'] = drupal_get_query_array($options['query']);
01282 }
01283 if (isset($alter['alias'])) {
01284
01285 $options['alias'] = $alter['alias'];
01286 }
01287 if (isset($alter['fragment'])) {
01288 $options['fragment'] = strtr($alter['fragment'], $tokens);
01289 }
01290 if (isset($alter['language'])) {
01291 $options['language'] = $alter['language'];
01292 }
01293
01294
01295 if (isset($alter['entity'])) {
01296 $options['entity'] = $alter['entity'];
01297 }
01298 if (isset($alter['entity_type'])) {
01299 $options['entity_type'] = $alter['entity_type'];
01300 }
01301
01302 $value .= l($text, $path, $options);
01303
01304 if (!empty($alter['suffix'])) {
01305 $value .= filter_xss_admin(strtr($alter['suffix'], $tokens));
01306 }
01307
01308 return $value;
01309 }
01310
01318 function get_render_tokens($item) {
01319 $tokens = array();
01320 if (!empty($this->view->build_info['substitutions'])) {
01321 $tokens = $this->view->build_info['substitutions'];
01322 }
01323 $count = 0;
01324 foreach ($this->view->display_handler->get_handlers('argument') as $arg => $handler) {
01325 $token = '%' . ++$count;
01326 if (!isset($tokens[$token])) {
01327 $tokens[$token] = '';
01328 }
01329
01330
01331
01332
01333 $tokens['!' . $count] = isset($this->view->args[$count - 1]) ? strip_tags(decode_entities($this->view->args[$count - 1])) : '';
01334 }
01335
01336
01337 foreach ($this->view->display_handler->get_handlers('field') as $field => $handler) {
01338 if (isset($handler->last_render)) {
01339 $tokens["[$field]"] = $handler->last_render;
01340 }
01341 else {
01342 $tokens["[$field]"] = '';
01343 }
01344 if (!empty($item)) {
01345 $this->add_self_tokens($tokens, $item);
01346 }
01347
01348
01349 if ($field == $this->options['id']) {
01350 break;
01351 }
01352 }
01353
01354
01355 $this->view->style_plugin->render_tokens[$this->view->row_index] = $tokens;
01356 $this->last_tokens = $tokens;
01357 return $tokens;
01358 }
01359
01371 function add_self_tokens(&$tokens, $item) { }
01372
01378 function document_self_tokens(&$tokens) { }
01379
01384 function theme($values) {
01385 return theme($this->theme_functions(),
01386 array(
01387 'view' => $this->view,
01388 'field' => $this,
01389 'row' => $values
01390 ));
01391 }
01392
01393 function theme_functions() {
01394 $themes = array();
01395 $hook = 'views_view_field';
01396
01397 $display = $this->view->display[$this->view->current_display];
01398
01399 if (!empty($display)) {
01400 $themes[] = $hook . '__' . $this->view->name . '__' . $display->id . '__' . $this->options['id'];
01401 $themes[] = $hook . '__' . $this->view->name . '__' . $display->id;
01402 $themes[] = $hook . '__' . $display->id . '__' . $this->options['id'];
01403 $themes[] = $hook . '__' . $display->id;
01404 if ($display->id != $display->display_plugin) {
01405 $themes[] = $hook . '__' . $this->view->name . '__' . $display->display_plugin . '__' . $this->options['id'];
01406 $themes[] = $hook . '__' . $this->view->name . '__' . $display->display_plugin;
01407 $themes[] = $hook . '__' . $display->display_plugin . '__' . $this->options['id'];
01408 $themes[] = $hook . '__' . $display->display_plugin;
01409 }
01410 }
01411 $themes[] = $hook . '__' . $this->view->name . '__' . $this->options['id'];
01412 $themes[] = $hook . '__' . $this->view->name;
01413 $themes[] = $hook . '__' . $this->options['id'];
01414 $themes[] = $hook;
01415
01416 return $themes;
01417 }
01418
01419 function ui_name($short = FALSE) {
01420 return $this->get_field(parent::ui_name($short));
01421 }
01422 }
01423
01429 class views_handler_field_broken extends views_handler_field {
01430 function ui_name($short = FALSE) {
01431 return t('Broken/missing handler');
01432 }
01433
01434 function ensure_my_table() { }
01435 function query($group_by = FALSE) { }
01436 function options_form(&$form, &$form_state) {
01437 $form['markup'] = array(
01438 '#markup' => '<div class="form-item description">' . t('The handler for this item is broken or missing and cannot be used. If a module provided the handler and was disabled, re-enabling the module may restore it. Otherwise, you should probably delete this item.') . '</div>',
01439 );
01440 }
01441
01445 function broken() { return TRUE; }
01446 }
01447
01453 class views_handler_field_file_size extends views_handler_field {
01454 function option_definition() {
01455 $options = parent::option_definition();
01456
01457 $options['file_size_display'] = array('default' => 'formatted');
01458
01459 return $options;
01460 }
01461
01462 function options_form(&$form, &$form_state) {
01463 parent::options_form($form, $form_state);
01464 $form['file_size_display'] = array(
01465 '#title' => t('File size display'),
01466 '#type' => 'select',
01467 '#options' => array(
01468 'formatted' => t('Formatted (in KB or MB)'),
01469 'bytes' => t('Raw bytes'),
01470 ),
01471 );
01472 }
01473
01474 function render($values) {
01475 $value = $this->get_value($values);
01476 if ($value) {
01477 switch ($this->options['file_size_display']) {
01478 case 'bytes':
01479 return $value;
01480 case 'formatted':
01481 default:
01482 return format_size($value);
01483 }
01484 }
01485 else {
01486 return '';
01487 }
01488 }
01489 }
01490
01496 class views_handler_field_xss extends views_handler_field {
01497 function render($values) {
01498 $value = $this->get_value($values);
01499 return $this->sanitize_value($value, 'xss');
01500 }
01501 }
01502