559 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			559 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
 | 
						|
namespace WapplerSystems\Meilisearch\Domain\Search\Query;
 | 
						|
 | 
						|
/***************************************************************
 | 
						|
 *  Copyright notice
 | 
						|
 *
 | 
						|
 *  (c) 2017 <timo.hund@dkd.de>
 | 
						|
 *  All rights reserved
 | 
						|
 *
 | 
						|
 *  This script is part of the TYPO3 project. The TYPO3 project is
 | 
						|
 *  free software; you can redistribute it and/or modify
 | 
						|
 *  it under the terms of the GNU General Public License as published by
 | 
						|
 *  the Free Software Foundation; either version 3 of the License, or
 | 
						|
 *  (at your option) any later version.
 | 
						|
 *
 | 
						|
 *  The GNU General Public License can be found at
 | 
						|
 *  http://www.gnu.org/copyleft/gpl.html.
 | 
						|
 *
 | 
						|
 *  This script is distributed in the hope that it will be useful,
 | 
						|
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
 *  GNU General Public License for more details.
 | 
						|
 *
 | 
						|
 *  This copyright notice MUST APPEAR in all copies of the script!
 | 
						|
 ***************************************************************/
 | 
						|
 | 
						|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\BigramPhraseFields;
 | 
						|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\Elevation;
 | 
						|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\Faceting;
 | 
						|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\FieldCollapsing;
 | 
						|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\Grouping;
 | 
						|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\Highlighting;
 | 
						|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\Operator;
 | 
						|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\PhraseFields;
 | 
						|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\QueryFields;
 | 
						|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\ReturnFields;
 | 
						|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\Slops;
 | 
						|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\Sorting;
 | 
						|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\Sortings;
 | 
						|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\Spellchecking;
 | 
						|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\TrigramPhraseFields;
 | 
						|
use TYPO3\CMS\Core\Utility\GeneralUtility;
 | 
						|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
 | 
						|
 | 
						|
/**
 | 
						|
 * The AbstractQueryBuilder contains all logic to initialize meilisearch queries independent from TYPO3.
 | 
						|
 */
 | 
						|
abstract class AbstractQueryBuilder {
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var Query
 | 
						|
     */
 | 
						|
    protected $queryToBuild = null;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param Query $query
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function startFrom(Query $query)
 | 
						|
    {
 | 
						|
        $this->queryToBuild = $query;
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return Query
 | 
						|
     */
 | 
						|
    public function getQuery(): Query
 | 
						|
    {
 | 
						|
        return $this->queryToBuild;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param bool $omitHeader
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useOmitHeader($omitHeader = true)
 | 
						|
    {
 | 
						|
        $this->queryToBuild->setOmitHeader($omitHeader);
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Uses an array of filters and applies them to the query.
 | 
						|
     *
 | 
						|
     * @param array $filterArray
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useFilterArray(array $filterArray)
 | 
						|
    {
 | 
						|
        foreach ($filterArray as $key => $additionalFilter) {
 | 
						|
            $this->useFilter($additionalFilter, $key);
 | 
						|
        }
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Applies the queryString that is used to search
 | 
						|
     *
 | 
						|
     * @param string $queryString
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useQueryString($queryString)
 | 
						|
    {
 | 
						|
        $this->queryToBuild->setQuery($queryString);
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Applies the passed queryType to the query.
 | 
						|
     *
 | 
						|
     * @param string $queryType
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useQueryType(string $queryType)
 | 
						|
    {
 | 
						|
        $this->queryToBuild->addParam('qt', $queryType);
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Remove the queryType (qt) from the query.
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function removeQueryType()
 | 
						|
    {
 | 
						|
        $this->queryToBuild->addParam('qt', null);
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Can be used to remove all sortings from the query.
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function removeAllSortings()
 | 
						|
    {
 | 
						|
        $this->queryToBuild->clearSorts();
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Applies the passed sorting to the query.
 | 
						|
     *
 | 
						|
     * @param Sorting $sorting
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useSorting(Sorting $sorting)
 | 
						|
    {
 | 
						|
        if (strpos($sorting->getFieldName(), 'relevance') !== false) {
 | 
						|
            $this->removeAllSortings();
 | 
						|
            return $this;
 | 
						|
        }
 | 
						|
 | 
						|
        $this->queryToBuild->addSort($sorting->getFieldName(), $sorting->getDirection());
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Applies the passed sorting to the query.
 | 
						|
     *
 | 
						|
     * @param Sortings $sortings
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useSortings(Sortings $sortings)
 | 
						|
    {
 | 
						|
        foreach($sortings->getSortings() as $sorting) {
 | 
						|
            $this->useSorting($sorting);
 | 
						|
        }
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param int $resultsPerPage
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useResultsPerPage($resultsPerPage)
 | 
						|
    {
 | 
						|
        $this->queryToBuild->setRows($resultsPerPage);
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param int $page
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function usePage($page)
 | 
						|
    {
 | 
						|
        $this->queryToBuild->setStart($page);
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param Operator $operator
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useOperator(Operator $operator)
 | 
						|
    {
 | 
						|
        $this->queryToBuild->setQueryDefaultOperator( $operator->getOperator());
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Remove the default query operator.
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function removeOperator()
 | 
						|
    {
 | 
						|
        $this->queryToBuild->setQueryDefaultOperator('');
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param Slops $slops
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useSlops(Slops $slops)
 | 
						|
    {
 | 
						|
        return $slops->build($this);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Uses the passed boostQuer(y|ies) for the query.
 | 
						|
     *
 | 
						|
     * @param string|array $boostQueries
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useBoostQueries($boostQueries)
 | 
						|
    {
 | 
						|
        $boostQueryArray = [];
 | 
						|
        if(is_array($boostQueries)) {
 | 
						|
            foreach($boostQueries as $boostQuery) {
 | 
						|
                $boostQueryArray[] = ['key' => md5($boostQuery), 'query' => $boostQuery];
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            $boostQueryArray[] = ['key' => md5($boostQueries), 'query' => $boostQueries];
 | 
						|
        }
 | 
						|
 | 
						|
        $this->queryToBuild->getEDisMax()->setBoostQueries($boostQueryArray);
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Removes all boost queries from the query.
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function removeAllBoostQueries()
 | 
						|
    {
 | 
						|
        $this->queryToBuild->getEDisMax()->clearBoostQueries();
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Uses the passed boostFunction for the query.
 | 
						|
     *
 | 
						|
     * @param string $boostFunction
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useBoostFunction(string $boostFunction)
 | 
						|
    {
 | 
						|
        $this->queryToBuild->getEDisMax()->setBoostFunctions($boostFunction);
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Removes all previously configured boost functions.
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function removeAllBoostFunctions()
 | 
						|
    {
 | 
						|
        $this->queryToBuild->getEDisMax()->setBoostFunctions('');
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    /**
 | 
						|
     * Uses the passed minimumMatch(mm) for the query.
 | 
						|
     *
 | 
						|
     * @param string $minimumMatch
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useMinimumMatch(string $minimumMatch)
 | 
						|
    {
 | 
						|
        $this->queryToBuild->getEDisMax()->setMinimumMatch($minimumMatch);
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Remove any previous passed minimumMatch parameter.
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function removeMinimumMatch()
 | 
						|
    {
 | 
						|
        $this->queryToBuild->getEDisMax()->setMinimumMatch('');
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    /**
 | 
						|
     * Applies the tie parameter to the query.
 | 
						|
     *
 | 
						|
     * @param mixed $tie
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useTieParameter($tie)
 | 
						|
    {
 | 
						|
        $this->queryToBuild->getEDisMax()->setTie($tie);
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Applies custom QueryFields to the query.
 | 
						|
     *
 | 
						|
     * @param QueryFields $queryFields
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useQueryFields(QueryFields $queryFields)
 | 
						|
    {
 | 
						|
        return $queryFields->build($this);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Applies custom ReturnFields to the query.
 | 
						|
     *
 | 
						|
     * @param ReturnFields $returnFields
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useReturnFields(ReturnFields $returnFields)
 | 
						|
    {
 | 
						|
        return $returnFields->build($this);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Can be used to use a specific filter string in the meilisearch query.
 | 
						|
     *
 | 
						|
     * @param string $filterString
 | 
						|
     * @param string $filterName
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useFilter($filterString, $filterName = '')
 | 
						|
    {
 | 
						|
        $filterName = $filterName === '' ? $filterString : $filterName;
 | 
						|
 | 
						|
        $nameWasPassedAndFilterIsAllreadySet = $filterName !== '' && $this->queryToBuild->getFilterQuery($filterName) !== null;
 | 
						|
        if($nameWasPassedAndFilterIsAllreadySet) {
 | 
						|
            return $this;
 | 
						|
        }
 | 
						|
        $this->queryToBuild->addFilterQuery(['key' => $filterName, 'query' => $filterString]);
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Removes a filter by the fieldName.
 | 
						|
     *
 | 
						|
     * @param string $fieldName
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function removeFilterByFieldName($fieldName)
 | 
						|
    {
 | 
						|
        return $this->removeFilterByFunction(
 | 
						|
            function($key, $query) use ($fieldName) {
 | 
						|
                $queryString = $query->getQuery();
 | 
						|
                $storedFieldName = substr($queryString,0, strpos($queryString, ":"));
 | 
						|
                return $storedFieldName == $fieldName;
 | 
						|
            }
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Removes a filter by the name of the filter (also known as key).
 | 
						|
     *
 | 
						|
     * @param string $name
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function removeFilterByName($name)
 | 
						|
    {
 | 
						|
        return $this->removeFilterByFunction(
 | 
						|
            function($key, $query) use ($name) {
 | 
						|
                $key = $query->getKey();
 | 
						|
                return $key == $name;
 | 
						|
            }
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Removes a filter by the filter value.
 | 
						|
     *
 | 
						|
     * @param string $value
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function removeFilterByValue($value)
 | 
						|
    {
 | 
						|
        return $this->removeFilterByFunction(
 | 
						|
            function($key, $query) use ($value) {
 | 
						|
                $query = $query->getQuery();
 | 
						|
                return $query == $value;
 | 
						|
            }
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param \Closure $filterFunction
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function removeFilterByFunction($filterFunction)
 | 
						|
    {
 | 
						|
        $queries = $this->queryToBuild->getFilterQueries();
 | 
						|
        foreach($queries as $key =>  $query) {
 | 
						|
            $canBeRemoved = $filterFunction($key, $query);
 | 
						|
            if($canBeRemoved) {
 | 
						|
                unset($queries[$key]);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        $this->queryToBuild->setFilterQueries($queries);
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Passes the alternative query to the Query
 | 
						|
     * @param string $query
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useAlternativeQuery(string $query)
 | 
						|
    {
 | 
						|
        $this->queryToBuild->getEDisMax()->setQueryAlternative($query);
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Remove the alternative query from the Query.
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function removeAlternativeQuery()
 | 
						|
    {
 | 
						|
        $this->queryToBuild->getEDisMax()->setQueryAlternative(null);
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Applies a custom Faceting configuration to the query.
 | 
						|
     *
 | 
						|
     * @param Faceting $faceting
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useFaceting(Faceting $faceting)
 | 
						|
    {
 | 
						|
        return $faceting->build($this);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param FieldCollapsing $fieldCollapsing
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useFieldCollapsing(FieldCollapsing $fieldCollapsing)
 | 
						|
    {
 | 
						|
        return $fieldCollapsing->build($this);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Applies a custom initialized grouping to the query.
 | 
						|
     *
 | 
						|
     * @param Grouping $grouping
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useGrouping(Grouping $grouping)
 | 
						|
    {
 | 
						|
        return $grouping->build($this);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param Highlighting $highlighting
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useHighlighting(Highlighting $highlighting)
 | 
						|
    {
 | 
						|
        return $highlighting->build($this);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param boolean $debugMode
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useDebug($debugMode)
 | 
						|
    {
 | 
						|
        if (!$debugMode) {
 | 
						|
            $this->queryToBuild->addParam('debugQuery', null);
 | 
						|
            $this->queryToBuild->addParam('echoParams', null);
 | 
						|
            return $this;
 | 
						|
        }
 | 
						|
 | 
						|
        $this->queryToBuild->addParam('debugQuery', 'true');
 | 
						|
        $this->queryToBuild->addParam('echoParams', 'all');
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param Elevation $elevation
 | 
						|
     * @return QueryBuilder
 | 
						|
     */
 | 
						|
    public function useElevation(Elevation $elevation)
 | 
						|
    {
 | 
						|
        return $elevation->build($this);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param Spellchecking $spellchecking
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useSpellchecking(Spellchecking $spellchecking)
 | 
						|
    {
 | 
						|
        return $spellchecking->build($this);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Applies a custom configured PhraseFields to the query.
 | 
						|
     *
 | 
						|
     * @param PhraseFields $phraseFields
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function usePhraseFields(PhraseFields $phraseFields)
 | 
						|
    {
 | 
						|
        return $phraseFields->build($this);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Applies a custom configured BigramPhraseFields to the query.
 | 
						|
     *
 | 
						|
     * @param BigramPhraseFields $bigramPhraseFields
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useBigramPhraseFields(BigramPhraseFields $bigramPhraseFields)
 | 
						|
    {
 | 
						|
        return $bigramPhraseFields->build($this);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Applies a custom configured TrigramPhraseFields to the query.
 | 
						|
     *
 | 
						|
     * @param TrigramPhraseFields $trigramPhraseFields
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function useTrigramPhraseFields(TrigramPhraseFields $trigramPhraseFields)
 | 
						|
    {
 | 
						|
        return $trigramPhraseFields->build($this);
 | 
						|
    }
 | 
						|
}
 |