Completed
Branch 5.3 (dfff57)
by Arjay
14:48
created

Oci8Connection::bindValues()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 4
eloc 6
c 2
b 1
f 0
nc 2
nop 2
dl 0
loc 10
rs 9.2
1
<?php
2
3
namespace Yajra\Oci8;
4
5
use Doctrine\DBAL\Connection as DoctrineConnection;
6
use Doctrine\DBAL\Driver\OCI8\Driver as DoctrineDriver;
7
use Illuminate\Database\Connection;
8
use Illuminate\Database\Grammar;
9
use PDO;
10
use Yajra\Oci8\Query\Grammars\OracleGrammar as QueryGrammar;
11
use Yajra\Oci8\Query\OracleBuilder as QueryBuilder;
12
use Yajra\Oci8\Query\Processors\OracleProcessor as Processor;
13
use Yajra\Oci8\Schema\Grammars\OracleGrammar as SchemaGrammar;
14
use Yajra\Oci8\Schema\OracleBuilder as SchemaBuilder;
15
use Yajra\Oci8\Schema\Sequence;
16
use Yajra\Oci8\Schema\Trigger;
17
18
class Oci8Connection extends Connection
19
{
20
    /**
21
     * @var string
22
     */
23
    protected $schema;
24
25
    /**
26
     * @var \Yajra\Oci8\Schema\Sequence
27
     */
28
    protected $sequence;
29
30
    /**
31
     * @var \Yajra\Oci8\Schema\Trigger
32
     */
33
    protected $trigger;
34
35
    /**
36
     * @param PDO|\Closure $pdo
37
     * @param string $database
38
     * @param string $tablePrefix
39
     * @param array $config
40
     */
41
    public function __construct($pdo, $database = '', $tablePrefix = '', array $config = [])
42
    {
43
        parent::__construct($pdo, $database, $tablePrefix, $config);
44
        $this->sequence = new Sequence($this);
45
        $this->trigger  = new Trigger($this);
46
    }
47
48
    /**
49
     * Get current schema.
50
     *
51
     * @return string
52
     */
53
    public function getSchema()
54
    {
55
        return $this->schema;
56
    }
57
58
    /**
59
     * Set current schema.
60
     *
61
     * @param string $schema
62
     * @return $this
63
     */
64
    public function setSchema($schema)
65
    {
66
        $this->schema = $schema;
67
        $sessionVars  = [
68
            'CURRENT_SCHEMA' => $schema,
69
        ];
70
71
        return $this->setSessionVars($sessionVars);
72
    }
73
74
    /**
75
     * Update oracle session variables.
76
     *
77
     * @param array $sessionVars
78
     * @return $this
79
     */
80
    public function setSessionVars(array $sessionVars)
81
    {
82
        $vars = [];
83
        foreach ($sessionVars as $option => $value) {
84
            if (strtoupper($option) == 'CURRENT_SCHEMA') {
85
                $vars[] = "$option  = $value";
86
            } else {
87
                $vars[] = "$option  = '$value'";
88
            }
89
        }
90
        if ($vars) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $vars of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
91
            $sql = "ALTER SESSION SET " . implode(" ", $vars);
92
            $this->statement($sql);
93
        }
94
95
        return $this;
96
    }
97
98
    /**
99
     * Get sequence class.
100
     *
101
     * @return \Yajra\Oci8\Schema\Sequence
102
     */
103
    public function getSequence()
104
    {
105
        return $this->sequence;
106
    }
107
108
    /**
109
     * Set sequence class.
110
     *
111
     * @param \Yajra\Oci8\Schema\Sequence $sequence
112
     * @return \Yajra\Oci8\Schema\Sequence
113
     */
114
    public function setSequence(Sequence $sequence)
115
    {
116
        return $this->sequence = $sequence;
117
    }
118
119
    /**
120
     * Get oracle trigger class.
121
     *
122
     * @return \Yajra\Oci8\Schema\Trigger
123
     */
124
    public function getTrigger()
125
    {
126
        return $this->trigger;
127
    }
128
129
    /**
130
     * Set oracle trigger class.
131
     *
132
     * @param \Yajra\Oci8\Schema\Trigger $trigger
133
     * @return \Yajra\Oci8\Schema\Trigger
134
     */
135
    public function setTrigger(Trigger $trigger)
136
    {
137
        return $this->trigger = $trigger;
138
    }
139
140
    /**
141
     * Get a schema builder instance for the connection.
142
     *
143
     * @return \Yajra\Oci8\Schema\OracleBuilder
144
     */
145
    public function getSchemaBuilder()
146
    {
147
        if (is_null($this->schemaGrammar)) {
148
            $this->useDefaultSchemaGrammar();
149
        }
150
151
        return new SchemaBuilder($this);
152
    }
153
154
    /**
155
     * Begin a fluent query against a database table.
156
     *
157
     * @param  string $table
158
     * @return \Yajra\Oci8\Query\OracleBuilder
159
     */
160
    public function table($table)
161
    {
162
        $processor = $this->getPostProcessor();
163
164
        $query = new QueryBuilder($this, $this->getQueryGrammar(), $processor);
165
166
        return $query->from($table);
167
    }
168
169
    /**
170
     * Set oracle session date format.
171
     *
172
     * @param string $format
173
     * @return $this
174
     */
175
    public function setDateFormat($format = 'YYYY-MM-DD HH24:MI:SS')
176
    {
177
        $sessionVars = [
178
            'NLS_DATE_FORMAT'      => $format,
179
            'NLS_TIMESTAMP_FORMAT' => $format,
180
        ];
181
182
        return $this->setSessionVars($sessionVars);
183
    }
184
185
    /**
186
     * Get doctrine connection.
187
     *
188
     * @return \Doctrine\DBAL\Connection
189
     */
190
    public function getDoctrineConnection()
191
    {
192
        $driver = $this->getDoctrineDriver();
193
194
        $data = ['pdo' => $this->getPdo(), 'user' => $this->getConfig('username')];
195
196
        return new DoctrineConnection($data, $driver);
197
    }
198
199
    /**
200
     * Get doctrine driver.
201
     *
202
     * @return \Doctrine\DBAL\Driver\OCI8\Driver
203
     */
204
    protected function getDoctrineDriver()
205
    {
206
        return new DoctrineDriver;
207
    }
208
209
    /**
210
     * Execute a PL/SQL Function and return its value.
211
     * Usage: DB::executeFunction('function_name(:binding_1,:binding_n)', [':binding_1' => 'hi', ':binding_n' =>
212
     * 'bye'], PDO::PARAM_LOB)
213
     *
214
     * @author Tylerian - [email protected]
215
     * @param string $sql (mixed)
216
     * @param array $bindings (kvp array)
217
     * @param int $returnType (PDO::PARAM_*)
218
     * @return mixed $returnType
219
     */
220
    public function executeFunction($sql, array $bindings = [], $returnType = PDO::PARAM_STR)
221
    {
222
        $query = $this->getPdo()->prepare('begin :result := ' . $sql . '; end;');
223
224
        foreach ($bindings as $key => &$value) {
225
            if (! preg_match('/^:(.*)$/i', $key)) {
226
                $key = ':' . $key;
227
            }
228
229
            $query->bindParam($key, $value);
230
        }
231
232
        $query->bindParam(':result', $result, $returnType);
233
        $query->execute();
234
235
        return $result;
236
    }
237
238
    /**
239
     * Bind values to their parameters in the given statement.
240
     *
241
     * @param  \PDOStatement $statement
242
     * @param  array $bindings
243
     * @return void
244
     */
245
    public function bindValues($statement, $bindings)
246
    {
247
        foreach ($bindings as $key => $value) {
248
            $statement->bindParam(
249
                $key,
250
                $bindings[$key],
251
                ! is_string($value) && is_numeric($value) ? PDO::PARAM_INT : PDO::PARAM_STR
252
            );
253
        }
254
    }
255
256
    /**
257
     * Get the default query grammar instance.
258
     *
259
     * @return \Illuminate\Database\Grammar|\Yajra\Oci8\Query\Grammars\OracleGrammar
260
     */
261
    protected function getDefaultQueryGrammar()
262
    {
263
        return $this->withTablePrefix(new QueryGrammar);
264
    }
265
266
    /**
267
     * Set the table prefix and return the grammar.
268
     *
269
     * @param \Illuminate\Database\Grammar|\Yajra\Oci8\Query\Grammars\OracleGrammar|\Yajra\Oci8\Schema\Grammars\OracleGrammar $grammar
270
     * @return \Illuminate\Database\Grammar
271
     */
272
    public function withTablePrefix(Grammar $grammar)
273
    {
274
        return $this->withSchemaPrefix(parent::withTablePrefix($grammar));
275
    }
276
277
    /**
278
     * Set the schema prefix and return the grammar.
279
     *
280
     * @param \Illuminate\Database\Grammar|\Yajra\Oci8\Query\Grammars\OracleGrammar|\Yajra\Oci8\Schema\Grammars\OracleGrammar $grammar
281
     * @return \Illuminate\Database\Grammar
282
     */
283
    public function withSchemaPrefix(Grammar $grammar)
284
    {
285
        $grammar->setSchemaPrefix($this->getConfigSchemaPrefix());
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Illuminate\Database\Grammar as the method setSchemaPrefix() does only exist in the following sub-classes of Illuminate\Database\Grammar: Yajra\Oci8\Query\Grammars\OracleGrammar, Yajra\Oci8\Schema\Grammars\OracleGrammar. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
286
287
        return $grammar;
288
    }
289
290
    /**
291
     * Get config schema prefix.
292
     *
293
     * @return string
294
     */
295
    protected function getConfigSchemaPrefix()
296
    {
297
        return isset($this->config['prefix_schema']) ? $this->config['prefix_schema'] : '';
298
    }
299
300
    /**
301
     * Get the default schema grammar instance.
302
     *
303
     * @return \Illuminate\Database\Grammar|\Yajra\Oci8\Schema\Grammars\OracleGrammar
304
     */
305
    protected function getDefaultSchemaGrammar()
306
    {
307
        return $this->withTablePrefix(new SchemaGrammar);
308
    }
309
310
    /**
311
     * Get the default post processor instance.
312
     *
313
     * @return \Yajra\Oci8\Query\Processors\OracleProcessor
314
     */
315
    protected function getDefaultPostProcessor()
316
    {
317
        return new Processor;
318
    }
319
}
320