Coverage for Doctrine_Record_Generator

Back to coverage report

1 <?php
2 /*
3  *  $Id$
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_Record_Generator
24  *
25  * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
26  * @package     Doctrine
27  * @subpackage  Plugin
28  * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
29  * @version     $Revision$
30  * @link        www.phpdoctrine.org
31  * @since       1.0
32  */
33 abstract class Doctrine_Record_Generator extends Doctrine_Record_Abstract
34 {
35     /**
36      * _options
37      *
38      * @var array $_options     an array of plugin specific options
39      */
40     protected $_options = array('generateFiles' => false,
41                                 'identifier'    => false,
42                                 'generateFiles' => false,
43                                 'table'         => false,
44                                 'pluginTable'   => false,
45                                 'children'      => array());
46
47     /**
48      * _initialized
49      *
50      * @var bool $_initialized
51      */
52     protected $_initialized = false;
53
54     /**
55      * __get
56      * an alias for getOption
57      *
58      * @param string $option
59      */
60     public function __get($option)
61     {
62         if (isset($this->_options[$option])) {
63             return $this->_options[$option];
64         }
65         return null;
66     }
67
68     /**
69      * __isset
70      *
71      * @param string $option
72      */
73     public function __isset($option) 
74     {
75         return isset($this->_options[$option]);
76     }
77
78     /**
79      * returns the value of an option
80      *
81      * @param $option       the name of the option to retrieve
82      * @return mixed        the value of the option
83      */
84     public function getOption($name)
85     {
86         if ( ! isset($this->_options[$name])) {
87             throw new Doctrine_Plugin_Exception('Unknown option ' . $name);
88         }
89         
90         return $this->_options[$name];
91     }
92
93     /**
94      * sets given value to an option
95      *
96      * @param $option       the name of the option to be changed
97      * @param $value        the value of the option
98      * @return Doctrine_Plugin  this object
99      */
100     public function setOption($name, $value)
101     {
102         $this->_options[$name] = $value;
103         
104         return $this;
105     }
106
107     /**
108      * addChild
109      *
110      * Add child record generator 
111      *
112      * @param  Doctrine_Record_Generator $generator 
113      * @return void
114      */
115     public function addChild(Doctrine_Record_Generator $generator)
116     {
117         $this->_options['children'][] = $generator;
118     }
119
120     /**
121      * getOptions
122      *
123      * returns all options and their associated values
124      *
125      * @return array    all options as an associative array
126      */
127     public function getOptions()
128     {
129         return $this->_options;
130     }
131
132     /**
133      * initialize
134      *
135      * Initialize the plugin. Call in Doctrine_Template setTableDefinition() in order to initiate a generator in a template
136      * SEE: Doctrine_Template_I18n for an example
137      *
138      * @param  Doctrine_Table $table 
139      * @return void
140      */
141     public function initialize(Doctrine_Table $table)
142     {
143        if ($this->_initialized) {
144            return false;
145        }
146         
147         $this->_initialized = true;
148
149         $this->initOptions();
150
151         $table->addGenerator($this, get_class($this));
152
153         $this->_options['table'] = $table;
154
155         $this->_options['className'] = str_replace('%CLASS%',
156                                                    $this->_options['table']->getComponentName(),
157                                                    $this->_options['className']);
158
159         // check that class doesn't exist (otherwise we cannot create it)
160         if (class_exists($this->_options['className'])) {
161             return false;
162         }
163
164         $conn = $this->_options['table']->getConnection();
165         $conn->getManager()->bindComponent($this->_options['className'], $conn->getName());
166
167         $this->_table = new Doctrine_Table($this->_options['className'], $conn);
168
169         $conn->addTable($this->_table);
170
171         $fk = $this->buildForeignKeys($this->_options['table']);
172
173         $this->_table->setColumns($fk);
174
175         $this->buildRelation();
176
177         $this->setTableDefinition();
178         $this->setUp();
179
180         $this->generateClass(array('columns' => $this->_table->getColumns()));
181
182         $this->buildChildDefinitions();
183
184         $this->_table->initIdentifier();
185     }
186
187     /** 
188      * empty template method for providing the concrete plugins the ability
189      * to initialize options before the actual definition is being built
190      *
191      * @return void
192      */
193     public function initOptions()
194     {
195         
196     }
197
198     /**
199      * buildChildDefinitions
200      *
201      * @return void
202      */
203     public function buildChildDefinitions()
204     {
205         if ( ! isset($this->_options['children'])) {
206             throw new Doctrine_Plugin_Exception("Unknown option 'children'.");
207         }
208
209         foreach ($this->_options['children'] as $child) {
210             $this->_table->addGenerator($child, get_class($child));
211
212             $child->setTable($this->_table);
213
214             $child->setUp();
215         }
216     }
217
218     /**
219      * buildForeignKeys
220      *
221      * generates foreign keys for the plugin table based on the owner table
222      *
223      * the foreign keys generated by this method can be used for 
224      * setting the relations between the owner and the plugin classes
225      *
226      * @param Doctrine_Table $table     the table object that owns the plugin
227      * @return array                    an array of foreign key definitions
228      */
229     public function buildForeignKeys(Doctrine_Table $table)
230     {
231         $fk = array();
232
233         foreach ((array) $table->getIdentifier() as $column) {
234             $def = $table->getDefinitionOf($column);
235
236             unset($def['autoincrement']);
237             unset($def['sequence']);
238             unset($def['primary']);
239
240             $col = $column;
241
242             $def['primary'] = true;
243             $fk[$col] = $def;
244         }
245         return $fk;
246     }
247
248     /**
249      * buildLocalRelation
250      *
251      * @return void
252      */
253     public function buildLocalRelation()
254     {
255         $options = array('local'    => $this->_options['table']->getIdentifier(),
256                          'foreign'  => $this->_options['table']->getIdentifier(),
257                          'type'     => Doctrine_Relation::MANY);
258
259         $options['type'] = Doctrine_Relation::ONE;
260         $options['onDelete'] = 'CASCADE';
261         $options['onUpdate'] = 'CASCADE';
262
263         $this->_table->getRelationParser()->bind($this->_options['table']->getComponentName(), $options);
264     }
265
266     /**
267      * buildForeignRelation
268      *
269      * @param string $alias Alias of the foreign relation
270      * @return void
271      */
272     public function buildForeignRelation($alias = null)
273     {
274         $options = array('local'    => $this->_options['table']->getIdentifier(),
275                          'foreign'  => $this->_options['table']->getIdentifier(),
276                          'type'     => Doctrine_Relation::MANY);
277
278         $aliasStr = '';
279
280         if ($alias !== null) {
281             $aliasStr = ' as ' . $alias;
282         }
283
284         $this->_options['table']->getRelationParser()->bind($this->_table->getComponentName() . $aliasStr,
285                                                             $options);
286     }
287
288     /**
289      * buildRelation
290      *
291      * this method can be used for generating the relation from the plugin 
292      * table to the owner table. By default buildForeignRelation() and buildLocalRelation() are called
293      * Those methods can be overridden or this entire method can be overridden
294      *
295      * @return void
296      */
297     public function buildRelation()
298     {
299        $this->buildForeignRelation();
300         $this->buildLocalRelation();
301     }
302
303     /**
304      * generateClass
305      *
306      * generates the class definition for plugin class
307      *
308      * @param array $columns    the plugin class columns, keys representing the column names
309      *                          and values as column definitions
310      *
311      * @param array $relations  the bound relations of the plugin class
312      *
313      * @param array $options    plugin class options, keys representing the option names
314      *                          and values as option values
315      * @return void
316      */
317     public function generateClass(array $definition = array())
318     {
319         $definition['className'] = $this->_options['className'];
320
321         $builder = new Doctrine_Import_Builder();
322
323         if ($this->_options['generateFiles']) {
324             if (isset($this->_options['generatePath']) && $this->_options['generatePath']) {
325                 $builder->setTargetPath($this->_options['generatePath']);
326
327                 $builder->buildRecord($definition);
328             } else {
329                 throw new Doctrine_Record_Exception('If you wish to generate files then you must specify the path to generate the files in.');
330             }
331         } else {
332             $def = $builder->buildDefinition($definition);
333
334             eval($def);
335         }
336     }
337 }