00001 <?php
00053 abstract class spunQ_db implements spunQ_IDatabaseConnection {
00054
00059 protected static $handlers = NULL;
00060
00066 private static $connections = array();
00067
00072 private static $listeners = array();
00073
00080 public static function getConnection($name = 'default') {
00081 if (!isset(self::$connections[$name])) {
00082 $config = spunQ::getConfiguration()->getStringsForPrefix('spunQ.db.connection.' . $name);
00083 if ($config === NULL || !isset($config['dbms'])) {
00084 throw new spunQ_ConfigurationError('db.DbConfigurationNotFound', $name);
00085 }
00086 $dbms = $config['dbms'];
00087 if (self::$handlers === NULL || !self::$handlers->keyExists($dbms)) {
00088 throw new spunQ_InitializationError('db.DbmsFactoryNotFound', $dbms);
00089 }
00090 foreach (self::$listeners as $listener) {
00091 $listener->creatingDatabaseInstance($name);
00092 }
00093 self::$connections[$name] = self::$handlers->get($dbms)->createInstance($config, $name);
00094 foreach (self::$listeners as $listener) {
00095 $listener->createdDatabaseInstance($name, self::$connections[$name]);
00096 }
00097 }
00098 return self::$connections[$name];
00099 }
00100
00106 public static function observeInitializations(spunQ_IDatabaseInstantiationListener $listener) {
00107 self::$listeners[] = $listener;
00108 return NULL;
00109 }
00110
00115 public static function getDefaultConnection() {
00116 return self::getConnection('default');
00117 }
00118
00127 public static function registerDbmsHandler($dbms, spunQ_IDatabaseConnectionFactory $factory) {
00128 if (self::$handlers === NULL) {
00129 self::$handlers = new spunQ_Map();
00130 }
00131 self::$handlers->add($dbms, $factory);
00132 return NULL;
00133 }
00134
00151 protected static function sanityCheck($connection = NULL) {
00152 if ($connection === NULL) {
00153 $connection = self::getDefaultConnection();
00154 }
00155 $additionalTypes = self::getAdditionalTypes($connection);
00156 $missingTypes = self::getMissingTypes($connection);
00157 $changedTypes = self::getChangedTypes($connection);
00158 $additionalMembers = self::getAdditionalTypeMembers($connection);
00159 $missingMembers = self::getMissingTypeMembers($connection);
00160 $changedMembers = self::getChangedTypeMembers($connection);
00161 if (isset($additionalTypes[0])) {
00162 foreach ($additionalTypes as &$type) {
00163 $type = $type->getName();
00164 }
00165 throw new spunQ_InitializationError('db.AdditionalTypeStorages', $additionalTypes);
00166 }
00167 if (isset($missingTypes[0])) {
00168 foreach ($missingTypes as &$type) {
00169 $type = $type->getName();
00170 }
00171 throw new spunQ_InitializationError('db.MissingTypeStorages', $missingTypes);
00172 }
00173 if (isset($changedTypes[0])) {
00174 $array = array();
00175 foreach ($changedTypes->getKeys() as $type) {
00176 $array[] = $type->getName();
00177 }
00178 throw new spunQ_InitializationError('db.ChangedTypeStorages', $changedTypes);
00179 }
00180 if (isset($additionalMembers[0])) {
00181 foreach ($additionalMembers as &$member) {
00182 $member = $member->getMemberName();
00183 }
00184 throw new spunQ_InitializationError('db.AdditionalTypeMemberStorages', $additionalMembers);
00185 }
00186 if (isset($missingMembers[0])) {
00187 foreach ($missingMembers as &$member) {
00188 $member = $member->getName();
00189 }
00190 throw new spunQ_InitializationError('db.MissingTypeMemberStorages', $missingMembers);
00191 }
00192 if (!$changedMembers->isEmpty()) {
00193 $array = array();
00194 foreach ($changedMembers->getKeys() as $member) {
00195 $array[] = $member->getName() . '(' . $member->getType() . ' -> ' . $changedMembers->get($member) . ')';
00196 }
00197 throw new spunQ_InitializationError('db.ChangedTypeMemberStorages', $array);
00198 }
00199 return NULL;
00200 }
00201
00208 public static function getMissingTypes($connection = NULL) {
00209 if ($connection === NULL) {
00210 $connection = self::getDefaultConnection();
00211 }
00212 $missing = array();
00213 $storages = $connection->getAllTypeStorages();
00214 foreach (spunQ_LocalUserType::getAll() as $name => $type) {
00215 if (!$type->inheritsFrom(spunQ_UserType::getByName('spunQ.db.StorableObject'))) {
00216 continue;
00217 }
00218 if (!isset($storages[$name])) {
00219 $missing[] = $type;
00220 }
00221 }
00222 return $missing;
00223 }
00224
00231 public static function getAdditionalTypes($connection = NULL) {
00232 if ($connection === NULL) {
00233 $connection = self::getDefaultConnection();
00234 }
00235 $additional = array();
00236 foreach ($connection->getAllTypeStorages() as $name => $storage) {
00237 try {
00238 spunQ_UserType::getByName($name);
00239 } catch (spunQ_UndefinedTypeError $e) {
00240 $additional[] = $storage;
00241 }
00242 }
00243 return $additional;
00244 }
00245
00253 public static function getChangedTypes($connection = NULL) {
00254 if ($connection === NULL) {
00255 $connection = self::getDefaultConnection();
00256 }
00257 $changed = new spunQ_Map();
00258 $storages = $connection->getAllTypeStorages();
00259 foreach (spunQ_LocalUserType::getAll() as $name => $type) {
00260 if (!$type->inheritsFrom(spunQ_UserType::getByName('spunQ.db.StorableObject'))) {
00261 continue;
00262 }
00263 if (!isset($storages[$name])) {
00264 continue;
00265 }
00266 if ($storages[$name]->getParent() === NULL) {
00267 continue;
00268 }
00269 if ($storages[$name]->getParent()->getTypeName() !== $type->getParent()->getName()) {
00270 $changed->add($type, spunQ_Type::getByName($storages[$name]->getParent()->getTypeName()));
00271 }
00272 }
00273 return $changed;
00274 }
00275
00282 public static function getMissingTypeMembers($connection = NULL) {
00283 if ($connection === NULL) {
00284 $connection = self::getDefaultConnection();
00285 }
00286 $missing = array();
00287 $storages = $connection->getAllTypeStorages();
00288 foreach (spunQ_LocalUserType::getAll() as $name => $type) {
00289 if (!$type->inheritsFrom(spunQ_UserType::getByName('spunQ.db.StorableObject'))) {
00290 continue;
00291 }
00292 if (!isset($storages[$name])) {
00293 continue;
00294 }
00295 $memberStorages = $storages[$name]->getMemberStorages();
00296 foreach ($type->getOwnMembers() as $member) {
00297 if (!isset($memberStorages[$member->getName()])) {
00298 $missing[] = $member;
00299 }
00300 }
00301 }
00302 return $missing;
00303 }
00304
00311 public static function getAdditionalTypeMembers($connection = NULL) {
00312 if ($connection === NULL) {
00313 $connection = self::getDefaultConnection();
00314 }
00315 $additional = array();
00316 foreach ($connection->getAllTypeStorages() as $name => $storage) {
00317 try {
00318 $type = spunQ_UserType::getByName($name);
00319 foreach ($storage->getMemberStorages() as $name => $memberStorage) {
00320 if (!$type->memberExists($name)) {
00321 $additional[] = $memberStorage;
00322 }
00323 }
00324 } catch (spunQ_UndefinedTypeError $e) {
00325 }
00326 }
00327 return $additional;
00328 }
00329
00337 public static function getChangedTypeMembers($connection = NULL) {
00338 if ($connection === NULL) {
00339 $connection = self::getDefaultConnection();
00340 }
00341 $changed = new spunQ_Map();
00342 $storages = $connection->getAllTypeStorages();
00343 foreach (spunQ_LocalUserType::getAll() as $name => $type) {
00344 if (!$type->inheritsFrom(spunQ_UserType::getByName('spunQ.db.StorableObject'))) {
00345 continue;
00346 }
00347 if (!isset($storages[$name])) {
00348 continue;
00349 }
00350 $memberStorages = $storages[$name]->getMemberStorages();
00351 foreach ($type->getOwnMembers() as $member) {
00352 if (!isset($memberStorages[$member->getName()])) {
00353 continue;
00354 }
00355 $memberStorage = $memberStorages[$member->getName()];
00356 if ($memberStorage->getTypeString() !== $member->getType()->getName()) {
00357 vdebug($memberStorage->getType());
00358 $changed->add($member, $memberStorage->getType());
00359 continue;
00360 }
00361 }
00362 }
00363 return $changed;
00364 }
00365
00366 }
00367