1<?php
2
3namespace Elastica\Suggest;
4
5use Elastica\Suggest\CandidateGenerator\AbstractCandidateGenerator;
6
7/**
8 * Class Phrase.
9 *
10 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters-phrase.html
11 */
12class Phrase extends AbstractSuggest
13{
14    const DEFAULT_REAL_WORD_ERROR_LIKELIHOOD = 0.95;
15    const DEFAULT_CONFIDENCE = 1.0;
16    const DEFAULT_MAX_ERRORS = 1.0;
17    const DEFAULT_STUPID_BACKOFF_DISCOUNT = 0.4;
18    const DEFAULT_LAPLACE_SMOOTHING_ALPHA = 0.5;
19
20    /**
21     * @param string $analyzer
22     *
23     * @return $this
24     */
25    public function setAnalyzer(string $analyzer): Phrase
26    {
27        return $this->setParam('analyzer', $analyzer);
28    }
29
30    /**
31     * Set the max size of the n-grams (shingles) in the field.
32     *
33     * @param int $size
34     *
35     * @return $this
36     */
37    public function setGramSize(int $size): Phrase
38    {
39        return $this->setParam('gram_size', $size);
40    }
41
42    /**
43     * Set the likelihood of a term being misspelled even if the term exists in the dictionary.
44     *
45     * @param float $likelihood Defaults to 0.95, meaning 5% of the words are misspelled.
46     *
47     * @return $this
48     */
49    public function setRealWordErrorLikelihood(float $likelihood): Phrase
50    {
51        return $this->setParam('real_word_error_likelihood', $likelihood);
52    }
53
54    /**
55     * Set the factor applied to the input phrases score to be used as a threshold for other suggestion candidates.
56     * Only candidates which score higher than this threshold will be included in the result.
57     *
58     * @param float $confidence Defaults to 1.0.
59     *
60     * @return $this
61     */
62    public function setConfidence(float $confidence): Phrase
63    {
64        return $this->setParam('confidence', $confidence);
65    }
66
67    /**
68     * Set the maximum percentage of the terms considered to be misspellings in order to form a correction.
69     *
70     * @param float $max
71     *
72     * @return $this
73     */
74    public function setMaxErrors(float $max): Phrase
75    {
76        return $this->setParam('max_errors', $max);
77    }
78
79    /**
80     * @param string $separator
81     *
82     * @return $this
83     */
84    public function setSeparator(string $separator): Phrase
85    {
86        return $this->setParam('separator', $separator);
87    }
88
89    /**
90     * Set suggestion highlighting.
91     *
92     * @param string $preTag
93     * @param string $postTag
94     *
95     * @return $this
96     */
97    public function setHighlight(string $preTag, string $postTag): Phrase
98    {
99        return $this->setParam('highlight', [
100            'pre_tag' => $preTag,
101            'post_tag' => $postTag,
102        ]);
103    }
104
105    /**
106     * @param float $discount
107     *
108     * @return $this
109     */
110    public function setStupidBackoffSmoothing(float $discount): Phrase
111    {
112        return $this->setSmoothingModel('stupid_backoff', [
113            'discount' => $discount,
114        ]);
115    }
116
117    /**
118     * @param float $alpha
119     *
120     * @return $this
121     */
122    public function setLaplaceSmoothing(float $alpha): Phrase
123    {
124        return $this->setSmoothingModel('laplace', [
125            'alpha' => $alpha,
126        ]);
127    }
128
129    /**
130     * @param float $trigramLambda
131     * @param float $bigramLambda
132     * @param float $unigramLambda
133     *
134     * @return $this
135     */
136    public function setLinearInterpolationSmoothing(float $trigramLambda, float $bigramLambda, float $unigramLambda): Phrase
137    {
138        return $this->setSmoothingModel('linear_interpolation', [
139            'trigram_lambda' => $trigramLambda,
140            'bigram_lambda' => $bigramLambda,
141            'unigram_lambda' => $unigramLambda,
142        ]);
143    }
144
145    /**
146     * @param string $model  the name of the smoothing model
147     * @param array  $params
148     *
149     * @return $this
150     */
151    public function setSmoothingModel(string $model, array $params): Phrase
152    {
153        return $this->setParam('smoothing', [
154            $model => $params,
155        ]);
156    }
157
158    /**
159     * @param AbstractCandidateGenerator $generator
160     *
161     * @return $this
162     */
163    public function addCandidateGenerator(AbstractCandidateGenerator $generator): Phrase
164    {
165        return $this->setParam('candidate_generator', $generator);
166    }
167
168    /**
169     * {@inheritdoc}
170     */
171    public function toArray(): array
172    {
173        $array = parent::toArray();
174
175        $baseName = $this->_getBaseName();
176
177        if (isset($array[$baseName]['candidate_generator'])) {
178            $generator = $array[$baseName]['candidate_generator'];
179            unset($array[$baseName]['candidate_generator']);
180
181            $keys = \array_keys($generator);
182            $values = \array_values($generator);
183
184            $array[$baseName][$keys[0]][] = $values[0];
185        }
186
187        return $array;
188    }
189}
190