Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions src/Bridge/Doctrine/Persister/ManagerRegistryPersister.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php

/*
* This file is part of the Fidry\AliceDataFixtures package.
*
* (c) Théo FIDRY <theo.fidry@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Fidry\AliceDataFixtures\Bridge\Doctrine\Persister;

use Doctrine\Persistence\ManagerRegistry;
use Fidry\AliceDataFixtures\Persistence\PersisterInterface;
use function get_class;
use function implode;
use InvalidArgumentException;
use Nelmio\Alice\IsAServiceTrait;
use function sprintf;

/**
* @final
*/
class ManagerRegistryPersister implements PersisterInterface
{
use IsAServiceTrait;

private $registry;

/**
* @var PersisterInterface[]
*/
private $persisters = [];

public function __construct(ManagerRegistry $registry)
{
$this->registry = $registry;

$managers = $registry->getManagers();

foreach ($managers as $manager) {
$this->persisters[spl_object_hash($manager)] = new ObjectManagerPersister($manager);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This allows having multiple instance of Doctrine\ORM\EntityManager

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}
}

/**
* {@inheritdoc}
*/
public function persist($object)
{
$persister = $this->getPersisterForClass(get_class($object));

$persister->persist($object);
}

/**
* {@inheritdoc}
*/
public function flush()
{
foreach ($this->persisters as $persister) {
$persister->flush();
}
}

private function getPersisterForClass(string $class): PersisterInterface
{
$manager = $this->registry->getManagerForClass($class);

if (null === $manager) {
throw new InvalidArgumentException(
sprintf(
'Could not find a manager for the class "%s". Known managers: "%s"',
$class,
implode('", "', $this->registry->getManagerNames())
)
);
}

return $this->persisters[spl_object_hash($manager)];
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(this matches previous comment)

}
}
8 changes: 4 additions & 4 deletions src/Bridge/Doctrine/Persister/ObjectManagerPersister.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
use Fidry\AliceDataFixtures\Persistence\PersisterInterface;
use Nelmio\Alice\IsAServiceTrait;

class ObjectManagerPersister implements PersisterInterface
/* final */ class ObjectManagerPersister implements PersisterInterface
{
use IsAServiceTrait;

Expand All @@ -46,7 +46,7 @@ public function __construct(ObjectManager $manager)
}

/**
* @inheritdoc
* {@inheritdoc}
*/
public function persist($object)
{
Expand Down Expand Up @@ -85,7 +85,7 @@ public function persist($object)
}

/**
* @inheritdoc
* {@inheritdoc}
*/
public function flush()
{
Expand Down Expand Up @@ -117,7 +117,7 @@ private function getPersistableClasses(ObjectManager $manager): array
return $persistableClasses;
}

private function saveMetadataToRestore(ClassMetadata $metadata): void
private function saveMetadataToRestore(ORMClassMetadataInfo $metadata): void
{
if (!isset($this->metadataToRestore[$metadata->getName()])) {
$this->metadataToRestore[$metadata->getName()] = $metadata;
Expand Down
73 changes: 73 additions & 0 deletions src/Bridge/Doctrine/Purger/ManagerRegistryPurger.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

/*
* This file is part of the Fidry\AliceDataFixtures package.
*
* (c) Théo FIDRY <theo.fidry@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Fidry\AliceDataFixtures\Bridge\Doctrine\Purger;

use function array_map;
use Doctrine\Persistence\ManagerRegistry;
use Doctrine\Persistence\ObjectManager;
use Fidry\AliceDataFixtures\Persistence\PurgeMode;
use Fidry\AliceDataFixtures\Persistence\PurgerFactoryInterface;
use Fidry\AliceDataFixtures\Persistence\PurgerInterface;
use InvalidArgumentException;
use Nelmio\Alice\IsAServiceTrait;

/**
* @final
*/
/* final */ class ManagerRegistryPurger implements PurgerInterface, PurgerFactoryInterface
{
use IsAServiceTrait;

private $registry;
private $purgeMode;

/**
* @var PurgerInterface[]
*/
private $purgers = [];

public function __construct(ManagerRegistry $registry, PurgeMode $purgeMode = null)
{
$this->registry = $registry;

$this->purgers = array_map(
function (ObjectManager $manager) use ($purgeMode): PurgerInterface {
return new ObjectManagerPurger($manager, $purgeMode);
},
$registry->getManagers()
);
}

/**
* @inheritdoc
*/
public function create(PurgeMode $mode, PurgerInterface $purger = null): PurgerInterface
{
if (null !== $purger) {
throw new InvalidArgumentException('Cannot create a new purger from an existing one.');
}

return new self($this->registry, $mode);
}

/**
* @inheritdoc
*/
public function purge(): void
{
foreach ($this->purgers as $purger) {
$purger->purge();
}
}
}
144 changes: 144 additions & 0 deletions src/Bridge/Doctrine/Purger/ObjectManagerPurger.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
<?php

/*
* This file is part of the Fidry\AliceDataFixtures package.
*
* (c) Théo FIDRY <theo.fidry@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Fidry\AliceDataFixtures\Bridge\Doctrine\Purger;

use Doctrine\Common\DataFixtures\Purger\MongoDBPurger as DoctrineMongoDBPurger;
use Doctrine\Common\DataFixtures\Purger\ORMPurger as DoctrineOrmPurger;
use Doctrine\Common\DataFixtures\Purger\PHPCRPurger as DoctrinePhpCrPurger;
use Doctrine\Common\DataFixtures\Purger\PurgerInterface as DoctrinePurgerInterface;
use Doctrine\DBAL\Driver\AbstractMySQLDriver;
use Doctrine\ODM\MongoDB\DocumentManager as DoctrineMongoDocumentManager;
use Doctrine\ODM\PHPCR\DocumentManager as DoctrinePhpCrDocumentManager;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ObjectManager;
use Fidry\AliceDataFixtures\Persistence\PurgeMode;
use Fidry\AliceDataFixtures\Persistence\PurgerFactoryInterface;
use Fidry\AliceDataFixtures\Persistence\PurgerInterface;
use InvalidArgumentException;
use Nelmio\Alice\IsAServiceTrait;

/**
* Bridge for Doctrine purger.
*
* @author Vincent CHALAMON <vincentchalamon@gmail.com>
* @final
*/
/* final */ class ObjectManagerPurger implements PurgerInterface, PurgerFactoryInterface
{
use IsAServiceTrait;

private $manager;
private $purgeMode;
private $purger;

public function __construct(ObjectManager $manager, PurgeMode $purgeMode = null)
{
$this->manager = $manager;
$this->purgeMode = $purgeMode;

$this->purger = static::createPurger($manager, $purgeMode);
}

/**
* @inheritdoc
*/
public function create(PurgeMode $mode, PurgerInterface $purger = null): PurgerInterface
{
if (null === $purger) {
return new self($this->manager, $mode);
}

if ($purger instanceof DoctrinePurgerInterface) {
$manager = $purger->getObjectManager();
} elseif ($purger instanceof self) {
$manager = $purger->manager;
} else {
throw new InvalidArgumentException(
sprintf(
'Expected purger to be either and instance of "%s" or "%s". Got "%s".',
DoctrinePurgerInterface::class,
__CLASS__,
get_class($purger)
)
);
}

if (null === $manager) {
throw new InvalidArgumentException(
sprintf(
'Expected purger "%s" to have an object manager, got "null" instead.',
get_class($purger)
)
);
}

return new self($manager, $mode);
}

/**
* @inheritdoc
*/
public function purge(): void
{
// Because MySQL rocks, you got to disable foreign key checks when doing a TRUNCATE/DELETE unlike in for example
// PostgreSQL. This ideally should be done in the Purger of doctrine/data-fixtures but meanwhile we are doing
// it here.
// See the progress in https://github.com/doctrine/data-fixtures/pull/272
$disableFkChecks = (
$this->purger instanceof DoctrineOrmPurger
&& in_array($this->purgeMode->getValue(), [PurgeMode::createDeleteMode()->getValue(), PurgeMode::createTruncateMode()->getValue()])
&& $this->purger->getObjectManager()->getConnection()->getDriver() instanceof AbstractMySQLDriver
);

if ($disableFkChecks) {
$connection = $this->purger->getObjectManager()->getConnection();

$connection->exec('SET FOREIGN_KEY_CHECKS = 0;');
}

$this->purger->purge();

if ($disableFkChecks && isset($connection)) {
$connection->exec('SET FOREIGN_KEY_CHECKS = 1;');
}
}

private static function createPurger(ObjectManager $manager, ?PurgeMode $purgeMode): DoctrinePurgerInterface
{
if ($manager instanceof EntityManagerInterface) {
$purger = new DoctrineOrmPurger($manager);

if (null !== $purgeMode) {
$purger->setPurgeMode($purgeMode->getValue());
}

return $purger;
}

if ($manager instanceof DoctrinePhpCrDocumentManager) {
return new DoctrinePhpCrPurger($manager);
}

if ($manager instanceof DoctrineMongoDocumentManager) {
return new DoctrineMongoDBPurger($manager);
}

throw new InvalidArgumentException(
sprintf(
'Cannot create a purger for ObjectManager of class %s',
get_class($manager)
)
);
}
}
Loading