PageRenderTime 61ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/testing/RedUNIT/Base/Preloading.php

http://github.com/gabordemooij/redbean
PHP | 1617 lines | 976 code | 513 blank | 128 comment | 21 complexity | ccf277863c720ab0eb5be93c70108c7a MD5 | raw file
  1. <?php
  2. /**
  3. * RedUNIT_Base_Preloading
  4. *
  5. * @file RedUNIT/Base/Preloading.php
  6. * @desc Tests eager loading for parent beans.
  7. * @author Gabor de Mooij and the RedBeanPHP Community
  8. * @license New BSD/GPLv2
  9. *
  10. * (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
  11. * This source file is subject to the New BSD/GPLv2 License that is bundled
  12. * with this source code in the file license.txt.
  13. */
  14. class RedUNIT_Base_Preloading extends RedUNIT_Base
  15. {
  16. /**
  17. * Test Preload save.
  18. *
  19. * @return void
  20. */
  21. public function testPreloadSave()
  22. {
  23. testpack( 'Can we save in preload ?' );
  24. $publisher = R::dispense( 'publisher' );
  25. list( $book, $magazine ) = R::dispense( 'book', 2 );
  26. $book->ownPage = R::dispense( 'page', 3 );
  27. $magazine->ownPage = R::dispense( 'page', 2 );
  28. $magazine->title = 'magazine';
  29. $firstPage = reset( $book->ownPage );
  30. $secondPage = reset( $magazine->ownPage );
  31. $book->publisher = $publisher;
  32. $magazine->publisher = $publisher;
  33. R::storeAll( array( $book, $magazine ) );
  34. $firstPage = $firstPage->fresh();
  35. $secondPage = $secondPage->fresh();
  36. $pages = array( $firstPage, $secondPage );
  37. R::each( $pages, 'book,*.publisher', function ( $page, $book, $publisher ) {
  38. R::storeAll( array( $page, $book, $publisher ) );
  39. } );
  40. asrt( R::count( 'publisher' ), 1 );
  41. asrt( R::count( 'book' ), 2 );
  42. asrt( R::count( 'page' ), 5 );
  43. testpack( 'Can we re-preload ?' );
  44. $books = $publishers = array();
  45. R::each( $pages, 'book,*.publisher', function ( $page, $book, $publisher ) use ( &$pages, &$books, &$publishers ) {
  46. $books[] = $book;
  47. $publishers[] = $publisher;
  48. } );
  49. asrt( count( $books ), 2 );
  50. $foundMagazine = NULL;
  51. foreach ( $books as $book ) {
  52. if ( $book->title === 'magazine' ) {
  53. $foundMagazine = $book;
  54. }
  55. }
  56. asrt( ( $foundMagazine instanceof RedBean_OODBBean ), TRUE );
  57. asrt( count( $foundMagazine->ownPage ), 2 );
  58. testpack( 'Does deleting still work after preloading ?' );
  59. $firstPageOfMag = reset( $foundMagazine->ownPage );
  60. $firstID = $firstPageOfMag->id;
  61. unset( $foundMagazine->ownPage[$firstID] );
  62. R::store( $foundMagazine );
  63. asrt( count( $foundMagazine->ownPage ), 1 );
  64. }
  65. /**
  66. * Test shadow updates.
  67. *
  68. * @return void
  69. */
  70. public function testShadowUpdate()
  71. {
  72. testpack( 'Is the shadow updated ?' );
  73. $book = R::dispense( 'book' );
  74. $book->ownPage = R::dispense( 'page', 3 );
  75. $firstPage = reset( $book->ownPage );
  76. R::store( $book );
  77. $book = $book->fresh();
  78. R::preload( array( $book ), array( 'ownPage' => 'page' ) );
  79. R::store( $book );
  80. $book = $book->fresh();
  81. // Don't we lose beans when saving?
  82. asrt( count( $book->ownPage ), 3 );
  83. $book = $book->fresh();
  84. R::preload( array( $book ), array( 'ownPage' => 'page' ) );
  85. // Can we delete bean from list if bean has been preloaded ?
  86. unset( $book->ownPage[$firstPage->id] );
  87. R::store( $book );
  88. $book = $book->fresh();
  89. asrt( count( $book->ownPage ), 2 );
  90. $book = $book->fresh();
  91. R::preload( array( $book ), array( 'ownPage' => 'page' ) );
  92. // Can we add a page?
  93. $book->ownPage[] = R::dispense( 'page' );
  94. R::store( $book );
  95. $book = $book->fresh();
  96. asrt( count( $book->ownPage ), 3 );
  97. }
  98. /**
  99. * Test list manipulation i.c.w preloading.
  100. *
  101. * @return void
  102. */
  103. public function testListManipulationAndPreloader()
  104. {
  105. $book = R::dispense( 'book' );
  106. $book->sharedPage = R::dispense( 'page', 3 );
  107. $firstPage = reset( $book->sharedPage );
  108. R::store( $book );
  109. $book = $book->fresh();
  110. R::preload( array( $book ), array( 'sharedPage' => 'page' ) );
  111. R::store( $book );
  112. $book = $book->fresh();
  113. // Don't we lose beans when saving?
  114. asrt( count( $book->sharedPage ), 3 );
  115. $book = $book->fresh();
  116. R::preload( array( $book ), array( 'sharedPage' => 'page' ) );
  117. // Can we delete bean from list if bean has been preloaded ?
  118. unset( $book->sharedPage[$firstPage->id] );
  119. R::store( $book );
  120. $book = $book->fresh();
  121. asrt( count( $book->sharedPage ), 2 );
  122. $book = $book->fresh();
  123. R::preload( array( $book ), array( 'sharedPage' => 'page' ) );
  124. // Can we add a page?
  125. $book->sharedPage[] = R::dispense( 'page' );
  126. R::store( $book );
  127. $book = $book->fresh();
  128. asrt( count( $book->sharedPage ), 3 );
  129. }
  130. /**
  131. * Test no preloader.
  132. *
  133. * @return void
  134. */
  135. public function testNoPreload()
  136. {
  137. $books = R::dispense( 'book', 3 );
  138. $i = 0;
  139. foreach ( $books as $book ) {
  140. $i++;
  141. $book->name = $i;
  142. $book->ownPage[] = R::dispense( 'page' )->setAttr( 'name', $i );
  143. $book->author = R::dispense( 'author' )->setAttr( 'name', $i );
  144. $book->coauthor = R::dispense( 'author' )->setAttr( 'name', $i );
  145. }
  146. R::storeAll( $books );
  147. $books = R::find( 'book' );
  148. R::nuke();
  149. $i = 0;
  150. foreach ( $books as $book ) {
  151. asrt( $book->author->id, 0 );
  152. }
  153. }
  154. /**
  155. * Test basic preloader.
  156. *
  157. * @return void
  158. */
  159. public function testPreload()
  160. {
  161. $books = R::dispense( 'book', 3 );
  162. $i = 0;
  163. foreach ( $books as $book ) {
  164. $i++;
  165. $book->name = $i;
  166. $book->ownPage[] = R::dispense( 'page' )->setAttr( 'name', $i );
  167. $book->author = R::dispense( 'author' )->setAttr( 'name', $i );
  168. $book->coauthor = R::dispense( 'author' )->setAttr( 'name', $i );
  169. }
  170. R::storeAll( $books );
  171. $books = R::find( 'book' );
  172. R::preload( $books, array( 'author' ) );
  173. R::nuke();
  174. $i = 0;
  175. foreach ( $books as $book ) {
  176. asrt( $book->author->name, strval( ++$i ) );
  177. }
  178. }
  179. /**
  180. * Test preloader and aliasing.
  181. *
  182. * @return void
  183. */
  184. public function testAliasedPreload()
  185. {
  186. $books = R::dispense( 'book', 3 );
  187. $i = 0;
  188. foreach ( $books as $book ) {
  189. $i++;
  190. $book->name = $i;
  191. $book->ownPage[] = R::dispense( 'page' )->setAttr( 'name', $i );
  192. $book->author = R::dispense( 'author' )->setAttr( 'name', $i );
  193. $book->coauthor = R::dispense( 'author' )->setAttr( 'name', $i );
  194. }
  195. R::storeAll( $books );
  196. $books = R::find( 'book' );
  197. R::preload( $books, array( 'coauthor' => 'author' ) );
  198. R::nuke();
  199. $i = 0;
  200. foreach ( $books as $book ) {
  201. asrt( $book->fetchAs( 'author' )->coauthor->name, strval( ++$i ) );
  202. }
  203. }
  204. /**
  205. * Test various preloading combinations.
  206. *
  207. * @return void
  208. */
  209. public function testCombinedAndMultiple()
  210. {
  211. $books = R::dispense( 'book', 3 );
  212. $i = 0;
  213. foreach ( $books as $book ) {
  214. $i++;
  215. $book->name = $i;
  216. $book->ownPage[] = R::dispense( 'page' )->setAttr( 'name', $i );
  217. $book->author = R::dispense( 'author' )->setAttr( 'name', $i );
  218. $book->coauthor = R::dispense( 'author' )->setAttr( 'name', $i );
  219. $book->collection = R::dispense( 'collection' )->setAttr( 'name', $i );
  220. }
  221. R::storeAll( $books );
  222. $books = R::find( 'book' );
  223. R::preload( $books, array( 'coauthor' => 'author', 'author', 'collection' ) );
  224. R::nuke();
  225. $i = 0;
  226. foreach ( $books as $book ) {
  227. asrt( $book->author->name, strval( ++$i ) );
  228. }
  229. $i = 0;
  230. foreach ( $books as $book ) {
  231. asrt( $book->fetchAs( 'author' )->coauthor->name, strval( ++$i ) );
  232. }
  233. $i = 0;
  234. foreach ( $books as $book ) {
  235. asrt( $book->collection->name, strval( ++$i ) );
  236. }
  237. // Crud
  238. $books = R::dispense( 'book', 3 );
  239. $i = 0;
  240. foreach ( $books as $book ) {
  241. $i++;
  242. $book->name = $i;
  243. $book->ownPage[] = R::dispense( 'page' )->setAttr( 'name', $i );
  244. $book->author = R::dispense( 'author' )->setAttr( 'name', $i );
  245. $book->coauthor = R::dispense( 'author' )->setAttr( 'name', $i );
  246. $book->collection = R::dispense( 'collection' )->setAttr( 'name', $i );
  247. }
  248. R::storeAll( $books );
  249. $books = R::find( 'book' );
  250. R::preload( $books, array( 'coauthor' => 'author', 'author', 'collection' ) );
  251. $i = 0;
  252. foreach ( $books as $book ) {
  253. $book->author->name .= 'nth';
  254. }
  255. $i = 0;
  256. foreach ( $books as $book ) {
  257. $book->fetchAs( 'author' )->coauthor->name .= 'nth';
  258. }
  259. $i = 0;
  260. foreach ( $books as $book ) {
  261. $book->collection->name .= 'nth';
  262. }
  263. R::storeAll( $books );
  264. $books = R::find( 'books' );
  265. $i = 0;
  266. foreach ( $books as $book ) {
  267. asrt( $book->author->name, strval( ++$i ) . 'nth' );
  268. }
  269. $i = 0;
  270. foreach ( $books as $book ) {
  271. asrt( $book->fetchAs( 'author' )->coauthor->name, strval( ++$i ) . 'nth' );
  272. }
  273. $i = 0;
  274. foreach ( $books as $book ) {
  275. asrt( $book->collection->name, strval( ++$i ) . 'nth' );
  276. }
  277. }
  278. /**
  279. * Test preloading with multiple items having the same parent.
  280. *
  281. * @return void
  282. */
  283. public function testMultipleSameParents()
  284. {
  285. $author = R::dispense( 'author' );
  286. $author->setAttr( 'name', 'John' );
  287. R::store( $author );
  288. $books = R::dispense( 'book', 3 );
  289. $books[0]->title = 'First book';
  290. $books[1]->title = 'Second book';
  291. $books[2]->title = 'Third book';
  292. $author->ownBook = $books;
  293. R::store( $author );
  294. $collection = R::findAll( 'book' );
  295. R::preload( $collection, array( 'author' ) );
  296. R::nuke();
  297. foreach ( $collection as $item ) {
  298. asrt( $item->author->name, 'John' );
  299. }
  300. }
  301. public function testNested()
  302. {
  303. $authors = R::dispense( 'author', 2 );
  304. foreach ( $authors as $author ) {
  305. $author->ownBook = R::dispense( 'book', 2 );
  306. foreach ( $author->ownBook as $book ) {
  307. $book->ownPage = R::dispense( 'page', 2 );
  308. foreach ( $book->ownPage as $page ) {
  309. $page->ownText[] = R::dispense( 'text', 1 );
  310. }
  311. }
  312. }
  313. R::storeAll( $authors );
  314. $texts = R::find( 'text' );
  315. R::nuke();
  316. $text = reset( $texts );
  317. asrt( (int) ( $text->page->id ), 0 );
  318. }
  319. /**
  320. * Test nested preloading.
  321. *
  322. * @return void
  323. */
  324. public function testNestedPreload()
  325. {
  326. $authors = R::dispense( 'author', 2 );
  327. foreach ( $authors as $author ) {
  328. $author->ownBook = R::dispense( 'book', 2 );
  329. foreach ( $author->ownBook as $book ) {
  330. $book->ownPage = R::dispense( 'page', 2 );
  331. foreach ( $book->ownPage as $page ) {
  332. $page->ownText = R::dispense( 'text', 2 );
  333. }
  334. }
  335. }
  336. R::storeAll( $authors );
  337. $texts = R::find( 'text' );
  338. R::preload( $texts, array( 'page', 'page.book', 'page.book.author' ) );
  339. R::nuke();
  340. $text = reset( $texts );
  341. asrt( ( $text->page->id ) > 0, TRUE );
  342. asrt( ( $text->page->book->id ) > 0, TRUE );
  343. asrt( ( $text->page->book->author->id ) > 0, TRUE );
  344. }
  345. /**
  346. * Test nested preloading with aliasing.
  347. *
  348. * @return void
  349. */
  350. public function testNestedPreloadAlias()
  351. {
  352. $authors = R::dispense( 'author', 2 );
  353. foreach ( $authors as $author ) {
  354. $author->alias( 'coauthor' )->ownBook = R::dispense( 'book', 2 );
  355. foreach ( $author->alias( 'coauthor' )->ownBook as $book ) {
  356. $book->ownPage = R::dispense( 'page', 2 );
  357. foreach ( $book->ownPage as $page ) {
  358. $page->ownText = R::dispense( 'text', 2 );
  359. }
  360. }
  361. }
  362. R::storeAll( $authors );
  363. $texts = R::find( 'text' );
  364. R::preload( $texts, array( 'page', 'page.book', 'page.book.coauthor' => 'author' ) );
  365. R::nuke();
  366. $text = reset( $texts );
  367. asrt( ( $text->page->id ) > 0, TRUE );
  368. asrt( ( $text->page->book->id ) > 0, TRUE );
  369. asrt( ( $text->page->book->fetchAs( 'author' )->coauthor->id ) > 0, TRUE );
  370. }
  371. /**
  372. * Test preloading own list with short notation.
  373. *
  374. * @return void
  375. */
  376. public function testPreloadOwnlistShort()
  377. {
  378. $tree = R::dispense( 'tree' );
  379. $tree->ownLeaf = R::dispense( 'leaf', 3 );
  380. $id = R::store( $tree );
  381. $tree = R::load( 'tree', $id );
  382. R::preload( $tree, 'ownLeaf|leaf' );
  383. R::nuke();
  384. asrt( count( $tree->ownLeaf ), 3 );
  385. }
  386. /**
  387. * Test preloading own list.
  388. * (also short notation)
  389. *
  390. * @return void
  391. */
  392. public function testPreloadOwnlist()
  393. {
  394. $authors = R::dispense( 'author', 2 );
  395. foreach ( $authors as $author ) {
  396. $author->ownBook = R::dispense( 'book', 2 );
  397. foreach ( $author->ownBook as $book ) {
  398. $book->ownPage = R::dispense( 'page', 2 );
  399. foreach ( $book->ownPage as $page ) {
  400. $page->ownText = R::dispense( 'text', 2 );
  401. }
  402. }
  403. }
  404. R::storeAll( $authors );
  405. $authors = R::find( 'author' );
  406. R::preload( $authors, 'ownBook|book,ownBook.ownPage|page,ownBook.ownPage.ownText|text' );
  407. R::nuke();
  408. $author = reset( $authors );
  409. asrt( count( $author->ownBook ), 2 );
  410. $book = reset( $author->ownBook );
  411. asrt( count( $book->ownPage ), 2 );
  412. $page = reset( $book->ownPage );
  413. asrt( count( $page->ownText ), 2 );
  414. }
  415. /**
  416. * test preloading of shared lists.
  417. *
  418. * @return void
  419. */
  420. public function testPreloadSharedLists()
  421. {
  422. list( $a1, $a2, $a3 ) = R::dispense( 'army', 3 );
  423. list( $v1, $v2, $v3 ) = R::dispense( 'village', 3 );
  424. $v1->name = 'a';
  425. $v2->name = 'b';
  426. $v3->name = 'c';
  427. $a1->name = 'one';
  428. $a2->name = 'two';
  429. $a3->name = 'three';
  430. $a1->sharedVillage = array( $v1, $v3 );
  431. $a2->sharedVillage = array( $v3, $v1, $v2 );
  432. $a3->sharedVillage = array();
  433. list( $g, $e ) = R::dispense( 'people', 2 );
  434. $g->nature = 'good';
  435. $e->nature = 'evil';
  436. $v1->sharedPeople = array( $g );
  437. $v2->sharedPeople = array( $e, $g );
  438. $v3->sharedPeople = array( $g );
  439. R::storeAll( array( $a1, $a2, $a3 ) );
  440. $armies = R::find( 'army' );
  441. R::each(
  442. $armies,
  443. array( 'sharedVillage' => 'village', 'sharedVillage.sharedPeople' => 'people' ),
  444. function ( $army, $villages, $people ) {
  445. if ( $army->name == 'one' ) {
  446. $names = array();
  447. foreach ( $villages as $village ) {
  448. $names[] = $village->name;
  449. }
  450. sort( $names );
  451. $names = implode( ',', $names );
  452. asrt( $names, 'a,c' );
  453. }
  454. if ( $army->name == 'two' ) {
  455. $names = array();
  456. foreach ( $villages as $village ) {
  457. $names[] = $village->name;
  458. }
  459. sort( $names );
  460. $names = implode( ',', $names );
  461. asrt( $names, 'a,b,c' );
  462. }
  463. if ( $army->name == 'three' ) {
  464. asrt( count( $villages ), 0 );
  465. }
  466. }
  467. );
  468. R::nuke();
  469. foreach ( $armies as $army ) {
  470. $villages = $army->sharedVillage;
  471. $ppl = array();
  472. foreach ( $villages as $village ) {
  473. $ppl = array_merge( $ppl, $village->sharedPeople );
  474. }
  475. if ( $army->name == 'one' ) {
  476. asrt( count( $villages ), 2 );
  477. asrt( count( $ppl ), 2 );
  478. foreach ( $ppl as $p ) {
  479. if ( $p->nature !== 'good' ) fail();
  480. }
  481. $names = array();
  482. foreach ( $villages as $village ) {
  483. $names[] = $village->name;
  484. }
  485. sort( $names );
  486. $names = implode( ',', $names );
  487. asrt( $names, 'a,c' );
  488. $natures = array();
  489. foreach ( $ppl as $p ) {
  490. $natures[] = $p->nature;
  491. }
  492. sort( $natures );
  493. $natures = implode( ',', $natures );
  494. asrt( $natures, 'good,good' );
  495. }
  496. if ( $army->name == 'two' ) {
  497. asrt( count( $villages ), 3 );
  498. asrt( count( $ppl ), 4 );
  499. $names = array();
  500. foreach ( $villages as $village ) {
  501. $names[] = $village->name;
  502. }
  503. sort( $names );
  504. $names = implode( ',', $names );
  505. asrt( $names, 'a,b,c' );
  506. $natures = array();
  507. foreach ( $ppl as $p ) {
  508. $natures[] = $p->nature;
  509. }
  510. sort( $natures );
  511. $natures = implode( ',', $natures );
  512. asrt( $natures, 'evil,good,good,good' );
  513. }
  514. if ( $army->name == 'three' ) {
  515. asrt( count( $villages ), 0 );
  516. asrt( count( $ppl ), 0 );
  517. }
  518. }
  519. // Now test with empty beans
  520. $authors = R::dispense( 'author', 2 );
  521. R::storeAll( $authors );
  522. $authors = R::find( 'author' );
  523. R::preload( $authors, array( 'ownBook' => 'book', 'ownBook.ownPage' => 'page', 'ownBook.ownPage.ownText' => 'text' ) );
  524. $author = reset( $authors );
  525. asrt( count( $author->ownBook ), 0 );
  526. $texts = R::dispense( 'text', 2 );
  527. R::storeAll( $texts );
  528. $texts = R::find( 'text' );
  529. R::preload( $texts, array( 'page', 'page.book' ) );
  530. $text = reset( $texts );
  531. asrt( $text->page, NULL );
  532. }
  533. /**
  534. * Test preloading with closure (each).
  535. *
  536. * @return void
  537. */
  538. public function testClosure()
  539. {
  540. $books = R::dispense( 'book', 3 );
  541. $i = 0;
  542. foreach ( $books as $book ) {
  543. $i++;
  544. $book->name = $i;
  545. $book->ownPage[] = R::dispense( 'page' )->setAttr( 'name', $i );
  546. $book->author = R::dispense( 'author' )->setAttr( 'name', $i );
  547. $book->coauthor = R::dispense( 'author' )->setAttr( 'name', $i );
  548. }
  549. R::storeAll( $books );
  550. $books = R::find( 'book' );
  551. $hasNuked = FALSE;
  552. R::preload(
  553. $books,
  554. 'author',
  555. function ( $book, $author ) use ( &$hasNuked ) {
  556. if ( !$hasNuked ) {
  557. R::nuke();
  558. $hasNuked = TRUE;
  559. }
  560. asrt( $book->getMeta( 'type' ), 'book' );
  561. asrt( $author->getMeta( 'type' ), 'author' );
  562. }
  563. );
  564. }
  565. /**
  566. * Test preloading with closure and abbreviations (*).
  567. *
  568. * @return void
  569. */
  570. public function testClosureAbbreviations()
  571. {
  572. $authors = R::dispense( 'author', 2 );
  573. foreach ( $authors as $author ) {
  574. $author->ownBook = R::dispense( 'book', 2 );
  575. foreach ( $author->ownBook as $book ) {
  576. $book->ownPage = R::dispense( 'page', 2 );
  577. foreach ( $book->ownPage as $page ) {
  578. $page->ownText = R::dispense( 'text', 2 );
  579. }
  580. }
  581. }
  582. R::storeAll( $authors );
  583. $texts = R::find( 'text' );
  584. $hasNuked = FALSE;
  585. R::preload(
  586. $texts,
  587. 'page,*.book,*.author',
  588. function ( $text, $page, $book, $author ) use ( &$hasNuked ) {
  589. if ( !$hasNuked ) {
  590. R::nuke();
  591. $hasNuked = TRUE;
  592. }
  593. asrt( $text->getMeta( 'type' ), 'text' );
  594. asrt( $page->getMeta( 'type' ), 'page' );
  595. asrt( $book->getMeta( 'type' ), 'book' );
  596. asrt( $author->getMeta( 'type' ), 'author' );
  597. }
  598. );
  599. }
  600. /**
  601. * Test preloading with same-level abbreviations (&)
  602. *
  603. * @return void
  604. */
  605. public function testClosureAbbreviationsSameLevel()
  606. {
  607. $authors = R::dispense( 'author', 2 );
  608. foreach ( $authors as $author ) {
  609. $author->ownBook = R::dispense( 'book', 2 );
  610. foreach ( $author->ownBook as $book ) {
  611. $book->ownPage = R::dispense( 'page', 2 );
  612. foreach ( $book->ownPage as $page ) {
  613. $page->ownText = R::dispense( 'text', 2 );
  614. }
  615. }
  616. }
  617. foreach ( $authors as $author ) {
  618. foreach ( $author->ownBook as $book ) {
  619. $book->shelf = R::dispense( 'shelf' )->setAttr( 'name', 'abc' );
  620. }
  621. }
  622. R::storeAll( $authors );
  623. $texts = R::find( 'text' );
  624. $hasNuked = FALSE;
  625. R::preload(
  626. $texts,
  627. 'page,*.book,*.author,&.shelf',
  628. function ( $text, $page, $book, $author, $shelf ) use ( &$hasNuked ) {
  629. if ( !$hasNuked ) {
  630. R::nuke();
  631. $hasNuked = TRUE;
  632. }
  633. asrt( $text->getMeta( 'type' ), 'text' );
  634. asrt( $page->getMeta( 'type' ), 'page' );
  635. asrt( ( $page->id > 0 ), TRUE );
  636. asrt( $book->getMeta( 'type' ), 'book' );
  637. asrt( ( $book->id > 0 ), TRUE );
  638. asrt( $author->getMeta( 'type' ), 'author' );
  639. asrt( $shelf->getMeta( 'type' ), 'shelf' );
  640. }
  641. );
  642. }
  643. /**
  644. * Test preloading with closure and abbr and own list.
  645. *
  646. * @return void
  647. */
  648. public function testClosureAbbreviationOwnlist()
  649. {
  650. $authors = R::dispense( 'author', 2 );
  651. foreach ( $authors as $author ) {
  652. $author->ownBook = R::dispense( 'book', 2 );
  653. foreach ( $author->ownBook as $book ) {
  654. $book->ownPage = R::dispense( 'page', 2 );
  655. foreach ( $book->ownPage as $page ) {
  656. $page->ownText = R::dispense( 'text', 2 );
  657. }
  658. }
  659. }
  660. R::storeAll( $authors );
  661. $pages = R::find( 'page' );
  662. $hasNuked = FALSE;
  663. R::preload(
  664. $pages,
  665. array( 'book', '*.author', 'ownText' => 'text' ),
  666. function ( $page, $book, $author, $texts ) use ( &$hasNuked ) {
  667. if ( !$hasNuked ) {
  668. R::nuke();
  669. $hasNuked = TRUE;
  670. }
  671. asrt( $page->getMeta( 'type' ), 'page' );
  672. asrt( ( $page->id > 0 ), TRUE );
  673. asrt( $book->getMeta( 'type' ), 'book' );
  674. asrt( ( $book->id > 0 ), TRUE );
  675. asrt( $author->getMeta( 'type' ), 'author' );
  676. asrt( ( $author->id > 0 ), TRUE );
  677. asrt( is_array( $texts ), TRUE );
  678. asrt( count( $texts ), 2 );
  679. $first = reset( $texts );
  680. asrt( $first->getMeta( 'type' ), 'text' );
  681. }
  682. );
  683. }
  684. /**
  685. * Test variations.
  686. *
  687. * @return void
  688. */
  689. public function testVariations()
  690. {
  691. $authors = R::dispense( 'author', 2 );
  692. foreach ( $authors as $author ) {
  693. $author->ownBook = R::dispense( 'book', 2 );
  694. foreach ( $author->ownBook as $book ) {
  695. $book->ownPage = R::dispense( 'page', 2 );
  696. $book->cover = R::dispense( 'cover', 1 );
  697. foreach ( $book->ownPage as $page ) {
  698. $page->ownText = R::dispense( 'text', 2 );
  699. }
  700. foreach ( $book->ownPage as $page ) {
  701. $page->ownPicture = R::dispense( 'picture', 3 );
  702. }
  703. }
  704. }
  705. R::storeAll( $authors );
  706. $texts = R::find( 'text' );
  707. $hasNuked = FALSE;
  708. $i = 0;
  709. R::each(
  710. $texts,
  711. array(
  712. 'page',
  713. '*.ownPicture' => 'picture',
  714. '&.book',
  715. '*.cover',
  716. '&.author'
  717. ),
  718. function ( $t, $p, $x, $b, $c, $a ) use ( &$hasNuked, &$i ) {
  719. if ( !$hasNuked ) {
  720. R::nuke();
  721. $hasNuked = TRUE;
  722. }
  723. $i++;
  724. asrt( count( $x ), 3 );
  725. asrt( ( $p->id > 0 ), TRUE );
  726. asrt( ( $c->id > 0 ), TRUE );
  727. asrt( ( $t->id > 0 ), TRUE );
  728. asrt( ( $b->id > 0 ), TRUE );
  729. asrt( ( $a->id > 0 ), TRUE );
  730. asrt( $t->getMeta( 'type' ), 'text' );
  731. asrt( $p->getMeta( 'type' ), 'page' );
  732. asrt( $c->getMeta( 'type' ), 'cover' );
  733. asrt( $b->getMeta( 'type' ), 'book' );
  734. asrt( $a->getMeta( 'type' ), 'author' );
  735. $x1 = reset( $x );
  736. asrt( $x1->getMeta( 'type' ), 'picture' );
  737. }
  738. );
  739. // Follows the first parameter
  740. asrt( $i, 16 );
  741. }
  742. /**
  743. * Test complex variations.
  744. *
  745. * @return void
  746. */
  747. public function testVariations2()
  748. {
  749. // Extra, test in combination with writer cache
  750. R::$writer->setUseCache( TRUE );
  751. $villages = R::dispense( 'village', 3 );
  752. foreach ( $villages as $v ) {
  753. $v->ownBuilding = R::dispense( 'building', 3 );
  754. }
  755. foreach ( $villages as $v ) {
  756. foreach ( $v->ownBuilding as $b ) {
  757. $b->ownFurniture = R::dispense( 'furniture', 2 );
  758. }
  759. }
  760. $armies = R::dispense( 'army', 3 );
  761. $villages[0]->sharedArmy = array( $armies[1], $armies[2] );
  762. $villages[1]->sharedArmy = array( $armies[0], $armies[1] );
  763. $villages[2]->sharedArmy = array( $armies[2] );
  764. $soldiers = R::dispense( 'soldier', 4 );
  765. $armies[0]->sharedSoldier = array( $soldiers[0], $soldiers[1], $soldiers[2] );
  766. $armies[1]->sharedSoldier = array( $soldiers[2], $soldiers[1] );
  767. $armies[2]->sharedSoldier = array( $soldiers[2] );
  768. $counter = 0;
  769. foreach ( $villages as $v ) {
  770. $v->name = $counter++;
  771. }
  772. $counter = 0;
  773. foreach ( $armies as $a ) {
  774. $a->name = $counter++;
  775. }
  776. $counter = 0;
  777. foreach ( $soldiers as $s ) {
  778. $s->name = $counter++;
  779. }
  780. $buildings = R::dispense( 'building', 4 );
  781. $villages[0]->ownBuilding = array( $buildings[0] );
  782. $villages[1]->ownBuilding = array( $buildings[1], $buildings[2] );
  783. $villages[2]->ownBuilding = array( $buildings[3] );
  784. $counter = 0;
  785. foreach ( $buildings as $b ) $b->name = $counter++;
  786. $books = R::dispense( 'book', 5 );
  787. $counter = 0;
  788. foreach ( $books as $b ) $b->name = $counter++;
  789. $buildings[0]->ownBook = array( $books[0], $books[1] );
  790. $buildings[1]->ownBook = array( $books[2] );
  791. $buildings[2]->ownBook = array( $books[3], $books[4] );
  792. $world = R::dispense( 'world' );
  793. $world->name = 'w1';
  794. $villages[1]->world = $world;
  795. R::storeAll( $villages );
  796. $towns = R::find( 'village' );
  797. $counter = 0;
  798. R::each(
  799. $towns,
  800. array(
  801. 'sharedArmy' => 'army',
  802. 'sharedArmy.sharedSoldier' => 'soldier',
  803. 'ownBuilding' => 'building',
  804. 'ownBuilding.ownBook' => 'book',
  805. 'world'
  806. ),
  807. function ( $t, $a, $s, $b, $x, $w ) use ( &$counter ) {
  808. if ( $counter === 0 ) {
  809. asrt( $w, NULL );
  810. asrt( (string) $t->name, '0' );
  811. asrt( count( $t->sharedArmy ), 2 );
  812. $list = array();
  813. foreach ( $a as $item ) {
  814. $list[] = $item->name;
  815. }
  816. sort( $list );
  817. asrt( implode( ',', $list ), '1,2' );
  818. $list = array();
  819. foreach ( $s as $item ) {
  820. $list[] = $item->name;
  821. }
  822. sort( $list );
  823. asrt( implode( ',', $list ), '1,2' );
  824. $list = array();
  825. foreach ( $b as $item ) {
  826. $list[] = $item->name;
  827. }
  828. sort( $list );
  829. asrt( implode( ',', $list ), '0' );
  830. $list = array();
  831. foreach ( $x as $item ) {
  832. $list[] = $item->name;
  833. }
  834. sort( $list );
  835. asrt( implode( ',', $list ), '0,1' );
  836. $first = reset( $a );
  837. asrt( $first->getMeta( 'type' ), 'army' );
  838. $first = reset( $s );
  839. asrt( $first->getMeta( 'type' ), 'soldier' );
  840. $first = reset( $b );
  841. asrt( $first->getMeta( 'type' ), 'building' );
  842. $first = reset( $x );
  843. asrt( $first->getMeta( 'type' ), 'book' );
  844. } elseif ( $counter === 1 ) {
  845. asrt( $w->name, 'w1' );
  846. asrt( (string) $t->name, '1' );
  847. asrt( count( $t->sharedArmy ), 2 );
  848. $list = array();
  849. foreach ( $a as $item ) {
  850. $list[] = $item->name;
  851. }
  852. sort( $list );
  853. asrt( implode( ',', $list ), '0,1' );
  854. $list = array();
  855. foreach ( $s as $item ) {
  856. $list[] = $item->name;
  857. }
  858. sort( $list );
  859. asrt( implode( ',', $list ), '0,1,2' );
  860. $list = array();
  861. foreach ( $b as $item ) {
  862. $list[] = $item->name;
  863. }
  864. sort( $list );
  865. asrt( implode( ',', $list ), '1,2' );
  866. $list = array();
  867. foreach ( $x as $item ) {
  868. $list[] = $item->name;
  869. }
  870. sort( $list );
  871. asrt( implode( ',', $list ), '2,3,4' );
  872. $first = reset( $a );
  873. asrt( $first->getMeta( 'type' ), 'army' );
  874. $first = reset( $s );
  875. asrt( $first->getMeta( 'type' ), 'soldier' );
  876. $first = reset( $b );
  877. asrt( $first->getMeta( 'type' ), 'building' );
  878. $first = reset( $x );
  879. asrt( $first->getMeta( 'type' ), 'book' );
  880. } elseif ( $counter === 2 ) {
  881. asrt( $w, NULL );
  882. asrt( (string) $t->name, '2' );
  883. asrt( count( $t->sharedArmy ), 1 );
  884. $list = array();
  885. foreach ( $a as $item ) {
  886. $list[] = $item->name;
  887. }
  888. sort( $list );
  889. asrt( implode( ',', $list ), '2' );
  890. $list = array();
  891. foreach ( $s as $item ) {
  892. $list[] = $item->name;
  893. }
  894. sort( $list );
  895. asrt( implode( ',', $list ), '2' );
  896. $list = array();
  897. foreach ( $b as $item ) {
  898. $list[] = $item->name;
  899. }
  900. sort( $list );
  901. asrt( implode( ',', $list ), '3' );
  902. asrt( count( $x ), 0 );
  903. $first = reset( $a );
  904. asrt( $first->getMeta( 'type' ), 'army' );
  905. $first = reset( $s );
  906. asrt( $first->getMeta( 'type' ), 'soldier' );
  907. $first = reset( $b );
  908. asrt( $first->getMeta( 'type' ), 'building' );
  909. }
  910. $counter++;
  911. }
  912. );
  913. }
  914. /**
  915. * Test preloading variations with caching.
  916. *
  917. * @return void
  918. */
  919. public function testPreloadingVariationsAndCache()
  920. {
  921. R::$writer->setUseCache( FALSE );
  922. $books = R::dispense( 'book', 4 );
  923. foreach ( $books as $b ) $b->ownPage = R::dispense( 'page', 2 );
  924. foreach ( $books as $b ) $b->sharedAd = R::dispense( 'ad', 2 );
  925. R::storeAll( $books );
  926. $books = R::find( 'book' );
  927. R::preload(
  928. $books,
  929. array(
  930. 'ownPage' => array( 'page', array( ' AND page.id > 0 LIMIT ? ', array( 2 ) ) ),
  931. 'sharedAd' => array( 'ad', array( ' AND ad.id > 0 LIMIT ? ', array( 4 ) ) )
  932. )
  933. );
  934. asrt( count( $books[1]->ownPage ), 2 );
  935. asrt( count( $books[1]->sharedAd ), 2 );
  936. asrt( count( $books[2]->ownPage ), 0 );
  937. asrt( count( $books[2]->sharedAd ), 2 );
  938. asrt( count( $books[3]->ownPage ), 0 );
  939. asrt( count( $books[3]->sharedAd ), 0 );
  940. }
  941. /**
  942. * Test variations and cache 2.
  943. *
  944. * @return void
  945. */
  946. public function testPreloadingVariationsAndCache2()
  947. {
  948. R::$writer->setUseCache( FALSE );
  949. $villages = R::dispense( 'village', 3 );
  950. foreach ( $villages as $v ) {
  951. $v->ownBuilding = R::dispense( 'building', 3 );
  952. }
  953. foreach ( $villages as $v ) {
  954. foreach ( $v->ownBuilding as $b ) {
  955. $b->ownFurniture = R::dispense( 'furniture', 2 );
  956. }
  957. }
  958. $armies = R::dispense( 'army', 3 );
  959. $villages[0]->sharedArmy = array( $armies[1], $armies[2] );
  960. $villages[1]->sharedArmy = array( $armies[0], $armies[1] );
  961. $villages[2]->sharedArmy = array( $armies[2] );
  962. $soldiers = R::dispense( 'soldier', 4 );
  963. $armies[0]->sharedSoldier = array( $soldiers[0], $soldiers[1], $soldiers[2] );
  964. $armies[1]->sharedSoldier = array( $soldiers[2], $soldiers[1] );
  965. $armies[2]->sharedSoldier = array( $soldiers[2] );
  966. $counter = 0;
  967. foreach ( $villages as $v ) $v->name = $counter++;
  968. $counter = 0;
  969. foreach ( $armies as $a ) $a->name = $counter++;
  970. $counter = 0;
  971. foreach ( $soldiers as $s ) $s->name = $counter++;
  972. $buildings = R::dispense( 'building', 4 );
  973. $villages[0]->ownBuilding = array( $buildings[0] );
  974. $villages[1]->ownBuilding = array( $buildings[1], $buildings[2] );
  975. $villages[2]->ownBuilding = array( $buildings[3] );
  976. $counter = 0;
  977. foreach ( $buildings as $b ) $b->name = $counter++;
  978. $books = R::dispense( 'book', 5 );
  979. $counter = 0;
  980. foreach ( $books as $b ) $b->name = $counter++;
  981. $buildings[0]->ownBook = array( $books[0], $books[1] );
  982. $buildings[1]->ownBook = array( $books[2] );
  983. $buildings[2]->ownBook = array( $books[3], $books[4] );
  984. $world = R::dispense( 'world' );
  985. $world->name = 'w1';
  986. $villages[1]->world = $world;
  987. R::storeAll( $villages );
  988. $towns = R::find( 'village' );
  989. $counter = 0;
  990. R::each(
  991. $towns,
  992. array(
  993. 'sharedArmy' => 'army',
  994. 'sharedArmy.sharedSoldier' => array( 'soldier', array( ' ORDER BY soldier.name DESC ', array() ) ),
  995. 'ownBuilding' => array( 'building', array( ' ORDER BY building.name DESC ', array() ) ),
  996. 'ownBuilding.ownBook' => 'book',
  997. 'world'
  998. ),
  999. function ( $t, $a, $s, $b, $x, $w ) use ( &$counter ) {
  1000. if ( $counter === 0 ) {
  1001. asrt( $w, NULL );
  1002. asrt( (string) $t->name, '0' );
  1003. asrt( count( $t->sharedArmy ), 2 );
  1004. $list = array();
  1005. foreach ( $a as $item ) {
  1006. $list[] = $item->name;
  1007. }
  1008. sort( $list );
  1009. asrt( implode( ',', $list ), '1,2' );
  1010. $list = array();
  1011. foreach ( $s as $item ) {
  1012. $list[] = $item->name;
  1013. }
  1014. asrt( implode( ',', $list ), '2,1' );
  1015. $list = array();
  1016. foreach ( $b as $item ) {
  1017. $list[] = $item->name;
  1018. }
  1019. sort( $list );
  1020. asrt( implode( ',', $list ), '0' );
  1021. $list = array();
  1022. foreach ( $x as $item ) {
  1023. $list[] = $item->name;
  1024. }
  1025. sort( $list );
  1026. asrt( implode( ',', $list ), '0,1' );
  1027. $first = reset( $a );
  1028. asrt( $first->getMeta( 'type' ), 'army' );
  1029. $first = reset( $s );
  1030. asrt( $first->getMeta( 'type' ), 'soldier' );
  1031. $first = reset( $b );
  1032. asrt( $first->getMeta( 'type' ), 'building' );
  1033. $first = reset( $x );
  1034. asrt( $first->getMeta( 'type' ), 'book' );
  1035. } elseif ( $counter === 1 ) {
  1036. asrt( $w->name, 'w1' );
  1037. asrt( (string) $t->name, '1' );
  1038. asrt( count( $t->sharedArmy ), 2 );
  1039. $list = array();
  1040. foreach ( $a as $item ) {
  1041. $list[] = $item->name;
  1042. }
  1043. sort( $list );
  1044. asrt( implode( ',', $list ), '0,1' );
  1045. $list = array();
  1046. foreach ( $s as $item ) {
  1047. $list[] = $item->name;
  1048. }
  1049. sort( $list );
  1050. asrt( implode( ',', $list ), '0,1,2' );
  1051. $list = array();
  1052. foreach ( $b as $item ) {
  1053. $list[] = $item->name;
  1054. }
  1055. asrt( implode( ',', $list ), '2,1' );
  1056. $list = array();
  1057. foreach ( $x as $item ) {
  1058. $list[] = $item->name;
  1059. }
  1060. sort( $list );
  1061. asrt( implode( ',', $list ), '2,3,4' );
  1062. $first = reset( $a );
  1063. asrt( $first->getMeta( 'type' ), 'army' );
  1064. $first = reset( $s );
  1065. asrt( $first->getMeta( 'type' ), 'soldier' );
  1066. $first = reset( $b );
  1067. asrt( $first->getMeta( 'type' ), 'building' );
  1068. $first = reset( $x );
  1069. asrt( $first->getMeta( 'type' ), 'book' );
  1070. } elseif ( $counter === 2 ) {
  1071. asrt( $w, NULL );
  1072. asrt( (string) $t->name, '2' );
  1073. asrt( count( $t->sharedArmy ), 1 );
  1074. $list = array();
  1075. foreach ( $a as $item ) {
  1076. $list[] = $item->name;
  1077. }
  1078. sort( $list );
  1079. asrt( implode( ',', $list ), '2' );
  1080. $list = array();
  1081. foreach ( $s as $item ) {
  1082. $list[] = $item->name;
  1083. }
  1084. sort( $list );
  1085. asrt( implode( ',', $list ), '2' );
  1086. $list = array();
  1087. foreach ( $b as $item ) {
  1088. $list[] = $item->name;
  1089. }
  1090. sort( $list );
  1091. asrt( implode( ',', $list ), '3' );
  1092. asrt( count( $x ), 0 );
  1093. $first = reset( $a );
  1094. asrt( $first->getMeta( 'type' ), 'army' );
  1095. $first = reset( $s );
  1096. asrt( $first->getMeta( 'type' ), 'soldier' );
  1097. $first = reset( $b );
  1098. asrt( $first->getMeta( 'type' ), 'building' );
  1099. }
  1100. $counter++;
  1101. }
  1102. );
  1103. }
  1104. }