QueryComponentFacetTrait::getFieldFacets()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 6
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 10
ccs 7
cts 7
cp 1
crap 2
rs 10
1
<?php
2
/**
3
 * Trait QueryComponentFacetTrait|Firesphere\SolrSearch\Traits\QueryComponentFacetTrait Trait to set Faceting on fields
4
 * for the {@link \Firesphere\SolrSearch\Factories\QueryComponentFactory}
5
 *
6
 * @package Firesphere\Solr\Search
7
 * @author Simon `Firesphere` Erkelens; Marco `Sheepy` Hermo
8
 * @copyright Copyright (c) 2018 - now() Firesphere & Sheepy
9
 */
10
11
namespace Firesphere\SolrSearch\Traits;
12
13
use Firesphere\SolrSearch\Indexes\BaseIndex;
14
use Firesphere\SolrSearch\Queries\BaseQuery;
15
use Minimalcode\Search\Criteria;
16
use Solarium\Component\Facet\Field;
17
use Solarium\QueryType\Select\Query\Query;
18
19
/**
20
 * Trait QueryComponentFacetTrait deals with the facets.
21
 *
22
 * Faceting for any given query or index.
23
 *
24
 * @package Firesphere\Solr\Search
25
 */
26
trait QueryComponentFacetTrait
27
{
28
    /**
29
     * @var BaseIndex Index to query
30
     */
31
    protected $index;
32
    /**
33
     * @var BaseQuery Query to use
34
     */
35
    protected $query;
36
    /**
37
     * @var Query Solarium query
38
     */
39
    protected $clientQuery;
40
41
    /**
42
     * Add facets from the index, to make sure Solr returns
43
     * the expected facets and their respective count on the
44
     * correct fields
45
     */
46 9
    protected function buildQueryFacets(): void
47
    {
48 9
        $facets = $this->clientQuery->getFacetSet();
49
        // Facets should be set from the index configuration
50 9
        foreach ($this->index->getFacetFields() as $config) {
51 2
            $shortClass = getShortFieldName($config['BaseClass']);
52 2
            $underscoredField = str_replace('.', '_', $config['Field']);
53 2
            $field = sprintf('%s_%s', $shortClass, $underscoredField);
54
            /** @var Field $facet */
55 2
            $facet = $facets->createFacetField('facet-' . $config['Title']);
56 2
            $facet->setField($field);
57
        }
58
        // Count however, comes from the query
59 9
        $facets->setMinCount($this->query->getFacetsMinCount());
60 9
    }
61
62
    /**
63
     * Add AND facet filters based on the current request
64
     */
65 9
    protected function buildAndFacetFilterQuery()
66
    {
67 9
        $filterFacets = $this->query->getAndFacetFilter();
68
        /** @var null|Criteria $criteria */
69 9
        $criteria = null;
70 9
        foreach ($this->index->getFacetFields() as $config) {
71 2
            if (isset($filterFacets[$config['Title']])) {
72 1
                [$filter, $field] = $this->getFieldFacets($filterFacets, $config);
73 2
                $this->createFacetCriteria($criteria, $field, $filter);
74
            }
75
        }
76 9
        if ($criteria) {
77 1
            $this->clientQuery
78 1
                ->createFilterQuery('andFacets')
79 1
                ->setQuery($criteria->getQuery());
80
        }
81 9
    }
82
83
    /**
84
     * Get the field and it's respected values to filter on to generate Criteria from
85
     *
86
     * @param array $filterFacets
87
     * @param array $config
88
     * @return array
89
     */
90 1
    protected function getFieldFacets(array $filterFacets, $config): array
91
    {
92 1
        $filter = $filterFacets[$config['Title']];
93 1
        $filter = is_array($filter) ? $filter : [$filter];
94
        // Fields are "short named" for convenience
95 1
        $shortClass = getShortFieldName($config['BaseClass']);
96 1
        $underscoredField = str_replace('.', '_', $config['Field']);
97 1
        $field = sprintf('%s_%s', $shortClass, $underscoredField);
98
99 1
        return [$filter, $field];
100
    }
101
102
    /**
103
     * Combine all facets as AND facet filters for the results
104
     *
105
     * @param null|Criteria $criteria
106
     * @param string $field
107
     * @param array $filter
108
     */
109 1
    protected function createFacetCriteria(&$criteria, string $field, array $filter)
110
    {
111
        // If the criteria is empty, create a new one with a value from the filter array
112 1
        if (!$criteria) {
113 1
            $criteria = Criteria::where($field)->is(array_pop($filter));
114
        }
115
        // Add the other items in the filter array, as an AND
116 1
        foreach ($filter as $filterValue) {
117 1
            $criteria->andWhere($field)->is($filterValue);
118
        }
119 1
    }
120
121
    /**
122
     * Add OR facet filters based on the current request
123
     */
124 9
    protected function buildOrFacetFilterQuery()
125
    {
126 9
        $filterFacets = $this->query->getOrFacetFilter();
127 9
        $index = 0;
128
        /** @var null|Criteria $criteria */
129 9
        foreach ($this->index->getFacetFields() as $config) {
130 2
            $criteria = null;
131 2
            if (isset($filterFacets[$config['Title']])) {
132 1
                [$filter, $field] = $this->getFieldFacets($filterFacets, $config);
133 1
                $this->createFacetCriteria($criteria, $field, $filter);
134 1
                $this->clientQuery
135 1
                    ->createFilterQuery('orFacet-' . $index++)
136 2
                    ->setQuery($criteria->getQuery());
137
            }
138
        }
139 9
    }
140
}
141