Code

< 40 %
40-60 %
> 60 %
1
<?php
2
3
namespace Brouzie\Sphinxy;
4
5
use Brouzie\Sphinxy\Connection\ConnectionInterface;
6
7
class Escaper
8
{
9
    /**
10
     * @var ConnectionInterface
11
     */
12
    protected $conn;
13
14 3
    public function __construct(ConnectionInterface $conn)
15
    {
16 3
        $this->conn = $conn;
17 3
    }
18
19
    /**
20
     * Wraps the input with identifiers when necessary.
21
     *
22
     * @param Expr|string $value The string to be quoted, or an Expression to leave it untouched
23
     *
24
     * @return string The untouched Expression or the quoted string
25
     */
26
    public function quoteIdentifier($value)
27
    {
28
        if ($value instanceof Expr) {
29
            return $value->getValue();
30
        }
31
32
        if ($value === '*') {
33
            return $value;
34
        }
35
36
        $pieces = explode('.', $value);
37
38
        foreach ($pieces as $key => $piece) {
39
            $pieces[$key] = '`'.$piece.'`';
40
        }
41
42
        return implode('.', $pieces);
43
    }
44
45
    /**
46
     * Calls $this->quoteIdentifier() on every element of the array passed.
47
     *
48
     * @param array $array An array of strings to be quoted
49
     *
50
     * @return array The array of quoted strings
51
     */
52
    public function quoteIdentifierArr(array $array)
53
    {
54
        $result = array();
55
56
        foreach ($array as $key => $item) {
57
            $result[$key] = $this->quoteIdentifier($item);
58
        }
59
60
        return $result;
61
    }
62
63
    /**
64
     * Adds quotes around values when necessary.
65
     * Based on FuelPHP's quoting function.
66
     *
67
     * @param Expr|mixed $value The input string, eventually wrapped in an expression to leave it untouched
68
     *
69
     * @return string The untouched Expression or the quoted string
70
     */
71
    public function quote($value)
72
    {
73
        switch (true) {
74
            case $value === null:
75
                return 'null';
76
77
            case $value === true:
78
                return '1';
79
80
            case $value === false:
81
                return '0';
82
83
            case $value instanceof Expr:
84
                return $value->getValue();
85
86
            case is_int($value) || ctype_digit($value):
87
                return (int) $value;
88
89
            case is_float($value):
90
                // Convert to non-locale aware float to prevent possible commas
91
                return sprintf('%F', $value);
92
93
            case is_array($value):
94
                // Supports MVA attributes
95
                if (!count($value)) {
96
                    return '()';
97
                }
98
99
                return '('.implode(',', $this->quoteArr($value)).')';
100
        }
101
102
        return $this->conn->quote($value);
103
    }
104
105
    /**
106
     * Calls $this->quote() on every element of the array passed.
107
     *
108
     * @param array $array The array of strings to quote
109
     *
110
     * @return array The array of quotes strings
111
     */
112 View Code Duplication
    public function quoteArr(array $array)
113
    {
114
        $result = array();
115
116
        foreach ($array as $key => $item) {
117
            $result[$key] = $this->quote($item);
118
        }
119
120
        return $result;
121
    }
122
123 View Code Duplication
    public function quoteSetArr(array $array)
124
    {
125
        $result = array();
126
127
        foreach ($array as $key => $item) {
128
            $result[$this->quoteIdentifier($key)] = $this->quote($item);
129
        }
130
131
        return $result;
132
    }
133
134
    /**
135
     * Escapes the query for the MATCH() function.
136
     *
137
     * @param  string $string The string to escape for the MATCH
138
     *
139
     * @return  string  The escaped string
140
     */
141
    public function escapeMatch($string)
142
    {
143
        //TODO: maybe better use addcslashes instead of strtr
144
        static $fromTo = array(
145
            '\\' => '\\\\',
146
            '(' => '\(',
147
            ')' => '\)',
148
            '|' => '\|',
149
            '-' => '\-',
150
            '!' => '\!',
151
            '@' => '\@',
152
            '~' => '\~',
153
            '"' => '\"',
154
            '&' => '\&',
155
            '/' => '\/',
156
            '^' => '\^',
157
            '$' => '\$',
158
            '=' => '\=',
159
        );
160
161
        return strtr($string, $fromTo);
162
    }
163
164
    /**
165
     * Escapes the query for the MATCH() function
166
     * Allows some of the control characters to pass through for use with a search field: -, |, "
167
     * It also does some tricks to wrap/unwrap within " the string and prevents errors.
168
     *
169
     * @param  string $string The string to escape for the MATCH
170
     *
171
     * @return  string  The escaped string
172
     */
173
    public function halfEscapeMatch($string)
174
    {
175
        static $fromTo = array(
176
            '\\' => '\\\\',
177
            '(' => '\(',
178
            ')' => '\)',
179
            '!' => '\!',
180
            '@' => '\@',
181
            '~' => '\~',
182
            '&' => '\&',
183
            '/' => '\/',
184
            '^' => '\^',
185
            '$' => '\$',
186
            '=' => '\=',
187
        );
188
189
        $string = strtr($string, $fromTo);
190
191
        // this manages to lower the error rate by a lot
192
        if (mb_substr_count($string, '"') % 2 !== 0) {
193
            $string .= '"';
194
        }
195
196
        $fromToPreg = array(
197
            "'\"([^\s]+)-([^\s]*)\"'" => "\\1\-\\2",
198
            "'([^\s]+)-([^\s]*)'" => "\"\\1\-\\2\"",
199
        );
200
201
        $string = preg_replace(array_keys($fromToPreg), array_values($fromToPreg), $string);
202
203
        return $string;
204
    }
205
}
206