• Main Page
  • Related Pages
  • Modules
  • Classes
  • Files
  • File List
  • File Members

modules/field/views_handler_field_field.inc

00001 <?php
00002 
00008 function _field_view_formatter_options($field_type = NULL) {
00009   $options = &drupal_static(__FUNCTION__);
00010 
00011   if (!isset($options)) {
00012     $field_types = field_info_field_types();
00013     $options = array();
00014     foreach (field_info_formatter_types() as $name => $formatter) {
00015       foreach ($formatter['field types'] as $formatter_field_type) {
00016         // Check that the field type exists.
00017         if (isset($field_types[$formatter_field_type])) {
00018           $options[$formatter_field_type][$name] = $formatter['label'];
00019         }
00020       }
00021     }
00022   }
00023 
00024   if ($field_type) {
00025     return !empty($options[$field_type]) ? $options[$field_type] : array();
00026   }
00027   return $options;
00028 }
00029 
00033 class views_handler_field_field extends views_handler_field {
00037   public $items = array();
00038 
00042   public $field_info = array();
00043 
00044   function init(&$view, &$options) {
00045     parent::init($view, $options);
00046 
00047     $this->field_info = $field = field_info_field($this->definition['field_name']);
00048     $this->multiple = FALSE;
00049     $this->limit_values = FALSE;
00050 
00051     if ($field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED) {
00052       $this->multiple = TRUE;
00053 
00054       // If "Display all values in the same row" is FALSE, then we always limit
00055       // in order to show a single unique value per row.
00056       if (!$this->options['group_rows']) {
00057         $this->limit_values = TRUE;
00058       }
00059 
00060       // If "First and last only" is chosen, limit the values
00061       if (!empty($this->options['delta_first_last'])) {
00062         $this->limit_values = TRUE;
00063       }
00064 
00065       // Otherwise, we only limit values if the user hasn't selected "all", 0, or
00066       // the value matching field cardinality.
00067       if ((intval($this->options['delta_limit']) && ($this->options['delta_limit'] != $field['cardinality'])) || intval($this->options['delta_offset'])) {
00068         $this->limit_values = TRUE;
00069       }
00070     }
00071   }
00072 
00076   function access() {
00077     $base_table = $this->get_base_table();
00078     return field_access('view', $this->field_info, $this->definition['entity_tables'][$base_table]);
00079   }
00080 
00084   function get_base_table() {
00085     if (!isset($this->base_table)) {
00086       // This base_table is coming from the entity not the field.
00087       $this->base_table = $this->view->base_table;
00088 
00089       // If the current field is under a relationship you can't be sure that the
00090       // base table of the view is the base table of the current field.
00091       // For example a field from a node author on a node view does have users as base table.
00092       if (!empty($this->options['relationship']) && $this->options['relationship'] != 'none') {
00093         $relationships = $this->view->display_handler->get_option('relationships');
00094         if (!empty($relationships[$this->options['relationship']])) {
00095           $options = $relationships[$this->options['relationship']];
00096           $data = views_fetch_data($options['table']);
00097           $this->base_table = $data[$options['field']]['relationship']['base'];
00098         }
00099       }
00100     }
00101 
00102     return $this->base_table;
00103   }
00104 
00116   function query($use_groupby = FALSE) {
00117     $this->get_base_table();
00118 
00119     $params = array();
00120     if ($use_groupby) {
00121       // When grouping on a "field API" field (whose "real_field" is set to
00122       // entity_id), retrieve the minimum entity_id to have a valid entity_id to
00123       // pass to field_view_field().
00124       $params = array(
00125         'function' => 'min',
00126       );
00127 
00128       $this->ensure_my_table();
00129     }
00130 
00131     // Get the entity type according to the base table of the field.
00132     // Then add it to the query as a formula. That way we can avoid joining
00133     // the field table if all we need is entity_id and entity_type.
00134     $entity_type = $this->definition['entity_tables'][$this->base_table];
00135     $entity_info = entity_get_info($entity_type);
00136 
00137     if (isset($this->relationship)) {
00138       $this->base_table_alias = $this->relationship;
00139     }
00140     else {
00141       $this->base_table_alias = $this->base_table;
00142     }
00143 
00144     // We always need the base field (entity_id / revision_id).
00145     if (empty($this->definition['is revision'])) {
00146       $this->field_alias = $this->query->add_field($this->base_table_alias, $entity_info['entity keys']['id'], '', $params);
00147     }
00148     else {
00149       $this->field_alias = $this->query->add_field($this->base_table_alias, $entity_info['entity keys']['revision'], '', $params);
00150       $this->aliases['entity_id'] = $this->query->add_field($this->base_table_alias, $entity_info['entity keys']['id'], '', $params);
00151     }
00152 
00153 
00154     // The alias needs to be unique, so we use both the field table and the entity type.
00155     $entity_type_alias = $this->definition['table'] . '_' . $entity_type . '_entity_type';
00156     $this->aliases['entity_type'] = $this->query->add_field(NULL, "'$entity_type'", $entity_type_alias);
00157 
00158     $fields = $this->additional_fields;
00159     // We've already added entity_type, so we can remove it from the list.
00160     $entity_type_key = array_search('entity_type', $fields);
00161     if ($entity_type_key !== FALSE) {
00162       unset($fields[$entity_type_key]);
00163     }
00164 
00165     if ($use_groupby) {
00166       // Add the fields that we're actually grouping on.
00167       $options = array();
00168 
00169       if ($this->options['group_column'] != 'entity_id') {
00170         $options = array($this->options['group_column'] => $this->options['group_column']);
00171       }
00172 
00173       $options += $this->options['group_columns'];
00174 
00175 
00176       $fields = array();
00177       $rkey = $this->definition['is revision'] ? 'FIELD_LOAD_REVISION' : 'FIELD_LOAD_CURRENT';
00178       // Go through the list and determine the actual column name from field api.
00179       foreach ($options as $column) {
00180         $name = $column;
00181         if (isset($this->field_info['storage']['details']['sql'][$rkey][$this->table][$column])) {
00182           $name = $this->field_info['storage']['details']['sql'][$rkey][$this->table][$column];
00183         }
00184 
00185         $fields[$column] = $name;
00186       }
00187 
00188       $this->group_fields = $fields;
00189     }
00190 
00191     // Add additional fields (and the table join itself) if needed.
00192     if ($this->add_field_table($use_groupby)) {
00193       $this->ensure_my_table();
00194       $this->add_additional_fields($fields);
00195 
00196       // Filter by language, if field translation is enabled.
00197       $field = $this->field_info;
00198       if (field_is_translatable($entity_type, $field) && !empty($this->view->display_handler->options['field_language_add_to_query'])) {
00199         $column = $this->table_alias . '.language';
00200         // By the same reason as field_language the field might be LANGUAGE_NONE in reality so allow it as well.
00201         // @see this::field_language()
00202         global $language_content;
00203         $default_language = language_default('language');
00204         $language = str_replace(array('***CURRENT_LANGUAGE***', '***DEFAULT_LANGUAGE***'),
00205                                 array($language_content->language, $default_language),
00206                                 $this->view->display_handler->options['field_language']);
00207         $placeholder = $this->placeholder();
00208         $language_fallback_candidates = array($language);
00209         if (variable_get('locale_field_language_fallback', TRUE) && module_exists('locale')) {
00210           $language_fallback_candidates = array_merge($language_fallback_candidates, language_fallback_get_candidates());
00211         }
00212         else {
00213           $language_fallback_candidates[] = LANGUAGE_NONE;
00214         }
00215         $this->query->add_where_expression(0, "$column IN($placeholder) OR $column IS NULL", array($placeholder => $language_fallback_candidates));
00216       }
00217     }
00218 
00219     // The revision id inhibits grouping.
00220     // So, stop here if we're using grouping, or if aren't adding all columns to
00221     // the query.
00222     if ($use_groupby || empty($this->definition['add fields to query'])) {
00223       return;
00224     }
00225 
00226     $this->add_additional_fields(array('revision_id'));
00227   }
00228 
00232   function add_field_table($use_groupby) {
00233     // Grouping is enabled, or we are explicitly required to do this.
00234     if ($use_groupby || !empty($this->definition['add fields to query'])) {
00235       return TRUE;
00236     }
00237     // This a multiple value field, but "group multiple values" is not checked.
00238     if ($this->multiple && !$this->options['group_rows']) {
00239       return TRUE;
00240     }
00241     return FALSE;
00242   }
00243 
00247   function click_sortable() {
00248     // Not click sortable in any case.
00249     if (empty($this->definition['click sortable'])) {
00250       return FALSE;
00251     }
00252     // A field is not click sortable if it's a multiple field with
00253     // "group multiple values" checked, since a click sort in that case would
00254     // add a join to the field table, which would produce unwanted duplicates.
00255     if ($this->multiple && $this->options['group_rows']) {
00256       return FALSE;
00257     }
00258     return TRUE;
00259   }
00260 
00264   function click_sort($order) {
00265     // No column selected, can't continue.
00266     if (empty($this->options['click_sort_column'])) {
00267       return;
00268     }
00269 
00270     $this->ensure_my_table();
00271     $column = _field_sql_storage_columnname($this->definition['field_name'], $this->options['click_sort_column']);
00272     if (!isset($this->aliases[$column])) {
00273       // Column is not in query; add a sort on it (without adding the column).
00274       $this->aliases[$column] = $this->table_alias . '.' . $column;
00275     }
00276     $this->query->add_orderby(NULL, NULL, $order, $this->aliases[$column]);
00277   }
00278 
00279   function option_definition() {
00280     $options = parent::option_definition();
00281 
00282     // option_definition runs before init/construct, so no $this->field_info
00283     $field = field_info_field($this->definition['field_name']);
00284     $field_type = field_info_field_types($field['type']);
00285     $column_names = array_keys($field['columns']);
00286     $default_column = '';
00287     // Try to determine a sensible default.
00288     if (count($column_names) == 1) {
00289       $default_column = $column_names[0];
00290     }
00291     elseif (in_array('value', $column_names)) {
00292       $default_column = 'value';
00293     }
00294 
00295     // If the field has a "value" column, we probably need that one.
00296     $options['click_sort_column'] = array(
00297       'default' => $default_column,
00298     );
00299     $options['type'] = array(
00300       'default' => $field_type['default_formatter'],
00301     );
00302     $options['settings'] = array(
00303       'default' => array(),
00304     );
00305     $options['group_column'] = array(
00306       'default' => $default_column,
00307     );
00308     $options['group_columns'] = array(
00309       'default' => array(),
00310     );
00311 
00312     // Options used for multiple value fields.
00313     $options['group_rows'] = array(
00314       'default' => TRUE,
00315     );
00316     // If we know the exact number of allowed values, then that can be
00317     // the default. Otherwise, default to 'all'.
00318     $options['delta_limit'] = array(
00319       'default' => ($field['cardinality'] > 1) ? $field['cardinality'] : 'all',
00320     );
00321     $options['delta_offset'] = array(
00322       'default' => 0,
00323     );
00324     $options['delta_reversed'] = array(
00325       'default' => FALSE,
00326     );
00327     $options['delta_first_last'] = array(
00328       'default' => FALSE,
00329     );
00330 
00331     $options['multi_type'] = array(
00332       'default' => 'separator'
00333     );
00334     $options['separator'] = array(
00335       'default' => ', '
00336     );
00337 
00338     $options['field_api_classes'] = array(
00339       'default' => FALSE,
00340     );
00341 
00342     return $options;
00343   }
00344 
00345   function options_form(&$form, &$form_state) {
00346     parent::options_form($form, $form_state);
00347 
00348     $field = $this->field_info;
00349     $formatters = _field_view_formatter_options($field['type']);
00350     $column_names = array_keys($field['columns']);
00351 
00352     // If this is a multiple value field, add its options.
00353     if ($this->multiple) {
00354       $this->multiple_options_form($form, $form_state);
00355     }
00356 
00357     // No need to ask the user anything if the field has only one column.
00358     if (count($field['columns']) == 1) {
00359       $form['click_sort_column'] = array(
00360         '#type' => 'value',
00361         '#value' => isset($column_names[0]) ? $column_names[0] : '',
00362       );
00363     }
00364     else {
00365       $form['click_sort_column'] = array(
00366         '#type' => 'select',
00367         '#title' => t('Click sort column'),
00368         '#options' => drupal_map_assoc($column_names),
00369         '#default_value' => $this->options['click_sort_column'],
00370         '#description' => t('Used by Style: Table to determine the actual column to click sort the field on. The default is usually fine.'),
00371         '#fieldset' => 'more',
00372       );
00373     }
00374 
00375     $form['type'] = array(
00376       '#type' => 'select',
00377       '#title' => t('Formatter'),
00378       '#options' => $formatters,
00379       '#default_value' => $this->options['type'],
00380       '#ajax' => array(
00381         'path' => views_ui_build_form_url($form_state),
00382       ),
00383       '#submit' => array('views_ui_config_item_form_submit_temporary'),
00384       '#executes_submit_callback' => TRUE,
00385     );
00386 
00387     $form['field_api_classes'] = array(
00388       '#title' => t('Use field template'),
00389       '#type' => 'checkbox',
00390       '#default_value' => $this->options['field_api_classes'],
00391       '#description' => t('If checked, field api classes will be added using field.tpl.php (or equivalent). This is not recommended unless your CSS depends upon these classes. If not checked, template will not be used.'),
00392       '#fieldset' => 'style_settings',
00393       '#weight' => 20,
00394     );
00395 
00396     if ($this->multiple) {
00397       $form['field_api_classes']['#description'] .= ' ' . t('Checking this option will cause the group Display Type and Separator values to be ignored.');
00398     }
00399 
00400     // Get the currently selected formatter.
00401     $format = $this->options['type'];
00402 
00403     $formatter = field_info_formatter_types($format);
00404     $settings = $this->options['settings'] + field_info_formatter_settings($format);
00405 
00406     // Provide an instance array for hook_field_formatter_settings_form().
00407     ctools_include('fields');
00408     $instance = ctools_fields_fake_field_instance($this->definition['field_name'], '_dummy', $formatter, $settings);
00409 
00410     // Store the settings in a '_dummy' view mode.
00411     $instance['display']['_dummy'] = array(
00412       'type' => $format,
00413       'settings' => $settings,
00414     );
00415 
00416     // Get the settings form.
00417     $settings_form = array('#value' => array());
00418     $function = $formatter['module'] . '_field_formatter_settings_form';
00419     if (function_exists($function)) {
00420       $settings_form = $function($field, $instance, '_dummy', $form, $form_state);
00421     }
00422     $form['settings'] = $settings_form;
00423   }
00424 
00428   function multiple_options_form(&$form, &$form_state) {
00429     $field = $this->field_info;
00430 
00431     $form['multiple_field_settings'] = array(
00432       '#type' => 'fieldset',
00433       '#title' => t('Multiple field settings'),
00434       '#collapsible' => TRUE,
00435       '#collapsed' => TRUE,
00436       '#weight' => 5,
00437     );
00438 
00439     $form['group_rows'] = array(
00440       '#title' => t('Display all values in the same row'),
00441       '#type' => 'checkbox',
00442       '#default_value' => $this->options['group_rows'],
00443       '#description' => t('If checked, multiple values for this field will be shown in the same row. If not checked, each value in this field will create a new row. If using group by, please make sure to group by "Entity ID" for this setting to have any effect.'),
00444       '#fieldset' => 'multiple_field_settings',
00445     );
00446 
00447     // Make the string translatable by keeping it as a whole rather than
00448     // translating prefix and suffix separately.
00449     list($prefix, $suffix) = explode('@count', t('Display @count value(s)'));
00450 
00451     if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED) {
00452       $type = 'textfield';
00453       $options = NULL;
00454       $size = 5;
00455     }
00456     else {
00457       $type = 'select';
00458       $options = drupal_map_assoc(range(1, $field['cardinality']));
00459       $size = 1;
00460     }
00461     $form['multi_type'] = array(
00462       '#type' => 'radios',
00463       '#title' => t('Display type'),
00464       '#options' => array(
00465         'ul' => t('Unordered list'),
00466         'ol' => t('Ordered list'),
00467         'separator' => t('Simple separator'),
00468       ),
00469       '#dependency' => array('edit-options-group-rows' => array(TRUE)),
00470       '#default_value' => $this->options['multi_type'],
00471       '#fieldset' => 'multiple_field_settings',
00472     );
00473 
00474     $form['separator'] = array(
00475       '#type' => 'textfield',
00476       '#title' => t('Separator'),
00477       '#default_value' => $this->options['separator'],
00478       '#dependency' => array(
00479         'radio:options[multi_type]' => array('separator'),
00480         'edit-options-group-rows' => array(TRUE),
00481       ),
00482       '#dependency_count' => 2,
00483       '#fieldset' => 'multiple_field_settings',
00484     );
00485 
00486     $form['delta_limit'] = array(
00487       '#type' => $type,
00488       '#size' => $size,
00489       '#field_prefix' => $prefix,
00490       '#field_suffix' => $suffix,
00491       '#options' => $options,
00492       '#default_value' => $this->options['delta_limit'],
00493       '#prefix' => '<div class="container-inline">',
00494       '#dependency' => array('edit-options-group-rows' => array(TRUE)),
00495       '#fieldset' => 'multiple_field_settings',
00496     );
00497 
00498     list($prefix, $suffix) = explode('@count', t('starting from @count'));
00499     $form['delta_offset'] = array(
00500       '#type' => 'textfield',
00501       '#size' => 5,
00502       '#field_prefix' => $prefix,
00503       '#field_suffix' => $suffix,
00504       '#default_value' => $this->options['delta_offset'],
00505       '#dependency' => array('edit-options-group-rows' => array(TRUE)),
00506       '#description' => t('(first item is 0)'),
00507       '#fieldset' => 'multiple_field_settings',
00508     );
00509     $form['delta_reversed'] = array(
00510       '#title' => t('Reversed'),
00511       '#type' => 'checkbox',
00512       '#default_value' => $this->options['delta_reversed'],
00513       '#suffix' => $suffix,
00514       '#dependency' => array('edit-options-group-rows' => array(TRUE)),
00515       '#description' => t('(start from last values)'),
00516       '#fieldset' => 'multiple_field_settings',
00517     );
00518     $form['delta_first_last'] = array(
00519       '#title' => t('First and last only'),
00520       '#type' => 'checkbox',
00521       '#default_value' => $this->options['delta_first_last'],
00522       '#suffix' => '</div>',
00523       '#dependency' => array('edit-options-group-rows' => array(TRUE)),
00524       '#fieldset' => 'multiple_field_settings',
00525     );
00526   }
00527 
00531   function groupby_form(&$form, &$form_state) {
00532     parent::groupby_form($form, $form_state);
00533     // With "field API" fields, the column target of the grouping function
00534     // and any additional grouping columns must be specified.
00535     $group_columns = array(
00536       'entity_id' => t('Entity ID'),
00537     ) + drupal_map_assoc(array_keys($this->field_info['columns']), 'ucfirst');
00538 
00539     $form['group_column'] = array(
00540       '#type' => 'select',
00541       '#title' => t('Group column'),
00542       '#default_value' => $this->options['group_column'],
00543       '#description' => t('Select the column of this field to apply the grouping function selected above.'),
00544       '#options' => $group_columns,
00545     );
00546 
00547     $options = drupal_map_assoc(array('bundle', 'language', 'entity_type'), 'ucfirst');
00548 
00549     // Add on defined fields, noting that they're prefixed with the field name.
00550     $form['group_columns'] = array(
00551       '#type' => 'checkboxes',
00552       '#title' => t('Group columns (additional)'),
00553       '#default_value' => $this->options['group_columns'],
00554       '#description' => t('Select any additional columns of this field to include in the query and to group on.'),
00555       '#options' => $options + $group_columns,
00556     );
00557   }
00558 
00559   function groupby_form_submit(&$form, &$form_state) {
00560     parent::groupby_form_submit($form, $form_state);
00561     $item =& $form_state['handler']->options;
00562 
00563     // Add settings for "field API" fields.
00564     $item['group_column'] = $form_state['values']['options']['group_column'];
00565     $item['group_columns'] = array_filter($form_state['values']['options']['group_columns']);
00566   }
00567 
00571   function post_execute(&$values) {
00572     if (!empty($values)) {
00573       // Divide the entity ids by entity type, so they can be loaded in bulk.
00574       $entities_by_type = array();
00575       $revisions_by_type = array();
00576       foreach ($values as $key => $object) {
00577         if (isset($object->{$this->field_alias}) && !isset($values[$key]->_field_data[$this->field_alias])) {
00578           $entity_type = $object->{$this->aliases['entity_type']};
00579           if (empty($this->definition['is revision'])) {
00580             $entity_id = $object->{$this->field_alias};
00581             $entities_by_type[$entity_type][$key] = $entity_id;
00582           }
00583           else {
00584             $revision_id = $object->{$this->field_alias};
00585             $entity_id = $object->{$this->aliases['entity_id']};
00586             $entities_by_type[$entity_type][$key] = array($entity_id, $revision_id);
00587           }
00588         }
00589       }
00590 
00591       // Load the entities.
00592       foreach ($entities_by_type as $entity_type => $entity_ids) {
00593         $entity_info = entity_get_info($entity_type);
00594         if (empty($this->definition['is revision'])) {
00595           $entities = entity_load($entity_type, $entity_ids);
00596           $keys = $entity_ids;
00597         }
00598         else {
00599           // Revisions can't be loaded multiple, so we have to load them
00600           // one by one.
00601           $entities = array();
00602           $keys = array();
00603           foreach ($entity_ids as $key => $combined) {
00604             list($entity_id, $revision_id) = $combined;
00605             $entity = entity_load($entity_type, array($entity_id), array($entity_info['entity keys']['revision'] => $revision_id));
00606             if ($entity) {
00607               $entities[$revision_id] = array_shift($entity);
00608               $keys[$key] = $revision_id;
00609             }
00610           }
00611         }
00612 
00613         foreach ($keys as $key => $entity_id) {
00614           // If this is a revision, load the revision instead.
00615           if (isset($entities[$entity_id])) {
00616             $values[$key]->_field_data[$this->field_alias] = array(
00617               'entity_type' => $entity_type,
00618               'entity' => $entities[$entity_id],
00619             );
00620           }
00621         }
00622       }
00623 
00624       // Now, transfer the data back into the resultset so it can be easily used.
00625       foreach ($values as $row_id => &$value) {
00626         $value->{'field_' . $this->options['id']} = $this->set_items($value, $row_id);
00627       }
00628     }
00629   }
00630 
00637   function render_items($items) {
00638     if (!empty($items)) {
00639       if (!$this->options['group_rows']) {
00640         return implode('', $items);
00641       }
00642 
00643       if ($this->options['multi_type'] == 'separator') {
00644         return implode(filter_xss_admin($this->options['separator']), $items);
00645       }
00646       else {
00647         return theme('item_list',
00648           array(
00649             'items' => $items,
00650             'title' => NULL,
00651             'type' => $this->options['multi_type']
00652           ));
00653       }
00654     }
00655   }
00656 
00657   function get_items($values) {
00658     return $values->{'field_' . $this->options['id']};
00659   }
00660 
00661   function get_value($values, $field = NULL) {
00662     // Go ahead and render and store in $this->items.
00663     $entity = clone $values->_field_data[$this->field_alias]['entity'];
00664 
00665     $entity_type = $values->_field_data[$this->field_alias]['entity_type'];
00666     $langcode = $this->field_language($entity_type, $entity);
00667     // If we are grouping, copy our group fields into the cloned entity.
00668     // It's possible this will cause some weirdness, but there's only
00669     // so much we can hope to do.
00670     if (!empty($this->group_fields)) {
00671       // first, test to see if we have a base value.
00672       $base_value = array();
00673       // Note: We would copy original values here, but it can cause problems.
00674       // For example, text fields store cached filtered values as
00675       // 'safe_value' which doesn't appear anywhere in the field definition
00676       // so we can't affect it. Other side effects could happen similarly.
00677       $data = FALSE;
00678       foreach ($this->group_fields as $field_name => $column) {
00679         if (property_exists($values, $this->aliases[$column])) {
00680           $base_value[$field_name] = $values->{$this->aliases[$column]};
00681           if (isset($base_value[$field_name])) {
00682             $data = TRUE;
00683           }
00684         }
00685       }
00686 
00687       // If any of our aggregated fields have data, fake it:
00688       if ($data) {
00689         // Now, overwrite the original value with our aggregated value.
00690         // This overwrites it so there is always just one entry.
00691         $entity->{$this->definition['field_name']}[$langcode] = array($base_value);
00692       }
00693       else {
00694         $entity->{$this->definition['field_name']}[$langcode] = array();
00695       }
00696     }
00697 
00698     // The field we are trying to display doesn't exist on this entity.
00699     if (!isset($entity->{$this->definition['field_name']})) {
00700       return array();
00701     }
00702 
00703     // We are supposed to show only certain deltas.
00704     if ($this->limit_values && !empty($entity->{$this->definition['field_name']})) {
00705       $all_values = !empty($entity->{$this->definition['field_name']}[$langcode]) ? $entity->{$this->definition['field_name']}[$langcode] : array();
00706       if ($this->options['delta_reversed']) {
00707         $all_values = array_reverse($all_values);
00708       }
00709 
00710       // Offset is calculated differently when row grouping for a field is
00711       // not enabled. Since there are multiple rows, the delta needs to be
00712       // taken into account, so that different values are shown per row.
00713       if (!$this->options['group_rows'] && isset($this->aliases['delta']) && isset($values->{$this->aliases['delta']})) {
00714         $delta_limit = 1;
00715         $offset = $values->{$this->aliases['delta']};
00716       }
00717       // Single fields don't have a delta available so choose 0.
00718       elseif (!$this->options['group_rows'] && !$this->multiple) {
00719         $delta_limit = 1;
00720         $offset = 0;
00721       }
00722       else {
00723         $delta_limit = $this->options['delta_limit'];
00724         $offset = intval($this->options['delta_offset']);
00725 
00726         // We should only get here in this case if there's an offset, and
00727         // in that case we're limiting to all values after the offset.
00728         if ($delta_limit == 'all') {
00729           $delta_limit = count($all_values) - $offset;
00730         }
00731       }
00732 
00733       // Determine if only the first and last values should be shown
00734       $delta_first_last = $this->options['delta_first_last'];
00735 
00736       $new_values = array();
00737       for ($i = 0; $i < $delta_limit; $i++) {
00738         $new_delta = $offset + $i;
00739 
00740         if (isset($all_values[$new_delta])) {
00741           // If first-last option was selected, only use the first and last values
00742           if (!$delta_first_last
00743             // Use the first value.
00744             || $new_delta == $offset
00745             // Use the last value.
00746             || $new_delta == ($delta_limit + $offset - 1)) {
00747             $new_values[] = $all_values[$new_delta];
00748           }
00749         }
00750       }
00751       $entity->{$this->definition['field_name']}[$langcode] = $new_values;
00752     }
00753 
00754     if ($field == 'entity') {
00755       return $entity;
00756     }
00757     else {
00758       return !empty($entity->{$this->definition['field_name']}[$langcode]) ? $entity->{$this->definition['field_name']}[$langcode] : array();
00759     }
00760   }
00761 
00765   function set_items($values, $row_id) {
00766     if (empty($values->_field_data[$this->field_alias]) || empty($values->_field_data[$this->field_alias]['entity'])) {
00767       return array();
00768     }
00769 
00770     $display = array(
00771       'type' => $this->options['type'],
00772       'settings' => $this->options['settings'],
00773       'label' => 'hidden',
00774       // Pass the View object in the display so that fields can act on it.
00775       'views_view' => $this->view,
00776       'views_field' => $this,
00777       'views_row_id' => $row_id,
00778     );
00779 
00780 
00781     $entity_type = $values->_field_data[$this->field_alias]['entity_type'];
00782     $entity = $this->get_value($values, 'entity');
00783     if (!$entity) {
00784       return array();
00785     }
00786 
00787     $langcode = $this->field_language($entity_type, $entity);
00788     $render_array = field_view_field($entity_type, $entity, $this->definition['field_name'], $display, $langcode);
00789 
00790     $items = array();
00791     if ($this->options['field_api_classes']) {
00792       // Make a copy.
00793       $array = $render_array;
00794       return array(array('rendered' => drupal_render($render_array)));
00795     }
00796 
00797     foreach (element_children($render_array) as $count) {
00798       $items[$count]['rendered'] = $render_array[$count];
00799       // field_view_field() adds an #access property to the render array that
00800       // determines whether or not the current user is allowed to view the
00801       // field in the context of the current entity. We need to respect this
00802       // parameter when we pull out the children of the field array for
00803       // rendering.
00804       if (isset($render_array['#access'])) {
00805         $items[$count]['rendered']['#access'] = $render_array['#access'];
00806       }
00807       // Only add the raw field items (for use in tokens) if the curent user
00808       // has access to view the field content.
00809       if ((!isset($items[$count]['rendered']['#access']) || $items[$count]['rendered']['#access']) && !empty($render_array['#items'][$count])) {
00810         $items[$count]['raw'] = $render_array['#items'][$count];
00811       }
00812     }
00813     return $items;
00814   }
00815 
00816   function render_item($count, $item) {
00817     return render($item['rendered']);
00818   }
00819 
00820   function document_self_tokens(&$tokens) {
00821     $field = $this->field_info;
00822     foreach ($field['columns'] as $id => $column) {
00823       $tokens['[' . $this->options['id'] . '-' . $id . ']'] = t('Raw @column', array('@column' => $id));
00824     }
00825   }
00826 
00827   function add_self_tokens(&$tokens, $item) {
00828     $field = $this->field_info;
00829     foreach ($field['columns'] as $id => $column) {
00830       // Use filter_xss_admin because it's user data and we can't be sure it is safe.
00831       // We know nothing about the data, though, so we can't really do much else.
00832 
00833       if (isset($item['raw'])) {
00834         // If $item['raw'] is an array then we can use as is, if it's an object
00835         // we cast it to an array, if it's neither, we can't use it.
00836         $raw = is_array($item['raw']) ? $item['raw'] :
00837                (is_object($item['raw']) ? (array)$item['raw'] : NULL);
00838       }
00839       if (isset($raw) && isset($raw[$id]) && is_scalar($raw[$id])) {
00840         $tokens['[' . $this->options['id'] . '-' . $id . ']'] = filter_xss_admin($raw[$id]);
00841       }
00842       else {
00843         // Take sure that empty values are replaced as well.
00844         $tokens['[' . $this->options['id'] . '-' . $id . ']'] = '';
00845       }
00846     }
00847   }
00848 
00853   function field_language($entity_type, $entity) {
00854     global $language_content;
00855 
00856     if (field_is_translatable($entity_type, $this->field_info)) {
00857       $default_language = language_default('language');
00858       $language = str_replace(array('***CURRENT_LANGUAGE***', '***DEFAULT_LANGUAGE***'),
00859                               array($language_content->language, $default_language),
00860                               $this->view->display_handler->options['field_language']);
00861 
00862       // Give the Field Language API a chance to fallback to a different language
00863       // (or LANGUAGE_NONE), in case the field has no data for the selected language.
00864       // field_view_field() does this as well, but since the returned language code
00865       // is used before calling it, the fallback needs to happen explicitly.
00866       $language = field_language($entity_type, $entity, $this->field_info['field_name'], $language);
00867 
00868       return $language;
00869     }
00870     else {
00871       return LANGUAGE_NONE;
00872     }
00873   }
00874 }

Generated on Sun Feb 26 2012 12:52:51 for Views by  doxygen 1.7.1