Permalink
Browse files

Refactoring and adding proper unit tests.

  • Loading branch information...
1 parent e1976cc commit a5f54fecd5ab2113f0aa151cc36a8b083310d13e @jwage jwage committed Oct 3, 2010
View
@@ -0,0 +1,9 @@
+[submodule "lib/vendor/doctrine-common"]
+ path = lib/vendor/doctrine-common
+ url = git://github.com/doctrine/common.git
+[submodule "lib/vendor/doctrine-orm"]
+ path = lib/vendor/doctrine-orm
+ url = git://github.com/doctrine/doctrine2.git
+[submodule "lib/vendor/doctrine-dbal"]
+ path = lib/vendor/doctrine-dbal
+ url = git://github.com/doctrine/dbal.git
View
@@ -27,7 +27,7 @@ Now you can begin adding the fixtures to a loader instance:
use Doctrine\ORM\DataFixtures\Loader;
use MyDataFixtures\LoadUserData;
- $loader = new Loader($em);
+ $loader = new Loader();
$loader->addFixture(new LoadUserData);
You can load a set of fixtures from a directory as well:
@@ -40,4 +40,13 @@ You can get the added fixtures using the getFixtures() method:
Now you can easily execute the fixtures:
- $loader->execute();
+ use Doctrine\ORM\DataFixtures\Executor;
+
+ $purger = new Purger();
+ $executor = new Executor($em, $purger);
+ $executor->execute($loader->getFixtures());
+
+If you want to append the fixtures instead of purging before loading then pass false
+to the 2nd argument of execute:
+
+ $executor->execute($loader->getFixtures(), true);
@@ -0,0 +1,70 @@
+<?php
+/*
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.doctrine-project.org>.
+ */
+
+namespace Doctrine\ORM\DataFixtures;
+
+use Doctrine\ORM\EntityManager;
+
+/**
+ * Class responsible for executing data fixtures.
+ *
+ * @author Jonathan H. Wage <jonwage@gmail.com>
+ */
+class Executer
+{
+ /** Purger instance for purging database before loading data fixtures */
+ private $purger;
+
+ /**
+ * Construct new fixtures loader instance.
+ *
+ * @param EntityManager $em EntityManager instance used for persistence.
+ */
+ public function __construct(EntityManager $em, Purger $purger = null)
+ {
+ $this->em = $em;
+ if ($purger !== null) {
+ $this->purger = $purger;
+ $this->purger->setEntityManager($em);
+ }
+ }
+
+ /**
+ * Executes the the array of data fixtures.
+ *
+ * @param array $fixtures Array of fixtures to execute.
+ * @param boolean $append Whether to append the data fixtures or purge the database before loading.
+ */
+ public function execute(array $fixtures, $append = false)
+ {
+ $purger = $this->purger;
+ $this->em->transactional(function(EntityManager $em) use ($fixtures, $append, $purger) {
+ if ($append === false) {
+ if ($purger === null) {
+ throw new \Exception('Doctrine\ORM\DataFixtures\Purger instance is required if you want to purge the database before loading your data fixtures.');
+ }
+ $purger->purge();
+ }
+
+ foreach ($fixtures as $fixture) {
+ $fixture->load($em);
+ }
+ });
+ }
+}
@@ -33,5 +33,5 @@
*
* @param EntityManager $em
*/
- function load(EntityManager $em);
+ public function load(EntityManager $em);
}
@@ -22,29 +22,16 @@
use Doctrine\ORM\EntityManager;
/**
- * Class responsible for managing and executing data fixtures classes.
+ * Class responsible for loading data fixture classes.
*
* @author Jonathan H. Wage <jonwage@gmail.com>
*/
class Loader
{
- /** EntityManager instance used for persistence. */
- private $em;
-
/** Array of fixture object instances to execute. */
private $fixtures = array();
/**
- * Construct new fixtures loader instance.
- *
- * @param EntityManager $em EntityManager instance used for persistence.
- */
- public function __construct(EntityManager $em)
- {
- $this->em = $em;
- }
-
- /**
* Find fixtures classes in a given directory and load them.
*
* @param string $dir Directory to find fixture classes in.
@@ -56,7 +43,7 @@ public function loadFromDirectory($dir)
throw new \InvalidArgumentException(sprintf('"%s" does not exist', $dir));
}
- $classes = array();
+ $fixtures = array();
$includedFiles = array();
$iterator = new \RecursiveIteratorIterator(
@@ -70,7 +57,6 @@ public function loadFromDirectory($dir)
$includedFiles[] = $sourceFile;
}
$declared = get_declared_classes();
-
$fixtures = array();
foreach ($declared as $className) {
$reflClass = new \ReflectionClass($className);
@@ -105,19 +91,6 @@ public function getFixtures()
}
/**
- * Executes the the array of data fixtures.
- */
- public function execute()
- {
- $fixtures = $this->getFixtures();
- $this->em->transactional(function(EntityManager $em) use ($fixtures) {
- foreach ($fixtures as $fixture) {
- $fixture->load($em);
- }
- });
- }
-
- /**
* Check if a given fixture is transient and should not be considered a data fixtures
* class.
*
@@ -0,0 +1,132 @@
+<?php
+/*
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.doctrine-project.org>.
+ */
+
+namespace Doctrine\ORM\DataFixtures;
+
+use Doctrine\ORM\EntityManager;
+use Doctrine\ORM\Internal\CommitOrderCalculator;
+use Doctrine\ORM\Mapping\ClassMetadata;
+
+/**
+ * Class responsible for purging databases of data before reloading data fixtures.
+ *
+ * @author Jonathan H. Wage <jonwage@gmail.com>
+ */
+class Purger
+{
+ /** EntityManager instance used for persistence. */
+ private $em;
+
+ /**
+ * Construct new purger instance.
+ *
+ * @param EntityManager $em EntityManager instance used for persistence.
+ */
+ public function __construct(EntityManager $em = null)
+ {
+ $this->em = $em;
+ }
+
+ /**
+ * Set the EntityManager instance this purger instance should use.
+ *
+ * @param EntityManager $em
+ */
+ public function setEntityManager(EntityManager $em)
+ {
+ $this->em = $em;
+ }
+
+ /**
+ * Purge the data from the database for the given EntityManager.
+ *
+ * @return void
+ */
+ public function purge()
+ {
+ $classes = array();
+ $metadatas = $this->em->getMetadataFactory()->getAllMetadata();
+
+ foreach ($metadatas as $metadata) {
+ if (!$metadata->isMappedSuperclass) {
+ $classes[] = $metadata;
+ }
+ }
+
+ $commitOrder = $this->getCommitOrder($this->em, $classes);
+
+ // Drop association tables first
+ $orderedTables = $this->getAssociationTables($commitOrder);
+
+ // Drop tables in reverse commit order
+ for ($i = count($commitOrder) - 1; $i >= 0; --$i) {
+ $class = $commitOrder[$i];
+
+ if (($class->isInheritanceTypeSingleTable() && $class->name != $class->rootEntityName)
+ || $class->isMappedSuperclass) {
+ continue;
+ }
+
+ $orderedTables[] = $class->getTableName();
+ }
+
+ foreach($orderedTables as $tbl) {
+ $em->getConnection()->executeUpdate("DELETE FROM $tbl");
+ }
+ }
+
+ private function getCommitOrder(EntityManager $em, array $classes)
+ {
+ $calc = new CommitOrderCalculator;
+
+ foreach ($classes as $class) {
+ $calc->addClass($class);
+
+ foreach ($class->associationMappings as $assoc) {
+ if ($assoc['isOwningSide']) {
+ $targetClass = $em->getClassMetadata($assoc['targetEntity']);
+
+ if ( ! $calc->hasClass($targetClass->name)) {
+ $calc->addClass($targetClass);
+ }
+
+ // add dependency ($targetClass before $class)
+ $calc->addDependency($targetClass, $class);
+ }
+ }
+ }
+
+ return $calc->getCommitOrder();
+ }
+
+ private function getAssociationTables(array $classes)
+ {
+ $associationTables = array();
+
+ foreach ($classes as $class) {
+ foreach ($class->associationMappings as $assoc) {
+ if ($assoc['isOwningSide'] && $assoc['type'] == ClassMetadata::MANY_TO_MANY) {
+ $associationTables[] = $assoc['joinTable']['name'];
+ }
+ }
+ }
+
+ return $associationTables;
+ }
+}
Submodule doctrine-common added at 976a69
Submodule doctrine-dbal added at 173d7e
Submodule doctrine-orm added at b05e1a
@@ -0,0 +1,62 @@
+<?php
+/*
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.doctrine-project.org>.
+ */
+
+namespace Doctrine\Tests\ORM\DataFixtures;
+
+require_once __DIR__.'/TestInit.php';
+
+use Doctrine\ORM\EntityManager;
+use PHPUnit_Framework_TestCase;
+
+/**
+ * Base test class
+ *
+ * @author Jonathan H. Wage <jonwage@gmail.com>
+ */
+abstract class BaseTest extends PHPUnit_Framework_TestCase
+{
+ protected function getMockEntityManager()
+ {
+ $driver = $this->getMock('Doctrine\DBAL\Driver');
+ $driver->expects($this->once())
+ ->method('getDatabasePlatform')
+ ->will($this->returnValue($this->getMock('Doctrine\DBAL\Platforms\MySqlPlatform')));
+
+ $conn = $this->getMock('Doctrine\DBAL\Connection', array(), array(array(), $driver));
+ $conn->expects($this->once())
+ ->method('getEventManager')
+ ->will($this->returnValue($this->getMock('Doctrine\Common\EventManager')));
+
+ $config = $this->getMock('Doctrine\ORM\Configuration');
+ $config->expects($this->once())
+ ->method('getProxyDir')
+ ->will($this->returnValue('test'));
+
+ $config->expects($this->once())
+ ->method('getProxyNamespace')
+ ->will($this->returnValue('Proxies'));
+
+ $config->expects($this->once())
+ ->method('getMetadataDriverImpl')
+ ->will($this->returnValue($this->getMock('Doctrine\ORM\Mapping\Driver\DriverChain')));
+
+ $em = EntityManager::create($conn, $config);
+ return $em;
+ }
+}
Oops, something went wrong. Retry.

0 comments on commit a5f54fe

Please sign in to comment.