source: Dev/branches/cakephp/cake/libs/model/connection_manager.php @ 126

Last change on this file since 126 was 126, checked in by fpvanagthoven, 14 years ago

Cakephp branch.

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