Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

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