1
|
|
|
<?php declare(strict_types=1); |
2
|
|
|
/** |
3
|
|
|
* @package Terah\FluentPdoModel |
4
|
|
|
* |
5
|
|
|
* Licensed under The MIT License |
6
|
|
|
* For full copyright and license information, please see the LICENSE.txt |
7
|
|
|
* Redistributions of files must retain the above copyright notice. |
8
|
|
|
* |
9
|
|
|
* @license http://www.opensource.org/licenses/mit-license.php MIT License |
10
|
|
|
*/ |
11
|
|
|
namespace Terah\FluentPdoModel; |
12
|
|
|
|
13
|
|
|
use Psr\Log\LoggerInterface; |
14
|
|
|
use Terah\FluentPdoModel\Drivers\AbstractPdo; |
15
|
|
|
use Terah\FluentPdoModel\Drivers\DriverInterface; |
16
|
|
|
use Terah\RedisCache\CacheInterface; |
17
|
|
|
use function Terah\Assert\Assert; |
18
|
|
|
|
19
|
|
|
class ConnectionPool |
20
|
|
|
{ |
21
|
|
|
/** |
22
|
|
|
* @var DriverInterface|\Closure[] $_connections |
23
|
|
|
*/ |
24
|
|
|
protected $_connections = []; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* @var ConnectionPool |
28
|
|
|
*/ |
29
|
|
|
static protected $instance = null; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* Constructor |
33
|
|
|
*/ |
34
|
|
|
protected function __construct() |
35
|
|
|
{} |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @param array $connections |
39
|
|
|
* @param LoggerInterface $logger |
40
|
|
|
* @param CacheInterface $cache |
41
|
|
|
*/ |
42
|
|
|
public function addConnections(array $connections=[], LoggerInterface $logger=null, CacheInterface $cache=null) |
43
|
|
|
{ |
44
|
|
|
foreach ( $connections as $name => $conn ) |
45
|
|
|
{ |
46
|
|
|
$this->addConnection($name, $conn, $logger, $cache); |
47
|
|
|
} |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* @param array $config |
52
|
|
|
* @param LoggerInterface|null $logger |
53
|
|
|
* @param CacheInterface|null $cache |
54
|
|
|
* @return \Closure |
55
|
|
|
*/ |
56
|
|
|
public static function getDriverFromArray(array $config, LoggerInterface $logger=null, CacheInterface $cache=null) : \Closure |
57
|
|
|
{ |
58
|
|
|
$dsn = $user = $pass = ''; |
59
|
|
|
extract($config); |
60
|
|
|
unset($config['dsn'],$config['user'], $config['pass']); |
61
|
|
|
Assert($dsn)->notEmpty("The dsn cannot be empty."); |
62
|
|
|
$driver = 'Terah\\FluentPdoModel\\Drivers\\' . ucfirst(strtolower(substr($dsn, 0, strpos($dsn, ':')))) . 'Pdo'; |
63
|
|
|
Assert($driver)->classExists("The database driver {$driver} is not supported."); |
64
|
|
|
|
65
|
|
|
return function() use ($driver, $dsn, $user, $pass, $config, $logger, $cache) { |
66
|
|
|
|
67
|
|
|
return new $driver($dsn, $user, $pass, $config, $logger, $cache); |
68
|
|
|
}; |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* @param String $name |
73
|
|
|
* @param DriverInterface|array|\Closure $conn |
74
|
|
|
* @param LoggerInterface $logger |
75
|
|
|
* @param CacheInterface $cache |
76
|
|
|
* |
77
|
|
|
* @return ConnectionPool |
78
|
|
|
* @throws \Exception |
79
|
|
|
*/ |
80
|
|
|
public function addConnection(string $name, $conn, LoggerInterface $logger=null, CacheInterface $cache=null) : ConnectionPool |
81
|
|
|
{ |
82
|
|
|
Assert($name)->notEmpty("The connection name cannot be empty."); |
83
|
|
|
Assert($conn)->notEmpty("The connection details cannot be empty."); |
84
|
|
|
|
85
|
|
|
if ( $conn instanceof AbstractPdo || $conn instanceof \Closure ) |
86
|
|
|
{ |
87
|
|
|
$this->_connections[$name] = $conn; |
88
|
|
|
|
89
|
|
|
return $this; |
90
|
|
|
} |
91
|
|
|
$this->_connections[$name] = static::getDriverFromArray($conn, $logger, $cache); |
|
|
|
|
92
|
|
|
|
93
|
|
|
return $this; |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* @param $name |
98
|
|
|
* @param AbstractPdo $conn |
99
|
|
|
* @return ConnectionPool |
100
|
|
|
*/ |
101
|
|
|
public static function add(string $name, AbstractPdo $conn) : ConnectionPool |
102
|
|
|
{ |
103
|
|
|
return static::getInstance()->addConnection($name, $conn); |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* @param string $name |
108
|
|
|
* @return AbstractPdo |
109
|
|
|
*/ |
110
|
|
|
public function getConnection(string $name) : AbstractPdo |
111
|
|
|
{ |
112
|
|
|
Assert($this->_connections)->keyExists($name, "The database connection {$name} has not been added."); |
113
|
|
|
|
114
|
|
|
if ( $this->_connections[$name] instanceof \Closure ) |
115
|
|
|
{ |
116
|
|
|
$this->_connections[$name] = $this->_connections[$name]->__invoke(); |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
return $this->_connections[$name]; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* @param string $name |
124
|
|
|
* @return AbstractPdo |
125
|
|
|
*/ |
126
|
|
|
public static function get(string $name) : AbstractPdo |
127
|
|
|
{ |
128
|
|
|
return static::getInstance()->getConnection($name); |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* @return ConnectionPool |
134
|
|
|
*/ |
135
|
|
|
final public static function getInstance() : ConnectionPool |
136
|
|
|
{ |
137
|
|
|
if ( ! static::$instance ) |
138
|
|
|
{ |
139
|
|
|
$calledClass = get_called_class(); |
140
|
|
|
static::$instance = new $calledClass(); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
return static::$instance; |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
final private function __clone() |
147
|
|
|
{} |
148
|
|
|
} |
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.