getCurrentLanguage()->getId(); $this->index = Index::load('database'); $this->results = [ 'uuids' => [], 'nids' => [] ]; // AND QUERY $this->and_query = $this->index->query(['offset'=>0,'limit'=>10000]); // set parse mode and conjunction $parse_mode = \Drupal::service('plugin.manager.search_api.parse_mode') ->createInstance('terms'); $parse_mode->setConjunction('AND'); $this->and_query->setParseMode($parse_mode); // Set fulltext search keywords and fields. if ($this->keys) { $this->and_query->keys($this->keys); } // in case of term id provided restrict the keys to taxo fields if ($this->term) { $term_conditions = $this->and_query->createConditionGroup('OR'); $term = (int) $this->term; foreach (['tag_tid', 'thesaurus_tid'] as $field) { $term_conditions->addCondition($field, $term); } $this->and_query->addConditionGroup($term_conditions); // INSTEAD TRY TO BOOST THE TAG AND THESAURUS FIELDS // foreach ($taxoSolrFieldsName as $fname) { // // $solarium_query->addParam('bf', "recip(abs(ms(NOW,{$solrField})),3.16e-11,10,0.1)"); // $bfparam = "if(gt(termfreq({$fname},{$this->term}),0),^21,0)"; // $this->or_query->addParam('bf', $bfparam); // } // look @ materio_sapi_search_api_solr_query_alter in materio_sapi.module // $this->or_query->setOption('termid', $this->term); } if ($this->filters) { // FILTERS $filters_conditions = $this->and_query->createConditionGroup('AND'); foreach ($this->filters as $filter) { $filter = (int) $filter; foreach (['thesaurus_tid'] as $field) { // 'tag_tid', $filters_conditions->addCondition($field, $filter); } } $this->and_query->addConditionGroup($filters_conditions); if(!$this->keys) { // if no keys but filters switch query to direct and add wildcard solr keys *:* $direct_and_parse_mode = \Drupal::service('plugin.manager.search_api.parse_mode') ->createInstance('direct'); $direct_and_parse_mode->setConjunction('AND'); $this->and_query->setParseMode($direct_and_parse_mode); // $this->and_query->keys('*:*'); } } // else{ $fulltextFields = []; // Recherche uniquement sur les champ thésaurus et tag $fulltextFields += [ 'thesaurus_name_0', 'thesaurus_synonyms_0', 'thesaurus_name_1', 'thesaurus_synonyms_1', 'thesaurus_name_2', 'thesaurus_synonyms_2', 'thesaurus_name_3', 'thesaurus_synonyms_3', 'thesaurus_name_4', 'thesaurus_synonyms_4', 'thesaurus_name', 'thesaurus_synonyms', 'tag_name', 'tag_synonyms' ]; if(count($fulltextFields)){ $this->and_query->setFulltextFields($fulltextFields); } // } // Restrict the search to specific languages. $this->and_query->setLanguages([$lang]); // Do paging. // $this->and_query->range($this->offset, $this->limit); // retrieve all results // $this->and_query->range(0, -1); // Add sorting. $this->and_query->sort('search_api_relevance', 'DESC'); // Set one or more tags for the query. // @see hook_search_api_query_TAG_alter() // @see hook_search_api_results_TAG_alter() $this->and_query->addTag('materio_sapi_search_and_query'); $and_results = $this->and_query->execute(); foreach ($and_results as $result) { $this->results['uuids'][] = $result->getField('uuid')->getValues()[0]; $this->results['nids'][] = $result->getField('nid')->getValues()[0]; } $this->exactematch_count = count($this->results['nids']); // // OR QUERY // $this->or_query = $this->index->query(['offset'=>0,'limit'=>10000]); // Change the parse mode for the search. // Les différentes possibilités sont // - « direct » => Requête directe // - « terms » => Multiple words // - « phrase » => Single phrase // - " edismax " => ??? $or_parse_mode = \Drupal::service('plugin.manager.search_api.parse_mode') ->createInstance('direct'); $or_parse_mode->setConjunction('OR'); $this->or_query->setParseMode($or_parse_mode); // Set fulltext search keywords and fields. if ($this->keys) { $this->or_query->keys($this->keys); } // exclude results from and_query $exclude_and_results_conditions = $this->or_query->createConditionGroup('AND'); foreach ($this->results['nids'] as $nid) { $exclude_and_results_conditions->addCondition('nid', $nid, '<>'); } $this->or_query->addConditionGroup($exclude_and_results_conditions); if (preg_match_all('/[WTRPCMFGSO]\d{4}/i', $this->keys, $matches)) { // in case we search for material references like W0117 $ref_conditions = $this->or_query->createConditionGroup('OR'); foreach ($matches[0] as $key => $value) { $ref_conditions->addCondition('field_reference', $value); } $this->or_query->addConditionGroup($ref_conditions); } if ($this->filters) { // FILTERS $or_filters_conditions = $this->or_query->createConditionGroup('OR'); foreach ($this->filters as $filter) { $filter = (int) $filter; foreach (['thesaurus_tid'] as $field) { // 'tag_tid', $or_filters_conditions->addCondition($field, $filter); } } $this->or_query->addConditionGroup($or_filters_conditions); if(!$this->keys) { // if no keys but filters switch query to direct and add wildcard solr keys *:* $direct_or_parse_mode = \Drupal::service('plugin.manager.search_api.parse_mode') ->createInstance('direct'); $direct_or_parse_mode->setConjunction('OR'); $this->or_query->setParseMode($direct_or_parse_mode); // $this->or_query->keys('*:*'); } } // Restrict the search to specific languages. $this->or_query->setLanguages([$lang]); // Do paging. // $this->or_query->range($this->offset, $this->limit); // retrieve all results // $this->or_query->range(0, -1); // Add sorting. $this->or_query->sort('search_api_relevance', 'DESC'); // Set one or more tags for the query. // @see hook_search_api_query_TAG_alter() // @see hook_search_api_results_TAG_alter() $this->or_query->addTag('materio_sapi_search_or_query'); $or_results = $this->or_query->execute(); foreach ($or_results as $result) { $this->results['uuids'][] = $result->getField('uuid')->getValues()[0]; $this->results['nids'][] = $result->getField('nid')->getValues()[0]; } // todo you may like / more like this } private function defaultQuery(){ $lang = \Drupal::languageManager()->getCurrentLanguage()->getId(); $entity_storage = \Drupal::entityTypeManager()->getStorage('node'); $this->query = $entity_storage->getQuery() ->condition('type', ['materiau', 'thematique'], 'IN') ->condition('status', '1') ->condition('langcode', $lang) ->range($this->offset, $this->limit) ->accessCheck(TRUE) ->sort('created', 'DESC'); // ->condition('field_example', 'test_value') $this->results = $this->query->execute(); $this->count_query = $entity_storage->getQuery() ->condition('type', ['materiau', 'thematique'], 'IN') ->condition('langcode', $lang) ->accessCheck(TRUE) ->condition('status', '1') ->count(); $this->count = $this->count_query->execute(); } /** * get params from request */ private function parseRequest(Request $request){ // Get the typed string from the URL, if it exists. $this->keys = $request->query->get('keys'); if($this->keys){ $this->keys = mb_strtolower($this->keys); // $this->keys = Tags::explode($this->keys); \Drupal::logger('materio_sapi')->notice($this->keys); } // get the exacte term id in case of autocomplete $this->term = $request->query->get('term'); // get the filters of advanced search $f = $request->query->get('filters'); $this->filters = strlen($f) ? explode(',', $f) : null; // $this->allparams = $request->query->all(); // $request->attributes->get('_raw_variables')->get('filters') // $this->offset = $request->query->get('offset') ?? $this->offset; $this->limit = $request->query->get('limit') ?? $this->limit; } /** * Handler for ajax search. */ public function getResults(Request $request) { $this->parseRequest($request); $resp = [ 'range' => array( 'offset' => $this->offset, 'limit' => $this->limit ), ]; if ($this->keys || $this->filters) { $lang = \Drupal::languageManager()->getCurrentLanguage()->getId(); $this->sapiQuery(); $resp['keys'] = $this->keys; $resp['term'] = $this->term; $resp['filters'] = $this->filters; // $resp['count'] = $this->results->getResultCount(); $resp['count'] = count($this->results['nids']); $resp['exactematch_count'] = $this->exactematch_count; $resp['infos'] = t('The search found @exactmatchcount exact match result(s) for @count total result(s) with', array( "@exactmatchcount" => $resp['exactematch_count'], "@count" => $resp['count'] )); if ($this->keys) { $resp['infos'] .= t(' keywords @keys', array( "@keys" => $this->keys )); } if ($this->keys && $this->filters) { $resp['infos'] .= " and"; } if ($this->filters) { // get the terms names from tid $storage = \Drupal::entityTypeManager()->getStorage('taxonomy_term'); $filters_names = []; foreach ($this->filters as $tid) { /** @var \Drupal\Core\Entity\EntityInterface $entity */ $entity = $storage->load($tid); $entity_trans = \Drupal::service('entity.repository')->getTranslationFromContext($entity, $lang); $filters_names[] = $entity_trans->getName(); } $resp['infos'] .= t(' filters @filters', array( "@filters" => implode(', ', $filters_names) )); } // $resp['options'] = $this->query->getOptions(); // $uuids = []; // $nids = []; // foreach ($this->results as $result) { // $uuids[] = $result->getField('uuid')->getValues()[0]; // $nids[] = $result->getField('nid')->getValues()[0]; // } $resp['nids'] = array_slice($this->results['nids'], $this->offset, $this->limit); $resp['uuids'] = array_slice($this->results['uuids'], $this->offset, $this->limit); } else { // no keys or terms to search for // display the default base page $this->defaultQuery(); // $uuids = []; $nids = []; // Using entityTypeManager // Get a node storage object. // $node_storage = \Drupal::entityTypeManager()->getStorage('node'); foreach ($this->results as $result) { // $lang = \Drupal::languageManager()->getCurrentLanguage()->getId(); // Load a single node. // $node = $node_storage->load($result); // check if has translation // i used to filter like bellow because of a graphql probleme // if ($node->hasTranslation($lang)) { $nids[] = $result; // } } // $resp['uuids'] = $uuids; $resp['nids'] = $nids; $resp['count'] = $this->count; $resp['infos'] = t('Please use the search form to search from our @count materials.', array( "@count" => $resp['count'] )); } return new JsonResponse($resp); } /** * Handler for regular page search. */ function pageHandler(Request $request){ // \Drupal::logger('materio_sapi')->notice(print_r($request, true)); $this->parseRequest($request); $resp = [ "#title" => 'Base' ]; if ($this->keys) { $resp['#title'] = $this->keys; // $this->sapiQuery(); // $node_storage = \Drupal::entityTypeManager()->getStorage('node'); // $node_view_builder = \Drupal::entityTypeManager()->getViewBuilder('node'); // // $items = $this->results->getResultItems(); // $nids = $this->results['nids']; // $this->items = []; // foreach ($nids as $nid) { // // \Drupal::logger('materio_sapi')->notice(print_r($nid, true)); // try { // /** @var \Drupal\Core\Entity\EntityInterface $entity */ // // $entity = $item->getOriginalObject()->getValue(); // $entity = $node_storage->load($nid); // } // catch (SearchApiException $e) { // continue; // } // if (!$entity) { // continue; // } // // TODO: define dynamicly viewmode // $this->items[] = $node_view_builder->view($entity, 'teaser'); // } // $resp['items'] = $this->items; $resp['items'] = []; }else{ $resp['#markup'] = t("no keys to search for"); } return $resp; } }