vendor/doctrine-fixtures/lib/Doctrine/Common/DataFixtures/Purger/ORMPurger.php
changeset 58 624e5900f5a4
equal deleted inserted replaced
57:b36a42d260d8 58:624e5900f5a4
       
     1 <?php
       
     2 /*
       
     3  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       
     4  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
       
     5  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
       
     6  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
       
     7  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
     8  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
       
     9  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
       
    10  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
       
    11  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    12  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    13  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    14  *
       
    15  * This software consists of voluntary contributions made by many individuals
       
    16  * and is licensed under the LGPL. For more information, see
       
    17  * <http://www.doctrine-project.org>.
       
    18  */
       
    19 
       
    20 namespace Doctrine\Common\DataFixtures\Purger;
       
    21 
       
    22 use Doctrine\ORM\EntityManager;
       
    23 use Doctrine\ORM\Internal\CommitOrderCalculator;
       
    24 use Doctrine\ORM\Mapping\ClassMetadata;
       
    25 
       
    26 /**
       
    27  * Class responsible for purging databases of data before reloading data fixtures.
       
    28  *
       
    29  * @author Jonathan H. Wage <jonwage@gmail.com>
       
    30  * @author Benjamin Eberlei <kontakt@beberlei.de>
       
    31  */
       
    32 class ORMPurger implements PurgerInterface
       
    33 {
       
    34     const PURGE_MODE_DELETE = 1;
       
    35     const PURGE_MODE_TRUNCATE = 2;
       
    36 
       
    37     /** EntityManager instance used for persistence. */
       
    38     private $em;
       
    39 
       
    40     /**
       
    41      * If the purge should be done through DELETE or TRUNCATE statements
       
    42      *
       
    43      * @var int
       
    44      */
       
    45     private $purgeMode = self::PURGE_MODE_DELETE;
       
    46 
       
    47     /**
       
    48      * Construct new purger instance.
       
    49      *
       
    50      * @param EntityManager $em EntityManager instance used for persistence.
       
    51      */
       
    52     public function __construct(EntityManager $em = null)
       
    53     {
       
    54         $this->em = $em;
       
    55     }
       
    56 
       
    57     /**
       
    58      * Set the purge mode
       
    59      *
       
    60      * @param $mode
       
    61      * @return void
       
    62      */
       
    63     public function setPurgeMode($mode)
       
    64     {
       
    65         $this->purgeMode = $mode;
       
    66     }
       
    67 
       
    68     /**
       
    69      * Get the purge mode
       
    70      *
       
    71      * @return int
       
    72      */
       
    73     public function getPurgeMode()
       
    74     {
       
    75         return $this->purgeMode;
       
    76     }
       
    77 
       
    78     /**
       
    79      * Set the EntityManager instance this purger instance should use.
       
    80      *
       
    81      * @param EntityManager $em
       
    82      */
       
    83     public function setEntityManager(EntityManager $em)
       
    84     {
       
    85       $this->em = $em;
       
    86     }
       
    87 
       
    88     /** @inheritDoc */
       
    89     public function purge()
       
    90     {
       
    91         $classes = array();
       
    92         $metadatas = $this->em->getMetadataFactory()->getAllMetadata();
       
    93 
       
    94         foreach ($metadatas as $metadata) {
       
    95             if ( ! $metadata->isMappedSuperclass) {
       
    96                 $classes[] = $metadata;
       
    97             }
       
    98         }
       
    99 
       
   100         $commitOrder = $this->getCommitOrder($this->em, $classes);
       
   101 
       
   102         // Drop association tables first
       
   103         $orderedTables = $this->getAssociationTables($commitOrder);
       
   104 
       
   105         // Drop tables in reverse commit order
       
   106         for ($i = count($commitOrder) - 1; $i >= 0; --$i) {
       
   107             $class = $commitOrder[$i];
       
   108 
       
   109             if (($class->isInheritanceTypeSingleTable() && $class->name != $class->rootEntityName)
       
   110                 || $class->isMappedSuperclass) {
       
   111                 continue;
       
   112             }
       
   113 
       
   114             $orderedTables[] = $class->getTableName();
       
   115         }
       
   116 
       
   117         $platform = $this->em->getConnection()->getDatabasePlatform();
       
   118         foreach($orderedTables as $tbl) {
       
   119             if ($this->purgeMode === self::PURGE_MODE_DELETE) {
       
   120                 $this->em->getConnection()->executeUpdate("DELETE FROM " . $tbl);
       
   121             } else {
       
   122                 $this->em->getConnection()->executeUpdate($platform->getTruncateTableSQL($tbl, true));
       
   123             }
       
   124         }
       
   125     }
       
   126 
       
   127     private function getCommitOrder(EntityManager $em, array $classes)
       
   128     {
       
   129         $calc = new CommitOrderCalculator;
       
   130 
       
   131         foreach ($classes as $class) {
       
   132             $calc->addClass($class);
       
   133 
       
   134             foreach ($class->associationMappings as $assoc) {
       
   135                 if ($assoc['isOwningSide']) {
       
   136                     $targetClass = $em->getClassMetadata($assoc['targetEntity']);
       
   137 
       
   138                     if ( ! $calc->hasClass($targetClass->name)) {
       
   139                         $calc->addClass($targetClass);
       
   140                     }
       
   141 
       
   142                     // add dependency ($targetClass before $class)
       
   143                     $calc->addDependency($targetClass, $class);
       
   144                 }
       
   145             }
       
   146         }
       
   147 
       
   148         return $calc->getCommitOrder();
       
   149     }
       
   150 
       
   151     private function getAssociationTables(array $classes)
       
   152     {
       
   153         $associationTables = array();
       
   154 
       
   155         foreach ($classes as $class) {
       
   156             foreach ($class->associationMappings as $assoc) {
       
   157                 if ($assoc['isOwningSide'] && $assoc['type'] == ClassMetadata::MANY_TO_MANY) {
       
   158                     $associationTables[] = $assoc['joinTable']['name'];
       
   159                 }
       
   160             }
       
   161         }
       
   162 
       
   163         return $associationTables;
       
   164     }
       
   165 }