<?php /** * Datasource connection manager * * Provides an interface for loading and enumerating connections defined in app/config/database.php * * PHP 5 * * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * Redistributions of files must retain the above copyright notice. * * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://cakephp.org CakePHP(tm) Project * @package cake * @subpackage cake.cake.libs.model * @since CakePHP(tm) v 0.10.x.1402 * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ App::uses('DataSource', 'Model/Datasource'); /** * Manages loaded instances of DataSource objects * * @package cake * @subpackage cake.cake.libs.model */ class ConnectionManager { /** * Holds a loaded instance of the Connections object * * @var DATABASE_CONFIG * @access public */ public static $config = null; /** * Holds instances DataSource objects * * @var array * @access protected */ protected static $_dataSources = array(); /** * Contains a list of all file and class names used in Connection settings * * @var array * @access protected */ protected static $_connectionsEnum = array(); /** * Indicates if the init code for this class has alredy been executed * * @var boolean */ private static $_init = false; /** * Loads connections configuration. * */ private static function init() { include_once CONFIGS . 'database.php'; if (class_exists('DATABASE_CONFIG')) { self::$config = new DATABASE_CONFIG(); self::_getConnectionObjects(); } register_shutdown_function('ConnectionManager::shutdown'); self::$_init = true; } /** * Gets a reference to a DataSource object * * @param string $name The name of the DataSource, as defined in app/config/database.php * @return object Instance */ public static function getDataSource($name) { if (empty(self::$_init)) { self::init(); } if (!empty(self::$_dataSources[$name])) { $return = self::$_dataSources[$name]; return $return; } if (empty(self::$_connectionsEnum[$name])) { trigger_error(__("ConnectionManager::getDataSource - Non-existent data source %s", $name), E_USER_ERROR); $null = null; return $null; } $conn = self::$_connectionsEnum[$name]; $class = $conn['classname']; if (self::loadDataSource($name) === null) { trigger_error(__("ConnectionManager::getDataSource - Could not load class %s", $class), E_USER_ERROR); $null = null; return $null; } self::$_dataSources[$name] = new $class(self::$config->{$name}); self::$_dataSources[$name]->configKeyName = $name; return self::$_dataSources[$name]; } /** * Gets the list of available DataSource connections * * @return array List of available connections */ public static function sourceList() { if (empty(self::$_init)) { self::init(); } return array_keys(self::$_dataSources); } /** * Gets a DataSource name from an object reference. * * **Warning** this method may cause fatal errors in PHP4. * * @param object $source DataSource object * @return string Datasource name, or null if source is not present * in the ConnectionManager. */ public static function getSourceName(&$source) { if (empty(self::$_init)) { self::init(); } foreach (self::$_dataSources as $name => $ds) { if ($ds == $source) { return $name; } } return ''; } /** * Loads the DataSource class for the given connection name * * @param mixed $connName A string name of the connection, as defined in app/config/database.php, * or an array containing the filename (without extension) and class name of the object, * to be found in app/models/datasources/ or cake/libs/model/datasources/. * @return boolean True on success, null on failure or false if the class is already loaded */ public static function loadDataSource($connName) { if (empty(self::$_init)) { self::init(); } if (is_array($connName)) { $conn = $connName; } else { $conn = self::$_connectionsEnum[$connName]; } if (class_exists($conn['classname'], false)) { return false; } $plugin = $package = null; if (!empty($conn['plugin'])) { $plugin .= '.'; } if (!empty($conn['package'])) { $package = '/' . $conn['package']; } App::uses($conn['classname'], $plugin . 'Model/Datasource' . $package); if (!class_exists($conn['classname'])) { trigger_error(__('ConnectionManager::loadDataSource - Unable to import DataSource class %s', $class), E_USER_ERROR); return null; } return true; } /** * Return a list of connections * * @return array An associative array of elements where the key is the connection name * (as defined in Connections), and the value is an array with keys 'filename' and 'classname'. */ public static function enumConnectionObjects() { if (empty(self::$_init)) { self::init(); } return self::$_connectionsEnum; } /** * Dynamically creates a DataSource object at runtime, with the given name and settings * * @param string $name The DataSource name * @param array $config The DataSource configuration settings * @return object A reference to the DataSource object, or null if creation failed */ public static function create($name = '', $config = array()) { if (empty(self::$_init)) { self::init(); } if (empty($name) || empty($config) || array_key_exists($name, self::$_connectionsEnum)) { $null = null; return $null; } self::$config->{$name} = $config; self::$_connectionsEnum[$name] = self::_connectionData($config); $return = self::getDataSource($name); return $return; } /** * Gets a list of class and file names associated with the user-defined DataSource connections * * @return void */ protected static function _getConnectionObjects() { $connections = get_object_vars(self::$config); if ($connections != null) { foreach ($connections as $name => $config) { self::$_connectionsEnum[$name] = self::_connectionData($config); } } else { throw new MissingConnectionException(array('class' => 'ConnectionManager')); } } /** * Returns the file, class name, and parent for the given driver. * * @return array An indexed array with: filename, classname, plugin and parent */ private static function _connectionData($config) { $package = $classname = $plugin = null; list($plugin, $classname) = pluginSplit($config['datasource']); if (strpos($classname, '/') !== false) { $package = dirname($classname); $classname = basename($classname); } return compact('package', 'classname', 'plugin'); } /** * Destructor. * */ public static function shutdown() { if (Configure::read('Session.defaults') == 'database' && function_exists('session_write_close')) { session_write_close(); } } }