Completed
Push — master ( 36bec6...b439bc )
by Hung
9s
created

Connection::ensureConnection()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
rs 9.4285
cc 2
eloc 5
nc 2
nop 0
1
<?php
2
3
namespace Foolz\SphinxQL\Drivers\Mysqli;
4
5
use Foolz\SphinxQL\Exception\ConnectionException;
6
use Foolz\SphinxQL\Exception\DatabaseException;
7
use Foolz\SphinxQL\Exception\SphinxQLException;
8
use Foolz\SphinxQL\Drivers\ConnectionBase;
9
10
class Connection extends ConnectionBase
11
{
12
    /**
13
     * Internal Encoding
14
     *
15
     * @var string
16
     */
17
    protected $internal_encoding = null;
18
19
    /**
20
     * Disables any warning outputs returned on the \MySQLi connection with @ prefix.
21
     *
22
     * @var boolean
23
     */
24
    protected $silence_connection_warning = false;
25
26
    /**
27
     * Forces the \MySQLi connection to suppress all errors returned. This should only be used
28
     * when the production server is running with high error reporting settings.
29
     *
30
     * @param boolean $enable True if it should be enabled, false if it should be disabled
31
     */
32
    public function silenceConnectionWarning($enable = true)
33
    {
34
        $this->silence_connection_warning = $enable;
35
    }
36
37
    /**
38
     * Returns the internal encoding.
39
     *
40
     * @return string current multibyte internal encoding
41
     */
42
    public function getInternalEncoding()
43
    {
44
        return $this->internal_encoding;
45
    }
46
47
    /**
48
     * Establishes a connection to the Sphinx server with \MySQLi.
49
     *
50
     * @param boolean $suppress_error If the warnings on the connection should be suppressed
51
     *
52
     * @return boolean True if connected
53
     * @throws ConnectionException If a connection error was encountered
54
     */
55 View Code Duplication
    public function connect($suppress_error = false)
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
56
    {
57
        $data = $this->getParams();
58
        $conn = mysqli_init();
59
60
        if (!empty($data['options'])) {
61
            foreach ($data['options'] as $option => $value) {
62
                $conn->options($option, $value);
63
            }
64
        }
65
66
        if (!$suppress_error && ! $this->silence_connection_warning) {
67
            $conn->real_connect($data['host'], null, null, null, (int) $data['port'], $data['socket']);
68
        } else {
69
            @ $conn->real_connect($data['host'], null, null, null, (int) $data['port'], $data['socket']);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
70
        }
71
72
        if ($conn->connect_error) {
73
            throw new ConnectionException('Connection Error: ['.$conn->connect_errno.']'
74
                .$conn->connect_error);
75
        }
76
77
        $conn->set_charset('utf8');
78
        $this->connection = $conn;
79
        $this->mbPush();
80
81
        return true;
82
    }
83
84
    /**
85
     * Pings the Sphinx server.
86
     *
87
     * @return boolean True if connected, false otherwise
88
     */
89
    public function ping()
90
    {
91
        $this->ensureConnection();
92
        return $this->getConnection()->ping();
93
    }
94
95
    /**
96
     * Establishes a connection if needed
97
     * @throws ConnectionException
98
     */
99
    private function ensureConnection()
100
    {
101
        try {
102
            $this->getConnection();
103
        } catch (ConnectionException $e) {
104
            $this->connect();
105
        }
106
    }
107
108
    /**
109
     * Closes and unset the connection to the Sphinx server.
110
     */
111
    public function close()
112
    {
113
        $this->mbPop();
114
        $this->getConnection()->close();
115
        $this->connection = null;
116
    }
117
118
    /**
119
     * Performs a query on the Sphinx server.
120
     *
121
     * @param string $query The query string
122
     *
123
     * @return ResultSet The result array or number of rows affected
124
     * @throws DatabaseException If the executed query produced an error
125
     */
126
    public function query($query)
127
    {
128
        $this->ensureConnection();
129
130
        $resource = $this->getConnection()->query($query);
131
132 View Code Duplication
        if ($this->getConnection()->error) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
133
            throw new DatabaseException('['.$this->getConnection()->errno.'] '.
134
                $this->getConnection()->error.' [ '.$query.']');
135
        }
136
137
        return new ResultSet($this, $resource);
138
    }
139
140
    /**
141
     * Performs multiple queries on the Sphinx server.
142
     *
143
     * @param array $queue Queue holding all of the queries to be executed
144
     *
145
     * @return MultiResultSet The result array
146
     * @throws DatabaseException In case a query throws an error
147
     * @throws SphinxQLException In case the array passed is empty
148
     */
149
    public function multiQuery(Array $queue)
150
    {
151
        $count = count($queue);
152
153
        if ($count === 0) {
154
            throw new SphinxQLException('The Queue is empty.');
155
        }
156
157
        $this->ensureConnection();
158
159
        // HHVM bug (2015/07/07, HipHop VM 3.8.0-dev (rel)): $mysqli->error and $mysqli->errno aren't set
160 View Code Duplication
        if (!$this->getConnection()->multi_query(implode(';', $queue))) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
161
            throw new DatabaseException('['.$this->getConnection()->errno.'] '.
162
                $this->getConnection()->error.' [ '.implode(';', $queue).']');
163
        };
164
165
        return new MultiResultSet($this, $count);
0 ignored issues
show
Unused Code introduced by
The call to MultiResultSet::__construct() has too many arguments starting with $count.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
166
    }
167
168
    /**
169
     * Escapes the input with \MySQLi::real_escape_string.
170
     * Based on FuelPHP's escaping function.
171
     *
172
     * @param string $value The string to escape
173
     *
174
     * @return string The escaped string
175
     * @throws DatabaseException If an error was encountered during server-side escape
176
     */
177 View Code Duplication
    public function escape($value)
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
178
    {
179
        $this->ensureConnection();
180
181
        if (($value = $this->getConnection()->real_escape_string((string) $value)) === false) {
182
            // @codeCoverageIgnoreStart
183
            throw new DatabaseException($this->getConnection()->error, $this->getConnection()->errno);
184
            // @codeCoverageIgnoreEnd
185
        }
186
187
        return "'".$value."'";
188
    }
189
190
    /**
191
     * Enter UTF-8 multi-byte workaround mode.
192
     */
193
    public function mbPush()
194
    {
195
        $this->internal_encoding = mb_internal_encoding();
196
        mb_internal_encoding('UTF-8');
197
198
        return $this;
199
    }
200
201
    /**
202
     * Exit UTF-8 multi-byte workaround mode.
203
     */
204
    public function mbPop()
205
    {
206
        mb_internal_encoding($this->internal_encoding);
207
        $this->internal_encoding = null;
208
209
        return $this;
210
    }
211
}
212