Completed
Push — master ( 686084...a2bb6b )
by
unknown
9s
created

CwpSearchEngine::search()   C

Complexity

Conditions 7
Paths 10

Size

Total Lines 28
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 28
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 14
nc 10
nop 6
1
<?php
2
3
namespace CWP\Search;
4
5
use Exception;
6
use Psr\Log\LoggerInterface;
7
use SilverStripe\CMS\Model\SiteTree;
8
use SilverStripe\Core\Config\Configurable;
9
use SilverStripe\Core\Extensible;
10
use SilverStripe\Core\Injector\Injectable;
11
use SilverStripe\Core\Injector\Injector;
12
use SilverStripe\FullTextSearch\Search\Queries\SearchQuery;
13
use SilverStripe\FullTextSearch\Solr\SolrIndex;
14
15
/**
16
 * Provides interface for generating search results for a SolrIndex
17
 */
18
class CwpSearchEngine
19
{
20
    use Configurable;
21
    use Extensible;
22
    use Injectable;
23
24
    /**
25
     * Default search options
26
     *
27
     * @var array
28
     * @config
29
     */
30
    private static $search_options = [
0 ignored issues
show
introduced by
The private property $search_options is not used, and could be removed.
Loading history...
31
        'hl' => 'true',
32
    ];
33
34
    /**
35
     * Additional search options to send to search when spellcheck
36
     * is included
37
     *
38
     * @var array
39
     * @config
40
     */
41
    private static $spellcheck_options = [
0 ignored issues
show
introduced by
The private property $spellcheck_options is not used, and could be removed.
Loading history...
42
        'spellcheck' => 'true',
43
        'spellcheck.collate' => 'true',
44
        // spellcheck.dictionary can also be configured to use '_spellcheck'
45
        // dictionary when indexing fields under the _spellcheckText column
46
        'spellcheck.dictionary' => 'default',
47
    ];
48
49
    /**
50
     * Build a SearchQuery for a new search
51
     *
52
     * @param string $keywords
53
     * @param array $classes
54
     * @return SearchQuery
55
     */
56
    protected function getSearchQuery($keywords, $classes)
57
    {
58
        $query = new SearchQuery();
59
        $query->classes = $classes;
60
        $query->search($keywords);
61
        $query->exclude(SiteTree::class . '_ShowInSearch', 0);
62
63
        // Artificially lower the amount of results to prevent too high resource usage.
64
        // on subsequent canView check loop.
65
        $query->limit(100);
66
67
        // Allow user code to modify the search query before returning it
68
        $this->extend('updateSearchQuery', $query);
69
70
        return $query;
71
    }
72
73
    /**
74
     * Get solr search options for this query
75
     *
76
     * @param bool $spellcheck True if we should include spellcheck support
77
     * @return array
78
     */
79
    protected function getSearchOptions($spellcheck)
80
    {
81
        $options = $this->config()->get('search_options');
82
        if ($spellcheck) {
83
            $options = array_merge($options, $this->config()->get('spellcheck_options'));
84
        }
85
        return $options;
86
    }
87
88
    /**
89
     * Get results for a search term
90
     *
91
     * @param string $keywords
92
     * @param array $classes
93
     * @param SolrIndex $searchIndex
94
     * @param int $limit Max number of results for this page
95
     * @param int $start Skip this number of records
96
     * @param bool $spellcheck True to enable spellcheck
97
     * @return CwpSearchResult
98
     */
99
    protected function getResult($keywords, $classes, $searchIndex, $limit = -1, $start = 0, $spellcheck = false)
100
    {
101
        // Prepare options
102
        $query = $this->getSearchQuery($keywords, $classes);
103
        $options = $this->getSearchOptions($spellcheck);
104
105
        // Get results
106
        $solrResult = $searchIndex->search(
107
            $query,
108
            $start,
109
            $limit,
110
            $options
111
        );
112
113
        return CwpSearchResult::create($keywords, $solrResult);
0 ignored issues
show
Bug introduced by
$solrResult of type SilverStripe\View\ArrayData is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

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

113
        return CwpSearchResult::create($keywords, /** @scrutinizer ignore-type */ $solrResult);
Loading history...
Bug introduced by
$keywords of type string is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

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

113
        return CwpSearchResult::create(/** @scrutinizer ignore-type */ $keywords, $solrResult);
Loading history...
114
    }
115
116
    /**
117
     * Get a CwpSearchResult for a given criterea
118
     *
119
     * @param string $keywords
120
     * @param array $classes
121
     * @param SolrIndex $searchIndex
122
     * @param int $limit Max number of results for this page
123
     * @param int $start Skip this number of records
124
     * @param bool $followSuggestions True to enable suggested searches to be returned immediately
125
     * @return CwpSearchResult|null
126
     */
127
    public function search($keywords, $classes, $searchIndex, $limit = -1, $start = 0, $followSuggestions = false)
128
    {
129
        if (empty($keywords)) {
130
            return null;
131
        }
132
133
        try {
134
            // Begin search
135
            $result = $this->getResult($keywords, $classes, $searchIndex, $limit, $start, true);
136
137
            // Return results if we don't need to refine this any further
138
            if (!$followSuggestions || $result->hasResults() || !$result->getSuggestion()) {
139
                return $result;
140
            }
141
142
            // Perform new search with the suggested terms
143
            $suggested = $result->getSuggestion();
144
            $newResult = $this->getResult($suggested, $classes, $searchIndex, $limit, $start, false);
145
            $newResult->setOriginal($keywords);
146
147
            // Compare new results to the original query
148
            if ($newResult->hasResults()) {
149
                return $newResult;
150
            }
151
152
            return $result;
153
        } catch (Exception $e) {
154
            Injector::inst()->get(LoggerInterface::class)->warning($e);
155
        }
156
    }
157
}
158