Annotation.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. <?php
  2. namespace Gedmo\Tree\Mapping\Driver;
  3. use Gedmo\Mapping\Driver,
  4. Doctrine\Common\Annotations\AnnotationReader,
  5. Doctrine\ORM\Mapping\ClassMetadataInfo,
  6. Gedmo\Tree\Mapping\MappingException;
  7. /**
  8. * This is an annotation mapping driver for Tree
  9. * behavioral extension. Used for extraction of extended
  10. * metadata from Annotations specificaly for Tree
  11. * extension.
  12. *
  13. * @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
  14. * @package Gedmo.Tree.Mapping.Driver
  15. * @subpackage Annotation
  16. * @link http://www.gediminasm.org
  17. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  18. */
  19. class Annotation implements Driver
  20. {
  21. /**
  22. * Annotation to mark field as one which will store left value
  23. */
  24. const ANNOTATION_LEFT = 'Gedmo\Tree\Mapping\TreeLeft';
  25. /**
  26. * Annotation to mark field as one which will store right value
  27. */
  28. const ANNOTATION_RIGHT = 'Gedmo\Tree\Mapping\TreeRight';
  29. /**
  30. * Annotation to mark relative parent field
  31. */
  32. const ANNOTATION_PARENT = 'Gedmo\Tree\Mapping\TreeParent';
  33. /**
  34. * Annotation to mark node level
  35. */
  36. const ANNOTATION_LEVEL = 'Gedmo\Tree\Mapping\TreeLevel';
  37. /**
  38. * List of types which are valid for timestamp
  39. *
  40. * @var array
  41. */
  42. private $_validTypes = array(
  43. 'integer',
  44. 'smallint',
  45. 'bigint'
  46. );
  47. /**
  48. * {@inheritDoc}
  49. */
  50. public function validateFullMetadata(ClassMetadataInfo $meta, array $config)
  51. {
  52. if ($config) {
  53. $missingFields = array();
  54. if (!isset($config['parent'])) {
  55. $missingFields[] = 'ancestor';
  56. }
  57. if (!isset($config['left'])) {
  58. $missingFields[] = 'left';
  59. }
  60. if (!isset($config['right'])) {
  61. $missingFields[] = 'right';
  62. }
  63. if ($missingFields) {
  64. throw MappingException::missingMetaProperties($missingFields, $meta->name);
  65. }
  66. }
  67. }
  68. /**
  69. * {@inheritDoc}
  70. */
  71. public function readExtendedMetadata(ClassMetadataInfo $meta, array &$config) {
  72. require_once __DIR__ . '/../Annotations.php';
  73. $reader = new AnnotationReader();
  74. $reader->setAnnotationNamespaceAlias('Gedmo\Tree\Mapping\\', 'gedmo');
  75. $class = $meta->getReflectionClass();
  76. // property annotations
  77. foreach ($class->getProperties() as $property) {
  78. if ($meta->isMappedSuperclass && !$property->isPrivate() ||
  79. $meta->isInheritedField($property->name) ||
  80. $meta->isInheritedAssociation($property->name)
  81. ) {
  82. continue;
  83. }
  84. // left
  85. if ($left = $reader->getPropertyAnnotation($property, self::ANNOTATION_LEFT)) {
  86. $field = $property->getName();
  87. if (!$meta->hasField($field)) {
  88. throw MappingException::fieldMustBeMapped($field, $meta->name);
  89. }
  90. if (!$this->_isValidField($meta, $field)) {
  91. throw MappingException::notValidFieldType($field, $meta->name);
  92. }
  93. $config['left'] = $field;
  94. }
  95. // right
  96. if ($right = $reader->getPropertyAnnotation($property, self::ANNOTATION_RIGHT)) {
  97. $field = $property->getName();
  98. if (!$meta->hasField($field)) {
  99. throw MappingException::fieldMustBeMapped($field, $meta->name);
  100. }
  101. if (!$this->_isValidField($meta, $field)) {
  102. throw MappingException::notValidFieldType($field, $meta->name);
  103. }
  104. $config['right'] = $field;
  105. }
  106. // ancestor/parent
  107. if ($parent = $reader->getPropertyAnnotation($property, self::ANNOTATION_PARENT)) {
  108. $field = $property->getName();
  109. if (!$meta->isSingleValuedAssociation($field)) {
  110. throw MappingException::parentFieldNotMappedOrRelated($field, $meta->name);
  111. }
  112. $config['parent'] = $field;
  113. }
  114. // level
  115. if ($parent = $reader->getPropertyAnnotation($property, self::ANNOTATION_LEVEL)) {
  116. $field = $property->getName();
  117. if (!$meta->hasField($field)) {
  118. throw MappingException::fieldMustBeMapped($field, $meta->name);
  119. }
  120. if (!$this->_isValidField($meta, $field)) {
  121. throw MappingException::notValidFieldType($field, $meta->name);
  122. }
  123. $config['level'] = $field;
  124. }
  125. }
  126. }
  127. /**
  128. * Checks if $field type is valid
  129. *
  130. * @param ClassMetadataInfo $meta
  131. * @param string $field
  132. * @return boolean
  133. */
  134. protected function _isValidField(ClassMetadataInfo $meta, $field)
  135. {
  136. return in_array($meta->getTypeOfField($field), $this->_validTypes);
  137. }
  138. }