chado_views_handler_field.inc 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. <?php
  2. // We need to include the views_handler_field_field file since it
  3. // includes _field_view_formatter_options() which we need.
  4. require_once drupal_get_path('module', 'views') . '/modules/field/views_handler_field_field.inc';
  5. /**
  6. * Views Field Handler for chado fields.
  7. * Uses the same approach as the field api views_handler_field_field.
  8. */
  9. class chado_views_handler_field extends views_handler_field {
  10. /**
  11. * Alter the views query to provide information for this field.
  12. *
  13. * We are going to take the same approach as the field api and simply load
  14. * the entities in order to get the values of the chado fields. The hope is
  15. * that a small number of cached simple queries will be more efficient than
  16. * the crazy joins that occur when using chado. *fingers crossed*
  17. */
  18. function query($use_groupby = FALSE) {
  19. $this->base_table = $this->definition['entity_table'];
  20. $this->base_table_alias = $this->base_table;
  21. $this->ensure_my_table();
  22. // Because we are just loading entities, we need the entity id and type only.
  23. $this->entity = $entity_info = entity_get_info($this->definition['entity_type']);
  24. $alias_stub = 'chado_field_' . $this->definition['chado_table'] . '_' . $this->definition['chado_field'];
  25. $this->id_alias = $this->field_alias = $this->query->add_field($this->base_table_alias, $entity_info['entity keys']['id'], $alias_stub . '_entity_id');
  26. $this->type_alias = $this->query->add_field(NULL, "'" . $this->definition['entity_type'] . "'", $alias_stub . '_entity_type');
  27. }
  28. /**
  29. * Load the entities for all fields that are about to be displayed.
  30. *
  31. * Notice that, although we load the entities for each chado field,
  32. * Drupal caches entities to ensure we don't get a performance hit per field,
  33. * just per row.
  34. */
  35. function post_execute(&$values) {
  36. if (!empty($values) AND isset($this->id_alias) AND isset($this->type_alias)) {
  37. // Foreach row in the view we want to grab the appropriate entity_id/type.
  38. $entity_ids = [];
  39. $keys = [];
  40. foreach ($values as $key => $object) {
  41. // Only load the entity if we can access the entity_id.
  42. if (isset($this->id_alias) AND isset($object->{$this->id_alias})) {
  43. $entity_ids[$object->{$this->type_alias}][] = $object->{$this->id_alias};
  44. $keys[$key] = $object->{$this->id_alias};
  45. }
  46. }
  47. // Now load the entities.
  48. foreach ($entity_ids as $type => $ids) {
  49. $entities[$type] = entity_load($type, $ids);
  50. }
  51. // Finally add the loaded entities and values back into the resultset for easy access.
  52. foreach ($keys as $row_id => $entity_id) {
  53. // First set the entities.
  54. foreach ($entities as $type => $objects) {
  55. $values[$row_id]->_chado_field_data[$type] = [
  56. 'entity_type' => $type,
  57. 'entity' => $objects[$entity_id],
  58. ];
  59. }
  60. // Then set the value of this field.
  61. $values[$row_id]->{$this->field_alias} = $this->render_field($objects[$entity_id], $this->definition['field_name'], $row_id);
  62. }
  63. }
  64. }
  65. /**
  66. * Render the field for display in the view.
  67. *
  68. * @param TripalEntity $entity
  69. * The entity containing the field to be rendered.
  70. * @param string $field_name
  71. * The name of the field to render.
  72. * @param integer $row_id
  73. * The id of the row this field will be displayed in.
  74. *
  75. * @return string
  76. * The rendered field.
  77. */
  78. function render_field($entity, $field_name, $row_id) {
  79. $display = [
  80. 'type' => $this->options['type'],
  81. 'settings' => (isset($this->options['settings'])) ? $this->options['settings'] : [],
  82. 'label' => 'hidden',
  83. // Pass the View object in the display so that fields can act on it.
  84. 'views_view' => $this->view,
  85. 'views_field' => $this,
  86. 'views_row_id' => $row_id,
  87. ];
  88. $langcode = LANGUAGE_NONE;
  89. $items = field_get_items($entity->type, $entity, $field_name);
  90. if (count($items) == 1) {
  91. $render_array = field_view_value($entity->type, $entity, $field_name, $items[0], $display, $langcode);
  92. }
  93. // @todo: handle fields with multiple values.
  94. else {
  95. $render_array = field_view_value($entity->type, $entity, $field_name, $items[0], $display, $langcode);
  96. drupal_set_message('Tripal Chado currently only supports views integration for single value fields. The first value has been shown.', 'warning');
  97. }
  98. return $render_array;
  99. }
  100. /**
  101. * @{inheritdoc}
  102. */
  103. function render($values) {
  104. $value = $this->get_value($values);
  105. if (is_array($value)) {
  106. return drupal_render($value);
  107. }
  108. else {
  109. return $this->sanitize_value($value);
  110. }
  111. }
  112. /**
  113. * Provide options for views ui admin specific to fields.
  114. */
  115. function options_form(&$form, &$form_state) {
  116. parent::options_form($form, $form_state);
  117. $field = field_info_field($this->definition['field_name']);
  118. $formatters = _field_view_formatter_options($field['type']);
  119. $form['type'] = [
  120. '#type' => 'select',
  121. '#title' => t('Formatter'),
  122. '#options' => $formatters,
  123. '#default_value' => $this->options['type'],
  124. '#ajax' => [
  125. 'path' => views_ui_build_form_url($form_state),
  126. ],
  127. '#submit' => ['views_ui_config_item_form_submit_temporary'],
  128. '#executes_submit_callback' => TRUE,
  129. ];
  130. // Get the currently selected formatter.
  131. $format = $this->options['type'];
  132. $formatter = field_info_formatter_types($format);
  133. if (!isset($this->options['settings'])) {
  134. $this->options['settings'] = [];
  135. }
  136. $settings = $this->options['settings'] + field_info_formatter_settings($format);
  137. // Provide an instance array for hook_field_formatter_settings_form().
  138. ctools_include('fields');
  139. $this->instance = ctools_fields_fake_field_instance($this->definition['field_name'], '_custom', $formatter, $settings);
  140. // Store the settings in a '_custom' view mode.
  141. $this->instance['display']['_custom'] = [
  142. 'type' => $format,
  143. 'settings' => $settings,
  144. ];
  145. // Get the settings form.
  146. $settings_form = ['#value' => []];
  147. $function = $formatter['module'] . '_field_formatter_settings_form';
  148. if (function_exists($function)) {
  149. $settings_form = $function($field, $this->instance, '_custom', $form, $form_state);
  150. }
  151. $form['settings'] = $settings_form;
  152. }
  153. /**
  154. * Define the options we are going to provide.
  155. */
  156. function option_definition() {
  157. $options = parent::option_definition();
  158. $field = field_info_field($this->definition['field_name']);
  159. $field_type = field_info_field_types($field['type']);
  160. $options['type'] = [
  161. 'default' => $field_type['default_formatter'],
  162. ];
  163. $options['settings'] = [
  164. 'default' => [],
  165. ];
  166. return $options;
  167. }
  168. }