3ce6570bec023f533bb75b52a1c9c261888d56b7
[yaffs-website] / vendor / gabordemooij / redbean / testing / RedUNIT / Base / Traverse.php
1 <?php
2
3 namespace RedUNIT\Base;
4
5 use RedUNIT\Base as Base;
6 use RedBeanPHP\Facade as R;
7 use RedBeanPHP\RedException as RedException;
8 use RedBeanPHP\OODBBean as OODBBean;
9
10 /**
11  * Traverse
12  *
13  * Tests whether RedBeanPHP can easily deal with hierarchies
14  * of beans.
15  *
16  * @file    RedUNIT/Base/Traverse.php
17  * @desc    Tests traversal functionality
18  * @author  Gabor de Mooij and the RedBeanPHP Community
19  * @license New BSD/GPLv2
20  *
21  * (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
22  * This source file is subject to the New BSD/GPLv2 License that is bundled
23  * with this source code in the file license.txt.
24  */
25 class Traverse extends Base
26 {
27
28         /**
29          * Very simple traverse case (one-level).
30          *
31          * @return void
32          */
33         public function testSimplestTraversal()
34         {
35                 R::nuke();
36                 $books = R::dispense( 'book', 10 );
37                 $i = 1;
38                 foreach( $books as $book ) {
39                         $book->title = 'Book ' . ( $i++ );
40                 }
41                 $books[5]->marked = TRUE;
42                 $shelf = R::dispense( 'shelf' );
43                 $shelf->ownBook = $books;
44                 $found = NULL;
45                 $shelf->traverse('ownBookList', function( $book ) use ( &$found ) {
46                         if ( $book->marked ) $found = $book;
47                 });
48                 asrt( ( $found->marked == TRUE ), TRUE );
49                 asrt( $found->title, 'Book 6' );
50         }
51
52         /**
53          * Tests basic traversal.
54          *
55          * @return void
56          */
57         public function testBasicTraversal()
58         {
59                 R::nuke();
60                 $pageA = R::dispense( 'page' )->setAttr( 'title', 'a' );
61                 $pageB = R::dispense( 'page' )->setAttr( 'title', 'b' );
62                 $pageC = R::dispense( 'page' )->setAttr( 'title', 'c' );
63                 $pageD = R::dispense( 'page' )->setAttr( 'title', 'd' );
64                 $pageE = R::dispense( 'page' )->setAttr( 'title', 'e' );
65                 $pageF = R::dispense( 'page' )->setAttr( 'title', 'f' );
66                 $pageG = R::dispense( 'page' )->setAttr( 'title', 'g' );
67                 $pageH = R::dispense( 'page' )->setAttr( 'title', 'h' );
68                 $pageA->ownPage = array( $pageB, $pageC );
69                 $pageB->ownPage = array( $pageD );
70                 $pageC->ownPage = array( $pageE, $pageF );
71                 $pageD->ownPage = array( $pageG );
72                 $pageF->ownPage = array( $pageH );
73                 R::store( $pageA );
74                 $pageA = $pageA->fresh();
75                 //also tests non-existant column handling by count().
76                 asrt( R::count( 'page', ' price = ? ', array( '5' ) ), 0);
77                 asrt( R::count( 'tag',  ' title = ? ', array( 'new' ) ), 0);
78                 $pageA->traverse( 'ownPageList', function( $bean ) {
79                         $bean->price = 5;
80                 });
81                 R::store( $pageA );
82                 asrt( R::count( 'page', ' price = ? ', array( '5' ) ), 7);
83         }
84
85         /**
86         * Test traversing paths, ancestry.
87         *
88         * @return void
89         */
90         public function testTraversePaths()
91         {
92                 R::nuke();
93                 $pageA = R::dispense( 'page' )->setAttr( 'title', 'a' );
94                 $pageB = R::dispense( 'page' )->setAttr( 'title', 'b' );
95                 $pageC = R::dispense( 'page' )->setAttr( 'title', 'c' );
96                 $pageD = R::dispense( 'page' )->setAttr( 'title', 'd' );
97                 $pageE = R::dispense( 'page' )->setAttr( 'title', 'e' );
98                 $pageF = R::dispense( 'page' )->setAttr( 'title', 'f' );
99                 $pageG = R::dispense( 'page' )->setAttr( 'title', 'g' );
100                 $pageH = R::dispense( 'page' )->setAttr( 'title', 'h' );
101                 $pageA->ownPage = array( $pageB, $pageC );
102                 $pageB->ownPage = array( $pageD );
103                 $pageC->ownPage = array( $pageE, $pageF );
104                 $pageD->ownPage = array( $pageG );
105                 $pageF->ownPage = array( $pageH );
106                 R::store( $pageA );
107                 $parents = array();
108                 $pageF->traverse( 'page', function( $page ) use ( &$parents ) {
109                         $parents[] = $page->title;
110                 } );
111                 asrt( implode( ',', $parents ), 'c,a' );
112                 $parents = array();
113                 $pageH->traverse( 'page', function( $page ) use ( &$parents ) {
114                         $parents[] = $page->title;
115                 } );
116                 asrt( implode( ',', $parents ), 'f,c,a' );
117                 $parents = array();
118                 $pageG->traverse( 'page', function( $page ) use ( &$parents ) {
119                         $parents[] = $page->title;
120                 } );
121                 asrt( implode( ',', $parents ), 'd,b,a' );
122                 $path = array();
123                 $pageA->traverse( 'ownPageList', function( $page ) use ( &$path ) {
124                         $path[] = $page->title;
125                 } );
126                 asrt( implode( ',', $path ), 'b,d,g,c,e,f,h' );
127                 $path = array();
128                 $pageC->traverse( 'ownPageList', function( $page ) use ( &$path ) {
129                         $path[] = $page->title;
130                 } );
131                 asrt( implode( ',', $path ), 'e,f,h' );
132                 $path = array();
133                 $pageA->traverse( 'ownPageList', function( $page ) use ( &$path ) {
134                         $path[] = $page->title;
135                 }, 2 );
136                 asrt( implode( ',', $path ), 'b,d,c,e,f' );
137         }
138
139         /**
140          * Test traversal with embedded SQL snippets.
141          *
142          * @return void
143          */
144         public function testTraversalWithSQL()
145         {
146                 $tasks = R::dispense('task', 10);
147                 foreach( $tasks as $key => $task ) {
148                         $task->descr = 't'.$key;
149                 }
150                 $tasks[0]->ownTask = array( $tasks[1], $tasks[9], $tasks[7] );
151                 $tasks[1]->ownTask = array( $tasks[5] );
152                 $tasks[9]->ownTask = array( $tasks[3], $tasks[8] );
153                 $tasks[2]->ownTask = array( $tasks[4] );
154                 $tasks[7]->ownTask = array( $tasks[6] );
155                 R::storeAll( $tasks );
156                 $task = R::load('task', $tasks[0]->id);
157                 $todo = array();
158                 $task->with(' ORDER BY descr ASC ')->traverse('ownTaskList', function( $t ) use ( &$todo ) {
159                         $todo[] = $t->descr;
160                 } );
161                 asrt( implode( ',', $todo ), 't1,t5,t7,t6,t9,t3,t8' );
162                 $task = R::load( 'task', $tasks[0]->id );
163                 $todo = array();
164                 $task->withCondition( ' ( descr = ? OR descr = ? ) ', array( 't7','t6' ) )
165                         ->traverse( 'ownTaskList', function( $task ) use( &$todo ){
166                                 $todo[] = $task->descr;
167                         } );
168                 asrt( implode( ',', $todo ), 't7,t6' );
169         }
170
171         /**
172          * Test traversal with aliases.
173          *
174          * @return void
175          */
176         public function testTraversalWithAlias()
177         {
178                 R::nuke();
179                 $book = R::dispense( 'book' );
180                 $cats = R::dispense( 'category', 3 );
181                 $cats[0]->gname = 'SF';
182                 $cats[1]->gname = 'Fantasy';
183                 $cats[2]->gname = 'Horror';
184                 $book->genre = $cats[0];
185                 $book->name = 'Space Story';
186                 $cats[0]->genre = $cats[1];
187                 $cats[2]->genre = $cats[1];
188                 R::store( $book );
189                 $book2 = R::dispense( 'book' );
190                 $book2->genre = $cats[2];
191                 $book2->name = 'Ghost Story';
192                 R::store( $book2 );
193                 $fantasy = R::load( 'category', $cats[1]->id );
194                 $cats = array();
195                 $book = $book->fresh();
196                 $book->fetchAs( 'category' )->traverse( 'genre', function( $cat ) use ( &$cats ) {
197                         $cats[] = $cat->gname;
198                 } );
199                 asrt( implode( ',', $cats ), 'SF,Fantasy' );
200                 $catList = array();
201                 $fantasy->alias( 'genre' )
202                         ->with( ' ORDER BY gname ASC ' )
203                         ->traverse( 'ownCategory', function( $cat ) use ( &$catList ) {
204                         $catList[] = $cat->gname;
205                 } );
206                 asrt( implode( ',', $catList ), 'Horror,SF' );
207         }
208
209         /**
210          * Traverse can only work with own-lists, otherwise infinite loops.
211          *
212          * @return void
213          */
214         public function testSharedTraversal()
215         {
216                 $friend = R::dispense( 'friend' );
217                 try {
218                         $friend->traverse( 'sharedFriend', function( $friend ){ } );
219                         fail();
220                 } catch( RedException $e ) {
221                         pass();
222                 }
223         }
224 }