Commit 1b9b6c68 authored by piccoloprincipe's avatar piccoloprincipe

[2.0] added many-to-many uni and bi directional tests (affects #2276)

parent 2c508102
......@@ -82,4 +82,8 @@ class ECommerceCart
public function addProduct(ECommerceProduct $product) {
$this->products[] = $product;
}
public function removeProduct(ECommerceProduct $product) {
return $this->products->removeElement($product);
}
}
<?php
namespace Doctrine\Tests\Models\ECommerce;
/**
* ECommerceCategory
* Represents a tag applied on particular products.
*
* @author Giorgio Sironi
* @Entity
* @Table(name="ecommerce_categories")
*/
class ECommerceCategory
{
/**
* @Column(type="integer")
* @Id
* @GeneratedValue(strategy="AUTO")
*/
public $id;
/**
* @Column(type="string", length=50)
*/
public $name;
/**
* @ManyToMany(targetEntity="ECommerceProduct", mappedBy="categories")
*/
public $products;
public function __construct()
{
$this->products = new \Doctrine\Common\Collections\Collection();
}
public function getId()
{
return $this->id;
}
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
public function addProduct(ECommerceProduct $product)
{
if (!$this->products->contains($product)) {
$this->products[] = $product;
$product->addCategory($this);
}
}
public function removeProduct(ECommerceProduct $product)
{
if ($this->products->contains($product)) {
$this->products->removeElement($product);
$product->removeCategory($this);
}
}
public function getProducts()
{
return $this->products;
}
}
......@@ -20,7 +20,7 @@ class ECommerceProduct
private $id;
/**
* @Column(type="string", length=50)
* @Column(type="string", length=50, nullable="true")
*/
private $name;
......@@ -40,12 +40,13 @@ class ECommerceProduct
* @JoinTable(name="ecommerce_products_categories",
joinColumns={{"name"="product_id", "referencedColumnName"="id"}},
inverseJoinColumns={{"name"="category_id", "referencedColumnName"="id"}})
private $categories;
*/
private $categories;
public function __construct()
{
$this->features = new \Doctrine\Common\Collections\Collection;
$this->categories = new \Doctrine\Common\Collections\Collection;
}
public function getId()
......@@ -83,17 +84,20 @@ class ECommerceProduct
return $this->features;
}
public function addFeature(ECommerceFeature $feature) {
public function addFeature(ECommerceFeature $feature)
{
$this->features[] = $feature;
$feature->setProduct($this);
}
/** does not set the owning side */
public function brokenAddFeature(ECommerceFeature $feature) {
public function brokenAddFeature(ECommerceFeature $feature)
{
$this->features[] = $feature;
}
public function removeFeature(ECommerceFeature $feature) {
public function removeFeature(ECommerceFeature $feature)
{
if ($this->features->contains($feature)) {
$removed = $this->features->removeElement($feature);
if ($removed) {
......@@ -103,4 +107,25 @@ class ECommerceProduct
}
return false;
}
public function addCategory(ECommerceCategory $category)
{
if (!$this->categories->contains($category)) {
$this->categories[] = $category;
$category->addProduct($this);
}
}
public function removeCategory(ECommerceCategory $category)
{
if ($this->categories->contains($category)) {
$this->categories->removeElement($category);
$category->removeProduct($this);
}
}
public function getCategories()
{
return $this->categories;
}
}
<?php
namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Common\Collections\Collection;
require_once __DIR__ . '/../../TestInit.php';
/**
* Base class for testing a many-to-many association mapping (without inheritance).
*/
class AbstractManyToManyAssociationTestCase extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected $_firstField;
protected $_secondField;
protected $_table;
public function assertForeignKeysContain($firstId, $secondId)
{
$this->assertEquals(1, $this->_countForeignKeys($firstId, $secondId));
}
public function assertForeignKeysNotContain($firstId, $secondId)
{
$this->assertEquals(0, $this->_countForeignKeys($firstId, $secondId));
}
protected function _countForeignKeys($firstId, $secondId)
{
return count($this->_em->getConnection()
->execute("SELECT {$this->_firstField}
FROM {$this->_table}
WHERE {$this->_firstField}=?
AND {$this->_secondField}=?",
array($firstId, $secondId)));
}
public function assertCollectionEquals(Collection $first, Collection $second)
{
if (count($first) != count($second)) {
return false;
}
foreach ($first as $element) {
if (!$second->contains($element)) {
return false;
}
}
return true;
}
}
......@@ -29,6 +29,8 @@ class AllTests
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\OneToOneUnidirectionalAssociationTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\OneToOneBidirectionalAssociationTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\OneToManyBidirectionalAssociationTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\ManyToManyUnidirectionalAssociationTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\ManyToManyBidirectionalAssociationTest');
return $suite;
}
......
<?php
namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Common\Collections\Collection;
use Doctrine\Tests\Models\ECommerce\ECommerceProduct;
use Doctrine\Tests\Models\ECommerce\ECommerceCategory;
require_once __DIR__ . '/../../TestInit.php';
/**
* Tests a bidirectional many-to-many association mapping (without inheritance).
* Inverse side is not present.
*/
class ManyToManyBidirectionalAssociationTest extends AbstractManyToManyAssociationTestCase
{
protected $_firstField = 'cart_id';
protected $_secondField = 'product_id';
protected $_table = 'ecommerce_carts_products';
private $firstProduct;
private $secondProduct;
private $firstCategory;
private $secondCategory;
protected function setUp()
{
$this->useModelSet('ecommerce');
parent::setUp();
$this->firstProduct = new ECommerceProduct();
$this->secondProduct = new ECommerceProduct();
$this->firstCategory = new ECommerceCategory();
$this->firstCategory->setName("Business");
$this->secondCategory = new ECommerceCategory();
$this->secondCategory->setName("Home");
}
public function testSavesAManyToManyAssociationWithCascadeSaveSet()
{
$this->firstProduct->addCategory($this->firstCategory);
$this->firstProduct->addCategory($this->secondCategory);
$this->_em->save($this->firstProduct);
$this->_em->flush();
$this->assertForeignKeysContain($this->firstProduct->getId(),
$this->firstCategory->getId());
$this->assertForeignKeysContain($this->firstProduct->getId(),
$this->secondCategory->getId());
}
public function testRemovesAManyToManyAssociation()
{
$this->firstProduct->addCategory($this->firstCategory);
$this->firstProduct->addCategory($this->secondCategory);
$this->_em->save($this->firstProduct);
$this->firstProduct->removeCategory($this->firstCategory);
$this->_em->flush();
$this->assertForeignKeysNotContain($this->firstProduct->getId(),
$this->firstCategory->getId());
$this->assertForeignKeysContain($this->firstProduct->getId(),
$this->secondCategory->getId());
}
public function testEagerLoadsInverseSide()
{
$this->_createLoadingFixture();
list ($firstProduct, $secondProduct) = $this->_findProducts();
$categories = $firstProduct->getCategories();
$this->assertTrue($categories[0] instanceof ECommerceCategory);
$this->assertTrue($categories[1] instanceof ECommerceCategory);
$this->assertCollectionEquals($categories, $secondProduct->getCategories());
}
public function testEagerLoadsOwningSide()
{
$this->_createLoadingFixture();
list ($firstProduct, $secondProduct) = $this->_findProducts();
$categories = $firstProduct->getCategories();
$products = $categories[0]->getProducts();
$this->assertTrue($products[0] instanceof ECommerceProduct);
$this->assertTrue($products[1] instanceof ECommerceProduct);
$this->assertCollectionEquals($products, $categories[1]->getProducts());
}
protected function _createLoadingFixture()
{
$this->firstProduct->addCategory($this->firstCategory);
$this->firstProduct->addCategory($this->secondCategory);
$this->secondProduct->addCategory($this->firstCategory);
$this->secondProduct->addCategory($this->secondCategory);
$this->_em->save($this->firstProduct);
$this->_em->save($this->secondProduct);
$this->_em->flush();
$this->_em->clear();
}
protected function _findProducts()
{
$query = $this->_em->createQuery('SELECT p, c FROM Doctrine\Tests\Models\ECommerce\ECommerceProduct p LEFT JOIN p.categories c ORDER BY p.id, c.id');
return $query->getResultList();
}
/* TODO: not yet implemented
public function testLazyLoad() {
}*/
}
<?php
namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Common\Collections\Collection;
use Doctrine\Tests\Models\ECommerce\ECommerceCart;
use Doctrine\Tests\Models\ECommerce\ECommerceProduct;
require_once __DIR__ . '/../../TestInit.php';
/**
* Tests a unidirectional many-to-many association mapping (without inheritance).
* Inverse side is not present.
*/
class ManyToManyUnidirectionalAssociationTest extends AbstractManyToManyAssociationTestCase
{
protected $_firstField = 'cart_id';
protected $_secondField = 'product_id';
protected $_table = 'ecommerce_carts_products';
private $firstProduct;
private $secondProduct;
private $firstCart;
private $secondCart;
protected function setUp()
{
$this->useModelSet('ecommerce');
parent::setUp();
$this->firstProduct = new ECommerceProduct();
$this->firstProduct->setName('Doctrine 1.x Manual');
$this->secondProduct = new ECommerceProduct();
$this->secondProduct->setName('Doctrine 2.x Manual');
$this->firstCart = new ECommerceCart();
$this->secondCart = new ECommerceCart();
}
public function testSavesAManyToManyAssociationWithCascadeSaveSet()
{
$this->firstCart->addProduct($this->firstProduct);
$this->firstCart->addProduct($this->secondProduct);
$this->_em->save($this->firstCart);
$this->_em->flush();
$this->assertForeignKeysContain($this->firstCart->getId(),
$this->firstProduct->getId());
$this->assertForeignKeysContain($this->firstCart->getId(),
$this->secondProduct->getId());
}
public function testRemovesAManyToManyAssociation()
{
$this->firstCart->addProduct($this->firstProduct);
$this->firstCart->addProduct($this->secondProduct);
$this->_em->save($this->firstCart);
$this->firstCart->removeProduct($this->firstProduct);
$this->_em->flush();
$this->assertForeignKeysNotContain($this->firstCart->getId(),
$this->firstProduct->getId());
$this->assertForeignKeysContain($this->firstCart->getId(),
$this->secondProduct->getId());
}
public function testEagerLoad()
{
$this->firstCart->addProduct($this->firstProduct);
$this->firstCart->addProduct($this->secondProduct);
$this->secondCart->addProduct($this->firstProduct);
$this->secondCart->addProduct($this->secondProduct);
$this->_em->save($this->firstCart);
$this->_em->save($this->secondCart);
$this->_em->flush();
$this->_em->clear();
$query = $this->_em->createQuery('SELECT c, p FROM Doctrine\Tests\Models\ECommerce\ECommerceCart c LEFT JOIN c.products p ORDER BY c.id, p.id');
$result = $query->getResultList();
$firstCart = $result[0];
$products = $firstCart->getProducts();
$secondCart = $result[1];
$this->assertTrue($products[0] instanceof ECommerceProduct);
$this->assertTrue($products[1] instanceof ECommerceProduct);
$this->assertCollectionEquals($products, $secondCart->getProducts());
//$this->assertEquals("Doctrine 1.x Manual", $products[0]->getName());
//$this->assertEquals("Doctrine 2.x Manual", $products[1]->getName());
}
/* TODO: not yet implemented
public function testLazyLoad() {
}*/
}
......@@ -49,7 +49,8 @@ class OrmFunctionalTestCase extends OrmTestCase
'Doctrine\Tests\Models\ECommerce\ECommerceCustomer',
'Doctrine\Tests\Models\ECommerce\ECommerceProduct',
'Doctrine\Tests\Models\ECommerce\ECommerceShipping',
'Doctrine\Tests\Models\ECommerce\ECommerceFeature'
'Doctrine\Tests\Models\ECommerce\ECommerceFeature',
'Doctrine\Tests\Models\ECommerce\ECommerceCategory'
),
'generic' => array(
'Doctrine\Tests\Models\Generic\DateTimeModel'
......@@ -81,6 +82,7 @@ class OrmFunctionalTestCase extends OrmTestCase
$conn->exec('DELETE FROM ecommerce_products');
$conn->exec('DELETE FROM ecommerce_shippings');
$conn->exec('DELETE FROM ecommerce_features');
$conn->exec('DELETE FROM ecommerce_categories');
}
if (isset($this->_usedModelSets['company'])) {
$conn->exec('DELETE FROM company_persons_friends');
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment