Test Setup Failed
Push — testing ( e489a3...bf119f )
by Roman
03:29
created

Connection::__call()   A

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 2
1
<?php
2
3
namespace lroman242\LaravelCassandra;
4
5
use Cassandra;
6
use Cassandra\BatchStatement;
7
8
class Connection extends \Illuminate\Database\Connection
9
{
10
    const DEFAULT_PAGE_SIZE = 5000;
11
    
12
    /**
13
     * The Cassandra keyspace
14
     *
15
     * @var string
16
     */
17
    protected $keyspace;
18
19
    /**
20
     * The Cassandra cluster
21
     *
22
     * @var \Cassandra\Cluster
23
     */
24
    protected $cluster;
25
26
    /**
27
     * The Cassandra connection handler.
28
     *
29
     * @var \Cassandra\Session
30
     */
31
    protected $session;
32
33
    /**
34
     * The config
35
     *
36
     * @var array
37
     */
38
    protected $config;
39
40
    /**
41
     * Create a new database connection instance.
42
     *
43
     * @param  array   $config
44
     */
45
    public function __construct(array $config)
46
    {
47
        $this->config = $config;
48
        if (empty($this->config['page_size'])) {
49
            $this->config['page_size'] = self::DEFAULT_PAGE_SIZE;
50
        }
51
52
        // Create the connection
53
        $this->cluster = $this->createCluster($config);
54
55
        if (isset($config['keyspace'])) {
56
            $keyspaceName = $config['keyspace'];
57
58
            $this->keyspace = $keyspaceName;
59
            $this->session = $this->cluster->connect($keyspaceName);
60
        }
61
62
        $this->useDefaultPostProcessor();
63
64
        $this->useDefaultSchemaGrammar();
65
66
        $this->setQueryGrammar($this->getDefaultQueryGrammar());
67
    }
68
69
    /**
70
     * Begin a fluent query against a database table.
71
     *
72
     * @param  string  $table
73
     * @return Query\Builder
74
     */
75
    public function table($table)
76
    {
77
        $processor = $this->getPostProcessor();
78
79
        $query = new Query\Builder($this, null, $processor);
0 ignored issues
show
Documentation introduced by
$processor is of type object<Illuminate\Databa...y\Processors\Processor>, but the function expects a null|object<lroman242\La...sandra\Query\Processor>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
80
81
        return $query->from($table);
82
    }
83
84
    /**
85
     * return Cassandra cluster.
86
     *
87
     * @return \Cassandra\Cluster
88
     */
89
    public function getCassandraCluster()
90
    {
91
        return $this->cluster;
92
    }
93
94
    /**
95
     * return Cassandra Session.
96
     *
97
     * @return \Cassandra\Session
98
     */
99
    public function getCassandraSession()
100
    {
101
        return $this->session;
102
    }
103
104
    /**
105
     * Return the Cassandra keyspace
106
     *
107
     * @return string
108
     */
109
    public function getKeyspace()
110
    {
111
        return $this->keyspace;
112
    }
113
114
    /**
115
     * Create a new Cassandra cluster object.
116
     *
117
     * @param  array   $config
118
     *
119
     * @return \Cassandra\Cluster
120
     */
121
    protected function createCluster(array $config)
122
    {
123
        $cluster = Cassandra::cluster();
124
125
        // Authentication
126
        if (isset($config['username']) && isset($config['password'])) {
127
            $cluster->withCredentials($config['username'], $config['password']);
128
        }
129
130
        // Contact Points/Host
131
        if (!empty($config['host'])) {
132
            $contactPoints = $config['host'];
133
134
            if (is_array($contactPoints)) {
135
                $contactPoints = implode(',', $contactPoints);
136
            }
137
138
            $cluster->withContactPoints($contactPoints);
139
        }
140
141
        if (!empty($config['port'])) {
142
            $cluster->withPort((int) $config['port']);
143
        }
144
145
        $cluster->withDefaultPageSize(intval(!empty($config['page_size']) ? $config['page_size'] : self::DEFAULT_PAGE_SIZE));
146
147
        if (isset($config['consistency']) && in_array($config['consistency'], [
148
                Cassandra::CONSISTENCY_ANY, Cassandra::CONSISTENCY_ONE, Cassandra::CONSISTENCY_TWO,
149
                Cassandra::CONSISTENCY_THREE, Cassandra::CONSISTENCY_QUORUM, Cassandra::CONSISTENCY_ALL,
150
                Cassandra::CONSISTENCY_SERIAL, Cassandra::CONSISTENCY_QUORUM, Cassandra::CONSISTENCY_LOCAL_QUORUM,
151
                Cassandra::CONSISTENCY_EACH_QUORUM, Cassandra::CONSISTENCY_LOCAL_SERIAL, Cassandra::CONSISTENCY_LOCAL_ONE,
152
            ])) {
153
154
            $cluster->withDefaultConsistency($config['consistency']);
155
        }
156
157
        if (!empty($config['timeout'])) {
158
            $cluster->withDefaultTimeout(intval($config['timeout']));
159
        }
160
161
        if (!empty($config['connect_timeout'])) {
162
            $cluster->withConnectTimeout(floatval($config['connect_timeout']));
163
        }
164
165
        if (!empty($config['request_timeout'])) {
166
            $cluster->withRequestTimeout(floatval($config['request_timeout']));
167
        }
168
169
        return $cluster->build();
170
    }
171
172
    /**
173
     * Disconnect from the underlying Cassandra connection.
174
     */
175
    public function disconnect()
176
    {
177
        unset($this->connection);
178
    }
179
180
    /**
181
     * Get the PDO driver name.
182
     *
183
     * @return string
184
     */
185
    public function getDriverName()
186
    {
187
        return 'cassandra';
188
    }
189
190
    /**
191
     * Run a select statement against the database.
192
     *
193
     * @param  string  $query
194
     * @param  array  $bindings
195
     * @param  bool  $useReadPdo
196
     * @param  array  $customOptions
197
     *
198
     * @return array
199
     */
200
    public function select($query, $bindings = [], $useReadPdo = true, array $customOptions = [])
201
    {
202
        return $this->runStatement($query, $bindings, $customOptions);
203
    }
204
205
    /**
206
     * Run an bulk insert statement against the database.
207
     *
208
     * @param  array  $queries
209
     * @param  array  $bindings
210
     * @param  int  $type
211
     * @param  array  $customOptions
212
     *
213
     * @return bool
214
     */
215
    public function insertBulk($queries = [], $bindings = [], $type = Cassandra::BATCH_LOGGED, array $customOptions = [])
216
    {
217
        return $this->batchStatement($queries, $bindings, $type, $customOptions);
218
    }
219
220
    /**
221
     * Execute a group of queries inside a batch statement against the database.
222
     *
223
     * @param  array  $queries
224
     * @param  array  $bindings
225
     * @param  int  $type
226
     * @param  array  $customOptions
227
     *
228
     * @return bool
229
     */
230
    public function batchStatement($queries = [], $bindings = [], $type = Cassandra::BATCH_LOGGED, array $customOptions = [])
231
    {
232
        return $this->run($queries, $bindings, function ($queries, $bindings) use ($type, $customOptions) {
0 ignored issues
show
Documentation introduced by
$queries is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
233
            if ($this->pretending()) {
234
                return [];
235
            }
236
237
            $batch = new BatchStatement($type);
238
239
            foreach ($queries as $k => $query) {
240
                $preparedStatement = $this->session->prepare($query);
241
                $batch->add($preparedStatement, $bindings[$k]);
242
            }
243
244
            return $this->session->execute($batch, $customOptions);
245
        });
246
    }
247
248
    /**
249
     * Execute an CQL statement and return the boolean result.
250
     *
251
     * @param  string  $query
252
     * @param  array   $bindings
253
     * @param  array  $customOptions
254
     *
255
     * @return bool
256
     */
257
    public function statement($query, $bindings = [], array $customOptions = [])
258
    {
259
        return $this->runStatement($query, $bindings, $customOptions);
260
    }
261
262
    /**
263
     * Because Cassandra is an eventually consistent database, it's not possible to obtain
264
     * the affected count for statements so we're just going to return 0, based on the idea
265
     * that if the query fails somehow, an exception will be thrown
266
     *
267
     * @param  string  $query
268
     * @param  array   $bindings
269
     * @param  array  $customOptions
270
     *
271
     * @return int
272
     */
273
    public function affectingStatement($query, $bindings = [], array $customOptions = [])
274
    {
275
        return $this->runStatement($query, $bindings, $customOptions, 0, 1);
276
    }
277
278
    /**
279
     * @inheritdoc
280
     */
281
    protected function getDefaultPostProcessor()
282
    {
283
        return new Query\Processor();
284
    }
285
286
    /**
287
     * @inheritdoc
288
     */
289
    protected function getDefaultQueryGrammar()
290
    {
291
        return new Query\Grammar();
292
    }
293
294
    /**
295
     * @inheritdoc
296
     */
297
    protected function getDefaultSchemaGrammar()
298
    {
299
        //return new Schema\Grammar();
300
    }
301
302
    /**
303
     * Reconnect to the database if connection is missing.
304
     *
305
     * @return void
306
     */
307
    protected function reconnectIfMissingConnection()
308
    {
309
        if (is_null($this->session)) {
310
            $this->session = $this->createCluster($this->config, [])->connect($this->keyspace);
0 ignored issues
show
Unused Code introduced by
The call to Connection::createCluster() has too many arguments starting with array().

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...
311
        }
312
    }
313
314
    /**
315
     * Dynamically pass methods to the connection.
316
     *
317
     * @param  string  $method
318
     * @param  array   $parameters
319
     * @return mixed
320
     */
321
    public function __call($method, $parameters)
322
    {
323
        return call_user_func_array([$this->cluster, $method], $parameters);
324
    }
325
326
    /**
327
     * Execute an CQL statement and return the boolean result.
328
     *
329
     * @param string $query
330
     * @param array $bindings
331
     * @param array $customOptions
332
     * @param mixed $defaultFailed
333
     * @param mixed $defaultSuccess
334
     *
335
     * @return mixed
336
     */
337
    protected function runStatement($query, $bindings = [], array $customOptions = [], $defaultFailed = [], $defaultSuccess = null)
338
    {
339
        return $this->run($query, $bindings, function ($query, $bindings) use ($customOptions, $defaultFailed, $defaultSuccess) {
340
            if ($this->pretending()) {
341
                return $defaultFailed;
342
            }
343
344
            $preparedStatement = $this->session->prepare($query);
345
346
            //Add bindings
347
            $customOptions['arguments'] = $bindings;
348
349
            $result = $this->session->execute($preparedStatement, $customOptions);
350
351
            return $defaultSuccess === null ? $result : $defaultSuccess;
352
        });
353
    }
354
}
355