original_string: protected function _scopeWordsInFulltext(Query $query, TokenInterface $token)
      {
          $value = str_replace(['*', '!'], ['*', '*'], $token->value());
          $value = mb_strpos($value, '+') === 0 ? mb_substr($value, 1) : $value;
  
          if (empty($value) || in_array($value, $this->_stopWords())) {
              return $query;
          }
  
          $not = $token->negated() ? 'NOT' : '';
          $value = str_replace(["'", '@'], ['"', ' '], $value);
          $conditions = ["{$not} MATCH(SearchDatasets.words) AGAINST('{$value}' IN BOOLEAN MODE) > 0"];
  
          if ($token->where() === 'or') {
              $query->orWhere($conditions);
          } elseif ($token->where() === 'and') {
              $query->andWhere($conditions);
          } else {
              $query->where($conditions);
          }
  
          return $query;
      }
code: protected function _scopeWordsInFulltext(Query $query, TokenInterface $token)
      {
          $value = str_replace(['*', '!'], ['*', '*'], $token->value());
          $value = mb_strpos($value, '+') === 0 ? mb_substr($value, 1) : $value;
  
          if (empty($value) || in_array($value, $this->_stopWords())) {
              return $query;
          }
  
          $not = $token->negated() ? 'NOT' : '';
          $value = str_replace(["'", '@'], ['"', ' '], $value);
          $conditions = ["{$not} MATCH(SearchDatasets.words) AGAINST('{$value}' IN BOOLEAN MODE) > 0"];
  
          if ($token->where() === 'or') {
              $query->orWhere($conditions);
          } elseif ($token->where() === 'and') {
              $query->andWhere($conditions);
          } else {
              $query->where($conditions);
          }
  
          return $query;
      }
code_tokens: protected function _scopeWordsInFulltext ( Query $ query , TokenInterface $ token ) { $ value = str_replace ( [ '*' , '!' ] , [ '*' , '*' ] , $ token -> value ( ) ) ; $ value = mb_strpos ( $ value , '+' ) === 0 ? mb_substr ( $ value , 1 ) : $ value ; if ( empty ( $ value ) || in_array ( $ value , $ this -> _stopWords ( ) ) ) { return $ query ; } $ not = $ token -> negated ( ) ? 'NOT' : '' ; $ value = str_replace ( [ "'" , '@' ] , [ '"' , ' ' ] , $ value ) ; $ conditions = [ "{$not} MATCH(SearchDatasets.words) AGAINST('{$value}' IN BOOLEAN MODE) > 0" ] ; if ( $ token -> where ( ) === 'or' ) { $ query -> orWhere ( $ conditions ) ; } elseif ( $ token -> where ( ) === 'and' ) { $ query -> andWhere ( $ conditions ) ; } else { $ query -> where ( $ conditions ) ; } return $ query ; }
docstring: Similar to "_scopeWords" but using MySQL's fulltext indexes.
  
  @param \Cake\ORM\Query $query The query to scope
  @param \Search\TokenInterface $token Token describing a words sequence. e.g `this is a phrase`
  @return \Cake\ORM\Query Scoped query
docstring_tokens: Similar to _scopeWords but using MySQL s fulltext indexes .