Completed
Push — master ( 3bc514...3a2d29 )
by Nicolas
03:28
created

Util::isDateMathEscaped()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
namespace Elastica;
3
4
/**
5
 * Elastica tools.
6
 *
7
 * @author Nicolas Ruflin <[email protected]>
8
 * @author Thibault Duplessis <[email protected]>
9
 * @author Oleg Zinchenko <[email protected]>
10
 * @author Roberto Nygaard <[email protected]>
11
 */
12
class Util
13
{
14
    /** @var array */
15
    protected static $dateMathSymbols = ['<', '>', '/', '{', '}', '|', '+', ':', ','];
16
17
    /** @var array */
18
    protected static $escapedDateMathSymbols = ['%3C', '%3E', '%2F', '%7B', '%7D', '%7C', '%2B', '%3A', '%2C'];
19
20
    /**
21
     * Checks if date math is already escaped within request URI.
22
     *
23
     * @param string $requestUri
24
     *
25
     * @return bool
26
     */
27
    public static function isDateMathEscaped($requestUri)
28
    {
29
        // In practice, the only symbol that really needs to be escaped in URI is '/' => '%2F'
30
        return false !== strpos(strtoupper($requestUri), '%2F');
31
    }
32
33
    /**
34
     * Escapes date math symbols within request URI.
35
     * @see https://www.elastic.co/guide/en/elasticsearch/reference/5.x/date-math-index-names.html
36
     *
37
     * @param string $requestUri
38
     *
39
     * @return string
40
     */
41
    public static function escapeDateMath($requestUri)
42
    {
43
        if (empty($requestUri)) {
44
            return $requestUri;
45
        }
46
47
        // Check if date math if used at all. Find last '>'. E.g. /<log-{now/d}>,log-2011.12.01/log/_refresh
48
        $pos1 = strrpos($requestUri, '>');
49
        if (false === $pos1) {
50
            return $requestUri;
51
        }
52
53
        // Find the position up to which we should escape.
54
        // Should be next slash '/' after last '>' E.g. /<log-{now/d}>,log-2011.12.01/log/_refresh
55
        $pos2 = strpos($requestUri, '/', $pos1);
56
        $pos2 = false !== $pos2 ? $pos2 : strlen($requestUri);
57
58
        // Cut out the bit we need to escape: /<log-{now/d}>,log-2011.12.01
59
        $uriSegment = substr($requestUri, 0, $pos2);
60
61
        // Escape using character map
62
        $escapedUriSegment = str_replace(static::$dateMathSymbols, static::$escapedDateMathSymbols, $uriSegment);
63
64
        // '\\{' and '\\}' should not be escaped
65
        if (false !== strpos($uriSegment, '\\\\')) {
66
            $escapedUriSegment = str_replace(['\\\\%7B', '\\\\%7D'], ['\\\\{', '\\\\}'], $escapedUriSegment);
67
        }
68
69
        // Replace part of the string. E.g. /%3Clog-%7Bnow%2Fd%7D%3E%2Clog-2011.12.01/log/_refresh
70
        return substr_replace($requestUri, $escapedUriSegment, 0, $pos2);
71
    }
72
73
    /**
74
     * Replace the following reserved words: AND OR NOT
75
     * and
76
     * escapes the following terms: + - && || ! ( ) { } [ ] ^ " ~ * ? : \.
77
     *
78
     * @link http://lucene.apache.org/java/2_4_0/queryparsersyntax.html#Boolean%20operators
79
     * @link http://lucene.apache.org/java/2_4_0/queryparsersyntax.html#Escaping%20Special%20Characters
80
     *
81
     * @param string $term Query term to replace and escape
82
     *
83
     * @return string Replaced and escaped query term
84
     */
85
    public static function replaceBooleanWordsAndEscapeTerm($term)
86
    {
87
        $result = $term;
88
        $result = self::replaceBooleanWords($result);
89
        $result = self::escapeTerm($result);
90
91
        return $result;
92
    }
93
94
    /**
95
     * Escapes the following terms (because part of the query language)
96
     * + - && || ! ( ) { } [ ] ^ " ~ * ? : \ < >.
97
     *
98
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html#_reserved_characters
99
     *
100
     * @param string $term Query term to escape
101
     *
102
     * @return string Escaped query term
103
     */
104
    public static function escapeTerm($term)
105
    {
106
        $result = $term;
107
        // \ escaping has to be first, otherwise escaped later once again
108
        $chars = ['\\', '+', '-', '&&', '||', '!', '(', ')', '{', '}', '[', ']', '^', '"', '~', '*', '?', ':', '/', '<', '>'];
109
110
        foreach ($chars as $char) {
111
            $result = str_replace($char, '\\'.$char, $result);
112
        }
113
114
        return $result;
115
    }
116
117
    /**
118
     * Replace the following reserved words (because part of the query language)
119
     * AND OR NOT.
120
     *
121
     * @link http://lucene.apache.org/java/2_4_0/queryparsersyntax.html#Boolean%20operators
122
     *
123
     * @param string $term Query term to replace
124
     *
125
     * @return string Replaced query term
126
     */
127
    public static function replaceBooleanWords($term)
128
    {
129
        $replacementMap = [' AND ' => ' && ', ' OR ' => ' || ', ' NOT ' => ' !'];
130
        $result = strtr($term, $replacementMap);
131
132
        return $result;
133
    }
134
135
    /**
136
     * Converts a snake_case string to CamelCase.
137
     *
138
     * For example: hello_world to HelloWorld
139
     *
140
     * @param string $string snake_case string
141
     *
142
     * @return string CamelCase string
143
     */
144
    public static function toCamelCase($string)
145
    {
146
        return str_replace(' ', '', ucwords(str_replace('_', ' ', $string)));
147
    }
148
149
    /**
150
     * Converts a CamelCase string to snake_case.
151
     *
152
     * For Example HelloWorld to hello_world
153
     *
154
     * @param string $string CamelCase String to Convert
155
     *
156
     * @return string SnakeCase string
157
     */
158
    public static function toSnakeCase($string)
159
    {
160
        $string = preg_replace('/([A-Z])/', '_$1', $string);
161
162
        return strtolower(substr($string, 1));
163
    }
164
165
    /**
166
     * Converts given time to format: 1995-12-31T23:59:59Z.
167
     *
168
     * This is the lucene date format
169
     *
170
     * @param int|string $date Date input (could be string etc.) -> must be supported by strtotime
171
     *
172
     * @return string Converted date string
173
     */
174
    public static function convertDate($date)
175
    {
176
        if (is_int($date)) {
177
            $timestamp = $date;
178
        } else {
179
            $timestamp = strtotime($date);
180
        }
181
        $string = date('Y-m-d\TH:i:s\Z', $timestamp);
182
183
        return $string;
184
    }
185
186
    /**
187
     * Convert a \DateTime object to format: 1995-12-31T23:59:59Z+02:00.
188
     *
189
     * Converts it to the lucene format, including the appropriate TimeZone
190
     *
191
     * @param \DateTime $dateTime
192
     * @param bool      $includeTimezone
193
     *
194
     * @return string
195
     */
196
    public static function convertDateTimeObject(\DateTime $dateTime, $includeTimezone = true)
197
    {
198
        $formatString = 'Y-m-d\TH:i:s'.($includeTimezone === true ? 'P' : '\Z');
199
        $string = $dateTime->format($formatString);
200
201
        return $string;
202
    }
203
204
    /**
205
     * Tries to guess the name of the param, based on its class
206
     * Example: \Elastica\Filter\HasChildFilter => has_child.
207
     *
208
     * @param string|object Class or Class name
209
     *
210
     * @return string parameter name
211
     */
212
    public static function getParamName($class)
213
    {
214
        if (is_object($class)) {
215
            $class = get_class($class);
216
        }
217
218
        $parts = explode('\\', $class);
219
        $last = array_pop($parts);
220
        $last = preg_replace('/(Query|Filter)$/', '', $last);
221
        $name = self::toSnakeCase($last);
222
223
        return $name;
224
    }
225
226
    /**
227
     * Converts Request to Curl console command.
228
     *
229
     * @param Request $request
230
     *
231
     * @return string
232
     */
233
    public static function convertRequestToCurlCommand(Request $request)
234
    {
235
        $message = 'curl -X'.strtoupper($request->getMethod()).' ';
236
        $message .= '\'http://'.$request->getConnection()->getHost().':'.$request->getConnection()->getPort().'/';
237
        $message .= $request->getPath();
238
239
        $query = $request->getQuery();
240
        if (!empty($query)) {
241
            $message .= '?'.http_build_query($query);
242
        }
243
244
        $message .= '\'';
245
246
        $data = $request->getData();
247
        if (!empty($data)) {
248
            $message .= ' -d \''.JSON::stringify($data).'\'';
249
        }
250
251
        return $message;
252
    }
253
}
254