EdlpSearchController.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. <?php
  2. namespace Drupal\edlp_search\Controller;
  3. use Drupal\Core\Controller\ControllerBase;
  4. use Symfony\Component\DependencyInjection\ContainerInterface;
  5. use Drupal\Core\Form\FormBuilder;
  6. use Drupal\search_api\Entity\Index;
  7. use Drupal\Core\Url;
  8. use Drupal\Core\Language\LanguageInterface;
  9. use Symfony\Component\HttpFoundation\Request;
  10. use Symfony\Component\HttpFoundation\JsonResponse;
  11. // use Drupal\Core\Cache\CacheableJsonResponse;
  12. // use Drupal\Core\Cache\CacheableMetadata;
  13. use Drupal\core\render\RenderContext;
  14. /**
  15. * Class EdlpSearchController.
  16. */
  17. class EdlpSearchController extends ControllerBase {
  18. /**
  19. * The form builder.
  20. *
  21. * @var \Drupal\Core\Form\FormBuilder
  22. */
  23. protected $formBuilder;
  24. protected $sapi_index_id;
  25. /**
  26. * Construct.
  27. */
  28. public function __construct(FormBuilder $formBuilder) {
  29. $this->formBuilder = $formBuilder;
  30. $this->sapi_index_id = "collection";
  31. }
  32. /**
  33. * {@inheritdoc}
  34. */
  35. public static function create(ContainerInterface $container) {
  36. return new static(
  37. $container->get('form_builder')
  38. );
  39. }
  40. private function getSearchForm(){
  41. $this->form = $this->formBuilder->getForm('Drupal\edlp_search\Form\EdlpSearchForm');
  42. }
  43. private function buildRenderable(){
  44. $this->getSearchForm();
  45. $this->renderable = array(
  46. "#theme" => "edlp_search_search_form",
  47. '#form' => $this->form
  48. );
  49. }
  50. /**
  51. * Searchform.
  52. *
  53. * @return string
  54. * Return Hello string.
  55. */
  56. public function searchForm() {
  57. $this->buildRenderable();
  58. return $this->renderable;
  59. }
  60. /**
  61. * searchFormJson
  62. */
  63. public function searchFormJson(){
  64. $this->buildRenderable();
  65. $rendered = render($this->renderable);
  66. $data = [
  67. 'rendered' => $rendered,
  68. 'title' => 'Search',
  69. ];
  70. // translations links
  71. $route_name = 'edlp_search.edlp_search_controller_searchForm';
  72. $links = \Drupal::languageManager()->getLanguageSwitchLinks(LanguageInterface::TYPE_URL, Url::fromRoute($route_name));
  73. if (isset($links->links)) {
  74. $translations_build = [
  75. '#theme' => 'links__language_block',
  76. '#links' => $links->links,
  77. '#attributes' => ['class' => ["language-switcher-{$links->method_id}",],],
  78. '#set_active_class' => TRUE,
  79. ];
  80. $translations_rendered = \Drupal::service('renderer')->executeInRenderContext(new RenderContext(), function () use ($translations_build) {return render($translations_build);});
  81. $data['translations_links'] = $translations_rendered;
  82. }
  83. // TODO: make respponse cachable
  84. $response = new JsonResponse();
  85. $response->setData($data);
  86. return $response;
  87. }
  88. public function autocomplete(Request $request){
  89. // TODO: get field_name parameter
  90. $this->request = $request;
  91. $this->getRequestAutocompleteArgs();
  92. // run a search on selected field and get the fields unique values
  93. $this->autocompleteQuery();
  94. $response = new JsonResponse($this->matches);
  95. return $response;
  96. // return array(
  97. // "#markup" => "autocomplete"
  98. // );
  99. }
  100. /**
  101. * autocompleteQuery
  102. */
  103. private function autocompleteQuery(){
  104. // TODO: get the sapi index id with settings
  105. /* @var $sapi_index \Drupal\search_api\IndexInterface */
  106. $sapi_index = Index::load($this->sapi_index_id);
  107. // dpm($sapi_index);
  108. // Create the query.
  109. $query = $sapi_index->query();
  110. $query->setSearchID('edlp_search:autocomplete');
  111. $parse_mode = \Drupal::getContainer()
  112. ->get('plugin.manager.search_api.parse_mode')
  113. ->createInstance('direct');
  114. $query->setParseMode($parse_mode);
  115. $current_langcode = \Drupal::languageManager()->getCurrentLanguage()->getId();
  116. $query->setLanguages(array($current_langcode));
  117. // $query->range(0, 20);
  118. // workflow
  119. $wf_condition_group = $query->createConditionGroup('OR');
  120. $wf_condition_group->addCondition('field_workflow', 'corpus_documents_publie', "=");
  121. // TODO: add condition with the other workflow field
  122. $query->addConditionGroup($wf_condition_group);
  123. // Search for keys.
  124. if (!empty($this->keys)) {
  125. // dpm($this->keys);
  126. $query->keys($this->keys);
  127. }
  128. if(null !== $this->field_synonyms){
  129. // select the taxo field AND the synonym field in which search will be performed
  130. $query->setFulltextFields(array($this->field_name, $this->field_synonyms));
  131. }else{
  132. // OR select the unique taxo field in which search will be performed
  133. $query->setFulltextFields(array($this->field_name));
  134. }
  135. $result = $query->execute();
  136. $items = $result->getResultItems();
  137. // dpm($items);
  138. $this->matches = [];
  139. foreach ($items as $item) {
  140. // get the field from item
  141. try {
  142. /** @var \Drupal\Core\Entity\EntityInterface $entity */
  143. $fields = $item->getField($this->field_name)->getValues();
  144. }catch (SearchApiException $e) {
  145. // if error on getinfg the field, skip item
  146. continue;
  147. }
  148. // if no fields returned, skip item
  149. if (!$fields) {
  150. continue;
  151. }
  152. // dpm($fields);
  153. // get field content
  154. $field_text = $fields[0]->getText();
  155. // if content already in matches, skip item
  156. if( in_array($field_text, $this->matches) ){
  157. continue;
  158. }
  159. // add the item to the return list
  160. $this->matches[] = $field_text;
  161. // do not return more than 14 items
  162. if(count($this->matches) > 14){
  163. break;
  164. }
  165. }
  166. // dpm($this->matches);
  167. }
  168. /**
  169. * getRequestArgs
  170. */
  171. private function getRequestAutocompleteArgs(){
  172. // args are provided by form definition with autocomplete_route_parameters
  173. // dpm($this->request);
  174. $this->field_name = $this->request->query->get('field_name');
  175. // if($this->request->query->get('field_synonyms')){
  176. $this->field_synonyms = $this->request->query->get('field_synonyms');
  177. // }
  178. // if($this->request->query->get('node_type')){
  179. // $this->node_type = $this->request->query->get('node_type');
  180. // }
  181. $this->keys = $this->request->query->get('q');
  182. }
  183. /**
  184. * searchResults
  185. */
  186. public function searchResults(Request $request) {
  187. $this->request = $request;
  188. $this->getRequestSearchArgs();
  189. return $this->getrenderable();
  190. }
  191. /**
  192. * searchResultsJson
  193. */
  194. public function searchResultsJson(Request $request){
  195. $this->request = $request;
  196. $this->getRequestSearchArgs();
  197. $renderable = $this->getrenderable();
  198. $rendered = render($renderable);
  199. // build an array of results's nids
  200. $results_nids = [];
  201. foreach ($this->items as $item) {
  202. $results_nids[] = $item->id();
  203. }
  204. $response = new JsonResponse();
  205. $response->setData([
  206. 'test'=>'search results',
  207. 'keys'=>$this->keys,
  208. 'entries' => $this->entries,
  209. 'entry_names' => $this->entry_names,
  210. 'langues' => $this->langues,
  211. 'genres' => $this->genres,
  212. 'rendered'=> $rendered,
  213. 'results_nids'=>$results_nids,
  214. ]);
  215. return $response;
  216. }
  217. /**
  218. * getRenderable
  219. */
  220. private function getRenderable(){
  221. $this->query();
  222. $build = array(
  223. '#theme' => 'edlp_search_results',
  224. '#items' => $this->items
  225. );
  226. if(!count($this->items)){
  227. $build['#no_results_found'] = array(
  228. '#markup' => t('Your search yielded no results.')
  229. );
  230. // $build['#search_help'] = array(
  231. // '#markup' => $this->t('<ul>
  232. // <li>Check if your spelling is correct.</li>
  233. // <li>Remove quotes around phrases to search for each word individually. <em>bike shed</em> will often show more results than <em>&quot;bike shed&quot;</em>.</li>
  234. // <li>Consider loosening your query with <em>OR</em>. <em>bike OR shed</em> will often show more results than <em>bike shed</em>.</li>
  235. // </ul>')
  236. // );
  237. }
  238. return $build;
  239. }
  240. /**
  241. * query
  242. */
  243. private function query(){
  244. // TODO: get the sapi index id with settings
  245. /* @var $sapi_index \Drupal\search_api\IndexInterface */
  246. $sapi_index = Index::load($this->sapi_index_id);
  247. // dpm($sapi_index);
  248. // Create the query.
  249. $query = $sapi_index->query();
  250. // dpm($query);
  251. $query->setSearchID('edlp_search:ajaxsearch');
  252. $parse_mode = \Drupal::getContainer()
  253. ->get('plugin.manager.search_api.parse_mode')
  254. ->createInstance('direct');
  255. $query->setParseMode($parse_mode);
  256. // workflow
  257. $wf_condition_group = $query->createConditionGroup('OR');
  258. $wf_condition_group->addCondition('field_workflow', 'corpus_documents_publie', "=");
  259. // TODO: add condition with the other workflow field
  260. $query->addConditionGroup($wf_condition_group);
  261. // Search for keys.
  262. if (!empty($this->keys)) {
  263. // $query->keys($this->keys);
  264. $keys_condition_group = $query->createConditionGroup('OR');
  265. $keys_condition_group->addCondition('title', $this->keys, 'IN');
  266. $keys_condition_group->addCondition('field_description', $this->keys, 'IN');
  267. $query->addConditionGroup($keys_condition_group);
  268. }
  269. // langues
  270. if (!empty($this->langues)) {
  271. $query->addCondition('field_langues', $this->langues, "=");
  272. }
  273. // genres
  274. if (!empty($this->genres)) {
  275. $query->addCondition('field_genres', $this->genres, "=");
  276. }
  277. // entries
  278. $this->entry_names = [];
  279. if (!empty($this->entries)){
  280. $terms = entity_load_multiple('taxonomy_term', $this->entries);
  281. $entries_condition_group = $query->createConditionGroup();
  282. foreach ($terms as $tid => $term) {
  283. $entries_condition_group->addCondition('field_entrees', (int)$tid, "=");
  284. $this->entry_names[] = $term->getName();
  285. }
  286. // dpm($entries_condition_group);
  287. $query->addConditionGroup($entries_condition_group);
  288. }
  289. // TODO: locuteurs
  290. $language = \Drupal::languageManager()->getCurrentLanguage()->getId();
  291. // $language = \Drupal::languageManager()->getCurrentLanguage()->getName();
  292. $query->addCondition('search_api_language', $language);
  293. $result = $query->execute();
  294. $items = $result->getResultItems();
  295. // dpm($items);
  296. $this->items = [];
  297. foreach ($items as $item) {
  298. try {
  299. /** @var \Drupal\Core\Entity\EntityInterface $entity */
  300. $entity = $item->getOriginalObject()->getValue();
  301. }
  302. catch (SearchApiException $e) {
  303. continue;
  304. }
  305. if (!$entity) {
  306. continue;
  307. }
  308. $this->items[] = $entity;
  309. }
  310. // dpm($this->items);
  311. }
  312. /**
  313. * getRequestArgs
  314. */
  315. private function getRequestSearchArgs(){
  316. // dpm($this->request);
  317. $this->keys = $this->request->query->get('keys');
  318. $this->langues = $this->request->query->get('langues');
  319. $this->genres = $this->request->query->get('genres');
  320. $this->entries = $this->request->query->get('entries');
  321. }
  322. }