Completed
Pull Request — master (#13)
by Robbie
02:33
created

CwpSearchEngine::search()   C

Complexity

Conditions 7
Paths 10

Size

Total Lines 28
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 15
nc 10
nop 6
dl 0
loc 28
rs 6.7272
c 0
b 0
f 0
1
<?php
2
3
namespace CWP\CWP\Search;
4
5
use Exception;
6
use Psr\Log\LoggerInterface;
7
use SilverStripe\Core\Config\Configurable;
8
use SilverStripe\Core\Extensible;
9
use SilverStripe\Core\Injector\Injectable;
10
use SilverStripe\Core\Injector\Injector;
11
use SilverStripe\FullTextSearch\Search\Queries\SearchQuery;
0 ignored issues
show
Bug introduced by
The type SilverStripe\FullTextSea...rch\Queries\SearchQuery was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use SilverStripe\FullTextSearch\Solr\SolrIndex;
0 ignored issues
show
Bug introduced by
The type SilverStripe\FullTextSearch\Solr\SolrIndex was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
14
/**
15
 * Provides interface for generating search results for a SolrIndex
16
 */
17
class CwpSearchEngine
18
{
19
    use Configurable;
20
    use Extensible;
21
    use Injectable;
22
23
    /**
24
     * Default search options
25
     *
26
     * @var array
27
     * @config
28
     */
29
    private static $search_options = [
30
        'hl' => 'true',
31
    ];
32
33
    /**
34
     * Additional search options to send to search when spellcheck
35
     * is included
36
     *
37
     * @var array
38
     * @config
39
     */
40
    private static $spellcheck_options = [
41
        'spellcheck' => 'true',
42
        'spellcheck.collate' => 'true',
43
        // spellcheck.dictionary can also be configured to use '_spellcheck'
44
        // dictionary when indexing fields under the _spellcheckText column
45
        'spellcheck.dictionary' => 'default',
46
    ];
47
48
    /**
49
     * Build a SearchQuery for a new search
50
     *
51
     * @param string $keywords
52
     * @param array $classes
53
     * @return SearchQuery
54
     */
55
    protected function getSearchQuery($keywords, $classes)
56
    {
57
        $query = new SearchQuery();
58
        $query->classes = $classes;
59
        $query->search($keywords);
60
        $query->exclude('SiteTree_ShowInSearch', 0);
61
        $query->exclude('File_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
        return $query;
67
    }
68
69
    /**
70
     * Get solr search options for this query
71
     *
72
     * @param bool $spellcheck True if we should include spellcheck support
73
     * @return array
74
     */
75
    protected function getSearchOptions($spellcheck)
76
    {
77
        $options = $this->config()->search_options;
78
        if ($spellcheck) {
79
            $options = array_merge($options, $this->config()->spellcheck_options);
80
        }
81
        return $options;
82
    }
83
84
    /**
85
     * Get results for a search term
86
     *
87
     * @param string $keywords
88
     * @param array $classes
89
     * @param SolrIndex $searchIndex
90
     * @param int $limit Max number of results for this page
91
     * @param int $start Skip this number of records
92
     * @param bool $spellcheck True to enable spellcheck
93
     * @return CwpSearchResult
94
     */
95
    protected function getResult($keywords, $classes, $searchIndex, $limit = -1, $start = 0, $spellcheck = false)
96
    {
97
        // Prepare options
98
        $query = $this->getSearchQuery($keywords, $classes);
99
        $options = $this->getSearchOptions($spellcheck);
100
101
        // Get results
102
        $solrResult = $searchIndex->search(
103
            $query,
104
            $start,
105
            $limit,
106
            $options
107
        );
108
109
        return CwpSearchResult::create($keywords, $solrResult);
0 ignored issues
show
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

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