Coverage for Doctrine_Import_Builder

Back to coverage report

1 <?php
2 /*
3  *  $Id: Builder.php 3082 2007-11-08 00:29:15Z Jonathan.Wage $
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: 3082 $
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 = '.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      * setOptions
240      *
241      * @param string $options 
242      * @return void
243      */
244     public function setOptions($options)
245     {
246         if (!empty($options)) {
247             foreach ($options as $key => $value) {
248                 $this->setOption($key, $value);
249             }
250         }
251     }
252
253     /**
254      * setOption
255      *
256      * @param string $key 
257      * @param string $value 
258      * @return void
259      */
260     public function setOption($key, $value)
261     {
262         $name = '_'.$key;
263         $this->$name = $value;
264     }
265
266     /**
267      * loadTemplate
268      * 
269      * Loads the class template used for generating classes
270      *
271      * @return void
272      */
273     public function loadTemplate() 
274     {
275         if (isset(self::$_tpl)) {
276             return;
277         }
278
279         self::$_tpl =<<<END
280 /**
281  * This class has been auto-generated by the Doctrine ORM Framework
282  */
283 %sclass %s extends %s
284 {
285 %s
286 %s
287 %s
288 }
289 END;
290     }
291
292     /*
293      * Build the accessors
294      *
295      * @param  string $table
296      * @param  array  $columns
297      */
298     public function buildAccessors(array $options, array $columns)
299     {
300         $ret = '';
301         foreach ($columns as $name => $column) {
302             // getters
303             $ret .= "\n  public function get".Doctrine::classify($name)."(\$load = true)\n";
304             $ret .= "  {\n";
305             $ret .= "    return \$this->get('{$name}', \$load);\n";
306             $ret .= "  }\n";
307
308             // setters
309             $ret .= "\n  public function set".Doctrine::classify($name)."(\${$name}, \$load = true)\n";
310             $ret .= "  {\n";
311             $ret .= "    return \$this->set('{$name}', \${$name}, \$load);\n";
312             $ret .= "  }\n";
313         }
314
315         return $ret;
316     }
317
318     /*
319      * Build the table definition of a Doctrine_Record object
320      *
321      * @param  string $table
322      * @param  array  $tableColumns
323      */
324     public function buildTableDefinition(array $options, array $columns, array $relations, array $indexes, array $attributes, array $templates, array $actAs)
325     {
326         $ret = array();
327         
328         $i = 0;
329         
330         if (isset($options['inheritance']['extends']) && !(isset($options['override_parent']) && $options['override_parent'] == false)) {
331             $ret[$i] = "    parent::setTableDefinition();";
332             $i++;
333         }
334         
335         if (isset($options['tableName']) && !empty($options['tableName'])) {
336             $ret[$i] = "    ".'$this->setTableName(\''. $options['tableName'].'\');';
337             
338             $i++;
339         }
340         
341         foreach ($columns as $name => $column) {
342             $ret[$i] = "    ".'$this->hasColumn(\'' . $name . '\', \'' . $column['type'] . '\'';
343             
344             if ($column['length']) {
345                 $ret[$i] .= ', ' . $column['length'];
346             } else {
347                 $ret[$i] .= ', null';
348             }
349
350             $a = array();
351
352             if (isset($column['default'])) {
353                 $a[] = '\'default\' => ' . var_export($column['default'], true);
354             }
355             if (isset($column['notnull']) && $column['notnull']) {
356                 $a[] = '\'notnull\' => true';
357             }
358             if (isset($column['primary']) && $column['primary']) {
359                 $a[] = '\'primary\' => true';
360             }
361             if ((isset($column['autoinc']) && $column['autoinc']) || isset($column['autoincrement']) && $column['autoincrement']) {
362                 $a[] = '\'autoincrement\' => true';
363             }
364             if (isset($column['unique']) && $column['unique']) {
365                 $a[] = '\'unique\' => true';
366             }
367             if (isset($column['unsigned']) && $column['unsigned']) {
368                 $a[] = '\'unsigned\' => true';
369             }
370             if ($column['type'] == 'enum' && isset($column['values']) ) {
371                 $a[] = '\'values\' => array(\'' . implode('\',\'', $column['values']) . '\')';
372             }
373
374             if ( ! empty($a)) {
375                 $ret[$i] .= ', ' . 'array(';
376                 $length = strlen($ret[$i]);
377                 $ret[$i] .= implode(',' . PHP_EOL . str_repeat(' ', $length), $a) . ')';
378             }
379             
380             $ret[$i] .= ');';
381
382             if ($i < (count($columns) - 1)) {
383                 $ret[$i] .= PHP_EOL;
384             }
385             $i++;
386         }
387         
388         $ret[$i] = $this->buildIndexes($indexes);
389         $i++;
390         
391         $ret[$i] = $this->buildAttributes($attributes);
392         $i++;
393         
394         $ret[$i] = $this->buildTemplates($templates);
395         $i++;
396         
397         $ret[$i] = $this->buildActAs($actAs);
398         
399         $code = implode("\n", $ret);
400         $code = trim($code);
401         
402         if ($code) {
403           return "\n  public function setTableDefinition()"."\n  {\n    ".$code."\n  }";
404         }
405     }
406
407     /**
408      * buildTemplates
409      *
410      * @param string $array 
411      * @return void
412      */
413     public function buildTemplates(array $templates)
414     {
415         $build = '';
416         foreach ($templates as $name => $options) {
417             
418             if (is_array($options) && !empty($options)) {
419                 $optionsPhp = $this->arrayToPhpArrayCode($options);
420             
421                 $build .= "    \$this->loadTemplate('" . $name . "', " . $optionsPhp . ");\n";
422             } else {
423                 if (isset($templates[0])) {
424                     $build .= "    \$this->loadTemplate('" . $options . "');\n";
425                 } else {
426                     $build .= "    \$this->loadTemplate('" . $name . "');\n";
427                 }
428             }
429         }
430         
431         return $build;
432     }
433
434     /**
435      * buildActAs
436      *
437      * @param string $array 
438      * @return void
439      */
440     public function buildActAs(array $actAs)
441     {
442         $build = '';
443         foreach ($actAs as $name => $options) {
444             if (is_array($options) && !empty($options)) {
445                 $optionsPhp = $this->arrayToPhp($options);
446                 
447                 $build .= "    \$this->actAs('" . $name . "', " . $optionsPhp . ");\n";
448             } else {
449                 if (isset($actAs[0])) {
450                     $build .= "    \$this->actAs('" . $options . "');\n";
451                 } else {
452                     $build .= "    \$this->actAs('" . $name . "');\n";
453                 }
454             }
455         }
456         
457         return $build;
458     }
459
460     /**
461      * arrayToPhp
462      *
463      * @param string $array 
464      * @return void
465      */
466     protected function arrayToPhp(array $array)
467     {
468         ob_start();
469         var_export($array);
470         $php = ob_get_contents();
471         ob_end_clean();
472         
473         return $php;
474     }
475
476     /**
477      * buildAttributes
478      *
479      * @param string $array 
480      * @return void
481      */
482     public function buildAttributes(array $attributes)
483     {
484         $build = "\n";
485         foreach ($attributes as $key => $value) {
486           
487             if (is_bool($value))
488             {
489               $values = $value ? 'true':'false';
490             } else {
491                 if ( ! is_array($value)) {
492                     $value = array($value);
493                 }
494             
495                 $values = '';
496                 foreach ($value as $attr) {
497                     $values .= "Doctrine::" . strtoupper($key) . "_" . strtoupper($attr) . ' ^ ';
498                 }
499                 
500                 // Trim last ^
501                 $values = substr($values, 0, strlen($values) - 3);
502             }
503             
504             $build .= "    \$this->setAttribute(Doctrine::ATTR_" . strtoupper($key) . ", " . $values . ");\n";
505         }
506         
507         return $build;
508     }
509
510     /**
511      * buildIndexes
512      *
513      * @param string $array 
514      * @return void
515      */
516     public function buildIndexes(array $indexes)
517     {
518       $build = '';
519
520       foreach ($indexes as $indexName => $definitions) {
521           $build .= "\n    ".'$this->index(\'' . $indexName . '\', array(';
522
523           foreach ($definitions as $name => $value) {
524
525             // parse fields
526             if ($name === 'fields' || $name === 'columns') {
527               $build .= '\'fields\' => array(';
528
529               foreach ($value as $fieldName => $fieldValue) {
530                 $build .= '\'' . $fieldName . '\' => array( ';
531
532                 // parse options { sorting, length, primary }
533                 if (isset($fieldValue) && $fieldValue) {
534                   foreach ($fieldValue as $optionName => $optionValue) {
535
536                     $build .= '\'' . $optionName . '\' => ';
537
538                     // check primary option, mark either as true or false
539                     if ($optionName === 'primary') {
540                      $build .= (($optionValue == 'true') ? 'true' : 'false') . ', ';
541                      continue;
542                     }
543
544                     // convert sorting option to uppercase, for instance, asc -> ASC
545                     if ($optionName === 'sorting') {
546                      $build .= '\'' . strtoupper($optionValue) . '\', ';
547                      continue;
548                     }
549
550                     // check the rest of the options
551                     $build .= '\'' . $optionValue . '\', ';
552                   }
553                 }
554
555                 $build .= '), ';
556               }
557             }
558
559             // parse index type option, 4 choices { unique, fulltext, gist, gin }
560             if ($name === 'type') {
561              $build .= '), \'type\' => \'' . $value . '\'';
562             }
563
564             // add extra ) if type definition is not declared
565             if ( ! isset($definitions['type'])) {
566              $build .= ')';
567             }
568           }
569
570           $build .= '));';
571       }
572
573       return $build;
574     }
575
576     /**
577      * buildSetUp
578      *
579      * @param  array $options 
580      * @param  array $columns 
581      * @param  array $relations 
582      * @return string
583      */
584     public function buildSetUp(array $options, array $columns, array $relations)
585     {
586         $ret = array();
587         $i = 0;
588         
589         if (isset($options['inheritance']['extends']) && !(isset($options['override_parent']) && $options['override_parent'] == false)) {
590             $ret[$i] = "    parent::setUp();";
591             $i++;
592         }
593         
594         foreach ($relations as $name => $relation) {
595             $class = isset($relation['class']) ? $relation['class']:$name;
596             $alias = (isset($relation['alias']) && $relation['alias'] !== $relation['class']) ? ' as ' . $relation['alias'] : '';
597
598             if ( ! isset($relation['type'])) {
599                 $relation['type'] = Doctrine_Relation::ONE;
600             }
601
602             if ($relation['type'] === Doctrine_Relation::ONE || 
603                 $relation['type'] === Doctrine_Relation::ONE_COMPOSITE) {
604                 $ret[$i] = "    ".'$this->hasOne(\'' . $class . $alias . '\'';
605             } else {
606                 $ret[$i] = "    ".'$this->hasMany(\'' . $class . $alias . '\'';
607             }
608             
609             $a = array();
610
611             if (isset($relation['refClass'])) {
612                 $a[] = '\'refClass\' => ' . var_export($relation['refClass'], true);
613             }
614             
615             if (isset($relation['deferred']) && $relation['deferred']) {
616                 $a[] = '\'default\' => ' . var_export($relation['deferred'], true);
617             }
618             
619             if (isset($relation['local']) && $relation['local']) {
620                 $a[] = '\'local\' => ' . var_export($relation['local'], true);
621             }
622             
623             if (isset($relation['foreign']) && $relation['foreign']) {
624                 $a[] = '\'foreign\' => ' . var_export($relation['foreign'], true);
625             }
626             
627             if (isset($relation['onDelete']) && $relation['onDelete']) {
628                 $a[] = '\'onDelete\' => ' . var_export($relation['onDelete'], true);
629             }
630             
631             if (isset($relation['onUpdate']) && $relation['onUpdate']) {
632                 $a[] = '\'onUpdate\' => ' . var_export($relation['onUpdate'], true);
633             }
634             
635             if (isset($relation['equal']) && $relation['equal']) { 
636                 $a[] = '\'equal\' => ' . var_export($relation['equal'], true); 
637             }
638             
639             if ( ! empty($a)) {
640                 $ret[$i] .= ', ' . 'array(';
641                 $length = strlen($ret[$i]);
642                 $ret[$i] .= implode(',' . PHP_EOL . str_repeat(' ', $length), $a) . ')';
643             }
644             
645             $ret[$i] .= ');'."\n";
646             $i++;
647         }
648         
649         if (isset($options['inheritance']['keyField']) && isset($options['inheritance']['keyValue'])) {
650             $i++;
651             $ret[$i] = "    ".'$this->setInheritanceMap(array(\''.$options['inheritance']['keyField'].'\' => '.$options['inheritance']['keyValue'].'));';
652         }
653         
654         $code = implode("\n", $ret);
655         $code = trim($code);
656         
657         if ($code) {
658           return "\n  public function setUp()\n  {\n    ".$code."\n  }";
659         }
660     }
661
662     /**
663      * buildDefinition
664      *
665      * @param array $options 
666      * @param array $columns 
667      * @param array $relations 
668      * @param array $indexes 
669      * @param array $attributes 
670      * @param array $templates 
671      * @param array $actAs 
672      * @return string
673      */
674     public function buildDefinition(array $options, array $columns, array $relations = array(), array $indexes = array(), $attributes = array(), array $templates = array(), array $actAs = array())
675     {
676         if ( ! isset($options['className'])) {
677             throw new Doctrine_Import_Builder_Exception('Missing class name.');
678         }
679
680         $abstract = isset($options['abstract']) && $options['abstract'] === true ? 'abstract ':null;
681         $className = $options['className'];
682         $extends = isset($options['inheritance']['extends']) ? $options['inheritance']['extends']:$this->_baseClassName;
683
684         if ( ! (isset($options['no_definition']) && $options['no_definition'] === true)) {
685             $definition = $this->buildTableDefinition($options, $columns, $relations, $indexes, $attributes, $templates, $actAs);
686             $setUp = $this->buildSetUp($options, $columns, $relations);
687         } else {
688             $definition = null;
689             $setUp = null;
690         }
691         
692         $accessors = (isset($options['generate_accessors']) && $options['generate_accessors'] === true) ? $this->buildAccessors($options, $columns):null;
693         
694         $content = sprintf(self::$_tpl, $abstract,
695                                        $className,
696                                        $extends,
697                                        $definition,
698                                        $setUp,
699                                        $accessors);
700         
701         return $content;
702     }
703
704     /**
705      * buildRecord
706      *
707      * @param array $options 
708      * @param array $columns 
709      * @param array $relations 
710      * @param array $indexes 
711      * @param array $attributes 
712      * @param array $templates 
713      * @param array $actAs 
714      * @return void=
715      */
716     public function buildRecord(array $options, array $columns, array $relations = array(), array $indexes = array(), array $attributes = array(), array $templates = array(), array $actAs = array())
717     {
718         if ( !isset($options['className'])) {
719             throw new Doctrine_Import_Builder_Exception('Missing class name.');
720         }
721
722         if ($this->generateBaseClasses()) {
723             $options['is_package'] = (isset($options['package']) && $options['package']) ? true:false;
724             
725             if ($options['is_package']) {
726                 $e = explode('.', $options['package']);
727                 $options['package_name'] = $e[0];
728                 unset($e[0]);
729                 
730                 $options['package_path'] = implode(DIRECTORY_SEPARATOR, $e);
731             }
732             
733             // Top level definition that extends from all the others
734             $topLevel = $options;
735             unset($topLevel['tableName']);
736             
737             // If we have a package then we need to make this extend the package definition and not the base definition
738             // The package definition will then extends the base definition
739             $topLevel['inheritance']['extends'] = (isset($topLevel['package']) && $topLevel['package']) ? $this->_packagesPrefix . $topLevel['className']:'Base' . $topLevel['className'];
740             $topLevel['no_definition'] = true;
741             $topLevel['generate_once'] = true;
742             $topLevel['is_main_class'] = true;
743
744             // Package level definition that extends from the base definition
745             if (isset($options['package'])) {
746                 
747                 $packageLevel = $options;
748                 $packageLevel['className'] = $topLevel['inheritance']['extends'];
749                 $packageLevel['inheritance']['extends'] = 'Base' . $topLevel['className'];
750                 $packageLevel['no_definition'] = true;
751                 $packageLevel['abstract'] = true;
752                 $packageLevel['override_parent'] = true;
753                 $packageLevel['generate_once'] = true;
754                 $packageLevel['is_package_class'] = true;
755             }
756
757             $baseClass = $options;
758             $baseClass['className'] = 'Base' . $baseClass['className'];
759             $baseClass['abstract'] = true;
760             $baseClass['override_parent'] = true;
761             $baseClass['is_base_class'] = true;
762
763             $this->writeDefinition($baseClass, $columns, $relations, $indexes, $attributes, $templates, $actAs);
764             
765             if (!empty($packageLevel)) {
766                 $this->writeDefinition($packageLevel);
767             }
768             
769             $this->writeDefinition($topLevel);
770         } else {
771             $this->writeDefinition($options, $columns, $relations, $indexes, $attributes, $templates, $actAs);
772         }
773     }
774     
775     /**
776      * writeTableDefinition
777      *
778      * @return void
779      */
780     public function writeTableDefinition($className, $path, $options = array())
781     {
782         $className = $className . 'Table';
783         
784         $content  = '<?php' . PHP_EOL;
785         $content .= sprintf(self::$_tpl, false,
786                                        $className,
787                                        isset($options['extends']) ? $options['extends']:'Doctrine_Table',
788                                        null,
789                                        null,
790                                        null
791                                        );
792         
793         Doctrine::makeDirectories($path);
794         
795         $writePath = $path . DIRECTORY_SEPARATOR . $className . $this->_suffix;
796         
797         if (!file_exists($writePath)) {
798             file_put_contents($writePath, $content);
799         }
800     }
801     
802     /**
803      * writeDefinition
804      *
805      * @param array $options 
806      * @param array $columns 
807      * @param array $relations 
808      * @param array $indexes 
809      * @param array $attributes 
810      * @param array $templates 
811      * @param array $actAs 
812      * @return void
813      */
814     public function writeDefinition(array $options, array $columns = array(), array $relations = array(), array $indexes = array(), array $attributes = array(), array $templates = array(), array $actAs = array())
815     {
816         $definition = $this->buildDefinition($options, $columns, $relations, $indexes, $attributes, $templates, $actAs);
817
818         $fileName = $options['className'] . $this->_suffix;
819
820         $packagesPath = $this->_packagesPath ? $this->_packagesPath:$this->_path;
821
822         // If this is a main class that either extends from Base or Package class
823         if (isset($options['is_main_class']) && $options['is_main_class']) {
824             // If is package then we need to put it in a package subfolder
825             if (isset($options['is_package']) && $options['is_package']) {
826                 $writePath = $this->_path . DIRECTORY_SEPARATOR . $options['package_name'];
827                 
828                 $this->writeTableDefinition($options['className'], $writePath, array('extends' => $options['inheritance']['extends'] . 'Table'));
829             // Otherwise lets just put it in the root of the path
830             } else {
831                 $writePath = $this->_path;
832                 
833                 $this->writeTableDefinition($options['className'], $writePath);
834             }
835         }
836
837         // If is the package class then we need to make the path to the complete package
838         if (isset($options['is_package_class']) && $options['is_package_class']) {
839             $path = str_replace('.', DIRECTORY_SEPARATOR, trim($options['package']));
840             
841             $writePath = $packagesPath . DIRECTORY_SEPARATOR . $path;
842             
843             $this->writeTableDefinition($options['className'], $writePath);
844         }
845         
846         // If it is the base class of the doctrine record definition
847         if (isset($options['is_base_class']) && $options['is_base_class']) {
848             // If it is a part of a package then we need to put it in a package subfolder
849             if (isset($options['is_package']) && $options['is_package']) {
850                 $writePath  = $this->_path . DIRECTORY_SEPARATOR . $options['package_name'] . DIRECTORY_SEPARATOR . $this->_baseClassesDirectory;
851             // Otherwise lets just put it in the root generated folder
852             } else {
853                 $writePath = $this->_path . DIRECTORY_SEPARATOR . $this->_baseClassesDirectory;
854             }
855         }
856         
857         if (isset($writePath)) {
858             Doctrine::makeDirectories($writePath);
859             
860             $writePath .= DIRECTORY_SEPARATOR . $fileName;
861         } else {
862             Doctrine::makeDirectories($this->_path);
863             
864             $writePath = $this->_path . DIRECTORY_SEPARATOR . $fileName;
865         }
866         
867         $code = "<?php" . PHP_EOL;
868         
869         if (isset($options['requires'])) {
870             if ( ! is_array($options['requires'])) {
871                 $options['requires'] = array($options['requires']);
872             }
873             
874             foreach ($options['requires'] as $require) {
875                 $code .= "require_once('".$require."');\n";
876             }
877         }
878         
879         if (isset($options['connection']) && $options['connection']) {
880             $code .= "// Connection Component Binding\n";
881             $code .= "Doctrine_Manager::getInstance()->bindComponent('" . $options['connectionClassName'] . "', '" . $options['connection'] . "');\n";
882         }
883
884         $code .= PHP_EOL . $definition;
885
886         if (isset($options['generate_once']) && $options['generate_once'] === true) {
887             if (!file_exists($writePath)) {
888                 $bytes = file_put_contents($writePath, $code);
889             }
890         } else {
891             $bytes = file_put_contents($writePath, $code);
892         }
893
894         if (isset($bytes) && $bytes === false) {
895             throw new Doctrine_Import_Builder_Exception("Couldn't write file " . $writePath);
896         }
897     }
898 }