Passed
Push — master ( 1a5f01...95cf58 )
by Aimeos
09:39
created

PDO::close()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 8
rs 10
cc 2
nc 2
nop 0
1
<?php
2
3
/**
4
 * @license LGPLv3, https://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2015-2022
6
 * @package Base
7
 * @subpackage DB
8
 */
9
10
11
namespace Aimeos\Base\DB\Connection;
12
13
14
/**
15
 * Database connection class for \PDO connections.
16
 *
17
 * @package Base
18
 * @subpackage DB
19
 */
20
class PDO extends \Aimeos\Base\DB\Connection\Base implements \Aimeos\Base\DB\Connection\Iface
21
{
22
	private $connection;
23
	private $txnumber = 0;
24
	private $stmts = [];
25
26
27
	/**
28
	 * Initializes the PDO connection object.
29
	 *
30
	 * @param array $params Associative list of connection parameters
31
	 * @param string[] $stmts List of SQL statements to execute after connecting
32
	 */
33
	public function __construct( array $params, array $stmts )
34
	{
35
		parent::__construct( $params );
36
37
		$this->stmts = $stmts;
38
		$this->connect();
39
	}
40
41
42
	/**
43
	 * Closes the connection to the database server
44
	 *
45
	 * @return \Aimeos\MW\DB\Connection\Iface Connection instance for method chaining
0 ignored issues
show
Bug introduced by
The type Aimeos\MW\DB\Connection\Iface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
46
	 */
47
	public function close() : Iface
48
	{
49
		if( $this->inTransaction() ) {
50
			$this->rollback();
51
		}
52
53
		unset( $this->connection );
54
		return $this;
55
	}
56
57
58
	/**
59
	 * Connects (or reconnects) to the database server
60
	 *
61
	 * @return \Aimeos\Base\DB\Connection\Iface Connection instance for method chaining
62
	 */
63
	public function connect() : Iface
64
	{
65
		$param = $this->getParameters();
66
		$param['driverOptions'][\PDO::ATTR_CASE] = \PDO::CASE_NATURAL;
67
		$param['driverOptions'][\PDO::ATTR_ERRMODE] = \PDO::ERRMODE_EXCEPTION;
68
		$param['driverOptions'][\PDO::ATTR_ORACLE_NULLS] = \PDO::NULL_NATURAL;
69
		$param['driverOptions'][\PDO::ATTR_STRINGIFY_FETCHES] = false;
70
71
		$pdo = new \PDO( $param['dsn'], $param['username'] ?? '', $param['password'] ?? '', $param['driverOptions'] );
72
		$conn = $this->connection;
73
74
		$this->connection = $pdo;
75
		$this->txnumber = 0;
76
77
		unset( $conn );
78
79
		foreach( $this->stmts as $stmt ) {
80
			$this->create( $stmt )->execute()->finish();
81
		}
82
83
		return $this;
84
	}
85
86
87
	/**
88
	 * Creates a \PDO database statement.
89
	 *
90
	 * @param string $sql SQL statement, maybe with place holders
91
	 * @return \Aimeos\Base\DB\Statement\Iface PDO statement object
92
	 * @throws \Aimeos\Base\DB\Exception if type is invalid or the \PDO object throws an exception
93
	 */
94
	public function create( string $sql ) : \Aimeos\Base\DB\Statement\Iface
95
	{
96
		try
97
		{
98
			if( strpos( $sql, '?' ) === false ) {
99
				return new \Aimeos\Base\DB\Statement\PDO\Simple( $this, $sql );
100
			}
101
102
			return new \Aimeos\Base\DB\Statement\PDO\Prepared( $this, $sql );
103
		}
104
		catch( \PDOException $e )
105
		{
106
			throw new \Aimeos\Base\DB\Exception( $e->getMessage(), $e->getCode(), $e->errorInfo );
107
		}
108
	}
109
110
111
	/**
112
	 * Returns the underlying connection object
113
	 *
114
	 * @return \PDO Underlying connection object
115
	 */
116
	public function getRawObject()
117
	{
118
		return $this->connection;
119
	}
120
121
122
	/**
123
	 * Checks if a transaction is currently running
124
	 *
125
	 * @return bool True if transaction is currently running, false if not
126
	 */
127
	public function inTransaction() : bool
128
	{
129
		return $this->connection->inTransaction();
130
	}
131
132
133
	/**
134
	 * Starts a transaction for this connection.
135
	 *
136
	 * Transactions can't be nested and a new transaction can only be started
137
	 * if the previous transaction was committed or rolled back before.
138
	 *
139
	 * @return \Aimeos\Base\DB\Connection\Iface Connection instance for method chaining
140
	 */
141
	public function begin() : Iface
142
	{
143
		if( $this->txnumber === 0 )
144
		{
145
			if( $this->connection->beginTransaction() === false ) {
146
				throw new \Aimeos\Base\DB\Exception( 'Unable to start new transaction' );
147
			}
148
		}
149
150
		$this->txnumber++;
151
		return $this;
152
	}
153
154
155
	/**
156
	 * Commits the changes done inside of the transaction to the storage.
157
	 *
158
	 * @return \Aimeos\Base\DB\Connection\Iface Connection instance for method chaining
159
	 */
160
	public function commit() : Iface
161
	{
162
		if( $this->txnumber === 1 )
163
		{
164
			if( $this->connection->commit() === false ) {
165
				throw new \Aimeos\Base\DB\Exception( 'Failed to commit transaction' );
166
			}
167
		}
168
169
		$this->txnumber--;
170
		return $this;
171
	}
172
173
174
	/**
175
	 * Discards the changes done inside of the transaction.
176
	 *
177
	 * @return \Aimeos\Base\DB\Connection\Iface Connection instance for method chaining
178
	 */
179
	public function rollback() : Iface
180
	{
181
		if( $this->txnumber === 1 )
182
		{
183
			if( $this->connection->rollBack() === false ) {
184
				throw new \Aimeos\Base\DB\Exception( 'Failed to roll back transaction' );
185
			}
186
		}
187
188
		$this->txnumber--;
189
		return $this;
190
	}
191
}
192