Base.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. <?php
  2. // https://www.drupal.org/docs/8/modules/search-api/developer-documentation/executing-a-search-in-code
  3. namespace Drupal\materio_sapi\Controller;
  4. use Drupal\Core\Controller\ControllerBase;
  5. use Symfony\Component\HttpFoundation\JsonResponse;
  6. use Symfony\Component\HttpFoundation\Request;
  7. use Drupal\Component\Utility\Tags;
  8. use Drupal\Component\Utility\Unicode;
  9. use Drupal\search_api\Entity\Index;
  10. // https://drupal.stackexchange.com/questions/225008/programatically-use-search-api
  11. /**
  12. * Defines a route controller for materio sapi search (regular and ajax).
  13. */
  14. class Base extends ControllerBase {
  15. private $limit = 15;
  16. private $offset = 0;
  17. private function sapiQuery(){
  18. // https://www.drupal.org/docs/8/modules/search-api/developer-documentation/executing-a-search-in-code
  19. $this->index = Index::load('database');
  20. $this->query = $this->index->query();
  21. // Change the parse mode for the search.
  22. $parse_mode = \Drupal::service('plugin.manager.search_api.parse_mode')
  23. ->createInstance('direct');
  24. $parse_mode->setConjunction('OR');
  25. $this->query->setParseMode($parse_mode);
  26. // Set fulltext search keywords and fields.
  27. $this->query->keys($this->keys);
  28. // $this->query->setFulltextFields(['field_reference']);
  29. // Set additional conditions.
  30. // in case we search for material references like W0117
  31. if (preg_match_all('/[WTRPCMFGSO]\d{4}/i', $this->keys, $matches)) {
  32. $ref_conditions = $this->query->createConditionGroup('OR');
  33. foreach ($matches[0] as $key => $value) {
  34. $ref_conditions->addCondition('field_reference', $value);
  35. }
  36. $this->query->addConditionGroup($ref_conditions);
  37. }
  38. // in case of term id provided restrict the keys to taxo fields
  39. if ($this->term) {
  40. $term_conditions = $this->query->createConditionGroup('OR');
  41. $term = (int) $this->term;
  42. foreach (['tag_tid', 'thesaurus_tid'] as $field) {
  43. $term_conditions->addCondition($field, $term);
  44. }
  45. // foreach (['tag_name', 'thesaurus_name'] as $field) {
  46. // $term_conditions->addCondition($field, $this->keys);
  47. // }
  48. // $term_conditions->addCondition('tag_name', $this->keys);
  49. // $term_conditions->addCondition('thesaurus_name', $this->keys);
  50. $this->query->addConditionGroup($term_conditions);
  51. }
  52. // Restrict the search to specific languages.
  53. // $this->query->setLanguages(['de', 'it']);
  54. // Do paging.
  55. $this->query->range($this->offset, $this->limit);
  56. // Add sorting.
  57. $this->query->sort('search_api_relevance', 'DESC');
  58. // Set one or more tags for the query.
  59. // @see hook_search_api_query_TAG_alter()
  60. // @see hook_search_api_results_TAG_alter()
  61. $this->query->addTag('materio_sapi_search');
  62. $this->results = $this->query->execute();
  63. }
  64. private function defaultQuery(){
  65. $entity_storage = \Drupal::entityTypeManager()->getStorage('node');
  66. $this->query = $entity_storage->getQuery()
  67. ->condition('type', 'materiau')
  68. ->condition('status', '1')
  69. ->range($this->offset, $this->limit)
  70. ->accessCheck(TRUE)
  71. ->sort('changed', 'DESC');
  72. // ->condition('field_example', 'test_value')
  73. $this->results = $this->query->execute();
  74. $this->count_query = $entity_storage->getQuery()
  75. ->condition('type', 'materiau')
  76. ->accessCheck(TRUE)
  77. ->condition('status', '1')
  78. ->count();
  79. $this->count = $this->count_query->execute();
  80. }
  81. /**
  82. * get params from request
  83. */
  84. private function parseRequest(Request $request){
  85. // Get the typed string from the URL, if it exists.
  86. $this->keys = $request->query->get('keys');
  87. if($this->keys){
  88. $this->keys = Unicode::strtolower($this->keys);
  89. // $this->keys = Tags::explode($this->keys);
  90. \Drupal::logger('materio_sapi')->notice($this->keys);
  91. }
  92. $this->term = $request->query->get('term');
  93. $this->offset = $request->query->get('offset') ?? $this->offset;
  94. $this->limit = $request->query->get('limit') ?? $this->limit;
  95. }
  96. /**
  97. * Handler for ajax search.
  98. */
  99. public function getResults(Request $request) {
  100. $this->parseRequest($request);
  101. $resp = [
  102. 'range' => array(
  103. 'offset' => $this->offset,
  104. 'limit' => $this->limit
  105. ),
  106. ];
  107. if ($this->keys) {
  108. $this->sapiQuery();
  109. $resp['keys'] = $this->keys;
  110. $resp['term'] = $this->term;
  111. $resp['count'] = $this->results->getResultCount();
  112. $resp['infos'] = t('The search found @count result(s) with keywords @keys.', array(
  113. "@count" => $resp['count'],
  114. "@keys" => $this->keys
  115. ));
  116. $resp['options'] = $this->query->getOptions();
  117. // $items = [];
  118. $uuids = [];
  119. $nids = [];
  120. foreach ($this->results as $result) {
  121. // $nid = $result->getField('nid')->getValues()[0];
  122. // $uuid = $result->getField('uuid')->getValues()[0];
  123. // $title = $result->getField('title')->getValues()[0]->getText();
  124. // $items[] = [
  125. // 'nid' => $nid,
  126. // 'uuid' => $uuid,
  127. // 'title' => $title,
  128. // ];
  129. $uuids[] = $result->getField('uuid')->getValues()[0];
  130. $nids[] = $result->getField('nid')->getValues()[0];
  131. }
  132. // $resp['items'] = $items;
  133. $resp['uuids'] = $uuids;
  134. $resp['nids'] = $nids;
  135. } else {
  136. // no keys or terms to search for
  137. // display the default base page
  138. $this->defaultQuery();
  139. // $uuids = [];
  140. $nids = [];
  141. // Using entityTypeManager
  142. // Get a node storage object.
  143. $node_storage = \Drupal::entityTypeManager()->getStorage('node');
  144. foreach ($this->results as $result) {
  145. $lang = \Drupal::languageManager()->getCurrentLanguage()->getId();
  146. // Load a single node.
  147. $node = $node_storage->load($result);
  148. // check if has translation
  149. if ($node->hasTranslation($lang)) {
  150. // $uuids[] = $result->getField('uuid')->getValues()[0];
  151. $nids[] = $result;
  152. }
  153. }
  154. // $resp['uuids'] = $uuids;
  155. $resp['nids'] = $nids;
  156. $resp['count'] = $this->count;
  157. $resp['infos'] = t('Please use the search form to search from our @count materials.', array(
  158. "@count" => $resp['count']
  159. ));
  160. }
  161. return new JsonResponse($resp);
  162. }
  163. /**
  164. * Handler for regular page search.
  165. */
  166. function pageHandler(Request $request){
  167. // \Drupal::logger('materio_sapi')->notice(print_r($request, true));
  168. $this->parseRequest($request);
  169. $resp = [
  170. "#title" => 'Base'
  171. ];
  172. if ($this->keys) {
  173. $resp['#title'] = $this->keys;
  174. $this->sapiQuery();
  175. $node_view_builder = \Drupal::entityTypeManager()->getViewBuilder('node');
  176. $items = $this->results->getResultItems();
  177. $this->items = [];
  178. foreach ($items as $item) {
  179. // \Drupal::logger('materio_sapi')->notice(print_r($item, true));
  180. try {
  181. /** @var \Drupal\Core\Entity\EntityInterface $entity */
  182. $entity = $item->getOriginalObject()->getValue();
  183. }
  184. catch (SearchApiException $e) {
  185. continue;
  186. }
  187. if (!$entity) {
  188. continue;
  189. }
  190. // TODO: define dynamicly viewmode
  191. $this->items[] = $node_view_builder->view($entity, 'teaser');
  192. }
  193. $resp['items'] = $this->items;
  194. }else{
  195. $resp['#markup'] = t("no keys to search for");
  196. }
  197. return $resp;
  198. }
  199. }