Passed
Pull Request — master (#216)
by Simon
29:26 queued 19:23
created

buildAndFacetFilterQuery()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 10
c 0
b 0
f 0
nc 6
nop 0
dl 0
loc 16
ccs 10
cts 10
cp 1
crap 4
rs 9.9332
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\SolrSearch\Traits
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\SolrSearch\Traits
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 9
     * correct fields
45
     */
46 9
    protected function buildQueryFacets(): void
47
    {
48 9
        $facets = $this->clientQuery->getFacetSet();
49 2
        $facetSets = array_merge($this->index->getFacetFields(), $this->index->getOrFacetFields());
0 ignored issues
show
Bug introduced by
The method getOrFacetFields() does not exist on Firesphere\SolrSearch\Indexes\BaseIndex. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

49
        $facetSets = array_merge($this->index->getFacetFields(), $this->index->/** @scrutinizer ignore-call */ getOrFacetFields());
Loading history...
50 2
        // Facets should be set from the index configuration
51
        foreach ($facetSets as $config) {
52 2
            $shortClass = getShortFieldName($config['BaseClass']);
53 2
            $field = $shortClass . '_' . str_replace('.', '_', $config['Field']);
54
            /** @var Field $facet */
55
            $facet = $facets->createFacetField('facet-' . $config['Title']);
56 9
            $facet->setField($field);
57 9
        }
58
        // Count however, comes from the query
59
        $facets->setMinCount($this->query->getFacetsMinCount());
60
    }
61
62 9
    /**
63
     * Add AND facet filters based on the current request
64 9
     */
65
    protected function buildAndFacetFilterQuery()
66 9
    {
67 9
        $filterFacets = $this->query->getAndFacetFilter();
68 2
        /** @var null|Criteria $criteria */
69
        $criteria = null;
70 1
        foreach ($this->index->getFacetFields() as $config) {
71 2
            if (isset($filterFacets[$config['Title']])) {
72
                // For the API generator, this needs to be old style list();
73
                list($filter, $field) = $this->getFieldFacets($filterFacets, $config);
74 9
                $this->createFacetCriteria($criteria, $field, $filter);
75 1
            }
76 1
        }
77 1
        if ($criteria) {
78
            $this->clientQuery
79 9
                ->createFilterQuery('andFacets')
80
                ->setQuery($criteria->getQuery());
81
        }
82
    }
83
84
    /**
85
     * Add OR facet filters based on the current request
86
     */
87
    protected function buildOrFacetFilterQuery()
88 1
    {
89
        $filterFacets = $this->query->getOrFacetFilter();
90 1
        $i = 0;
91 1
        /** @var null|Criteria $criteria */
92
        foreach ($this->index->getOrFacetFields() as $config) {
93 1
            $criteria = null;
94 1
            if (isset($filterFacets[$config['Title']])) {
95
                // For the API generator, this needs to be old style list();
96 1
                list($filter, $field) = $this->getFieldFacets($filterFacets, $config);
97
                $this->createFacetCriteria($criteria, $field, $filter);
98
                $this->clientQuery
99
                    ->createFilterQuery('orFacet-' . $i++)
100
                    ->setQuery($criteria->getQuery());
101
            }
102
        }
103
    }
104
105 1
    /**
106
     * Get the field and it's respected values to filter on to generate Criteria from
107 1
     *
108 1
     * @param array $filterFacets
109
     * @param array $config
110 1
     * @return array
111 1
     */
112
    protected function getFieldFacets(array $filterFacets, $config): array
113 1
    {
114
        $filter = $filterFacets[$config['Title']];
115
        $filter = is_array($filter) ? $filter : [$filter];
116
        // Fields are "short named" for convenience
117
        $shortClass = getShortFieldName($config['BaseClass']);
118
        $field = $shortClass . '_' . str_replace('.', '_', $config['Field']);
119
120
        return [$filter, $field];
121
    }
122
123
    /**
124
     * Combine all facets as AND facet filters for the results
125
     *
126
     * @param null|Criteria $criteria
127
     * @param string $field
128
     * @param array $filter
129
     */
130
    protected function createFacetCriteria(&$criteria, string $field, array $filter)
131
    {
132
        // If the criteria is empty, create a new one with a value from the filter array
133
        if (!$criteria) {
134
            $criteria = Criteria::where($field)->is(array_pop($filter));
135
        }
136
        // Add the other items in the filter array, as an AND
137
        foreach ($filter as $filterValue) {
138
            $criteria->andWhere($field)->is($filterValue);
139
        }
140
    }
141
}
142