/** * Test Joins. * * @return void */ public function testJoins() { R::nuke(); list($a1, $a2, $a3) = R::dispense('area', 3); list($p1, $p2) = R::dispense('person', 2); list($v1, $v2, $v3, $v4) = R::dispense('visit', 4); $a1->name = 'Belgium'; $a2->name = 'Arabia'; $a3->name = 'France'; $v1->person = $p1; $v2->person = $p1; $v3->person = $p2; $v4->person = $p2; $v1->area = $a3; $v2->area = $a2; $v3->area = $a2; $v4->area = $a1; $v1->label = 'v1 to France'; $v2->label = 'v2 to Arabia'; $v3->label = 'v3 to Arabia'; $v4->label = 'v4 to Belgium'; R::storeAll(array($v1, $v2, $v3, $v4)); $visits = $p1->ownVisit; asrt(is_array($visits), TRUE); asrt(count($visits), 2); $names = array(); foreach ($visits as $visit) { asrt(isset($visit->label), TRUE); asrt(isset($visit->name), FALSE); asrt(isset($visit->visit_id), FALSE); $names[] = $visit->label; } $labelList = implode(',', $names); asrt($labelList, 'v1 to France,v2 to Arabia'); $visits = $p1->with('ORDER BY @joined.area.name ASC')->ownVisit; asrt(is_array($visits), TRUE); asrt(count($visits), 2); $names = array(); foreach ($visits as $visit) { asrt(isset($visit->label), TRUE); asrt(isset($visit->name), FALSE); asrt(isset($visit->visit_id), FALSE); $names[] = $visit->label; } $labelList = implode(',', $names); asrt($labelList, 'v2 to Arabia,v1 to France'); }
/** * Test traversal with embedded SQL snippets. * * @return void */ public function testTraversalWithSQL() { $tasks = R::dispense('task', 10); foreach ($tasks as $key => $task) { $task->descr = 't' . $key; } $tasks[0]->ownTask = array($tasks[1], $tasks[9], $tasks[7]); $tasks[1]->ownTask = array($tasks[5]); $tasks[9]->ownTask = array($tasks[3], $tasks[8]); $tasks[2]->ownTask = array($tasks[4]); $tasks[7]->ownTask = array($tasks[6]); R::storeAll($tasks); $task = R::load('task', $tasks[0]->id); $todo = array(); $task->with(' ORDER BY descr ASC ')->traverse('ownTaskList', function ($t) use(&$todo) { $todo[] = $t->descr; }); asrt(implode(',', $todo), 't1,t5,t7,t6,t9,t3,t8'); $task = R::load('task', $tasks[0]->id); $todo = array(); $task->withCondition(' ( descr = ? OR descr = ? ) ', array('t7', 't6'))->traverse('ownTaskList', function ($task) use(&$todo) { $todo[] = $task->descr; }); asrt(implode(',', $todo), 't7,t6'); }
/** * Test Via and Link together. * * @return void */ public function testViaAndLink() { R::nuke(); list($John, $Anna, $Celine) = R::dispense('employee', 3); $John->badge = 'John'; $Anna->badge = 'Anna'; $Celine->badge = 'Celine'; $project = R::dispense('project'); $project->name = 'x'; $project2 = R::dispense('project'); $project2->name = 'y'; $John->link('participant', array('arole' => 'designer'))->project = $project; $Anna->link('participant', array('arole' => 'developer'))->project = $project; $Celine->link('participant', array('arole' => 'sales'))->project = $project2; $Anna->link('participant', array('arole' => 'lead'))->project = $project2; R::storeAll(array($project, $project2, $John, $Anna, $Celine)); $employees = $project->with(' ORDER BY badge ASC ')->via('participant')->sharedEmployee; asrt(is_array($employees), TRUE); asrt(count($employees), 2); $badges = array(); foreach ($employees as $employee) { $badges[] = $employee->badge; } asrt(implode(',', $badges), 'Anna,John'); $employees = $project2->with(' ORDER BY badge ASC ')->via('participant')->sharedEmployee; asrt(is_array($employees), TRUE); asrt(count($employees), 2); $badges = array(); foreach ($employees as $employee) { $badges[] = $employee->badge; } asrt(implode(',', $badges), 'Anna,Celine'); $projects = $John->sharedProject; asrt(is_array($projects), TRUE); asrt(count($projects), 1); $projectList = array(); foreach ($projects as $project) { $projectList[] = $project->name; } sort($projectList); asrt(implode(',', $projectList), 'x'); $projects = $Anna->sharedProject; asrt(is_array($projects), TRUE); asrt(count($projects), 2); $projectList = array(); foreach ($projects as $project) { $projectList[] = $project->name; } sort($projectList); asrt(implode(',', $projectList), 'x,y'); $projects = $Anna->via('participant')->sharedProject; asrt(is_array($projects), TRUE); asrt(count($projects), 2); $projectList = array(); foreach ($projects as $project) { $projectList[] = $project->name; } sort($projectList); asrt(implode(',', $projectList), 'x,y'); $projects = $Celine->via('participant')->sharedProject; asrt(is_array($projects), TRUE); asrt(count($projects), 1); $projectList = array(); foreach ($projects as $project) { $projectList[] = $project->name; } sort($projectList); asrt(implode(',', $projectList), 'y'); $roles = $Anna->ownParticipant; asrt(is_array($roles), TRUE); asrt(count($roles), 2); $roleList = array(); foreach ($roles as $role) { $roleList[] = $role->arole; } sort($roleList); asrt(implode(',', $roleList), 'developer,lead'); $project2->sharedEmployee[] = $John; R::store($project2); $projects = $John->sharedProject; asrt(is_array($projects), TRUE); asrt(count($projects), 2); $projectList = array(); foreach ($projects as $project) { $projectList[] = $project->name; } sort($projectList); asrt(implode(',', $projectList), 'x,y'); $projects = $John->via('participant')->sharedProject; asrt(is_array($projects), TRUE); asrt(count($projects), 2); $projectList = array(); foreach ($projects as $project) { $projectList[] = $project->name; } sort($projectList); asrt(implode(',', $projectList), 'x,y'); }
/** * Test self-referential N-M relations. */ public function testSelfRefNM() { R::nuke(); $friend1 = R::xdispense(FRIEND); $friend1->name = 'f1'; $friend2 = R::xdispense(FRIEND); $friend2->name = 'f2'; $friend3 = R::xdispense(FRIEND); $friend3->name = 'f3'; $friend1->{FRIENDLIST} = array($friend2, $friend3); $friend3->{FRIENDLIST} = array($friend1); R::storeAll(array($friend1, $friend2, $friend3)); $friend1 = $friend1->fresh(); $friend2 = $friend2->fresh(); $friend3 = $friend3->fresh(); asrt(count($friend1->{FRIENDLIST}), 2); asrt(count($friend2->{FRIENDLIST}), 1); asrt(count($friend3->{FRIENDLIST}), 1); $friend = reset($friend3->{FRIENDLIST}); asrt($friend->name, 'f1'); }
/** * Test trashAll(). */ public function testMultiDeleteUpdate() { testpack('test multi delete and multi update'); $beans = R::dispenseLabels('bean', array('a', 'b')); $ids = R::storeAll($beans); asrt((int) R::count('bean'), 2); R::trashAll(R::batch('bean', $ids)); asrt((int) R::count('bean'), 0); testpack('test assocManager check'); $rb = new OODB(R::getWriter()); try { $rb->getAssociationManager(); fail(); } catch (RedException $e) { pass(); } }
/** * Switching aliases (->alias) should not change other list during * storage. * * @return void */ public function testShadow() { list($project1, $project2) = R::dispense('project', 2); list($irene, $ilse) = R::dispense('person', 2); $project1->developer = $ilse; $project1->designer = $irene; $project2->developer = $ilse; R::storeAll(array($project1, $project2)); $ilse = R::load('person', $ilse->id); $irene = R::load('person', $irene->id); asrt(count($ilse->alias('developer')->ownProject), 2); asrt(count($ilse->alias('designer')->ownProject), 0); R::store($ilse); $ilse = R::load('person', $ilse->id); $irene = R::load('person', $irene->id); asrt(count($ilse->alias('designer')->ownProject), 0); asrt(count($ilse->alias('developer')->ownProject), 2); R::storeAll(array($ilse, $irene)); $ilse = R::load('person', $ilse->id); $irene = R::load('person', $irene->id); asrt(count($ilse->alias('designer')->ownProject), 0); asrt(count($ilse->alias('developer')->ownProject), 2); asrt(count($irene->alias('designer')->ownProject), 1); asrt(count($irene->alias('developer')->ownProject), 0); R::storeAll(array($ilse, $irene)); $ilse = R::load('person', $ilse->id); $irene = R::load('person', $irene->id); asrt(count($ilse->alias('designer')->ownProject), 0); asrt(count($ilse->alias('developer')->ownProject), 2); asrt(count($irene->alias('designer')->ownProject), 1); asrt(count($irene->alias('developer')->ownProject), 0); }
/** * Shared lists can only be formed using types. * If you happen to have two beans of the same type you can still * have a shared list but not with a sense of direction. * I.e. quest->sharedQuest returns all the quests that follow the first one, * but also the ones that are followed by the first one. * If you want to have some sort of direction; i.e. one quest follows another one * you'll have to use an alias: quest->target, but now you can't use the shared list * anymore because it will start looking for a type named 'target' (which is just an alias) * for quest, but it cant find that table and it's not possible to 'keep remembering' * the alias throughout the system. * * The aggr() method solves this inconvenience. * Aggr iterates through the list identified by its first argument ('target' -> ownQuestTargetList) * and fetches every ID of the target (quest_target.target_id), loads these beans in batch for * optimal performance, puts them back in the beans (questTarget->target) and returns the * references. * * @return void */ public function testAggregationInSelfRefNM() { R::nuke(); $quest1 = R::dispense('quest'); $quest1->name = 'Quest 1'; $quest2 = R::dispense('quest'); $quest2->name = 'Quest 2'; $quest3 = R::dispense('quest'); $quest3->name = 'Quest 3'; $quest4 = R::dispense('quest'); $quest4->name = 'Quest 4'; $quest1->link('questTarget')->target = $quest2; $quest1->link('questTarget')->target = $quest3; $quest3->link('questTarget')->target = $quest4; $quest3->link('questTarget')->target = $quest1; R::storeAll(array($quest1, $quest3)); //There should be 4 links asrt((int) R::count('questTarget'), 4); $quest1 = $quest1->fresh(); $targets = $quest1->aggr('ownQuestTargetList', 'target', 'quest'); //can we aggregate the targets over the link type? asrt(count($targets), 2); //are the all valid beans? foreach ($targets as $target) { //are they beans? asrt($target instanceof OODBBean, TRUE); //are they fetched as quest? asrt($target->getMeta('type'), 'quest'); } //list target should already have been loaded, nuke has no effect R::nuke(); $links = $quest1->ownQuestTargetList; //are the links still there, have they been set in the beans as well? asrt(count($links), 2); //are they references instead of copies, changes in the aggregation set should affect the beans in links! foreach ($targets as $target) { $target->name .= 'b'; asrt(substr($target->name, -1), 'b'); } //do the names end with a 'b' here as well ? i.e. have they been changed through references? foreach ($links as $link) { asrt(substr($target->name, -1), 'b'); } //now test the effect on existing shadow... R::nuke(); $quest1 = R::dispense('quest'); $quest1->name = 'Quest 1'; $quest2 = R::dispense('quest'); $quest2->name = 'Quest 2'; $quest3 = R::dispense('quest'); $quest3->name = 'Quest 3'; $quest4 = R::dispense('quest'); $quest4->name = 'Quest 4'; $quest1->link('questTarget')->target = $quest2; $quest1->link('questTarget')->target = $quest3; R::store($quest1); asrt((int) R::count('questTarget'), 2); //now lets first build a shadow $quest1->link('questTarget')->target = $quest4; //$quest1 = $quest1->fresh(); $targets = $quest1->aggr('ownQuestTargetList', 'target', 'quest'); //targets should not include the new bean... asrt(count($targets), 2); //this should not overwrite the existing beans R::store($quest1); asrt((int) R::count('questTarget'), 3); }
/** * Test batch alias loadAll. * * @return void */ public function testBatchAliasLoadAll() { $ids = R::storeAll(R::dispense('page', 2)); $pages = R::loadAll('page', $ids); asrt(is_array($pages), true); asrt(count($pages), 2); asrt($pages[$ids[0]] instanceof OODBBean, true); }
/** * More variations... * * @return void */ public function testEmbeddedSQLPart2() { list($book1, $book2, $book3) = R::dispense('book', 3); $book1->position = 1; $book2->position = 2; $book3->position = 3; $shelf = R::dispense('shelf'); $shelf->ownBook = array($book1, $book2, $book3); $id = R::store($shelf); $shelf = R::load('shelf', $id); $books = $shelf->with(' ORDER BY position ASC ')->ownBook; $book1 = array_shift($books); asrt((int) $book1->position, 1); $book2 = array_shift($books); asrt((int) $book2->position, 2); $book3 = array_shift($books); asrt((int) $book3->position, 3); $books = $shelf->with(' ORDER BY position DESC ')->ownBook; $book1 = array_shift($books); asrt((int) $book1->position, 3); $book2 = array_shift($books); asrt((int) $book2->position, 2); $book3 = array_shift($books); asrt((int) $book3->position, 1); //R::debug(1); $shelf = R::load('shelf', $id); $books = $shelf->with(' AND position > 2 ')->ownBook; asrt(count($books), 1); $shelf = R::load('shelf', $id); $books = $shelf->with(' AND position < ? ', array(3))->ownBook; asrt(count($books), 2); $shelf = R::load('shelf', $id); $books = $shelf->with(' AND position = 1 ')->ownBook; asrt(count($books), 1); $shelf = R::load('shelf', $id); $books = $shelf->withCondition(' position > -1 ')->ownBook; asrt(count($books), 3); // With-condition should not affect storing $shelf = R::load('shelf', $id); $books = $shelf->with(' AND position = 1 ')->ownBook; asrt(count($books), 1); asrt(count($shelf->ownBook), 1); $book = reset($shelf->ownBook); $book->title = 'Trees and other Poems'; R::store($shelf); $books = $shelf->withCondition(' position > -1 ')->ownBook; asrt(count($books), 3); asrt(count($shelf->ownBook), 3); $shelf = R::load('shelf', $id); $books = $shelf->with(' AND position = 1 ')->ownBook; // Also with trashing -- just trash one! $shelf->ownBook = array(); R::store($shelf); $books = $shelf->withCondition(' position > -1 ')->ownBook; asrt(count($books), 2); // With should cause a reload of a list $shelf = R::load('shelf', $id); $books = $shelf->with(' AND position = 2 ')->ownBook; asrt(count($books), 1); $books = $shelf->withCondition(' position > -1 ')->ownBook; asrt(count($books), 2); $book = reset($books); $book->title = 'Venetian Music'; // Should not affect storage (fact that we used with twice, unsetting prop) R::store($shelf); $shelf = R::load('shelf', $id); asrt(count($shelf->ownBook), 2); // Alias list($game1, $game2, $game3) = R::dispense('game', 3); list($t1, $t2, $t3) = R::dispense('team', 3); $t1->name = 'Bats'; $t2->name = 'Tigers'; $t3->name = 'Eagles'; $game1->name = 'a'; $game1->team1 = $t1; $game1->team2 = $t2; $game2->name = 'b'; $game2->team1 = $t1; $game2->team2 = $t3; $game3->name = 'c'; $game3->team1 = $t2; $game3->team2 = $t3; R::storeAll(array($game1, $game2, $game3)); $team1 = R::load('team', $t1->id); $team2 = R::load('team', $t2->id); $team3 = R::load('team', $t3->id); asrt(count($team1->alias('team1')->ownGame), 2); asrt(count($team2->alias('team1')->ownGame), 1); $team1 = R::load('team', $t1->id); $team2 = R::load('team', $t2->id); asrt(count($team1->alias('team2')->ownGame), 0); asrt(count($team2->alias('team2')->ownGame), 1); asrt(count($team3->alias('team1')->ownGame), 0); $team3 = R::load('team', $t3->id); asrt(count($team3->alias('team2')->ownGame), 2); $team1 = R::load('team', $t1->id); $games = $team1->alias('team1')->ownGame; $game4 = R::dispense('game'); $game4->name = 'd'; $game4->team2 = $t3; $team1->alias('team1')->ownGame[] = $game4; R::store($team1); $team1 = R::load('team', $t1->id); asrt(count($team1->alias('team1')->ownGame), 3); foreach ($team1->ownGame as $g) { if ($g->name == 'a') { $game = $g; } } $game->name = 'match'; R::store($team1); $team1 = R::load('team', $t1->id); asrt(count($team1->alias('team1')->ownGame), 3); $found = 0; foreach ($team1->ownGame as $g) { if ($g->name == 'match') { $found = 1; } } if ($found) { pass(); } $team1->ownGame = array(); R::store($team1); $team1 = R::load('team', $t1->id); asrt(count($team1->alias('team1')->ownGame), 0); $team1->ownBook[] = $book1; R::store($team1); $team1 = R::load('team', $t1->id); asrt(count($team1->alias('team1')->ownGame), 0); asrt(count($team1->ownBook), 1); }
/** * Test find and export. * * @return void */ public function testFindAndExport() { R::nuke(); $pages = R::dispense('page', 3); $i = 1; foreach ($pages as $page) { $page->pageNumber = $i++; } R::storeAll($pages); $pages = R::findAndExport('page'); asrt(is_array($pages), TRUE); asrt(isset($pages[0]), TRUE); asrt(is_array($pages[0]), TRUE); asrt(count($pages), 3); }
/** * test emulation via association renaming * * @return void */ public function testAssociationRenaming() { list($p1, $p2, $p3) = R::dispense('painting', 3); list($m1, $m2, $m3) = R::dispense('museum', 3); $p1->name = 'painting1'; $p2->name = 'painting2'; $p3->name = 'painting3'; $m1->thename = 'a'; $m2->thename = 'b'; $m3->thename = 'c'; R::renameAssociation('museum_painting', 'exhibited'); // Also test array syntax R::renameAssociation(array('museum_museum' => 'center')); $m1->link('center', array('name' => 'History Center'))->museum2 = $m2; $m1->link('exhibited', '{"from":"2014-02-01","til":"2014-07-02"}')->painting = $p3; $m2->link('exhibited', '{"from":"2014-07-03","til":"2014-10-02"}')->painting = $p3; $m3->link('exhibited', '{"from":"2014-02-01","til":"2014-07-02"}')->painting = $p1; $m2->link('exhibited', '{"from":"2014-02-01","til":"2014-07-02"}')->painting = $p2; R::storeAll(array($m1, $m2, $m3)); list($m1, $m2, $m3) = array_values(R::findAll('museum', ' ORDER BY thename ASC')); asrt(count($m1->sharedMuseum), 1); asrt(count($m1->sharedPainting), 1); asrt(count($m2->sharedPainting), 2); asrt(count($m3->sharedPainting), 1); $p3 = reset($m1->sharedPainting); asrt(count($p3->ownExhibited), 2); asrt(count($m2->ownExhibited), 2); R::storeAll(array($m1, $m2, $m3)); list($m1, $m2, $m3) = array_values(R::findAll('museum', ' ORDER BY thename ASC')); asrt(count($m1->sharedPainting), 1); asrt(count($m2->sharedPainting), 2); asrt(count($m3->sharedPainting), 1); $p3 = reset($m1->sharedPainting); asrt(count($p3->ownExhibited), 2); $paintings = $m2->sharedPainting; foreach ($paintings as $painting) { if ($painting->name === 'painting2') { pass(); $paintingX = $painting; } } unset($m2->sharedPainting[$paintingX->id]); R::store($m2); $m2 = R::load('museum', $m2->id); asrt(count($m2->sharedPainting), 1); $left = reset($m2->sharedPainting); asrt($left->name, 'painting3'); asrt(count($m2->ownExhibited), 1); $exhibition = reset($m2->ownExhibited); asrt($exhibition->from, '2014-07-03'); asrt($exhibition->til, '2014-10-02'); }
/** * Test limited support for 1-to-1 associations. * * @return void */ public function testOneToOne() { testpack('Testing one-to-ones'); $author = R::dispense('author')->setAttr('name', 'a'); $bio = R::dispense('bio')->setAttr('name', 'a'); R::storeAll(array($author, $bio)); $id1 = $author->id; $author = R::dispense('author')->setAttr('name', 'b'); $bio = R::dispense('bio')->setAttr('name', 'b'); R::storeAll(array($author, $bio)); $x = $author->one('bio'); $y = $bio->one('author'); asrt($x->name, $bio->name); asrt($y->name, $author->name); asrt($x->id, $bio->id); asrt($y->id, $author->id); $id2 = $author->id; list($a, $b) = R::loadMulti('author,bio', $id1); asrt($a->name, $b->name); asrt($a->name, 'a'); list($a, $b) = R::loadMulti('author,bio', $id2); asrt($a->name, $b->name); asrt($a->name, 'b'); list($a, $b) = R::loadMulti(array('author', 'bio'), $id1); asrt($a->name, $b->name); asrt($a->name, 'a'); list($a, $b) = R::loadMulti(array('author', 'bio'), $id2); asrt($a->name, $b->name); asrt($a->name, 'b'); asrt(is_array(R::loadMulti(NULL, 1)), TRUE); asrt(count(R::loadMulti(NULL, 1)) === 0, TRUE); }