Completed
Push — master ( 58d53e...73f4ae )
by Lukas
13:40
created

ConnectionFactory   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 163
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
dl 0
loc 163
rs 10
c 0
b 0
f 0
wmc 19
lcom 1
cbo 5

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 2
A getDefaultConnectionParams() 0 15 4
B getConnection() 0 33 5
A normalizeType() 0 3 2
A isValidType() 0 4 1
B createConnectionParams() 0 38 5
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Andreas Fischer <[email protected]>
6
 * @author Jörn Friedrich Dreyer <[email protected]>
7
 * @author Morris Jobke <[email protected]>
8
 * @author Robin Appelman <[email protected]>
9
 * @author Thomas Müller <[email protected]>
10
 *
11
 * @license AGPL-3.0
12
 *
13
 * This code is free software: you can redistribute it and/or modify
14
 * it under the terms of the GNU Affero General Public License, version 3,
15
 * as published by the Free Software Foundation.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
 * GNU Affero General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License, version 3,
23
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
24
 *
25
 */
26
27
namespace OC\DB;
28
use Doctrine\DBAL\Event\Listeners\OracleSessionInit;
29
use Doctrine\DBAL\Event\Listeners\SQLSessionInit;
30
use Doctrine\DBAL\Event\Listeners\MysqlSessionInit;
31
use OCP\IConfig;
32
33
/**
34
* Takes care of creating and configuring Doctrine connections.
35
*/
36
class ConnectionFactory {
37
	/**
38
	* @var array
39
	*
40
	* Array mapping DBMS type to default connection parameters passed to
41
	* \Doctrine\DBAL\DriverManager::getConnection().
42
	*/
43
	protected $defaultConnectionParams = array(
44
		'mysql' => array(
45
			'adapter' => '\OC\DB\AdapterMySQL',
46
			'charset' => 'UTF8',
47
			'driver' => 'pdo_mysql',
48
			'wrapperClass' => 'OC\DB\Connection',
49
		),
50
		'oci' => array(
51
			'adapter' => '\OC\DB\AdapterOCI8',
52
			'charset' => 'AL32UTF8',
53
			'driver' => 'oci8',
54
			'wrapperClass' => 'OC\DB\OracleConnection',
55
		),
56
		'pgsql' => array(
57
			'adapter' => '\OC\DB\AdapterPgSql',
58
			'driver' => 'pdo_pgsql',
59
			'wrapperClass' => 'OC\DB\Connection',
60
		),
61
		'sqlite3' => array(
62
			'adapter' => '\OC\DB\AdapterSqlite',
63
			'driver' => 'pdo_sqlite',
64
			'wrapperClass' => 'OC\DB\Connection',
65
		),
66
	);
67
68
	public function __construct(IConfig $config) {
69
		if($config->getSystemValue('mysql.utf8mb4', false)) {
70
			$this->defaultConnectionParams['mysql']['charset'] = 'utf8mb4';
71
		}
72
	}
73
74
	/**
75
	* @brief Get default connection parameters for a given DBMS.
76
	* @param string $type DBMS type
77
	* @throws \InvalidArgumentException If $type is invalid
78
	* @return array Default connection parameters.
79
	*/
80
	public function getDefaultConnectionParams($type) {
81
		$normalizedType = $this->normalizeType($type);
82
		if (!isset($this->defaultConnectionParams[$normalizedType])) {
83
			throw new \InvalidArgumentException("Unsupported type: $type");
84
		}
85
		$result = $this->defaultConnectionParams[$normalizedType];
86
		// \PDO::MYSQL_ATTR_FOUND_ROWS may not be defined, e.g. when the MySQL
87
		// driver is missing. In this case, we won't be able to connect anyway.
88
		if ($normalizedType === 'mysql' && defined('\PDO::MYSQL_ATTR_FOUND_ROWS')) {
89
			$result['driverOptions'] = array(
90
				\PDO::MYSQL_ATTR_FOUND_ROWS => true,
91
			);
92
		}
93
		return $result;
94
	}
95
96
	/**
97
	* @brief Get default connection parameters for a given DBMS.
98
	* @param string $type DBMS type
99
	* @param array $additionalConnectionParams Additional connection parameters
100
	* @return \OC\DB\Connection
101
	*/
102
	public function getConnection($type, $additionalConnectionParams) {
103
		$normalizedType = $this->normalizeType($type);
104
		$eventManager = new \Doctrine\Common\EventManager();
105
		switch ($normalizedType) {
106
			case 'mysql':
107
				// Send "SET NAMES utf8". Only required on PHP 5.3 below 5.3.6.
108
				// See http://stackoverflow.com/questions/4361459/php-pdo-charset-set-names#4361485
109
				$eventManager->addEventSubscriber(new MysqlSessionInit(
110
					$this->defaultConnectionParams['mysql']['charset']
111
				));
112
				$eventManager->addEventSubscriber(
113
					new SQLSessionInit("SET SESSION AUTOCOMMIT=1"));
114
				break;
115
			case 'oci':
116
				$eventManager->addEventSubscriber(new OracleSessionInit);
117
				// the driverOptions are unused in dbal and need to be mapped to the parameters
118
				if (isset($additionalConnectionParams['driverOptions'])) {
119
					$additionalConnectionParams = array_merge($additionalConnectionParams, $additionalConnectionParams['driverOptions']);
120
				}
121
				break;
122
			case 'sqlite3':
123
				$journalMode = $additionalConnectionParams['sqlite.journal_mode'];
124
				$additionalConnectionParams['platform'] = new OCSqlitePlatform();
125
				$eventManager->addEventSubscriber(new SQLiteSessionInit(true, $journalMode));
126
				break;
127
		}
128
		$connection = \Doctrine\DBAL\DriverManager::getConnection(
129
			array_merge($this->getDefaultConnectionParams($type), $additionalConnectionParams),
130
			new \Doctrine\DBAL\Configuration(),
131
			$eventManager
132
		);
133
		return $connection;
134
	}
135
136
	/**
137
	* @brief Normalize DBMS type
138
	* @param string $type DBMS type
139
	* @return string Normalized DBMS type
140
	*/
141
	public function normalizeType($type) {
142
		return $type === 'sqlite' ? 'sqlite3' : $type;
143
	}
144
145
	/**
146
	* @brief Checks whether the specified DBMS type is valid.
147
	* @return bool
148
	*/
149
	public function isValidType($type) {
150
		$normalizedType = $this->normalizeType($type);
151
		return isset($this->defaultConnectionParams[$normalizedType]);
152
	}
153
154
	/**
155
	 * Create the connection parameters for the config
156
	 *
157
	 * @param \OC\SystemConfig $config
158
	 * @return array
159
	 */
160
	public function createConnectionParams($config) {
161
		$type = $config->getValue('dbtype', 'sqlite');
162
163
		$connectionParams = array(
164
			'user' => $config->getValue('dbuser', ''),
165
			'password' => $config->getValue('dbpassword', ''),
166
		);
167
		$name = $config->getValue('dbname', 'owncloud');
168
169
		if ($this->normalizeType($type) === 'sqlite3') {
170
			$dataDir = $config->getValue("datadirectory", \OC::$SERVERROOT . '/data');
171
			$connectionParams['path'] = $dataDir . '/' . $name . '.db';
172
		} else {
173
			$host = $config->getValue('dbhost', '');
174
			if (strpos($host, ':')) {
175
				// Host variable may carry a port or socket.
176
				list($host, $portOrSocket) = explode(':', $host, 2);
177
				if (ctype_digit($portOrSocket)) {
178
					$connectionParams['port'] = $portOrSocket;
179
				} else {
180
					$connectionParams['unix_socket'] = $portOrSocket;
181
				}
182
			}
183
			$connectionParams['host'] = $host;
184
			$connectionParams['dbname'] = $name;
185
		}
186
187
		$connectionParams['tablePrefix'] = $config->getValue('dbtableprefix', 'oc_');
188
		$connectionParams['sqlite.journal_mode'] = $config->getValue('sqlite.journal_mode', 'WAL');
189
190
		//additional driver options, eg. for mysql ssl
191
		$driverOptions = $config->getValue('dbdriveroptions', null);
192
		if ($driverOptions) {
193
			$connectionParams['driverOptions'] = $driverOptions;
194
		}
195
196
		return $connectionParams;
197
	}
198
}
199