From af59ea962f15e70991caa32592a60278af2d23b2 Mon Sep 17 00:00:00 2001
From: Marco Pivetta <ocramius@gmail.com>
Date: Tue, 27 Jan 2015 06:19:26 +0100
Subject: [PATCH 01/12]  #1169 DDC-3343 - updating test expectations -
 one-to-many changes should be no-op unless orphan removal is specified.

---
 .../Functional/ExtraLazyCollectionTest.php    | 104 ++++++++++++++++++
 1 file changed, 104 insertions(+)

diff --git a/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php b/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
index 42d8020d3..ab160d384 100644
--- a/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
@@ -653,6 +653,110 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
 
         $this->topic = $article1->topic;
         $this->phonenumber = $phonenumber1->phonenumber;
+
+    }
+
+    /**
+     * @group DDC-3343
+     */
+    public function testRemoveManagedElementFromOneToManyExtraLazyCollectionIsNoOp()
+    {
+        list($userId, $tweetId) = $this->loadTweetFixture();
+
+        /* @var $user User */
+        $user = $this->_em->find(User::CLASSNAME, $userId);
+
+        $user->tweets->removeElement($this->_em->find(Tweet::CLASSNAME, $tweetId));
+
+        $this->_em->clear();
+
+        /* @var $user User */
+        $user = $this->_em->find(User::CLASSNAME, $userId);
+
+        $this->assertCount(1, $user->tweets, 'Element was not removed - need to update the owning side first');
+    }
+
+    /**
+     * @group DDC-3343
+     */
+    public function testRemoveManagedElementFromOneToManyExtraLazyCollectionWithoutDeletingTheTargetEntityEntryIsNoOp()
+    {
+        list($userId, $tweetId) = $this->loadTweetFixture();
+
+        /* @var $user User */
+        $user  = $this->_em->find(User::CLASSNAME, $userId);
+
+        $e = $this->_em->find(Tweet::CLASSNAME, $tweetId);
+
+        $user->tweets->removeElement($e);
+
+        $this->_em->clear();
+
+        /* @var $tweet Tweet */
+        $tweet = $this->_em->find(Tweet::CLASSNAME, $tweetId);
+        $this->assertInstanceOf(
+            Tweet::CLASSNAME,
+            $tweet,
+            'Even though the collection is extra lazy, the tweet should not have been deleted'
+        );
+
+        $this->assertInstanceOf(
+            User::CLASSNAME,
+            $tweet->author,
+            'Tweet author link has not been removed - need to update the owning side first'
+        );
+    }
+
+    /**
+     * @group DDC-3343
+     */
+    public function testRemovingManagedLazyProxyFromExtraLazyOneToManyDoesRemoveTheAssociationButNotTheEntity()
+    {
+        list($userId, $tweetId) = $this->loadTweetFixture();
+
+        /* @var $user User */
+        $user  = $this->_em->find(User::CLASSNAME, $userId);
+        $tweet = $this->_em->getReference(Tweet::CLASSNAME, $tweetId);
+
+        $user->tweets->removeElement($this->_em->getReference(Tweet::CLASSNAME, $tweetId));
+
+        $this->_em->clear();
+
+        /* @var $tweet Tweet */
+        $tweet = $this->_em->find(Tweet::CLASSNAME, $tweet->id);
+        $this->assertInstanceOf(
+            Tweet::CLASSNAME,
+            $tweet,
+            'Even though the collection is extra lazy, the tweet should not have been deleted'
+        );
+
+        $this->assertNull($tweet->author);
+
+        /* @var $user User */
+        $user = $this->_em->find(User::CLASSNAME, $userId);
+
+        $this->assertCount(1, $user->tweets, 'Element was not removed - need to update the owning side first');
+    }
+
+    /**
+     * @return int[] ordered tuple: user id and tweet id
+     */
+    private function loadTweetFixture()
+    {
+        $user  = new User();
+        $tweet = new Tweet();
+
+        $user->name     = 'ocramius';
+        $tweet->content = 'The cat is on the table';
+
+        $user->addTweet($tweet);
+
+        $this->_em->persist($user);
+        $this->_em->persist($tweet);
+        $this->_em->flush();
+        $this->_em->clear();
+
+        return array($user->id, $tweet->id);
     }
 
     /**

From 94c0e46c96e5be6eba2033a9bb313e51ba1d2ef9 Mon Sep 17 00:00:00 2001
From: Marco Pivetta <ocramius@gmail.com>
Date: Tue, 27 Jan 2015 06:26:55 +0100
Subject: [PATCH 02/12]  #1169 DDC-3343 - updating test expectations -
 one-to-many changes should be no-op unless orphan removal is specified.

---
 tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php b/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
index ab160d384..2aea54200 100644
--- a/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
@@ -730,7 +730,7 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
             'Even though the collection is extra lazy, the tweet should not have been deleted'
         );
 
-        $this->assertNull($tweet->author);
+        $this->assertInstanceOf(User::CLASSNAME, $tweet->author);
 
         /* @var $user User */
         $user = $this->_em->find(User::CLASSNAME, $userId);

From cbe5575f3877a23c725d030e98b2cad389235ca5 Mon Sep 17 00:00:00 2001
From: Marco Pivetta <ocramius@gmail.com>
Date: Tue, 27 Jan 2015 07:42:48 +0100
Subject: [PATCH 03/12]  #1169 DDC-3343 - adding tests for orphan-removal +
 extra-lazy + one-to-many element removal behavior

---
 tests/Doctrine/Tests/Models/Tweet/User.php    |  14 ++-
 .../Doctrine/Tests/Models/Tweet/UserList.php  |  29 +++++
 .../Functional/ExtraLazyCollectionTest.php    | 105 +++++++++++++++++-
 .../Doctrine/Tests/OrmFunctionalTestCase.php  |  11 ++
 4 files changed, 155 insertions(+), 4 deletions(-)
 create mode 100644 tests/Doctrine/Tests/Models/Tweet/UserList.php

diff --git a/tests/Doctrine/Tests/Models/Tweet/User.php b/tests/Doctrine/Tests/Models/Tweet/User.php
index 4722e6317..68cf137f2 100644
--- a/tests/Doctrine/Tests/Models/Tweet/User.php
+++ b/tests/Doctrine/Tests/Models/Tweet/User.php
@@ -29,9 +29,15 @@ class User
      */
     public $tweets;
 
+    /**
+     * @OneToMany(targetEntity="UserList", mappedBy="owner", fetch="EXTRA_LAZY", orphanRemoval=true)
+     */
+    public $userLists;
+
     public function __construct()
     {
-        $this->tweets = new ArrayCollection();
+        $this->tweets    = new ArrayCollection();
+        $this->userLists = new ArrayCollection();
     }
 
     public function addTweet(Tweet $tweet)
@@ -39,4 +45,10 @@ class User
         $tweet->setAuthor($this);
         $this->tweets->add($tweet);
     }
+
+    public function addUserList(UserList $userList)
+    {
+        $userList->owner = $this;
+        $this->userLists->add($userList);
+    }
 }
diff --git a/tests/Doctrine/Tests/Models/Tweet/UserList.php b/tests/Doctrine/Tests/Models/Tweet/UserList.php
new file mode 100644
index 000000000..1eb3e141f
--- /dev/null
+++ b/tests/Doctrine/Tests/Models/Tweet/UserList.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace Doctrine\Tests\Models\Tweet;
+
+/**
+ * @Entity
+ * @Table(name="tweet_user_list")
+ */
+class UserList
+{
+    const CLASSNAME = __CLASS__;
+
+    /**
+     * @Id
+     * @GeneratedValue
+     * @Column(type="integer")
+     */
+    public $id;
+
+    /**
+     * @Column(type="string")
+     */
+    public $listName;
+
+    /**
+     * @ManyToOne(targetEntity="User", inversedBy="userLists")
+     */
+    public $owner;
+}
diff --git a/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php b/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
index 2aea54200..6633f0c24 100644
--- a/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
@@ -5,6 +5,8 @@ namespace Doctrine\Tests\ORM\Functional;
 use Doctrine\ORM\Mapping\ClassMetadataInfo;
 use Doctrine\Tests\Models\Tweet\Tweet;
 use Doctrine\Tests\Models\Tweet\User;
+use Doctrine\Tests\Models\Tweet\UserList;
+use Doctrine\Tests\OrmFunctionalTestCase;
 
 require_once __DIR__ . '/../../TestInit.php';
 
@@ -685,10 +687,9 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
 
         /* @var $user User */
         $user  = $this->_em->find(User::CLASSNAME, $userId);
+        $tweet = $this->_em->find(Tweet::CLASSNAME, $tweetId);
 
-        $e = $this->_em->find(Tweet::CLASSNAME, $tweetId);
-
-        $user->tweets->removeElement($e);
+        $user->tweets->removeElement($tweet);
 
         $this->_em->clear();
 
@@ -835,6 +836,83 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
         $this->assertCount(0, $user->tweets);
     }
 
+    /**
+     * @group DDC-3343
+     */
+    public function testRemoveOrphanedManagedElementFromOneToManyExtraLazyCollection()
+    {
+        list($userId, $userListId) = $this->loadUserListFixture();
+
+        /* @var $user User */
+        $user = $this->_em->find(User::CLASSNAME, $userId);
+
+        $user->tweets->removeElement($this->_em->find(UserList::CLASSNAME, $userListId));
+
+        $this->_em->clear();
+
+        /* @var $user User */
+        $user = $this->_em->find(User::CLASSNAME, $userId);
+
+        $this->assertCount(0, $user->userLists, 'Element was removed from association due to orphan removal');
+        $this->assertNull(
+            $this->_em->find(UserList::CLASSNAME, $userListId),
+            'Element was deleted due to orphan removal'
+        );
+    }
+
+    /**
+     * @group DDC-3343
+     */
+    public function testRemoveOrphanedUnManagedElementFromOneToManyExtraLazyCollection()
+    {
+        list($userId, $userListId) = $this->loadUserListFixture();
+
+        /* @var $user User */
+        $user = $this->_em->find(User::CLASSNAME, $userId);
+
+        $user->userLists->removeElement(new UserList());
+
+        $this->_em->clear();
+
+        /* @var $userList UserList */
+        $userList = $this->_em->find(UserList::CLASSNAME, $userListId);
+        $this->assertInstanceOf(
+            UserList::CLASSNAME,
+            $userList,
+            'Even though the collection is extra lazy + orphan removal, the user list should not have been deleted'
+        );
+
+        $this->assertInstanceOf(
+            User::CLASSNAME,
+            $userList->owner,
+            'User list to owner link has not been removed'
+        );
+    }
+
+    /**
+     * @group DDC-3343
+     */
+    public function testRemoveOrphanedManagedLazyProxyFromExtraLazyOneToMany()
+    {
+        list($userId, $userListId) = $this->loadUserListFixture();
+
+        /* @var $user User */
+        $user = $this->_em->find(User::CLASSNAME, $userId);
+
+        $user->tweets->removeElement($this->_em->getReference(UserList::CLASSNAME, $userListId));
+
+        $this->_em->clear();
+
+        /* @var $user User */
+        $user = $this->_em->find(User::CLASSNAME, $userId);
+
+        $this->assertCount(0, $user->userLists, 'Element was removed from association due to orphan removal');
+        $this->assertNull(
+            $this->_em->find(UserList::CLASSNAME, $userListId),
+            'Element was deleted due to orphan removal'
+        );
+    }
+
     /**
      * @return int[] ordered tuple: user id and tweet id
      */
@@ -855,4 +933,25 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
 
         return array($user->id, $tweet->id);
     }
+
+    /**
+     * @return int[] ordered tuple: user id and user list id
+     */
+    private function loadUserListFixture()
+    {
+        $user     = new User();
+        $userList = new UserList();
+
+        $user->name     = 'ocramius';
+        $userList->listName = 'PHP Developers to follow closely';
+
+        $user->addUserList($userList);
+
+        $this->_em->persist($user);
+        $this->_em->persist($userList);
+        $this->_em->flush();
+        $this->_em->clear();
+
+        return array($user->id, $userList->id);
+    }
 }
diff --git a/tests/Doctrine/Tests/OrmFunctionalTestCase.php b/tests/Doctrine/Tests/OrmFunctionalTestCase.php
index ff0f2cb53..b9ccbcb66 100644
--- a/tests/Doctrine/Tests/OrmFunctionalTestCase.php
+++ b/tests/Doctrine/Tests/OrmFunctionalTestCase.php
@@ -166,6 +166,11 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
             'Doctrine\Tests\Models\Taxi\Car',
             'Doctrine\Tests\Models\Taxi\Driver',
         ),
+        'tweet' => array(
+            'Doctrine\Tests\Models\Tweet\User',
+            'Doctrine\Tests\Models\Tweet\Tweet',
+            'Doctrine\Tests\Models\Tweet\UserList',
+        ),
     );
 
     /**
@@ -305,6 +310,12 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
             $conn->executeUpdate('DELETE FROM taxi_driver');
         }
 
+        if (isset($this->_usedModelSets['tweet'])) {
+            $conn->executeUpdate('DELETE FROM tweet_tweet');
+            $conn->executeUpdate('DELETE FROM tweet_user_list');
+            $conn->executeUpdate('DELETE FROM tweet_user');
+        }
+
         $this->_em->clear();
     }
 

From fac410b213e941736f0fb952bdf1e63b83085114 Mon Sep 17 00:00:00 2001
From: Marco Pivetta <ocramius@gmail.com>
Date: Thu, 29 Jan 2015 18:39:30 +0000
Subject: [PATCH 04/12]  #1169 DDC-3343 - aligning test suite logic to the 2.5
 branch (failing tests)

---
 tests/Doctrine/Tests/Models/Tweet/Tweet.php         | 13 ++++++++-----
 .../ORM/Functional/ExtraLazyCollectionTest.php      |  1 +
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/tests/Doctrine/Tests/Models/Tweet/Tweet.php b/tests/Doctrine/Tests/Models/Tweet/Tweet.php
index 8a315df9e..14411dc2a 100644
--- a/tests/Doctrine/Tests/Models/Tweet/Tweet.php
+++ b/tests/Doctrine/Tests/Models/Tweet/Tweet.php
@@ -18,17 +18,20 @@ class Tweet
     public $id;
 
     /**
-     * @Column(type="string")
+     * @Column(type="string", length=140)
      */
-    public $content;
+    public $content = '';
 
     /**
-     * @ManyToOne(targetEntity="User", inversedBy="tweets")
+     * @ManyToOne(targetEntity="User", inversedBy="tweets", cascade={"persist"}, fetch="EXTRA_LAZY")
      */
     public $author;
 
-    public function setAuthor(User $user)
+    /**
+     * @param User $author
+     */
+    public function setAuthor(User $author)
     {
-        $this->author = $user;
+        $this->user = $author;
     }
 }
diff --git a/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php b/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
index 6633f0c24..2c6fd6faf 100644
--- a/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
@@ -28,6 +28,7 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
     {
         $this->useModelSet('tweet');
         $this->useModelSet('cms');
+        $this->useModelSet('tweet');
         parent::setUp();
 
         $class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');

From 4884183b957dd2e481ba17f203a863b8424ba809 Mon Sep 17 00:00:00 2001
From: Marco Pivetta <ocramius@gmail.com>
Date: Thu, 5 Feb 2015 00:11:19 +0000
Subject: [PATCH 05/12]  #1169 DDC-3343 - fixing test case typos (referencing
 wrong/inexisting properties, inexisting owning side assigned

---
 tests/Doctrine/Tests/Models/Tweet/Tweet.php              | 2 +-
 .../Tests/ORM/Functional/ExtraLazyCollectionTest.php     | 9 ++++-----
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/tests/Doctrine/Tests/Models/Tweet/Tweet.php b/tests/Doctrine/Tests/Models/Tweet/Tweet.php
index 14411dc2a..9f564e27b 100644
--- a/tests/Doctrine/Tests/Models/Tweet/Tweet.php
+++ b/tests/Doctrine/Tests/Models/Tweet/Tweet.php
@@ -32,6 +32,6 @@ class Tweet
      */
     public function setAuthor(User $author)
     {
-        $this->user = $author;
+        $this->author = $author;
     }
 }
diff --git a/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php b/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
index 2c6fd6faf..daf7a2613 100644
--- a/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
@@ -369,8 +369,7 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
         $user->articles->removeElement($article);
 
         $this->assertFalse($user->articles->isInitialized(), "Post-Condition: Collection is not initialized.");
-        // NOTE: +2 queries because CmsArticle is a versioned entity, and that needs to be handled accordingly
-        $this->assertEquals($queryCount + 2, $this->getCurrentQueryCount());
+        $this->assertEquals($queryCount, $this->getCurrentQueryCount());
 
         // Test One to Many removal with Entity state as new
         $article = new \Doctrine\Tests\Models\CMS\CmsArticle();
@@ -391,7 +390,7 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
 
         $user->articles->removeElement($article);
 
-        $this->assertEquals($queryCount, $this->getCurrentQueryCount(), "Removing a persisted entity will not cause queries when the owning side doesn't actually change.");
+        $this->assertEquals($queryCount, $this->getCurrentQueryCount(), "Removing a persisted entity should cause one query to be executed.");
         $this->assertFalse($user->articles->isInitialized(), "Post-Condition: Collection is not initialized.");
 
         // Test One to Many removal with Entity state as managed
@@ -847,7 +846,7 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
         /* @var $user User */
         $user = $this->_em->find(User::CLASSNAME, $userId);
 
-        $user->tweets->removeElement($this->_em->find(UserList::CLASSNAME, $userListId));
+        $user->userLists->removeElement($this->_em->find(UserList::CLASSNAME, $userListId));
 
         $this->_em->clear();
 
@@ -900,7 +899,7 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
         /* @var $user User */
         $user = $this->_em->find(User::CLASSNAME, $userId);
 
-        $user->tweets->removeElement($this->_em->getReference(UserList::CLASSNAME, $userListId));
+        $user->userLists->removeElement($this->_em->getReference(UserList::CLASSNAME, $userListId));
 
         $this->_em->clear();
 

From 4bed15b9846932929294e6a0969ba8d867f428cc Mon Sep 17 00:00:00 2001
From: Marco Pivetta <ocramius@gmail.com>
Date: Thu, 5 Feb 2015 00:11:53 +0000
Subject: [PATCH 06/12]  #1169 DDC-3343 - one-to-many persister should only
 interact with the data when `orphanRemoval` and `EXTRA_LAZY` are combined

---
 lib/Doctrine/ORM/Persisters/OneToManyPersister.php | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/lib/Doctrine/ORM/Persisters/OneToManyPersister.php b/lib/Doctrine/ORM/Persisters/OneToManyPersister.php
index cf39436d4..6e02272f4 100644
--- a/lib/Doctrine/ORM/Persisters/OneToManyPersister.php
+++ b/lib/Doctrine/ORM/Persisters/OneToManyPersister.php
@@ -223,6 +223,13 @@ class OneToManyPersister extends AbstractCollectionPersister
      */
     public function removeElement(PersistentCollection $coll, $element)
     {
+        $mapping = $coll->getMapping();
+
+        if ( ! $mapping['orphanRemoval']) {
+            // no-op: this is not the owning side, therefore no operations should be applied
+            return false;
+        }
+
         $uow = $this->em->getUnitOfWork();
 
         // shortcut for new entities
@@ -238,9 +245,9 @@ class OneToManyPersister extends AbstractCollectionPersister
             return false;
         }
 
-        $mapping        = $coll->getMapping();
-        $persister      = $this->uow->getEntityPersister($mapping['targetEntity']);
-        $targetMetadata = $this->em->getClassMetadata($mapping['targetEntity']);
+        $class = $this->em->getClassMetadata($mapping['targetEntity']);
+        $sql   = 'DELETE FROM ' . $this->quoteStrategy->getTableName($class, $this->platform)
+            . ' WHERE ' . implode('= ? AND ', $class->getIdentifierColumnNames()) . ' = ?';
 
         if ($element instanceof Proxy && ! $element->__isInitialized()) {
             $element->__load();

From c6e7a8184973a4dc8432b9ce603bf9c422478594 Mon Sep 17 00:00:00 2001
From: Marco Pivetta <ocramius@gmail.com>
Date: Thu, 5 Feb 2015 00:21:28 +0000
Subject: [PATCH 07/12] #1169 DDC-3343 - removing duplicate test method

---
 .../Functional/ExtraLazyCollectionTest.php    | 55 +------------------
 1 file changed, 1 insertion(+), 54 deletions(-)

diff --git a/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php b/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
index daf7a2613..06223e4e0 100644
--- a/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
@@ -6,7 +6,6 @@ use Doctrine\ORM\Mapping\ClassMetadataInfo;
 use Doctrine\Tests\Models\Tweet\Tweet;
 use Doctrine\Tests\Models\Tweet\User;
 use Doctrine\Tests\Models\Tweet\UserList;
-use Doctrine\Tests\OrmFunctionalTestCase;
 
 require_once __DIR__ . '/../../TestInit.php';
 
@@ -29,6 +28,7 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
         $this->useModelSet('tweet');
         $this->useModelSet('cms');
         $this->useModelSet('tweet');
+
         parent::setUp();
 
         $class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
@@ -655,7 +655,6 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
 
         $this->topic = $article1->topic;
         $this->phonenumber = $phonenumber1->phonenumber;
-
     }
 
     /**
@@ -739,27 +738,6 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
         $this->assertCount(1, $user->tweets, 'Element was not removed - need to update the owning side first');
     }
 
-    /**
-     * @return int[] ordered tuple: user id and tweet id
-     */
-    private function loadTweetFixture()
-    {
-        $user  = new User();
-        $tweet = new Tweet();
-
-        $user->name     = 'ocramius';
-        $tweet->content = 'The cat is on the table';
-
-        $user->addTweet($tweet);
-
-        $this->_em->persist($user);
-        $this->_em->persist($tweet);
-        $this->_em->flush();
-        $this->_em->clear();
-
-        return array($user->id, $tweet->id);
-    }
-
     /**
      * @group DDC-3343
      */
@@ -805,37 +783,6 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
         $this->assertNull($tweet->author, 'Tweet author link has been removed');
     }
 
-    /**
-     * @group DDC-3343
-     */
-    public function testRemovingManagedLazyProxyFromExtraLazyOneToManyDoesRemoveTheAssociationButNotTheEntity()
-    {
-        list($userId, $tweetId) = $this->loadTweetFixture();
-
-        /* @var $user User */
-        $user  = $this->_em->find(User::CLASSNAME, $userId);
-        $tweet = $this->_em->getReference(Tweet::CLASSNAME, $tweetId);
-
-        $user->tweets->removeElement($this->_em->getReference(Tweet::CLASSNAME, $tweetId));
-
-        $this->_em->clear();
-
-        /* @var $tweet Tweet */
-        $tweet = $this->_em->find(Tweet::CLASSNAME, $tweet->id);
-        $this->assertInstanceOf(
-            Tweet::CLASSNAME,
-            $tweet,
-            'Even though the collection is extra lazy, the tweet should not have been deleted'
-        );
-
-        $this->assertNull($tweet->author);
-
-        /* @var $user User */
-        $user = $this->_em->find(User::CLASSNAME, $userId);
-
-        $this->assertCount(0, $user->tweets);
-    }
-
     /**
      * @group DDC-3343
      */

From c4ab4db743869f0ffd4e3efa3ece8b9e7733784a Mon Sep 17 00:00:00 2001
From: Marco Pivetta <ocramius@gmail.com>
Date: Thu, 5 Feb 2015 00:23:51 +0000
Subject: [PATCH 08/12] #1169 DDC-3343 - remove duplicate tests introduced by
 cherry-picking conflicts

---
 .../Functional/ExtraLazyCollectionTest.php    | 45 -------------------
 1 file changed, 45 deletions(-)

diff --git a/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php b/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
index 06223e4e0..8cb85b138 100644
--- a/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php
@@ -738,51 +738,6 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
         $this->assertCount(1, $user->tweets, 'Element was not removed - need to update the owning side first');
     }
 
-    /**
-     * @group DDC-3343
-     */
-    public function testRemovesManagedElementFromOneToManyExtraLazyCollection()
-    {
-        list($userId, $tweetId) = $this->loadTweetFixture();
-
-        /* @var $user User */
-        $user = $this->_em->find(User::CLASSNAME, $userId);
-
-        $user->tweets->removeElement($this->_em->find(Tweet::CLASSNAME, $tweetId));
-
-        $this->_em->clear();
-
-        /* @var $user User */
-        $user = $this->_em->find(User::CLASSNAME, $userId);
-
-        $this->assertCount(0, $user->tweets);
-    }
-
-    /**
-     * @group DDC-3343
-     */
-    public function testRemovesManagedElementFromOneToManyExtraLazyCollectionWithoutDeletingTheTargetEntityEntry()
-    {
-        list($userId, $tweetId) = $this->loadTweetFixture();
-
-        /* @var $user User */
-        $user  = $this->_em->find(User::CLASSNAME, $userId);
-
-        $user->tweets->removeElement($this->_em->find(Tweet::CLASSNAME, $tweetId));
-
-        $this->_em->clear();
-
-        /* @var $tweet Tweet */
-        $tweet = $this->_em->find(Tweet::CLASSNAME, $tweetId);
-        $this->assertInstanceOf(
-            Tweet::CLASSNAME,
-            $tweet,
-            'Even though the collection is extra lazy, the tweet should not have been deleted'
-        );
-
-        $this->assertNull($tweet->author, 'Tweet author link has been removed');
-    }
-
     /**
      * @group DDC-3343
      */

From 2fa48c6e8860bd056c9ff48fae9ea33a48e632c6 Mon Sep 17 00:00:00 2001
From: Marco Pivetta <ocramius@gmail.com>
Date: Thu, 5 Feb 2015 00:25:06 +0000
Subject: [PATCH 09/12] #1169 DDC-3343 - actually deleting associated elements
 when they are orphaned and EXTRA_LAZY is used

---
 lib/Doctrine/ORM/Persisters/OneToManyPersister.php | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/lib/Doctrine/ORM/Persisters/OneToManyPersister.php b/lib/Doctrine/ORM/Persisters/OneToManyPersister.php
index 6e02272f4..539f13b14 100644
--- a/lib/Doctrine/ORM/Persisters/OneToManyPersister.php
+++ b/lib/Doctrine/ORM/Persisters/OneToManyPersister.php
@@ -249,16 +249,6 @@ class OneToManyPersister extends AbstractCollectionPersister
         $sql   = 'DELETE FROM ' . $this->quoteStrategy->getTableName($class, $this->platform)
             . ' WHERE ' . implode('= ? AND ', $class->getIdentifierColumnNames()) . ' = ?';
 
-        if ($element instanceof Proxy && ! $element->__isInitialized()) {
-            $element->__load();
-        }
-
-        // clearing owning side value
-        $targetMetadata->reflFields[$mapping['mappedBy']]->setValue($element, null);
-
-        $this->uow->computeChangeSet($targetMetadata, $element);
-        $persister->update($element);
-
-        return true;
+        return (bool) $this->conn->executeUpdate($sql, $this->getDeleteRowSQLParameters($coll, $element));
     }
 }

From a1bd3e8cc9b36f180816917aa956251949c87a63 Mon Sep 17 00:00:00 2001
From: Marco Pivetta <ocramius@gmail.com>
Date: Thu, 5 Feb 2015 00:25:20 +0000
Subject: [PATCH 10/12] #1169 DDC-3343 - optimized imports

---
 lib/Doctrine/ORM/Persisters/OneToManyPersister.php | 1 -
 1 file changed, 1 deletion(-)

diff --git a/lib/Doctrine/ORM/Persisters/OneToManyPersister.php b/lib/Doctrine/ORM/Persisters/OneToManyPersister.php
index 539f13b14..6e43ef29e 100644
--- a/lib/Doctrine/ORM/Persisters/OneToManyPersister.php
+++ b/lib/Doctrine/ORM/Persisters/OneToManyPersister.php
@@ -19,7 +19,6 @@
 
 namespace Doctrine\ORM\Persisters;
 
-use Doctrine\Common\Proxy\Proxy;
 use Doctrine\ORM\PersistentCollection;
 use Doctrine\ORM\UnitOfWork;
 

From f5705d6d954c97d98bbb00d4e0eaaed36edf1d92 Mon Sep 17 00:00:00 2001
From: Marco Pivetta <ocramius@gmail.com>
Date: Thu, 5 Feb 2015 00:52:54 +0000
Subject: [PATCH 11/12] #1169 DDC-3343 - corrected persister logic - only uses
 the entity persister to perform deletes on the owning side

---
 lib/Doctrine/ORM/Persisters/OneToManyPersister.php | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/lib/Doctrine/ORM/Persisters/OneToManyPersister.php b/lib/Doctrine/ORM/Persisters/OneToManyPersister.php
index 6e43ef29e..b1ff59cdc 100644
--- a/lib/Doctrine/ORM/Persisters/OneToManyPersister.php
+++ b/lib/Doctrine/ORM/Persisters/OneToManyPersister.php
@@ -244,10 +244,11 @@ class OneToManyPersister extends AbstractCollectionPersister
             return false;
         }
 
-        $class = $this->em->getClassMetadata($mapping['targetEntity']);
-        $sql   = 'DELETE FROM ' . $this->quoteStrategy->getTableName($class, $this->platform)
-            . ' WHERE ' . implode('= ? AND ', $class->getIdentifierColumnNames()) . ' = ?';
+        $this
+            ->uow
+            ->getEntityPersister($mapping['targetEntity'])
+            ->delete($element);
 
-        return (bool) $this->conn->executeUpdate($sql, $this->getDeleteRowSQLParameters($coll, $element));
+        return true;
     }
 }

From 11936a6cac1a3100d0cc4cafa713bbcd57b124d7 Mon Sep 17 00:00:00 2001
From: Marco Pivetta <ocramius@gmail.com>
Date: Thu, 5 Feb 2015 00:53:34 +0000
Subject: [PATCH 12/12] #1169 DDC-3343 - correcting functional test case
 cleanup logic (sorting deletes by FK dependencies)

---
 tests/Doctrine/Tests/OrmFunctionalTestCase.php | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/Doctrine/Tests/OrmFunctionalTestCase.php b/tests/Doctrine/Tests/OrmFunctionalTestCase.php
index b9ccbcb66..479887b92 100644
--- a/tests/Doctrine/Tests/OrmFunctionalTestCase.php
+++ b/tests/Doctrine/Tests/OrmFunctionalTestCase.php
@@ -280,6 +280,7 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
         }
         if (isset($this->_usedModelSets['tweet'])) {
             $conn->executeUpdate('DELETE FROM tweet_tweet');
+            $conn->executeUpdate('DELETE FROM tweet_user_list');
             $conn->executeUpdate('DELETE FROM tweet_user');
         }
         if (isset($this->_usedModelSets['legacy'])) {