PageRenderTime 45ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/propel_15/vendor/propel/test/testsuite/generator/behavior/nestedset/NestedSetBehaviorObjectBuilderModifierTest.php

http://github.com/eventhorizonpl/forked-php-orm-benchmark
PHP | 1521 lines | 1058 code | 59 blank | 404 comment | 0 complexity | 04231140b21dbb86fe87b05add302c01 MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-3.0
  1. <?php
  2. /*
  3. * $Id: NestedSetBehaviorObjectBuilderModifierTest.php 2167 2011-01-20 14:12:28Z francois $
  4. * This file is part of the Propel package.
  5. * For the full copyright and license information, please view the LICENSE
  6. * file that was distributed with this source code.
  7. *
  8. * @license MIT License
  9. */
  10. require_once 'tools/helpers/bookstore/behavior/BookstoreNestedSetTestBase.php';
  11. /**
  12. * Tests for NestedSetBehaviorObjectBuilderModifier class
  13. *
  14. * @author Fran?§ois Zaninotto
  15. * @version $Revision: 2167 $
  16. * @package generator.behavior.nestedset
  17. */
  18. class NestedSetBehaviorObjectBuilderModifierTest extends BookstoreNestedSetTestBase
  19. {
  20. public function testDefault()
  21. {
  22. $t = new Table9();
  23. $t->setTreeLeft('123');
  24. $this->assertEquals($t->getLeftValue(), '123', 'nested_set adds a getLeftValue() method');
  25. $t->setTreeRight('456');
  26. $this->assertEquals($t->getRightValue(), '456', 'nested_set adds a getRightValue() method');
  27. $t->setLevel('789');
  28. $this->assertEquals($t->getLevel(), '789', 'nested_set adds a getLevel() method');
  29. }
  30. public function testParameters()
  31. {
  32. $t = new Table10();
  33. $t->setMyLeftColumn('123');
  34. $this->assertEquals($t->getLeftValue(), '123', 'nested_set adds a getLeftValue() method');
  35. $t->setMyRightColumn('456');
  36. $this->assertEquals($t->getRightValue(), '456', 'nested_set adds a getRightValue() method');
  37. $t->setMyLevelColumn('789');
  38. $this->assertEquals($t->getLevel(), '789', 'nested_set adds a getLevel() method');
  39. $t->setMyScopeColumn('012');
  40. $this->assertEquals($t->getScopeValue(), '012', 'nested_set adds a getScopeValue() method');
  41. }
  42. public function testObjectAttributes()
  43. {
  44. $expectedAttributes = array('nestedSetQueries');
  45. foreach ($expectedAttributes as $attribute) {
  46. $this->assertClassHasAttribute($attribute, 'Table9');
  47. }
  48. }
  49. public function testSaveOutOfTree()
  50. {
  51. Table9Peer::doDeleteAll();
  52. $t1 = new Table9();
  53. $t1->setTitle('t1');
  54. try {
  55. $t1->save();
  56. $this->assertTrue(true, 'A node can be saved without valid tree information');
  57. } catch (Exception $e) {
  58. $this->fail('A node can be saved without valid tree information');
  59. }
  60. try {
  61. $t1->makeRoot();
  62. $this->assertTrue(true, 'A saved node can be turned into root');
  63. } catch (Exception $e) {
  64. $this->fail('A saved node can be turned into root');
  65. }
  66. $t1->save();
  67. $t2 = new Table9();
  68. $t2->setTitle('t1');
  69. $t2->save();
  70. try {
  71. $t2->insertAsFirstChildOf($t1);
  72. $this->assertTrue(true, 'A saved node can be inserted into the tree');
  73. } catch (Exception $e) {
  74. $this->fail('A saved node can be inserted into the tree');
  75. }
  76. try {
  77. $t2->save();
  78. $this->assertTrue(true, 'A saved node can be inserted into the tree');
  79. } catch (Exception $e) {
  80. $this->fail('A saved node can be inserted into the tree');
  81. }
  82. }
  83. /**
  84. * @expectedException PropelException
  85. */
  86. public function testSaveRootInTreeWithExistingRoot()
  87. {
  88. Table9Peer::doDeleteAll();
  89. $t1 = new Table9();
  90. $t1->makeRoot();
  91. $t1->save();
  92. $t2 = new Table9();
  93. $t2->makeRoot();
  94. $t2->save();
  95. }
  96. public function testPreUpdate()
  97. {
  98. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  99. $t3->setLeftValue(null);
  100. try {
  101. $t3->save();
  102. $this->fail('Trying to save a node incorrectly updated throws an exception');
  103. } catch (Exception $e) {
  104. $this->assertTrue(true, 'Trying to save a node incorrectly updated throws an exception');
  105. }
  106. }
  107. public function testDelete()
  108. {
  109. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  110. /* Tree used for tests
  111. t1
  112. | \
  113. t2 t3
  114. | \
  115. t4 t5
  116. | \
  117. t6 t7
  118. */
  119. $t5->delete();
  120. $this->assertEquals(13, $t3->getRightValue(), 'delete() does not update existing nodes (because delete() clears the instance cache)');
  121. $expected = array(
  122. 't1' => array(1, 8, 0),
  123. 't2' => array(2, 3, 1),
  124. 't3' => array(4, 7, 1),
  125. 't4' => array(5, 6, 2),
  126. );
  127. $this->assertEquals($expected, $this->dumpTree(), 'delete() deletes all descendants and shifts the entire subtree correctly');
  128. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  129. try {
  130. $t1->delete();
  131. $this->fail('delete() throws an exception when called on a root node');
  132. } catch (PropelException $e) {
  133. $this->assertTrue(true, 'delete() throws an exception when called on a root node');
  134. }
  135. $this->assertNotEquals(array(), Table9Peer::doSelect(new Criteria()), 'delete() called on the root node does not delete the whole tree');
  136. }
  137. public function testDeleteNotInTree()
  138. {
  139. $t1 = new Table9();
  140. $t1->save();
  141. $t1->delete();
  142. $this->assertTrue($t1->isDeleted());
  143. }
  144. public function testMakeRoot()
  145. {
  146. $t = new Table9();
  147. $t->makeRoot();
  148. $this->assertEquals($t->getLeftValue(), 1, 'makeRoot() initializes left_column to 1');
  149. $this->assertEquals($t->getRightValue(), 2, 'makeRoot() initializes right_column to 2');
  150. $this->assertEquals($t->getLevel(), 0, 'makeRoot() initializes right_column to 0');
  151. $t = new Table9();
  152. $t->setLeftValue(12);
  153. try {
  154. $t->makeRoot();
  155. $this->fail('makeRoot() throws an exception when called on an object with a left_column value');
  156. } catch (PropelException $e) {
  157. $this->assertTrue(true, 'makeRoot() throws an exception when called on an object with a left_column value');
  158. }
  159. }
  160. public function testIsInTree()
  161. {
  162. $t1 = new Table9();
  163. $this->assertFalse($t1->isInTree(), 'inInTree() returns false for nodes with no left and right value');
  164. $t1->save();
  165. $this->assertFalse($t1->isInTree(), 'inInTree() returns false for saved nodes with no left and right value');
  166. $t1->setLeftValue(1)->setRightValue(0);
  167. $this->assertFalse($t1->isInTree(), 'inInTree() returns false for nodes with zero left value');
  168. $t1->setLeftValue(0)->setRightValue(1);
  169. $this->assertFalse($t1->isInTree(), 'inInTree() returns false for nodes with zero right value');
  170. $t1->setLeftValue(1)->setRightValue(1);
  171. $this->assertFalse($t1->isInTree(), 'inInTree() returns false for nodes with equal left and right value');
  172. $t1->setLeftValue(1)->setRightValue(2);
  173. $this->assertTrue($t1->isInTree(), 'inInTree() returns true for nodes with left < right value');
  174. $t1->setLeftValue(2)->setRightValue(1);
  175. $this->assertFalse($t1->isInTree(), 'inInTree() returns false for nodes with left > right value');
  176. }
  177. public function testIsRoot()
  178. {
  179. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  180. /* Tree used for tests
  181. t1
  182. | \
  183. t2 t3
  184. | \
  185. t4 t5
  186. | \
  187. t6 t7
  188. */
  189. $this->assertTrue($t1->isRoot(), 'root is seen as root');
  190. $this->assertFalse($t2->isRoot(), 'leaf is not seen as root');
  191. $this->assertFalse($t3->isRoot(), 'node is not seen as root');
  192. }
  193. public function testIsLeaf()
  194. {
  195. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  196. /* Tree used for tests
  197. t1
  198. | \
  199. t2 t3
  200. | \
  201. t4 t5
  202. | \
  203. t6 t7
  204. */
  205. $this->assertFalse($t1->isLeaf(), 'root is not seen as leaf');
  206. $this->assertTrue($t2->isLeaf(), 'leaf is seen as leaf');
  207. $this->assertFalse($t3->isLeaf(), 'node is not seen as leaf');
  208. }
  209. public function testIsDescendantOf()
  210. {
  211. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  212. /* Tree used for tests
  213. t1
  214. | \
  215. t2 t3
  216. | \
  217. t4 t5
  218. | \
  219. t6 t7
  220. */
  221. $this->assertFalse($t1->isDescendantOf($t1), 'root is not seen as a descendant of root');
  222. $this->assertTrue($t2->isDescendantOf($t1), 'direct child is seen as a descendant of root');
  223. $this->assertFalse($t1->isDescendantOf($t2), 'root is not seen as a descendant of leaf');
  224. $this->assertTrue($t5->isDescendantOf($t1), 'grandchild is seen as a descendant of root');
  225. $this->assertTrue($t5->isDescendantOf($t3), 'direct child is seen as a descendant of node');
  226. $this->assertFalse($t3->isDescendantOf($t5), 'node is not seen as a descendant of its parent');
  227. }
  228. public function testIsAncestorOf()
  229. {
  230. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  231. /* Tree used for tests
  232. t1
  233. | \
  234. t2 t3
  235. | \
  236. t4 t5
  237. | \
  238. t6 t7
  239. */
  240. $this->assertFalse($t1->isAncestorOf($t1), 'root is not seen as an ancestor of root');
  241. $this->assertTrue($t1->isAncestorOf($t2), 'root is seen as an ancestor of direct child');
  242. $this->assertFalse($t2->isAncestorOf($t1), 'direct child is not seen as an ancestor of root');
  243. $this->assertTrue($t1->isAncestorOf($t5), 'root is seen as an ancestor of grandchild');
  244. $this->assertTrue($t3->isAncestorOf($t5), 'parent is seen as an ancestor of node');
  245. $this->assertFalse($t5->isAncestorOf($t3), 'child is not seen as an ancestor of its parent');
  246. }
  247. public function testHasParent()
  248. {
  249. Table9Peer::doDeleteAll();
  250. $t0 = new Table9();
  251. $t1 = new Table9();
  252. $t1->setTitle('t1')->setLeftValue(1)->setRightValue(6)->setLevel(0)->save();
  253. $t2 = new Table9();
  254. $t2->setTitle('t2')->setLeftValue(2)->setRightValue(5)->setLevel(1)->save();
  255. $t3 = new Table9();
  256. $t3->setTitle('t3')->setLeftValue(3)->setRightValue(4)->setLevel(2)->save();
  257. $this->assertFalse($t0->hasParent(), 'empty node has no parent');
  258. $this->assertFalse($t1->hasParent(), 'root node has no parent');
  259. $this->assertTrue($t2->hasParent(), 'not root node has a parent');
  260. $this->assertTrue($t3->hasParent(), 'leaf node has a parent');
  261. }
  262. public function testGetParent()
  263. {
  264. Table9Peer::doDeleteAll();
  265. $t0 = new Table9();
  266. $this->assertFalse($t0->hasParent(), 'empty node has no parent');
  267. $t1 = new Table9();
  268. $t1->setTitle('t1')->setLeftValue(1)->setRightValue(8)->setLevel(0)->save();
  269. $t2 = new Table9();
  270. $t2->setTitle('t2')->setLeftValue(2)->setRightValue(7)->setLevel(1)->save();
  271. $t3 = new Table9();
  272. $t3->setTitle('t3')->setLeftValue(3)->setRightValue(4)->setLevel(2)->save();
  273. $t4 = new Table9();
  274. $t4->setTitle('t4')->setLeftValue(5)->setRightValue(6)->setLevel(2)->save();
  275. $this->assertNull($t1->getParent($this->con), 'getParent() return null for root nodes');
  276. $this->assertEquals($t2->getParent($this->con), $t1, 'getParent() correctly retrieves parent for nodes');
  277. $this->assertEquals($t3->getParent($this->con), $t2, 'getParent() correctly retrieves parent for leafs');
  278. $this->assertEquals($t4->getParent($this->con), $t2, 'getParent() retrieves the same parent for two siblings');
  279. }
  280. public function testGetParentCache()
  281. {
  282. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  283. /* Tree used for tests
  284. t1
  285. | \
  286. t2 t3
  287. | \
  288. t4 t5
  289. | \
  290. t6 t7
  291. */
  292. $con = Propel::getConnection();
  293. $count = $con->getQueryCount();
  294. $parent = $t5->getParent($con);
  295. $parent = $t5->getParent($con);
  296. $this->assertEquals($count + 1, $con->getQueryCount(), 'getParent() only issues a query once');
  297. $this->assertEquals('t3', $parent->getTitle(), 'getParent() returns the parent Node');
  298. }
  299. public function testHasPrevSibling()
  300. {
  301. Table9Peer::doDeleteAll();
  302. $t0 = new Table9();
  303. $t1 = new Table9();
  304. $t1->setTitle('t1')->setLeftValue(1)->setRightValue(6)->save();
  305. $t2 = new Table9();
  306. $t2->setTitle('t2')->setLeftValue(2)->setRightValue(3)->save();
  307. $t3 = new Table9();
  308. $t3->setTitle('t3')->setLeftValue(4)->setRightValue(5)->save();
  309. $this->assertFalse($t0->hasPrevSibling(), 'empty node has no previous sibling');
  310. $this->assertFalse($t1->hasPrevSibling(), 'root node has no previous sibling');
  311. $this->assertFalse($t2->hasPrevSibling(), 'first sibling has no previous sibling');
  312. $this->assertTrue($t3->hasPrevSibling(), 'not first sibling has a previous siblingt');
  313. }
  314. public function testGetPrevSibling()
  315. {
  316. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  317. /* Tree used for tests
  318. t1
  319. | \
  320. t2 t3
  321. | \
  322. t4 t5
  323. | \
  324. t6 t7
  325. */
  326. $this->assertNull($t1->getPrevSibling($this->con), 'getPrevSibling() returns null for root nodes');
  327. $this->assertNull($t2->getPrevSibling($this->con), 'getPrevSibling() returns null for first siblings');
  328. $this->assertEquals($t3->getPrevSibling($this->con), $t2, 'getPrevSibling() correctly retrieves prev sibling');
  329. $this->assertNull($t6->getPrevSibling($this->con), 'getPrevSibling() returns null for first siblings');
  330. $this->assertEquals($t7->getPrevSibling($this->con), $t6, 'getPrevSibling() correctly retrieves prev sibling');
  331. }
  332. public function testHasNextSibling()
  333. {
  334. Table9Peer::doDeleteAll();
  335. $t0 = new Table9();
  336. $t1 = new Table9();
  337. $t1->setTitle('t1')->setLeftValue(1)->setRightValue(6)->save();
  338. $t2 = new Table9();
  339. $t2->setTitle('t2')->setLeftValue(2)->setRightValue(3)->save();
  340. $t3 = new Table9();
  341. $t3->setTitle('t3')->setLeftValue(4)->setRightValue(5)->save();
  342. $this->assertFalse($t0->hasNextSibling(), 'empty node has no next sibling');
  343. $this->assertFalse($t1->hasNextSibling(), 'root node has no next sibling');
  344. $this->assertTrue($t2->hasNextSibling(), 'not last sibling has a next sibling');
  345. $this->assertFalse($t3->hasNextSibling(), 'last sibling has no next sibling');
  346. }
  347. public function testGetNextSibling()
  348. {
  349. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  350. /* Tree used for tests
  351. t1
  352. | \
  353. t2 t3
  354. | \
  355. t4 t5
  356. | \
  357. t6 t7
  358. */
  359. $this->assertNull($t1->getNextSibling($this->con), 'getNextSibling() returns null for root nodes');
  360. $this->assertEquals($t2->getNextSibling($this->con), $t3, 'getNextSibling() correctly retrieves next sibling');
  361. $this->assertNull($t3->getNextSibling($this->con), 'getNextSibling() returns null for last siblings');
  362. $this->assertEquals($t6->getNextSibling($this->con), $t7, 'getNextSibling() correctly retrieves next sibling');
  363. $this->assertNull($t7->getNextSibling($this->con), 'getNextSibling() returns null for last siblings');
  364. }
  365. public function testAddNestedSetChildren()
  366. {
  367. $t0 = new Table9();
  368. $t1 = new Table9();
  369. $t2 = new Table9();
  370. $t0->addNestedSetChild($t1);
  371. $t0->addNestedSetChild($t2);
  372. $this->assertEquals(2, $t0->countChildren(), 'addNestedSetChild() adds the object to the internal children collection');
  373. $this->assertEquals($t0, $t1->getParent(), 'addNestedSetChild() sets the object as th parent of the parameter');
  374. $this->assertEquals($t0, $t2->getParent(), 'addNestedSetChild() sets the object as th parent of the parameter');
  375. }
  376. public function testHasChildren()
  377. {
  378. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  379. /* Tree used for tests
  380. t1
  381. | \
  382. t2 t3
  383. | \
  384. t4 t5
  385. | \
  386. t6 t7
  387. */
  388. $this->assertTrue($t1->hasChildren(), 'root has children');
  389. $this->assertFalse($t2->hasChildren(), 'leaf has no children');
  390. $this->assertTrue($t3->hasChildren(), 'node has children');
  391. }
  392. public function testGetChildren()
  393. {
  394. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  395. /* Tree used for tests
  396. t1
  397. | \
  398. t2 t3
  399. | \
  400. t4 t5
  401. | \
  402. t6 t7
  403. */
  404. $this->assertTrue($t2->getChildren() instanceof PropelObjectCollection, 'getChildren() returns a collection');
  405. $this->assertEquals(0, count($t2->getChildren()), 'getChildren() returns an empty collection for leafs');
  406. $children = $t3->getChildren();
  407. $expected = array(
  408. 't4' => array(5, 6, 2),
  409. 't5' => array(7, 12, 2),
  410. );
  411. $this->assertEquals($expected, $this->dumpNodes($children, true), 'getChildren() returns a collection of children');
  412. $c = new Criteria();
  413. $c->add(Table9Peer::TITLE, 't5');
  414. $children = $t3->getChildren($c);
  415. $expected = array(
  416. 't5' => array(7, 12, 2),
  417. );
  418. $this->assertEquals($expected, $this->dumpNodes($children, true), 'getChildren() accepts a criteria as parameter');
  419. }
  420. public function testGetChildrenCache()
  421. {
  422. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  423. $con = Propel::getConnection();
  424. $count = $con->getQueryCount();
  425. $children = $t3->getChildren(null, $con);
  426. $children = $t3->getChildren(null, $con);
  427. $this->assertEquals($count + 1, $con->getQueryCount(), 'getChildren() only issues a query once');
  428. $expected = array(
  429. 't4' => array(5, 6, 2),
  430. 't5' => array(7, 12, 2),
  431. );
  432. $this->assertEquals($expected, $this->dumpNodes($children, true), 'getChildren() returns a collection of children');
  433. // when using criteria, cache is not used
  434. $c = new Criteria();
  435. $c->add(Table9Peer::TITLE, 't5');
  436. $children = $t3->getChildren($c, $con);
  437. $this->assertEquals($count + 2, $con->getQueryCount(), 'getChildren() issues a new query when ??ssed a non-null Criteria');
  438. $expected = array(
  439. 't5' => array(7, 12, 2),
  440. );
  441. $this->assertEquals($expected, $this->dumpNodes($children, true), 'getChildren() accepts a criteria as parameter');
  442. // but not erased either
  443. $children = $t3->getChildren(null, $con);
  444. $this->assertEquals($count + 2, $con->getQueryCount(), 'getChildren() keeps its internal cache after being called with a Criteria');
  445. $expected = array(
  446. 't4' => array(5, 6, 2),
  447. 't5' => array(7, 12, 2),
  448. );
  449. $this->assertEquals($expected, $this->dumpNodes($children, true), 'getChildren() returns a collection of children');
  450. }
  451. public function testCountChildren()
  452. {
  453. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  454. /* Tree used for tests
  455. t1
  456. | \
  457. t2 t3
  458. | \
  459. t4 t5
  460. | \
  461. t6 t7
  462. */
  463. $this->assertEquals(0, $t2->countChildren(), 'countChildren() returns 0 for leafs');
  464. $this->assertEquals(2, $t3->countChildren(), 'countChildren() returns the number of children');
  465. $c = new Criteria();
  466. $c->add(Table9Peer::TITLE, 't5');
  467. $this->assertEquals(1, $t3->countChildren($c), 'countChildren() accepts a criteria as parameter');
  468. }
  469. public function testCountChildrenCache()
  470. {
  471. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  472. /* Tree used for tests
  473. t1
  474. | \
  475. t2 t3
  476. | \
  477. t4 t5
  478. | \
  479. t6 t7
  480. */
  481. $con = Propel::getConnection();
  482. $count = $con->getQueryCount();
  483. $children = $t3->getChildren(null, $con);
  484. $nbChildren = $t3->countChildren(null, $con);
  485. $this->assertEquals($count + 1, $con->getQueryCount(), 'countChildren() uses the internal collection when passed no Criteria');
  486. $nbChildren = $t3->countChildren(new Criteria(), $con);
  487. $this->assertEquals($count + 2, $con->getQueryCount(), 'countChildren() issues a new query when passed a Criteria');
  488. }
  489. public function testGetFirstChild()
  490. {
  491. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  492. $t5->moveToNextSiblingOf($t3);
  493. /* Results in
  494. t1
  495. | \ \
  496. t2 t3 t5
  497. | | \
  498. t4 t6 t7
  499. */
  500. $this->assertEquals($t2, $t1->getFirstChild(), 'getFirstChild() returns the first child');
  501. }
  502. public function testGetLastChild()
  503. {
  504. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  505. $t5->moveToNextSiblingOf($t3);
  506. /* Results in
  507. t1
  508. | \ \
  509. t2 t3 t5
  510. | | \
  511. t4 t6 t7
  512. */
  513. $this->assertEquals($t5, $t1->getLastChild(), 'getLastChild() returns the last child');
  514. }
  515. public function testGetSiblings()
  516. {
  517. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  518. /* Tree used for tests
  519. t1
  520. | \
  521. t2 t3
  522. | \
  523. t4 t5
  524. | \
  525. t6 t7
  526. */
  527. $this->assertEquals(array(), $t1->getSiblings(), 'getSiblings() returns an empty array for root');
  528. $siblings = $t5->getSiblings();
  529. $expected = array(
  530. 't4' => array(5, 6, 2),
  531. );
  532. $this->assertEquals($expected, $this->dumpNodes($siblings), 'getSiblings() returns an array of siblings');
  533. $siblings = $t5->getSiblings(true);
  534. $expected = array(
  535. 't4' => array(5, 6, 2),
  536. 't5' => array(7, 12, 2)
  537. );
  538. $this->assertEquals($expected, $this->dumpNodes($siblings), 'getSiblings(true) includes the current node');
  539. $t5->moveToNextSiblingOf($t3);
  540. /* Results in
  541. t1
  542. | \ \
  543. t2 t3 t5
  544. | | \
  545. t4 t6 t7
  546. */
  547. $this->assertEquals(0, count($t4->getSiblings()), 'getSiblings() returns an empty colleciton for lone children');
  548. $siblings = $t3->getSiblings();
  549. $expected = array(
  550. 't2' => array(2, 3, 1),
  551. 't5' => array(8, 13, 1),
  552. );
  553. $this->assertEquals($expected, $this->dumpNodes($siblings), 'getSiblings() returns all siblings');
  554. $this->assertEquals('t2', $siblings[0]->getTitle(), 'getSiblings() returns siblings in natural order');
  555. $this->assertEquals('t5', $siblings[1]->getTitle(), 'getSiblings() returns siblings in natural order');
  556. }
  557. public function testGetDescendants()
  558. {
  559. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  560. /* Tree used for tests
  561. t1
  562. | \
  563. t2 t3
  564. | \
  565. t4 t5
  566. | \
  567. t6 t7
  568. */
  569. $this->assertEquals(array(), $t2->getDescendants(), 'getDescendants() returns an empty array for leafs');
  570. $descendants = $t3->getDescendants();
  571. $expected = array(
  572. 't4' => array(5, 6, 2),
  573. 't5' => array(7, 12, 2),
  574. 't6' => array(8, 9, 3),
  575. 't7' => array(10, 11, 3),
  576. );
  577. $this->assertEquals($expected, $this->dumpNodes($descendants), 'getDescendants() returns an array of descendants');
  578. $c = new Criteria();
  579. $c->add(Table9Peer::TITLE, 't5');
  580. $descendants = $t3->getDescendants($c);
  581. $expected = array(
  582. 't5' => array(7, 12, 2),
  583. );
  584. $this->assertEquals($expected, $this->dumpNodes($descendants), 'getDescendants() accepts a criteria as parameter');
  585. }
  586. public function testCountDescendants()
  587. {
  588. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  589. /* Tree used for tests
  590. t1
  591. | \
  592. t2 t3
  593. | \
  594. t4 t5
  595. | \
  596. t6 t7
  597. */
  598. $this->assertEquals(0, $t2->countDescendants(), 'countDescendants() returns 0 for leafs');
  599. $this->assertEquals(4, $t3->countDescendants(), 'countDescendants() returns the number of descendants');
  600. $c = new Criteria();
  601. $c->add(Table9Peer::TITLE, 't5');
  602. $this->assertEquals(1, $t3->countDescendants($c), 'countDescendants() accepts a criteria as parameter');
  603. }
  604. public function testGetBranch()
  605. {
  606. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  607. /* Tree used for tests
  608. t1
  609. | \
  610. t2 t3
  611. | \
  612. t4 t5
  613. | \
  614. t6 t7
  615. */
  616. $this->assertEquals(array($t2), $t2->getBranch()->getArrayCopy(), 'getBranch() returns the current node for leafs');
  617. $descendants = $t3->getBranch();
  618. $expected = array(
  619. 't3' => array(4, 13, 1),
  620. 't4' => array(5, 6, 2),
  621. 't5' => array(7, 12, 2),
  622. 't6' => array(8, 9, 3),
  623. 't7' => array(10, 11, 3),
  624. );
  625. $this->assertEquals($expected, $this->dumpNodes($descendants), 'getBranch() returns an array of descendants, uncluding the current node');
  626. $c = new Criteria();
  627. $c->add(Table9Peer::TITLE, 't3', Criteria::NOT_EQUAL);
  628. $descendants = $t3->getBranch($c);
  629. unset($expected['t3']);
  630. $this->assertEquals($expected, $this->dumpNodes($descendants), 'getBranch() accepts a criteria as first parameter');
  631. }
  632. public function testGetAncestors()
  633. {
  634. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  635. /* Tree used for tests
  636. t1
  637. | \
  638. t2 t3
  639. | \
  640. t4 t5
  641. | \
  642. t6 t7
  643. */
  644. $this->assertEquals(array(), $t1->getAncestors(), 'getAncestors() returns an empty array for roots');
  645. $ancestors = $t5->getAncestors();
  646. $expected = array(
  647. 't1' => array(1, 14, 0),
  648. 't3' => array(4, 13, 1),
  649. );
  650. $this->assertEquals($expected, $this->dumpNodes($ancestors), 'getAncestors() returns an array of ancestors');
  651. $c = new Criteria();
  652. $c->add(Table9Peer::TITLE, 't3');
  653. $ancestors = $t5->getAncestors($c);
  654. $expected = array(
  655. 't3' => array(4, 13, 1),
  656. );
  657. $this->assertEquals($expected, $this->dumpNodes($ancestors), 'getAncestors() accepts a criteria as parameter');
  658. }
  659. public function testAddChild()
  660. {
  661. Table9Peer::doDeleteAll();
  662. $t1 = new Table9();
  663. $t1->setTitle('t1');
  664. $t1->makeRoot();
  665. $t1->save();
  666. $t2 = new Table9();
  667. $t2->setTitle('t2');
  668. $t1->addChild($t2);
  669. $t2->save();
  670. $t3 = new Table9();
  671. $t3->setTitle('t3');
  672. $t1->addChild($t3);
  673. $t3->save();
  674. $t4 = new Table9();
  675. $t4->setTitle('t4');
  676. $t2->addChild($t4);
  677. $t4->save();
  678. $expected = array(
  679. 't1' => array(1, 8, 0),
  680. 't2' => array(4, 7, 1),
  681. 't3' => array(2, 3, 1),
  682. 't4' => array(5, 6, 2),
  683. );
  684. $this->assertEquals($expected, $this->dumpTree(), 'addChild() adds the child and saves it');
  685. }
  686. public function testInsertAsFirstChildOf()
  687. {
  688. $this->assertTrue(method_exists('Table9', 'insertAsFirstChildOf'), 'nested_set adds a insertAsFirstChildOf() method');
  689. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  690. /* Tree used for tests
  691. t1
  692. | \
  693. t2 t3
  694. | \
  695. t4 t5
  696. | \
  697. t6 t7
  698. */
  699. $t8 = new PublicTable9();
  700. $t8->setTitle('t8');
  701. $t = $t8->insertAsFirstChildOf($t3);
  702. $this->assertEquals($t8, $t, 'insertAsFirstChildOf() returns the object it was called on');
  703. $this->assertEquals(5, $t4->getLeftValue(), 'insertAsFirstChildOf() does not modify the tree until the object is saved');
  704. $t8->save();
  705. $this->assertEquals(5, $t8->getLeftValue(), 'insertAsFirstChildOf() sets the left value correctly');
  706. $this->assertEquals(6, $t8->getRightValue(), 'insertAsFirstChildOf() sets the right value correctly');
  707. $this->assertEquals(2, $t8->getLevel(), 'insertAsFirstChildOf() sets the level correctly');
  708. $expected = array(
  709. 't1' => array(1, 16, 0),
  710. 't2' => array(2, 3, 1),
  711. 't3' => array(4, 15, 1),
  712. 't4' => array(7, 8, 2),
  713. 't5' => array(9, 14, 2),
  714. 't6' => array(10, 11, 3),
  715. 't7' => array(12, 13, 3),
  716. 't8' => array(5, 6, 2)
  717. );
  718. $this->assertEquals($expected, $this->dumpTree(), 'insertAsFirstChildOf() shifts the other nodes correctly');
  719. try {
  720. $t8->insertAsFirstChildOf($t4);
  721. $this->fail('insertAsFirstChildOf() throws an exception when called on a saved object');
  722. } catch (PropelException $e) {
  723. $this->assertTrue(true, 'insertAsFirstChildOf() throws an exception when called on a saved object');
  724. }
  725. }
  726. public function testInsertAsFirstChildOfExistingObject()
  727. {
  728. Table9Query::create()->deleteAll();
  729. $t = new Table9();
  730. $t->makeRoot();
  731. $t->save();
  732. $this->assertEquals(1, $t->getLeftValue());
  733. $this->assertEquals(2, $t->getRightValue());
  734. $this->assertEquals(0, $t->getLevel());
  735. $t1 = new Table9();
  736. $t1->save();
  737. $t1->insertAsFirstChildOf($t);
  738. $this->assertEquals(2, $t1->getLeftValue());
  739. $this->assertEquals(3, $t1->getRightValue());
  740. $this->assertEquals(1, $t1->getLevel());
  741. $t1->save();
  742. $this->assertEquals(1, $t->getLeftValue());
  743. $this->assertEquals(4, $t->getRightValue());
  744. $this->assertEquals(0, $t->getLevel());
  745. $this->assertEquals(2, $t1->getLeftValue());
  746. $this->assertEquals(3, $t1->getRightValue());
  747. $this->assertEquals(1, $t1->getLevel());
  748. }
  749. public function testInsertAsLastChildOf()
  750. {
  751. $this->assertTrue(method_exists('Table9', 'insertAsLastChildOf'), 'nested_set adds a insertAsLastChildOf() method');
  752. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  753. /* Tree used for tests
  754. t1
  755. | \
  756. t2 t3
  757. | \
  758. t4 t5
  759. | \
  760. t6 t7
  761. */
  762. $t8 = new PublicTable9();
  763. $t8->setTitle('t8');
  764. $t = $t8->insertAsLastChildOf($t3);
  765. $this->assertEquals($t8, $t, 'insertAsLastChildOf() returns the object it was called on');
  766. $this->assertEquals(13, $t3->getRightValue(), 'insertAsLastChildOf() does not modify the tree until the object is saved');
  767. $t8->save();
  768. $this->assertEquals(13, $t8->getLeftValue(), 'insertAsLastChildOf() sets the left value correctly');
  769. $this->assertEquals(14, $t8->getRightValue(), 'insertAsLastChildOf() sets the right value correctly');
  770. $this->assertEquals(2, $t8->getLevel(), 'insertAsLastChildOf() sets the level correctly');
  771. $expected = array(
  772. 't1' => array(1, 16, 0),
  773. 't2' => array(2, 3, 1),
  774. 't3' => array(4, 15, 1),
  775. 't4' => array(5, 6, 2),
  776. 't5' => array(7, 12, 2),
  777. 't6' => array(8, 9, 3),
  778. 't7' => array(10, 11, 3),
  779. 't8' => array(13, 14, 2)
  780. );
  781. $this->assertEquals($expected, $this->dumpTree(), 'insertAsLastChildOf() shifts the other nodes correctly');
  782. try {
  783. $t8->insertAsLastChildOf($t4);
  784. $this->fail('insertAsLastChildOf() throws an exception when called on a saved object');
  785. } catch (PropelException $e) {
  786. $this->assertTrue(true, 'insertAsLastChildOf() throws an exception when called on a saved object');
  787. }
  788. }
  789. public function testInsertAsLastChildOfExistingObject()
  790. {
  791. Table9Query::create()->deleteAll();
  792. $t = new Table9();
  793. $t->makeRoot();
  794. $t->save();
  795. $this->assertEquals(1, $t->getLeftValue());
  796. $this->assertEquals(2, $t->getRightValue());
  797. $this->assertEquals(0, $t->getLevel());
  798. $t1 = new Table9();
  799. $t1->save();
  800. $t1->insertAsLastChildOf($t);
  801. $this->assertEquals(2, $t1->getLeftValue());
  802. $this->assertEquals(3, $t1->getRightValue());
  803. $this->assertEquals(1, $t1->getLevel());
  804. $t1->save();
  805. $this->assertEquals(1, $t->getLeftValue());
  806. $this->assertEquals(4, $t->getRightValue());
  807. $this->assertEquals(0, $t->getLevel());
  808. $this->assertEquals(2, $t1->getLeftValue());
  809. $this->assertEquals(3, $t1->getRightValue());
  810. $this->assertEquals(1, $t1->getLevel());
  811. }
  812. public function testInsertAsPrevSiblingOf()
  813. {
  814. $this->assertTrue(method_exists('Table9', 'insertAsPrevSiblingOf'), 'nested_set adds a insertAsPrevSiblingOf() method');
  815. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  816. /* Tree used for tests
  817. t1
  818. | \
  819. t2 t3
  820. | \
  821. t4 t5
  822. | \
  823. t6 t7
  824. */
  825. $t8 = new PublicTable9();
  826. $t8->setTitle('t8');
  827. $t = $t8->insertAsPrevSiblingOf($t3);
  828. $this->assertEquals($t8, $t, 'insertAsPrevSiblingOf() returns the object it was called on');
  829. $this->assertEquals(4, $t3->getLeftValue(), 'insertAsPrevSiblingOf() does not modify the tree until the object is saved');
  830. $t8->save();
  831. $this->assertEquals(4, $t8->getLeftValue(), 'insertAsPrevSiblingOf() sets the left value correctly');
  832. $this->assertEquals(5, $t8->getRightValue(), 'insertAsPrevSiblingOf() sets the right value correctly');
  833. $this->assertEquals(1, $t8->getLevel(), 'insertAsPrevSiblingOf() sets the level correctly');
  834. $expected = array(
  835. 't1' => array(1, 16, 0),
  836. 't2' => array(2, 3, 1),
  837. 't3' => array(6, 15, 1),
  838. 't4' => array(7, 8, 2),
  839. 't5' => array(9, 14, 2),
  840. 't6' => array(10, 11, 3),
  841. 't7' => array(12, 13, 3),
  842. 't8' => array(4, 5, 1)
  843. );
  844. $this->assertEquals($expected, $this->dumpTree(), 'insertAsPrevSiblingOf() shifts the other nodes correctly');
  845. try {
  846. $t8->insertAsPrevSiblingOf($t4);
  847. $this->fail('insertAsPrevSiblingOf() throws an exception when called on a saved object');
  848. } catch (PropelException $e) {
  849. $this->assertTrue(true, 'insertAsPrevSiblingOf() throws an exception when called on a saved object');
  850. }
  851. }
  852. public function testInsertAsPrevSiblingOfExistingObject()
  853. {
  854. Table9Query::create()->deleteAll();
  855. $t = new Table9();
  856. $t->makeRoot();
  857. $t->save();
  858. $t1 = new Table9();
  859. $t1->insertAsFirstChildOf($t);
  860. $t1->save();
  861. $this->assertEquals(1, $t->getLeftValue());
  862. $this->assertEquals(4, $t->getRightValue());
  863. $this->assertEquals(0, $t->getLevel());
  864. $this->assertEquals(2, $t1->getLeftValue());
  865. $this->assertEquals(3, $t1->getRightValue());
  866. $this->assertEquals(1, $t1->getLevel());
  867. $t2 = new Table9();
  868. $t2->save();
  869. $t2->insertAsPrevSiblingOf($t1);
  870. $this->assertEquals(2, $t2->getLeftValue());
  871. $this->assertEquals(3, $t2->getRightValue());
  872. $this->assertEquals(1, $t2->getLevel());
  873. $t2->save();
  874. $this->assertEquals(1, $t->getLeftValue());
  875. $this->assertEquals(6, $t->getRightValue());
  876. $this->assertEquals(0, $t->getLevel());
  877. $this->assertEquals(4, $t1->getLeftValue());
  878. $this->assertEquals(5, $t1->getRightValue());
  879. $this->assertEquals(1, $t1->getLevel());
  880. $this->assertEquals(2, $t2->getLeftValue());
  881. $this->assertEquals(3, $t2->getRightValue());
  882. $this->assertEquals(1, $t2->getLevel());
  883. }
  884. public function testInsertAsNextSiblingOf()
  885. {
  886. $this->assertTrue(method_exists('Table9', 'insertAsNextSiblingOf'), 'nested_set adds a insertAsNextSiblingOf() method');
  887. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  888. /* Tree used for tests
  889. t1
  890. | \
  891. t2 t3
  892. | \
  893. t4 t5
  894. | \
  895. t6 t7
  896. */
  897. $t8 = new PublicTable9();
  898. $t8->setTitle('t8');
  899. $t = $t8->insertAsNextSiblingOf($t3);
  900. $this->assertEquals($t8, $t, 'insertAsNextSiblingOf() returns the object it was called on');
  901. $this->assertEquals(14, $t1->getRightValue(), 'insertAsNextSiblingOf() does not modify the tree until the object is saved');
  902. $t8->save();
  903. $this->assertEquals(14, $t8->getLeftValue(), 'insertAsNextSiblingOf() sets the left value correctly');
  904. $this->assertEquals(15, $t8->getRightValue(), 'insertAsNextSiblingOf() sets the right value correctly');
  905. $this->assertEquals(1, $t8->getLevel(), 'insertAsNextSiblingOf() sets the level correctly');
  906. $expected = array(
  907. 't1' => array(1, 16, 0),
  908. 't2' => array(2, 3, 1),
  909. 't3' => array(4, 13, 1),
  910. 't4' => array(5, 6, 2),
  911. 't5' => array(7, 12, 2),
  912. 't6' => array(8, 9, 3),
  913. 't7' => array(10, 11, 3),
  914. 't8' => array(14, 15, 1)
  915. );
  916. $this->assertEquals($expected, $this->dumpTree(), 'insertAsNextSiblingOf() shifts the other nodes correctly');
  917. try {
  918. $t8->insertAsNextSiblingOf($t4);
  919. $this->fail('insertAsNextSiblingOf() throws an exception when called on a saved object');
  920. } catch (PropelException $e) {
  921. $this->assertTrue(true, 'insertAsNextSiblingOf() throws an exception when called on a saved object');
  922. }
  923. }
  924. public function testInsertAsNextSiblingOfExistingObject()
  925. {
  926. Table9Query::create()->deleteAll();
  927. $t = new Table9();
  928. $t->makeRoot();
  929. $t->save();
  930. $t1 = new Table9();
  931. $t1->insertAsFirstChildOf($t);
  932. $t1->save();
  933. $this->assertEquals(1, $t->getLeftValue());
  934. $this->assertEquals(4, $t->getRightValue());
  935. $this->assertEquals(0, $t->getLevel());
  936. $this->assertEquals(2, $t1->getLeftValue());
  937. $this->assertEquals(3, $t1->getRightValue());
  938. $this->assertEquals(1, $t1->getLevel());
  939. $t2 = new Table9();
  940. $t2->save();
  941. $t2->insertAsNextSiblingOf($t1);
  942. $this->assertEquals(4, $t2->getLeftValue());
  943. $this->assertEquals(5, $t2->getRightValue());
  944. $this->assertEquals(1, $t2->getLevel());
  945. $t2->save();
  946. $this->assertEquals(1, $t->getLeftValue());
  947. $this->assertEquals(6, $t->getRightValue());
  948. $this->assertEquals(0, $t->getLevel());
  949. $this->assertEquals(2, $t1->getLeftValue());
  950. $this->assertEquals(3, $t1->getRightValue());
  951. $this->assertEquals(1, $t1->getLevel());
  952. $this->assertEquals(4, $t2->getLeftValue());
  953. $this->assertEquals(5, $t2->getRightValue());
  954. $this->assertEquals(1, $t2->getLevel());
  955. }
  956. public function testMoveToFirstChildOf()
  957. {
  958. $this->assertTrue(method_exists('Table9', 'moveToFirstChildOf'), 'nested_set adds a moveToFirstChildOf() method');
  959. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  960. /* Tree used for tests
  961. t1
  962. | \
  963. t2 t3
  964. | \
  965. t4 t5
  966. | \
  967. t6 t7
  968. */
  969. try {
  970. $t3->moveToFirstChildOf($t5);
  971. $this->fail('moveToFirstChildOf() throws an exception when the target is a child node');
  972. } catch (PropelException $e) {
  973. $this->assertTrue(true, 'moveToFirstChildOf() throws an exception when the target is a child node');
  974. }
  975. // moving down
  976. $t = $t3->moveToFirstChildOf($t2);
  977. $this->assertEquals($t3, $t, 'moveToFirstChildOf() returns the object it was called on');
  978. $expected = array(
  979. 't1' => array(1, 14, 0),
  980. 't2' => array(2, 13, 1),
  981. 't3' => array(3, 12, 2),
  982. 't4' => array(4, 5, 3),
  983. 't5' => array(6, 11, 3),
  984. 't6' => array(7, 8, 4),
  985. 't7' => array(9, 10, 4),
  986. );
  987. $this->assertEquals($expected, $this->dumpTree(), 'moveToFirstChildOf() moves the entire subtree down correctly');
  988. // moving up
  989. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  990. $t5->moveToFirstChildOf($t1);
  991. $expected = array(
  992. 't1' => array(1, 14, 0),
  993. 't2' => array(8, 9, 1),
  994. 't3' => array(10, 13, 1),
  995. 't4' => array(11, 12, 2),
  996. 't5' => array(2, 7, 1),
  997. 't6' => array(3, 4, 2),
  998. 't7' => array(5, 6, 2),
  999. );
  1000. $this->assertEquals($expected, $this->dumpTree(), 'moveToFirstChildOf() moves the entire subtree up correctly');
  1001. // moving to the same level
  1002. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  1003. $t5->moveToFirstChildOf($t3);
  1004. $expected = array(
  1005. 't1' => array(1, 14, 0),
  1006. 't2' => array(2, 3, 1),
  1007. 't3' => array(4, 13, 1),
  1008. 't4' => array(11, 12, 2),
  1009. 't5' => array(5, 10, 2),
  1010. 't6' => array(6, 7, 3),
  1011. 't7' => array(8, 9, 3),
  1012. );
  1013. $this->assertEquals($expected, $this->dumpTree(), 'moveToFirstChildOf() moves the entire subtree to the same level correctly');
  1014. }
  1015. public function testMoveToFirstChildOfAndChildrenCache()
  1016. {
  1017. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  1018. /* Tree used for tests
  1019. t1
  1020. | \
  1021. t2 t3
  1022. | \
  1023. t4 t5
  1024. | \
  1025. t6 t7
  1026. */
  1027. // fill children cache
  1028. $t3->getChildren();
  1029. $t1->getChildren();
  1030. // move
  1031. $t5->moveToFirstChildOf($t1);
  1032. $children = $t3->getChildren();
  1033. $expected = array(
  1034. 't4' => array(11, 12, 2),
  1035. );
  1036. $this->assertEquals($expected, $this->dumpNodes($children, true), 'moveToFirstChildOf() reinitializes the child collection of all concerned nodes');
  1037. $children = $t1->getChildren();
  1038. $expected = array(
  1039. 't5' => array(2, 7, 1),
  1040. 't2' => array(8, 9, 1),
  1041. 't3' => array(10, 13, 1),
  1042. );
  1043. $this->assertEquals($expected, $this->dumpNodes($children, true), 'moveToFirstChildOf() reinitializes the child collection of all concerned nodes');
  1044. }
  1045. public function testMoveToLastChildOf()
  1046. {
  1047. $this->assertTrue(method_exists('Table9', 'moveToLastChildOf'), 'nested_set adds a moveToLastChildOf() method');
  1048. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  1049. /* Tree used for tests
  1050. t1
  1051. | \
  1052. t2 t3
  1053. | \
  1054. t4 t5
  1055. | \
  1056. t6 t7
  1057. */
  1058. try {
  1059. $t3->moveToLastChildOf($t5);
  1060. $this->fail('moveToLastChildOf() throws an exception when the target is a child node');
  1061. } catch (PropelException $e) {
  1062. $this->assertTrue(true, 'moveToLastChildOf() throws an exception when the target is a child node');
  1063. }
  1064. // moving up
  1065. $t = $t5->moveToLastChildOf($t1);
  1066. $this->assertEquals($t5, $t, 'moveToLastChildOf() returns the object it was called on');
  1067. $expected = array(
  1068. 't1' => array(1, 14, 0),
  1069. 't2' => array(2, 3, 1),
  1070. 't3' => array(4, 7, 1),
  1071. 't4' => array(5, 6, 2),
  1072. 't5' => array(8, 13, 1),
  1073. 't6' => array(9, 10, 2),
  1074. 't7' => array(11, 12, 2),
  1075. );
  1076. $this->assertEquals($expected, $this->dumpTree(), 'moveToLastChildOf() moves the entire subtree up correctly');
  1077. // moving down
  1078. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  1079. $t3->moveToLastChildOf($t2);
  1080. $expected = array(
  1081. 't1' => array(1, 14, 0),
  1082. 't2' => array(2, 13, 1),
  1083. 't3' => array(3, 12, 2),
  1084. 't4' => array(4, 5, 3),
  1085. 't5' => array(6, 11, 3),
  1086. 't6' => array(7, 8, 4),
  1087. 't7' => array(9, 10, 4),
  1088. );
  1089. $this->assertEquals($expected, $this->dumpTree(), 'moveToLastChildOf() moves the entire subtree down correctly');
  1090. // moving to the same level
  1091. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  1092. $t4->moveToLastChildOf($t3);
  1093. $expected = array(
  1094. 't1' => array(1, 14, 0),
  1095. 't2' => array(2, 3, 1),
  1096. 't3' => array(4, 13, 1),
  1097. 't4' => array(11, 12, 2),
  1098. 't5' => array(5, 10, 2),
  1099. 't6' => array(6, 7, 3),
  1100. 't7' => array(8, 9, 3),
  1101. );
  1102. $this->assertEquals($expected, $this->dumpTree(), 'moveToLastChildOf() moves the entire subtree to the same level correctly');
  1103. }
  1104. public function testMoveToLastChildOfAndChildrenCache()
  1105. {
  1106. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  1107. /* Tree used for tests
  1108. t1
  1109. | \
  1110. t2 t3
  1111. | \
  1112. t4 t5
  1113. | \
  1114. t6 t7
  1115. */
  1116. // fill children cache
  1117. $t3->getChildren();
  1118. $t1->getChildren();
  1119. // move
  1120. $t5->moveToLastChildOf($t1);
  1121. $children = $t3->getChildren();
  1122. $expected = array(
  1123. 't4' => array(5, 6, 2),
  1124. );
  1125. $this->assertEquals($expected, $this->dumpNodes($children, true), 'moveToLastChildOf() reinitializes the child collection of all concerned nodes');
  1126. $children = $t1->getChildren();
  1127. $expected = array(
  1128. 't2' => array(2, 3, 1),
  1129. 't3' => array(4, 7, 1),
  1130. 't5' => array(8, 13, 1),
  1131. );
  1132. $this->assertEquals($expected, $this->dumpNodes($children, true), 'moveToLastChildOf() reinitializes the child collection of all concerned nodes');
  1133. }
  1134. public function testMoveToPrevSiblingOf()
  1135. {
  1136. $this->assertTrue(method_exists('Table9', 'moveToPrevSiblingOf'), 'nested_set adds a moveToPrevSiblingOf() method');
  1137. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  1138. /* Tree used for tests
  1139. t1
  1140. | \
  1141. t2 t3
  1142. | \
  1143. t4 t5
  1144. | \
  1145. t6 t7
  1146. */
  1147. try {
  1148. $t5->moveToPrevSiblingOf($t1);
  1149. $this->fail('moveToPrevSiblingOf() throws an exception when the target is a root node');
  1150. } catch (PropelException $e) {
  1151. $this->assertTrue(true, 'moveToPrevSiblingOf() throws an exception when the target is a root node');
  1152. }
  1153. try {
  1154. $t5->moveToPrevSiblingOf($t6);
  1155. $this->fail('moveToPrevSiblingOf() throws an exception when the target is a child node');
  1156. } catch (PropelException $e) {
  1157. $this->assertTrue(true, 'moveToPrevSiblingOf() throws an exception when the target is a child node');
  1158. }
  1159. // moving up
  1160. $t = $t5->moveToPrevSiblingOf($t3);
  1161. /* Results in
  1162. t1
  1163. | \ \
  1164. t2 t5 t3
  1165. | \ |
  1166. t6 t7 t4
  1167. */
  1168. $this->assertEquals($t5, $t, 'moveToPrevSiblingOf() returns the object it was called on');
  1169. $expected = array(
  1170. 't1' => array(1, 14, 0),
  1171. 't2' => array(2, 3, 1),
  1172. 't3' => array(10, 13, 1),
  1173. 't4' => array(11, 12, 2),
  1174. 't5' => array(4, 9, 1),
  1175. 't6' => array(5, 6, 2),
  1176. 't7' => array(7, 8, 2),
  1177. );
  1178. $this->assertEquals($expected, $this->dumpTree(), 'moveToPrevSiblingOf() moves the entire subtree up correctly');
  1179. // moving down
  1180. $t5->moveToPrevSiblingOf($t4);
  1181. /* Results in
  1182. t1
  1183. | \
  1184. t2 t3
  1185. | \
  1186. t5 t4
  1187. | \
  1188. t6 t7
  1189. */
  1190. $expected = array(
  1191. 't1' => array(1, 14, 0),
  1192. 't2' => array(2, 3, 1),
  1193. 't3' => array(4, 13, 1),
  1194. 't4' => array(11, 12, 2),
  1195. 't5' => array(5, 10, 2),
  1196. 't6' => array(6, 7, 3),
  1197. 't7' => array(8, 9, 3),
  1198. );
  1199. $this->assertEquals($expected, $this->dumpTree(), 'moveToPrevSiblingOf() moves the entire subtree down correctly');
  1200. // moving at the same level
  1201. $t4->moveToPrevSiblingOf($t5);
  1202. /* Results in
  1203. t1
  1204. | \
  1205. t2 t3
  1206. | \
  1207. t4 t5
  1208. | \
  1209. t6 t7
  1210. */
  1211. $expected = array(
  1212. 't1' => array(1, 14, 0),
  1213. 't2' => array(2, 3, 1),
  1214. 't3' => array(4, 13, 1),
  1215. 't4' => array(5, 6, 2),
  1216. 't5' => array(7, 12, 2),
  1217. 't6' => array(8, 9, 3),
  1218. 't7' => array(10, 11, 3),
  1219. );
  1220. $this->assertEquals($expected, $this->dumpTree(), 'moveToPrevSiblingOf() moves the entire subtree at the same level correctly');
  1221. }
  1222. public function testMoveToPrevSiblingOfAndChildrenCache()
  1223. {
  1224. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  1225. /* Tree used for tests
  1226. t1
  1227. | \
  1228. t2 t3
  1229. | \
  1230. t4 t5
  1231. | \
  1232. t6 t7
  1233. */
  1234. // fill children cache
  1235. $t3->getChildren();
  1236. $t1->getChildren();
  1237. // move
  1238. $t5->moveToPrevSiblingOf($t2);
  1239. $children = $t3->getChildren();
  1240. $expected = array(
  1241. 't4' => array(11, 12, 2),
  1242. );
  1243. $this->assertEquals($expected, $this->dumpNodes($children, true), 'moveToPrevSiblingOf() reinitializes the child collection of all concerned nodes');
  1244. $children = $t1->getChildren();
  1245. $expected = array(
  1246. 't5' => array(2, 7, 1),
  1247. 't2' => array(8, 9, 1),
  1248. 't3' => array(10, 13, 1),
  1249. );
  1250. $this->assertEquals($expected, $this->dumpNodes($children, true), 'moveToPrevSiblingOf() reinitializes the child collection of all concerned nodes');
  1251. }
  1252. public function testMoveToNextSiblingOfAndChildrenCache()
  1253. {
  1254. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  1255. /* Tree used for tests
  1256. t1
  1257. | \
  1258. t2 t3
  1259. | \
  1260. t4 t5
  1261. | \
  1262. t6 t7
  1263. */
  1264. // fill children cache
  1265. $t3->getChildren();
  1266. $t1->getChildren();
  1267. // move
  1268. $t5->moveToNextSiblingOf($t3);
  1269. $children = $t3->getChildren();
  1270. $expected = array(
  1271. 't4' => array(5, 6, 2),
  1272. );
  1273. $this->assertEquals($expected, $this->dumpNodes($children, true), 'moveToNextSiblingOf() reinitializes the child collection of all concerned nodes');
  1274. $children = $t1->getChildren();
  1275. $expected = array(
  1276. 't2' => array(2, 3, 1),
  1277. 't3' => array(4, 7, 1),
  1278. 't5' => array(8, 13, 1),
  1279. );
  1280. $this->assertEquals($expected, $this->dumpNodes($children, true), 'moveToNextSiblingOf() reinitializes the child collection of all concerned nodes');
  1281. }
  1282. public function testMoveToNextSiblingOf()
  1283. {
  1284. $this->assertTrue(method_exists('Table9', 'moveToNextSiblingOf'), 'nested_set adds a moveToNextSiblingOf() method');
  1285. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  1286. /* Tree used for tests
  1287. t1
  1288. | \
  1289. t2 t3
  1290. | \
  1291. t4 t5
  1292. | \
  1293. t6 t7
  1294. */
  1295. try {
  1296. $t5->moveToNextSiblingOf($t1);
  1297. $this->fail('moveToNextSiblingOf() throws an exception when the target is a root node');
  1298. } catch (PropelException $e) {
  1299. $this->assertTrue(true, 'moveToNextSiblingOf() throws an exception when the target is a root node');
  1300. }
  1301. try {
  1302. $t5->moveToNextSiblingOf($t6);
  1303. $this->fail('moveToNextSiblingOf() throws an exception when the target is a child node');
  1304. } catch (PropelException $e) {
  1305. $this->assertTrue(true, 'moveToNextSiblingOf() throws an exception when the target is a child node');
  1306. }
  1307. // moving up
  1308. $t = $t5->moveToNextSiblingOf($t3);
  1309. /* Results in
  1310. t1
  1311. | \ \
  1312. t2 t3 t5
  1313. | | \
  1314. t4 t6 t7
  1315. */
  1316. $this->assertEquals($t5, $t, 'moveToPrevSiblingOf() returns the object it was called on');
  1317. $expected = array(
  1318. 't1' => array(1, 14, 0),
  1319. 't2' => array(2, 3, 1),
  1320. 't3' => array(4, 7, 1),
  1321. 't4' => array(5, 6, 2),
  1322. 't5' => array(8, 13, 1),
  1323. 't6' => array(9, 10, 2),
  1324. 't7' => array(11, 12, 2),
  1325. );
  1326. $this->assertEquals($expected, $this->dumpTree(), 'moveToNextSiblingOf() moves the entire subtree up correctly');
  1327. // moving down
  1328. $t = $t5->moveToNextSiblingOf($t4);
  1329. /* Results in
  1330. t1
  1331. | \
  1332. t2 t3
  1333. | \
  1334. t4 t5
  1335. | \
  1336. t6 t7
  1337. */
  1338. $expected = array(
  1339. 't1' => array(1, 14, 0),
  1340. 't2' => array(2, 3, 1),
  1341. 't3' => array(4, 13, 1),
  1342. 't4' => array(5, 6, 2),
  1343. 't5' => array(7, 12, 2),
  1344. 't6' => array(8, 9, 3),
  1345. 't7' => array(10, 11, 3),
  1346. );
  1347. $this->assertEquals($expected, $this->dumpTree(), 'moveToNextSiblingOf() moves the entire subtree down correctly');
  1348. // moving at the same level
  1349. $t = $t4->moveToNextSiblingOf($t5);
  1350. /* Results in
  1351. t1
  1352. | \
  1353. t2 t3
  1354. | \
  1355. t5 t4
  1356. | \
  1357. t6 t7
  1358. */
  1359. $expected = array(
  1360. 't1' => array(1, 14, 0),
  1361. 't2' => array(2, 3, 1),
  1362. 't3' => array(4, 13, 1),
  1363. 't4' => array(11, 12, 2),
  1364. 't5' => array(5, 10, 2),
  1365. 't6' => array(6, 7, 3),
  1366. 't7' => array(8, 9, 3),
  1367. );
  1368. $this->assertEquals($expected, $this->dumpTree(), 'moveToNextSiblingOf() moves the entire subtree at the same level correctly');
  1369. }
  1370. public function testDeleteDescendants()
  1371. {
  1372. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  1373. /* Tree used for tests
  1374. t1
  1375. | \
  1376. t2 t3
  1377. | \
  1378. t4 t5
  1379. | \
  1380. t6 t7
  1381. */
  1382. $this->assertNull($t2->deleteDescendants(), 'deleteDescendants() returns null leafs');
  1383. $this->assertEquals(4, $t3->deleteDescendants(), 'deleteDescendants() returns the number of deleted nodes');
  1384. $this->assertEquals(5, $t3->getRightValue(), 'deleteDescendants() updates the current node');
  1385. $this->assertEquals(5, $t4->getLeftValue(), 'deleteDescendants() does not update existing nodes (because delete() clears the instance cache)');
  1386. $expected = array(
  1387. 't1' => array(1, 6, 0),
  1388. 't2' => array(2, 3, 1),
  1389. 't3' => array(4, 5, 1),
  1390. );
  1391. $this->assertEquals($expected, $this->dumpTree(), 'deleteDescendants() shifts the entire subtree correctly');
  1392. list($t1, $t2, $t3, $t4, $t5, $t6, $t7) = $this->initTree();
  1393. /* Tree used for tests
  1394. t1
  1395. | \
  1396. t2 t3
  1397. | \
  1398. t4 t5
  1399. | \
  1400. t6 t7
  1401. */
  1402. $this->assertEquals(6, $t1->deleteDescendants(), 'deleteDescendants() can be called on the root node');
  1403. $expected = array(
  1404. 't1' => array(1, 2, 0),
  1405. );
  1406. $this->assertEquals($expected, $this->dumpTree(), 'deleteDescendants() can delete all descendants of the root node');
  1407. }
  1408. public function testGetIterator()
  1409. {
  1410. $fixtures = $this->initTree();
  1411. $this->assertTrue(method_exists('Table9', 'getIterator'), 'nested_set adds a getIterator() method');
  1412. $root = Table9Peer::retrieveRoot();
  1413. $iterator = $root->getIterator();
  1414. $this->assertTrue($iterator instanceof NestedSetRecursiveIterator, 'getIterator() returns a NestedSetRecursiveIterator');
  1415. foreach ($iterator as $node) {
  1416. $expected = array_shift($fixtures);
  1417. $this->assertEquals($expected, $node, 'getIterator returns an iterator parsing the tree order by left column');
  1418. }
  1419. }
  1420. public function testCompatibilityProxies()
  1421. {
  1422. $proxies = array('createRoot', 'retrieveParent', 'setParentNode', 'getNumberOfDescendants', 'getNumberOfChildren', 'retrievePrevSibling', 'retrieveNextSibling', 'retrieveFirstChild', 'retrieveLastChild', 'getPath');
  1423. foreach ($proxies as $method) {
  1424. $this->assertFalse(method_exists('Table9', $method), 'proxies are not enabled by default');
  1425. $this->assertTrue(method_exists('Table10', $method), 'setting method_proxies to true adds compatibility proxies');
  1426. }
  1427. }
  1428. public function testCreateRoot()
  1429. {
  1430. $t = new Table10();
  1431. $t->createRoot();
  1432. $this->assertEquals($t->getLeftValue(), 1, 'createRoot() is an alias for makeRoot()');
  1433. $this->assertEquals($t->getRightValue(), 2, 'createRoot() is an alias for makeRoot()');
  1434. $this->assertEquals($t->getLevel(), 0, 'createRoot() is an alias for makeRoot()');
  1435. }
  1436. public function testGetPath()
  1437. {
  1438. list($t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10) = $this->initTreeWithScope();
  1439. /* Tree used for tests
  1440. Scope 1
  1441. t1
  1442. | \
  1443. t2 t3
  1444. | \
  1445. t4 t5
  1446. | \
  1447. t6 t7
  1448. Scope 2
  1449. t8
  1450. | \
  1451. t9 t10
  1452. */
  1453. $this->assertEquals(array($t1), $t1->getPath(), 'getPath() returns the current object for roots');
  1454. $path = $t5->getPath();
  1455. $expected = array(
  1456. 't1' => array(1, 14, 0),
  1457. 't3' => array(4, 13, 1),
  1458. 't5' => array(7, 12, 2),
  1459. );
  1460. $this->assertEquals($expected, $this->dumpNodes($path), 'getPath() returns path from the current scope only');
  1461. }
  1462. }