cake/libs/model/connection_manager.php

1 <?php
2 /* SVN FILE: $Id$ */
3 /**
4 * Datasource connection manager
5 *
6 * Provides an interface for loading and enumerating connections defined in app/config/database.php
7 *
8 * PHP versions 4 and 5
9 *
10 * CakePHP(tm) : Rapid Development Framework (http://www.cakephp.org)
11 * Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
12 *
13 * Licensed under The MIT License
14 * Redistributions of files must retain the above copyright notice.
15 *
16 * @filesource
17 * @copyright Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
18 * @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
19 * @package cake
20 * @subpackage cake.cake.libs.model
21 * @since CakePHP(tm) v 0.10.x.1402
22 * @version $Revision$
23 * @modifiedby $LastChangedBy$
24 * @lastmodified $Date$
25 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
26 */
27 uses ('model' . DS . 'datasources' . DS . 'datasource');
28 config('database');
29  
30 /**
31 * Manages loaded instances of DataSource objects
32 *
33 * Long description for file
34 *
35 * @package cake
36 * @subpackage cake.cake.libs.model
37 */
38 class ConnectionManager extends Object {
39 /**
40 * Holds a loaded instance of the Connections object
41 *
42 * @var DATABASE_CONFIG
43 * @access public
44 */
45 var $config = null;
46 /**
47 * Holds instances DataSource objects
48 *
49 * @var array
50 * @access protected
51 */
52 var $_dataSources = array();
53 /**
54 * Contains a list of all file and class names used in Connection settings
55 *
56 * @var array
57 * @access protected
58 */
59 var $_connectionsEnum = array();
60 /**
61 * Constructor.
62 *
63 */
64 function __construct() {
65 if (class_exists('DATABASE_CONFIG')) {
66 $this->config =& new DATABASE_CONFIG();
67 }
68 }
69 /**
70 * Gets a reference to the ConnectionManger object instance
71 *
72 * @return object Instance
73 * @access public
74 * @static
75 */
76 function &getInstance() {
77 static $instance = array();
78  
79 if (!$instance) {
80 $instance[0] =& new ConnectionManager();
81 }
82  
83 return $instance[0];
84 }
85 /**
86 * Gets a reference to a DataSource object
87 *
88 * @param string $name The name of the DataSource, as defined in app/config/database.php
89 * @return object Instance
90 * @access public
91 * @static
92 */
93 function &getDataSource($name) {
94 $_this =& ConnectionManager::getInstance();
95  
96 if (!empty($_this->_dataSources[$name])) {
97 $return =& $_this->_dataSources[$name];
98 return $return;
99 }
100  
101 $connections = $_this->enumConnectionObjects();
102 if (!empty($connections[$name])) {
103 $conn = $connections[$name];
104 $class = $conn['classname'];
105 $_this->loadDataSource($name);
106 $_this->_dataSources[$name] =& new $class($_this->config->{$name});
107 $_this->_dataSources[$name]->configKeyName = $name;
108 } else {
109 trigger_error(sprintf(__("ConnectionManager::getDataSource - Non-existent data source %s", true), $name), E_USER_ERROR);
110 return null;
111 }
112  
113 $return =& $_this->_dataSources[$name];
114 return $return;
115 }
116 /**
117 * Gets the list of available DataSource connections
118 *
119 * @return array List of available connections
120 * @access public
121 * @static
122 */
123 function sourceList() {
124 $_this =& ConnectionManager::getInstance();
125 return array_keys($_this->_dataSources);
126 }
127 /**
128 * Gets a DataSource name from an object reference
129 *
130 * @param object $source DataSource object
131 * @return string Datasource name
132 * @access public
133 * @static
134 */
135 function getSourceName(&$source) {
136 $_this =& ConnectionManager::getInstance();
137 $names = array_keys($_this->_dataSources);
138 for ($i = 0; $i < count($names); $i++) {
139 if ($_this->_dataSources[$names[$i]] === $source) {
140 return $names[$i];
141 }
142 }
143 return null;
144 }
145 /**
146 * Loads the DataSource class for the given connection name
147 *
148 * @param mixed $connName A string name of the connection, as defined in app/config/database.php,
149 * or an array containing the filename (without extension) and class name of the object,
150 * to be found in app/models/datasources/ or cake/libs/model/datasources/.
151 * @return boolean True on success, null on failure or false if the class is already loaded
152 * @access public
153 * @static
154 */
155 function loadDataSource($connName) {
156 $_this =& ConnectionManager::getInstance();
157  
158 if (is_array($connName)) {
159 $conn = $connName;
160 } else {
161 $connections = $_this->enumConnectionObjects();
162 $conn = $connections[$connName];
163 }
164  
165 if (!empty($conn['parent'])) {
166 $_this->loadDataSource($conn['parent']);
167 }
168  
169 if (class_exists($conn['classname'])) {
170 return false;
171 }
172  
173 if (file_exists(MODELS . 'datasources' . DS . $conn['filename'] . '.php')) {
174 require (MODELS . 'datasources' . DS . $conn['filename'] . '.php');
175 } elseif (fileExistsInPath(LIBS . 'model' . DS . 'datasources' . DS . $conn['filename'] . '.php')) {
176 require (LIBS . 'model' . DS . 'datasources' . DS . $conn['filename'] . '.php');
177 } else {
178 $error = __('Unable to load DataSource file %s.php', true);
179 trigger_error(sprintf($error, $conn['filename']), E_USER_ERROR);
180 return null;
181 }
182  
183 return true;
184 }
185 /**
186 * Gets a list of class and file names associated with the user-defined DataSource connections
187 *
188 * @return array An associative array of elements where the key is the connection name
189 * (as defined in Connections), and the value is an array with keys 'filename' and 'classname'.
190 * @access public
191 * @static
192 */
193 function enumConnectionObjects() {
194 $_this =& ConnectionManager::getInstance();
195  
196 if (!empty($_this->_connectionsEnum)) {
197 return $_this->_connectionsEnum;
198 }
199 $connections = get_object_vars($_this->config);
200  
201 if ($connections != null) {
202 foreach ($connections as $name => $config) {
203 $_this->_connectionsEnum[$name] = $_this->__getDriver($config);
204 }
205 return $_this->_connectionsEnum;
206 } else {
207 $_this->cakeError('missingConnection', array(array('className' => 'ConnectionManager')));
208 }
209 }
210 /**
211 * Dynamically creates a DataSource object at runtime, with the given name and settings
212 *
213 * @param string $name The DataSource name
214 * @param array $config The DataSource configuration settings
215 * @return object A reference to the DataSource object, or null if creation failed
216 * @access public
217 * @static
218 */
219 function &create($name = '', $config = array()) {
220 $_this =& ConnectionManager::getInstance();
221  
222 if (empty($name) || empty($config) || array_key_exists($name, $_this->_connectionsEnum)) {
223 $null = null;
224 return $null;
225 }
226  
227 $_this->config->{$name} = $config;
228 $_this->_connectionsEnum[$name] = $_this->__getDriver($config);
229 $return =& $_this->getDataSource($name);
230 return $return;
231 }
232 /**
233 * Returns the file, class name, and parent for the given driver.
234 *
235 * @return array An indexed array with: filename, classname, and parent
236 * @access private
237 */
238 function __getDriver($config) {
239 if (!isset($config['datasource'])) {
240 $config['datasource'] = 'dbo';
241 }
242  
243 if (isset($config['driver']) && $config['driver'] != null && !empty($config['driver'])) {
244 $filename = $config['datasource'] . DS . $config['datasource'] . '_' . $config['driver'];
245 $classname = Inflector::camelize(strtolower($config['datasource'] . '_' . $config['driver']));
246 $parent = $this->__getDriver(array('datasource' => $config['datasource']));
247 } else {
248 $filename = $config['datasource'] . '_source';
249 $classname = Inflector::camelize(strtolower($config['datasource'] . '_source'));
250 $parent = null;
251 }
252 return array('filename' => $filename, 'classname' => $classname, 'parent' => $parent);
253 }
254 /**
255 * Destructor.
256 *
257 * @access private
258 */
259 function __destruct() {
260 if (Configure::read('Session.save') == 'database' && function_exists('session_write_close')) {
261 session_write_close();
262 }
263 }
264 }
265 ?>
266  
267