Coverage for Doctrine

Back to coverage report

1 <?php
2 /*
3  *  $Id: Doctrine.php 3223 2007-11-25 19:07:30Z romanb $
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, see
19  * <http://www.phpdoctrine.com>.
20  */
21
22 /**
23  * Doctrine
24  * the base class of Doctrine framework
25  *
26  * @package     Doctrine
27  * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
28  * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
29  * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
30  * @link        www.phpdoctrine.com
31  * @since       1.0
32  * @version     $Revision: 3223 $
33  */
34 final class Doctrine
35 {
36     /**
37      * VERSION
38      */
39     const VERSION                   = '0.1.0';
40
41     /**
42      * ERROR CONSTANTS
43      */
44     const ERR                       = -1;
45     const ERR_SYNTAX                = -2;
46     const ERR_CONSTRAINT            = -3;
47     const ERR_NOT_FOUND             = -4;
48     const ERR_ALREADY_EXISTS        = -5;
49     const ERR_UNSUPPORTED           = -6;
50     const ERR_MISMATCH              = -7;
51     const ERR_INVALID               = -8;
52     const ERR_NOT_CAPABLE           = -9;
53     const ERR_TRUNCATED             = -10;
54     const ERR_INVALID_NUMBER        = -11;
55     const ERR_INVALID_DATE          = -12;
56     const ERR_DIVZERO               = -13;
57     const ERR_NODBSELECTED          = -14;
58     const ERR_CANNOT_CREATE         = -15;
59     const ERR_CANNOT_DELETE         = -16;
60     const ERR_CANNOT_DROP           = -17;
61     const ERR_NOSUCHTABLE           = -18;
62     const ERR_NOSUCHFIELD           = -19;
63     const ERR_NEED_MORE_DATA        = -20;
64     const ERR_NOT_LOCKED            = -21;
65     const ERR_VALUE_COUNT_ON_ROW    = -22;
66     const ERR_INVALID_DSN           = -23;
67     const ERR_CONNECT_FAILED        = -24;
68     const ERR_EXTENSION_NOT_FOUND   = -25;
69     const ERR_NOSUCHDB              = -26;
70     const ERR_ACCESS_VIOLATION      = -27;
71     const ERR_CANNOT_REPLACE        = -28;
72     const ERR_CONSTRAINT_NOT_NULL   = -29;
73     const ERR_DEADLOCK              = -30;
74     const ERR_CANNOT_ALTER          = -31;
75     const ERR_MANAGER               = -32;
76     const ERR_MANAGER_PARSE         = -33;
77     const ERR_LOADMODULE            = -34;
78     const ERR_INSUFFICIENT_DATA     = -35;
79     const ERR_CLASS_NAME            = -36;
80
81     /**
82      * PDO derived constants
83      */
84     const CASE_LOWER = 2;
85     const CASE_NATURAL = 0;
86     const CASE_UPPER = 1;
87     const CURSOR_FWDONLY = 0;
88     const CURSOR_SCROLL = 1;
89     const ERRMODE_EXCEPTION = 2;
90     const ERRMODE_SILENT = 0;
91     const ERRMODE_WARNING = 1;
92     const FETCH_ASSOC = 2;
93     const FETCH_BOTH = 4;
94     const FETCH_BOUND = 6;
95     const FETCH_CLASS = 8;
96     const FETCH_CLASSTYPE = 262144;
97     const FETCH_COLUMN = 7;
98     const FETCH_FUNC = 10;
99     const FETCH_GROUP = 65536;
100     const FETCH_INTO = 9;
101     const FETCH_LAZY = 1;
102     const FETCH_NAMED = 11;
103     const FETCH_NUM = 3;
104     const FETCH_OBJ = 5;
105     const FETCH_ORI_ABS = 4;
106     const FETCH_ORI_FIRST = 2;
107     const FETCH_ORI_LAST = 3;
108     const FETCH_ORI_NEXT = 0;
109     const FETCH_ORI_PRIOR = 1;
110     const FETCH_ORI_REL = 5;
111     const FETCH_SERIALIZE = 524288;
112     const FETCH_UNIQUE = 196608;
113     const NULL_EMPTY_STRING = 1;
114     const NULL_NATURAL = 0;
115     const NULL_TO_STRING         = NULL;
116     const PARAM_BOOL = 5;
117     const PARAM_INPUT_OUTPUT = -2147483648;
118     const PARAM_INT = 1;
119     const PARAM_LOB = 3;
120     const PARAM_NULL = 0;
121     const PARAM_STMT = 4;
122     const PARAM_STR = 2;
123
124     /**
125      * ATTRIBUTE CONSTANTS
126      */
127
128     /**
129      * PDO derived attributes
130      */
131     const ATTR_AUTOCOMMIT           = 0;
132     const ATTR_PREFETCH             = 1;
133     const ATTR_TIMEOUT              = 2;
134     const ATTR_ERRMODE              = 3;
135     const ATTR_SERVER_VERSION       = 4;
136     const ATTR_CLIENT_VERSION       = 5;
137     const ATTR_SERVER_INFO          = 6;
138     const ATTR_CONNECTION_STATUS    = 7;
139     const ATTR_CASE                 = 8;
140     const ATTR_CURSOR_NAME          = 9;
141     const ATTR_CURSOR               = 10;
142     const ATTR_ORACLE_NULLS         = 11;
143     const ATTR_PERSISTENT           = 12;
144     const ATTR_STATEMENT_CLASS      = 13;
145     const ATTR_FETCH_TABLE_NAMES    = 14;
146     const ATTR_FETCH_CATALOG_NAMES  = 15;
147     const ATTR_DRIVER_NAME          = 16;
148     const ATTR_STRINGIFY_FETCHES    = 17;
149     const ATTR_MAX_COLUMN_LEN       = 18;
150
151     /**
152      * Doctrine constants
153      */
154     const ATTR_LISTENER             = 100;
155     const ATTR_QUOTE_IDENTIFIER     = 101;
156     const ATTR_FIELD_CASE           = 102;
157     const ATTR_IDXNAME_FORMAT       = 103;
158     const ATTR_SEQNAME_FORMAT       = 104;
159     const ATTR_SEQCOL_NAME          = 105;
160     const ATTR_CMPNAME_FORMAT       = 118;
161     const ATTR_DBNAME_FORMAT        = 117;
162     const ATTR_TBLCLASS_FORMAT      = 119;
163     const ATTR_TBLNAME_FORMAT       = 120;
164     const ATTR_EXPORT               = 140;
165     const ATTR_DECIMAL_PLACES       = 141;
166
167     const ATTR_PORTABILITY          = 106;
168     const ATTR_VALIDATE             = 107;
169     const ATTR_COLL_KEY             = 108;
170     const ATTR_QUERY_LIMIT          = 109;
171     const ATTR_DEFAULT_TABLE_TYPE   = 112;
172     const ATTR_DEF_TEXT_LENGTH      = 113;
173     const ATTR_DEF_VARCHAR_LENGTH   = 114;
174     const ATTR_DEF_TABLESPACE       = 115;
175     const ATTR_EMULATE_DATABASE     = 116;
176     const ATTR_USE_NATIVE_ENUM      = 117;
177     const ATTR_DEFAULT_SEQUENCE     = 133;
178
179     const ATTR_FETCHMODE                = 118;
180     const ATTR_NAME_PREFIX              = 121;
181     const ATTR_CREATE_TABLES            = 122;
182     const ATTR_COLL_LIMIT               = 123;
183
184     const ATTR_CACHE                    = 150;
185     const ATTR_RESULT_CACHE             = 150;
186     const ATTR_CACHE_LIFESPAN           = 151;
187     const ATTR_RESULT_CACHE_LIFESPAN    = 151;
188     const ATTR_LOAD_REFERENCES          = 153;
189     const ATTR_RECORD_LISTENER          = 154;
190     const ATTR_THROW_EXCEPTIONS         = 155;
191     const ATTR_DEFAULT_PARAM_NAMESPACE  = 156;
192     const ATTR_QUERY_CACHE              = 157;
193     const ATTR_QUERY_CACHE_LIFESPAN     = 158;
194
195     /**
196      * LIMIT CONSTANTS
197      */
198
199     /**
200      * constant for row limiting
201      */
202     const LIMIT_ROWS       = 1;
203
204     /**
205      * constant for record limiting
206      */
207     const LIMIT_RECORDS    = 2;
208
209     /**
210      * FETCHMODE CONSTANTS
211      */
212
213     /**
214      * IMMEDIATE FETCHING
215      * mode for immediate fetching
216      */
217     const FETCH_IMMEDIATE       = 0;
218
219     /**
220      * BATCH FETCHING
221      * mode for batch fetching
222      */
223     const FETCH_BATCH           = 1;
224
225     /**
226      * LAZY FETCHING
227      * mode for offset fetching
228      */
229     const FETCH_OFFSET          = 3;
230
231     /**
232      * LAZY OFFSET FETCHING
233      * mode for lazy offset fetching
234      */
235     const FETCH_LAZY_OFFSET     = 4;
236
237     /**
238      * FETCH CONSTANTS
239      */
240
241
242     /**
243      * FETCH VALUEHOLDER
244      */
245     const FETCH_VHOLDER         = 1;
246
247     /**
248      * FETCH RECORD
249      *
250      * Specifies that the fetch method shall return Doctrine_Record
251      * objects as the elements of the result set.
252      *
253      * This is the default fetchmode.
254      */
255     const FETCH_RECORD          = 2;
256
257     /**
258      * FETCH ARRAY
259      */
260     const FETCH_ARRAY           = 3;
261
262     /**
263      * PORTABILITY CONSTANTS
264      */
265
266     /**
267      * Portability: turn off all portability features.
268      * @see self::ATTR_PORTABILITY
269      */
270     const PORTABILITY_NONE          = 0;
271
272     /**
273      * Portability: convert names of tables and fields to case defined in the
274      * "field_case" option when using the query*(), fetch*() methods.
275      * @see self::ATTR_PORTABILITY
276      */
277     const PORTABILITY_FIX_CASE      = 1;
278
279     /**
280      * Portability: right trim the data output by query*() and fetch*().
281      * @see self::ATTR_PORTABILITY
282      */
283     const PORTABILITY_RTRIM         = 2;
284
285     /**
286      * Portability: force reporting the number of rows deleted.
287      * @see self::ATTR_PORTABILITY
288      */
289     const PORTABILITY_DELETE_COUNT  = 4;
290
291     /**
292      * Portability: convert empty values to null strings in data output by
293      * query*() and fetch*().
294      * @see self::ATTR_PORTABILITY
295      */
296     const PORTABILITY_EMPTY_TO_NULL = 8;
297
298     /**
299      * Portability: removes database/table qualifiers from associative indexes
300      * @see self::ATTR_PORTABILITY
301      */
302     const PORTABILITY_FIX_ASSOC_FIELD_NAMES = 16;
303
304     /**
305      * Portability: makes Doctrine_Expression throw exception for unportable RDBMS expressions
306      * @see self::ATTR_PORTABILITY
307      */
308     const PORTABILITY_EXPR          = 32;
309
310     /**
311      * Portability: turn on all portability features.
312      * @see self::ATTR_PORTABILITY
313      */
314     const PORTABILITY_ALL           = 63;
315
316     /**
317      * LOCKMODE CONSTANTS
318      */
319
320     /**
321      * mode for optimistic locking
322      */
323     const LOCK_OPTIMISTIC       = 0;
324
325     /**
326      * mode for pessimistic locking
327      */
328     const LOCK_PESSIMISTIC      = 1;
329
330     /**
331      * EXPORT CONSTANTS
332      */
333
334     /**
335      * EXPORT_NONE
336      */
337     const EXPORT_NONE               = 0;
338
339     /**
340      * EXPORT_TABLES
341      */
342     const EXPORT_TABLES             = 1;
343
344     /**
345      * EXPORT_CONSTRAINTS
346      */
347     const EXPORT_CONSTRAINTS        = 2;
348
349     /**
350      * EXPORT_PLUGINS
351      */
352     const EXPORT_PLUGINS            = 4;
353
354     /**
355      * EXPORT_ALL
356      */
357     const EXPORT_ALL                = 7;
358
359     /**
360      * HYDRATION CONSTANTS
361      */
362     const HYDRATE_RECORD            = 2;
363
364     /**
365      * HYDRATE_ARRAY
366      */
367     const HYDRATE_ARRAY             = 3;
368
369     /**
370      * HYDRATE_NONE
371      */
372     const HYDRATE_NONE              = 4;
373
374     /**
375      * VALIDATION CONSTANTS
376      */
377     const VALIDATE_NONE             = 0;
378
379     /**
380      * VALIDATE_LENGTHS
381      */
382     const VALIDATE_LENGTHS          = 1;
383
384     /**
385      * VALIDATE_TYPES
386      */
387     const VALIDATE_TYPES            = 2;
388
389     /**
390      * VALIDATE_CONSTRAINTS
391      */
392     const VALIDATE_CONSTRAINTS      = 4;
393
394     /**
395      * VALIDATE_ALL
396      */
397     const VALIDATE_ALL              = 7;
398
399     /**
400      * IDENTIFIER_AUTOINC
401      *
402      * constant for auto_increment identifier
403      */
404     const IDENTIFIER_AUTOINC        = 1;
405
406     /**
407      * IDENTIFIER_SEQUENCE
408      *
409      * constant for sequence identifier
410      */
411     const IDENTIFIER_SEQUENCE       = 2;
412
413     /**
414      * IDENTIFIER_NATURAL
415      *
416      * constant for normal identifier
417      */
418     const IDENTIFIER_NATURAL        = 3;
419
420     /**
421      * IDENTIFIER_COMPOSITE
422      *
423      * constant for composite identifier
424      */
425     const IDENTIFIER_COMPOSITE      = 4;
426
427     /**
428      * Path
429      *
430      * @var string $path            doctrine root directory
431      */
432     private static $_path;
433
434     /**
435      * Debug
436      *
437      * Bool true/false
438      *
439      * @var boolean $_debug
440      */
441     private static $_debug = false;
442
443     /**
444      * _loadedModels
445      *
446      * Array of all the loaded models and the path to each one for autoloading
447      *
448      * @var array
449      */
450     private static $_loadedModels = array();
451
452     /**
453      * _validators
454      *
455      * Array of all the loaded validators
456      * @var array
457      */
458     private static $_validators = array();
459
460     /**
461      * Constructor for the main class
462      *
463      * This class can not be instantiated so it will throw an exception. 
464      *
465      * @return void
466      * @throws Doctrine_Exception
467      */
468     public function __construct()
469     {
470         throw new Doctrine_Exception('Doctrine is static class. No instances can be created.');
471     }
472
473     /**
474      * debug
475      *
476      * @param string $bool
477      * @return void
478      */
479     public static function debug($bool = null)
480     {
481         if ($bool !== null) {
482             self::$_debug = (bool) $bool;
483         }
484
485         return self::$_debug;
486     }
487
488     /**
489      * getPath
490      * returns the doctrine root
491      *
492      * @return string
493      */
494     public static function getPath()
495     {
496         if ( ! self::$_path) {
497             self::$_path = dirname(__FILE__);
498         }
499
500         return self::$_path;
501     }
502
503     /**
504      * loadModels
505      *
506      * Recursively load all models from a directory or array of directories
507      *
508      * @param string $directory    Path to directory of models or array of directory paths
509      * @return array $loadedModels
510      */
511     public static function loadModels($directory)
512     {
513         if ($directory !== null) {
514             $manager = Doctrine_Manager::getInstance();
515
516             foreach ((array) $directory as $dir) {
517                 $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir),
518                                                         RecursiveIteratorIterator::LEAVES_ONLY);
519                 foreach ($it as $file) {
520                     $e = explode('.', $file->getFileName());
521                     if (end($e) === 'php' && strpos($file->getFileName(), '.inc') === false) {
522                         self::$_loadedModels[$e[0]] = $file->getPathName();
523                     }
524                 }
525             }
526         }
527
528         return self::getLoadedModels(array_keys(self::$_loadedModels));
529     }
530
531     /**
532      * getLoadedModels
533      *
534      * Get all the loaded models, you can provide an array of classes or it will use get_declared_classes()
535      *
536      * Will filter through an array of classes and return the Doctrine_Records out of them.
537      * If you do not specify $classes it will return all of the currently loaded Doctrine_Records
538      *
539      * @param classes  Array of classes to filter through, otherwise uses get_declared_classes()
540      * @return array   $loadedModels
541      */
542     public static function getLoadedModels($classes = null)
543     {
544         if ($classes === null) {
545             $classes = get_declared_classes();
546             $classes = array_merge($classes, array_keys(self::$_loadedModels));
547         }
548
549         $loadedModels = array();
550
551         foreach ((array) $classes as $name) {
552             try {
553                 $declaredBefore = get_declared_classes();
554                 $class = new ReflectionClass($name);
555                 if (self::isValidModelClass($class)) {
556                     $loadedModels[] = $name;
557                 }
558             } catch (Exception $e) {
559                 // Determine class names by the actual inclusion of the model file
560                 // The possibility exists that the class name(s) contained in the model
561                 // file is not the same as the actual model file name itself
562                 if (isset(self::$_loadedModels[$name])) {
563                     try {
564                         require_once self::$_loadedModels[$name];
565                         $declaredAfter = get_declared_classes();
566                         // Using array_slice since array_diff is broken is some versions
567                         $foundClasses = array_slice($declaredAfter, count($declaredBefore)-1);
568                         if ($foundClasses) {
569                             foreach ($foundClasses as $name) {
570                                 $class = new ReflectionClass($name);
571                                 if (self::isValidModelClass($class)) {
572                                     $loadedModels[] = $name;
573                                 }
574                             }
575                         }
576                     } catch (Exception $e) {
577                         continue;
578                     }
579                 }
580             }
581
582         }
583         return $loadedModels;
584     }
585
586
587     /**
588      * isValidModelClass
589      *
590      * Checks whether a reflection class is a valid Doctrine model class
591      *
592      * @param class  A reflection class to validate
593      * @return boolean
594      */
595     public static function isValidModelClass($class)
596     {
597         if ($class instanceof ReflectionClass) {
598             // Skip the following classes
599             // - abstract classes
600             // - not a subclass of Doctrine_Record
601             // - don't have a setTableDefinition method
602             if (!$class->isAbstract() &&
603                 $class->isSubClassOf('Doctrine_Record') &&
604                 $class->hasMethod('setTableDefinition')) {
605                 return true;
606             }
607         }
608         return false;
609     }
610
611
612     /**
613      * getConnectionByTableName
614      *
615      * Get the connection object for a table by the actual table name
616      *
617      * @param string $tableName
618      * @return object Doctrine_Connection
619      */
620     public static function getConnectionByTableName($tableName)
621     {
622         $loadedModels = self::getLoadedModels();
623
624         foreach ($loadedModels as $name) {
625             $model = new $name();
626             $table = $model->getTable();
627
628             if ($table->getTableName() == $tableName) {
629                return $table->getConnection();
630             }
631         }
632
633         return Doctrine_Manager::connection();
634     }
635
636     /**
637      * generateModelsFromDb
638      *
639      * method for importing existing schema to Doctrine_Record classes
640      *
641      * @param string $directory Directory to write your models to
642      * @param array $databases Array of databases to generate models for
643      * @return boolean
644      * @throws Exception
645      */
646     public static function generateModelsFromDb($directory, array $databases = array())
647     {
648         return Doctrine_Manager::connection()->import->importSchema($directory, $databases);
649     }
650
651     /**
652      * generateYamlFromDb
653      *
654      * Generates models from database to temporary location then uses those models to generate a yaml schema file.
655      * This should probably be fixed. We should write something to generate a yaml schema file directly from the database.
656      *
657      * @param string $yamlPath Path to write oyur yaml schema file to
658      * @return void
659      */
660     public static function generateYamlFromDb($yamlPath)
661     {
662         $directory = '/tmp/tmp_doctrine_models';
663
664         Doctrine::generateModelsFromDb($directory);
665
666         $export = new Doctrine_Export_Schema();
667
668         $result = $export->exportSchema($yamlPath, 'yml', $directory);
669
670         exec('rm -rf ' . $directory);
671
672         return $result;
673     }
674
675     /**
676      * generateModelsFromYaml
677      *
678      * Generate a yaml schema file from an existing directory of models
679      *
680      * @param string $yamlPath Path to your yaml schema files
681      * @param string $directory Directory to generate your models in
682      * @param array  $options Array of options to pass to the schema importer
683      * @return void
684      */
685     public static function generateModelsFromYaml($yamlPath, $directory, $options = array())
686     {
687         $import = new Doctrine_Import_Schema();
688         $import->setOptions($options);
689
690         return $import->importSchema($yamlPath, 'yml', $directory);
691     }
692
693     /**
694      * createTablesFromModels
695      *
696      * Creates database tables for the models in the specified directory
697      *
698      * @param string $directory Directory containing your models
699      * @return void
700      */
701     public static function createTablesFromModels($directory = null)
702     {
703         return Doctrine_Manager::connection()->export->exportSchema($directory);
704     }
705
706     /**
707      * createTablesFromArray
708      *
709      * Creates database tables for the models in the supplied array
710      *
711      * @param array $array An array of models to be exported
712      * @return void
713      */
714     public static function createTablesFromArray($array)
715     {
716         return Doctrine_Manager::connection()->export->exportClasses($array);
717     }
718
719     /**
720      * generateSqlFromModels
721      *
722      * @param string $directory
723      * @return string $build  String of sql queries. One query per line
724      */
725     public static function generateSqlFromModels($directory = null)
726     {
727         $sql = Doctrine_Manager::connection()->export->exportSql($directory);
728
729         $build = '';
730         foreach ($sql as $query) {
731             $build .= $query.";\n";
732         }
733
734         return $build;
735     }
736
737     /**
738      * generateYamlFromModels
739      *
740      * Generate yaml schema file for the models in the specified directory
741      *
742      * @param string $yamlPath Path to your yaml schema files
743      * @param string $directory Directory to generate your models in
744      * @return void
745      */
746     public static function generateYamlFromModels($yamlPath, $directory)
747     {
748         $export = new Doctrine_Export_Schema();
749
750         return $export->exportSchema($yamlPath, 'yml', $directory);
751     }
752
753     /**
754      * createDatabases
755      *
756      * Creates databases for connections
757      *
758      * @param string $specifiedConnections Array of connections you wish to create the database for
759      * @return void
760      */
761     public static function createDatabases($specifiedConnections = array())
762     {
763         if ( ! is_array($specifiedConnections)) {
764             $specifiedConnections = (array) $specifiedConnections;
765         }
766
767         $manager = Doctrine_Manager::getInstance();
768         $connections = $manager->getConnections();
769
770         $results = array();
771
772         foreach ($connections as $name => $connection) {
773             if ( ! empty($specifiedConnections) && !in_array($name, $specifiedConnections)) {
774                 continue;
775             }
776
777             $info = $manager->parsePdoDsn($connection->getOption('dsn'));
778             $username = $connection->getOption('username');
779             $password = $connection->getOption('password');
780
781             // Make connection without database specified so we can create it
782             $connect = $manager->openConnection(new PDO($info['scheme'] . ':host=' . $info['host'], $username, $password), 'tmp_connection', false);
783
784             try {
785                 // Create database
786                 $connect->export->createDatabase($name);
787
788                 // Close the tmp connection with no database
789                 $manager->closeConnection($connect);
790
791                 // Close original connection
792                 $manager->closeConnection($connection);
793
794                 // Reopen original connection with newly created database
795                 $manager->openConnection(new PDO($info['dsn'], $username, $password), $name, true);
796
797                 $results[$name] = true;
798             } catch (Exception $e) {
799                 $results[$name] = false;
800             }
801         }
802
803         return $results;
804     }
805
806     /**
807      * dropDatabases
808      *
809      * Drops databases for connections
810      *
811      * @param string $specifiedConnections Array of connections you wish to drop the database for
812      * @return void
813      */
814     public static function dropDatabases($specifiedConnections = array())
815     {
816         if ( ! is_array($specifiedConnections)) {
817             $specifiedConnections = (array) $specifiedConnections;
818         }
819
820         $manager = Doctrine_Manager::getInstance();
821
822         $connections = $manager->getConnections();
823
824         $results = array();
825
826         foreach ($connections as $name => $connection) {
827             if ( ! empty($specifiedConnections) && !in_array($name, $specifiedConnections)) {
828                 continue;
829             }
830
831             try {
832                 $connection->export->dropDatabase($name);
833
834                 $results[$name] = true;
835             } catch (Exception $e) {
836                 $results[$name] = false;
837             }
838         }
839
840         return $results;
841     }
842
843     /**
844      * dumpData
845      *
846      * Dump data to a yaml fixtures file
847      *
848      * @param string $yamlPath Path to write the yaml data fixtures to
849      * @param string $individualFiles Whether or not to dump data to individual fixtures files
850      * @return void
851      */
852     public static function dumpData($yamlPath, $individualFiles = false)
853     {
854         $data = new Doctrine_Data();
855
856         return $data->exportData($yamlPath, 'yml', array(), $individualFiles);
857     }
858
859     /**
860      * loadData
861      *
862      * Load data from a yaml fixtures file.
863      * The output of dumpData can be fed to loadData
864      *
865      * @param string $yamlPath Path to your yaml data fixtures
866      * @param string $append Whether or not to append the data
867      * @return void
868      */
869     public static function loadData($yamlPath, $append = false)
870     {
871         $data = new Doctrine_Data();
872
873         if ( ! $append) {
874             $data->purge();
875         }
876
877         return $data->importData($yamlPath, 'yml');
878     }
879
880     /**
881      * migrate
882      *
883      * Migrate database to specified $to version. Migrates from current to latest if you do not specify.
884      *
885      * @param string $migrationsPath Path to migrations directory which contains your migration classes
886      * @param string $to Version you wish to migrate to.
887      * @return bool true
888      * @throws new Doctrine_Migration_Exception
889      */
890     public static function migrate($migrationsPath, $to = null)
891     {
892         $migration = new Doctrine_Migration($migrationsPath);
893
894         return $migration->migrate($to);
895     }
896
897     /**
898      * generateMigrationClass
899      *
900      * Generate new migration class skeleton
901      *
902      * @param string $className Name of the Migration class to generate
903      * @param string $migrationsPath Path to directory which contains your migration classes
904      */
905     public static function generateMigrationClass($className, $migrationsPath)
906     {
907         $builder = new Doctrine_Migration_Builder($migrationsPath);
908
909         return $builder->generateMigrationClass($className);
910     }
911
912     /**
913      * generateMigrationsFromDb
914      *
915      * @param string $migrationsPath
916      * @return void
917      * @throws new Doctrine_Migration_Exception
918      */
919     public static function generateMigrationsFromDb($migrationsPath)
920     {
921         $builder = new Doctrine_Migration_Builder($migrationsPath);
922
923         return $builder->generateMigrationsFromDb();
924     }
925
926     /**
927      * generateMigrationsFromModels
928      *
929      * @param string $migrationsPath
930      * @param string $modelsPath
931      * @return void
932      */
933     public static function generateMigrationsFromModels($migrationsPath, $modelsPath = null)
934     {
935         $builder = new Doctrine_Migration_Builder($migrationsPath);
936
937         return $builder->generateMigrationsFromModels($modelsPath);
938     }
939
940     /**
941      * getTable
942      *
943      * @param string $tableName
944      * @return void
945      */
946     public static function getTable($tableName)
947     {
948         return Doctrine_Manager::table($tableName);
949     }
950
951     /**
952      * fileFinder
953      *
954      * @param string $type
955      * @return void
956      */
957     public static function fileFinder($type)
958     {
959         return Doctrine_FileFinder::type($type);
960     }
961
962     /**
963      * compile
964      *
965      * method for making a single file of most used doctrine runtime components
966      * including the compiled file instead of multiple files (in worst
967      * cases dozens of files) can improve performance by an order of magnitude
968      *
969      * @param string $target
970      * @param array  $includedDrivers
971      * @throws Doctrine_Exception
972      * @return void
973      */
974     public static function compile($target = null, $includedDrivers = array())
975     {
976         return Doctrine_Compiler::compile($target, $includedDrivers);
977     }
978
979     /**
980      * autoload
981      *
982      * simple autoload function
983      * returns true if the class was loaded, otherwise false
984      *
985      * @param string $classname
986      * @return boolean
987      */
988     public static function autoload($className)
989     {
990         if (class_exists($className, false)) {
991             return false;
992         }
993
994         if ( ! self::$_path) {
995             self::$_path = dirname(__FILE__);
996         }
997
998         $class = self::$_path . DIRECTORY_SEPARATOR . str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
999
1000         if (file_exists($class)) {
1001             require_once($class);
1002
1003             return true;
1004         }
1005
1006         $loadedModels = self::$_loadedModels;
1007
1008         if (isset($loadedModels[$className]) && file_exists($loadedModels[$className])) {
1009             require_once($loadedModels[$className]);
1010
1011             return true;
1012         }
1013
1014         return false;
1015     }
1016
1017     /**
1018      * dump
1019      *
1020      * dumps a given variable
1021      *
1022      * @param mixed $var        a variable of any type
1023      * @param boolean $output   whether to output the content
1024      * @param string $indent    indention string
1025      * @return void|string
1026      */
1027     public static function dump($var, $output = true, $indent = "")
1028     {
1029         $ret = array();
1030         switch (gettype($var)) {
1031             case 'array':
1032                 $ret[] = 'Array(';
1033                 $indent .= "    ";
1034                 foreach ($var as $k => $v) {
1035
1036                     $ret[] = $indent . $k . ' : ' . self::dump($v, false, $indent);
1037                 }
1038                 $indent = substr($indent,0, -4);
1039                 $ret[] = $indent . ")";
1040                 break;
1041             case 'object':
1042                 $ret[] = 'Object(' . get_class($var) . ')';
1043                 break;
1044             default:
1045                 $ret[] = var_export($var, true);
1046         }
1047         if ($output) {
1048             print implode("\n", $ret);
1049         }
1050         return implode("\n", $ret);
1051     }
1052
1053     /**
1054      * tableize
1055      *
1056      * returns table name from class name
1057      *
1058      * @param string $classname
1059      * @return string
1060      */
1061     public static function tableize($classname)
1062     {
1063          return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $classname));
1064     }
1065
1066     /**
1067      * classify
1068      *
1069      * returns class name from table name
1070      *
1071      * @param string $tablename
1072      * @return string
1073      */
1074     public static function classify($tablename)
1075     {
1076         return preg_replace_callback('~(_?)(_)([\w])~', array("Doctrine", "classifyCallback"), ucfirst($tablename));
1077     }
1078
1079     /**
1080      * classifyCallback
1081      *
1082      * Callback function to classify a classname properly.
1083      *
1084      * @param array $matches An array of matches from a pcre_replace call
1085      * @return string A string with matches 1 and mathces 3 in upper case.
1086      */
1087     public static function classifyCallback($matches)
1088     {
1089         return $matches[1] . strtoupper($matches[3]);
1090     }
1091
1092     /**
1093      * isValidClassName
1094      *
1095      * checks for valid class name (uses camel case and underscores)
1096      *
1097      * @param string $classname
1098      * @return boolean
1099      */
1100     public static function isValidClassname($classname)
1101     {
1102         if (preg_match('~(^[a-z])|(_[a-z])|([\W])|(_{2})~', $classname)) {
1103             return false;
1104         }
1105
1106         return true;
1107     }
1108
1109     /**
1110      * makeDirectories
1111      *
1112      * Makes the directories for a path recursively
1113      *
1114      * @param string $path
1115      * @return void
1116      */
1117     public static function makeDirectories($path, $mode = 0777)
1118     {
1119         if (!$path) {
1120           return false;
1121         }
1122
1123         if (is_dir($path) || is_file($path)) {
1124           return true;
1125         }
1126
1127         return mkdir($path, $mode, true);
1128     }
1129
1130     /**
1131      * removeDirectories
1132      *
1133      * @param string $folderPath
1134      * @return void
1135      */
1136     public static function removeDirectories($folderPath)
1137     {
1138         if ( ! is_dir($folderPath))
1139         {
1140             return false;
1141         }
1142
1143         foreach (scandir($folderPath) as $value)
1144         {
1145             if ($value != '.' && $value != '..')
1146             {
1147                 $value = $folderPath . "/" . $value;
1148
1149                 if (is_dir($value)) {
1150                     self::removeDirectories($value);
1151                 } else if (is_file($value)) {
1152                     @unlink($value);
1153                 }
1154             }
1155         }
1156
1157         return rmdir ( $folderPath );
1158     }    
1159
1160     /**
1161      * getValidators
1162      *
1163      * Get available doctrine validators
1164      *
1165      * @return array $validators
1166      */
1167     public static function getValidators()
1168     {
1169         if (empty(self::$_validators)) {
1170             $dir = Doctrine::getPath() . DIRECTORY_SEPARATOR . 'Doctrine' . DIRECTORY_SEPARATOR . 'Validator';
1171
1172             $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::LEAVES_ONLY);
1173             foreach ($files as $file) {
1174                 $e = explode('.', $file->getFileName());
1175
1176                 if (end($e) == 'php') {
1177                     $name = strtolower($e[0]);
1178
1179                     self::$_validators[$name] = $name;
1180                 }
1181             }
1182         }
1183
1184         return self::$_validators;
1185     }
1186 }