SoftDeleteableWalker.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. <?php
  2. namespace Gedmo\SoftDeleteable\Query\TreeWalker;
  3. use Doctrine\ORM\Query\SqlWalker;
  4. use Doctrine\ORM\Query\AST\DeleteStatement;
  5. use Doctrine\ORM\Query\AST\DeleteClause;
  6. use Doctrine\ORM\Query\AST\UpdateClause;
  7. use Doctrine\ORM\Query\AST\UpdateItem;
  8. use Doctrine\ORM\Query\Exec\SingleTableDeleteUpdateExecutor;
  9. use Doctrine\ORM\Query\AST\PathExpression;
  10. use Gedmo\SoftDeleteable\SoftDeleteableListener;
  11. use Gedmo\SoftDeleteable\Query\TreeWalker\Exec\MultiTableDeleteExecutor;
  12. /**
  13. * This SqlWalker is needed when you need to use a DELETE DQL query.
  14. * It will update the "deletedAt" field with the actual date, instead
  15. * of actually deleting it.
  16. *
  17. * @author Gustavo Falco <comfortablynumb84@gmail.com>
  18. * @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
  19. * @package Gedmo.Query.TreeWalker
  20. * @subpackage SoftDeleteableWalker
  21. * @link http://www.gediminasm.org
  22. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  23. */
  24. class SoftDeleteableWalker extends SqlWalker
  25. {
  26. protected $conn;
  27. protected $platform;
  28. protected $listener;
  29. protected $configuration;
  30. protected $alias;
  31. protected $deletedAtField;
  32. protected $meta;
  33. /**
  34. * {@inheritDoc}
  35. */
  36. public function __construct($query, $parserResult, array $queryComponents)
  37. {
  38. parent::__construct($query, $parserResult, $queryComponents);
  39. $this->conn = $this->getConnection();
  40. $this->platform = $this->conn->getDatabasePlatform();
  41. $this->listener = $this->getSoftDeleteableListener();
  42. $this->extractComponents($queryComponents);
  43. }
  44. /**
  45. * {@inheritDoc}
  46. */
  47. public function getExecutor($AST)
  48. {
  49. switch (true) {
  50. case ($AST instanceof DeleteStatement):
  51. $primaryClass = $this->getEntityManager()->getClassMetadata($AST->deleteClause->abstractSchemaName);
  52. return ($primaryClass->isInheritanceTypeJoined())
  53. ? new MultiTableDeleteExecutor($AST, $this, $this->meta, $this->platform, $this->configuration)
  54. : new SingleTableDeleteUpdateExecutor($AST, $this);
  55. default:
  56. throw new \Gedmo\Exception\UnexpectedValueException('SoftDeleteable walker should be used only on delete statement');
  57. }
  58. }
  59. /**
  60. * Change a DELETE clause for an UPDATE clause
  61. *
  62. * @param DeleteClause
  63. * @return string The SQL.
  64. */
  65. public function walkDeleteClause(DeleteClause $deleteClause)
  66. {
  67. $em = $this->getEntityManager();
  68. $class = $em->getClassMetadata($deleteClause->abstractSchemaName);
  69. $tableName = $class->getTableName();
  70. $this->setSQLTableAlias($tableName, $tableName, $deleteClause->aliasIdentificationVariable);
  71. $quotedTableName = $class->getQuotedTableName($this->platform);
  72. $quotedColumnName = $class->getQuotedColumnName($this->deletedAtField, $this->platform);
  73. $sql = 'UPDATE '.$quotedTableName.' SET '.$quotedColumnName.' = "'.date('Y-m-d H:i:s').'"';
  74. return $sql;
  75. }
  76. /**
  77. * Get the currently used SoftDeleteableListener
  78. *
  79. * @throws \Gedmo\Exception\RuntimeException - if listener is not found
  80. * @return SoftDeleteableListener
  81. */
  82. private function getSoftDeleteableListener()
  83. {
  84. if (is_null($this->listener)) {
  85. $em = $this->getEntityManager();
  86. foreach ($em->getEventManager()->getListeners() as $event => $listeners) {
  87. foreach ($listeners as $hash => $listener) {
  88. if ($listener instanceof SoftDeleteableListener) {
  89. $this->listener = $listener;
  90. break;
  91. }
  92. }
  93. if ($this->listener) {
  94. break;
  95. }
  96. }
  97. if (is_null($this->listener)) {
  98. throw new \Gedmo\Exception\RuntimeException('The SoftDeleteable listener could not be found.');
  99. }
  100. }
  101. return $this->listener;
  102. }
  103. /**
  104. * Search for components in the delete clause
  105. *
  106. * @param array $queryComponents
  107. * @return void
  108. */
  109. private function extractComponents(array $queryComponents)
  110. {
  111. $em = $this->getEntityManager();
  112. foreach ($queryComponents as $alias => $comp) {
  113. if (!isset($comp['metadata'])) {
  114. continue;
  115. }
  116. $meta = $comp['metadata'];
  117. $config = $this->listener->getConfiguration($em, $meta->name);
  118. if ($config && isset($config['softDeleteable']) && $config['softDeleteable']) {
  119. $this->configuration = $config;
  120. $this->deletedAtField = $config['fieldName'];
  121. $this->meta = $meta;
  122. }
  123. }
  124. }
  125. }