Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/*
3
 *  $Id: Propel.php 1691 2010-04-19 22:01:20Z francois $
4
 *
5
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
10
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
11
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
15
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16
 *
17
 * This software consists of voluntary contributions made by many individuals
18
 * and is licensed under the LGPL. For more information please see
19
 * <http://propel.phpdb.org>.
20
 */
21
 
22
require 'propel/PropelException.php';
23
require 'propel/adapter/DBAdapter.php';
24
require 'propel/util/PropelPDO.php';
25
 
26
/**
27
 * Propel's main resource pool and initialization & configuration class.
28
 *
29
 * This static class is used to handle Propel initialization and to maintain all of the
30
 * open database connections and instantiated database maps.
31
 *
32
 * @author     Hans Lellelid <hans@xmpl.rg> (Propel)
33
 * @author     Daniel Rall <dlr@finemaltcoding.com> (Torque)
34
 * @author     Magnús Þór Torfason <magnus@handtolvur.is> (Torque)
35
 * @author     Jason van Zyl <jvanzyl@apache.org> (Torque)
36
 * @author     Rafal Krzewski <Rafal.Krzewski@e-point.pl> (Torque)
37
 * @author     Martin Poeschl <mpoeschl@marmot.at> (Torque)
38
 * @author     Henning P. Schmiedehausen <hps@intermeta.de> (Torque)
39
 * @author     Kurt Schrader <kschrader@karmalab.org> (Torque)
40
 * @version    $Revision: 1691 $
41
 * @package    propel
42
 */
43
class Propel
44
{
45
	/**
46
	 * A constant for <code>default</code>.
47
	 */
48
	const DEFAULT_NAME = "default";
49
 
50
	/**
51
	 * A constant defining 'System is unusuable' logging level
52
	 */
53
	const LOG_EMERG = 0;
54
 
55
	/**
56
	 * A constant defining 'Immediate action required' logging level
57
	 */
58
	const LOG_ALERT = 1;
59
 
60
	/**
61
	 * A constant defining 'Critical conditions' logging level
62
	 */
63
	const LOG_CRIT = 2;
64
 
65
	/**
66
	 * A constant defining 'Error conditions' logging level
67
	 */
68
	const LOG_ERR = 3;
69
 
70
	/**
71
	 * A constant defining 'Warning conditions' logging level
72
	 */
73
	const LOG_WARNING = 4;
74
 
75
	/**
76
	 * A constant defining 'Normal but significant' logging level
77
	 */
78
	const LOG_NOTICE = 5;
79
 
80
	/**
81
	 * A constant defining 'Informational' logging level
82
	 */
83
	const LOG_INFO = 6;
84
 
85
	/**
86
	 * A constant defining 'Debug-level messages' logging level
87
	 */
88
	const LOG_DEBUG = 7;
89
 
90
	/**
91
	 * The Propel version.
92
	 */
93
	const VERSION = '1.4.2';
94
 
95
	/**
96
	 * The class name for a PDO object.
97
	 */
98
	const CLASS_PDO = 'PDO';
99
 
100
	/**
101
	 * The class name for a PropelPDO object.
102
	 */
103
	const CLASS_PROPEL_PDO = 'PropelPDO';
104
 
105
	/**
106
	 * The class name for a DebugPDO object.
107
	 */
108
	const CLASS_DEBUG_PDO = 'DebugPDO';
109
 
110
	/**
111
	 * Constant used to request a READ connection (applies to replication).
112
	 */
113
	const CONNECTION_READ = 'read';
114
 
115
	/**
116
	 * Constant used to request a WRITE connection (applies to replication).
117
	 */
118
	const CONNECTION_WRITE = 'write';
119
 
120
	/**
121
	 * @var        string The db name that is specified as the default in the property file
122
	 */
123
	private static $defaultDBName;
124
 
125
	/**
126
	 * @var        array The global cache of database maps
127
	 */
128
	private static $dbMaps = array();
129
 
130
	/**
131
	 * @var        array The cache of DB adapter keys
132
	 */
133
	private static $adapterMap = array();
134
 
135
	/**
136
	 * @var        array Cache of established connections (to eliminate overhead).
137
	 */
138
	private static $connectionMap = array();
139
 
140
	/**
141
	 * @var        PropelConfiguration Propel-specific configuration.
142
	 */
143
	private static $configuration;
144
 
145
	/**
146
	 * @var        bool flag to set to true once this class has been initialized
147
	 */
148
	private static $isInit = false;
149
 
150
	/**
151
	 * @var        Log optional logger
152
	 */
153
	private static $logger = null;
154
 
155
	/**
156
	 * @var        string The name of the database mapper class
157
	 */
158
	private static $databaseMapClass = 'DatabaseMap';
159
 
160
	/**
161
	 * @var        bool Whether the object instance pooling is enabled
162
	 */
163
	private static $instancePoolingEnabled = true;
164
 
165
	/**
166
	 * @var        bool For replication, whether to force the use of master connection.
167
	 */
168
	private static $forceMasterConnection = false;
169
 
170
	/**
171
	 * @var        array A map of class names and their file paths for autoloading
172
	 */
173
	private static $autoloadMap = array(
174
		'PropelException' => 'propel/PropelException.php',
175
 
176
		'DBAdapter'       => 'propel/adapter/DBAdapter.php',
177
		'DBMSSQL'         => 'propel/adapter/DBMSSQL.php',
178
		'MssqlPropelPDO'  => 'propel/adapter/MSSQL/MssqlPropelPDO.php',
179
		'MssqlDebugPDO'   => 'propel/adapter/MSSQL/MssqlDebugPDO.php',
180
		'MssqlDateTime'   => 'propel/adapter/MSSQL/MssqlDateTime.class.php',
181
		'DBMySQL'         => 'propel/adapter/DBMySQL.php',
182
		'DBMySQLi'        => 'propel/adapter/DBMySQLi.php',
183
		'DBNone'          => 'propel/adapter/DBNone.php',
184
		'DBOracle'        => 'propel/adapter/DBOracle.php',
185
		'DBPostgres'      => 'propel/adapter/DBPostgres.php',
186
		'DBSQLite'        => 'propel/adapter/DBSQLite.php',
187
		'DBSybase'        => 'propel/adapter/DBSybase.php',
188
 
189
		'BasicLogger'       => 'propel/logger/BasicLogger.php',
190
		'MojaviLogAdapter'  => 'propel/logger/MojaviLogAdapter.php',
191
 
192
		'ColumnMap'    => 'propel/map/ColumnMap.php',
193
		'DatabaseMap'  => 'propel/map/DatabaseMap.php',
194
		'TableMap'     => 'propel/map/TableMap.php',
195
		'RelationMap'  => 'propel/map/RelationMap.php',
196
		'ValidatorMap' => 'propel/map/ValidatorMap.php',
197
 
198
		'BaseObject'                    => 'propel/om/BaseObject.php',
199
		'NodeObject'                    => 'propel/om/NodeObject.php',
200
		'Persistent'                    => 'propel/om/Persistent.php',
201
		'PreOrderNodeIterator'          => 'propel/om/PreOrderNodeIterator.php',
202
		'NestedSetPreOrderNodeIterator' => 'propel/om/NestedSetPreOrderNodeIterator.php',
203
		'NestedSetRecursiveIterator'    => 'propel/om/NestedSetRecursiveIterator.php',
204
 
205
		'BasePeer'            => 'propel/util/BasePeer.php',
206
		'NodePeer'            => 'propel/util/NodePeer.php',
207
		'Criteria'            => 'propel/util/Criteria.php',
208
		'Join'                => 'propel/util/Join.php',
209
		'PeerInfo'            => 'propel/util/PeerInfo.php',
210
		'PropelColumnTypes'   => 'propel/util/PropelColumnTypes.php',
211
		'PropelConfiguration' => 'propel/util/PropelConfiguration.php',
212
		'PropelConfigurationIterator' => 'propel/util/PropelConfigurationIterator.php',
213
		'PropelPDO'           => 'propel/util/PropelPDO.php',
214
		'PropelPager'         => 'propel/util/PropelPager.php',
215
		'PropelDateTime'      => 'propel/util/PropelDateTime.php',
216
		'DebugPDO'            => 'propel/util/DebugPDO.php',
217
		'DebugPDOStatement'   => 'propel/util/DebugPDOStatement.php',
218
 
219
 
220
		'BasicValidator'      => 'propel/validator/BasicValidator.php',
221
		'MatchValidator'      => 'propel/validator/MatchValidator.php',
222
		'MaxLengthValidator'  => 'propel/validator/MaxLengthValidator.php',
223
		'MaxValueValidator'   => 'propel/validator/MaxValueValidator.php',
224
		'MinLengthValidator'  => 'propel/validator/MinLengthValidator.php',
225
		'MinValueValidator'   => 'propel/validator/MinValueValidator.php',
226
		'NotMatchValidator'   => 'propel/validator/NotMatchValidator.php',
227
		'RequiredValidator'   => 'propel/validator/RequiredValidator.php',
228
		'UniqueValidator'     => 'propel/validator/UniqueValidator.php',
229
		'ValidValuesValidator' => 'propel/validator/ValidValuesValidator.php',
230
		'ValidationFailed'    => 'propel/validator/ValidationFailed.php',
231
	);
232
 
233
	/**
234
	 * Initializes Propel
235
	 *
236
	 * @throws     PropelException Any exceptions caught during processing will be
237
	 *                             rethrown wrapped into a PropelException.
238
	 */
239
	public static function initialize()
240
	{
241
		if (self::$configuration === null) {
242
			throw new PropelException("Propel cannot be initialized without a valid configuration. Please check the log files for further details.");
243
		}
244
 
245
		self::configureLogging();
246
 
247
		// reset the connection map (this should enable runtime changes of connection params)
248
		self::$connectionMap = array();
249
 
250
		if (isset(self::$configuration['classmap']) && is_array(self::$configuration['classmap'])) {
251
		  self::$autoloadMap = array_merge(self::$configuration['classmap'], self::$autoloadMap);
252
	  }
253
 
254
		self::$isInit = true;
255
	}
256
 
257
	/**
258
	 * Configure Propel using a PHP (array) config file.
259
	 *
260
	 * @param      string Path (absolute or relative to include_path) to config file.
261
	 *
262
	 * @throws     PropelException If configuration file cannot be opened.
263
	 *                             (E_WARNING probably will also be raised by PHP)
264
	 */
265
	public static function configure($configFile)
266
	{
267
		$configuration = include($configFile);
268
		if ($configuration === false) {
269
			throw new PropelException("Unable to open configuration file: " . var_export($configFile, true));
270
		}
271
		self::setConfiguration($configuration);
272
	}
273
 
274
	/**
275
	 * Configure the logging system, if config is specified in the runtime configuration.
276
	 */
277
	protected static function configureLogging()
278
	{
279
		if (self::$logger === null) {
280
			if (isset(self::$configuration['log']) && is_array(self::$configuration['log']) && count(self::$configuration['log'])) {
281
				include_once 'Log.php'; // PEAR Log class
282
				$c = self::$configuration['log'];
283
				$type = isset($c['type']) ? $c['type'] : 'file';
284
				$name = isset($c['name']) ? $c['name'] : './propel.log';
285
				$ident = isset($c['ident']) ? $c['ident'] : 'propel';
286
				$conf = isset($c['conf']) ? $c['conf'] : array();
287
				$level = isset($c['level']) ? $c['level'] : PEAR_LOG_DEBUG;
288
				self::$logger = Log::singleton($type, $name, $ident, $conf, $level);
289
			} // if isset()
290
		}
291
	}
292
 
293
	/**
294
	 * Initialization of Propel with a PHP (array) configuration file.
295
	 *
296
	 * @param      string $c The Propel configuration file path.
297
	 *
298
	 * @throws     PropelException Any exceptions caught during processing will be
299
	 *                             rethrown wrapped into a PropelException.
300
	 */
301
	public static function init($c)
302
	{
303
		self::configure($c);
304
		self::initialize();
305
	}
306
 
307
	/**
308
	 * Determine whether Propel has already been initialized.
309
	 *
310
	 * @return     bool True if Propel is already initialized.
311
	 */
312
	public static function isInit()
313
	{
314
		return self::$isInit;
315
	}
316
 
317
	/**
318
	 * Sets the configuration for Propel and all dependencies.
319
	 *
320
	 * @param      mixed The Configuration (array or PropelConfiguration)
321
	 */
322
	public static function setConfiguration($c)
323
	{
324
		if (is_array($c)) {
325
			if (isset($c['propel']) && is_array($c['propel'])) {
326
			  $c = $c['propel'];
327
		  }
328
			$c = new PropelConfiguration($c);
329
		}
330
		self::$configuration = $c;
331
	}
332
 
333
	/**
334
	 * Get the configuration for this component.
335
	 *
336
	 * @param      int - PropelConfiguration::TYPE_ARRAY: return the configuration as an array
337
	 *                   (for backward compatibility this is the default)
338
	 *                 - PropelConfiguration::TYPE_ARRAY_FLAT: return the configuration as a flat array
339
	 *                   ($config['name.space.item'])
340
	 *                 - PropelConfiguration::TYPE_OBJECT: return the configuration as a PropelConfiguration instance
341
	 * @return     mixed The Configuration (array or PropelConfiguration)
342
	 */
343
	public static function getConfiguration($type = PropelConfiguration::TYPE_ARRAY)
344
	{
345
		return self::$configuration->getParameters($type);
346
	}
347
 
348
	/**
349
	 * Override the configured logger.
350
	 *
351
	 * This is primarily for things like unit tests / debugging where
352
	 * you want to change the logger without altering the configuration file.
353
	 *
354
	 * You can use any logger class that implements the propel.logger.BasicLogger
355
	 * interface.  This interface is based on PEAR::Log, so you can also simply pass
356
	 * a PEAR::Log object to this method.
357
	 *
358
	 * @param      object The new logger to use. ([PEAR] Log or BasicLogger)
359
	 */
360
	public static function setLogger($logger)
361
	{
362
		self::$logger = $logger;
363
	}
364
 
365
	/**
366
	 * Returns true if a logger, for example PEAR::Log, has been configured,
367
	 * otherwise false.
368
	 *
369
	 * @return     bool True if Propel uses logging
370
	 */
371
	public static function hasLogger()
372
	{
373
		return (self::$logger !== null);
374
	}
375
 
376
	/**
377
	 * Get the configured logger.
378
	 *
379
	 * @return     object Configured log class ([PEAR] Log or BasicLogger).
380
	 */
381
	public static function logger()
382
	{
383
		return self::$logger;
384
	}
385
 
386
	/**
387
	 * Logs a message
388
	 * If a logger has been configured, the logger will be used, otherwrise the
389
	 * logging message will be discarded without any further action
390
	 *
391
	 * @param      string The message that will be logged.
392
	 * @param      string The logging level.
393
	 *
394
	 * @return     bool True if the message was logged successfully or no logger was used.
395
	 */
396
	public static function log($message, $level = self::LOG_DEBUG)
397
	{
398
		if (self::hasLogger()) {
399
			$logger = self::logger();
400
			switch ($level) {
401
				case self::LOG_EMERG:
402
					return $logger->log($message, $level);
403
				case self::LOG_ALERT:
404
					return $logger->alert($message);
405
				case self::LOG_CRIT:
406
					return $logger->crit($message);
407
				case self::LOG_ERR:
408
					return $logger->err($message);
409
				case self::LOG_WARNING:
410
					return $logger->warning($message);
411
				case self::LOG_NOTICE:
412
					return $logger->notice($message);
413
				case self::LOG_INFO:
414
					return $logger->info($message);
415
				default:
416
					return $logger->debug($message);
417
			}
418
		}
419
		return true;
420
	}
421
 
422
	/**
423
	 * Returns the database map information. Name relates to the name
424
	 * of the connection pool to associate with the map.
425
	 *
426
	 * The database maps are "registered" by the generated map builder classes.
427
	 *
428
	 * @param      string The name of the database corresponding to the DatabaseMap to retrieve.
429
	 *
430
	 * @return     DatabaseMap The named <code>DatabaseMap</code>.
431
	 *
432
	 * @throws     PropelException - if database map is null or propel was not initialized properly.
433
	 */
434
	public static function getDatabaseMap($name = null)
435
	{
436
		if ($name === null) {
437
			$name = self::getDefaultDB();
438
			if ($name === null) {
439
				throw new PropelException("DatabaseMap name is null!");
440
			}
441
		}
442
 
443
		if (!isset(self::$dbMaps[$name])) {
444
			$clazz = self::$databaseMapClass;
445
			self::$dbMaps[$name] = new $clazz($name);
446
		}
447
 
448
		return self::$dbMaps[$name];
449
	}
450
 
451
	/**
452
	 * Sets the database map object to use for specified datasource.
453
	 *
454
	 * @param      string $name The datasource name.
455
	 * @param      DatabaseMap $map The database map object to use for specified datasource.
456
	 */
457
	public static function setDatabaseMap($name, DatabaseMap $map)
458
	{
459
		if ($name === null) {
460
			$name = self::getDefaultDB();
461
		}
462
		self::$dbMaps[$name] = $map;
463
	}
464
 
465
	/**
466
	 * For replication, set whether to always force the use of a master connection.
467
	 *
468
	 * @param      boolean $bit True or False
469
	 */
470
	public static function setForceMasterConnection($bit)
471
	{
472
		self::$forceMasterConnection = (bool) $bit;
473
	}
474
 
475
	/**
476
	 * For replication, whether to always force the use of a master connection.
477
	 *
478
	 * @return     boolean
479
	 */
480
	public static function getForceMasterConnection()
481
	{
482
		return self::$forceMasterConnection;
483
	}
484
 
485
	/**
486
	 * Sets a Connection for specified datasource name.
487
	 *
488
	 * @param      string $name The datasource name for the connection being set.
489
	 * @param      PropelPDO $con The PDO connection.
490
	 * @param      string $mode Whether this is a READ or WRITE connection (Propel::CONNECTION_READ, Propel::CONNECTION_WRITE)
491
	 */
492
	public static function setConnection($name, PropelPDO $con, $mode = Propel::CONNECTION_WRITE)
493
	{
494
		if ($name === null) {
495
			$name = self::getDefaultDB();
496
		}
497
		if ($mode == Propel::CONNECTION_READ) {
498
			self::$connectionMap[$name]['slave'] = $con;
499
		} else {
500
			self::$connectionMap[$name]['master'] = $con;
501
		}
502
	}
503
 
504
	/**
505
	 * Gets an already-opened PDO connection or opens a new one for passed-in db name.
506
	 *
507
	 * @param      string $name The datasource name that is used to look up the DSN from the runtime configuation file.
508
	 * @param      string $mode The connection mode (this applies to replication systems).
509
	 *
510
	 * @return     PDO A database connection
511
	 *
512
	 * @throws     PropelException - if connection cannot be configured or initialized.
513
	 */
514
	public static function getConnection($name = null, $mode = Propel::CONNECTION_WRITE)
515
	{
516
		if ($name === null) {
517
			$name = self::getDefaultDB();
518
		}
519
 
520
		// IF a WRITE-mode connection was requested
521
		// or Propel is configured to always use the master connection
522
		// or the slave for this connection has already been set to FALSE (indicating no slave)
523
		// THEN return the master connection.
524
		if ($mode != Propel::CONNECTION_READ || self::$forceMasterConnection || (isset(self::$connectionMap[$name]['slave']) && self::$connectionMap[$name]['slave'] === false)) {
525
			if (!isset(self::$connectionMap[$name]['master'])) {
526
				// load connection parameter for master connection
527
				$conparams = isset(self::$configuration['datasources'][$name]['connection']) ? self::$configuration['datasources'][$name]['connection'] : null;
528
				if (empty($conparams)) {
529
					throw new PropelException('No connection information in your runtime configuration file for datasource ['.$name.']');
530
				}
531
				// initialize master connection
532
				$con = Propel::initConnection($conparams, $name);
533
				self::$connectionMap[$name]['master'] = $con;
534
			}
535
 
536
			return self::$connectionMap[$name]['master'];
537
 
538
		} else {
539
 
540
			if (!isset(self::$connectionMap[$name]['slave'])) {
541
 
542
				// we've already ensured that the configuration exists, in previous if-statement
543
				$slaveconfigs = isset(self::$configuration['datasources'][$name]['slaves']) ? self::$configuration['datasources'][$name]['slaves'] : null;
544
 
545
				if (empty($slaveconfigs)) { // no slaves configured for this datasource
546
					self::$connectionMap[$name]['slave'] = false;
547
					return self::getConnection($name, Propel::CONNECTION_WRITE); // Recurse to get the WRITE connection
548
				} else { // Initialize a new slave
549
					if (isset($slaveconfigs['connection']['dsn'])) { // only one slave connection configured
550
						$conparams = $slaveconfigs['connection'];
551
					} else {
552
						$randkey = array_rand($slaveconfigs['connection']);
553
						$conparams = $slaveconfigs['connection'][$randkey];
554
						if (empty($conparams)) {
555
							throw new PropelException('No connection information in your runtime configuration file for SLAVE ['.$randkey.'] to datasource ['.$name.']');
556
						}
557
					}
558
 
559
					// initialize master connection
560
					$con = Propel::initConnection($conparams, $name);
561
					self::$connectionMap[$name]['slave'] = $con;
562
				}
563
 
564
			} // if datasource slave not set
565
 
566
			return self::$connectionMap[$name]['slave'];
567
 
568
		} // if mode == CONNECTION_WRITE
569
 
570
	} // getConnection()
571
 
572
	/**
573
	 * Opens a new PDO connection for passed-in db name.
574
	 *
575
	 * @param      array $conparams Connection paramters.
576
	 * @param      string $name Datasource name.
577
	 * @param      string $defaultClass The PDO subclass to instantiate if there is no explicit classname
578
	 * 									specified in the connection params (default is Propel::CLASS_PROPEL_PDO)
579
	 *
580
	 * @return     PDO A database connection of the given class (PDO, PropelPDO, SlavePDO or user-defined)
581
	 *
582
	 * @throws     PropelException - if lower-level exception caught when trying to connect.
583
	 */
584
	public static function initConnection($conparams, $name, $defaultClass = Propel::CLASS_PROPEL_PDO)
585
	{
586
 
587
		$dsn = $conparams['dsn'];
588
		if ($dsn === null) {
589
			throw new PropelException('No dsn specified in your connection parameters for datasource ['.$name.']');
590
		}
591
 
592
		if (isset($conparams['classname']) && !empty($conparams['classname'])) {
593
			$classname = $conparams['classname'];
594
			if (!class_exists($classname)) {
595
				throw new PropelException('Unable to load specified PDO subclass: ' . $classname);
596
			}
597
		} else {
598
			$classname = $defaultClass;
599
		}
600
 
601
		$user = isset($conparams['user']) ? $conparams['user'] : null;
602
		$password = isset($conparams['password']) ? $conparams['password'] : null;
603
 
604
		// load any driver options from the config file
605
		// driver options are those PDO settings that have to be passed during the connection construction
606
		$driver_options = array();
607
		if ( isset($conparams['options']) && is_array($conparams['options']) ) {
608
			try {
609
				self::processDriverOptions( $conparams['options'], $driver_options );
610
			} catch (PropelException $e) {
611
				throw new PropelException('Error processing driver options for datasource ['.$name.']', $e);
612
			}
613
		}
614
 
615
		try {
616
			$con = new $classname($dsn, $user, $password, $driver_options);
617
			$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
618
		} catch (PDOException $e) {
619
			throw new PropelException("Unable to open PDO connection", $e);
620
		}
621
 
622
		// load any connection options from the config file
623
		// connection attributes are those PDO flags that have to be set on the initialized connection
624
		if (isset($conparams['attributes']) && is_array($conparams['attributes'])) {
625
			$attributes = array();
626
			try {
627
				self::processDriverOptions( $conparams['attributes'], $attributes );
628
			} catch (PropelException $e) {
629
				throw new PropelException('Error processing connection attributes for datasource ['.$name.']', $e);
630
			}
631
			foreach ($attributes as $key => $value) {
632
				$con->setAttribute($key, $value);
633
			}
634
		}
635
 
636
		// initialize the connection using the settings provided in the config file. this could be a "SET NAMES <charset>" query for MySQL, for instance
637
		$adapter = self::getDB($name);
638
		$adapter->initConnection($con, isset($conparams['settings']) && is_array($conparams['settings']) ? $conparams['settings'] : array());
639
 
640
		return $con;
641
	}
642
 
643
	/**
644
	 * Internal function to handle driver options or conneciton attributes in PDO.
645
	 *
646
	 * Process the INI file flags to be passed to each connection.
647
	 *
648
	 * @param      array Where to find the list of constant flags and their new setting.
649
	 * @param      array Put the data into here
650
	 *
651
	 * @throws     PropelException If invalid options were specified.
652
	 */
653
	private static function processDriverOptions($source, &$write_to)
654
	{
655
		foreach ($source as $option => $optiondata) {
656
			if (is_string($option) && strpos($option, '::') !== false) {
657
				$key = $option;
658
			} elseif (is_string($option)) {
659
				$key = 'PropelPDO::' . $option;
660
			}
661
			if (!defined($key)) {
662
				throw new PropelException("Invalid PDO option/attribute name specified: ".$key);
663
			}
664
			$key = constant($key);
665
 
666
			$value = $optiondata['value'];
667
			if (is_string($value) && strpos($value, '::') !== false) {
668
				if (!defined($value)) {
669
					throw new PropelException("Invalid PDO option/attribute value specified: ".$value);
670
				}
671
				$value = constant($value);
672
			}
673
 
674
			$write_to[$key] = $value;
675
		}
676
	}
677
 
678
	/**
679
	 * Returns database adapter for a specific datasource.
680
	 *
681
	 * @param      string The datasource name.
682
	 *
683
	 * @return     DBAdapter The corresponding database adapter.
684
	 *
685
	 * @throws     PropelException If unable to find DBdapter for specified db.
686
	 */
687
	public static function getDB($name = null)
688
	{
689
		if ($name === null) {
690
			$name = self::getDefaultDB();
691
		}
692
 
693
		if (!isset(self::$adapterMap[$name])) {
694
			if (!isset(self::$configuration['datasources'][$name]['adapter'])) {
695
				throw new PropelException("Unable to find adapter for datasource [" . $name . "].");
696
			}
697
			$db = DBAdapter::factory(self::$configuration['datasources'][$name]['adapter']);
698
			// register the adapter for this name
699
			self::$adapterMap[$name] = $db;
700
		}
701
 
702
		return self::$adapterMap[$name];
703
	}
704
 
705
	/**
706
	 * Sets a database adapter for specified datasource.
707
	 *
708
	 * @param      string $name The datasource name.
709
	 * @param      DBAdapter $adapter The DBAdapter implementation to use.
710
	 */
711
	public static function setDB($name, DBAdapter $adapter)
712
	{
713
		if ($name === null) {
714
			$name = self::getDefaultDB();
715
		}
716
		self::$adapterMap[$name] = $adapter;
717
	}
718
 
719
	/**
720
	 * Returns the name of the default database.
721
	 *
722
	 * @return     string Name of the default DB
723
	 */
724
	public static function getDefaultDB()
725
	{
726
		if (self::$defaultDBName === null) {
727
			// Determine default database name.
728
			self::$defaultDBName = isset(self::$configuration['datasources']['default']) ? self::$configuration['datasources']['default'] : self::DEFAULT_NAME;
729
		}
730
		return self::$defaultDBName;
731
	}
732
 
733
	/**
734
	 * Closes any associated resource handles.
735
	 *
736
	 * This method frees any database connection handles that have been
737
	 * opened by the getConnection() method.
738
	 */
739
	public static function close()
740
	{
741
		foreach (self::$connectionMap as $idx => $cons) {
742
			// Propel::log("Closing connections for " . $idx, Propel::LOG_DEBUG);
743
			unset(self::$connectionMap[$idx]);
744
		}
745
	}
746
 
747
	/**
748
	 * Autoload function for loading propel dependencies.
749
	 *
750
	 * @param      string The class name needing loading.
751
	 *
752
	 * @return     boolean TRUE if the class was loaded, false otherwise.
753
	 */
754
	public static function autoload($className)
755
	{
756
		if (isset(self::$autoloadMap[$className])) {
757
			require(self::$autoloadMap[$className]);
758
			return true;
759
		}
760
		return false;
761
	}
762
 
763
	/**
764
	 * Include once a file specified in DOT notation and reutrn unqualified clasname.
765
	 *
766
	 * Typically, Propel uses autoload is used to load classes and expects that all classes
767
	 * referenced within Propel are included in Propel's autoload map.  This method is only
768
	 * called when a specific non-Propel classname was specified -- for example, the
769
	 * classname of a validator in the schema.xml.  This method will attempt to include that
770
	 * class via autoload and then relative to a location on the include_path.
771
	 *
772
	 * @param      string $class dot-path to clas (e.g. path.to.my.ClassName).
773
	 * @return     string unqualified classname
774
	 */
775
	public static function importClass($path) {
776
 
777
		// extract classname
778
		if (($pos = strrpos($path, '.')) === false) {
779
			$class = $path;
780
		} else {
781
			$class = substr($path, $pos + 1);
782
		}
783
 
784
		// check if class exists, using autoloader to attempt to load it.
785
		if (class_exists($class, $useAutoload=true)) {
786
			return $class;
787
		}
788
 
789
		// turn to filesystem path
790
		$path = strtr($path, '.', DIRECTORY_SEPARATOR) . '.php';
791
 
792
		// include class
793
		$ret = include_once($path);
794
		if ($ret === false) {
795
			throw new PropelException("Unable to import class: " . $class . " from " . $path);
796
		}
797
 
798
		// return qualified name
799
		return $class;
800
	}
801
 
802
	/**
803
	 * Set your own class-name for Database-Mapping. Then
804
	 * you can change the whole TableMap-Model, but keep its
805
	 * functionality for Criteria.
806
	 *
807
	 * @param      string The name of the class.
808
	 */
809
	public static function setDatabaseMapClass($name)
810
	{
811
		self::$databaseMapClass = $name;
812
	}
813
 
814
	/**
815
	 * Disable instance pooling.
816
	 */
817
	public static function disableInstancePooling()
818
	{
819
		self::$instancePoolingEnabled = false;
820
	}
821
 
822
	/**
823
	 * Enable instance pooling (enabled by default).
824
	 */
825
	public static function enableInstancePooling()
826
	{
827
		self::$instancePoolingEnabled = true;
828
	}
829
 
830
	/**
831
	 *  the instance pooling behaviour. True by default.
832
	 *
833
	 * @return     boolean Whether the pooling is enabled or not.
834
	 */
835
	public static function isInstancePoolingEnabled()
836
	{
837
		return self::$instancePoolingEnabled;
838
	}
839
}
840
 
841
spl_autoload_register(array('Propel', 'autoload'));