Manager.php 25 KB
Newer Older
lsmith's avatar
lsmith committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
<?php
/*
 *  $Id$
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the LGPL. For more information, see
19
 * <http://www.phpdoctrine.org>.
lsmith's avatar
lsmith committed
20
 */
21

lsmith's avatar
lsmith committed
22 23
/**
 *
lsmith's avatar
lsmith committed
24
 * Doctrine_Manager is the base component of all doctrine based projects.
lsmith's avatar
lsmith committed
25 26 27
 * It opens and keeps track of all connections (database connections).
 *
 * @package     Doctrine
28
 * @subpackage  Manager
lsmith's avatar
lsmith committed
29 30 31 32 33 34
 * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
 * @link        www.phpdoctrine.com
 * @since       1.0
 * @version     $Revision$
 * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
 */
lsmith's avatar
lsmith committed
35 36
class Doctrine_Manager extends Doctrine_Configurable implements Countable, IteratorAggregate
{
lsmith's avatar
lsmith committed
37
    /**
zYne's avatar
zYne committed
38
     * @var array $connections          an array containing all the opened connections
lsmith's avatar
lsmith committed
39
     */
40
    protected $_connections   = array();
41

lsmith's avatar
lsmith committed
42
    /**
zYne's avatar
zYne committed
43
     * @var array $bound                an array containing all components that have a bound connection
lsmith's avatar
lsmith committed
44
     */
45
    protected $_bound         = array();
46

lsmith's avatar
lsmith committed
47
    /**
zYne's avatar
zYne committed
48
     * @var integer $index              the incremented index
lsmith's avatar
lsmith committed
49
     */
50
    protected $_index         = 0;
51

lsmith's avatar
lsmith committed
52
    /**
zYne's avatar
zYne committed
53
     * @var integer $currIndex          the current connection index
lsmith's avatar
lsmith committed
54
     */
55
    protected $_currIndex     = 0;
56

lsmith's avatar
lsmith committed
57
    /**
zYne's avatar
zYne committed
58
     * @var string $root                root directory
lsmith's avatar
lsmith committed
59
     */
60
    protected $_root;
61

zYne's avatar
zYne committed
62
    /**
zYne's avatar
zYne committed
63
     * @var Doctrine_Query_Registry     the query registry
zYne's avatar
zYne committed
64
     */
zYne's avatar
zYne committed
65
    protected $_queryRegistry;
zYne's avatar
zYne committed
66
    
zYne's avatar
zYne committed
67
    protected static $driverMap = array('oci' => 'oracle');
68

lsmith's avatar
lsmith committed
69 70 71 72 73
    /**
     * constructor
     *
     * this is private constructor (use getInstance to get an instance of this class)
     */
lsmith's avatar
lsmith committed
74 75
    private function __construct()
    {
76
        $this->_root = dirname(__FILE__);
77
        Doctrine_Locator_Injectable::initNullObject(new Doctrine_Null);
lsmith's avatar
lsmith committed
78
    }
79

lsmith's avatar
lsmith committed
80 81 82 83
    /**
     * setDefaultAttributes
     * sets default attributes
     *
84
     * @todo I do not understand the flow here. Explain or refactor?
lsmith's avatar
lsmith committed
85 86
     * @return boolean
     */
87
    public function setDefaultAttributes()
lsmith's avatar
lsmith committed
88
    {
lsmith's avatar
lsmith committed
89 90 91 92
        static $init = false;
        if ( ! $init) {
            $init = true;
            $attributes = array(
93
                        Doctrine::ATTR_CACHE                    => null,
94 95
                        Doctrine::ATTR_RESULT_CACHE             => null,
                        Doctrine::ATTR_QUERY_CACHE              => null,
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
                        Doctrine::ATTR_LOAD_REFERENCES          => true,
                        Doctrine::ATTR_LISTENER                 => new Doctrine_EventListener(),
                        Doctrine::ATTR_RECORD_LISTENER          => new Doctrine_Record_Listener(),
                        Doctrine::ATTR_THROW_EXCEPTIONS         => true,
                        Doctrine::ATTR_VALIDATE                 => Doctrine::VALIDATE_NONE,
                        Doctrine::ATTR_QUERY_LIMIT              => Doctrine::LIMIT_RECORDS,
                        Doctrine::ATTR_IDXNAME_FORMAT           => "%s_idx",
                        Doctrine::ATTR_SEQNAME_FORMAT           => "%s_seq",
                        Doctrine::ATTR_TBLNAME_FORMAT           => "%s",
                        Doctrine::ATTR_QUOTE_IDENTIFIER         => false,
                        Doctrine::ATTR_SEQCOL_NAME              => 'id',
                        Doctrine::ATTR_PORTABILITY              => Doctrine::PORTABILITY_ALL,
                        Doctrine::ATTR_EXPORT                   => Doctrine::EXPORT_ALL,
                        Doctrine::ATTR_DECIMAL_PLACES           => 2,
                        Doctrine::ATTR_DEFAULT_PARAM_NAMESPACE  => 'doctrine',
111
                        Doctrine::ATTR_AUTOLOAD_TABLE_CLASSES   => true,
112
                        ); 
lsmith's avatar
lsmith committed
113 114 115 116 117 118 119 120 121 122
            foreach ($attributes as $attribute => $value) {
                $old = $this->getAttribute($attribute);
                if ($old === null) {
                    $this->setAttribute($attribute,$value);
                }
            }
            return true;
        }
        return false;
    }
123

lsmith's avatar
lsmith committed
124 125 126 127 128
    /**
     * returns the root directory of Doctrine
     *
     * @return string
     */
lsmith's avatar
lsmith committed
129 130
    final public function getRoot()
    {
131
        return $this->_root;
lsmith's avatar
lsmith committed
132
    }
133

lsmith's avatar
lsmith committed
134 135 136 137 138 139 140
    /**
     * getInstance
     * returns an instance of this class
     * (this class uses the singleton pattern)
     *
     * @return Doctrine_Manager
     */
lsmith's avatar
lsmith committed
141 142
    public static function getInstance()
    {
lsmith's avatar
lsmith committed
143 144 145 146 147 148
        static $instance;
        if ( ! isset($instance)) {
            $instance = new self();
        }
        return $instance;
    }
zYne's avatar
zYne committed
149 150 151 152 153 154 155 156 157 158

    /**
     * getQueryRegistry
     * lazy-initializes the query registry object and returns it
     *
     * @return Doctrine_Query_Registry
     */
    public function getQueryRegistry()
    {
    	if ( ! isset($this->_queryRegistry)) {
zYne's avatar
zYne committed
159
    	   $this->_queryRegistry = new Doctrine_Query_Registry;
zYne's avatar
zYne committed
160 161 162
    	}
        return $this->_queryRegistry;
    }
163

zYne's avatar
zYne committed
164 165 166 167 168 169
    /**
     * setQueryRegistry
     * sets the query registry
     *
     * @return Doctrine_Manager     this object
     */
zYne's avatar
zYne committed
170
    public function setQueryRegistry(Doctrine_Query_Registry $registry)
zYne's avatar
zYne committed
171 172 173 174 175
    {
        $this->_queryRegistry = $registry;
        
        return $this;
    }
176

zYne's avatar
zYne committed
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
    /**
     * fetch
     * fetches data using the provided queryKey and 
     * the associated query in the query registry
     *
     * if no query for given queryKey is being found a 
     * Doctrine_Query_Registry exception is being thrown
     *
     * @param string $queryKey      the query key
     * @param array $params         prepared statement params (if any)
     * @return mixed                the fetched data
     */
    public function find($queryKey, $params = array(), $hydrationMode = Doctrine::HYDRATE_RECORD)
    {
        return Doctrine_Manager::getInstance()
192 193 194
                ->getQueryRegistry()
                ->get($queryKey)
                ->execute($params, $hydrationMode);
zYne's avatar
zYne committed
195
    }
196

zYne's avatar
zYne committed
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
    /**
     * fetchOne
     * fetches data using the provided queryKey and 
     * the associated query in the query registry
     *
     * if no query for given queryKey is being found a 
     * Doctrine_Query_Registry exception is being thrown
     *
     * @param string $queryKey      the query key
     * @param array $params         prepared statement params (if any)
     * @return mixed                the fetched data
     */
    public function findOne($queryKey, $params = array(), $hydrationMode = Doctrine::HYDRATE_RECORD)
    {
        return Doctrine_Manager::getInstance()
212 213 214
                ->getQueryRegistry()
                ->get($queryKey)
                ->fetchOne($params, $hydrationMode);
zYne's avatar
zYne committed
215
    }
216

lsmith's avatar
lsmith committed
217 218
    /**
     * connection
lsmith's avatar
lsmith committed
219
     *
lsmith's avatar
lsmith committed
220 221 222
     * if the adapter parameter is set this method acts as
     * a short cut for Doctrine_Manager::getInstance()->openConnection($adapter, $name);
     *
lsmith's avatar
lsmith committed
223
     * if the adapter paramater is not set this method acts as
lsmith's avatar
lsmith committed
224 225 226 227 228 229 230
     * a short cut for Doctrine_Manager::getInstance()->getCurrentConnection()
     *
     * @param PDO|Doctrine_Adapter_Interface $adapter   database driver
     * @param string $name                              name of the connection, if empty numeric key is used
     * @throws Doctrine_Manager_Exception               if trying to bind a connection with an existing name
     * @return Doctrine_Connection
     */
lsmith's avatar
lsmith committed
231 232
    public static function connection($adapter = null, $name = null)
    {
lsmith's avatar
lsmith committed
233 234 235 236 237
        if ($adapter == null) {
            return Doctrine_Manager::getInstance()->getCurrentConnection();
        } else {
            return Doctrine_Manager::getInstance()->openConnection($adapter, $name);
        }
lsmith's avatar
lsmith committed
238
    }
239

lsmith's avatar
lsmith committed
240 241 242 243 244 245 246
    /**
     * openConnection
     * opens a new connection and saves it to Doctrine_Manager->connections
     *
     * @param PDO|Doctrine_Adapter_Interface $adapter   database driver
     * @param string $name                              name of the connection, if empty numeric key is used
     * @throws Doctrine_Manager_Exception               if trying to bind a connection with an existing name
zYne's avatar
zYne committed
247
     * @throws Doctrine_Manager_Exception               if trying to open connection for unknown driver
lsmith's avatar
lsmith committed
248 249
     * @return Doctrine_Connection
     */
250
    public function openConnection($adapter, $name = null, $setCurrent = true)
lsmith's avatar
lsmith committed
251
    {
252
        if (is_object($adapter)) {
Jonathan.Wage's avatar
Jonathan.Wage committed
253 254
            if ( ! ($adapter instanceof PDO) && ! in_array('Doctrine_Adapter_Interface', class_implements($adapter))) {
                throw new Doctrine_Manager_Exception("First argument should be an instance of PDO or implement Doctrine_Adapter_Interface");
255 256 257
            }

            $driverName = $adapter->getAttribute(Doctrine::ATTR_DRIVER_NAME);
258
        } else if (is_array($adapter)) {
259 260 261 262 263
            if ( ! isset($adapter[0])) {
                throw new Doctrine_Manager_Exception('Empty data source name given.');
            }
            $e = explode(':', $adapter[0]);

264
            if ($e[0] == 'uri') {
265 266
                $e[0] = 'odbc';
            }
lsmith's avatar
lsmith committed
267

268 269 270 271 272 273 274 275 276 277 278
            $parts['dsn']    = $adapter[0];
            $parts['scheme'] = $e[0];
            $parts['user']   = (isset($adapter[1])) ? $adapter[1] : null;
            $parts['pass']   = (isset($adapter[2])) ? $adapter[2] : null;
            
            $driverName = $e[0];
            $adapter = $parts;
        } else {
            $parts = $this->parseDsn($adapter);
            $driverName = $parts['scheme'];
            $adapter = $parts;
279 280
        }

lsmith's avatar
lsmith committed
281 282 283 284 285
        // initialize the default attributes
        $this->setDefaultAttributes();

        if ($name !== null) {
            $name = (string) $name;
286
            if (isset($this->_connections[$name])) {
romanb's avatar
romanb committed
287 288 289
                if ($setCurrent) {
                    $this->_currIndex = $name;
                }
290
                return $this->_connections[$name];
lsmith's avatar
lsmith committed
291 292
            }
        } else {
293 294
            $name = $this->_index;
            $this->_index++;
lsmith's avatar
lsmith committed
295
        }
zYne's avatar
zYne committed
296

297 298 299 300 301 302 303 304 305 306
        $drivers = array('mysql'    => 'Doctrine_Connection_Mysql',
                         'sqlite'   => 'Doctrine_Connection_Sqlite',
                         'pgsql'    => 'Doctrine_Connection_Pgsql',
                         'oci'      => 'Doctrine_Connection_Oracle',
                         'oci8'     => 'Doctrine_Connection_Oracle',
                         'oracle'   => 'Doctrine_Connection_Oracle',
                         'mssql'    => 'Doctrine_Connection_Mssql',
                         'dblib'    => 'Doctrine_Connection_Mssql',
                         'firebird' => 'Doctrine_Connection_Firebird',
                         'informix' => 'Doctrine_Connection_Informix',
307
                         'mock'     => 'Doctrine_Connection_Mock');
308
        
309 310 311
        if ( ! isset($drivers[$driverName])) {
            throw new Doctrine_Manager_Exception('Unknown driver ' . $driverName);
        }
Jonathan.Wage's avatar
Jonathan.Wage committed
312
        
313 314
        $className = $drivers[$driverName];
        $conn = new $className($this, $adapter);
315
        $conn->setName($name);
316 317 318 319 320 321 322 323

        $this->_connections[$name] = $conn;

        if ($setCurrent) {
            $this->_currIndex = $name;
        }
        return $this->_connections[$name];
    }
324
    
325 326 327 328 329 330
    /**
     * parsePdoDsn 
     * 
     * @param array $dsn An array of dsn information 
     * @return array The array parsed
     */
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
    public function parsePdoDsn($dsn)
    {
        $parts = array();
        
        $names = array('dsn', 'scheme', 'host', 'port', 'user', 'pass', 'path', 'query', 'fragment');

        foreach ($names as $name) {
            if ( ! isset($parts[$name])) {
                $parts[$name] = null;
            }
        }
        
        $e = explode(':', $dsn);
        $parts['scheme'] = $e[0];
        $parts['dsn'] = $dsn;
        
        $e = explode(';', $e[1]);
        foreach ($e as $string) {
349 350 351 352 353 354 355 356
            if ($string) {
                $e2 = explode('=', $string);

                if (isset($e2[0]) && isset($e2[1])) {
                    list($key, $value) = $e2;
                    $parts[$key] = $value;
                }
            }
357
        }
358

359 360
        return $parts;
    }
361

362 363 364 365 366 367 368 369
    /**
     * parseDsn
     *
     * @param string $dsn
     * @return array Parsed contents of DSN
     */
    public function parseDsn($dsn)
    {
370 371 372 373
        // fix sqlite dsn so that it will parse correctly
        $dsn = str_replace("////", "/", $dsn);
        $dsn = str_replace("///c:/", "//c:/", $dsn);
        
374 375
        // silence any warnings
        $parts = @parse_url($dsn);
Jonathan.Wage's avatar
Jonathan.Wage committed
376

377 378 379 380 381 382 383 384 385 386 387 388 389
        $names = array('dsn', 'scheme', 'host', 'port', 'user', 'pass', 'path', 'query', 'fragment');

        foreach ($names as $name) {
            if ( ! isset($parts[$name])) {
                $parts[$name] = null;
            }
        }

        if (count($parts) == 0 || ! isset($parts['scheme'])) {
            throw new Doctrine_Manager_Exception('Empty data source name');
        }

        switch ($parts['scheme']) {
390
            case 'sqlite':
391 392 393 394 395
            case 'sqlite2':
            case 'sqlite3':
                if (isset($parts['host']) && $parts['host'] == ':memory') {
                    $parts['database'] = ':memory:';
                    $parts['dsn']      = 'sqlite::memory:';
zYne's avatar
zYne committed
396
                } else {
397 398 399 400 401
                    //fix windows dsn we have to add host: to path and set host to null
                    if (isset($parts['host'])) {
                        $parts['path'] = $parts['host'] . ":" . $parts["path"];
                        $parts["host"] = null;
                    }
zYne's avatar
zYne committed
402
                    $parts['database'] = $parts['path'];
403
                    $parts['dsn'] = $parts['scheme'] . ':' . $parts['path'];
404 405
                }

406
                break;
ppetermann's avatar
ppetermann committed
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
            
            case 'mssql':
            case 'dblib':
                if ( ! isset($parts['path']) || $parts['path'] == '/') {
                    throw new Doctrine_Manager_Exception('No database available in data source name');
                }
                if (isset($parts['path'])) {
                    $parts['database'] = substr($parts['path'], 1);
                }
                if ( ! isset($parts['host'])) {
                    throw new Doctrine_Manager_Exception('No hostname set in data source name');
                }
                
                if (isset(self::$driverMap[$parts['scheme']])) {
                    $parts['scheme'] = self::$driverMap[$parts['scheme']];
                }

                $parts['dsn'] = $parts['scheme'] . ':host='
                              . $parts['host'] . (isset($parts['port']) ? ':' . $parts['port']:null) . ';dbname='
                              . $parts['database'];
                
                break;

430 431
            case 'mysql':
            case 'informix':
zYne's avatar
zYne committed
432
            case 'oci8':
433
            case 'oci':
434
            case 'firebird':
435 436
            case 'pgsql':
            case 'odbc':
437
            case 'mock':
438 439
            case 'oracle':
                if ( ! isset($parts['path']) || $parts['path'] == '/') {
zYne's avatar
zYne committed
440
                    throw new Doctrine_Manager_Exception('No database available in data source name');
441 442 443 444 445 446 447 448 449 450 451 452 453
                }
                if (isset($parts['path'])) {
                    $parts['database'] = substr($parts['path'], 1);
                }
                if ( ! isset($parts['host'])) {
                    throw new Doctrine_Manager_Exception('No hostname set in data source name');
                }
                
                if (isset(self::$driverMap[$parts['scheme']])) {
                    $parts['scheme'] = self::$driverMap[$parts['scheme']];
                }

                $parts['dsn'] = $parts['scheme'] . ':host='
454
                              . $parts['host'] . (isset($parts['port']) ? ';port=' . $parts['port']:null) . ';dbname='
455 456
                              . $parts['database'];
                
457 458
                break;
            default:
459
                throw new Doctrine_Manager_Exception('Unknown driver '.$parts['scheme']);
460
        }
461 462

        return $parts;
lsmith's avatar
lsmith committed
463
    }
464

lsmith's avatar
lsmith committed
465 466 467 468 469 470
    /**
     * getConnection
     * @param integer $index
     * @return object Doctrine_Connection
     * @throws Doctrine_Manager_Exception   if trying to get a non-existent connection
     */
lsmith's avatar
lsmith committed
471 472
    public function getConnection($name)
    {
473
        if ( ! isset($this->_connections[$name])) {
lsmith's avatar
lsmith committed
474 475
            throw new Doctrine_Manager_Exception('Unknown connection: ' . $name);
        }
zYne's avatar
zYne committed
476

477
        return $this->_connections[$name];
lsmith's avatar
lsmith committed
478
    }
479

480
    /**
481
     * getComponentAlias
482
     * retrieves the alias for given component name
483 484 485 486 487 488 489 490 491 492 493
     * if the alias couldn't be found, this method returns the given
     * component name
     *
     * @param string $componentName
     * @return string                   the component alias
     */
    public function getComponentAlias($componentName)
    {
        if (isset($this->componentAliases[$componentName])) {
            return $this->componentAliases[$componentName];
        }
494

495 496
        return $componentName;
    }
497

498 499 500 501 502 503 504 505 506
    /**
     * sets an alias for given component name
     * very useful when building a large framework with a possibility
     * to override any given class
     *
     * @param string $componentName         the name of the component
     * @param string $alias
     * @return Doctrine_Manager
     */
507
    public function setComponentAlias($componentName, $alias)
508 509
    {
        $this->componentAliases[$componentName] = $alias;
510

511 512
        return $this;
    }
513

zYne's avatar
zYne committed
514 515 516
    /**
     * getConnectionName
     *
zYne's avatar
zYne committed
517 518
     * @param Doctrine_Connection $conn     connection object to be searched for
     * @return string                       the name of the connection
zYne's avatar
zYne committed
519
     */
520
    public function getConnectionName(Doctrine_Connection $conn)
zYne's avatar
zYne committed
521
    {
522
        return array_search($conn, $this->_connections, true);
zYne's avatar
zYne committed
523
    }
524

lsmith's avatar
lsmith committed
525 526 527 528 529 530 531 532 533 534
    /**
     * bindComponent
     * binds given component to given connection
     * this means that when ever the given component uses a connection
     * it will be using the bound connection instead of the current connection
     *
     * @param string $componentName
     * @param string $connectionName
     * @return boolean
     */
lsmith's avatar
lsmith committed
535 536
    public function bindComponent($componentName, $connectionName)
    {
537
        $this->_bound[$componentName] = $connectionName;
lsmith's avatar
lsmith committed
538
    }
539

lsmith's avatar
lsmith committed
540 541 542 543 544 545
    /**
     * getConnectionForComponent
     *
     * @param string $componentName
     * @return Doctrine_Connection
     */
lsmith's avatar
lsmith committed
546 547
    public function getConnectionForComponent($componentName = null)
    {
548 549
        if (isset($this->_bound[$componentName])) {
            return $this->getConnection($this->_bound[$componentName]);
lsmith's avatar
lsmith committed
550 551 552
        }
        return $this->getCurrentConnection();
    }
romanb's avatar
romanb committed
553 554 555 556 557 558 559 560 561 562 563
    
    /**
     * hasConnectionForComponent
     *
     * @param string $componentName
     * @return boolean
     */
    public function hasConnectionForComponent($componentName = null)
    {
        return isset($this->_bound[$componentName]);
    }
564

lsmith's avatar
lsmith committed
565
    /**
lsmith's avatar
lsmith committed
566 567 568 569 570 571 572 573
     * getTable
     * this is the same as Doctrine_Connection::getTable() except
     * that it works seamlessly in multi-server/connection environment
     *
     * @see Doctrine_Connection::getTable()
     * @param string $componentName
     * @return Doctrine_Table
     */
lsmith's avatar
lsmith committed
574 575
    public function getTable($componentName)
    {
lsmith's avatar
lsmith committed
576 577
        return $this->getConnectionForComponent($componentName)->getTable($componentName);
    }
578 579 580 581 582 583 584 585 586 587 588 589
    
    /**
     * getMapper
     * Returns the mapper object for the given component name.
     *
     * @param string $componentName
     * @return Doctrine_Mapper
     */
    public function getMapper($componentName)
    {
        return $this->getConnectionForComponent($componentName)->getMapper($componentName);
    }
590

zYne's avatar
zYne committed
591 592 593 594 595 596 597 598 599 600 601 602 603 604 605
    /**
     * table
     * this is the same as Doctrine_Connection::getTable() except
     * that it works seamlessly in multi-server/connection environment
     *
     * @see Doctrine_Connection::getTable()
     * @param string $componentName
     * @return Doctrine_Table
     */
    public static function table($componentName)
    {
        return Doctrine_Manager::getInstance()
               ->getConnectionForComponent($componentName)
               ->getTable($componentName);
    }
606

lsmith's avatar
lsmith committed
607 608 609 610 611 612
    /**
     * closes the connection
     *
     * @param Doctrine_Connection $connection
     * @return void
     */
lsmith's avatar
lsmith committed
613 614
    public function closeConnection(Doctrine_Connection $connection)
    {
lsmith's avatar
lsmith committed
615
        $connection->close();
616

617
        $key = array_search($connection, $this->_connections, true);
zYne's avatar
zYne committed
618 619

        if ($key !== false) {
620
            unset($this->_connections[$key]);
zYne's avatar
zYne committed
621
        }
622
        $this->_currIndex = key($this->_connections);
zYne's avatar
zYne committed
623

lsmith's avatar
lsmith committed
624 625
        unset($connection);
    }
626

lsmith's avatar
lsmith committed
627 628 629 630 631 632
    /**
     * getConnections
     * returns all opened connections
     *
     * @return array
     */
lsmith's avatar
lsmith committed
633 634
    public function getConnections()
    {
635
        return $this->_connections;
lsmith's avatar
lsmith committed
636
    }
637

lsmith's avatar
lsmith committed
638 639 640 641 642 643 644 645
    /**
     * setCurrentConnection
     * sets the current connection to $key
     *
     * @param mixed $key                        the connection key
     * @throws InvalidKeyException
     * @return void
     */
lsmith's avatar
lsmith committed
646 647
    public function setCurrentConnection($key)
    {
lsmith's avatar
lsmith committed
648
        $key = (string) $key;
649
        if ( ! isset($this->_connections[$key])) {
lsmith's avatar
lsmith committed
650 651
            throw new InvalidKeyException();
        }
652
        $this->_currIndex = $key;
lsmith's avatar
lsmith committed
653
    }
654

zYne's avatar
zYne committed
655 656 657 658 659 660 661
    /**
     * contains
     * whether or not the manager contains specified connection
     *
     * @param mixed $key                        the connection key
     * @return boolean
     */
662
    public function contains($key)
zYne's avatar
zYne committed
663
    {
664
        return isset($this->_connections[$key]);
zYne's avatar
zYne committed
665
    }
666

lsmith's avatar
lsmith committed
667 668 669 670 671 672
    /**
     * count
     * returns the number of opened connections
     *
     * @return integer
     */
lsmith's avatar
lsmith committed
673 674
    public function count()
    {
675
        return count($this->_connections);
lsmith's avatar
lsmith committed
676
    }
677

lsmith's avatar
lsmith committed
678 679 680 681 682 683
    /**
     * getIterator
     * returns an ArrayIterator that iterates through all connections
     *
     * @return ArrayIterator
     */
lsmith's avatar
lsmith committed
684 685
    public function getIterator()
    {
686
        return new ArrayIterator($this->_connections);
lsmith's avatar
lsmith committed
687
    }
688

lsmith's avatar
lsmith committed
689 690 691 692 693 694 695
    /**
     * getCurrentConnection
     * returns the current connection
     *
     * @throws Doctrine_Connection_Exception       if there are no open connections
     * @return Doctrine_Connection
     */
lsmith's avatar
lsmith committed
696 697
    public function getCurrentConnection()
    {
698 699
        $i = $this->_currIndex;
        if ( ! isset($this->_connections[$i])) {
lsmith's avatar
lsmith committed
700 701
            throw new Doctrine_Connection_Exception();
        }
702
        return $this->_connections[$i];
lsmith's avatar
lsmith committed
703
    }
704

705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758
    /**
     * createDatabases
     *
     * Creates databases for connections
     *
     * @param string $specifiedConnections Array of connections you wish to create the database for
     * @return void
     */
    public function createDatabases($specifiedConnections = array())
    {
        if ( ! is_array($specifiedConnections)) {
            $specifiedConnections = (array) $specifiedConnections;
        }

        $results = array();

        foreach ($this as $name => $connection) {
            if ( ! empty($specifiedConnections) && !in_array($name, $specifiedConnections)) {
                continue;
            }

            $results[$name] = $connection->createDatabase();
        }

        return $results;
    }

    /**
     * dropDatabases
     *
     * Drops databases for connections
     *
     * @param string $specifiedConnections Array of connections you wish to drop the database for
     * @return void
     */
    public function dropDatabases($specifiedConnections = array())
    {
        if ( ! is_array($specifiedConnections)) {
            $specifiedConnections = (array) $specifiedConnections;
        }

        $results = array();

        foreach ($this as $name => $connection) {
            if ( ! empty($specifiedConnections) && !in_array($name, $specifiedConnections)) {
                continue;
            }

            $results[$name] = $connection->dropDatabase();
        }

        return $results;
    }

lsmith's avatar
lsmith committed
759 760 761 762 763 764
    /**
     * __toString
     * returns a string representation of this object
     *
     * @return string
     */
lsmith's avatar
lsmith committed
765 766
    public function __toString()
    {
lsmith's avatar
lsmith committed
767 768
        $r[] = "<pre>";
        $r[] = "Doctrine_Manager";
769
        $r[] = "Connections : ".count($this->_connections);
lsmith's avatar
lsmith committed
770 771 772
        $r[] = "</pre>";
        return implode("\n",$r);
    }
773
}