Failed Conditions
Branch newinternal (bd75e4)
by Simon
03:48
created

PdoDatabase::prepare()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 32
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20
Metric Value
dl 0
loc 32
ccs 0
cts 17
cp 0
rs 8.5806
cc 4
eloc 20
nc 6
nop 2
crap 20
1
<?php
2
namespace Waca;
3
4
use Exception;
5
use PDO;
6
use PDOException;
7
use Waca\Exceptions\EnvironmentException;
8
9
class PdoDatabase extends PDO
10
{
11
	/**
12
	 * @var PdoDatabase[]
13
	 */
14
	private static $connections = array();
15
	/**
16
	 * @var bool True if a transaction is active
17
	 */
18
	protected $hasActiveTransaction = false;
19
20
	/**
21
	 * Unless you're doing low-level work, this is not the function you want.
22
	 *
23
	 * @param string $connectionName
24
	 *
25
	 * @return PdoDatabase
26
	 * @throws Exception
27
	 */
28
	public static function getDatabaseConnection($connectionName)
29
	{
30
		if (!isset(self::$connections[$connectionName])) {
31
			global $cDatabaseConfig;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
32
33
			if (!array_key_exists($connectionName, $cDatabaseConfig)) {
34
				throw new Exception("Database configuration not found for alias $connectionName");
35
			}
36
37
			try {
38
				$databaseObject = new PdoDatabase(
39
					$cDatabaseConfig[$connectionName]["dsrcname"],
40
					$cDatabaseConfig[$connectionName]["username"],
41
					$cDatabaseConfig[$connectionName]["password"]
42
				);
43
			}
44
			catch (PDOException $ex) {
45
				// wrap around any potential stack traces which may include passwords
46
				throw new EnvironmentException("Error connecting to database '$connectionName': " . $ex->getMessage());
47
			}
48
49
			$databaseObject->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
50
51
			// emulating prepared statements gives a performance boost on MySQL.
52
			//
53
			// however, our version of PDO doesn't seem to understand parameter types when emulating
54
			// the prepared statements, so we're forced to turn this off for now.
55
			// -- stw 2014-02-11
56
			$databaseObject->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
57
58
			self::$connections[$connectionName] = $databaseObject;
59
		}
60
61
		return self::$connections[$connectionName];
62
	}
63
64
	/**
65
	 * Determines if this connection has a transaction in progress or not
66
	 * @return boolean true if there is a transaction in progress.
67
	 */
68
	public function hasActiveTransaction()
69
	{
70
		return $this->hasActiveTransaction;
71
	}
72
73
	/**
74
	 * Summary of beginTransaction
75
	 * @return bool
76
	 */
77
	public function beginTransaction()
78
	{
79
		// Override the pre-existing method, which doesn't stop you from
80
		// starting transactions within transactions - which doesn't work and
81
		// will throw an exception. This eliminates the need to catch exceptions
82
		// all over the rest of the code
83
		if ($this->hasActiveTransaction) {
84
			return false;
85
		}
86
		else {
87
			// set the transaction isolation level for every transaction.
88
			$this->exec("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;");
89
90
			// start a new transaction, and return whether or not the start was
91
			// successful
92
			$this->hasActiveTransaction = parent::beginTransaction();
93
94
			return $this->hasActiveTransaction;
95
		}
96
	}
97
98
	/**
99
	 * Commits the active transaction
100
	 */
101
	public function commit()
102
	{
103
		if ($this->hasActiveTransaction) {
104
			parent::commit();
105
			$this->hasActiveTransaction = false;
106
		}
107
	}
108
109
	/**
110
	 * Rolls back a transaction
111
	 */
112
	public function rollBack()
113
	{
114
		if ($this->hasActiveTransaction) {
115
			parent::rollback();
116
			$this->hasActiveTransaction = false;
117
		}
118
	}
119
}
120