vendor/theofidry/alice-data-fixtures/src/Bridge/Doctrine/Purger/Purger.php line 47

Open in your IDE?
  1. <?php
  2. /*
  3. * This file is part of the Fidry\AliceDataFixtures package.
  4. *
  5. * (c) Théo FIDRY <theo.fidry@gmail.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. declare(strict_types=1);
  11. namespace Fidry\AliceDataFixtures\Bridge\Doctrine\Purger;
  12. use Doctrine\Common\DataFixtures\Purger\MongoDBPurger as DoctrineMongoDBPurger;
  13. use Doctrine\Common\DataFixtures\Purger\ORMPurger as DoctrineOrmPurger;
  14. use Doctrine\Common\DataFixtures\Purger\PHPCRPurger as DoctrinePhpCrPurger;
  15. use Doctrine\Common\DataFixtures\Purger\PurgerInterface as DoctrinePurgerInterface;
  16. use Doctrine\DBAL\Platforms\MariaDBPlatform;
  17. use Doctrine\DBAL\Platforms\MySqlPlatform;
  18. use Doctrine\ODM\MongoDB\DocumentManager as DoctrineMongoDocumentManager;
  19. use Doctrine\ODM\PHPCR\DocumentManager as DoctrinePhpCrDocumentManager;
  20. use Doctrine\ORM\EntityManagerInterface;
  21. use Doctrine\Persistence\ObjectManager;
  22. use Fidry\AliceDataFixtures\Persistence\PurgeMode;
  23. use Fidry\AliceDataFixtures\Persistence\PurgerFactoryInterface;
  24. use Fidry\AliceDataFixtures\Persistence\PurgerInterface;
  25. use InvalidArgumentException;
  26. use Nelmio\Alice\IsAServiceTrait;
  27. /**
  28. * Bridge for Doctrine purger.
  29. *
  30. * @author Vincent CHALAMON <vincentchalamon@gmail.com>
  31. *
  32. * @final
  33. */
  34. /* final */ class Purger implements PurgerInterface, PurgerFactoryInterface
  35. {
  36. use IsAServiceTrait;
  37. private ObjectManager $manager;
  38. private ?PurgeMode $purgeMode;
  39. private DoctrinePurgerInterface $purger;
  40. public function __construct(ObjectManager $manager, PurgeMode $purgeMode = null)
  41. {
  42. $this->manager = $manager;
  43. $this->purgeMode = $purgeMode;
  44. $this->purger = static::createPurger($manager, $purgeMode);
  45. }
  46. public function create(PurgeMode $mode, PurgerInterface $purger = null): PurgerInterface
  47. {
  48. if (null === $purger) {
  49. return new self($this->manager, $mode);
  50. }
  51. if ($purger instanceof DoctrinePurgerInterface) {
  52. $manager = $purger->getObjectManager();
  53. } elseif ($purger instanceof self) {
  54. $manager = $purger->manager;
  55. } else {
  56. throw new InvalidArgumentException(
  57. sprintf(
  58. 'Expected purger to be either and instance of "%s" or "%s". Got "%s".',
  59. DoctrinePurgerInterface::class,
  60. __CLASS__,
  61. get_class($purger)
  62. )
  63. );
  64. }
  65. if (null === $manager) {
  66. throw new InvalidArgumentException(
  67. sprintf(
  68. 'Expected purger "%s" to have an object manager, got "null" instead.',
  69. get_class($purger)
  70. )
  71. );
  72. }
  73. return new self($manager, $mode);
  74. }
  75. public function purge(): void
  76. {
  77. // Because MySQL rocks, you got to disable foreign key checks when doing a TRUNCATE/DELETE unlike in for example
  78. // PostgreSQL. This ideally should be done in the Purger of doctrine/data-fixtures but meanwhile we are doing
  79. // it here.
  80. // See the progress in https://github.com/doctrine/data-fixtures/pull/272
  81. $disableFkChecks = (
  82. $this->purger instanceof DoctrineOrmPurger
  83. && in_array($this->purgeMode->getValue(), [PurgeMode::createDeleteMode()->getValue(), PurgeMode::createTruncateMode()->getValue()])
  84. && $this->doesDatabaseSupportTruncate()
  85. );
  86. if ($disableFkChecks) {
  87. $connection = $this->purger->getObjectManager()->getConnection();
  88. $connection->executeStatement('SET FOREIGN_KEY_CHECKS = 0;');
  89. }
  90. $this->purger->purge();
  91. if ($disableFkChecks && isset($connection)) {
  92. $connection->executeStatement('SET FOREIGN_KEY_CHECKS = 1;');
  93. }
  94. }
  95. private static function createPurger(ObjectManager $manager, ?PurgeMode $purgeMode): DoctrinePurgerInterface
  96. {
  97. if ($manager instanceof EntityManagerInterface) {
  98. $purger = new DoctrineOrmPurger($manager);
  99. if (null !== $purgeMode) {
  100. $purger->setPurgeMode($purgeMode->getValue());
  101. }
  102. return $purger;
  103. }
  104. if ($manager instanceof DoctrinePhpCrDocumentManager) {
  105. return new DoctrinePhpCrPurger($manager);
  106. }
  107. if ($manager instanceof DoctrineMongoDocumentManager) {
  108. return new DoctrineMongoDBPurger($manager);
  109. }
  110. throw new InvalidArgumentException(
  111. sprintf(
  112. 'Cannot create a purger for ObjectManager of class %s',
  113. get_class($manager)
  114. )
  115. );
  116. }
  117. private function doesDatabaseSupportTruncate(): bool
  118. {
  119. $platform = $this->purger->getObjectManager()->getConnection()->getDatabasePlatform();
  120. return $platform instanceof MySqlPlatform
  121. || $platform instanceof MariaDBPlatform;
  122. }
  123. }