first commit

This commit is contained in:
Sven Wappler
2021-04-17 00:26:33 +02:00
commit 866c63cc63
813 changed files with 100696 additions and 0 deletions

View File

@@ -0,0 +1,46 @@
<?php
namespace WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder;
/***************************************************************
* 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!
***************************************************************/
abstract class AbstractDeactivatable {
/**
* @var bool
*/
protected $isEnabled = false;
/**
* @return boolean
*/
public function getIsEnabled()
{
return $this->isEnabled;
}
/**
* @param boolean $isEnabled
*/
public function setIsEnabled($isEnabled)
{
$this->isEnabled = $isEnabled;
}
}

View File

@@ -0,0 +1,115 @@
<?php
namespace WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder;
/***************************************************************
* Copyright notice
*
* (c) 2010-2017 dkd Internet Service GmbH <solr-support@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 TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* The AbstractFieldList class
*/
abstract class AbstractFieldList extends AbstractDeactivatable
{
/**
* @var array
*/
protected $fieldList = [];
/**
* Parameter key which should be used for Apache Solr URL query
*
* @var string
*/
protected $parameterKey = '';
/**
* FieldList parameter builder constructor.
*
* @param array $fieldList
*/
public function __construct($isEnabled, array $fieldList = [])
{
$this->isEnabled = $isEnabled;
$this->fieldList = $fieldList;
}
/**
* @param string $fieldListString
* @param string $delimiter
* @return array
*/
protected static function buildFieldList(string $fieldListString, string $delimiter):array
{
$fields = GeneralUtility::trimExplode($delimiter, $fieldListString, true);
$fieldList = [];
foreach ($fields as $field) {
$fieldNameAndBoost = explode('^', $field);
$boost = 1.0;
if (isset($fieldNameAndBoost[1])) {
$boost = floatval($fieldNameAndBoost[1]);
}
$fieldName = $fieldNameAndBoost[0];
$fieldList[$fieldName] = $boost;
}
return $fieldList;
}
/**
* @param string $fieldName
* @param float $boost
*
* @return AbstractFieldList
*/
public function add(string $fieldName, float $boost = 1.0): AbstractFieldList
{
$this->fieldList[$fieldName] = (float)$boost;
return $this;
}
/**
* Creates the string representation
*
* @param string $delimiter
* @return string
*/
public function toString(string $delimiter = ' ')
{
$fieldListString = '';
foreach ($this->fieldList as $fieldName => $fieldBoost) {
$fieldListString .= $fieldName;
if ($fieldBoost != 1.0) {
$fieldListString .= '^' . number_format($fieldBoost, 1, '.', '');
}
$fieldListString .= $delimiter;
}
return rtrim($fieldListString, $delimiter);
}
}

View File

@@ -0,0 +1,95 @@
<?php
namespace WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder;
/***************************************************************
* Copyright notice
*
* (c) 2010-2017 dkd Internet Service GmbH <solr-support@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\AbstractQueryBuilder;
use WapplerSystems\Meilisearch\System\Configuration\TypoScriptConfiguration;
/**
* The BigramPhraseFields class
*/
class BigramPhraseFields extends AbstractFieldList implements ParameterBuilder
{
/**
* Parameter key which should be used for Apache Solr URL query
*
* @var string
*/
protected $parameterKey = 'pf2';
/**
* Parses the string representation of the fieldList (e.g. content^100, title^10) to the object representation.
*
* @param string $fieldListString
* @param string $delimiter
* @return BigramPhraseFields
*/
public static function fromString(string $fieldListString, string $delimiter = ',') : BigramPhraseFields
{
return self::initializeFromString($fieldListString, $delimiter);
}
/**
* @param TypoScriptConfiguration $solrConfiguration
* @return BigramPhraseFields
*/
public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration)
{
$isEnabled = $solrConfiguration->getBigramPhraseSearchIsEnabled();
if (!$isEnabled) {
return new BigramPhraseFields(false);
}
return self::fromString((string)$solrConfiguration->getSearchQueryBigramPhraseFields());
}
/**
* Parses the string representation of the fieldList (e.g. content^100, title^10) to the object representation.
*
* @param string $fieldListString
* @param string $delimiter
* @return BigramPhraseFields
*/
protected static function initializeFromString(string $fieldListString, string $delimiter = ',') : BigramPhraseFields
{
$fieldList = self::buildFieldList($fieldListString, $delimiter);
return new BigramPhraseFields(true, $fieldList);
}
/**
* @param AbstractQueryBuilder $parentBuilder
* @return AbstractQueryBuilder
*/
public function build(AbstractQueryBuilder $parentBuilder): AbstractQueryBuilder
{
$bigramPhraseFieldsString = $this->toString();
if ($bigramPhraseFieldsString === '' || !$this->getIsEnabled()) {
return $parentBuilder;
}
$parentBuilder->getQuery()->getEDisMax()->setPhraseBigramFields($bigramPhraseFieldsString);
return $parentBuilder;
}
}

View File

@@ -0,0 +1,139 @@
<?php
namespace WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder;
/***************************************************************
* Copyright notice
*
* (c) 2018 <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\AbstractQueryBuilder;
use WapplerSystems\Meilisearch\System\Configuration\TypoScriptConfiguration;
/**
* The Elevation ParameterProvider is responsible to build the solr query parameters
* that are needed for the elevation.
*/
class Elevation extends AbstractDeactivatable implements ParameterBuilder
{
/**
* @var bool
*/
protected $isForced = true;
/**
* @var bool
*/
protected $markElevatedResults = true;
/**
* Elevation constructor.
* @param boolean $isEnabled
* @param boolean $isForced
* @param boolean $markElevatedResults
*/
public function __construct($isEnabled = false, $isForced = true, $markElevatedResults = true)
{
$this->isEnabled = $isEnabled;
$this->isForced = $isForced;
$this->markElevatedResults = $markElevatedResults;
}
/**
* @return boolean
*/
public function getIsForced(): bool
{
return $this->isForced;
}
/**
* @param boolean $isForced
*/
public function setIsForced(bool $isForced)
{
$this->isForced = $isForced;
}
/**
* @return boolean
*/
public function getMarkElevatedResults(): bool
{
return $this->markElevatedResults;
}
/**
* @param boolean $markElevatedResults
*/
public function setMarkElevatedResults(bool $markElevatedResults)
{
$this->markElevatedResults = $markElevatedResults;
}
/**
* @param TypoScriptConfiguration $solrConfiguration
* @return Elevation
*/
public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration)
{
$isEnabled = $solrConfiguration->getSearchElevation();
if (!$isEnabled) {
return new Elevation(false);
}
$force = $solrConfiguration->getSearchElevationForceElevation();
$markResults = $solrConfiguration->getSearchElevationMarkElevatedResults();
return new Elevation(true, $force, $markResults);
}
/**
* @return Elevation
*/
public static function getEmpty()
{
return new Elevation(false);
}
/**
* @param AbstractQueryBuilder $parentBuilder
* @return AbstractQueryBuilder
*/
public function build(AbstractQueryBuilder $parentBuilder): AbstractQueryBuilder
{
$query = $parentBuilder->getQuery();
if (!$this->getIsEnabled()) {
$query->addParam('enableElevation', null);
$query->addParam('forceElevation', null);
$query->removeField('isElevated:[elevated]');
return $parentBuilder;
}
$query->addParam('enableElevation', 'true');
$forceElevationString = $this->getIsForced() ? 'true' : 'false';
$query->addParam('forceElevation', $forceElevationString);
if ($this->getMarkElevatedResults()) {
$query->addField('isElevated:[elevated]');
}
return $parentBuilder;
}
}

View File

@@ -0,0 +1,282 @@
<?php
namespace WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder;
/***************************************************************
* 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\AbstractQueryBuilder;
use WapplerSystems\Meilisearch\Domain\Search\Query\QueryBuilder;
use WapplerSystems\Meilisearch\Domain\Search\ResultSet\Facets\SortingExpression;
use WapplerSystems\Meilisearch\System\Configuration\TypoScriptConfiguration;
/**
* The Faceting ParameterProvider is responsible to build the solr query parameters
* that are needed for the highlighting.
*/
class Faceting extends AbstractDeactivatable implements ParameterBuilder
{
/**
* @var string
*/
protected $sorting = '';
/**
* @var int
*/
protected $minCount = 1;
/**
* @var int
*/
protected $limit = 10;
/**
* @var array
*/
protected $fields = [];
/**
* @var array
*/
protected $additionalParameters = [];
/**
* Faceting constructor.
*
* @param bool $isEnabled
* @param string $sorting
* @param int $minCount
* @param int $limit
* @param array $fields
* @param array $additionalParameters
*/
public function __construct($isEnabled, $sorting = '', $minCount = 1, $limit = 10, $fields = [], $additionalParameters = [])
{
$this->isEnabled = $isEnabled;
$this->sorting = $sorting;
$this->minCount = $minCount;
$this->limit = $limit;
$this->fields = $fields;
$this->additionalParameters = $additionalParameters;
}
/**
* @return string
*/
public function getSorting()
{
return $this->sorting;
}
/**
* @param string $sorting
*/
public function setSorting($sorting)
{
$this->sorting = $sorting;
}
/**
* @return int
*/
public function getMinCount()
{
return $this->minCount;
}
/**
* @param int $minCount
*/
public function setMinCount($minCount)
{
$this->minCount = $minCount;
}
/**
* @return mixed
*/
public function getLimit()
{
return $this->limit;
}
/**
* @param mixed $limit
*/
public function setLimit($limit)
{
$this->limit = $limit;
}
/**
* @return array
*/
public function getFields()
{
return $this->fields;
}
/**
* @param array $fields
*/
public function setFields(array $fields)
{
$this->fields = $fields;
}
/**
* @param string $fieldName
*/
public function addField($fieldName)
{
$this->fields[] = $fieldName;
}
/**
* @return array
*/
public function getAdditionalParameters(): array
{
return $this->additionalParameters;
}
/**
* @param array $additionalParameters
*/
public function setAdditionalParameters(array $additionalParameters)
{
$this->additionalParameters = $additionalParameters;
}
/**
* @param array $value
*/
public function addAdditionalParameter($key, $value)
{
$this->additionalParameters[$key] = $value;
}
/**
* Reads the facet sorting configuration and applies it to the queryParameters.
*
* @param array $facetParameters
* @return array
*/
protected function applySorting(array $facetParameters)
{
$sortingExpression = new SortingExpression();
$globalSortingExpression = $sortingExpression->getForFacet($this->sorting);
if (!empty($globalSortingExpression)) {
$facetParameters['facet.sort'] = $globalSortingExpression;
}
return $facetParameters;
}
/**
* @param TypoScriptConfiguration $solrConfiguration
* @return Faceting
*/
public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration)
{
$isEnabled = $solrConfiguration->getSearchFaceting();
if (!$isEnabled) {
return new Faceting(false);
}
$minCount = $solrConfiguration->getSearchFacetingMinimumCount();
$limit = $solrConfiguration->getSearchFacetingFacetLimit();
$sorting = $solrConfiguration->getSearchFacetingSortBy();
return new Faceting($isEnabled, $sorting, $minCount, $limit);
}
/**
* @return Faceting
*/
public static function getEmpty()
{
return new Faceting(false);
}
/**
* Retrieves all parameters that are required for faceting.
*
* @return array
*/
protected function getFacetParameters() {
$facetParameters = [];
$facetParameters['facet'] = 'true';
$facetParameters['facet.mincount'] = $this->getMinCount();
$facetParameters['facet.limit'] = $this->getLimit();
$facetParameters['facet.field'] = $this->getFields();
foreach ($this->getAdditionalParameters() as $additionalParameterKey => $additionalParameterValue) {
$facetParameters[$additionalParameterKey] = $additionalParameterValue;
}
if ($facetParameters['json.facet']) {
$facetParameters['json.facet'] = json_encode($facetParameters['json.facet']);
}
$facetParameters = $this->applySorting($facetParameters);
return $facetParameters;
}
/**
* @param AbstractQueryBuilder $parentBuilder
* @return QueryBuilder
*/
public function build(AbstractQueryBuilder $parentBuilder): AbstractQueryBuilder
{
$query = $parentBuilder->getQuery();
if (!$this->getIsEnabled()) {
//@todo use unset functionality when present
$query->addParam('facet', null);
$query->addParam('lex', null);
$query->addParam('json.mincount', null);
$query->addParam('json.limit', null);
$query->addParam('json.field', null);
$query->addParam('facet.sort', null);
$params = $query->getParams();
foreach($params as $key => $value) {
if (strpos($key, 'f.') !== false) {
$query->addParam($key, null);
}
}
return $parentBuilder;
}
//@todo check of $this->queryToBuilder->getFacetSet() can be used
$facetingParameters = $this->getFacetParameters();
foreach($facetingParameters as $key => $value) {
$query->addParam($key, $value);
}
return $parentBuilder;
}
}

View File

@@ -0,0 +1,159 @@
<?php
namespace WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder;
/***************************************************************
* 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\AbstractQueryBuilder;
use WapplerSystems\Meilisearch\System\Configuration\TypoScriptConfiguration;
/**
* The FieldCollapsing ParameterProvider is responsible to build the solr query parameters
* that are needed for the field collapsing.
*/
class FieldCollapsing extends AbstractDeactivatable implements ParameterBuilder
{
/**
* @var string
*/
protected $collapseFieldName = 'variantId';
/**
* @var bool
*/
protected $expand = false;
/**
* @var int
*/
protected $expandRowCount = 10;
/**
* FieldCollapsing constructor.
* @param bool $isEnabled
* @param string $collapseFieldName
* @param bool $expand
* @param int $expandRowCount
*/
public function __construct($isEnabled, $collapseFieldName = 'variantId', $expand = false, $expandRowCount = 10)
{
$this->isEnabled = $isEnabled;
$this->collapseFieldName = $collapseFieldName;
$this->expand = $expand;
$this->expandRowCount = $expandRowCount;
}
/**
* @return string
*/
public function getCollapseFieldName(): string
{
return $this->collapseFieldName;
}
/**
* @param string $collapseFieldName
*/
public function setCollapseFieldName(string $collapseFieldName)
{
$this->collapseFieldName = $collapseFieldName;
}
/**
* @return boolean
*/
public function getIsExpand(): bool
{
return $this->expand;
}
/**
* @param boolean $expand
*/
public function setExpand(bool $expand)
{
$this->expand = $expand;
}
/**
* @return int
*/
public function getExpandRowCount(): int
{
return $this->expandRowCount;
}
/**
* @param int $expandRowCount
*/
public function setExpandRowCount(int $expandRowCount)
{
$this->expandRowCount = $expandRowCount;
}
/**
* @param TypoScriptConfiguration $solrConfiguration
* @return FieldCollapsing
*/
public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration)
{
$isEnabled = $solrConfiguration->getSearchVariants();
if (!$isEnabled) {
return new FieldCollapsing(false);
}
$collapseField = $solrConfiguration->getSearchVariantsField();
$expand = (bool)$solrConfiguration->getSearchVariantsExpand();
$expandRows = $solrConfiguration->getSearchVariantsLimit();
return new FieldCollapsing(true, $collapseField, $expand, $expandRows);
}
/**
* @return FieldCollapsing
*/
public static function getEmpty()
{
return new FieldCollapsing(false);
}
/**
* @param AbstractQueryBuilder $parentBuilder
* @return AbstractQueryBuilder
*/
public function build(AbstractQueryBuilder $parentBuilder): AbstractQueryBuilder
{
$query = $parentBuilder->getQuery();
if(!$this->getIsEnabled()) {
return $parentBuilder;
}
$parentBuilder->useFilter('{!collapse field=' . $this->getCollapseFieldName(). '}', 'fieldCollapsing');
if($this->getIsExpand()) {
$query->addParam('expand', 'true');
$query->addParam('expand.rows', $this->getExpandRowCount());
}
return $parentBuilder;
}
}

View File

@@ -0,0 +1,158 @@
<?php
namespace WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder;
/***************************************************************
* 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\System\Configuration\TypoScriptConfiguration;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* The Filters ParameterProvider is responsible to build the solr query parameters
* that are needed for the filtering.
*/
class Filters
{
/**
* @var array
*/
protected $filters = [];
/**
* Removes a filter on a field
*
* @param string $filterFieldName The field name the filter should be removed for
* @return void
*/
public function removeByFieldName($filterFieldName)
{
$this->removeByPrefix($filterFieldName . ':');
}
/**
* @param string $filterFieldName
*/
public function removeByPrefix($filterFieldName)
{
foreach ($this->filters as $key => $filterString) {
if (GeneralUtility::isFirstPartOfStr($filterString, $filterFieldName)) {
unset($this->filters[$key]);
}
}
}
/**
* Removes a filter based on name of filter array
*
* @param string $name name of the filter
*/
public function removeByName($name)
{
unset($this->filters[$name]);
}
/**
* @param string $filterString
* @param string $name
*/
public function add($filterString, $name = '')
{
if ($name !== '') {
$this->filters[$name] = $filterString;
} else {
$this->filters[] = $filterString;
}
}
/**
* Add's multiple filters to the filter collection.
*
* @param array $filterArray
* @return Filters
*/
public function addMultiple($filterArray)
{
foreach($filterArray as $key => $value) {
if (!$this->hasWithName($key)) {
$this->add($value, $key);
}
}
return $this;
}
/**
* @param string $name
* @return bool
*/
public function hasWithName($name)
{
return array_key_exists($name, $this->filters);
}
/**
* Removes a filter by the filter value. The value has the following format:
*
* "fieldname:value"
*
* @param string $filterString The filter to remove, in the form of field:value
*/
public function removeByValue($filterString)
{
$key = array_search($filterString, $this->filters);
if ($key === false) {
// value not found, nothing to do
return;
}
unset($this->filters[$key]);
}
/**
* Gets all currently applied filters.
*
* @return array Array of filters
*/
public function getValues()
{
return $this->filters;
}
/**
* @param TypoScriptConfiguration $solrConfiguration
* @return Filters
*/
public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration)
{
return new Filters();
}
/**
* @return Filters
*/
public static function getEmpty()
{
return new Filters();
}
}

View File

@@ -0,0 +1,254 @@
<?php
namespace WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder;
/***************************************************************
* 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\AbstractQueryBuilder;
use WapplerSystems\Meilisearch\System\Configuration\TypoScriptConfiguration;
/**
* The Grouping ParameterProvider is responsible to build the solr query parameters
* that are needed for the grouping.
*/
class Grouping extends AbstractDeactivatable implements ParameterBuilder
{
/**
* @var array
*/
protected $fields = [];
/**
* @var array
*/
protected $sortings = [];
/**
* @var array
*/
protected $queries = [];
/**
* @var int
*/
protected $numberOfGroups = 5;
/**
* @var int
*/
protected $resultsPerGroup = 1;
/**
* Grouping constructor.
*
* @param bool $isEnabled
* @param array $fields
* @param array $sortings
* @param array $queries
* @param int $numberOfGroups
* @param int $resultsPerGroup
*/
public function __construct($isEnabled, array $fields = [], array $sortings = [], array $queries = [], $numberOfGroups = 5, $resultsPerGroup = 1)
{
$this->isEnabled = $isEnabled;
$this->fields = $fields;
$this->sortings = $sortings;
$this->queries = $queries;
$this->numberOfGroups = $numberOfGroups;
$this->resultsPerGroup = $resultsPerGroup;
}
/**
* @return array
*/
public function getFields()
{
return $this->fields;
}
/**
* @param array $fields
*/
public function setFields(array $fields)
{
$this->fields = $fields;
}
/**
* @param string $field
*/
public function addField(string $field)
{
$this->fields[] = $field;
}
/**
* @return array
*/
public function getSortings()
{
return $this->sortings;
}
/**
* @param string $sorting
*/
public function addSorting($sorting)
{
$this->sortings[] = $sorting;
}
/**
* @param array $sortings
*/
public function setSortings(array $sortings)
{
$this->sortings = $sortings;
}
/**
* @return array
*/
public function getQueries(): array
{
return $this->queries;
}
/**
* @param string $query
*/
public function addQuery($query)
{
$this->queries[] = $query;
}
/**
* @param array $queries
*/
public function setQueries(array $queries)
{
$this->queries = $queries;
}
/**
* @return int
*/
public function getNumberOfGroups()
{
return $this->numberOfGroups;
}
/**
* @param int $numberOfGroups
*/
public function setNumberOfGroups($numberOfGroups)
{
$this->numberOfGroups = $numberOfGroups;
}
/**
* @return int
*/
public function getResultsPerGroup()
{
return $this->resultsPerGroup;
}
/**
* @param int $resultsPerGroup
*/
public function setResultsPerGroup($resultsPerGroup)
{
$resultsPerGroup = max(intval($resultsPerGroup), 0);
$this->resultsPerGroup = $resultsPerGroup;
}
/**
* @param TypoScriptConfiguration $solrConfiguration
* @return Grouping
*/
public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration)
{
$isEnabled = $solrConfiguration->getSearchGrouping();
if (!$isEnabled) {
return new Grouping(false);
}
$fields = [];
$queries = [];
$sortings = [];
$resultsPerGroup = $solrConfiguration->getSearchGroupingHighestGroupResultsLimit();
$configuredGroups = $solrConfiguration->getSearchGroupingGroupsConfiguration();
$numberOfGroups = $solrConfiguration->getSearchGroupingNumberOfGroups();
$sortBy = $solrConfiguration->getSearchGroupingSortBy();
foreach ($configuredGroups as $groupName => $groupConfiguration) {
if (isset($groupConfiguration['field'])) {
$fields[] = $groupConfiguration['field'];
} elseif (isset($groupConfiguration['query'])) {
$queries[] = $groupConfiguration['query'];
}
}
if (!empty(trim($sortBy))) {
$sortings[] = $sortBy;
}
return new Grouping($isEnabled, $fields, $sortings, $queries, $numberOfGroups, $resultsPerGroup);
}
/**
* @return Grouping
*/
public static function getEmpty()
{
return new Grouping(false);
}
/**
* @param AbstractQueryBuilder $parentBuilder
* @return AbstractQueryBuilder
*/
public function build(AbstractQueryBuilder $parentBuilder): AbstractQueryBuilder
{
$query = $parentBuilder->getQuery();
if(!$this->getIsEnabled()) {
$query->removeComponent($query->getGrouping());
return $parentBuilder;
}
$query->getGrouping()->setFields($this->getFields());
$query->getGrouping()->setLimit($this->getResultsPerGroup());
$query->getGrouping()->setQueries($this->getQueries());
$query->getGrouping()->setFormat('grouped');
$query->getGrouping()->setNumberOfGroups(true);
$query->setRows($this->getNumberOfGroups());
$sorting = implode(' ', $this->getSortings());
$query->getGrouping()->setSort($sorting);
return $parentBuilder;
}
}

View File

@@ -0,0 +1,211 @@
<?php
namespace WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder;
/***************************************************************
* 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\AbstractQueryBuilder;
use WapplerSystems\Meilisearch\Domain\Search\Query\QueryBuilder;
use WapplerSystems\Meilisearch\System\Configuration\TypoScriptConfiguration;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* The Highlighting ParameterProvider is responsible to build the solr query parameters
* that are needed for the highlighting.
*/
class Highlighting extends AbstractDeactivatable implements ParameterBuilder
{
/**
* @var int
*/
protected $fragmentSize = 200;
/**
* @var string
*/
protected $highlightingFieldList = '';
/**
* @var string
*/
protected $prefix = '';
/**
* @var string
*/
protected $postfix = '';
/**
* Highlighting constructor.
*
* @param bool $isEnabled
* @param int $fragmentSize
* @param string $highlightingFieldList
* @param string $prefix
* @param string $postfix
*/
public function __construct($isEnabled = false, $fragmentSize = 200, $highlightingFieldList = '', $prefix = '', $postfix = '')
{
$this->isEnabled = $isEnabled;
$this->fragmentSize = $fragmentSize;
$this->highlightingFieldList = $highlightingFieldList;
$this->prefix = $prefix;
$this->postfix = $postfix;
}
/**
* @return int
*/
public function getFragmentSize(): int
{
return $this->fragmentSize;
}
/**
* @param int $fragmentSize
*/
public function setFragmentSize(int $fragmentSize)
{
$this->fragmentSize = $fragmentSize;
}
/**
* @return string
*/
public function getHighlightingFieldList(): string
{
return $this->highlightingFieldList;
}
/**
* @param string $highlightingFieldList
*/
public function setHighlightingFieldList(string $highlightingFieldList)
{
$this->highlightingFieldList = $highlightingFieldList;
}
/**
* @return string
*/
public function getPrefix(): string
{
return $this->prefix;
}
/**
* @param string $prefix
*/
public function setPrefix(string $prefix)
{
$this->prefix = $prefix;
}
/**
* @return string
*/
public function getPostfix(): string
{
return $this->postfix;
}
/**
* @param string $postfix
*/
public function setPostfix(string $postfix)
{
$this->postfix = $postfix;
}
/**
* @return bool
*/
public function getUseFastVectorHighlighter()
{
return ($this->fragmentSize >= 18);
}
/**
* @param TypoScriptConfiguration $solrConfiguration
* @return Highlighting
*/
public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration)
{
$isEnabled = $solrConfiguration->getSearchResultsHighlighting();
if (!$isEnabled) {
return new Highlighting(false);
}
$fragmentSize = $solrConfiguration->getSearchResultsHighlightingFragmentSize();
$highlightingFields = $solrConfiguration->getSearchResultsHighlightingFields();
$wrap = explode('|', $solrConfiguration->getSearchResultsHighlightingWrap());
$prefix = isset($wrap[0]) ? $wrap[0] : '';
$postfix = isset($wrap[1]) ? $wrap[1] : '';
return new Highlighting($isEnabled, $fragmentSize, $highlightingFields, $prefix, $postfix);
}
/**
* @return Highlighting
*/
public static function getEmpty()
{
return new Highlighting(false);
}
/**
* @param AbstractQueryBuilder $parentBuilder
* @return AbstractQueryBuilder
*/
public function build(AbstractQueryBuilder $parentBuilder): AbstractQueryBuilder
{
$query = $parentBuilder->getQuery();
if(!$this->getIsEnabled()) {
$query->removeComponent($query->getHighlighting());
return $parentBuilder;
}
$query->getHighlighting()->setFragSize($this->getFragmentSize());
$query->getHighlighting()->setFields(GeneralUtility::trimExplode(",", $this->getHighlightingFieldList()));
if ($this->getUseFastVectorHighlighter()) {
$query->getHighlighting()->setUseFastVectorHighlighter(true);
$query->getHighlighting()->setTagPrefix($this->getPrefix());
$query->getHighlighting()->setTagPostfix($this->getPostfix());
} else {
$query->getHighlighting()->setUseFastVectorHighlighter(false);
$query->getHighlighting()->setTagPrefix('');
$query->getHighlighting()->setTagPostfix('');
}
if ($this->getPrefix() !== '' && $this->getPostfix() !== '') {
$query->getHighlighting()->setSimplePrefix($this->getPrefix());
$query->getHighlighting()->setSimplePostfix($this->getPostfix());
}
return $parentBuilder;
}
}

View File

@@ -0,0 +1,106 @@
<?php
namespace WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder;
/***************************************************************
* 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!
***************************************************************/
/**
* The Operator ParameterProvider is responsible to build the solr query parameters
* that are needed for the operator q.op.
*/
class Operator extends AbstractDeactivatable
{
const OPERATOR_AND = 'AND';
const OPERATOR_OR = 'OR';
/**
* @var string
*/
protected $operator = 'AND';
/**
* Faceting constructor.
*
* @param bool $isEnabled
* @param string $operator
*/
public function __construct($isEnabled, $operator = Operator::OPERATOR_AND)
{
$this->isEnabled = $isEnabled;
$this->setOperator($operator);
}
/**
* @param string $operator
*/
public function setOperator($operator)
{
if (!in_array($operator, [self::OPERATOR_AND, self::OPERATOR_OR])) {
throw new \InvalidArgumentException("Invalid operator");
}
$this->operator = $operator;
}
/**
* @return string
*/
public function getOperator(): string
{
return $this->operator;
}
/**
* @return Operator
*/
public static function getEmpty(): Operator
{
return new Operator(false);
}
/**
* @return Operator
*/
public static function getAnd(): Operator
{
return new Operator(true, static::OPERATOR_AND);
}
/**
* @return Operator
*/
public static function getOr(): Operator
{
return new Operator(true, static::OPERATOR_OR);
}
/**
* @param string $operator
* @return Operator
*/
public static function fromString($operator)
{
return new Operator(true, $operator);
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder;
/***************************************************************
* 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\AbstractQueryBuilder;
/**
* The implementation of ParameterBuilder is responsible to build an array with
* the query parameter that are needed for solr
*
* Interface ParameterProvider
*/
interface ParameterBuilder {
/**
* @param AbstractQueryBuilder $parentBuilder
* @return AbstractQueryBuilder
*/
public function build(AbstractQueryBuilder $parentBuilder): AbstractQueryBuilder;
}

View File

@@ -0,0 +1,95 @@
<?php
namespace WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder;
/***************************************************************
* Copyright notice
*
* (c) 2010-2017 dkd Internet Service GmbH <solr-support@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\AbstractQueryBuilder;
use WapplerSystems\Meilisearch\System\Configuration\TypoScriptConfiguration;
/**
* The PhraseFields class
*/
class PhraseFields extends AbstractFieldList implements ParameterBuilder
{
/**
* Parameter key which should be used for Apache Solr URL query
*
* @var string
*/
protected $parameterKey = 'pf';
/**
* Parses the string representation of the fieldList (e.g. content^100, title^10) to the object representation.
*
* @param string $fieldListString
* @param string $delimiter
* @return PhraseFields
*/
public static function fromString(string $fieldListString, string $delimiter = ',') : PhraseFields
{
return self::initializeFromString($fieldListString, $delimiter);
}
/**
* @param TypoScriptConfiguration $solrConfiguration
* @return PhraseFields
*/
public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration)
{
$isEnabled = $solrConfiguration->getPhraseSearchIsEnabled();
if (!$isEnabled) {
return new PhraseFields(false);
}
return self::fromString((string)$solrConfiguration->getSearchQueryPhraseFields());
}
/**
* Parses the string representation of the fieldList (e.g. content^100, title^10) to the object representation.
*
* @param string $fieldListString
* @param string $delimiter
* @return PhraseFields
*/
protected static function initializeFromString(string $fieldListString, string $delimiter = ',') : PhraseFields
{
$fieldList = self::buildFieldList($fieldListString, $delimiter);
return new PhraseFields(true, $fieldList);
}
/**
* @param AbstractQueryBuilder $parentBuilder
* @return AbstractQueryBuilder
*/
public function build(AbstractQueryBuilder $parentBuilder): AbstractQueryBuilder
{
$phraseFieldString = $this->toString();
if ($phraseFieldString === '' || !$this->getIsEnabled()) {
return $parentBuilder;
}
$parentBuilder->getQuery()->getEDisMax()->setPhraseFields($phraseFieldString);
return $parentBuilder;
}
}

View File

@@ -0,0 +1,117 @@
<?php
namespace WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder;
/***************************************************************
* 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\AbstractQueryBuilder;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* The QueryFields class holds all information for the query which fields should be used to query (Solr qf parameter).
*/
class QueryFields implements ParameterBuilder
{
/**
* @var array
*/
protected $queryFields = [];
/**
* QueryFields constructor.
*
* @param array $queryFields
*/
public function __construct(array $queryFields = [])
{
$this->queryFields = $queryFields;
}
/**
* @param string $fieldName
* @param float $boost
*/
public function set($fieldName, $boost = 1.0)
{
$this->queryFields[$fieldName] = (float)$boost;
}
/**
* Creates the string representation
*
* @param string $delimiter
* @return string
*/
public function toString($delimiter = ' ') {
$queryFieldString = '';
foreach ($this->queryFields as $fieldName => $fieldBoost) {
$queryFieldString .= $fieldName;
if ($fieldBoost != 1.0) {
$queryFieldString .= '^' . number_format($fieldBoost, 1, '.', '');
}
$queryFieldString .= $delimiter;
}
return rtrim($queryFieldString, $delimiter);
}
/**
* Parses the string representation of the queryFields (e.g. content^100, title^10) to the object representation.
*
* @param string $queryFieldsString
* @param string $delimiter
* @return QueryFields
*/
public static function fromString($queryFieldsString, $delimiter = ',') {
$fields = GeneralUtility::trimExplode($delimiter, $queryFieldsString, true);
$queryFields = [];
foreach ($fields as $field) {
$fieldNameAndBoost = explode('^', $field);
$boost = 1.0;
if (isset($fieldNameAndBoost[1])) {
$boost = floatval($fieldNameAndBoost[1]);
}
$fieldName = $fieldNameAndBoost[0];
$queryFields[$fieldName] = $boost;
}
return new QueryFields($queryFields);
}
/**
* @param AbstractQueryBuilder $parentBuilder
* @return AbstractQueryBuilder
*/
public function build(AbstractQueryBuilder $parentBuilder): AbstractQueryBuilder
{
$parentBuilder->getQuery()->getEDisMax()->setQueryFields($this->toString());
return $parentBuilder;
}
}

View File

@@ -0,0 +1,128 @@
<?php
namespace WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder;
/***************************************************************
* 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\AbstractQueryBuilder;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* The ReturnFields class is responsible to hold a list of field names that should be returned from
* solr.
*/
class ReturnFields implements ParameterBuilder
{
/**
* @var array
*/
protected $fieldList = [];
/**
* FieldList constructor.
*
* @param array $fieldList
*/
public function __construct(array $fieldList = [])
{
$this->fieldList = $fieldList;
}
/**
* Adds a field to the list of fields to return. Also checks whether * is
* set for the fields, if so it's removed from the field list.
*
* @param string $fieldName Name of a field to return in the result documents
*/
public function add($fieldName)
{
if (strpos($fieldName, '[') === false && strpos($fieldName, ']') === false && in_array('*', $this->fieldList)) {
$this->fieldList = array_diff($this->fieldList, ['*']);
}
$this->fieldList[] = $fieldName;
}
/**
* Removes a field from the list of fields to return (fl parameter).
*
* @param string $fieldName Field to remove from the list of fields to return
*/
public function remove($fieldName)
{
$key = array_search($fieldName, $this->fieldList);
if ($key !== false) {
unset($this->fieldList[$key]);
}
}
/**
* @param string $delimiter
* @return string
*/
public function toString($delimiter = ',')
{
return implode($delimiter, $this->fieldList);
}
/**
* @param string $fieldList
* @param string $delimiter
* @return ReturnFields
*/
public static function fromString($fieldList, $delimiter = ',')
{
$fieldListArray = GeneralUtility::trimExplode($delimiter, $fieldList);
return static::fromArray($fieldListArray);
}
/**
* @param array $fieldListArray
* @return ReturnFields
*/
public static function fromArray(array $fieldListArray)
{
return new ReturnFields($fieldListArray);
}
/**
* @return array
*/
public function getValues()
{
return array_unique(array_values($this->fieldList));
}
/**
* @param AbstractQueryBuilder $parentBuilder
* @return AbstractQueryBuilder
*/
public function build(AbstractQueryBuilder $parentBuilder): AbstractQueryBuilder
{
$parentBuilder->getQuery()->setFields($this->getValues());
return $parentBuilder;
}
}

View File

@@ -0,0 +1,257 @@
<?php
namespace WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder;
/***************************************************************
* 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\AbstractQueryBuilder;
use WapplerSystems\Meilisearch\System\Configuration\TypoScriptConfiguration;
/**
* The Slops ParameterProvider is responsible to build the solr query parameters
* that are needed for the several slop arguments.
*/
class Slops implements ParameterBuilder
{
const NO_SLOP = null;
/**
* The qs parameter
*
* @var int
*/
protected $querySlop = self::NO_SLOP;
/**
* @var int
*/
protected $phraseSlop = self::NO_SLOP;
/**
* @var int
*/
protected $bigramPhraseSlop = self::NO_SLOP;
/**
* @var int
*/
protected $trigramPhraseSlop = self::NO_SLOP;
/**
* Slops constructor.
* @param int|null $querySlop
* @param int|null $phraseSlop
* @param int|null $bigramPhraseSlop
* @param int|null $trigramPhraseSlop
*/
public function __construct($querySlop = self::NO_SLOP, $phraseSlop = self::NO_SLOP, $bigramPhraseSlop = self::NO_SLOP, $trigramPhraseSlop = self::NO_SLOP)
{
$this->querySlop = $querySlop;
$this->phraseSlop = $phraseSlop;
$this->bigramPhraseSlop = $bigramPhraseSlop;
$this->trigramPhraseSlop = $trigramPhraseSlop;
}
/**
* @return boolean
*/
public function getHasQuerySlop()
{
return $this->querySlop !== null;
}
/**
* @return int|null
*/
public function getQuerySlop()
{
return $this->querySlop;
}
/**
* @param int $querySlop
*/
public function setQuerySlop(int $querySlop)
{
$this->querySlop = $querySlop;
}
/**
* @return boolean
*/
public function getHasPhraseSlop()
{
return $this->phraseSlop !== null;
}
/**
* @return int|null
*/
public function getPhraseSlop()
{
return $this->phraseSlop;
}
/**
* @param int $phraseSlop
*/
public function setPhraseSlop(int $phraseSlop)
{
$this->phraseSlop = $phraseSlop;
}
/**
* @return boolean
*/
public function getHasBigramPhraseSlop()
{
return $this->bigramPhraseSlop !== null;
}
/**
* @return int|null
*/
public function getBigramPhraseSlop()
{
return $this->bigramPhraseSlop;
}
/**
* @param int $bigramPhraseSlop
*/
public function setBigramPhraseSlop(int $bigramPhraseSlop)
{
$this->bigramPhraseSlop = $bigramPhraseSlop;
}
/**
* @return boolean
*/
public function getHasTrigramPhraseSlop()
{
return $this->trigramPhraseSlop !== null;
}
/**
* @return int|null
*/
public function getTrigramPhraseSlop()
{
return $this->trigramPhraseSlop;
}
/**
* @param int $trigramPhraseSlop
*/
public function setTrigramPhraseSlop(int $trigramPhraseSlop)
{
$this->trigramPhraseSlop = $trigramPhraseSlop;
}
/**
* @param TypoScriptConfiguration $solrConfiguration
* @return Slops
*/
public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration)
{
$searchConfiguration = $solrConfiguration->getSearchConfiguration();
$querySlop = static::getQuerySlopFromConfiguration($searchConfiguration);
$phraseSlop = static::getPhraseSlopFromConfiguration($searchConfiguration);
$bigramPhraseSlop = static::getBigramPhraseSlopFromConfiguration($searchConfiguration);
$trigramPhraseSlop = static::getTrigramPhraseSlopFromConfiguration($searchConfiguration);
return new Slops($querySlop, $phraseSlop, $bigramPhraseSlop, $trigramPhraseSlop);
}
/**
* @param array $searchConfiguration
* @return int|null
*/
protected static function getPhraseSlopFromConfiguration($searchConfiguration)
{
$phraseEnabled = !(empty($searchConfiguration['query.']['phrase']) || $searchConfiguration['query.']['phrase'] !== 1);
$phraseSlopConfigured = !empty($searchConfiguration['query.']['phrase.']['slop']);
return ($phraseEnabled && $phraseSlopConfigured) ? $searchConfiguration['query.']['phrase.']['slop'] : self::NO_SLOP;
}
/**
* @param array $searchConfiguration
* @return int|null
*/
protected static function getQuerySlopFromConfiguration($searchConfiguration)
{
$phraseEnabled = !(empty($searchConfiguration['query.']['phrase']) || $searchConfiguration['query.']['phrase'] !== 1);
$querySlopConfigured = !empty($searchConfiguration['query.']['phrase.']['querySlop']);
return ($phraseEnabled && $querySlopConfigured) ? $searchConfiguration['query.']['phrase.']['querySlop'] : self::NO_SLOP;
}
/**
* @param array $searchConfiguration
* @return int|null
*/
protected static function getBigramPhraseSlopFromConfiguration($searchConfiguration)
{
$bigramPhraseEnabled = !empty($searchConfiguration['query.']['bigramPhrase']) && $searchConfiguration['query.']['bigramPhrase'] === 1;
$bigramSlopConfigured = !empty($searchConfiguration['query.']['bigramPhrase.']['slop']);
return ($bigramPhraseEnabled && $bigramSlopConfigured) ? $searchConfiguration['query.']['bigramPhrase.']['slop'] : self::NO_SLOP;
}
/**
* @param array $searchConfiguration
* @return int|null
*/
protected static function getTrigramPhraseSlopFromConfiguration($searchConfiguration)
{
$trigramPhraseEnabled = !empty($searchConfiguration['query.']['trigramPhrase']) && $searchConfiguration['query.']['trigramPhrase'] === 1;
$trigramSlopConfigured = !empty($searchConfiguration['query.']['trigramPhrase.']['slop']);
return ($trigramPhraseEnabled && $trigramSlopConfigured) ? $searchConfiguration['query.']['trigramPhrase.']['slop'] : self::NO_SLOP;
}
/**
* @param AbstractQueryBuilder $parentBuilder
* @return AbstractQueryBuilder
*/
public function build(AbstractQueryBuilder $parentBuilder): AbstractQueryBuilder
{
$query = $parentBuilder->getQuery();
if ($this->getHasPhraseSlop()) {
$query->getEDisMax()->setPhraseSlop($this->getPhraseSlop());
}
if ($this->getHasBigramPhraseSlop()) {
$query->getEDisMax()->setPhraseBigramSlop($this->getBigramPhraseSlop());
}
if ($this->getHasTrigramPhraseSlop()) {
$query->getEDisMax()->setPhraseTrigramSlop($this->getTrigramPhraseSlop());
}
if ($this->getHasQuerySlop()) {
$query->getEDisMax()->setQueryPhraseSlop($this->getQuerySlop());
}
return $parentBuilder;
}
}

View File

@@ -0,0 +1,112 @@
<?php
namespace WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder;
/***************************************************************
* 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 TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* The Sorting ParameterProvider is responsible to build the solr query parameters
* that are needed for the sorting.
*/
class Sorting extends AbstractDeactivatable
{
const SORT_ASC = 'ASC';
const SORT_DESC = 'DESC';
/**
* @var string
*/
protected $fieldName = '';
/**
* @var string
*/
protected $direction = self::SORT_ASC;
/**
* Debug constructor.
*
* @param bool $isEnabled
* @param string $fieldName
* @param string $direction
*/
public function __construct($isEnabled = false, $fieldName = '', $direction = self::SORT_ASC)
{
$this->isEnabled = $isEnabled;
$this->setFieldName($fieldName);
$this->setDirection($direction);
}
/**
* @return Sorting
*/
public static function getEmpty()
{
return new Sorting(false);
}
/**
* @return string
*/
public function getFieldName(): string
{
return $this->fieldName;
}
/**
* @param string $fieldName
*/
public function setFieldName(string $fieldName)
{
$this->fieldName = $fieldName;
}
/**
* @return string
*/
public function getDirection(): string
{
return $this->direction;
}
/**
* @param string $direction
*/
public function setDirection(string $direction)
{
$this->direction = $direction;
}
/**
* Parses a sorting representation "<fieldName> <direction>"
* @param string $sortingString
* @return Sorting
*/
public static function fromString($sortingString)
{
$parts = GeneralUtility::trimExplode(' ', $sortingString);
return new Sorting(true, $parts[0], $parts[1]);
}
}

View File

@@ -0,0 +1,99 @@
<?php
namespace WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder;
/***************************************************************
* 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 TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* The Sorting ParameterProvider is responsible to build the solr query parameters
* that are needed for the sorting.
*/
class Sortings extends AbstractDeactivatable
{
/**
* @var array
*/
protected $sortings = [];
/**
* Sortings constructor.
* @param bool $isEnabled
* @param array $sortings
*/
public function __construct($isEnabled = false, $sortings = [])
{
$this->isEnabled = $isEnabled;
$this->setSortings($sortings);
}
/**
* @return Sortings
*/
public static function getEmpty()
{
return new Sortings(false);
}
/**
* @return Sorting[]
*/
public function getSortings(): array
{
return $this->sortings;
}
/**
* @param array $sortings
*/
public function setSortings(array $sortings)
{
$this->sortings = $sortings;
}
/**
* @param Sorting $sorting
*/
public function addSorting(Sorting $sorting)
{
$this->sortings[] = $sorting;
}
/**
* Parses a sortings representation "<fieldName> <direction>,<fieldName> <direction>"
* @param string $sortingsString
* @return Sortings
*/
public static function fromString($sortingsString)
{
$sortFields = GeneralUtility::trimExplode(',',$sortingsString);
$sortings = [];
foreach($sortFields as $sortField) {
$sorting = Sorting::fromString($sortField);
$sortings[] = $sorting;
}
return new Sortings(true, $sortings);
}
}

View File

@@ -0,0 +1,102 @@
<?php
namespace WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder;
/***************************************************************
* 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\AbstractQueryBuilder;
use WapplerSystems\Meilisearch\System\Configuration\TypoScriptConfiguration;
/**
* The Spellchecking ParameterProvider is responsible to build the solr query parameters
* that are needed for the spellchecking.
*/
class Spellchecking extends AbstractDeactivatable implements ParameterBuilder
{
/**
* @var int
*/
protected $maxCollationTries = 0;
/**
* Spellchecking constructor.
*
* @param bool $isEnabled
* @param int $maxCollationTries
*/
public function __construct($isEnabled = false, int $maxCollationTries = 0)
{
$this->isEnabled = $isEnabled;
$this->maxCollationTries = $maxCollationTries;
}
/**
* @return int
*/
public function getMaxCollationTries(): int
{
return $this->maxCollationTries;
}
/**
* @param TypoScriptConfiguration $solrConfiguration
* @return Spellchecking
*/
public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration)
{
$isEnabled = $solrConfiguration->getSearchSpellchecking();
if (!$isEnabled) {
return new Spellchecking(false);
}
$maxCollationTries = $solrConfiguration->getSearchSpellcheckingNumberOfSuggestionsToTry();
return new Spellchecking($isEnabled, $maxCollationTries);
}
/**
* @return Spellchecking
*/
public static function getEmpty()
{
return new Spellchecking(false);
}
/**
* @param AbstractQueryBuilder $parentBuilder
* @return AbstractQueryBuilder
*/
public function build(AbstractQueryBuilder $parentBuilder): AbstractQueryBuilder
{
$query = $parentBuilder->getQuery();
if (!$this->getIsEnabled()) {
$query->removeComponent($query->getSpellcheck());
return $parentBuilder;
}
$query->getSpellcheck()->setMaxCollationTries($this->getMaxCollationTries());
$query->getSpellcheck()->setCollate(true);
return $parentBuilder;
}
}

View File

@@ -0,0 +1,94 @@
<?php
namespace WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder;
/***************************************************************
* Copyright notice
*
* (c) 2010-2017 dkd Internet Service GmbH <solr-support@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\AbstractQueryBuilder;
use WapplerSystems\Meilisearch\System\Configuration\TypoScriptConfiguration;
/**
* The TrigramPhraseFields class
*/
class TrigramPhraseFields extends AbstractFieldList implements ParameterBuilder
{
/**
* Parameter key which should be used for Apache Solr URL query
*
* @var string
*/
protected $parameterKey = 'pf3';
/**
* Parses the string representation of the fieldList (e.g. content^100, title^10) to the object representation.
*
* @param string $fieldListString
* @param string $delimiter
* @return TrigramPhraseFields
*/
public static function fromString(string $fieldListString, string $delimiter = ',') : TrigramPhraseFields
{
return self::initializeFromString($fieldListString, $delimiter);
}
/**
* @param TypoScriptConfiguration $solrConfiguration
* @return TrigramPhraseFields
*/
public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration)
{
$isEnabled = $solrConfiguration->getTrigramPhraseSearchIsEnabled();
if (!$isEnabled) {
return new TrigramPhraseFields(false);
}
return self::fromString((string)$solrConfiguration->getSearchQueryTrigramPhraseFields());
}
/**
* Parses the string representation of the fieldList (e.g. content^100, title^10) to the object representation.
*
* @param string $fieldListString
* @param string $delimiter
* @return TrigramPhraseFields
*/
protected static function initializeFromString(string $fieldListString, string $delimiter = ',') : TrigramPhraseFields
{
$fieldList = self::buildFieldList($fieldListString, $delimiter);
return new TrigramPhraseFields(true, $fieldList);
}
/**
* @param AbstractQueryBuilder $parentBuilder
* @return AbstractQueryBuilder
*/
public function build(AbstractQueryBuilder $parentBuilder): AbstractQueryBuilder
{
$trigramPhraseFieldsString = $this->toString();
if ($trigramPhraseFieldsString === '' || !$this->getIsEnabled()) {
return $parentBuilder;
}
$parentBuilder->getQuery()->getEDisMax()->setPhraseTrigramFields($trigramPhraseFieldsString);
return $parentBuilder;
}
}