Rajout de doctrine/orm
[zf2.biz/galerie.git] / vendor / doctrine / orm / lib / Doctrine / ORM / Tools / ConvertDoctrine1Schema.php
1 <?php
2 /*
3  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14  *
15  * This software consists of voluntary contributions made by many individuals
16  * and is licensed under the MIT license. For more information, see
17  * <http://www.doctrine-project.org>.
18  */
19
20 namespace Doctrine\ORM\Tools;
21
22 use Doctrine\ORM\Mapping\ClassMetadataInfo,
23     Doctrine\ORM\Tools\Export\Driver\AbstractExporter,
24     Doctrine\Common\Util\Inflector;
25
26 /**
27  * Class to help with converting Doctrine 1 schema files to Doctrine 2 mapping files
28  *
29  * 
30  * @link    www.doctrine-project.org
31  * @since   2.0
32  * @author  Guilherme Blanco <guilhermeblanco@hotmail.com>
33  * @author  Jonathan Wage <jonwage@gmail.com>
34  * @author  Roman Borschel <roman@code-factory.org>
35  */
36 class ConvertDoctrine1Schema
37 {
38     private $_legacyTypeMap = array(
39         // TODO: This list may need to be updated
40         'clob' => 'text',
41         'timestamp' => 'datetime',
42         'enum' => 'string'
43     );
44
45     /**
46      * Constructor passes the directory or array of directories
47      * to convert the Doctrine 1 schema files from
48      *
49      * @param array $from
50      * @author Jonathan Wage
51      */
52     public function __construct($from)
53     {
54         $this->_from = (array) $from;
55     }
56
57     /**
58      * Get an array of ClassMetadataInfo instances from the passed
59      * Doctrine 1 schema
60      *
61      * @return array $metadatas  An array of ClassMetadataInfo instances
62      */
63     public function getMetadata()
64     {
65         $schema = array();
66         foreach ($this->_from as $path) {
67             if (is_dir($path)) {
68                 $files = glob($path . '/*.yml');
69                 foreach ($files as $file) {
70                     $schema = array_merge($schema, (array) \Symfony\Component\Yaml\Yaml::parse($file));
71                 }
72             } else {
73                 $schema = array_merge($schema, (array) \Symfony\Component\Yaml\Yaml::parse($path));
74             }
75         }
76
77         $metadatas = array();
78         foreach ($schema as $className => $mappingInformation) {
79             $metadatas[] = $this->_convertToClassMetadataInfo($className, $mappingInformation);
80         }
81
82         return $metadatas;
83     }
84
85     private function _convertToClassMetadataInfo($className, $mappingInformation)
86     {
87         $metadata = new ClassMetadataInfo($className);
88
89         $this->_convertTableName($className, $mappingInformation, $metadata);
90         $this->_convertColumns($className, $mappingInformation, $metadata);
91         $this->_convertIndexes($className, $mappingInformation, $metadata);
92         $this->_convertRelations($className, $mappingInformation, $metadata);
93
94         return $metadata;
95     }
96
97     private function _convertTableName($className, array $model, ClassMetadataInfo $metadata)
98     {
99         if (isset($model['tableName']) && $model['tableName']) {
100             $e = explode('.', $model['tableName']);
101
102             if (count($e) > 1) {
103                 $metadata->table['schema'] = $e[0];
104                 $metadata->table['name'] = $e[1];
105             } else {
106                 $metadata->table['name'] = $e[0];
107             }
108         }
109     }
110
111     private function _convertColumns($className, array $model, ClassMetadataInfo $metadata)
112     {
113         $id = false;
114
115         if (isset($model['columns']) && $model['columns']) {
116             foreach ($model['columns'] as $name => $column) {
117                 $fieldMapping = $this->_convertColumn($className, $name, $column, $metadata);
118
119                 if (isset($fieldMapping['id']) && $fieldMapping['id']) {
120                     $id = true;
121                 }
122             }
123         }
124
125         if ( ! $id) {
126             $fieldMapping = array(
127                 'fieldName' => 'id',
128                 'columnName' => 'id',
129                 'type' => 'integer',
130                 'id' => true
131             );
132             $metadata->mapField($fieldMapping);
133             $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO);
134         }
135     }
136
137     private function _convertColumn($className, $name, $column, ClassMetadataInfo $metadata)
138     {
139         if (is_string($column)) {
140             $string = $column;
141             $column = array();
142             $column['type'] = $string;
143         }
144         if ( ! isset($column['name'])) {
145             $column['name'] = $name;
146         }
147         // check if a column alias was used (column_name as field_name)
148         if (preg_match("/(\w+)\sas\s(\w+)/i", $column['name'], $matches)) {
149             $name = $matches[1];
150             $column['name'] = $name;
151             $column['alias'] = $matches[2];
152         }
153         if (preg_match("/([a-zA-Z]+)\(([0-9]+)\)/", $column['type'], $matches)) {
154             $column['type'] = $matches[1];
155             $column['length'] = $matches[2];
156         }
157         $column['type'] = strtolower($column['type']);
158         // check if legacy column type (1.x) needs to be mapped to a 2.0 one
159         if (isset($this->_legacyTypeMap[$column['type']])) {
160             $column['type'] = $this->_legacyTypeMap[$column['type']];
161         }
162         if ( ! \Doctrine\DBAL\Types\Type::hasType($column['type'])) {
163             throw ToolsException::couldNotMapDoctrine1Type($column['type']);
164         }
165
166         $fieldMapping = array();
167         if (isset($column['primary'])) {
168             $fieldMapping['id'] = true;
169         }
170         $fieldMapping['fieldName'] = isset($column['alias']) ? $column['alias'] : $name;
171         $fieldMapping['columnName'] = $column['name'];
172         $fieldMapping['type'] = $column['type'];
173         if (isset($column['length'])) {
174             $fieldMapping['length'] = $column['length'];
175         }
176         $allowed = array('precision', 'scale', 'unique', 'options', 'notnull', 'version');
177         foreach ($column as $key => $value) {
178             if (in_array($key, $allowed)) {
179                 $fieldMapping[$key] = $value;
180             }
181         }
182
183         $metadata->mapField($fieldMapping);
184
185         if (isset($column['autoincrement'])) {
186             $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO);
187         } else if (isset($column['sequence'])) {
188             $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE);
189             $definition = array(
190                 'sequenceName' => is_array($column['sequence']) ? $column['sequence']['name']:$column['sequence']
191             );
192             if (isset($column['sequence']['size'])) {
193                 $definition['allocationSize'] = $column['sequence']['size'];
194             }
195             if (isset($column['sequence']['value'])) {
196                 $definition['initialValue'] = $column['sequence']['value'];
197             }
198             $metadata->setSequenceGeneratorDefinition($definition);
199         }
200         return $fieldMapping;
201     }
202
203     private function _convertIndexes($className, array $model, ClassMetadataInfo $metadata)
204     {
205         if (isset($model['indexes']) && $model['indexes']) {
206             foreach ($model['indexes'] as $name => $index) {
207                 $type = (isset($index['type']) && $index['type'] == 'unique')
208                     ? 'uniqueConstraints' : 'indexes';
209
210                 $metadata->table[$type][$name] = array(
211                     'columns' => $index['fields']
212                 );
213             }
214         }
215     }
216
217     private function _convertRelations($className, array $model, ClassMetadataInfo $metadata)
218     {
219         if (isset($model['relations']) && $model['relations']) {
220             foreach ($model['relations'] as $name => $relation) {
221                 if ( ! isset($relation['alias'])) {
222                     $relation['alias'] = $name;
223                 }
224                 if ( ! isset($relation['class'])) {
225                     $relation['class'] = $name;
226                 }
227                 if ( ! isset($relation['local'])) {
228                     $relation['local'] = Inflector::tableize($relation['class']);
229                 }
230                 if ( ! isset($relation['foreign'])) {
231                     $relation['foreign'] = 'id';
232                 }
233                 if ( ! isset($relation['foreignAlias'])) {
234                     $relation['foreignAlias'] = $className;
235                 }
236
237                 if (isset($relation['refClass'])) {
238                     $type = 'many';
239                     $foreignType = 'many';
240                     $joinColumns = array();
241                 } else {
242                     $type = isset($relation['type']) ? $relation['type'] : 'one';
243                     $foreignType = isset($relation['foreignType']) ? $relation['foreignType'] : 'many';
244                     $joinColumns = array(
245                         array(
246                             'name' => $relation['local'],
247                             'referencedColumnName' => $relation['foreign'],
248                             'onDelete' => isset($relation['onDelete']) ? $relation['onDelete'] : null,
249                         )
250                     );
251                 }
252
253                 if ($type == 'one' && $foreignType == 'one') {
254                     $method = 'mapOneToOne';
255                 } else if ($type == 'many' && $foreignType == 'many') {
256                     $method = 'mapManyToMany';
257                 } else {
258                     $method = 'mapOneToMany';
259                 }
260
261                 $associationMapping = array();
262                 $associationMapping['fieldName'] = $relation['alias'];
263                 $associationMapping['targetEntity'] = $relation['class'];
264                 $associationMapping['mappedBy'] = $relation['foreignAlias'];
265                 $associationMapping['joinColumns'] = $joinColumns;
266
267                 $metadata->$method($associationMapping);
268             }
269         }
270     }
271 }