search_api_multi.views.inc 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <?php
  2. /**
  3. * Implements hook_views_data().
  4. */
  5. // This is largely copied from search_api_views_views_data(), including the
  6. // "This is largely copied from _search_api_admin_get_fields()." comment.
  7. function search_api_multi_views_data() {
  8. $data = array();
  9. $servers = array();
  10. foreach (search_api_index_load_multiple(FALSE) as $index) {
  11. if (!($server = $index->server()) || !$server->supportsFeature('search_api_multi')) {
  12. continue;
  13. }
  14. $servers[$server->machine_name][$index->machine_name] = $index->name;
  15. // We need the complete indexed data.
  16. $array = array();
  17. $index->dataAlter($array);
  18. // Base data
  19. $key = 'search_api_server_' . $server->machine_name;
  20. $table = &$data[$key];
  21. $table['table']['base'] = array(
  22. 'field' => 'search_api_id',
  23. 'index' => $server->machine_name,
  24. 'title' => $server->name,
  25. 'help' => t('Use search indexes on the %name search server for filtering and retrieving data.', array('%name' => $server->name)),
  26. 'query class' => 'search_api_multi_query',
  27. );
  28. // Add all available fields
  29. // This is largely copied from _search_api_admin_get_fields().
  30. $max_depth = variable_get('search_api_multi_max_fields_depth', 2);
  31. $orig_wrapper = $index->entityWrapper(NULL, FALSE);
  32. $fields = empty($index->options['fields']) ? array() : $index->options['fields'];
  33. // A wrapper for a specific field name prefix, e.g. 'user:' mapped to the user wrapper
  34. $wrappers = array('' => $orig_wrapper);
  35. // Display names for the prefixes
  36. $prefix_names = array('' => '');
  37. // The list nesting level for entities with a certain prefix
  38. $nesting_levels = array('' => 0);
  39. $types = search_api_field_types();
  40. $types['options'] = t('Options');
  41. while ($wrappers) {
  42. foreach ($wrappers as $prefix => $wrapper) {
  43. $prefix_name = $prefix_names[$prefix];
  44. $depth = substr_count($prefix, ':');
  45. // Deal with lists.
  46. $nesting_level = $nesting_levels[$prefix];
  47. $type_prefix = str_repeat('list<', $nesting_level);
  48. $type_suffix = str_repeat('>', $nesting_level);
  49. if ($nesting_level) {
  50. $info = $wrapper->info();
  51. // The real nesting level of the wrapper, not the accumulated one.
  52. $level = search_api_list_nesting_level($info['type']);
  53. for ($i = 0; $i < $level; ++$i) {
  54. $wrapper = $wrapper[0];
  55. }
  56. }
  57. // Now look at all properties.
  58. foreach ($wrapper as $property => $value) {
  59. $info = $value->info();
  60. $type = $type_prefix . $info['type'] . $type_suffix;
  61. $inner_type = search_api_extract_inner_type($info['type']);
  62. if ($inner_type == 'token') {
  63. $inner_type = 'string';
  64. $type = search_api_nest_type('string', $type);
  65. }
  66. $key = $index->machine_name . ':' . $prefix . $property;
  67. if (isset($types[$inner_type])) {
  68. if ($value->optionsList()) {
  69. $inner_type = 'options';
  70. $type = search_api_nest_type('options', $type);
  71. }
  72. // Add field handler.
  73. $table[$key]['group'] = $prefix_name ? $index->name . ' » ' . $prefix_name : $index->name;
  74. $table[$key]['title'] = $info['label'];
  75. $table[$key]['help'] = empty($info['description']) ? t('(No information available)') : $info['description'];
  76. $table[$key]['type'] = $type;
  77. $table[$key]['field']['handler'] = _search_api_views_field_handler($type, $inner_type);
  78. if ($inner_type == 'options') {
  79. $table[$key]['field']['options'] = $value->optionsList();
  80. }
  81. // If field is indexed, also add additional handlers.
  82. if (!empty($fields[$prefix . $property])) {
  83. // Discern between original and indexed type
  84. $table[$key]['field']['type'] = $table[$key]['type'];
  85. $table[$key]['type'] = $fields[$prefix . $property]['type'];
  86. $table[$key] += _search_api_views_add_handlers($fields[$prefix . $property], $value);
  87. if (!empty($table[$key]['sort'])) {
  88. $table[$key]['field']['click sortable'] = TRUE;
  89. }
  90. }
  91. unset($fields[$prefix . $property]);
  92. }
  93. elseif ($depth < $max_depth) {
  94. // Visit this entity/struct in a later iteration.
  95. $key = $prefix . $property . ':';
  96. $wrappers[$key] = $value;
  97. $prefix_names[$key] = $prefix_name ? $prefix_name . ' » ' . $info['label'] : $info['label'];
  98. $nesting_levels[$key] = search_api_list_nesting_level($type);
  99. }
  100. }
  101. unset($wrappers[$prefix]);
  102. }
  103. }
  104. // Add handlers for all indexed fields which weren't processed yet.
  105. foreach ($fields as $key => $field) {
  106. $tmp = $orig_wrapper;
  107. $group = '';
  108. $name = $index->name;
  109. $parts = explode(':', $key);
  110. foreach ($parts as $i => $part) {
  111. if (!isset($tmp->$part)) {
  112. continue 2;
  113. }
  114. $tmp = $tmp->$part;
  115. $info = $tmp->info();
  116. $group = ($group ? $group . ' » ' . $name : ($name ? $name : ''));
  117. $name = $info['label'];
  118. if ($i < count($parts) - 1) {
  119. // Unwrap lists.
  120. $level = search_api_list_nesting_level($info['type']);
  121. for ($j = 0; $j < $level; ++$j) {
  122. $tmp = $tmp[0];
  123. }
  124. }
  125. }
  126. $key = $index->machine_name . ':' . $key;
  127. if ($group) {
  128. $table[$key]['group'] = $group;
  129. }
  130. $table[$key]['title'] = $name;
  131. $table[$key]['help'] = empty($info['description']) ? t('(No information available)') : $info['description'];
  132. $table[$key]['type'] = $field['type'];
  133. $table[$key] += _search_api_views_add_handlers($field, $tmp);
  134. }
  135. // Special handlers
  136. $table['search_api_relevance']['group'] = t('Search');
  137. $table['search_api_relevance']['title'] = t('Relevance');
  138. $table['search_api_relevance']['help'] = t('The relevance of this search result with respect to the query.');
  139. $table['search_api_relevance']['type'] = 'decimal';
  140. $table['search_api_relevance']['field']['handler'] = _search_api_views_field_handler('decimal', 'decimal');
  141. $table['search_api_relevance']['field']['click sortable'] = TRUE;
  142. $table['search_api_relevance']['sort']['handler'] = 'SearchApiViewsHandlerSort';
  143. $table['search_api_multi_fulltext']['group'] = t('Search');
  144. $table['search_api_multi_fulltext']['title'] = t('Fulltext search');
  145. $table['search_api_multi_fulltext']['help'] = t('Search several or all fulltext fields at once.');
  146. $table['search_api_multi_fulltext']['type'] = 'text';
  147. $table['search_api_multi_fulltext']['filter']['handler'] = 'SearchApiMultiHandlerFilterFulltext';
  148. $table['search_api_multi_fulltext']['argument']['handler'] = 'SearchApiMultiHandlerArgumentFulltext';
  149. }
  150. foreach ($servers as $server_id => $indexes) {
  151. $key = 'search_api_server_' . $server_id;
  152. $table = &$data[$key];
  153. $table['search_api_multi_index']['group'] = t('Search');
  154. $table['search_api_multi_index']['title'] = t('Index');
  155. $table['search_api_multi_index']['help'] = t('The search indexes that will be searched.');
  156. $table['search_api_multi_index']['type'] = 'options';
  157. $table['search_api_multi_index']['field']['handler'] = _search_api_views_field_handler('options', 'options');
  158. $table['search_api_multi_index']['field']['options'] = $indexes;
  159. $table['search_api_multi_index']['argument']['handler'] = 'SearchApiViewsHandlerArgument';
  160. $table['search_api_multi_index']['filter']['handler'] = 'SearchApiViewsHandlerFilterOptions';
  161. $table['search_api_multi_index']['filter']['options'] = $indexes;
  162. }
  163. return $data;
  164. }
  165. /**
  166. * Implements hook_views_plugins().
  167. */
  168. function search_api_multi_views_plugins() {
  169. return array(
  170. 'query' => array(
  171. 'search_api_multi_query' => array(
  172. 'title' => t('Search API Query'),
  173. 'help' => t('Query will be generated and run using the Search API.'),
  174. 'handler' => 'SearchApiMultiViewsQuery'
  175. ),
  176. ),
  177. );
  178. }