浏览代码

[sortable] inheritance mapped entity support

gedi 13 年之前
父节点
当前提交
46b59c74c3

+ 18 - 17
lib/Gedmo/Sortable/SortableListener.php

@@ -123,7 +123,7 @@ class SortableListener extends MappedEventSubscriber
             $groups[$group] = $meta->getReflectionProperty($group)->getValue($object);
         }
         // Get hash
-        $hash = $this->getHash($meta, $groups, $object);
+        $hash = $this->getHash($meta, $groups, $object, $config);
 
         // Get max position
         if (!isset($this->maxPositions[$hash])) {
@@ -140,7 +140,7 @@ class SortableListener extends MappedEventSubscriber
         $newPosition = min(array($this->maxPositions[$hash] + 1, $newPosition));
 
         // Compute relocations
-        $relocation = array($hash, $meta, $groups, $newPosition, -1, +1);
+        $relocation = array($hash, $config['useObjectClass'], $groups, $newPosition, -1, +1);
 
         // Apply existing relocations
         $applyDelta = 0;
@@ -192,7 +192,7 @@ class SortableListener extends MappedEventSubscriber
         if (!$changed) return;
 
         // Get hash
-        $hash = $this->getHash($meta, $groups, $object);
+        $hash = $this->getHash($meta, $groups, $object, $config);
 
         // Get max position
         if (!isset($this->maxPositions[$hash])) {
@@ -225,9 +225,9 @@ class SortableListener extends MappedEventSubscriber
         */
         $relocation = null;
         if ($newPosition < $oldPosition) {
-            $relocation = array($hash, $meta, $groups, $newPosition, $oldPosition, +1);
+            $relocation = array($hash, $config['useObjectClass'], $groups, $newPosition, $oldPosition, +1);
         } elseif ($newPosition > $oldPosition) {
-            $relocation = array($hash, $meta, $groups, $oldPosition + 1, $newPosition + 1, -1);
+            $relocation = array($hash, $config['useObjectClass'], $groups, $oldPosition + 1, $newPosition + 1, -1);
         }
 
         // Apply existing relocations
@@ -264,7 +264,7 @@ class SortableListener extends MappedEventSubscriber
             $groups[$group] = $meta->getReflectionProperty($group)->getValue($object);
         }
         // Get hash
-        $hash = $this->getHash($meta, $groups, $object);
+        $hash = $this->getHash($meta, $groups, $object, $config);
 
         // Get max position
         if (!isset($this->maxPositions[$hash])) {
@@ -272,7 +272,7 @@ class SortableListener extends MappedEventSubscriber
         }
 
         // Add relocation
-        $this->addRelocation($hash, $meta, $groups, $position, -1, -1);
+        $this->addRelocation($hash, $config['useObjectClass'], $groups, $position, -1, -1);
     }
 
     private function processRelocations($em)
@@ -300,8 +300,8 @@ class SortableListener extends MappedEventSubscriber
                     if (is_null($val)) {
                         $qb->andWhere($qb->expr()->isNull('n.'.$group));
                     } else {
-                        $qb->andWhere('n.'.$group.' = :group'.$i);
-                        $qb->setParameter('group'.$i, $val);
+                        $qb->andWhere('n.'.$group.' = :group__'.$i);
+                        $qb->setParameter('group__'.$i, $val);
                     }
                     $i++;
                 }
@@ -314,9 +314,9 @@ class SortableListener extends MappedEventSubscriber
         $this->maxPositions = array();
     }
 
-    private function getHash($meta, $groups, $object)
+    private function getHash($meta, $groups, $object, &$config)
     {
-        $data = $meta->name;
+        $data = $config['useObjectClass'];
         foreach ($groups as $group => $val) {
             if (is_object($val)) {
                 $val = spl_object_hash($val);
@@ -331,7 +331,7 @@ class SortableListener extends MappedEventSubscriber
         $maxPos = null;
         $qb = $em->createQueryBuilder();
         $qb->select('MAX(n.'.$config['position'].')')
-           ->from($meta->name, 'n');
+           ->from($config['useObjectClass'], 'n');
         $qb = $this->addGroupWhere($qb, $config["groups"], $meta, $object);
         $query = $qb->getQuery();
         $query->useQueryCache(false);
@@ -347,11 +347,12 @@ class SortableListener extends MappedEventSubscriber
         $i = 1;
         foreach ($groups as $group) {
             $value = $meta->getReflectionProperty($group)->getValue($object);
+            $whereFunc = is_null($qb->getDQLPart('where')) ? 'where' : 'andWhere';
             if (is_null($value)) {
-                $qb->andWhere($qb->expr()->isNull('n.'.$group));
+                $qb->{$whereFunc}($qb->expr()->isNull('n.'.$group));
             } else {
-                $qb->andWhere('n.'.$group.' = :group'.$i);
-                $qb->setParameter('group'.$i, $value);
+                $qb->{$whereFunc}('n.'.$group.' = :group__'.$i);
+                $qb->setParameter('group__'.$i, $value);
             }
             $i++;
         }
@@ -367,10 +368,10 @@ class SortableListener extends MappedEventSubscriber
      * @param int $stop Exclusive index to stop relocation at
      * @param int $delta The delta to add to relocated nodes
      */
-    private function addRelocation($hash, $meta, $groups, $start, $stop, $delta)
+    private function addRelocation($hash, $class, $groups, $start, $stop, $delta)
     {
         if (!array_key_exists($hash, $this->relocations)) {
-            $this->relocations[$hash] = array('name' => $meta->name, 'groups' => $groups, 'deltas' => array());
+            $this->relocations[$hash] = array('name' => $class, 'groups' => $groups, 'deltas' => array());
         }
 
         try {

+ 1 - 1
tests/Gedmo/Sortable/Fixture/Item.php

@@ -59,7 +59,7 @@ class Item
         return $this->position;
     }
 
-    public function setCategory(Category $category)
+    public function setCategory(Category $category = null)
     {
         $this->category = $category;
     }

+ 13 - 0
tests/Gedmo/Sortable/Fixture/Transport/Bus.php

@@ -0,0 +1,13 @@
+<?php
+
+namespace Sortable\Fixture\Transport;
+
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * @ORM\Entity
+ */
+class Bus extends Vehicle
+{
+
+}

+ 37 - 0
tests/Gedmo/Sortable/Fixture/Transport/Car.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace Sortable\Fixture\Transport;
+
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * @ORM\Entity
+ */
+class Car extends Vehicle
+{
+    /**
+     * @ORM\ManyToOne(targetEntity="Car", inversedBy="children")
+     * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="SET NULL")
+     */
+    private $parent;
+
+    /**
+     * @ORM\OneToMany(targetEntity="Car", mappedBy="parent")
+     */
+    private $children;
+
+    public function setParent($parent = null)
+    {
+        $this->parent = $parent;
+    }
+
+    public function getChildren()
+    {
+        return $this->children;
+    }
+
+    public function getParent()
+    {
+        return $this->parent;
+    }
+}

+ 54 - 0
tests/Gedmo/Sortable/Fixture/Transport/Engine.php

@@ -0,0 +1,54 @@
+<?php
+
+namespace Sortable\Fixture\Transport;
+
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * @ORM\Entity
+ */
+class Engine
+{
+    /**
+     * @ORM\Id
+     * @ORM\GeneratedValue
+     * @ORM\Column(type="integer")
+     */
+    private $id;
+
+    /**
+     * @ORM\Column(length=32)
+     */
+    private $type;
+
+    /**
+     * @ORM\Column(type="integer")
+     */
+    private $valves;
+
+    public function getId()
+    {
+        return $this->id;
+    }
+
+    public function setType($type)
+    {
+        $this->type = $type;
+    }
+
+    public function getType()
+    {
+        return $this->type;
+    }
+
+    public function setValves($valves)
+    {
+        $this->valves = $valves;
+    }
+
+    public function getValves()
+    {
+        return $this->valves;
+    }
+}
+

+ 78 - 0
tests/Gedmo/Sortable/Fixture/Transport/Vehicle.php

@@ -0,0 +1,78 @@
+<?php
+
+namespace Sortable\Fixture\Transport;
+
+use Gedmo\Mapping\Annotation as Gedmo;
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * @ORM\Entity
+ * @ORM\InheritanceType("SINGLE_TABLE")
+ * @ORM\DiscriminatorColumn(name="discriminator", type="string")
+ * @ORM\DiscriminatorMap({
+ *      "vehicle" = "Vehicle",
+ *      "car" = "Car",
+ *      "bus" = "Bus"
+ * })
+ */
+class Vehicle
+{
+    /**
+     * @ORM\Id
+     * @ORM\GeneratedValue
+     * @ORM\Column(type="integer")
+     */
+    private $id;
+
+    /**
+     * @Gedmo\SortableGroup
+     * @ORM\ManyToOne(targetEntity="Engine")
+     */
+    private $engine;
+
+    /**
+     * @ORM\Column(length=128)
+     */
+    private $title;
+
+    /**
+     * @Gedmo\SortablePosition
+     * @ORM\Column(type="integer")
+     */
+    private $sortByEngine;
+
+    public function getId()
+    {
+        return $this->id;
+    }
+
+    public function setSortByEngine($sort)
+    {
+        $this->sortByEngine = $sort;
+    }
+
+    public function getSortByEngine()
+    {
+        return $this->sortByEngine;
+    }
+
+    public function setEngine(Engine $engine)
+    {
+        $this->engine = $engine;
+    }
+
+    public function getEngine()
+    {
+        return $this->engine;
+    }
+
+    public function setTitle($title)
+    {
+        $this->title = $title;
+    }
+
+    public function getTitle()
+    {
+        return $this->title;
+    }
+}

+ 114 - 0
tests/Gedmo/Sortable/SortableGroupTest.php

@@ -0,0 +1,114 @@
+<?php
+
+namespace Gedmo\Sortable;
+
+use Doctrine\Common\EventManager;
+use Tool\BaseTestCaseORM;
+use Sortable\Fixture\Transport\Car;
+use Sortable\Fixture\Transport\Bus;
+use Sortable\Fixture\Transport\Vehicle;
+use Sortable\Fixture\Transport\Engine;
+
+/**
+ * These are tests for sluggable behavior
+ *
+ * @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
+ * @package Gedmo.Sluggable
+ * @link http://www.gediminasm.org
+ * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
+ */
+class SortableGroupTest extends BaseTestCaseORM
+{
+    const CAR = "Sortable\Fixture\Transport\Car";
+    const BUS = "Sortable\Fixture\Transport\Bus";
+    const VEHICLE = "Sortable\Fixture\Transport\Vehicle";
+    const ENGINE = "Sortable\Fixture\Transport\Engine";
+
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $evm = new EventManager;
+        $evm->addEventSubscriber(new SortableListener);
+
+        $this->getMockSqliteEntityManager($evm);
+        /*$this->getMockCustomEntityManager(array(
+            'driver' => 'pdo_mysql',
+            'dbname' => 'test',
+            'host' => '127.0.0.1',
+            'user' => 'root',
+            'password' => 'nimda'
+        ), $evm);*/
+    }
+
+    /**
+     * @test
+     */
+    function shouldBeAbleToRemove()
+    {
+        $this->populate();
+        $carRepo = $this->em->getRepository(self::CAR);
+
+        $audi80 = $carRepo->findOneByTitle('Audi-80');
+        $this->assertEquals(0, $audi80->getSortByEngine());
+
+        $audi80s = $carRepo->findOneByTitle('Audi-80s');
+        $this->assertEquals(1, $audi80s->getSortByEngine());
+
+        $icarus = $this->em->getRepository(self::BUS)->findOneByTitle('Icarus');
+        $this->assertEquals(2, $icarus->getSortByEngine());
+        //$this->em->remove($audi);
+        //$this->em->flush();
+    }
+
+    protected function getUsedEntityFixtures()
+    {
+        return array(
+            self::VEHICLE,
+            self::CAR,
+            self::ENGINE,
+            self::BUS
+        );
+    }
+
+    private function populate()
+    {
+        // engines
+        $v8 = new Engine;
+        $v8->setType('V8');
+        $v8->setValves(8);
+        $this->em->persist($v8);
+
+        $v6 = new Engine;
+        $v6->setType('V6');
+        $v6->setValves(8);
+        $this->em->persist($v6);
+        $this->em->flush();
+
+        // cars
+
+        $audi80 = new Car;
+        $audi80->setEngine($v8);
+        $audi80->setTitle('Audi-80');
+        $this->em->persist($audi80);
+
+        $audi80s = new Car;
+        $audi80s->setParent($audi80);
+        $audi80s->setTitle('Audi-80s');
+        $audi80s->setEngine($v8);
+        $this->em->persist($audi80s);
+
+        $icarus = new Bus;
+        $icarus->setEngine($v8);
+        $icarus->setTitle('Icarus');
+        $this->em->persist($icarus);
+
+        $audiJet = new Car;
+        $audiJet->setParent($audi80);
+        $audiJet->setTitle('Audi-jet');
+        $audiJet->setEngine($v6);
+        $this->em->persist($audiJet);
+
+        $this->em->flush();
+    }
+}