# 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.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: 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 | }