XmlExporter.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  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.doctrine-project.org>.
  20. */
  21. namespace Doctrine\ORM\Tools\Export\Driver;
  22. use Doctrine\ORM\Mapping\ClassMetadataInfo;
  23. /**
  24. * ClassMetadata exporter for Doctrine XML mapping files
  25. *
  26. * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
  27. * @link www.doctrine-project.org
  28. * @since 2.0
  29. * @version $Revision$
  30. * @author Jonathan Wage <jonwage@gmail.com>
  31. */
  32. class XmlExporter extends AbstractExporter
  33. {
  34. protected $_extension = '.dcm.xml';
  35. /**
  36. * Converts a single ClassMetadata instance to the exported format
  37. * and returns it
  38. *
  39. * @param ClassMetadataInfo $metadata
  40. * @return mixed $exported
  41. */
  42. public function exportClassMetadata(ClassMetadataInfo $metadata)
  43. {
  44. $xml = new \SimpleXmlElement("<?xml version=\"1.0\" encoding=\"utf-8\"?><doctrine-mapping ".
  45. "xmlns=\"http://doctrine-project.org/schemas/orm/doctrine-mapping\" " .
  46. "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ".
  47. "xsi:schemaLocation=\"http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd\" />");
  48. /*$xml->addAttribute('xmlns', 'http://doctrine-project.org/schemas/orm/doctrine-mapping');
  49. $xml->addAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
  50. $xml->addAttribute('xsi:schemaLocation', 'http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd');*/
  51. if ($metadata->isMappedSuperclass) {
  52. $root = $xml->addChild('mapped-superclass');
  53. } else {
  54. $root = $xml->addChild('entity');
  55. }
  56. if ($metadata->customRepositoryClassName) {
  57. $root->addAttribute('repository-class', $metadata->customRepositoryClassName);
  58. }
  59. $root->addAttribute('name', $metadata->name);
  60. if (isset($metadata->table['name'])) {
  61. $root->addAttribute('table', $metadata->table['name']);
  62. }
  63. if (isset($metadata->table['schema'])) {
  64. $root->addAttribute('schema', $metadata->table['schema']);
  65. }
  66. if (isset($metadata->table['inheritance-type'])) {
  67. $root->addAttribute('inheritance-type', $metadata->table['inheritance-type']);
  68. }
  69. if ($metadata->discriminatorColumn) {
  70. $discriminatorColumnXml = $root->addChild('discriminiator-column');
  71. $discriminatorColumnXml->addAttribute('name', $metadata->discriminatorColumn['name']);
  72. $discriminatorColumnXml->addAttribute('type', $metadata->discriminatorColumn['type']);
  73. $discriminatorColumnXml->addAttribute('length', $metadata->discriminatorColumn['length']);
  74. }
  75. if ($metadata->discriminatorMap) {
  76. $discriminatorMapXml = $root->addChild('discriminator-map');
  77. foreach ($metadata->discriminatorMap as $value => $className) {
  78. $discriminatorMappingXml = $discriminatorMapXml->addChild('discriminator-mapping');
  79. $discriminatorMappingXml->addAttribute('value', $value);
  80. $discriminatorMappingXml->addAttribute('class', $className);
  81. }
  82. }
  83. $root->addChild('change-tracking-policy', $this->_getChangeTrackingPolicyString($metadata->changeTrackingPolicy));
  84. if (isset($metadata->table['indexes'])) {
  85. $indexesXml = $root->addChild('indexes');
  86. foreach ($metadata->table['indexes'] as $name => $index) {
  87. $indexXml = $indexesXml->addChild('index');
  88. $indexXml->addAttribute('name', $name);
  89. $indexXml->addAttribute('columns', implode(',', $index['columns']));
  90. }
  91. }
  92. if (isset($metadata->table['uniqueConstraints'])) {
  93. $uniqueConstraintsXml = $root->addChild('unique-constraints');
  94. foreach ($metadata->table['uniqueConstraints'] as $unique) {
  95. $uniqueConstraintXml = $uniqueConstraintsXml->addChild('unique-constraint');
  96. $uniqueConstraintXml->addAttribute('name', $unique['name']);
  97. $uniqueConstraintXml->addAttribute('columns', implode(',', $unique['columns']));
  98. }
  99. }
  100. $fields = $metadata->fieldMappings;
  101. $id = array();
  102. foreach ($fields as $name => $field) {
  103. if (isset($field['id']) && $field['id']) {
  104. $id[$name] = $field;
  105. unset($fields[$name]);
  106. }
  107. }
  108. if ( ! $metadata->isIdentifierComposite && $idGeneratorType = $this->_getIdGeneratorTypeString($metadata->generatorType)) {
  109. $id[$metadata->getSingleIdentifierFieldName()]['generator']['strategy'] = $idGeneratorType;
  110. }
  111. if ($id) {
  112. foreach ($id as $field) {
  113. $idXml = $root->addChild('id');
  114. $idXml->addAttribute('name', $field['fieldName']);
  115. $idXml->addAttribute('type', $field['type']);
  116. if (isset($field['columnName'])) {
  117. $idXml->addAttribute('column', $field['columnName']);
  118. }
  119. if (isset($field['associationKey']) && $field['associationKey']) {
  120. $idXml->addAttribute('association-key', 'true');
  121. }
  122. if ($idGeneratorType = $this->_getIdGeneratorTypeString($metadata->generatorType)) {
  123. $generatorXml = $idXml->addChild('generator');
  124. $generatorXml->addAttribute('strategy', $idGeneratorType);
  125. }
  126. }
  127. }
  128. if ($fields) {
  129. foreach ($fields as $field) {
  130. $fieldXml = $root->addChild('field');
  131. $fieldXml->addAttribute('name', $field['fieldName']);
  132. $fieldXml->addAttribute('type', $field['type']);
  133. if (isset($field['columnName'])) {
  134. $fieldXml->addAttribute('column', $field['columnName']);
  135. }
  136. if (isset($field['length'])) {
  137. $fieldXml->addAttribute('length', $field['length']);
  138. }
  139. if (isset($field['precision'])) {
  140. $fieldXml->addAttribute('precision', $field['precision']);
  141. }
  142. if (isset($field['scale'])) {
  143. $fieldXml->addAttribute('scale', $field['scale']);
  144. }
  145. if (isset($field['unique']) && $field['unique']) {
  146. $fieldXml->addAttribute('unique', $field['unique']);
  147. }
  148. if (isset($field['options'])) {
  149. $optionsXml = $fieldXml->addChild('options');
  150. foreach ($field['options'] as $key => $value) {
  151. $optionsXml->addAttribute($key, $value);
  152. }
  153. }
  154. if (isset($field['version'])) {
  155. $fieldXml->addAttribute('version', $field['version']);
  156. }
  157. if (isset($field['columnDefinition'])) {
  158. $fieldXml->addAttribute('column-definition', $field['columnDefinition']);
  159. }
  160. }
  161. }
  162. foreach ($metadata->associationMappings as $name => $associationMapping) {
  163. if ($associationMapping['type'] == ClassMetadataInfo::ONE_TO_ONE) {
  164. $associationMappingXml = $root->addChild('one-to-one');
  165. } else if ($associationMapping['type'] == ClassMetadataInfo::MANY_TO_ONE) {
  166. $associationMappingXml = $root->addChild('many-to-one');
  167. } else if ($associationMapping['type'] == ClassMetadataInfo::ONE_TO_MANY) {
  168. $associationMappingXml = $root->addChild('one-to-many');
  169. } else if ($associationMapping['type'] == ClassMetadataInfo::MANY_TO_MANY) {
  170. $associationMappingXml = $root->addChild('many-to-many');
  171. }
  172. $associationMappingXml->addAttribute('field', $associationMapping['fieldName']);
  173. $associationMappingXml->addAttribute('target-entity', $associationMapping['targetEntity']);
  174. if (isset($associationMapping['mappedBy'])) {
  175. $associationMappingXml->addAttribute('mapped-by', $associationMapping['mappedBy']);
  176. }
  177. if (isset($associationMapping['inversedBy'])) {
  178. $associationMappingXml->addAttribute('inversed-by', $associationMapping['inversedBy']);
  179. }
  180. if (isset($associationMapping['orphanRemoval'])) {
  181. $associationMappingXml->addAttribute('orphan-removal', $associationMapping['orphanRemoval']);
  182. }
  183. if (isset($associationMapping['joinTable']) && $associationMapping['joinTable']) {
  184. $joinTableXml = $associationMappingXml->addChild('join-table');
  185. $joinTableXml->addAttribute('name', $associationMapping['joinTable']['name']);
  186. $joinColumnsXml = $joinTableXml->addChild('join-columns');
  187. foreach ($associationMapping['joinTable']['joinColumns'] as $joinColumn) {
  188. $joinColumnXml = $joinColumnsXml->addChild('join-column');
  189. $joinColumnXml->addAttribute('name', $joinColumn['name']);
  190. $joinColumnXml->addAttribute('referenced-column-name', $joinColumn['referencedColumnName']);
  191. if (isset($joinColumn['onDelete'])) {
  192. $joinColumnXml->addAttribute('on-delete', $joinColumn['onDelete']);
  193. }
  194. }
  195. $inverseJoinColumnsXml = $joinTableXml->addChild('inverse-join-columns');
  196. foreach ($associationMapping['joinTable']['inverseJoinColumns'] as $inverseJoinColumn) {
  197. $inverseJoinColumnXml = $inverseJoinColumnsXml->addChild('join-column');
  198. $inverseJoinColumnXml->addAttribute('name', $inverseJoinColumn['name']);
  199. $inverseJoinColumnXml->addAttribute('referenced-column-name', $inverseJoinColumn['referencedColumnName']);
  200. if (isset($inverseJoinColumn['onDelete'])) {
  201. $inverseJoinColumnXml->addAttribute('on-delete', $inverseJoinColumn['onDelete']);
  202. }
  203. if (isset($inverseJoinColumn['columnDefinition'])) {
  204. $inverseJoinColumnXml->addAttribute('column-definition', $inverseJoinColumn['columnDefinition']);
  205. }
  206. if (isset($inverseJoinColumn['nullable'])) {
  207. $inverseJoinColumnXml->addAttribute('nullable', $inverseJoinColumn['nullable']);
  208. }
  209. if (isset($inverseJoinColumn['orderBy'])) {
  210. $inverseJoinColumnXml->addAttribute('order-by', $inverseJoinColumn['orderBy']);
  211. }
  212. }
  213. }
  214. if (isset($associationMapping['joinColumns'])) {
  215. $joinColumnsXml = $associationMappingXml->addChild('join-columns');
  216. foreach ($associationMapping['joinColumns'] as $joinColumn) {
  217. $joinColumnXml = $joinColumnsXml->addChild('join-column');
  218. $joinColumnXml->addAttribute('name', $joinColumn['name']);
  219. $joinColumnXml->addAttribute('referenced-column-name', $joinColumn['referencedColumnName']);
  220. if (isset($joinColumn['onDelete'])) {
  221. $joinColumnXml->addAttribute('on-delete', $joinColumn['onDelete']);
  222. }
  223. if (isset($joinColumn['columnDefinition'])) {
  224. $joinColumnXml->addAttribute('column-definition', $joinColumn['columnDefinition']);
  225. }
  226. if (isset($joinColumn['nullable'])) {
  227. $joinColumnXml->addAttribute('nullable', $joinColumn['nullable']);
  228. }
  229. }
  230. }
  231. if (isset($associationMapping['orderBy'])) {
  232. $orderByXml = $associationMappingXml->addChild('order-by');
  233. foreach ($associationMapping['orderBy'] as $name => $direction) {
  234. $orderByFieldXml = $orderByXml->addChild('order-by-field');
  235. $orderByFieldXml->addAttribute('name', $name);
  236. $orderByFieldXml->addAttribute('direction', $direction);
  237. }
  238. }
  239. $cascade = array();
  240. if ($associationMapping['isCascadeRemove']) {
  241. $cascade[] = 'cascade-remove';
  242. }
  243. if ($associationMapping['isCascadePersist']) {
  244. $cascade[] = 'cascade-persist';
  245. }
  246. if ($associationMapping['isCascadeRefresh']) {
  247. $cascade[] = 'cascade-refresh';
  248. }
  249. if ($associationMapping['isCascadeMerge']) {
  250. $cascade[] = 'cascade-merge';
  251. }
  252. if ($associationMapping['isCascadeDetach']) {
  253. $cascade[] = 'cascade-detach';
  254. }
  255. if (count($cascade) === 5) {
  256. $cascade = array('cascade-all');
  257. }
  258. if ($cascade) {
  259. $cascadeXml = $associationMappingXml->addChild('cascade');
  260. foreach ($cascade as $type) {
  261. $cascadeXml->addChild($type);
  262. }
  263. }
  264. }
  265. if (isset($metadata->lifecycleCallbacks)) {
  266. $lifecycleCallbacksXml = $root->addChild('lifecycle-callbacks');
  267. foreach ($metadata->lifecycleCallbacks as $name => $methods) {
  268. foreach ($methods as $method) {
  269. $lifecycleCallbackXml = $lifecycleCallbacksXml->addChild('lifecycle-callback');
  270. $lifecycleCallbackXml->addAttribute('type', $name);
  271. $lifecycleCallbackXml->addAttribute('method', $method);
  272. }
  273. }
  274. }
  275. return $this->_asXml($xml);
  276. }
  277. /**
  278. * @param \SimpleXMLElement $simpleXml
  279. * @return string $xml
  280. */
  281. private function _asXml($simpleXml)
  282. {
  283. $dom = new \DOMDocument('1.0', 'UTF-8');
  284. $dom->loadXML($simpleXml->asXML());
  285. $dom->formatOutput = true;
  286. $result = $dom->saveXML();
  287. return $result;
  288. }
  289. }