PageRenderTime 59ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/htdocs/symfony/2.0.0pr2/src/vendor/doctrine/lib/Doctrine/ORM/Tools/SchemaValidator.php

http://github.com/pmjones/php-framework-benchmarks
PHP | 196 lines | 122 code | 18 blank | 56 comment | 33 complexity | 0cc67b1c9bc5cea301a97b06e1a6c2a5 MD5 | raw file
Possible License(s): LGPL-3.0, Apache-2.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1
  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;
  22. use Doctrine\ORM\EntityManager;
  23. use Doctrine\ORM\Mapping\ManyToManyMapping;
  24. use Doctrine\ORM\Mapping\OneToOneMapping;
  25. /**
  26. * Performs strict validation of the mapping schema
  27. *
  28. * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
  29. * @link www.doctrine-project.com
  30. * @since 1.0
  31. * @version $Revision$
  32. * @author Benjamin Eberlei <kontakt@beberlei.de>
  33. * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
  34. * @author Jonathan Wage <jonwage@gmail.com>
  35. * @author Roman Borschel <roman@code-factory.org>
  36. */
  37. class SchemaValidator
  38. {
  39. /**
  40. * @var EntityManager
  41. */
  42. private $em;
  43. /**
  44. * @param EntityManager $em
  45. */
  46. public function __construct(EntityManager $em)
  47. {
  48. $this->em = $em;
  49. }
  50. /**
  51. * Checks the internal consistency of mapping files.
  52. *
  53. * There are several checks that can't be done at runtime or are to expensive, which can be verified
  54. * with this command. For example:
  55. *
  56. * 1. Check if a relation with "mappedBy" is actually connected to that specified field.
  57. * 2. Check if "mappedBy" and "inversedBy" are consistent to each other.
  58. * 3. Check if "referencedColumnName" attributes are really pointing to primary key columns.
  59. *
  60. * @return array
  61. */
  62. public function validateMapping()
  63. {
  64. $errors = array();
  65. $cmf = $this->em->getMetadataFactory();
  66. $classes = $cmf->getAllMetadata();
  67. foreach ($classes AS $class) {
  68. /* @var $class ClassMetadata */
  69. foreach ($class->associationMappings AS $fieldName => $assoc) {
  70. $ce = array();
  71. if (!$cmf->hasMetadataFor($assoc->targetEntityName)) {
  72. $ce[] = "The target entity '" . $assoc->targetEntityName . "' specified on " . $class->name . '#' . $fieldName . ' is unknown.';
  73. }
  74. if ($assoc->mappedBy && $assoc->inversedBy) {
  75. $ce[] = "The association " . $class . "#" . $fieldName . " cannot be defined as both inverse and owning.";
  76. }
  77. $targetMetadata = $cmf->getMetadataFor($assoc->targetEntityName);
  78. /* @var $assoc AssociationMapping */
  79. if ($assoc->mappedBy) {
  80. if ($targetMetadata->hasField($assoc->mappedBy)) {
  81. $ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the owning side ".
  82. "field " . $assoc->targetEntityName . "#" . $assoc->mappedBy . " which is not defined as association.";
  83. }
  84. if (!$targetMetadata->hasAssociation($assoc->mappedBy)) {
  85. $ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the owning side ".
  86. "field " . $assoc->targetEntityName . "#" . $assoc->mappedBy . " which does not exist.";
  87. } else if ($targetMetadata->associationMappings[$assoc->mappedBy]->inversedBy == null) {
  88. $ce[] = "The field " . $class->name . "#" . $fieldName . " is on the inverse side of a ".
  89. "bi-directional relationship, but the specified mappedBy association on the target-entity ".
  90. $assoc->targetEntityName . "#" . $assoc->mappedBy . " does not contain the required ".
  91. "'inversedBy' attribute.";
  92. } else if ($targetMetadata->associationMappings[$assoc->mappedBy]->inversedBy != $fieldName) {
  93. $ce[] = "The mappings " . $class->name . "#" . $fieldName . " and " .
  94. $assoc->targetEntityName . "#" . $assoc->mappedBy . " are ".
  95. "incosistent with each other.";
  96. }
  97. }
  98. if ($assoc->inversedBy) {
  99. if ($targetMetadata->hasField($assoc->inversedBy)) {
  100. $ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the inverse side ".
  101. "field " . $assoc->targetEntityName . "#" . $assoc->inversedBy . " which is not defined as association.";
  102. }
  103. if (!$targetMetadata->hasAssociation($assoc->inversedBy)) {
  104. $ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the inverse side ".
  105. "field " . $assoc->targetEntityName . "#" . $assoc->inversedBy . " which does not exist.";
  106. } else if ($targetMetadata->associationMappings[$assoc->inversedBy]->mappedBy == null) {
  107. $ce[] = "The field " . $class->name . "#" . $fieldName . " is on the owning side of a ".
  108. "bi-directional relationship, but the specified mappedBy association on the target-entity ".
  109. $assoc->targetEntityName . "#" . $assoc->mappedBy . " does not contain the required ".
  110. "'inversedBy' attribute.";
  111. } else if ($targetMetadata->associationMappings[$assoc->inversedBy]->mappedBy != $fieldName) {
  112. $ce[] = "The mappings " . $class->name . "#" . $fieldName . " and " .
  113. $assoc->targetEntityName . "#" . $assoc->inversedBy . " are ".
  114. "incosistent with each other.";
  115. }
  116. }
  117. if ($assoc->isOwningSide) {
  118. if ($assoc instanceof ManyToManyMapping) {
  119. foreach ($assoc->joinTable['joinColumns'] AS $joinColumn) {
  120. if (!isset($class->fieldNames[$joinColumn['referencedColumnName']])) {
  121. $ce[] = "The referenced column name '" . $joinColumn['referencedColumnName'] . "' does not " .
  122. "have a corresponding field with this column name on the class '" . $class->name . "'.";
  123. break;
  124. }
  125. $fieldName = $class->fieldNames[$joinColumn['referencedColumnName']];
  126. if (!in_array($fieldName, $class->identifier)) {
  127. $ce[] = "The referenced column name '" . $joinColumn['referencedColumnName'] . "' " .
  128. "has to be a primary key column.";
  129. }
  130. }
  131. foreach ($assoc->joinTable['inverseJoinColumns'] AS $inverseJoinColumn) {
  132. $targetClass = $cmf->getMetadataFor($assoc->targetEntityName);
  133. if (!isset($targetClass->fieldNames[$inverseJoinColumn['referencedColumnName']])) {
  134. $ce[] = "The inverse referenced column name '" . $inverseJoinColumn['referencedColumnName'] . "' does not " .
  135. "have a corresponding field with this column name on the class '" . $targetClass->name . "'.";
  136. break;
  137. }
  138. $fieldName = $targetClass->fieldNames[$inverseJoinColumn['referencedColumnName']];
  139. if (!in_array($fieldName, $targetClass->identifier)) {
  140. $ce[] = "The referenced column name '" . $inverseJoinColumn['referencedColumnName'] . "' " .
  141. "has to be a primary key column.";
  142. }
  143. }
  144. } else if ($assoc instanceof OneToOneMapping) {
  145. foreach ($assoc->joinColumns AS $joinColumn) {
  146. $targetClass = $cmf->getMetadataFor($assoc->targetEntityName);
  147. if (!isset($targetClass->fieldNames[$joinColumn['referencedColumnName']])) {
  148. $ce[] = "The referenced column name '" . $joinColumn['referencedColumnName'] . "' does not " .
  149. "have a corresponding field with this column name on the class '" . $targetClass->name . "'.";
  150. break;
  151. }
  152. $fieldName = $targetClass->fieldNames[$joinColumn['referencedColumnName']];
  153. if (!in_array($fieldName, $targetClass->identifier)) {
  154. $ce[] = "The referenced column name '" . $joinColumn['referencedColumnName'] . "' " .
  155. "has to be a primary key column.";
  156. }
  157. }
  158. }
  159. }
  160. if ($ce) {
  161. $errors[$class->name] = $ce;
  162. }
  163. }
  164. }
  165. return $errors;
  166. }
  167. /**
  168. * Check if the Database Schema is in sync with the current metadata state.
  169. *
  170. * @return bool
  171. */
  172. public function schemaInSyncWithMetadata()
  173. {
  174. $schemaTool = new SchemaTool($this->em);
  175. $allMetadata = $this->em->getMetadataFactory()->getAllMetadata();
  176. return (count($schemaTool->getUpdateSchemaSql($allMetadata, false)) == 0);
  177. }
  178. }