1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
<?php
/*
* This file is part of the ICanBoogie package.
*
* (c) Olivier Laviale <olivier.laviale@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace ICanBoogie\ActiveRecord;
use ICanBoogie\Accessor\AccessorTrait;
/**
* Connection collection.
*
* @property-read array $definitions Connection definitions.
* @property-read Connection[] $established Established connections.
*/
class ConnectionCollection implements \ArrayAccess, \IteratorAggregate
{
use AccessorTrait;
/**
* Connections definitions.
*
* @var array
*/
private $definitions;
protected function get_definitions()
{
return $this->definitions;
}
/**
* Established connections.
*
* @var Connection[]
*/
private $established = [];
protected function get_established()
{
return $this->established;
}
/**
* Initializes the {@link $definitions} property.
*
* @param array $definitions Connection definitions.
*/
public function __construct(array $definitions)
{
foreach ($definitions as $id => $definition)
{
$this[$id] = $definition;
}
}
/**
* Checks if a connection definition exists.
*
* @param string $id Connection identifier.
*
* @return bool
*/
public function offsetExists($id)
{
return isset($this->definitions[$id]);
}
/**
* Sets the definition of a connection.
*
* @param string $id Connection identifier.
* @param array|string $definition Connection definition.
*
* @throws ConnectionAlreadyEstablished in attempt to set the definition of an already
* established connection.
*/
public function offsetSet($id, $definition)
{
if (isset($this->established[$id]))
{
throw new ConnectionAlreadyEstablished($id);
}
if (is_string($definition))
{
$definition = [ 'dsn' => $definition ];
}
if (empty($definition['dsn']))
{
throw new \InvalidArgumentException("<q>dsn</q> is empty or not defined.");
}
$this->definitions[$id] = $definition;
}
/**
* Removes a connection definition.
*
* @param string $id Connection identifier.
*
* @throws ConnectionAlreadyEstablished in attempt to unset the definition of an already
* established connection.
*/
public function offsetUnset($id)
{
if (isset($this->established[$id]))
{
throw new ConnectionAlreadyEstablished($id);
}
unset($this->definitions[$id]);
}
/**
* Returns a connection to the specified database.
*
* If the connection has not been established yet, it is created on the fly.
*
* @param string $id Connection identifier.
*
* @return Connection
*
* @throws ConnectionNotDefined when the connection requested is not defined.
* @throws ConnectionNotEstablished when the connection failed.
*/
public function offsetGet($id)
{
if (isset($this->established[$id]))
{
return $this->established[$id];
}
if (!$this->offsetExists($id))
{
throw new ConnectionNotDefined($id);
}
$options = $this->definitions[$id] + [
'dsn' => null,
'username' => 'root',
'password' => null
];
$options['options'][ConnectionOptions::ID] = $id;
#
# we catch connection exceptions and rethrow them in order to avoid displaying sensible
# information such as the username or password.
#
try
{
return $this->established[$id] = new Connection($options['dsn'], $options['username'], $options['password'], $options['options']);
}
catch (\PDOException $e)
{
throw new ConnectionNotEstablished($id, "Connection not established: " . $e->getMessage() . ".", 500);
}
}
/**
* Returns an iterator for established connections.
*/
public function getIterator()
{
return new \ArrayIterator($this->established);
}
}