Passed
Push — master ( 78ff77...606203 )
by Aimeos
04:53
created

PDO::createConnection()   B

Complexity

Conditions 8
Paths 10

Size

Total Lines 35
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 19
dl 0
loc 35
rs 8.4444
c 0
b 0
f 0
cc 8
nc 10
nop 2
1
<?php
2
3
/**
4
 * @license LGPLv3, https://opensource.org/licenses/LGPL-3.0
5
 * @copyright Metaways Infosystems GmbH, 2011
6
 * @copyright Aimeos (aimeos.org), 2015-2022
7
 * @package MW
8
 * @subpackage DB
9
 */
10
11
12
namespace Aimeos\Base\DB\Manager;
13
14
15
/**
16
 * Manager for database connections using the \PDO library.
17
 *
18
 * @package MW
19
 * @subpackage DB
20
 */
21
class PDO implements \Aimeos\Base\DB\Manager\Iface
22
{
23
	private $connections = [];
24
	private $count = [];
25
	private $config;
26
27
28
	/**
29
	 * Initializes the database manager object
30
	 *
31
	 * @param \Aimeos\Base\Config\Iface $config Object holding the configuration data
32
	 */
33
	public function __construct( \Aimeos\Base\Config\Iface $config )
34
	{
35
		$this->config = $config;
36
	}
37
38
39
	/**
40
	 * Cleans up the object
41
	 */
42
	public function __destruct()
43
	{
44
		foreach( $this->connections as $name => $list )
45
		{
46
			foreach( $list as $key => $conn ) {
47
				unset( $this->connections[$name][$key] );
48
			}
49
		}
50
	}
51
52
53
	/**
54
	 * Reset when cloning the object
55
	 */
56
	public function __clone()
57
	{
58
		$this->connections = [];
59
		$this->count = [];
60
	}
61
62
63
	/**
64
	 * Clean up the objects inside
65
	 */
66
	public function __sleep()
67
	{
68
		$this->__destruct();
69
70
		$this->connections = [];
71
		$this->count = [];
72
73
		return get_object_vars( $this );
74
	}
75
76
77
	/**
78
	 * Returns a database connection.
79
	 *
80
	 * @param string $name Name of the resource in configuration
81
	 * @return \Aimeos\Base\DB\Connection\Iface
82
	 */
83
	public function acquire( string $name = 'db' ) : \Aimeos\Base\DB\Connection\Iface
84
	{
85
		try
86
		{
87
			if( $this->config->get( 'resource/' . $name ) === null ) {
88
				$name = 'db';
89
			}
90
91
			$adapter = $this->config->get( 'resource/' . $name . '/adapter', 'mysql' );
92
93
			if( !isset( $this->connections[$name] ) || empty( $this->connections[$name] ) )
94
			{
95
				if( !isset( $this->count[$name] ) ) {
96
					$this->count[$name] = 0;
97
				}
98
99
				$limit = $this->config->get( 'resource/' . $name . '/limit', -1 );
100
101
				if( $limit >= 0 && $this->count[$name] >= $limit )
102
				{
103
					$msg = sprintf( 'Maximum number of connections (%1$d) for "%2$s" exceeded', $limit, $name );
104
					throw new \Aimeos\Base\DB\Exception( $msg );
105
				}
106
107
				$this->connections[$name] = array( $this->createConnection( $name, $adapter ) );
108
				$this->count[$name]++;
109
			}
110
111
			return array_pop( $this->connections[$name] );
112
		}
113
		catch( \PDOException $e ) {
114
			throw new \Aimeos\Base\DB\Exception( $e->getMessage(), $e->getCode(), $e->errorInfo );
115
		}
116
	}
117
118
119
	/**
120
	 * Releases the connection for reuse
121
	 *
122
	 * @param \Aimeos\Base\DB\Connection\Iface $connection Connection object
123
	 * @param string $name Name of resource
124
	 */
125
	public function release( \Aimeos\Base\DB\Connection\Iface $connection, string $name = 'db' )
126
	{
127
		if( ( $connection instanceof \Aimeos\Base\DB\Connection\PDO ) === false ) {
128
			throw new \Aimeos\Base\DB\Exception( 'Connection object isn\'t of type \PDO' );
129
		}
130
131
		if( $this->config->get( 'resource/' . $name ) === null ) {
132
			$name = 'db';
133
		}
134
135
		$this->connections[$name][] = $connection;
136
	}
137
138
139
	/**
140
	 * Creates a new database connection.
141
	 *
142
	 * @param string $name Name to the database configuration in the resource file
143
	 * @param string $adapter Name of the database adapter, e.g. "mysql"
144
	 * @return \Aimeos\Base\DB\Connection\Iface Database connection
145
	 */
146
	protected function createConnection( string $name, string $adapter ) : \Aimeos\Base\DB\Connection\Iface
147
	{
148
		$params = $this->config->get( 'resource/' . $name );
149
150
		if( !isset( $params['dsn'] ) )
151
		{
152
			$host = $this->config->get( 'resource/' . $name . '/host' );
153
			$port = $this->config->get( 'resource/' . $name . '/port' );
154
			$sock = $this->config->get( 'resource/' . $name . '/socket' );
155
			$dbase = $this->config->get( 'resource/' . $name . '/database' );
156
157
			$dsn = $adapter . ':';
158
159
			if( $adapter === 'sqlsrv' )
160
			{
161
				$dsn .= 'Database=' . $dbase;
162
				$dsn .= isset( $host ) ? ';Server=' . $host . ( isset( $port ) ? ',' . $port : '' ) : '';
163
			}
164
			elseif( $sock == null )
165
			{
166
				$dsn .= 'dbname=' . $dbase;
167
				$dsn .= isset( $host ) ? ';host=' . $host : '';
168
				$dsn .= isset( $port ) ? ';port=' . $port : '';
169
			}
170
			else
171
			{
172
				$dsn .= 'dbname=' . $dbase . ';unix_socket=' . $sock;
173
			}
174
175
			$params['dsn'] = $dsn;
176
		}
177
178
		$stmts = $this->config->get( 'resource/' . $name . '/stmt', [] );
179
180
		return new \Aimeos\Base\DB\Connection\PDO( $params, $stmts );
181
	}
182
}
183