LogEntryRepository.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. <?php
  2. namespace Gedmo\Loggable\Entity\Repository;
  3. use Doctrine\ORM\EntityRepository;
  4. use Gedmo\Loggable\LoggableListener;
  5. /**
  6. * The LogEntryRepository has some useful functions
  7. * to interact with log entries.
  8. *
  9. * @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
  10. * @package Gedmo\Loggable\Entity\Repository
  11. * @subpackage LogEntryRepository
  12. * @link http://www.gediminasm.org
  13. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  14. */
  15. class LogEntryRepository extends EntityRepository
  16. {
  17. /**
  18. * Currently used loggable listener
  19. *
  20. * @var LoggableListener
  21. */
  22. private $listener;
  23. /**
  24. * Loads all log entries for the
  25. * given $entity
  26. *
  27. * @param object $entity
  28. * @return array
  29. */
  30. public function getLogEntries($entity)
  31. {
  32. $q = $this->getLogEntriesQuery($entity);
  33. return $q->getResult();
  34. }
  35. /**
  36. * Get the query for loading of log entries
  37. *
  38. * @param object $entity
  39. * @return Query
  40. */
  41. public function getLogEntriesQuery($entity)
  42. {
  43. $objectClass = get_class($entity);
  44. $objectMeta = $this->_em->getClassMetadata($objectClass);
  45. $meta = $this->getClassMetadata();
  46. $dql = "SELECT log FROM {$meta->name} log";
  47. $dql .= " WHERE log.objectId = :objectId";
  48. $dql .= " AND log.objectClass = :objectClass";
  49. $dql .= " ORDER BY log.version DESC";
  50. $identifierField = $objectMeta->getSingleIdentifierFieldName();
  51. $objectId = $objectMeta->getReflectionProperty($identifierField)->getValue($entity);
  52. $q = $this->_em->createQuery($dql);
  53. $q->setParameters(compact('objectId', 'objectClass', 'order'));
  54. return $q;
  55. }
  56. /**
  57. * Reverts given $entity to $revision by
  58. * restoring all fields from that $revision.
  59. * After this operation you will need to
  60. * persist and flush the $entity.
  61. *
  62. * @param object $entity
  63. * @param integer $version
  64. * @throws \Gedmo\Exception\UnexpectedValueException
  65. * @return void
  66. */
  67. public function revert($entity, $version = 1)
  68. {
  69. $objectClass = get_class($entity);
  70. $objectMeta = $this->_em->getClassMetadata($objectClass);
  71. $meta = $this->getClassMetadata();
  72. $dql = "SELECT log FROM {$meta->name} log";
  73. $dql .= " WHERE log.objectId = :objectId";
  74. $dql .= " AND log.objectClass = :objectClass";
  75. $dql .= " AND log.version <= :version";
  76. $dql .= " ORDER BY log.version ASC";
  77. $identifierField = $objectMeta->getSingleIdentifierFieldName();
  78. $objectId = $objectMeta->getReflectionProperty($identifierField)->getValue($entity);
  79. $q = $this->_em->createQuery($dql);
  80. $q->setParameters(compact('objectId', 'objectClass', 'version'));
  81. $logs = $q->getResult();
  82. if ($logs) {
  83. $config = $this->getLoggableListener()->getConfiguration($this->_em, $objectMeta->name);
  84. $fields = $config['versioned'];
  85. $filled = false;
  86. while (($log = array_pop($logs)) && !$filled) {
  87. if ($data = $log->getData()) {
  88. foreach ($data as $field => $value) {
  89. if (in_array($field, $fields)) {
  90. if ($objectMeta->isSingleValuedAssociation($field)) {
  91. $mapping = $objectMeta->getAssociationMapping($field);
  92. $value = $value ? $this->_em->getReference($mapping['targetEntity'], $value) : null;
  93. }
  94. $objectMeta->getReflectionProperty($field)->setValue($entity, $value);
  95. unset($fields[array_search($field, $fields)]);
  96. }
  97. }
  98. }
  99. $filled = count($fields) === 0;
  100. }
  101. if (count($fields)) {
  102. throw new \Gedmo\Exception\UnexpectedValueException('Cound not fully revert the entity to version: '.$version);
  103. }
  104. } else {
  105. throw new \Gedmo\Exception\UnexpectedValueException('Count not find any log entries under version: '.$version);
  106. }
  107. }
  108. /**
  109. * Get the currently used LoggableListener
  110. *
  111. * @throws \Gedmo\Exception\RuntimeException - if listener is not found
  112. * @return LoggableListener
  113. */
  114. private function getLoggableListener()
  115. {
  116. if (is_null($this->listener)) {
  117. foreach ($this->_em->getEventManager()->getListeners() as $event => $listeners) {
  118. foreach ($listeners as $hash => $listener) {
  119. if ($listener instanceof LoggableListener) {
  120. $this->listener = $listener;
  121. break;
  122. }
  123. }
  124. if ($this->listener) {
  125. break;
  126. }
  127. }
  128. if (is_null($this->listener)) {
  129. throw new \Gedmo\Exception\RuntimeException('The loggable listener could not be found');
  130. }
  131. }
  132. return $this->listener;
  133. }
  134. }