1<?php
2
3/**
4 * @author Donald Ball
5 */
6class Doctrine_Ticket_966_TestCase extends Doctrine_UnitTestCase
7{
8
9  public function prepareTables()
10  {
11    $this->tables = array('Semester', 'Course', 'Weekday', 'CourseWeekday');
12    parent::prepareTables();
13  }
14
15  public function prepareData()
16  {
17    $semester = new Semester();
18    $semester['name'] = 'Semester';
19    $semester->save();
20
21    foreach (array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday') as $name)
22    {
23      $weekday = new Weekday();
24      $weekday['name'] = $name;
25      $weekday->save();
26    }
27
28    for ($i=0; $i<3; $i++)
29    {
30      $course = new Course();
31      $course['name'] = 'Course ' . $i;
32      $course['Semester'] = $semester;
33      $course->save();
34      for ($w = 3; $w <6; $w++)
35      {
36        $cw = new CourseWeekday();
37        $cw['Course'] = $course;
38        $cw['weekday_id'] = $w;
39        $cw->save();
40      }
41    }
42  }
43
44  public function testArrayHydration()
45  {
46    $query = Doctrine_Query::create()
47      ->from('Semester s')
48      ->leftJoin('s.Courses c')
49      ->leftJoin('c.Weekdays cw');
50
51    $semesters = $query->execute(array(), Doctrine_Core::HYDRATE_ARRAY);
52    $semester = $semesters[0];
53
54    $this->assertAllWeekdaysArePopulated($semester);
55  }
56
57  public function testObjectHydration()
58  {
59    $query = Doctrine_Query::create()
60      ->from('Semester s')
61      ->leftJoin('s.Courses c')
62      ->leftJoin('c.Weekdays cw');
63
64    $semester = $query->execute()->getFirst();
65
66    $weekdayOids = array();
67    foreach ($semester->Courses as $course) {
68        foreach ($course->Weekdays as $weekday) {
69            if ( ! in_array($weekday->getOid(), $weekdayOids)) {
70                $weekdayOids[] = $weekday->getOid();
71            }
72            $this->assertTrue(is_numeric($weekday->id));
73            $this->assertTrue(is_string($weekday->name));
74        }
75    }
76    // should be only 3 weekday objects in total
77    $this->assertEqual(3, count($weekdayOids));
78
79    $queryCountBefore = $this->conn->count();
80    $this->assertAllWeekdaysArePopulated($semester);
81    $this->assertEqual($queryCountBefore, $this->conn->count());
82  }
83
84  public function testLazyObjectHydration()
85  {
86      // clear identity maps to make sure we're starting with a clean plate
87    $this->conn->getTable('Course')->clear();
88    $this->conn->getTable('Weekday')->clear();
89    $this->conn->getTable('Semester')->clear();
90    $query = Doctrine_Query::create()->from('Semester s');
91
92    $semester = $query->execute()->getFirst();
93    $queryCountBefore = $this->conn->count();
94    $this->assertAllWeekdaysArePopulated($semester);
95    // expecting 4 additional queries: 1 to fetch the courses for the only semester and
96    // 1 for each weekday collection for each of the three courses.
97    $this->assertEqual($queryCountBefore + 4, $this->conn->count());
98  }
99
100  private function assertAllWeekdaysArePopulated($semester)
101  {
102    foreach ($semester['Courses'] as $course)
103    {
104      foreach ($course['Weekdays'] as $weekday)
105      {
106            $this->assertTrue(is_numeric($weekday['id']));
107            $this->assertTrue(is_string($weekday['name']));
108      }
109    }
110  }
111
112}
113
114class Semester extends Doctrine_Record
115{
116
117  public function setTableDefinition()
118  {
119    $this->setTableName('semester');
120    $this->hasColumn('id', 'integer', 4, array('primary'=>'true', 'autoincrement'=>'true'));
121    $this->hasColumn('name', 'string', 255, array('notnull' => true));
122  }
123
124  public function setUp()
125  {
126    parent::setUp();
127    $this->hasMany('Course as Courses', array('local'=>'id', 'foreign'=>'semester_id'));
128  }
129
130}
131
132class Weekday extends Doctrine_Record
133{
134
135  public function setTableDefinition()
136  {
137    $this->setTableName('weekday');
138    $this->hasColumn('id', 'integer', 4, array('primary' => true, 'autoincrement' => true));
139    $this->hasColumn('name', 'string', 9, array('notnull' => true, 'unique' => true));
140  }
141
142  public function setUp()
143  {
144      // need to make the many-many bidirectional in order for the lazy-loading test to work.
145      // lazy-loading the weekdays ($course['Weekdays']) doesnt work when the relation is
146      // set up unidirectional. this is true for all many-many relations.
147      $this->hasMany('Course as courses',
148        array('refClass'=>'CourseWeekday', 'local'=>'weekday_id', 'foreign'=>'course_id'));
149  }
150}
151
152class Course extends Doctrine_Record
153{
154
155  public function setTableDefinition()
156  {
157    $this->setTableName('course');
158    $this->hasColumn('id', 'integer', 4, array('primary'=>'true', 'autoincrement'=>'true'));
159    $this->hasColumn('semester_id', 'integer', 4, array('notnull'=>true));
160    $this->hasColumn('name', 'string', 255, array('notnull' => true));
161  }
162
163  public function setUp()
164  {
165    parent::setUp();
166    $this->hasOne('Semester', array('local' => 'semester_id',
167                                    'foreign' => 'id',
168                                    'onDelete' => 'CASCADE'));
169    $this->hasMany('Weekday as Weekdays',
170      array('refClass'=>'CourseWeekday', 'local'=>'course_id', 'foreign'=>'weekday_id'));
171  }
172
173}
174
175class CourseWeekday extends Doctrine_Record
176{
177
178  public function setTableDefinition()
179  {
180    $this->setTableName('course_weekday');
181    # Poor form to have an id on a join table, but that's what we were doing
182    $this->hasColumn('id', 'integer', 4, array('primary' => true, 'autoincrement' => true));
183    $this->hasColumn('course_id', 'integer', 4, array('notnull' => true));
184    $this->hasColumn('weekday_id', 'integer', 4, array('notnull' => true));
185  }
186
187  public function setUp()
188  {
189    parent::setUp();
190    $this->hasOne('Course', array('local'=>'course_id', 'foreign'=>'id', 'onDelete'=>'CASCADE'));
191    $this->hasOne('Weekday', array('local'=>'weekday_id', 'foreign'=>'id', 'onDelete'=>'CASCADE'));
192  }
193
194}
195