# Source for file Builder.php

Documentation is available at Builder.php

1. <?php
2. /*
3. * $Id: Builder.php 2051 2007-07-23 20:28:46Z zYne $
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. */
22. /**
23. * Doctrine_Import_Builder
24. * Import builder is responsible of building Doctrine ActiveRecord classes
25. * based on a database schema.
26. *
27. * @package Doctrine
28. * @category Object Relational Mapping
29. * @link www.phpdoctrine.com
30. * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
31. * @since 1.0
32. * @version $Revision: 2051 $
33. * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
34. * @author Jukka Hassinen <Jukka.Hassinen@BrainAlliance.com>
35. * @author Nicolas Bérard-Nault <nicobn@php.net>
36. */
37. class Doctrine_Import_Builder
38. {
39. /**
40. * @var string $path the path where imported files are being generated
41. */
42. private $path = '';
44. private $suffix = '.php';
46. private static $tpl;
48. public function __construct()
49. {
50. $this->loadTemplate();
51. }
53. /**
54. * setTargetPath
55. *
56. * @param string path the path where imported files are being generated
57. * @return
58. */
59. public function setTargetPath($path)
60. {
61. if ( ! file_exists($path)) {
62. mkdir($path, 0777);
63. }
65. $this->path = $path;
66. }
67. /**
68. * getTargetPath
69. *
70. * @return string the path where imported files are being generated
71. */
72. public function getTargetPath()
73. {
74. return $this->path;
75. }
77. /**
78. * This is a template that was previously in Builder/Record.tpl. Due to the fact
79. * that it was not bundled when compiling, it had to be moved here.
80. *
81. * @return void
82. */
83. public function loadTemplate()
84. {
85. if (isset(self::$tpl)) {
86. return;
87. }
89. self::$tpl =<<<END
90. /**
91. * This class has been auto-generated by the Doctrine ORM Framework
92. */
93. class %s extends Doctrine_Record
94. {
95. public function setTableDefinition()
96. {
97. %s
98. }
99. public function setUp()
100. {
101. %s
102. }
103. }
104. END;
106. }
108. /*
109. * Build the table definition of a Doctrine_Record object
110. *
111. * @param string $table
112. * @param array $tableColumns
113. */
114. public function buildColumnDefinition(array $tableColumns)
115. {
116. $columns = array();
117. $i = 1;
119. foreach ($tableColumns as $name => $column) {
120. $columns[$i] = ' $this->hasColumn(\'' . $name . '\', \'' . $column['type'] . '\'';
121. if ($column['length']) {
122. $columns[$i] .= ', ' . $column['length'];
123. } else {
124. $columns[$i] .= ', null';
125. }
127. $a = array();
129. if (isset($column['default']) && $column['default']) {
130. $a[] = '\'default\' => ' . var_export($column['default'], true);
131. }
132. if (isset($column['notnull']) && $column['notnull']) {
133. $a[] = '\'notnull\' => true';
134. }
135. if (isset($column['primary']) && $column['primary']) {
136. $a[] = '\'primary\' => true';
137. }
138. if (isset($column['autoinc']) && $column['autoinc']) {
139. $a[] = '\'autoincrement\' => true';
140. }
141. if (isset($column['unique']) && $column['unique']) {
142. $a[] = '\'unique\' => true';
143. }
144. if (isset($column['unsigned']) && $column['unsigned']) {
145. $a[] = '\'unsigned\' => true';
146. }
147. if ($column['type'] == 'enum' && isset($column['values']) && $column['values']) {
148. $a[] = '\'values\' => array(' . implode(',', $column['values']) . ')';
149. }
151. if ( ! empty($a)) {
152. $columns[$i] .= ', ' . 'array(';
153. $length = strlen($columns[$i]);
154. $columns[$i] .= implode(',' . PHP_EOL . str_repeat(' ', $length), $a) . ')';
155. }
156. $columns[$i] .= ');';
158. if ($i < (count($tableColumns) - 1)) {
159. $columns[$i] .= PHP_EOL;
160. }
161. $i++;
162. }
164. return implode("\n", $columns);
165. }
166. public function buildRelationDefinition(array $relations)
167. {
168. $ret = array();
169. $i = 0;
170. foreach ($relations as $name => $relation) {
171. $alias = (isset($relation['alias']) && $relation['alias'] !== $name) ? ' as ' . $relation['alias'] : '';
173. if ( ! isset($relation['type'])) {
174. $relation['type'] = Doctrine_Relation::ONE;
175. }
177. if ($relation['type'] === Doctrine_Relation::ONE ||
178. $relation['type'] === Doctrine_Relation::ONE_COMPOSITE) {
179. $ret[$i] = ' $this->hasOne(\'' . $name . $alias . '\'';
180. } else {
181. $ret[$i] = ' $this->hasMany(\'' . $name . $alias . '\'';
182. }
183. $a = array();
185. if (isset($relation['deferred']) && $relation['deferred']) {
186. $a[] = '\'default\' => ' . var_export($relation['deferred'], true);
187. }
188. if (isset($relation['local']) && $relation['local']) {
189. $a[] = '\'local\' => ' . var_export($relation['local'], true);
190. }
191. if (isset($relation['foreign']) && $relation['foreign']) {
192. $a[] = '\'foreign\' => ' . var_export($relation['foreign'], true);
193. }
194. if (isset($relation['onDelete']) && $relation['onDelete']) {
195. $a[] = '\'onDelete\' => ' . var_export($relation['onDelete'], true);
196. }
197. if (isset($relation['onUpdate']) && $relation['onUpdate']) {
198. $a[] = '\'onUpdate\' => ' . var_export($relation['onUpdate'], true);
199. }
200. if ( ! empty($a)) {
201. $ret[$i] .= ', ' . 'array(';
202. $length = strlen($ret[$i]);
203. $ret[$i] .= implode(',' . PHP_EOL . str_repeat(' ', $length), $a) . ')';
204. }
205. $ret[$i] .= ');';
206. $i++;
207. }
208. return implode("\n", $ret);
209. }
212. public function buildDefinition(array $options, array $columns, array $relations = array())
213. {
214. if ( ! isset($options['className'])) {
215. throw new Doctrine_Import_Builder_Exception('Missing class name.');
216. }
218. //$opt = array(0 => str_repeat(' ', 8) . '$this->setTableName(\''. $table .'\');');
220. $content = sprintf(self::$tpl, $options['className'],
221. $this->buildColumnDefinition($columns),
222. $this->buildRelationDefinition($relations));
224. return $content;
225. }
227. public function buildRecord($options, $columns, $relations)
228. {
229. if ( ! isset($options['className'])) {
230. throw new Doctrine_Import_Builder_Exception('Missing class name.');
231. }
233. if ( ! isset($options['fileName'])) {
234. if (empty($this->path)) {
235. $errMsg = 'No build target directory set.';
236. throw new Doctrine_Import_Builder_Exception($errMsg);
237. }
240. if (is_writable($this->path) === false) {
241. $errMsg = 'Build target directory ' . $this->path . ' is not writable.';
242. throw new Doctrine_Import_Builder_Exception($errMsg);
243. }
245. $options['fileName'] = $this->path . DIRECTORY_SEPARATOR . $options['className'] . $this->suffix;
246. }
248. $content = $this->buildDefinition($options, $columns, $relations);
250. $bytes = file_put_contents($options['fileName'], '<?php' . PHP_EOL . $content);
252. if ($bytes === false) {
253. throw new Doctrine_Import_Builder_Exception("Couldn't write file " . $options['fileName']);
254. }
255. }
256. }