Coverage for Doctrine

Back to coverage report

1 <?php
2 /*
3  *  $Id: Doctrine.php 4094 2008-03-23 00:05:14Z jwage $
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.org>.
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.org
31  * @since       1.0
32  * @version     $Revision: 4094 $
33  */
34 final class Doctrine
35 {
36     /**
37      * VERSION
38      */
39     const VERSION                   = '0.10.3';
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     const ATTR_AUTOLOAD_TABLE_CLASSES   = 160;
195     const ATTR_MODEL_LOADING            = 161;
196
197     /**
198      * LIMIT CONSTANTS
199      */
200
201     /**
202      * constant for row limiting
203      */
204     const LIMIT_ROWS       = 1;
205
206     /**
207      * constant for record limiting
208      */
209     const LIMIT_RECORDS    = 2;
210
211     /**
212      * FETCHMODE CONSTANTS
213      */
214
215     /**
216      * IMMEDIATE FETCHING
217      * mode for immediate fetching
218      */
219     const FETCH_IMMEDIATE       = 0;
220
221     /**
222      * BATCH FETCHING
223      * mode for batch fetching
224      */
225     const FETCH_BATCH           = 1;
226
227     /**
228      * LAZY FETCHING
229      * mode for offset fetching
230      */
231     const FETCH_OFFSET          = 3;
232
233     /**
234      * LAZY OFFSET FETCHING
235      * mode for lazy offset fetching
236      */
237     const FETCH_LAZY_OFFSET     = 4;
238
239     /**
240      * FETCH CONSTANTS
241      */
242
243
244     /**
245      * FETCH VALUEHOLDER
246      */
247     const FETCH_VHOLDER         = 1;
248
249     /**
250      * FETCH RECORD
251      *
252      * Specifies that the fetch method shall return Doctrine_Record
253      * objects as the elements of the result set.
254      *
255      * This is the default fetchmode.
256      */
257     const FETCH_RECORD          = 2;
258
259     /**
260      * FETCH ARRAY
261      */
262     const FETCH_ARRAY           = 3;
263
264     /**
265      * PORTABILITY CONSTANTS
266      */
267
268     /**
269      * Portability: turn off all portability features.
270      * @see self::ATTR_PORTABILITY
271      */
272     const PORTABILITY_NONE          = 0;
273
274     /**
275      * Portability: convert names of tables and fields to case defined in the
276      * "field_case" option when using the query*(), fetch*() methods.
277      * @see self::ATTR_PORTABILITY
278      */
279     const PORTABILITY_FIX_CASE      = 1;
280
281     /**
282      * Portability: right trim the data output by query*() and fetch*().
283      * @see self::ATTR_PORTABILITY
284      */
285     const PORTABILITY_RTRIM         = 2;
286
287     /**
288      * Portability: force reporting the number of rows deleted.
289      * @see self::ATTR_PORTABILITY
290      */
291     const PORTABILITY_DELETE_COUNT  = 4;
292
293     /**
294      * Portability: convert empty values to null strings in data output by
295      * query*() and fetch*().
296      * @see self::ATTR_PORTABILITY
297      */
298     const PORTABILITY_EMPTY_TO_NULL = 8;
299
300     /**
301      * Portability: removes database/table qualifiers from associative indexes
302      * @see self::ATTR_PORTABILITY
303      */
304     const PORTABILITY_FIX_ASSOC_FIELD_NAMES = 16;
305
306     /**
307      * Portability: makes Doctrine_Expression throw exception for unportable RDBMS expressions
308      * @see self::ATTR_PORTABILITY
309      */
310     const PORTABILITY_EXPR          = 32;
311
312     /**
313      * Portability: turn on all portability features.
314      * @see self::ATTR_PORTABILITY
315      */
316     const PORTABILITY_ALL           = 63;
317
318     /**
319      * LOCKMODE CONSTANTS
320      */
321
322     /**
323      * mode for optimistic locking
324      */
325     const LOCK_OPTIMISTIC       = 0;
326
327     /**
328      * mode for pessimistic locking
329      */
330     const LOCK_PESSIMISTIC      = 1;
331
332     /**
333      * EXPORT CONSTANTS
334      */
335
336     /**
337      * EXPORT_NONE
338      */
339     const EXPORT_NONE               = 0;
340
341     /**
342      * EXPORT_TABLES
343      */
344     const EXPORT_TABLES             = 1;
345
346     /**
347      * EXPORT_CONSTRAINTS
348      */
349     const EXPORT_CONSTRAINTS        = 2;
350
351     /**
352      * EXPORT_PLUGINS
353      */
354     const EXPORT_PLUGINS            = 4;
355
356     /**
357      * EXPORT_ALL
358      */
359     const EXPORT_ALL                = 7;
360
361     /**
362      * HYDRATION CONSTANTS
363      */
364     const HYDRATE_RECORD            = 2;
365
366     /**
367      * HYDRATE_ARRAY
368      */
369     const HYDRATE_ARRAY             = 3;
370
371     /**
372      * HYDRATE_NONE
373      */
374     const HYDRATE_NONE              = 4;
375
376     /**
377      * VALIDATION CONSTANTS
378      */
379     const VALIDATE_NONE             = 0;
380
381     /**
382      * VALIDATE_LENGTHS
383      */
384     const VALIDATE_LENGTHS          = 1;
385
386     /**
387      * VALIDATE_TYPES
388      */
389     const VALIDATE_TYPES            = 2;
390
391     /**
392      * VALIDATE_CONSTRAINTS
393      */
394     const VALIDATE_CONSTRAINTS      = 4;
395
396     /**
397      * VALIDATE_ALL
398      */
399     const VALIDATE_ALL              = 7;
400
401     /**
402      * IDENTIFIER_AUTOINC
403      *
404      * constant for auto_increment identifier
405      */
406     const IDENTIFIER_AUTOINC        = 1;
407
408     /**
409      * IDENTIFIER_SEQUENCE
410      *
411      * constant for sequence identifier
412      */
413     const IDENTIFIER_SEQUENCE       = 2;
414
415     /**
416      * IDENTIFIER_NATURAL
417      *
418      * constant for normal identifier
419      */
420     const IDENTIFIER_NATURAL        = 3;
421
422     /**
423      * IDENTIFIER_COMPOSITE
424      *
425      * constant for composite identifier
426      */
427     const IDENTIFIER_COMPOSITE      = 4;
428
429     /**
430      * MODEL_LOADING_AGGRESSIVE
431      *
432      * Constant for agressive model loading
433      * Will require_once() all found model files
434      */
435     const MODEL_LOADING_AGGRESSIVE   = 1;
436
437     /**
438      * MODEL_LOADING_CONSERVATIVE
439      *
440      * Constant for conservative model loading
441      * Will not require_once() found model files inititally instead it will build an array
442      * and reference it in autoload() when a class is needed it will require_once() it
443      */
444     const MODEL_LOADING_CONSERVATIVE= 2;
445     
446     /**
447      * Path
448      *
449      * @var string $path            doctrine root directory
450      */
451     private static $_path;
452
453     /**
454      * Debug
455      *
456      * Bool true/false
457      *
458      * @var boolean $_debug
459      */
460     private static $_debug = false;
461
462     /**
463      * _loadedModelFiles
464      *
465      * Array of all the loaded models and the path to each one for autoloading
466      *
467      * @var array
468      */
469     private static $_loadedModelFiles = array();
470
471     /**
472      * _validators
473      *
474      * Array of all the loaded validators
475      * @var array
476      */
477     private static $_validators = array();
478
479     /**
480      * __construct
481      *
482      * @return void
483      * @throws Doctrine_Exception
484      */
485     public function __construct()
486     {
487         throw new Doctrine_Exception('Doctrine is static class. No instances can be created.');
488     }
489
490     /**
491      * getLoadedModelFiles
492      *
493      * Returns an array of all the loaded models and the path where each of them exists
494      *
495      * @return array
496      */
497     public static function getLoadedModelFiles()
498     {
499         return self::$_loadedModelFiles;
500     }
501
502     /**
503      * debug
504      *
505      * @param string $bool
506      * @return void
507      */
508     public static function debug($bool = null)
509     {
510         if ($bool !== null) {
511             self::$_debug = (bool) $bool;
512         }
513
514         return self::$_debug;
515     }
516
517     /**
518      * getPath
519      * returns the doctrine root
520      *
521      * @return string
522      */
523     public static function getPath()
524     {
525         if ( ! self::$_path) {
526             self::$_path = dirname(__FILE__);
527         }
528
529         return self::$_path;
530     }
531
532     /**
533      * loadModel
534      *
535      * @package default
536      */
537     public static function loadModel($className, $path = null)
538     {
539         self::$_loadedModelFiles[$className] = $path;
540     }
541
542     /**
543      * loadModels
544      *
545      * Recursively load all models from a directory or array of directories
546      *
547      * @param  string   $directory      Path to directory of models or array of directory paths
548      * @param  integer  $modelLoading   Pass value of Doctrine::ATTR_MODEL_LOADING to force a certain style of model loading
549      *                                  Allowed Doctrine::MODEL_LOADING_AGGRESSIVE(default) or Doctrine::MODEL_LOADING_CONSERVATIVE
550      */
551     public static function loadModels($directory, $modelLoading = null)
552     {
553         $manager = Doctrine_Manager::getInstance();
554
555         $modelLoading = $modelLoading === null ? $manager->getAttribute(Doctrine::ATTR_MODEL_LOADING):$modelLoading;
556
557         $loadedModels = array();
558
559         if ($directory !== null && is_dir($directory)) {
560             foreach ((array) $directory as $dir) {
561                 $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir),
562                                                         RecursiveIteratorIterator::LEAVES_ONLY);
563                 foreach ($it as $file) {
564                     $e = explode('.', $file->getFileName());
565                     if (end($e) === 'php' && strpos($file->getFileName(), '.inc') === false) {
566                         $className = $e[0];
567
568                         if ($modelLoading == Doctrine::MODEL_LOADING_CONSERVATIVE) {
569                             self::loadModel($className, $file->getPathName());
570
571                             $loadedModels[$className] = $className;
572                         } else {
573                             $declaredBefore = get_declared_classes();
574                             require_once($file->getPathName());
575
576                             $declaredAfter = get_declared_classes();
577                             // Using array_slice because array_diff is broken is some PHP versions
578                             $foundClasses = array_slice($declaredAfter, count($declaredBefore) - 1);
579                             if ($foundClasses) {
580                                 foreach ($foundClasses as $className) {
581                                     if (self::isValidModelClass($className)) {
582                                         $loadedModels[$className] = $className;
583
584                                         self::loadModel($className, $file->getPathName());
585                                     }
586                                 }
587                             }
588                         }
589                     }
590                 }
591             }
592         } else {
593           throw new Doctrine_Exception('You must pass a valid path to a directory containing Doctrine models');
594         }
595
596         return $loadedModels;
597     }
598
599     /**
600      * getLoadedModels
601      *
602      * Get all the loaded models, you can provide an array of classes or it will use get_declared_classes()
603      *
604      * Will filter through an array of classes and return the Doctrine_Records out of them.
605      * If you do not specify $classes it will return all of the currently loaded Doctrine_Records
606      *
607      * @param classes  Array of classes to filter through, otherwise uses get_declared_classes()
608      * @return array   $loadedModels
609      */
610     public static function getLoadedModels($classes = null)
611     {
612         if ($classes === null) {
613             $classes = get_declared_classes();
614             $classes = array_merge($classes, array_keys(self::$_loadedModelFiles));
615         }
616
617         return self::filterInvalidModels($classes);
618     }
619
620     /**
621      * initializeModels
622      *
623      * Initialize all models so everything is present and loaded in to memory
624      * This will also inheritently initialize any model behaviors and add 
625      * the models generated by Doctrine generators and add them to the $models
626      * array
627      *
628      * @param string $models 
629      * @return array $models
630      */
631     public static function initializeModels($models)
632     {
633         foreach ($models as $model) {
634             $declaredBefore = get_declared_classes();
635
636             Doctrine::getTable($model);
637
638             $declaredAfter = get_declared_classes();
639             // Using array_slice because array_diff is broken is some PHP versions
640             $foundClasses = array_slice($declaredAfter, count($declaredBefore) - 1);
641             foreach ($foundClasses as $class) {
642                 if (self::isValidModelClass($class)) {
643                     $models[] = $class;
644                 }
645             }
646         }
647
648         return $models;
649     }
650
651     /**
652      * filterInvalidModels
653      *
654      * Filter through an array of classes and return all the classes that are valid models.
655      * This will inflect the class, causing it to be loaded in to memory.
656      *
657      * @param classes  Array of classes to filter through, otherwise uses get_declared_classes()
658      * @return array   $loadedModels
659      */
660     public static function filterInvalidModels($classes)
661     {
662         $validModels = array();
663
664         foreach ((array) $classes as $name) {
665             if (self::isValidModelClass($name) && ! in_array($name, $validModels)) {
666                 $validModels[] = $name;
667             }
668         }
669
670         return $validModels;
671     }
672
673     /**
674      * isValidModelClass
675      *
676      * Checks if what is passed is a valid Doctrine_Record
677      * Will load class in to memory in order to inflect it and find out information about the class
678      *
679      * @param   mixed   $class Can be a string named after the class, an instance of the class, or an instance of the class reflected
680      * @return  boolean
681      */
682     public static function isValidModelClass($class)
683     {
684         if ($class instanceof Doctrine_Record) {
685             $class = get_class($class);
686         }
687
688         if (is_string($class) && class_exists($class)) {
689             $class = new ReflectionClass($class);
690         }
691
692         if ($class instanceof ReflectionClass) {
693             // Skip the following classes
694             // - abstract classes
695             // - not a subclass of Doctrine_Record
696             if ( ! $class->isAbstract() && $class->isSubClassOf('Doctrine_Record')) {
697
698                 return true;
699             }
700         }
701
702         return false;
703     }
704
705     /**
706      * getConnectionByTableName
707      *
708      * Get the connection object for a table by the actual table name
709      *
710      * @param string $tableName
711      * @return object Doctrine_Connection
712      */
713     public static function getConnectionByTableName($tableName)
714     {
715         $loadedModels = self::getLoadedModels();
716
717         foreach ($loadedModels as $name) {
718             $table = Doctrine::getTable($name);
719
720             if ($table->getTableName() == $tableName) {
721                return $table->getConnection();
722             }
723         }
724
725         return Doctrine_Manager::connection();
726     }
727
728     /**
729      * generateModelsFromDb
730      *
731      * method for importing existing schema to Doctrine_Record classes
732      *
733      * @param string $directory Directory to write your models to
734      * @param array $databases Array of databases to generate models for
735      * @param array $options Array of options
736      * @return boolean
737      * @throws Exception
738      */
739     public static function generateModelsFromDb($directory, array $databases = array(), array $options = array())
740     {
741         return Doctrine_Manager::connection()->import->importSchema($directory, $databases, $options);
742     }
743
744     /**
745      * generateYamlFromDb
746      *
747      * Generates models from database to temporary location then uses those models to generate a yaml schema file.
748      * This should probably be fixed. We should write something to generate a yaml schema file directly from the database.
749      *
750      * @param string $yamlPath Path to write oyur yaml schema file to
751      * @param array  $options Array of options
752      * @return void
753      */
754     public static function generateYamlFromDb($yamlPath, array $databases = array(), array $options = array())
755     {
756         $directory = '/tmp/tmp_doctrine_models';
757
758         $options['generateBaseClasses'] = isset($options['generateBaseClasses']) ? $options['generateBaseClasses']:false;
759         $result = Doctrine::generateModelsFromDb($directory, $databases, $options);
760
761         if ( empty($result) && ! is_dir($directory)) {
762             throw new Doctrine_Exception('No models generated from your databases');
763         }
764
765         $export = new Doctrine_Export_Schema();
766
767         $result = $export->exportSchema($yamlPath, 'yml', $directory);
768
769         Doctrine_Lib::removeDirectories($directory);
770
771         return $result;
772     }
773
774     /**
775      * generateModelsFromYaml
776      *
777      * Generate a yaml schema file from an existing directory of models
778      *
779      * @param string $yamlPath Path to your yaml schema files
780      * @param string $directory Directory to generate your models in
781      * @param array  $options Array of options to pass to the schema importer
782      * @return void
783      */
784     public static function generateModelsFromYaml($yamlPath, $directory, $options = array())
785     {
786         $import = new Doctrine_Import_Schema();
787         $import->setOptions($options);
788
789         return $import->importSchema($yamlPath, 'yml', $directory);
790     }
791
792     /**
793      * createTablesFromModels
794      *
795      * Creates database tables for the models in the specified directory
796      *
797      * @param string $directory Directory containing your models
798      * @return void
799      */
800     public static function createTablesFromModels($directory = null)
801     {
802         return Doctrine_Manager::connection()->export->exportSchema($directory);
803     }
804
805     /**
806      * createTablesFromArray
807      *
808      * Creates database tables for the models in the supplied array
809      *
810      * @param array $array An array of models to be exported
811      * @return void
812      */
813     public static function createTablesFromArray($array)
814     {
815         return Doctrine_Manager::connection()->export->exportClasses($array);
816     }
817
818     /**
819      * generateSqlFromArray
820      *
821      * @param string $array 
822      * @return void
823      */
824     public static function generateSqlFromArray($array)
825     {
826         return Doctrine_Manager::connection()->export->exportClassesSql($array);
827     }
828
829     /**
830      * generateSqlFromModels
831      *
832      * @param string $directory
833      * @return string $build  String of sql queries. One query per line
834      */
835     public static function generateSqlFromModels($directory = null)
836     {
837         $sql = Doctrine_Manager::connection()->export->exportSql($directory);
838
839         $build = '';
840         foreach ($sql as $query) {
841             $build .= $query.";\n";
842         }
843
844         return $build;
845     }
846
847     /**
848      * generateYamlFromModels
849      *
850      * Generate yaml schema file for the models in the specified directory
851      *
852      * @param string $yamlPath Path to your yaml schema files
853      * @param string $directory Directory to generate your models in
854      * @return void
855      */
856     public static function generateYamlFromModels($yamlPath, $directory)
857     {
858         $export = new Doctrine_Export_Schema();
859
860         return $export->exportSchema($yamlPath, 'yml', $directory);
861     }
862
863     /**
864      * createDatabases
865      *
866      * Creates databases for connections
867      *
868      * @param string $specifiedConnections Array of connections you wish to create the database for
869      * @return void
870      */
871     public static function createDatabases($specifiedConnections = array())
872     {
873         return Doctrine_Manager::getInstance()->createDatabases($specifiedConnections);
874     }
875
876     /**
877      * dropDatabases
878      *
879      * Drops databases for connections
880      *
881      * @param string $specifiedConnections Array of connections you wish to drop the database for
882      * @return void
883      */
884     public static function dropDatabases($specifiedConnections = array())
885     {
886         return Doctrine_Manager::getInstance()->dropDatabases($specifiedConnections);
887     }
888
889     /**
890      * dumpData
891      *
892      * Dump data to a yaml fixtures file
893      *
894      * @param string $yamlPath Path to write the yaml data fixtures to
895      * @param string $individualFiles Whether or not to dump data to individual fixtures files
896      * @return void
897      */
898     public static function dumpData($yamlPath, $individualFiles = false)
899     {
900         $data = new Doctrine_Data();
901
902         return $data->exportData($yamlPath, 'yml', array(), $individualFiles);
903     }
904
905     /**
906      * loadData
907      *
908      * Load data from a yaml fixtures file.
909      * The output of dumpData can be fed to loadData
910      *
911      * @param string $yamlPath Path to your yaml data fixtures
912      * @param string $append Whether or not to append the data
913      * @return void
914      */
915     public static function loadData($yamlPath, $append = false)
916     {
917         $data = new Doctrine_Data();
918
919         if ( ! $append) {
920             $data->purge();
921         }
922
923         return $data->importData($yamlPath, 'yml');
924     }
925
926     /**
927      * migrate
928      *
929      * Migrate database to specified $to version. Migrates from current to latest if you do not specify.
930      *
931      * @param string $migrationsPath Path to migrations directory which contains your migration classes
932      * @param string $to Version you wish to migrate to.
933      * @return bool true
934      * @throws new Doctrine_Migration_Exception
935      */
936     public static function migrate($migrationsPath, $to = null)
937     {
938         $migration = new Doctrine_Migration($migrationsPath);
939
940         return $migration->migrate($to);
941     }
942
943     /**
944      * generateMigrationClass
945      *
946      * Generate new migration class skeleton
947      *
948      * @param string $className Name of the Migration class to generate
949      * @param string $migrationsPath Path to directory which contains your migration classes
950      */
951     public static function generateMigrationClass($className, $migrationsPath)
952     {
953         $builder = new Doctrine_Migration_Builder($migrationsPath);
954
955         return $builder->generateMigrationClass($className);
956     }
957
958     /**
959      * generateMigrationsFromDb
960      *
961      * @param string $migrationsPath
962      * @return void
963      * @throws new Doctrine_Migration_Exception
964      */
965     public static function generateMigrationsFromDb($migrationsPath)
966     {
967         $builder = new Doctrine_Migration_Builder($migrationsPath);
968
969         return $builder->generateMigrationsFromDb();
970     }
971
972     /**
973      * generateMigrationsFromModels
974      *
975      * @param string  $migrationsPath Path to your Doctrine migration classes
976      * @param string  $modelsPath     Path to your Doctrine model classes
977      * @param integer $modelLoading   Style of model loading to use for loading the models in order to generate migrations
978      * @return void
979      */
980     public static function generateMigrationsFromModels($migrationsPath, $modelsPath = null, $modelLoading = null)
981     {
982         $builder = new Doctrine_Migration_Builder($migrationsPath);
983
984         return $builder->generateMigrationsFromModels($modelsPath, $modelLoading);
985     }
986
987     /**
988      * getTable
989      *
990      * @param string $tableName
991      * @return void
992      */
993     public static function getTable($tableName)
994     {
995         return Doctrine_Manager::table($tableName);
996     }
997
998     /**
999      * fileFinder
1000      *
1001      * @param string $type
1002      * @return void
1003      */
1004     public static function fileFinder($type)
1005     {
1006         return Doctrine_FileFinder::type($type);
1007     }
1008
1009     /**
1010      * compile
1011      *
1012      * method for making a single file of most used doctrine runtime components
1013      * including the compiled file instead of multiple files (in worst
1014      * cases dozens of files) can improve performance by an order of magnitude
1015      *
1016      * @param string $target
1017      * @param array  $includedDrivers
1018      * @throws Doctrine_Exception
1019      * @return void
1020      */
1021     public static function compile($target = null, $includedDrivers = array())
1022     {
1023         return Doctrine_Compiler::compile($target, $includedDrivers);
1024     }
1025
1026     /**
1027      * autoload
1028      *
1029      * simple autoload function
1030      * returns true if the class was loaded, otherwise false
1031      *
1032      * @param string $classname
1033      * @return boolean
1034      */
1035     public static function autoload($className)
1036     {
1037         if (class_exists($className, false) || interface_exists($className, false)) {
1038             return false;
1039         }
1040
1041         $class = self::getPath() . DIRECTORY_SEPARATOR . str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
1042
1043         if (file_exists($class)) {
1044             require $class;
1045
1046             return true;
1047         }
1048
1049         $loadedModels = self::$_loadedModelFiles;
1050
1051         if (isset($loadedModels[$className]) && file_exists($loadedModels[$className])) {
1052             require $loadedModels[$className];
1053
1054             return true;
1055         }
1056
1057         return false;
1058     }
1059
1060     /**
1061      * dump
1062      *
1063      * dumps a given variable
1064      *
1065      * @param mixed $var        a variable of any type
1066      * @param boolean $output   whether to output the content
1067      * @param string $indent    indention string
1068      * @return void|string
1069      */
1070     public static function dump($var, $output = true, $indent = "")
1071     {
1072         $ret = array();
1073         switch (gettype($var)) {
1074             case 'array':
1075                 $ret[] = 'Array(';
1076                 $indent .= "    ";
1077                 foreach ($var as $k => $v) {
1078
1079                     $ret[] = $indent . $k . ' : ' . self::dump($v, false, $indent);
1080                 }
1081                 $indent = substr($indent,0, -4);
1082                 $ret[] = $indent . ")";
1083                 break;
1084             case 'object':
1085                 $ret[] = 'Object(' . get_class($var) . ')';
1086                 break;
1087             default:
1088                 $ret[] = var_export($var, true);
1089         }
1090
1091         if ($output) {
1092             print implode("\n", $ret);
1093         }
1094
1095         return implode("\n", $ret);
1096     }
1097
1098     /**
1099      * tableize
1100      *
1101      * returns table name from class name
1102      *
1103      * @param string $classname
1104      * @return string
1105      */
1106     public static function tableize($className)
1107     {
1108          return Doctrine_Inflector::tableize($className);
1109     }
1110
1111     /**
1112      * classify
1113      *
1114      * returns class name from table name
1115      *
1116      * @param string $tablename
1117      * @return string
1118      */
1119     public static function classify($tableName)
1120     {
1121         return Doctrine_Inflector::classify($tableName);
1122     }
1123
1124     /**
1125      * isValidClassName
1126      *
1127      * checks for valid class name (uses camel case and underscores)
1128      *
1129      * @param string $classname
1130      * @return boolean
1131      */
1132     public static function isValidClassname($className)
1133     {
1134         return Doctrine_Lib::isValidClassName($className);
1135     }
1136
1137     /**
1138      * makeDirectories
1139      *
1140      * Makes the directories for a path recursively
1141      *
1142      * @param string $path
1143      * @return void
1144      */
1145     public static function makeDirectories($path, $mode = 0777)
1146     {
1147         return Doctrine_Lib::makeDirectories($path, $mode);
1148     }
1149
1150     /**
1151      * removeDirectories
1152      *
1153      * @param string $folderPath
1154      * @return void
1155      */
1156     public static function removeDirectories($folderPath)
1157     {
1158         return Doctrine_Lib::removeDirectories($folderPath);
1159     }
1160 }