MappedEventSubscriber.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. <?php
  2. namespace Gedmo\Mapping;
  3. use Doctrine\Common\Annotations\AnnotationReader;
  4. use Doctrine\Common\Annotations\Reader;
  5. use Gedmo\Mapping\ExtensionMetadataFactory,
  6. Doctrine\Common\EventSubscriber,
  7. Doctrine\Common\Persistence\ObjectManager,
  8. Doctrine\Common\Persistence\Mapping\ClassMetadata,
  9. Doctrine\Common\ClassLoader,
  10. Doctrine\Common\EventArgs;
  11. /**
  12. * This is extension of event subscriber class and is
  13. * used specifically for handling the extension metadata
  14. * mapping for extensions.
  15. *
  16. * It dries up some reusable code which is common for
  17. * all extensions who mapps additional metadata through
  18. * extended drivers
  19. *
  20. * @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
  21. * @package Gedmo.Mapping
  22. * @subpackage MappedEventSubscriber
  23. * @link http://www.gediminasm.org
  24. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  25. */
  26. abstract class MappedEventSubscriber implements EventSubscriber
  27. {
  28. /**
  29. * List of cached object configurations
  30. *
  31. * @var array
  32. */
  33. protected $configurations = array();
  34. /**
  35. * ExtensionMetadataFactory used to read the extension
  36. * metadata through the extension drivers
  37. *
  38. * @var Gedmo\Mapping\ExtensionMetadataFactory
  39. */
  40. private $extensionMetadataFactory = array();
  41. /**
  42. * List of event adapters used for this listener
  43. *
  44. * @var array
  45. */
  46. private $adapters = array();
  47. /**
  48. * Custom annotation reader
  49. *
  50. * @var object
  51. */
  52. private $annotationReader;
  53. /**
  54. * Get an event adapter to handle event specific
  55. * methods
  56. *
  57. * @param EventArgs $args
  58. * @throws \Gedmo\Exception\InvalidArgumentException - if event is not recognized
  59. * @return \Gedmo\Mapping\Event\AdapterInterface
  60. */
  61. protected function getEventAdapter(EventArgs $args)
  62. {
  63. $class = get_class($args);
  64. if (preg_match('@Doctrine\\\([^\\\]+)@', $class, $m) && in_array($m[1], array('ODM', 'ORM'))) {
  65. if (!isset($this->adapters[$m[1]])) {
  66. $adapterClass = $this->getNamespace() . '\\Mapping\\Event\\Adapter\\' . $m[1];
  67. if (!class_exists($adapterClass)) {
  68. $adapterClass = 'Gedmo\\Mapping\\Event\\Adapter\\'.$m[1];
  69. }
  70. $this->adapters[$m[1]] = new $adapterClass;
  71. }
  72. $this->adapters[$m[1]]->setEventArgs($args);
  73. return $this->adapters[$m[1]];
  74. } else {
  75. throw new \Gedmo\Exception\InvalidArgumentException('Event mapper does not support event arg class: '.$class);
  76. }
  77. }
  78. /**
  79. * Get the configuration for specific object class
  80. * if cache driver is present it scans it also
  81. *
  82. * @param ObjectManager $objectManager
  83. * @param string $class
  84. * @return array
  85. */
  86. public function getConfiguration(ObjectManager $objectManager, $class) {
  87. $config = array();
  88. if (isset($this->configurations[$class])) {
  89. $config = $this->configurations[$class];
  90. } else {
  91. $cacheDriver = $objectManager->getMetadataFactory()->getCacheDriver();
  92. $cacheId = ExtensionMetadataFactory::getCacheId($class, $this->getNamespace());
  93. if ($cacheDriver && ($cached = $cacheDriver->fetch($cacheId)) !== false) {
  94. $this->configurations[$class] = $cached;
  95. $config = $cached;
  96. }
  97. }
  98. return $config;
  99. }
  100. /**
  101. * Get extended metadata mapping reader
  102. *
  103. * @param ObjectManager $objectManager
  104. * @return Gedmo\Mapping\ExtensionMetadataFactory
  105. */
  106. public function getExtensionMetadataFactory(ObjectManager $objectManager)
  107. {
  108. $oid = spl_object_hash($objectManager);
  109. if (!isset($this->extensionMetadataFactory[$oid])) {
  110. if (is_null($this->annotationReader)) {
  111. // create default annotation reader for extensions
  112. $this->annotationReader = new AnnotationReader;
  113. $this->annotationReader->setAutoloadAnnotations(true);
  114. if (!$this->annotationReader instanceof Reader) {
  115. $this->annotationReader->setAnnotationNamespaceAlias('Gedmo\\Mapping\\Annotation\\', 'gedmo');
  116. }
  117. }
  118. $this->extensionMetadataFactory[$oid] = new ExtensionMetadataFactory(
  119. $objectManager,
  120. $this->getNamespace(),
  121. $this->annotationReader
  122. );
  123. }
  124. return $this->extensionMetadataFactory[$oid];
  125. }
  126. /**
  127. * Set annotation reader class
  128. * since older doctrine versions do not provide an interface
  129. * it must provide these methods:
  130. * getClassAnnotations([reflectionClass])
  131. * getClassAnnotation([reflectionClass], [name])
  132. * getPropertyAnnotations([reflectionProperty])
  133. * getPropertyAnnotation([reflectionProperty], [name])
  134. *
  135. * @param object $reader - annotation reader class
  136. */
  137. public function setAnnotationReader($reader)
  138. {
  139. $this->annotationReader = $reader;
  140. }
  141. /**
  142. * Scans the objects for extended annotations
  143. * event subscribers must subscribe to loadClassMetadata event
  144. *
  145. * @param ObjectManager $objectManager
  146. * @param ClassMetadata $metadata
  147. * @return void
  148. */
  149. public function loadMetadataForObjectClass(ObjectManager $objectManager, ClassMetadata $metadata)
  150. {
  151. $factory = $this->getExtensionMetadataFactory($objectManager);
  152. $config = $factory->getExtensionMetadata($metadata);
  153. if ($config) {
  154. $this->configurations[$metadata->name] = $config;
  155. }
  156. }
  157. /**
  158. * Get the namespace of extension event subscriber.
  159. * used for cache id of extensions also to know where
  160. * to find Mapping drivers and event adapters
  161. *
  162. * @return string
  163. */
  164. abstract protected function getNamespace();
  165. }