SearchKeywordFormatter::getTerms()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
/**
3
 *
4
 * @author Mihkel Viilveer <[email protected]>
5
 * @date 3.09.2014
6
 */
7
8
namespace opus\elastic\search;
9
10
use yii\base\BaseObject;
11
12
/**
13
 * This class prepares search keywords for elastic query
14
 * Class SearchKeywordFormatter
15
 *
16
 * @author Mihkel Viilveer <[email protected]>
17
 * @package opus\elastic\search
18
 */
19
class SearchKeywordFormatter extends BaseObject
20
{
21
    /**
22
     * Wildcard definition
23
     *
24
     * @var string
25
     */
26
    public $wildCard = '*';
27
28
    /**
29
     * Maximum search term count to output
30
     *
31
     * @var int
32
     */
33
    public $maxTerms = 5;
34
35
    /**
36
     * Search terms map
37
     *
38
     * @var array
39
     */
40
    private $terms = [];
41
42
    /**
43
     * Search keyword input
44
     *
45
     * @var null
46
     */
47
    private $searchKeyword = null;
48
49
    /**
50
     * Wildcarded term template, leave this empty if you don't want to apply wildcards
51
     *
52
     * @var string
53
     */
54
    public $wildCardedTermTemplate = '{term}{wildcard}';
55
56
    /**
57
     * @param array $searchKeyword
58
     * @param array $config
59
     */
60
    public function __construct($searchKeyword, $config = [])
61
    {
62
        parent::__construct($config);
63
        $this->searchKeyword = $searchKeyword;
0 ignored issues
show
Documentation Bug introduced by
It seems like $searchKeyword of type array is incompatible with the declared type null of property $searchKeyword.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
64
        $this->format();
65
    }
66
67
    private function format()
68
    {
69
        $this->removeSpecialCharacters();
70
        $this->filterUniqueKeywords();
71
        if (!empty($this->wildCardedTermTemplate)) {
72
            $this->setTermWildCards();
73
        }
74
        if (!empty($this->maxTerms) && count($this->terms) > $this->maxTerms) {
75
            $this->removeShortestTerms($this->maxTerms);
76
        }
77
    }
78
79
    /**
80
     * Removes special characters from search keyword
81
     * If two quotes are provided, those are not removed to support exact match searching
82
     */
83
    private function removeSpecialCharacters()
84
    {
85
        $terms = mb_strtolower($this->searchKeyword, 'utf-8');
86
        // match the letters, numbers and double quote with unicode modifier
87
        $regex = '/[^\p{L}|\p{N}|"]/u';
88
        if (substr_count($terms, '"') !== 2) {
89
            // match the letters and numbers with unicode modifier
90
            $regex = '/[^\p{L}|\p{N}]/u';
91
        }
92
        $this->searchKeyword = preg_replace($regex, ' ', $terms);
0 ignored issues
show
Documentation Bug introduced by
It seems like preg_replace($regex, ' ', $terms) of type string is incompatible with the declared type null of property $searchKeyword.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
93
    }
94
95
    /**
96
     * Removes duplicated and empty terms
97
     */
98
    private function filterUniqueKeywords()
99
    {
100
        $terms = explode(' ', $this->searchKeyword);
101
        $terms = array_filter($terms);
102
        $uniqueTerms = array_unique($terms);
103
        $this->terms = $uniqueTerms;
104
    }
105
106
    /**
107
     * Applies wildcard(s) to search term based on wildCardedTermTemplate
108
     */
109
    private function setTermWildCards()
110
    {
111
        $wildCardedTerms = [];
112
        foreach ($this->terms as $term) {
113
            $wildCardedTerm = str_replace(
114
                '{term}',
115
                $term,
116
                $this->wildCardedTermTemplate
117
            );
118
            $wildCardedTerm = str_replace(
119
                '{wildcard}',
120
                $this->wildCard,
121
                $wildCardedTerm
122
            );
123
            $wildCardedTerms[] = $wildCardedTerm;
124
        }
125
        $this->terms = $wildCardedTerms;
126
    }
127
128
    /**
129
     * Removes shortest search terms from terms map
130
     *
131
     * @param $maxCount
132
     */
133
    private function removeShortestTerms($maxCount)
134
    {
135
        $longestWordLength = 0;
136
        $longestWord = '';
137
        $longestWords = [];
138
        for ($i = 0; $i <= $maxCount - 1; $i++) {
139
            $longestWordId = null;
140
            foreach ($this->terms as $id => $word) {
141
                if (strlen($word) > $longestWordLength) {
142
                    $longestWordLength = strlen($word);
143
                    $longestWord = $word;
144
                    $longestWordId = $id;
145
                }
146
            }
147
            $longestWordLength = 0;
148
            unset($this->terms[$longestWordId]);
149
150
            $longestWords[] = $longestWord;
151
        }
152
        $this->terms = $longestWords;
153
    }
154
155
    /**
156
     * Returns formatted terms
157
     * @return array
158
     */
159
    public function getTerms()
160
    {
161
        return $this->terms;
162
    }
163
}