first commit
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
namespace WapplerSystems\Meilisearch\Domain\Search\ResultSet\Facets\OptionBased\QueryGroup;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
use WapplerSystems\Meilisearch\Domain\Search\ResultSet\Facets\OptionBased\AbstractOptionFacetItem;
|
||||
|
||||
/**
|
||||
* Value object that represent an option of a queryGroup facet.
|
||||
*
|
||||
* @author Frans Saris <frans@beech.it>
|
||||
* @author Timo Hund <timo.hund@dkd.de>
|
||||
*/
|
||||
class Option extends AbstractOptionFacetItem
|
||||
{
|
||||
/**
|
||||
* @param QueryGroupFacet $facet
|
||||
* @param string $label
|
||||
* @param string $value
|
||||
* @param int $documentCount
|
||||
* @param bool $selected
|
||||
*/
|
||||
public function __construct(QueryGroupFacet $facet, $label = '', $value = '', $documentCount = 0, $selected = false)
|
||||
{
|
||||
parent::__construct($facet, $label, $value, $documentCount, $selected);
|
||||
}
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
namespace WapplerSystems\Meilisearch\Domain\Search\ResultSet\Facets\OptionBased\QueryGroup;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use WapplerSystems\Meilisearch\Domain\Search\ResultSet\Facets\OptionBased\AbstractOptionsFacet;
|
||||
use WapplerSystems\Meilisearch\Domain\Search\ResultSet\SearchResultSet;
|
||||
|
||||
/**
|
||||
* Class QueryGroupFacet
|
||||
*
|
||||
* @author Frans Saris <frans@beech.it>
|
||||
* @author Timo Hund <timo.hund@dkd.de>
|
||||
*/
|
||||
class QueryGroupFacet extends AbstractOptionsFacet
|
||||
{
|
||||
const TYPE_QUERY_GROUP = 'queryGroup';
|
||||
|
||||
/**
|
||||
* String
|
||||
* @var string
|
||||
*/
|
||||
protected static $type = self::TYPE_QUERY_GROUP;
|
||||
|
||||
/**
|
||||
* OptionsFacet constructor
|
||||
*
|
||||
* @param SearchResultSet $resultSet
|
||||
* @param string $name
|
||||
* @param string $field
|
||||
* @param string $label
|
||||
* @param array $configuration Facet configuration passed from typoscript
|
||||
*/
|
||||
public function __construct(SearchResultSet $resultSet, $name, $field, $label = '', array $configuration = [])
|
||||
{
|
||||
parent::__construct($resultSet, $name, $field, $label, $configuration);
|
||||
}
|
||||
}
|
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
namespace WapplerSystems\Meilisearch\Domain\Search\ResultSet\Facets\OptionBased\QueryGroup;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use WapplerSystems\Meilisearch\Domain\Search\ResultSet\Facets\AbstractFacetParser;
|
||||
use WapplerSystems\Meilisearch\Domain\Search\ResultSet\SearchResultSet;
|
||||
use WapplerSystems\Meilisearch\System\Solr\ResponseAdapter;
|
||||
|
||||
/**
|
||||
* Class QueryGroupFacetParser
|
||||
*
|
||||
* @author Frans Saris <frans@beech.it>
|
||||
* @author Timo Hund <timo.hund@dkd.de>
|
||||
*/
|
||||
class QueryGroupFacetParser extends AbstractFacetParser
|
||||
{
|
||||
|
||||
/**
|
||||
* @param SearchResultSet $resultSet
|
||||
* @param string $facetName
|
||||
* @param array $facetConfiguration
|
||||
* @return QueryGroupFacet|null
|
||||
*/
|
||||
public function parse(SearchResultSet $resultSet, $facetName, array $facetConfiguration)
|
||||
{
|
||||
$response = $resultSet->getResponse();
|
||||
$fieldName = $facetConfiguration['field'];
|
||||
$label = $this->getPlainLabelOrApplyCObject($facetConfiguration);
|
||||
|
||||
$rawOptions = $this->getRawOptions($response, $fieldName);
|
||||
$noOptionsInResponse = $rawOptions === [];
|
||||
$hideEmpty = !$resultSet->getUsedSearchRequest()->getContextTypoScriptConfiguration()->getSearchFacetingShowEmptyFacetsByName($facetName);
|
||||
|
||||
if ($noOptionsInResponse && $hideEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var QueryGroupFacet $facet */
|
||||
$facet = $this->objectManager->get(
|
||||
QueryGroupFacet::class,
|
||||
$resultSet,
|
||||
$facetName,
|
||||
$fieldName,
|
||||
$label,
|
||||
$facetConfiguration
|
||||
);
|
||||
|
||||
$activeFacets = $resultSet->getUsedSearchRequest()->getActiveFacetNames();
|
||||
$facet->setIsUsed(in_array($facetName, $activeFacets, true));
|
||||
|
||||
if (!$noOptionsInResponse) {
|
||||
$facet->setIsAvailable(true);
|
||||
foreach ($rawOptions as $query => $count) {
|
||||
$value = $this->getValueByQuery($query, $facetConfiguration);
|
||||
// Skip unknown queries
|
||||
if ($value === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->getIsExcludedFacetValue($query, $facetConfiguration)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$isOptionsActive = $resultSet->getUsedSearchRequest()->getHasFacetValue($facetName, $value);
|
||||
$label = $this->getLabelFromRenderingInstructions(
|
||||
$value,
|
||||
$count,
|
||||
$facetName,
|
||||
$facetConfiguration
|
||||
);
|
||||
$facet->addOption($this->objectManager->get(Option::class, $facet, $label, $value, $count, $isOptionsActive));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// after all options have been created we apply a manualSortOrder if configured
|
||||
// the sortBy (lex,..) is done by the solr server and triggered by the query, therefore it does not
|
||||
// need to be handled in the frontend.
|
||||
$this->applyManualSortOrder($facet, $facetConfiguration);
|
||||
$this->applyReverseOrder($facet, $facetConfiguration);
|
||||
|
||||
return $facet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get raw query options
|
||||
*
|
||||
* @param ResponseAdapter $response
|
||||
* @param string $fieldName
|
||||
* @return array
|
||||
*/
|
||||
protected function getRawOptions(ResponseAdapter $response, $fieldName)
|
||||
{
|
||||
$options = [];
|
||||
|
||||
foreach ($response->facet_counts->facet_queries as $rawValue => $count) {
|
||||
if ((int)$count === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// todo: add test cases to check if this is needed https://forge.typo3.org/issues/45440
|
||||
// remove tags from the facet.query response, for facet.field
|
||||
// and facet.range Solr does that on its own automatically
|
||||
$rawValue = preg_replace('/^\{!ex=[^\}]*\}(.*)/', '\\1', $rawValue);
|
||||
|
||||
list($field, $query) = explode(':', $rawValue, 2);
|
||||
if ($field === $fieldName) {
|
||||
$options[$query] = $count;
|
||||
}
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $query
|
||||
* @param array $facetConfiguration
|
||||
* @return string|null
|
||||
*/
|
||||
protected function getValueByQuery($query, array $facetConfiguration)
|
||||
{
|
||||
$value = null;
|
||||
foreach ($facetConfiguration['queryGroup.'] as $valueKey => $config) {
|
||||
if (isset($config['query']) && $config['query'] === $query) {
|
||||
$value = rtrim($valueKey, '.');
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
namespace WapplerSystems\Meilisearch\Domain\Search\ResultSet\Facets\OptionBased\QueryGroup;
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use WapplerSystems\Meilisearch\Domain\Search\ResultSet\Facets\DefaultFacetQueryBuilder;
|
||||
use WapplerSystems\Meilisearch\Domain\Search\ResultSet\Facets\FacetQueryBuilderInterface;
|
||||
use WapplerSystems\Meilisearch\System\Configuration\TypoScriptConfiguration;
|
||||
|
||||
class QueryGroupFacetQueryBuilder extends DefaultFacetQueryBuilder implements FacetQueryBuilderInterface {
|
||||
|
||||
/**
|
||||
* @param string $facetName
|
||||
* @param TypoScriptConfiguration $configuration
|
||||
* @return array
|
||||
*/
|
||||
public function build($facetName, TypoScriptConfiguration $configuration)
|
||||
{
|
||||
$facetParameters = [];
|
||||
$facetConfiguration = $configuration->getSearchFacetingFacetByName($facetName);
|
||||
foreach ($facetConfiguration['queryGroup.'] as $queryName => $queryConfiguration) {
|
||||
$tags = $this->buildExcludeTags($facetConfiguration, $configuration);
|
||||
$facetParameters['facet.query'][] = $tags . $facetConfiguration['field'] . ':' . $queryConfiguration['query'];
|
||||
}
|
||||
|
||||
return $facetParameters;
|
||||
}
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
namespace WapplerSystems\Meilisearch\Domain\Search\ResultSet\Facets\OptionBased\QueryGroup;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use WapplerSystems\Meilisearch\Domain\Search\ResultSet\Facets\AbstractFacetPackage;
|
||||
|
||||
/**
|
||||
* Class QueryGroupPackage
|
||||
*/
|
||||
class QueryGroupPackage extends AbstractFacetPackage {
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getParserClassName() {
|
||||
return (string)QueryGroupFacetParser::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getQueryBuilderClassName()
|
||||
{
|
||||
return (string)QueryGroupFacetQueryBuilder::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getUrlDecoderClassName()
|
||||
{
|
||||
return (string)QueryGroupUrlDecoder::class;
|
||||
}
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
namespace WapplerSystems\Meilisearch\Domain\Search\ResultSet\Facets\OptionBased\QueryGroup;
|
||||
|
||||
/***************************************************************
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2012-2015 Ingo Renner <ingo@typo3.org>
|
||||
* 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\ResultSet\Facets\FacetUrlDecoderInterface;
|
||||
|
||||
/**
|
||||
* Filter encoder to build facet query parameters
|
||||
*
|
||||
* @author Timo Hund <timo.hund@dkd.de>
|
||||
* @author Ingo Renner <ingo@typo3.org>
|
||||
*/
|
||||
class QueryGroupUrlDecoder implements FacetUrlDecoderInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Parses the query filter from GET parameters in the URL and translates it
|
||||
* to a Lucene filter value.
|
||||
*
|
||||
* @param string $filterValue the filter query from plugin
|
||||
* @param array $configuration options set in a facet's configuration
|
||||
* @return string Value to be used in a Lucene filter
|
||||
*/
|
||||
public function decode($filterValue, array $configuration = [])
|
||||
{
|
||||
return $configuration[$filterValue . '.']['query'];
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user