Coverage for Doctrine_Import_Builder

Back to coverage report

1 <?php
2 /*
3  *  $Id: Builder.php 3024 2007-10-29 12:22:53Z pookey $
4  *
5  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
10  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
11  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
15  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16  *
17  * This software consists of voluntary contributions made by many individuals
18  * and is licensed under the LGPL. For more information, see
19  * <http://www.phpdoctrine.com>.
20  */
21
22 /**
23  * Doctrine_Import_Builder
24  *
25  * Import builder is responsible of building Doctrine_Record classes
26  * based on a database schema.
27  *
28  * @package     Doctrine
29  * @subpackage  Import
30  * @link        www.phpdoctrine.com
31  * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
32  * @since       1.0
33  * @version     $Revision: 3024 $
34  * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
35  * @author      Jukka Hassinen <Jukka.Hassinen@BrainAlliance.com>
36  * @author      Nicolas BĂ©rard-Nault <nicobn@php.net>
37  * @author      Jonathan H. Wage <jwage@mac.com>
38  */
39 class Doctrine_Import_Builder
40 {
41     /**
42      * Path
43      * 
44      * the path where imported files are being generated
45      *
46      * @var string $_path
47      */
48     protected $_path = '';
49     
50     /**
51      * packagesPrefix
52      *
53      * @var string
54      */
55     protected $_packagesPrefix = 'Package';
56
57     /**
58      * packagesPath
59      *
60      * @var string
61      */
62     protected $_packagesPath = '';
63     
64     /**
65      * suffix
66      * 
67      * File suffix to use when writing class definitions
68      *
69      * @var string $suffix
70      */
71     protected $_suffix = '.class.php';
72
73     /**
74      * generateBaseClasses
75      * 
76      * Bool true/false for whether or not to generate base classes
77      *
78      * @var string $suffix
79      */
80     protected $_generateBaseClasses = true;
81     
82     /**
83      * generateTableClasses
84      *
85      * @var string
86      */
87     protected $_generateTableClasses = true;
88     
89     /**
90      * baseClassesDirectory
91      * 
92      * Directory to put the generate base classes in
93      *
94      * @var string $suffix
95      */
96     protected $_baseClassesDirectory = 'generated';
97     
98     /**
99      * baseClassName
100      *
101      * @var string
102      */
103     protected $_baseClassName = 'Doctrine_Record';
104     
105     /**
106      * tpl
107      *
108      * Class template used for writing classes
109      *
110      * @var $_tpl
111      */
112     protected static $_tpl;
113
114     /**
115      * __construct
116      *
117      * @return void
118      */
119     public function __construct()
120     {
121         $this->loadTemplate();
122     }
123
124     /**
125      * setTargetPath
126      *
127      * @param string path   the path where imported files are being generated
128      * @return
129      */
130     public function setTargetPath($path)
131     {
132         Doctrine::makeDirectories($path);
133         
134         if (!$this->_packagesPath) {
135             $this->_packagesPath = $path . DIRECTORY_SEPARATOR . 'packages';
136         }
137
138         $this->_path = $path;
139     }
140     
141     /**
142      * setPackagePath
143      *
144      * @param string $packagesPrefix 
145      * @return void
146      */
147     public function setPackagesPrefix($packagesPrefix)
148     {
149         $this->_packagesPrefix = $packagesPrefix;
150     }
151
152     /**
153      * setPackagesPath
154      *
155      * @param string $packagesPath 
156      * @return void
157      */
158     public function setPackagesPath($packagesPath)
159     {
160         $this->_packagesPath = $packagesPath;
161     }
162     
163     /**
164      * generateBaseClasses
165      *
166      * Specify whether or not to generate classes which extend from generated base classes
167      *
168      * @param string $bool
169      * @return void
170      */
171     public function generateBaseClasses($bool = null)
172     {
173         if ($bool !== null) {
174             $this->_generateBaseClasses = $bool;
175         }
176
177         return $this->_generateBaseClasses;
178     }
179     
180     /**
181      * generateTableClasses
182      *
183      * Specify whether or not to generate table classes which extend from Doctrine_Table
184      *
185      * @param string $bool
186      * @return void
187      */
188     public function generateTableClasses($bool = null)
189     {
190         if ($bool !== null) {
191             $this->_generateTableClasses = $bool;
192         }
193
194         return $this->_generateTableClasses;
195     }
196
197     /**
198      * setBaseClassesDirectory
199      *
200      * @return void
201      */
202     public function setBaseClassesDirectory($baseClassesDirectory)
203     {
204         $this->_baseClassesDirectory;
205     }
206     
207     /**
208      * setBaseClassName
209      *
210      * @package default
211      */
212     public function setBaseClassName($className)
213     {
214         $this->_baseClassName = $className;
215     }
216     
217     /**
218      * setSuffix
219      *
220      * @param string $suffix 
221      * @return void
222      */
223     public function setSuffix($suffix)
224     {
225         $this->_suffix = $suffix;
226     }
227
228     /**
229      * getTargetPath
230      *
231      * @return string       the path where imported files are being generated
232      */
233     public function getTargetPath()
234     {
235         return $this->_path;
236     }
237
238     /**
239      * loadTemplate
240      * 
241      * Loads the class template used for generating classes
242      *
243      * @return void
244      */
245     public function loadTemplate() 
246     {
247         if (isset(self::$_tpl)) {
248             return;
249         }
250
251         self::$_tpl =<<<END
252 /**
253  * This class has been auto-generated by the Doctrine ORM Framework
254  */
255 %sclass %s extends %s
256 {
257 %s
258 %s
259 %s
260 }
261 END;
262     }
263
264     /*
265      * Build the accessors
266      *
267      * @param  string $table
268      * @param  array  $columns
269      */
270     public function buildAccessors(array $options, array $columns)
271     {
272         $ret = '';
273         foreach ($columns as $name => $column) {
274             // getters
275             $ret .= "\n  public function get".Doctrine::classify($name)."(\$load = true)\n";
276             $ret .= "  {\n";
277             $ret .= "    return \$this->get('{$name}', \$load);\n";
278             $ret .= "  }\n";
279
280             // setters
281             $ret .= "\n  public function set".Doctrine::classify($name)."(\${$name}, \$load = true)\n";
282             $ret .= "  {\n";
283             $ret .= "    return \$this->set('{$name}', \${$name}, \$load);\n";
284             $ret .= "  }\n";
285         }
286
287         return $ret;
288     }
289
290     /*
291      * Build the table definition of a Doctrine_Record object
292      *
293      * @param  string $table
294      * @param  array  $tableColumns
295      */
296     public function buildTableDefinition(array $options, array $columns, array $relations, array $indexes, array $attributes, array $templates, array $actAs)
297     {
298         $ret = array();
299         
300         $i = 0;
301         
302         if (isset($options['inheritance']['extends']) && !(isset($options['override_parent']) && $options['override_parent'] == false)) {
303             $ret[$i] = "    parent::setTableDefinition();";
304             $i++;
305         }
306         
307         if (isset($options['tableName']) && !empty($options['tableName'])) {
308             $ret[$i] = "    ".'$this->setTableName(\''. $options['tableName'].'\');';
309             
310             $i++;
311         }
312         
313         foreach ($columns as $name => $column) {
314             $ret[$i] = "    ".'$this->hasColumn(\'' . $name . '\', \'' . $column['type'] . '\'';
315             
316             if ($column['length']) {
317                 $ret[$i] .= ', ' . $column['length'];
318             } else {
319                 $ret[$i] .= ', null';
320             }
321
322             $a = array();
323
324             if (isset($column['default'])) {
325                 $a[] = '\'default\' => ' . var_export($column['default'], true);
326             }
327             if (isset($column['notnull']) && $column['notnull']) {
328                 $a[] = '\'notnull\' => true';
329             }
330             if (isset($column['primary']) && $column['primary']) {
331                 $a[] = '\'primary\' => true';
332             }
333             if ((isset($column['autoinc']) && $column['autoinc']) || isset($column['autoincrement']) && $column['autoincrement']) {
334                 $a[] = '\'autoincrement\' => true';
335             }
336             if (isset($column['unique']) && $column['unique']) {
337                 $a[] = '\'unique\' => true';
338             }
339             if (isset($column['unsigned']) && $column['unsigned']) {
340                 $a[] = '\'unsigned\' => true';
341             }
342             if ($column['type'] == 'enum' && isset($column['values']) ) {
343                 $a[] = '\'values\' => array(\'' . implode('\',\'', $column['values']) . '\')';
344             }
345
346             if ( ! empty($a)) {
347                 $ret[$i] .= ', ' . 'array(';
348                 $length = strlen($ret[$i]);
349                 $ret[$i] .= implode(',' . PHP_EOL . str_repeat(' ', $length), $a) . ')';
350             }
351             
352             $ret[$i] .= ');';
353
354             if ($i < (count($columns) - 1)) {
355                 $ret[$i] .= PHP_EOL;
356             }
357             $i++;
358         }
359         
360         $ret[$i] = $this->buildIndexes($indexes);
361         $i++;
362         
363         $ret[$i] = $this->buildAttributes($attributes);
364         $i++;
365         
366         $ret[$i] = $this->buildTemplates($templates);
367         $i++;
368         
369         $ret[$i] = $this->buildActAs($actAs);
370         
371         $code = implode("\n", $ret);
372         $code = trim($code);
373         
374         if ($code) {
375           return "\n  public function setTableDefinition()"."\n  {\n    ".$code."\n  }";
376         }
377     }
378
379     /**
380      * buildTemplates
381      *
382      * @param string $array 
383      * @return void
384      */
385     public function buildTemplates(array $templates)
386     {
387         $build = '';
388         foreach ($templates as $name => $options) {
389             
390             if (is_array($options) && !empty($options)) {
391                 $optionsPhp = $this->arrayToPhpArrayCode($options);
392             
393                 $build .= "    \$this->loadTemplate('" . $name . "', " . $optionsPhp . ");\n";
394             } else {
395                 if (isset($templates[0])) {
396                     $build .= "    \$this->loadTemplate('" . $options . "');\n";
397                 } else {
398                     $build .= "    \$this->loadTemplate('" . $name . "');\n";
399                 }
400             }
401         }
402         
403         return $build;
404     }
405
406     /**
407      * buildActAs
408      *
409      * @param string $array 
410      * @return void
411      */
412     public function buildActAs(array $actAs)
413     {
414         $build = '';
415         foreach ($actAs as $name => $options) {
416             if (is_array($options) && !empty($options)) {
417                 $optionsPhp = $this->arrayToPhp($options);
418                 
419                 $build .= "    \$this->actAs('" . $name . "', " . $optionsPhp . ");\n";
420             } else {
421                 if (isset($actAs[0])) {
422                     $build .= "    \$this->actAs('" . $options . "');\n";
423                 } else {
424                     $build .= "    \$this->actAs('" . $name . "');\n";
425                 }
426             }
427         }
428         
429         return $build;
430     }
431
432     /**
433      * arrayToPhp
434      *
435      * @param string $array 
436      * @return void
437      */
438     protected function arrayToPhp(array $array)
439     {
440         ob_start();
441         var_export($array);
442         $php = ob_get_contents();
443         ob_end_clean();
444         
445         return $php;
446     }
447
448     /**
449      * buildAttributes
450      *
451      * @param string $array 
452      * @return void
453      */
454     public function buildAttributes(array $attributes)
455     {
456         $build = "\n";
457         foreach ($attributes as $key => $value) {
458           
459             if (is_bool($value))
460             {
461               $values = $value ? 'true':'false';
462             } else {
463                 if ( ! is_array($value)) {
464                     $value = array($value);
465                 }
466             
467                 $values = '';
468                 foreach ($value as $attr) {
469                     $values .= "Doctrine::" . strtoupper($key) . "_" . strtoupper($attr) . ' ^ ';
470                 }
471                 
472                 // Trim last ^
473                 $values = substr($values, 0, strlen($values) - 3);
474             }
475             
476             $build .= "    \$this->setAttribute(Doctrine::ATTR_" . strtoupper($key) . ", " . $values . ");\n";
477         }
478         
479         return $build;
480     }
481
482     /**
483      * buildIndexes
484      *
485      * @param string $array 
486      * @return void
487      */
488     public function buildIndexes(array $indexes)
489     {
490       $build = '';
491
492       foreach ($indexes as $indexName => $definitions) {
493           $build .= "\n    ".'$this->index(\'' . $indexName . '\', array(';
494
495           foreach ($definitions as $name => $value) {
496
497             // parse fields
498             if ($name === 'fields' || $name === 'columns') {
499               $build .= '\'fields\' => array(';
500
501               foreach ($value as $fieldName => $fieldValue) {
502                 $build .= '\'' . $fieldName . '\' => array( ';
503
504                 // parse options { sorting, length, primary }
505                 if (isset($fieldValue) && $fieldValue) {
506                   foreach ($fieldValue as $optionName => $optionValue) {
507
508                     $build .= '\'' . $optionName . '\' => ';
509
510                     // check primary option, mark either as true or false
511                     if ($optionName === 'primary') {
512                      $build .= (($optionValue == 'true') ? 'true' : 'false') . ', ';
513                      continue;
514                     }
515
516                     // convert sorting option to uppercase, for instance, asc -> ASC
517                     if ($optionName === 'sorting') {
518                      $build .= '\'' . strtoupper($optionValue) . '\', ';
519                      continue;
520                     }
521
522                     // check the rest of the options
523                     $build .= '\'' . $optionValue . '\', ';
524                   }
525                 }
526
527                 $build .= '), ';
528               }
529             }
530
531             // parse index type option, 4 choices { unique, fulltext, gist, gin }
532             if ($name === 'type') {
533              $build .= '), \'type\' => \'' . $value . '\'';
534             }
535
536             // add extra ) if type definition is not declared
537             if ( ! isset($definitions['type'])) {
538              $build .= ')';
539             }
540           }
541
542           $build .= '));';
543       }
544
545       return $build;
546     }
547
548     /**
549      * buildSetUp
550      *
551      * @param  array $options 
552      * @param  array $columns 
553      * @param  array $relations 
554      * @return string
555      */
556     public function buildSetUp(array $options, array $columns, array $relations)
557     {
558         $ret = array();
559         $i = 0;
560         
561         if (isset($options['inheritance']['extends']) && !(isset($options['override_parent']) && $options['override_parent'] == false)) {
562             $ret[$i] = "    parent::setUp();";
563             $i++;
564         }
565         
566         foreach ($relations as $name => $relation) {
567             $class = isset($relation['class']) ? $relation['class']:$name;
568             $alias = (isset($relation['alias']) && $relation['alias'] !== $relation['class']) ? ' as ' . $relation['alias'] : '';
569
570             if ( ! isset($relation['type'])) {
571                 $relation['type'] = Doctrine_Relation::ONE;
572             }
573
574             if ($relation['type'] === Doctrine_Relation::ONE || 
575                 $relation['type'] === Doctrine_Relation::ONE_COMPOSITE) {
576                 $ret[$i] = "    ".'$this->hasOne(\'' . $class . $alias . '\'';
577             } else {
578                 $ret[$i] = "    ".'$this->hasMany(\'' . $class . $alias . '\'';
579             }
580             
581             $a = array();
582
583             if (isset($relation['refClass'])) {
584                 $a[] = '\'refClass\' => ' . var_export($relation['refClass'], true);
585             }
586             
587             if (isset($relation['deferred']) && $relation['deferred']) {
588                 $a[] = '\'default\' => ' . var_export($relation['deferred'], true);
589             }
590             
591             if (isset($relation['local']) && $relation['local']) {
592                 $a[] = '\'local\' => ' . var_export($relation['local'], true);
593             }
594             
595             if (isset($relation['foreign']) && $relation['foreign']) {
596                 $a[] = '\'foreign\' => ' . var_export($relation['foreign'], true);
597             }
598             
599             if (isset($relation['onDelete']) && $relation['onDelete']) {
600                 $a[] = '\'onDelete\' => ' . var_export($relation['onDelete'], true);
601             }
602             
603             if (isset($relation['onUpdate']) && $relation['onUpdate']) {
604                 $a[] = '\'onUpdate\' => ' . var_export($relation['onUpdate'], true);
605             }
606             
607             if (isset($relation['equal']) && $relation['equal']) { 
608                 $a[] = '\'equal\' => ' . var_export($relation['equal'], true); 
609             }
610             
611             if ( ! empty($a)) {
612                 $ret[$i] .= ', ' . 'array(';
613                 $length = strlen($ret[$i]);
614                 $ret[$i] .= implode(',' . PHP_EOL . str_repeat(' ', $length), $a) . ')';
615             }
616             
617             $ret[$i] .= ');'."\n";
618             $i++;
619         }
620         
621         if (isset($options['inheritance']['keyField']) && isset($options['inheritance']['keyValue'])) {
622             $i++;
623             $ret[$i] = "    ".'$this->setInheritanceMap(array(\''.$options['inheritance']['keyField'].'\' => '.$options['inheritance']['keyValue'].'));';
624         }
625         
626         $code = implode("\n", $ret);
627         $code = trim($code);
628         
629         if ($code) {
630           return "\n  public function setUp()\n  {\n    ".$code."\n  }";
631         }
632     }
633
634     /**
635      * buildDefinition
636      *
637      * @param array $options 
638      * @param array $columns 
639      * @param array $relations 
640      * @param array $indexes 
641      * @param array $attributes 
642      * @param array $templates 
643      * @param array $actAs 
644      * @return string
645      */
646     public function buildDefinition(array $options, array $columns, array $relations = array(), array $indexes = array(), $attributes = array(), array $templates = array(), array $actAs = array())
647     {
648         if ( ! isset($options['className'])) {
649             throw new Doctrine_Import_Builder_Exception('Missing class name.');
650         }
651
652         $abstract = isset($options['abstract']) && $options['abstract'] === true ? 'abstract ':null;
653         $className = $options['className'];
654         $extends = isset($options['inheritance']['extends']) ? $options['inheritance']['extends']:$this->_baseClassName;
655
656         if ( ! (isset($options['no_definition']) && $options['no_definition'] === true)) {
657             $definition = $this->buildTableDefinition($options, $columns, $relations, $indexes, $attributes, $templates, $actAs);
658             $setUp = $this->buildSetUp($options, $columns, $relations);
659         } else {
660             $definition = null;
661             $setUp = null;
662         }
663         
664         $accessors = (isset($options['generate_accessors']) && $options['generate_accessors'] === true) ? $this->buildAccessors($options, $columns):null;
665         
666         $content = sprintf(self::$_tpl, $abstract,
667                                        $className,
668                                        $extends,
669                                        $definition,
670                                        $setUp,
671                                        $accessors);
672         
673         return $content;
674     }
675
676     /**
677      * buildRecord
678      *
679      * @param array $options 
680      * @param array $columns 
681      * @param array $relations 
682      * @param array $indexes 
683      * @param array $attributes 
684      * @param array $templates 
685      * @param array $actAs 
686      * @return void=
687      */
688     public function buildRecord(array $options, array $columns, array $relations = array(), array $indexes = array(), array $attributes = array(), array $templates = array(), array $actAs = array())
689     {
690         if ( !isset($options['className'])) {
691             throw new Doctrine_Import_Builder_Exception('Missing class name.');
692         }
693
694         if ($this->generateBaseClasses()) {
695             $options['is_package'] = (isset($options['package']) && $options['package']) ? true:false;
696             
697             if ($options['is_package']) {
698                 $e = explode('.', $options['package']);
699                 $options['package_name'] = $e[0];
700                 unset($e[0]);
701                 
702                 $options['package_path'] = implode(DIRECTORY_SEPARATOR, $e);
703             }
704             
705             // Top level definition that extends from all the others
706             $topLevel = $options;
707             unset($topLevel['tableName']);
708             
709             // If we have a package then we need to make this extend the package definition and not the base definition
710             // The package definition will then extends the base definition
711             $topLevel['inheritance']['extends'] = (isset($topLevel['package']) && $topLevel['package']) ? $this->_packagesPrefix . $topLevel['className']:'Base' . $topLevel['className'];
712             $topLevel['no_definition'] = true;
713             $topLevel['generate_once'] = true;
714             $topLevel['is_main_class'] = true;
715
716             // Package level definition that extends from the base definition
717             if (isset($options['package'])) {
718                 
719                 $packageLevel = $options;
720                 $packageLevel['className'] = $topLevel['inheritance']['extends'];
721                 $packageLevel['inheritance']['extends'] = 'Base' . $topLevel['className'];
722                 $packageLevel['no_definition'] = true;
723                 $packageLevel['abstract'] = true;
724                 $packageLevel['override_parent'] = true;
725                 $packageLevel['generate_once'] = true;
726                 $packageLevel['is_package_class'] = true;
727             }
728
729             $baseClass = $options;
730             $baseClass['className'] = 'Base' . $baseClass['className'];
731             $baseClass['abstract'] = true;
732             $baseClass['override_parent'] = true;
733             $baseClass['is_base_class'] = true;
734
735             $this->writeDefinition($baseClass, $columns, $relations, $indexes, $attributes, $templates, $actAs);
736             
737             if (!empty($packageLevel)) {
738                 $this->writeDefinition($packageLevel);
739             }
740             
741             $this->writeDefinition($topLevel);
742         } else {
743             $this->writeDefinition($options, $columns, $relations, $indexes, $attributes, $templates, $actAs);
744         }
745     }
746     
747     /**
748      * writeTableDefinition
749      *
750      * @return void
751      */
752     public function writeTableDefinition($className, $path, $options = array())
753     {
754         $className = $className . 'Table';
755         
756         $content  = '<?php' . PHP_EOL;
757         $content .= sprintf(self::$_tpl, false,
758                                        $className,
759                                        isset($options['extends']) ? $options['extends']:'Doctrine_Table',
760                                        null,
761                                        null,
762                                        null
763                                        );
764         
765         Doctrine::makeDirectories($path);
766         
767         $writePath = $path . DIRECTORY_SEPARATOR . $className . $this->_suffix;
768         
769         if (!file_exists($writePath)) {
770             file_put_contents($writePath, $content);
771         }
772     }
773     
774     /**
775      * writeDefinition
776      *
777      * @param array $options 
778      * @param array $columns 
779      * @param array $relations 
780      * @param array $indexes 
781      * @param array $attributes 
782      * @param array $templates 
783      * @param array $actAs 
784      * @return void
785      */
786     public function writeDefinition(array $options, array $columns = array(), array $relations = array(), array $indexes = array(), array $attributes = array(), array $templates = array(), array $actAs = array())
787     {
788         $definition = $this->buildDefinition($options, $columns, $relations, $indexes, $attributes, $templates, $actAs);
789
790         $fileName = $options['className'] . $this->_suffix;
791
792         $packagesPath = $this->_packagesPath ? $this->_packagesPath:$this->_path;
793
794         // If this is a main class that either extends from Base or Package class
795         if (isset($options['is_main_class']) && $options['is_main_class']) {
796             // If is package then we need to put it in a package subfolder
797             if (isset($options['is_package']) && $options['is_package']) {
798                 $writePath = $this->_path . DIRECTORY_SEPARATOR . $options['package_name'];
799                 
800                 $this->writeTableDefinition($options['className'], $writePath, array('extends' => $options['inheritance']['extends'] . 'Table'));
801             // Otherwise lets just put it in the root of the path
802             } else {
803                 $writePath = $this->_path;
804                 
805                 $this->writeTableDefinition($options['className'], $writePath);
806             }
807         }
808
809         // If is the package class then we need to make the path to the complete package
810         if (isset($options['is_package_class']) && $options['is_package_class']) {
811             $path = str_replace('.', DIRECTORY_SEPARATOR, $options['package']);
812             
813             $writePath = $packagesPath . DIRECTORY_SEPARATOR . $path;
814             
815             $this->writeTableDefinition($options['className'], $writePath);
816         }
817         
818         // If it is the base class of the doctrine record definition
819         if (isset($options['is_base_class']) && $options['is_base_class']) {
820             // If it is a part of a package then we need to put it in a package subfolder
821             if (isset($options['is_package']) && $options['is_package']) {
822                 $writePath  = $this->_path . DIRECTORY_SEPARATOR . $options['package_name'] . DIRECTORY_SEPARATOR . $this->_baseClassesDirectory;
823             // Otherwise lets just put it in the root generated folder
824             } else {
825                 $writePath = $this->_path . DIRECTORY_SEPARATOR . $this->_baseClassesDirectory;
826             }
827         }
828         
829         if (isset($writePath)) {
830             Doctrine::makeDirectories($writePath);
831             
832             $writePath .= DIRECTORY_SEPARATOR . $fileName;
833         } else {
834             Doctrine::makeDirectories($this->_path);
835             
836             $writePath = $this->_path . DIRECTORY_SEPARATOR . $fileName;
837         }
838         
839         $code = "<?php" . PHP_EOL;
840         
841         if (isset($options['requires'])) {
842             if ( ! is_array($options['requires'])) {
843                 $options['requires'] = array($options['requires']);
844             }
845             
846             foreach ($options['requires'] as $require) {
847                 $code .= "require_once('".$require."');\n";
848             }
849         }
850         
851         if (isset($options['connection']) && $options['connection']) {
852             $code .= "// Connection Component Binding\n";
853             $code .= "Doctrine_Manager::getInstance()->bindComponent('" . $options['connectionClassName'] . "', '" . $options['connection'] . "');\n";
854         }
855
856         $code .= PHP_EOL . $definition;
857
858         if (isset($options['generate_once']) && $options['generate_once'] === true) {
859             if (!file_exists($writePath)) {
860                 $bytes = file_put_contents($writePath, $code);
861             }
862         } else {
863             $bytes = file_put_contents($writePath, $code);
864         }
865
866         if (isset($bytes) && $bytes === false) {
867             throw new Doctrine_Import_Builder_Exception("Couldn't write file " . $writePath);
868         }
869     }
870 }