1<?php
2/*
3 *  $Id$
4 *
5 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
10 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
11 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
15 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 *
17 * This software consists of voluntary contributions made by many individuals
18 * and is licensed under the LGPL. For more information, see
19 * <http://www.doctrine-project.org>.
20 */
21
22/**
23 * Doctrine_Ticket_1623_TestCase
24 *
25 * @package     Doctrine
26 * @author      floriank
27 * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
28 * @category    Object Relational Mapping
29 * @link        www.doctrine-project.org
30 * @since       1.1
31 * @version     $Revision$
32 */
33class Doctrine_Ticket_1623_TestCase extends Doctrine_UnitTestCase
34{
35    public function prepareTables()
36    {
37        $this->tables = array();
38        $this->tables[] = 'Ticket_1623_User';
39        $this->tables[] = 'Ticket_1623_UserReference';
40        parent::prepareTables();
41    }
42
43    public function prepareData()
44    {
45        $firstUser = null;
46        $oldUser = null;
47
48        for ($i = 1; $i <= 20; $i++) {
49            $userI = $user = new Ticket_1623_User();
50            $userI->name = "test$i";
51            for ($j = 1; $j <= 20; $j++) {
52                $userJ = new Ticket_1623_User();
53                $userJ->name = "test$i-$j";
54                $userI->children[] = $userJ;
55                $userJ->save();
56            }
57            $userI->save();
58            $floriankChilds[] = $userI;
59        }
60
61        $user = new Ticket_1623_User();
62        $user->name = "floriank";
63        foreach ($floriankChilds as $child) {
64            $user->children[] = $child;
65        }
66        $user->save();
67    }
68
69    public function testPerformance()
70    {
71        Doctrine_Manager::getInstance()->setAttribute(Doctrine_Core::ATTR_VALIDATE, Doctrine_Core::VALIDATE_ALL);
72
73        $newChild = new Ticket_1623_User();
74        $newChild->name = 'myChild';
75        $newChild->save();
76
77        $user = Doctrine_Core::getTable('Ticket_1623_User')->findOneByName('floriank');
78        $user->children[] = $newChild;
79
80        $start = microtime(true);
81        $user->save();
82        $end = microtime(true);
83        $diff = $end - $start;
84        //assuming save() should not take longer than one second
85        $this->assertTrue($diff < 1);
86    }
87
88    public function testImplicitSave()
89    {
90        Doctrine_Manager::getInstance()->setAttribute(Doctrine_Core::ATTR_VALIDATE, Doctrine_Core::VALIDATE_ALL);
91        Doctrine_Manager::getInstance()->setAttribute(Doctrine_Core::ATTR_CASCADE_SAVES, false);
92
93        $newChild = new Ticket_1623_User();
94        $newChild->name = 'myGrandGrandChild';
95
96        $user = Doctrine_Core::getTable('Ticket_1623_User')->findOneByName('floriank');
97        $user->children[0]->children[0]->children[] = $newChild;
98
99        $user->save();
100
101        $user = Doctrine_Core::getTable('Ticket_1623_User')->findByName('myGrandGrandChild');
102        //as of Doctrine's default behaviour $newChild should have
103        //been implicitly saved with $user->save()
104        $this->assertEqual($user->count(), 0);
105
106        Doctrine_Manager::getInstance()->setAttribute(Doctrine_Core::ATTR_VALIDATE, Doctrine_Core::VALIDATE_NONE);
107        Doctrine_Manager::getInstance()->setAttribute(Doctrine_Core::ATTR_CASCADE_SAVES, true);
108    }
109}
110
111class Ticket_1623_User extends Doctrine_Record
112{
113    public function setTableDefinition()
114    {
115        $this->hasColumn('id', 'integer', null, array('primary' => true, 'autoincrement' => true));
116        $this->hasColumn('name', 'string', 30);
117    }
118
119    public function setUp()
120    {
121        $this->hasMany('Ticket_1623_User as parents',
122                                                array('local'    => 'parentId',
123                                                'refClass' => 'Ticket_1623_UserReference',
124                                                'foreign'  => 'childId',
125                                                'refClassRelationAlias' => 'childrenLinks'
126                                                ));
127
128        $this->hasMany('Ticket_1623_User as children',
129                                                 array('local'    => 'childId',
130                                                 'foreign'  => 'parentId',
131                                                 'refClass' => 'Ticket_1623_UserReference',
132                                                 'refClassRelationAlias' => 'parentLinks'
133                                                 ));
134    }
135
136    protected function validate()
137    {
138        // lets get some silly load in the validation:
139        // we do not want any child or parent to have the name 'caesar'
140        $unwantedName = false;
141        foreach ($this->children as $child) {
142            if ($child->name == 'caesar') {
143                $unwantedName = true;
144            }
145        }
146
147        foreach ($this->children as $child) {
148            if ($child->name == 'caesar') {
149                $unwantedName = true;
150            }
151        }
152
153        if ($unwantedName) {
154            $this->errorStack()->add('children', 'no child should have the name \'caesar\'');
155        }
156    }
157}
158
159class Ticket_1623_UserReference extends Doctrine_Record
160{
161    public function setTableDefinition()
162    {
163        $this->hasColumn('parent_id as parentId', 'integer', null, array('primary' => true));
164        $this->hasColumn('child_id as childId', 'integer', null, array('primary' => true));
165    }
166}