mirror of
https://gitlab.com/hashborgir/d2tools.git
synced 2025-11-29 13:11:34 -06:00
Begin Refactor
This commit is contained in:
387
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Aliasing.php
vendored
Normal file
387
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Aliasing.php
vendored
Normal file
@@ -0,0 +1,387 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\RedException as RedException;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
|
||||
/**
|
||||
* Aliasing
|
||||
*
|
||||
* Tests aliasing functionality, i.e. fetching beans as,
|
||||
* inferring correct type and retrieving lists as alias.
|
||||
*
|
||||
* @file RedUNIT/Base/Aliasing.php
|
||||
* @desc Tests for nested beans with aliases, i.e. teacher alias for person etc.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Aliasing extends Base
|
||||
{
|
||||
/**
|
||||
* Test for aliasing issue for LTS version.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIssueAliasingForLTSVersion() {
|
||||
$person = R::dispense('person');
|
||||
$pro = R::dispense('project');
|
||||
$c = R::dispense('course');
|
||||
$person->name = 'x';
|
||||
$person->alias('teacher')->ownProject[] = $pro;
|
||||
$person->alias('student')->ownCourse[] = $c;
|
||||
R::store($person);
|
||||
asrt($c->fresh()->fetchAs('person')->student->name, 'x');
|
||||
asrt($pro->fresh()->fetchAs('person')->teacher->name, 'x');
|
||||
$person = $person->fresh();
|
||||
$person->alias('teacher')->ownProject = array();
|
||||
$person->alias('student')->ownCourse = array();
|
||||
R::store($person);
|
||||
asrt($c->fresh()->fetchAs('person')->student, NULL);
|
||||
asrt($pro->fresh()->fetchAs('person')->teacher, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Describing how clearing state of bean works.
|
||||
* Every method returning somthing (except getID)
|
||||
* clears prefix-method-state (anything set by withCond,with,alias,fetchAs).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clearStateAdditionalTests()
|
||||
{
|
||||
list( $project1, $project2 ) = R::dispense( 'project', 2 );
|
||||
list( $irene, $ilse ) = R::dispense('person', 2);
|
||||
$project1->developer = $ilse;
|
||||
$project1->designer = $irene;
|
||||
$ilse->name = 'Ilse';
|
||||
$irene->name = 'Irene';
|
||||
$project2->developer = $ilse;
|
||||
R::storeAll( array( $project1, $project2 ) );
|
||||
$ilse = R::load( 'person', $ilse->id );
|
||||
asrt( count( $ilse->alias( 'developer' )->ownProject ), 2);
|
||||
//cached - same list
|
||||
asrt( count( $ilse->ownProject ), 2);
|
||||
asrt( count( $ilse->alias( 'designer' )->ownProject ), 0);
|
||||
//cached - same list
|
||||
asrt( count( $ilse->ownProject ), 0);
|
||||
//now test state
|
||||
asrt( count( $ilse->setAttr( 'a', 'b' )->alias( 'developer' )->ownProject ), 2);
|
||||
//now test state
|
||||
$ilse = $ilse->fresh();
|
||||
//attr clears state...
|
||||
asrt( count( $ilse->alias( 'developer' )->setAttr( 'a', 'b' )->ownProject ), 0);
|
||||
//but getID() does not!
|
||||
$ilse = $ilse->fresh();
|
||||
$ilse->alias('developer');
|
||||
$ilse->getID();
|
||||
asrt( count( $ilse->ownProject ), 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Can switch fetchAs().
|
||||
* Also checks shadow by storing.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function canSwitchParentBean()
|
||||
{
|
||||
list( $project1, $project2 ) = R::dispense( 'project', 2 );
|
||||
list( $irene, $ilse ) = R::dispense('person', 2);
|
||||
$project1->developer = $ilse;
|
||||
$project1->designer = $irene;
|
||||
$ilse->name = 'Ilse';
|
||||
$irene->name = 'Irene';
|
||||
$project2->developer = $ilse;
|
||||
R::storeAll( array( $project1, $project2 ) );
|
||||
$project1 = R::load( 'project', $project1->id );
|
||||
asrt( $project1->fetchAs('person')->developer->name, 'Ilse' );
|
||||
asrt( $project1->fetchAs('person')->designer->name, 'Irene' );
|
||||
R::store( $project1 );
|
||||
$project1 = R::load( 'project', $project1->id );
|
||||
asrt( $project1->fetchAs('person')->designer->name, 'Irene' );
|
||||
asrt( $project1->fetchAs('person')->developer->name, 'Ilse' );
|
||||
R::store( $project1 );
|
||||
asrt( $project1->fetchAs('person')->developer->name, 'Ilse' );
|
||||
asrt( $project1->fetchAs('person')->designer->name, 'Irene' );
|
||||
asrt( $project1->fetchAs('person')->developer->name, 'Ilse' );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue 291. State not cleared.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testFetchTypeConfusionIssue291()
|
||||
{
|
||||
list( $teacher, $student ) = R::dispense( 'person', 2 ) ;
|
||||
$teacher->name = 'jimmy' ;
|
||||
$student->name = 'jacko' ;
|
||||
R::store( $teacher ) ;
|
||||
R::store( $student ) ;
|
||||
$client = R::dispense( 'client' ) ;
|
||||
$client->firm = 'bean AG' ;
|
||||
R::store( $client ) ;
|
||||
$project = R::dispense( 'project' ) ;
|
||||
$project->teacher = $teacher ;
|
||||
$project->student = $student ;
|
||||
$project->client = $client ;
|
||||
R::store( $project ) ;
|
||||
unset( $project->student ) ;
|
||||
R::store( $project ) ;
|
||||
$project = R::load( 'project', 1 ) ;
|
||||
$teacher = $project->fetchAs( 'person' )->teacher ;
|
||||
$student = $project->fetchAs( 'person' )->student ;
|
||||
$client = $project->client ; // this will select from "person" instead of "client"
|
||||
asrt( $client->firm, 'bean AG' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test switching alias (also issue #291).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAliasSwitch()
|
||||
{
|
||||
$student = R::dispense( 'person' );
|
||||
$project = R::dispense( 'project' );
|
||||
$project->student = $student;
|
||||
R::store( $project );
|
||||
$person = R::load( 'person', $student->id );
|
||||
asrt( count( $person->alias( 'student' )->ownProject ), 1);
|
||||
asrt( count( $person->alias( 'teacher' )->ownProject ), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Associating two beans, then loading the associated bean
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAssociated()
|
||||
{
|
||||
$person = R::dispense( 'person' );
|
||||
$person->name = 'John';
|
||||
R::store( $person );
|
||||
$course = R::dispense( 'course' );
|
||||
$course->name = 'Math';
|
||||
|
||||
R::store( $course );
|
||||
$course->teacher = $person;
|
||||
$id = R::store( $course );
|
||||
$course = R::load( 'course', $id );
|
||||
$teacher = $course->fetchAs( 'person' )->teacher;
|
||||
asrt( $teacher->name, 'John' );
|
||||
|
||||
//Trying to load a property that has an invalid name
|
||||
$book = R::dispense( 'book' );
|
||||
$page = R::dispense( 'page' );
|
||||
$book->wrongProperty = array( $page );
|
||||
try {
|
||||
$book->wrongProperty[] = $page;
|
||||
R::store( $book );
|
||||
fail();
|
||||
} catch ( RedException $e ) {
|
||||
pass();
|
||||
} catch ( \Exception $e ) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for quick detect change.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function basic()
|
||||
{
|
||||
$book = R::dispense( 'book' );
|
||||
|
||||
asrt( isset( $book->prop ), FALSE ); //not a very good test
|
||||
asrt( in_array( 'prop', array_keys( $book->export() ) ), FALSE ); //better...
|
||||
|
||||
$book = R::dispense( 'book' );
|
||||
$page = R::dispense( 'page' );
|
||||
|
||||
$book->paper = $page;
|
||||
|
||||
$id = R::store( $book );
|
||||
$book = R::load( 'book', $id );
|
||||
|
||||
asrt( FALSE, ( isset( $book->paper ) ) );
|
||||
asrt( FALSE, ( isset( $book->page ) ) );
|
||||
|
||||
/**
|
||||
* The following tests try to store various things that aren't
|
||||
* beans (which is expected) with the own* and shared* properties
|
||||
* which only accept beans as assignments, so they're expected to fail
|
||||
*/
|
||||
foreach ( array( 'a string', 1928, TRUE, NULL, array()) as $value ) {
|
||||
try {
|
||||
$book->ownPage[] = $value;
|
||||
R::store( $book );
|
||||
$book->sharedPage[] = $value;
|
||||
R::store( $book );
|
||||
fail();
|
||||
} catch ( RedException $e ) {
|
||||
pass();
|
||||
} catch ( \Exception $e ) {
|
||||
if (strpos($e->getMessage(),'Array to string conversion')===FALSE) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finding $person beans that have been aliased into various roles
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAliasedFinder()
|
||||
{
|
||||
$message = R::dispense( 'message' );
|
||||
$message->subject = 'Roommate agreement';
|
||||
list( $sender, $recipient ) = R::dispense( 'person', 2 );
|
||||
$sender->name = 'Sheldon';
|
||||
$recipient->name = 'Leonard';
|
||||
$message->sender = $sender;
|
||||
$message->recipient = $recipient;
|
||||
$id = R::store( $message );
|
||||
$message = R::load( 'message', $id );
|
||||
asrt( $message->fetchAs( 'person' )->sender->name, 'Sheldon' );
|
||||
asrt( $message->fetchAs( 'person' )->recipient->name, 'Leonard' );
|
||||
$otherRecipient = R::dispense( 'person' );
|
||||
$otherRecipient->name = 'Penny';
|
||||
$message->recipient = $otherRecipient;
|
||||
R::store( $message );
|
||||
$message = R::load( 'message', $id );
|
||||
asrt( $message->fetchAs( 'person' )->sender->name, 'Sheldon' );
|
||||
asrt( $message->fetchAs( 'person' )->recipient->name, 'Penny' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Basic Fetch AS functionality.
|
||||
*/
|
||||
public function testBasicFetchAs()
|
||||
{
|
||||
$project = R::dispense( 'project' );
|
||||
$project->name = 'Mutant Project';
|
||||
list( $teacher, $student ) = R::dispense( 'person', 2 );
|
||||
$teacher->name = 'Charles Xavier';
|
||||
$project->student = $student;
|
||||
$project->student->name = 'Wolverine';
|
||||
$project->teacher = $teacher;
|
||||
$id = R::store( $project );
|
||||
$project = R::load( 'project', $id );
|
||||
asrt( $project->fetchAs( 'person' )->teacher->name, 'Charles Xavier' );
|
||||
asrt( $project->fetchAs( 'person' )->student->name, 'Wolverine' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Basic list variations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBasicListVariations()
|
||||
{
|
||||
$farm = R::dispense( 'building' );
|
||||
$village = R::dispense( 'village' );
|
||||
$farm->name = 'farm';
|
||||
$village->name = 'Dusty Mountains';
|
||||
$farm->village = $village;
|
||||
$id = R::store( $farm );
|
||||
$farm = R::load( 'building', $id );
|
||||
asrt( $farm->name, 'farm' );
|
||||
asrt( $farm->village->name, 'Dusty Mountains' );
|
||||
$village = R::dispense( 'village' );
|
||||
list( $mill, $tavern ) = R::dispense( 'building', 2 );
|
||||
$mill->name = 'Mill';
|
||||
$tavern->name = 'Tavern';
|
||||
$village->ownBuilding = array( $mill, $tavern );
|
||||
$id = R::store( $village );
|
||||
$village = R::load( 'village', $id );
|
||||
asrt( count( $village->ownBuilding ), 2 );
|
||||
$village2 = R::dispense( 'village' );
|
||||
$army = R::dispense( 'army' );
|
||||
$village->sharedArmy[] = $army;
|
||||
$village2->sharedArmy[] = $army;
|
||||
$id1 = R::store( $village );
|
||||
$id2 = R::store( $village2 );
|
||||
$village1 = R::load( 'village', $id1 );
|
||||
$village2 = R::load( 'village', $id2 );
|
||||
asrt( count( $village1->sharedArmy ), 1 );
|
||||
asrt( count( $village2->sharedArmy ), 1 );
|
||||
asrt( count( $village1->ownArmy ), 0 );
|
||||
asrt( count( $village2->ownArmy ), 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether aliasing plays nice with beautification.
|
||||
* Ensure that aliased column aren't beautified
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAliasWithBeautify()
|
||||
{
|
||||
$points = R::dispense( 'point', 2 );
|
||||
$line = R::dispense( 'line' );
|
||||
$line->pointA = $points[0];
|
||||
$line->pointB = $points[1];
|
||||
R::store( $line );
|
||||
$line2 = R::dispense( 'line' );
|
||||
$line2->pointA = $line->fetchAs('point')->pointA;
|
||||
$line2->pointB = R::dispense( 'point' );
|
||||
R::store( $line2 );
|
||||
|
||||
//now we have two points per line (1-to-x)
|
||||
//I want to know which lines cross A:
|
||||
$a = R::load( 'point', $line->pointA->id ); //reload A
|
||||
$lines = $a->alias( 'pointA' )->ownLine;
|
||||
asrt( count( $lines ), 2 );
|
||||
}
|
||||
}
|
||||
273
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Arrays.php
vendored
Normal file
273
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Arrays.php
vendored
Normal file
@@ -0,0 +1,273 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
|
||||
/**
|
||||
* Arrays
|
||||
*
|
||||
* Beans can also be treated like arrays, this test verifies
|
||||
* whether the bean array interface works correctly in various
|
||||
* scenarios (combination with lists and so on).
|
||||
*
|
||||
* @file RedUNIT/Base/Arrays.php
|
||||
* @desc Tests the array interface of beans
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Arrays extends Base
|
||||
{
|
||||
/**
|
||||
* Tests basic array access.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testArrayAccess()
|
||||
{
|
||||
$bean = R::dispense('bean');
|
||||
$bean->name = 'bean';
|
||||
$bean->taste = 'salty';
|
||||
$properties = array();
|
||||
foreach($bean as $key => $value) {
|
||||
$properties[ $key ] = $value;
|
||||
}
|
||||
asrt( count( $bean ), 3 );
|
||||
asrt( count( $properties ), 3 );
|
||||
asrt( isset( $properties['id'] ), TRUE );
|
||||
asrt( isset( $properties['name'] ), TRUE );
|
||||
asrt( isset( $properties['taste'] ), TRUE );
|
||||
$bean = R::dispense('bean');
|
||||
$bean['name'] = 'bean';
|
||||
$bean['taste'] = 'salty';
|
||||
$properties = array();
|
||||
foreach($bean as $key => $value) {
|
||||
$properties[ $key ] = $value;
|
||||
}
|
||||
asrt( count( $bean ), 3 );
|
||||
asrt( count( $properties ), 3 );
|
||||
asrt( isset( $properties['id'] ), TRUE );
|
||||
asrt( isset( $properties['name'] ), TRUE );
|
||||
asrt( isset( $properties['taste'] ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests array access with lists.
|
||||
* Tests whether list properties behave as arrays correctly.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testArrayAccessAndLists()
|
||||
{
|
||||
$book = R::dispense('book');
|
||||
$book['title'] = 'My Book';
|
||||
//Can we add a bean in list with array access?
|
||||
$book['ownPage'][] = R::dispense('page');
|
||||
$book['ownPage'][] = R::dispense('page');
|
||||
asrt( count( $book ), 3 );
|
||||
$properties = array();
|
||||
foreach($book as $key => $value) {
|
||||
$properties[ $key ] = $value;
|
||||
}
|
||||
asrt( count( $properties ), 3 );
|
||||
//Dont reveal aliased x-own and -List in foreach-loop
|
||||
asrt( isset( $properties['id'] ), TRUE );
|
||||
asrt( isset( $properties['title'] ), TRUE );
|
||||
asrt( isset( $properties['ownPage'] ), TRUE );
|
||||
asrt( isset( $properties['ownPageList'] ), FALSE );
|
||||
asrt( isset( $properties['xownPage'] ), FALSE );
|
||||
asrt( isset( $properties['xownPageList'] ), FALSE );
|
||||
//But keep them countable
|
||||
asrt( count( $book['ownPage'] ), 2 );
|
||||
asrt( count( $book['ownPageList'] ), 2 );
|
||||
asrt( count( $book['xownPage'] ), 2 );
|
||||
asrt( count( $book['xownPageList'] ), 2 );
|
||||
//And reveal state of items with isset()
|
||||
asrt( isset( $book['id'] ), TRUE );
|
||||
asrt( isset( $book['title'] ), TRUE );
|
||||
asrt( isset( $book['ownPage'] ), TRUE );
|
||||
asrt( isset( $book['ownPageList'] ), TRUE );
|
||||
asrt( isset( $book['xownPage'] ), TRUE );
|
||||
asrt( isset( $book['xownPageList'] ), TRUE );
|
||||
//Can we add using the List alias?
|
||||
$book['ownPageList'][] = R::dispense('page');
|
||||
asrt( count( $book['ownPage'] ), 3 );
|
||||
asrt( count( $book['ownPageList'] ), 3 );
|
||||
asrt( count( $book['xownPage'] ), 3 );
|
||||
asrt( count( $book['xownPageList'] ), 3 );
|
||||
//Can we add using the x-mode alias?
|
||||
$book['ownPageList'][] = R::dispense('page');
|
||||
asrt( count( $book['ownPage'] ), 4 );
|
||||
asrt( count( $book['ownPageList'] ), 4 );
|
||||
asrt( count( $book['xownPage'] ), 4 );
|
||||
asrt( count( $book['xownPageList'] ), 4 );
|
||||
//Can we unset using array access?
|
||||
unset( $book['ownPage'] );
|
||||
asrt( isset( $book['ownPage'] ), FALSE );
|
||||
asrt( isset( $book['ownPageList'] ), FALSE );
|
||||
asrt( isset( $book['xownPage'] ), FALSE );
|
||||
asrt( isset( $book['xownPageList'] ), FALSE );
|
||||
$book['ownPage'] = array( R::dispense('page') );
|
||||
unset( $book['xownPage'] );
|
||||
asrt( isset( $book['ownPage'] ), FALSE );
|
||||
asrt( isset( $book['ownPageList'] ), FALSE );
|
||||
asrt( isset( $book['xownPage'] ), FALSE );
|
||||
asrt( isset( $book['xownPageList'] ), FALSE );
|
||||
$book['ownPage'] = array( R::dispense('page') );
|
||||
unset( $book['ownPageList'] );
|
||||
asrt( isset( $book['ownPage'] ), FALSE );
|
||||
asrt( isset( $book['ownPageList'] ), FALSE );
|
||||
asrt( isset( $book['xownPage'] ), FALSE );
|
||||
asrt( isset( $book['xownPageList'] ), FALSE );
|
||||
$book['ownPage'] = array( R::dispense('page') );
|
||||
unset( $book['xownPageList'] );
|
||||
asrt( isset( $book['ownPage'] ), FALSE );
|
||||
asrt( isset( $book['ownPageList'] ), FALSE );
|
||||
asrt( isset( $book['xownPage'] ), FALSE );
|
||||
asrt( isset( $book['xownPageList'] ), FALSE );
|
||||
//does it work with shared lists as well?
|
||||
$book['sharedCategory'] = array( R::dispense('category') );
|
||||
asrt( count( $book ), 3 );
|
||||
$properties = array();
|
||||
foreach($book as $key => $value) {
|
||||
$properties[ $key ] = $value;
|
||||
}
|
||||
asrt( isset( $properties['sharedCategory'] ), TRUE );
|
||||
asrt( isset( $properties['sharedCategoryList'] ), FALSE );
|
||||
asrt( isset( $book['sharedCategory'] ), TRUE );
|
||||
asrt( isset( $book['sharedCategoryList'] ), TRUE );
|
||||
asrt( count( $book['sharedCategory'] ), 1 );
|
||||
asrt( count( $book['sharedCategoryList'] ), 1 );
|
||||
$book['sharedCategory'][] = R::dispense( 'category' );
|
||||
asrt( count( $book['sharedCategory'] ), 2 );
|
||||
asrt( count( $book['sharedCategoryList'] ), 2 );
|
||||
$book['sharedCategoryList'][] = R::dispense( 'category' );
|
||||
asrt( count( $book['sharedCategory'] ), 3 );
|
||||
asrt( count( $book['sharedCategoryList'] ), 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests array access with parent beans.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testArrayAccessWithBeans()
|
||||
{
|
||||
$book = R::dispense( 'bean' );
|
||||
$book['author'] = R::dispense( 'author' );
|
||||
asrt( isset( $book['author'] ), TRUE );
|
||||
asrt( count( $book ), 2 );
|
||||
$book['author']['name'] = 'me';
|
||||
asrt( $book['author']['name'], 'me' );
|
||||
$book['author']['address'] = R::dispense( 'address' );
|
||||
$book['author']['ownTagList'][] = R::dispense( 'tag' );
|
||||
asrt( isset( $book['author']['address'] ), TRUE );
|
||||
asrt( isset( $book['author']['ownTag'] ), TRUE );
|
||||
asrt( count( $book['author']['ownTag'] ), 1 );
|
||||
asrt( isset( $book['author']['xownTag'] ), TRUE );
|
||||
asrt( count( $book['author']['xownTag'] ), 1 );
|
||||
asrt( isset( $book['author']['ownTagList'] ), TRUE );
|
||||
asrt( count( $book['author']['ownTagList'] ), 1 );
|
||||
asrt( isset( $book['author']['xownTagList'] ), TRUE );
|
||||
asrt( count( $book['author']['xownTagList'] ), 1 );
|
||||
unset( $book['author'] );
|
||||
asrt( isset( $book['author'] ), FALSE );
|
||||
asrt( count( $book ), 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests array access with CRUD operations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testArrayAccessWithCRUD()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$book['ownPageList'] = R::dispense( 'page', 3 );
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
//note that isset first returns FALSE, so you can check if a list is loaded
|
||||
asrt( isset( $book['ownPage'] ), FALSE );
|
||||
asrt( isset( $book['ownPageList'] ), FALSE );
|
||||
asrt( isset( $book['xownPage'] ), FALSE );
|
||||
asrt( isset( $book['xownPageList'] ), FALSE );
|
||||
//count triggers load...
|
||||
asrt( count( $book['ownPage'] ), 3 );
|
||||
asrt( isset( $book['ownPage'] ), TRUE );
|
||||
asrt( isset( $book['ownPageList'] ), TRUE );
|
||||
asrt( isset( $book['xownPage'] ), TRUE );
|
||||
asrt( isset( $book['xownPageList'] ), TRUE );
|
||||
$book = $book->fresh();
|
||||
asrt( count( $book['xownPage'] ), 3 );
|
||||
$book = $book->fresh();
|
||||
asrt( count( $book['ownPageList'] ), 3 );
|
||||
$book = $book->fresh();
|
||||
asrt( count( $book['xownPageList'] ), 3 );
|
||||
$book['ownPage'][] = R::dispense( 'page' );
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
asrt( count( $book['ownPage'] ), 4 );
|
||||
$book = $book->fresh();
|
||||
asrt( count( $book['xownPage'] ), 4 );
|
||||
$book = $book->fresh();
|
||||
asrt( count( $book['ownPageList'] ), 4 );
|
||||
$book = $book->fresh();
|
||||
asrt( count( $book['xownPageList'] ), 4 );
|
||||
//does dependency still work?
|
||||
$book['xownPageList'] = array();
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
asrt( count( $book['ownPage'] ), 0 );
|
||||
$book = $book->fresh();
|
||||
asrt( count( $book['xownPage'] ), 0 );
|
||||
$book = $book->fresh();
|
||||
asrt( count( $book['ownPageList'] ), 0 );
|
||||
$book = $book->fresh();
|
||||
asrt( count( $book['xownPageList'] ), 0 );
|
||||
//does shared list work as well?
|
||||
$book['sharedTag'] = R::dispense( 'tag', 2 );
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
//note that isset first returns FALSE, so you can check if a list is loaded
|
||||
asrt( isset( $book['sharedTagList'] ), FALSE );
|
||||
asrt( isset( $book['sharedTag'] ), FALSE );
|
||||
//count triggers load...
|
||||
asrt( count( $book['sharedTagList'] ), 2 );
|
||||
asrt( count( $book['sharedTag'] ), 2 );
|
||||
asrt( isset( $book['sharedTagList'] ), TRUE );
|
||||
asrt( isset( $book['sharedTag'] ), TRUE );
|
||||
$book['sharedTag'][] = R::dispense( 'tag' );
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
asrt( count( $book['sharedTagList'] ), 3 );
|
||||
asrt( count( $book['sharedTag'] ), 3 );
|
||||
$book['sharedTagList'][] = R::dispense( 'tag' );
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
asrt( count( $book['sharedTagList'] ), 4 );
|
||||
asrt( count( $book['sharedTag'] ), 4 );
|
||||
//does it also work with cross-shared
|
||||
$book['sharedBookList'][] = R::dispense( 'book' );
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
asrt( isset( $book['sharedBookList'] ), FALSE );
|
||||
asrt( count( $book['sharedBookList'] ), 1 );
|
||||
$first = reset( $book['sharedBookList'] );
|
||||
$id = $first['id'];
|
||||
asrt( count( $book['sharedBookList'][$id]['sharedBookList'] ), 1 );
|
||||
$properties = array();
|
||||
foreach($book as $key => $value) {
|
||||
$properties[ $key ] = $value;
|
||||
}
|
||||
asrt( count( $properties ), 2 );
|
||||
$keys = array_keys( $properties );
|
||||
sort( $keys );
|
||||
asrt( implode( ',', $keys ), 'id,sharedBook' );
|
||||
}
|
||||
}
|
||||
296
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Association.php
vendored
Normal file
296
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Association.php
vendored
Normal file
@@ -0,0 +1,296 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\ToolBox as ToolBox;
|
||||
use RedBeanPHP\OODB as OODB;
|
||||
use RedBeanPHP\AssociationManager as AssociationManager;
|
||||
use RedBeanPHP\RedException\SQL as SQL;
|
||||
|
||||
/**
|
||||
* Association
|
||||
*
|
||||
* Originally meant to test R::associate - which is no longer
|
||||
* used, this class tests all kinds of relations from
|
||||
* one-to-one to polymorph relations using the poly() method.
|
||||
*
|
||||
* @file RedUNIT/Base/Association.php
|
||||
* @desc Tests Association API (N:N associations)
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Association extends Base
|
||||
{
|
||||
/**
|
||||
* MySQL specific tests.
|
||||
* Test MySQL specific issues with constraints.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMySQL()
|
||||
{
|
||||
if ( $this->currentlyActiveDriverID !== 'mysql' ) {
|
||||
return;
|
||||
}
|
||||
testpack( 'Throw exception in case of issue with assoc constraint' );
|
||||
$bunny = R::dispense( 'bunny' );
|
||||
$carrot = R::dispense( 'carrot' );
|
||||
$faultyWriter = new \FaultyWriter( R::getToolBox()->getDatabaseAdapter() );
|
||||
$faultyOODB = new OODB( $faultyWriter );
|
||||
$faultyOODB->setBeanHelper( R::getRedBean()->getBeanHelper() );
|
||||
$faultyToolbox = new ToolBox( $faultyOODB, R::getToolBox()->getDatabaseAdapter(), $faultyWriter );
|
||||
$faultyAssociationManager = new AssociationManager( $faultyToolbox );
|
||||
$faultyWriter->setSQLState( '23000' );
|
||||
$faultyAssociationManager->associate( $bunny, $carrot );
|
||||
pass();
|
||||
$faultyWriter->setSQLState( '42S22' );
|
||||
R::nuke();
|
||||
try {
|
||||
$faultyAssociationManager->associate( $bunny, $carrot );
|
||||
fail();
|
||||
} catch ( SQL $exception ) {
|
||||
pass();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test fast-track deletion, i.e. bypassing FUSE.
|
||||
* For link beans.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testFastTrackDeletion()
|
||||
{
|
||||
testpack( 'Test fast-track deletion' );
|
||||
$ghost = R::dispense( 'ghost' );
|
||||
$house = R::dispense( 'house' );
|
||||
$house->sharedGhost[] = $ghost;
|
||||
R::store($house);
|
||||
\Model_Ghost_House::$deleted = FALSE;
|
||||
R::getRedBean()->getAssociationManager()->unassociate( $house, $ghost );
|
||||
// No fast-track, assoc bean got trashed
|
||||
asrt( \Model_Ghost_House::$deleted, TRUE );
|
||||
\Model_Ghost_House::$deleted = FALSE;
|
||||
$house->sharedGhost[] = $ghost;
|
||||
R::store($house);
|
||||
R::getRedBean()->getAssociationManager()->unassociate( $house, $ghost, TRUE );
|
||||
// Fast-track, assoc bean got deleted right away
|
||||
asrt( \Model_Ghost_House::$deleted, FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test self-referential associations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCrossAssociation()
|
||||
{
|
||||
$ghost = R::dispense( 'ghost' );
|
||||
$ghost2 = R::dispense( 'ghost' );
|
||||
R::getRedBean()->getAssociationManager()->associate( $ghost, $ghost2 );
|
||||
\Model_Ghost_Ghost::$deleted = FALSE;
|
||||
R::getRedBean()->getAssociationManager()->unassociate( $ghost, $ghost2 );
|
||||
// No fast-track, assoc bean got trashed
|
||||
asrt( \Model_Ghost_Ghost::$deleted, TRUE );
|
||||
\Model_Ghost_Ghost::$deleted = FALSE;
|
||||
R::getRedBean()->getAssociationManager()->unassociate( $ghost, $ghost2, TRUE );
|
||||
// Fast-track, assoc bean got deleted right away
|
||||
asrt( \Model_Ghost_Ghost::$deleted, FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test limited support for polymorph associations.
|
||||
* RedBeanPHP does not really feature polymorph relations since
|
||||
* they are not really compatible with traditional relational databases.
|
||||
* However a light-weight, basic implementation has been added for
|
||||
* those circumstances where you can't live without...
|
||||
* i.e... possible legacy systems and so on.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testPoly()
|
||||
{
|
||||
testpack( 'Testing poly' );
|
||||
$shoe = R::dispense( 'shoe' );
|
||||
$lace = R::dispense( 'lace' );
|
||||
$lace->color = 'white';
|
||||
$id = R::store( $lace );
|
||||
$shoe->itemType = 'lace';
|
||||
$shoe->item = $lace;
|
||||
$id = R::store( $shoe );
|
||||
$shoe = R::load( 'shoe', $id );
|
||||
$x = $shoe->poly( 'itemType' )->item;
|
||||
asrt( $x->color, 'white' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test limited support for 1-to-1 associations.
|
||||
* The rule is, one-to-ones are supposes to be in the same table,
|
||||
* this is just for some legacy tables not designed to work
|
||||
* with RedBeanPHP at all.
|
||||
*
|
||||
* @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 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test single column bases unique constraints.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSingleColUniqueConstraint()
|
||||
{
|
||||
testpack( 'Testing unique constraint on single column' );
|
||||
$book = R::dispense( 'book' );
|
||||
$book->title = 'bla';
|
||||
$book->extra = 2;
|
||||
$id = R::store( $book );
|
||||
R::getWriter()->addUniqueIndex( 'book', array( 'title' ) );
|
||||
$book = R::dispense( 'book' );
|
||||
$book->title = 'bla';
|
||||
$expected = NULL;
|
||||
try {
|
||||
R::store( $book );
|
||||
|
||||
fail();
|
||||
} catch ( SQL $e ) {
|
||||
$expected = $e;
|
||||
}
|
||||
asrt( ( $expected instanceof SQL ), TRUE );
|
||||
asrt( R::count( 'book' ), 1 );
|
||||
$book = R::load( 'book', $id );
|
||||
// Causes failure, table will be rebuild
|
||||
$book->extra = 'CHANGE';
|
||||
$id2 = R::store( $book );
|
||||
$book2 = R::load( 'book', $id2 );
|
||||
$book = R::dispense( 'book' );
|
||||
$book->title = 'bla';
|
||||
try {
|
||||
R::store( $book );
|
||||
|
||||
fail();
|
||||
} catch ( SQL $e ) {
|
||||
$expected = $e;
|
||||
}
|
||||
asrt( ( $expected instanceof SQL ), TRUE );
|
||||
asrt( R::count( 'book' ), 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test multiple assiociation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMultiAssociationDissociation()
|
||||
{
|
||||
$wines = R::dispense( 'wine', 3 );
|
||||
$cheese = R::dispense( 'cheese', 3 );
|
||||
$olives = R::dispense( 'olive', 3 );
|
||||
R::getRedBean()->getAssociationManager()->associate( $wines, array_merge( $cheese, $olives ) );
|
||||
asrt( R::count( 'cheese' ), 3 );
|
||||
asrt( R::count( 'olive' ), 3 );
|
||||
asrt( R::count( 'wine' ), 3 );
|
||||
asrt( count( $wines[0]->sharedCheese ), 3 );
|
||||
asrt( count( $wines[0]->sharedOlive ), 3 );
|
||||
asrt( count( $wines[1]->sharedCheese ), 3 );
|
||||
asrt( count( $wines[1]->sharedOlive ), 3 );
|
||||
asrt( count( $wines[2]->sharedCheese ), 3 );
|
||||
asrt( count( $wines[2]->sharedOlive ), 3 );
|
||||
R::getRedBean()->getAssociationManager()->unassociate( $wines, $olives );
|
||||
asrt( count( $wines[0]->sharedCheese ), 3 );
|
||||
asrt( count( $wines[0]->sharedOlive ), 0 );
|
||||
asrt( count( $wines[1]->sharedCheese ), 3 );
|
||||
asrt( count( $wines[1]->sharedOlive ), 0 );
|
||||
asrt( count( $wines[2]->sharedCheese ), 3 );
|
||||
asrt( count( $wines[2]->sharedOlive ), 0 );
|
||||
R::getRedBean()->getAssociationManager()->unassociate( array( $wines[1] ), $cheese );
|
||||
asrt( count( $wines[0]->sharedCheese ), 3 );
|
||||
asrt( count( $wines[0]->sharedOlive ), 0 );
|
||||
asrt( count( $wines[1]->sharedCheese ), 0 );
|
||||
asrt( count( $wines[1]->sharedOlive ), 0 );
|
||||
asrt( count( $wines[2]->sharedCheese ), 3 );
|
||||
asrt( count( $wines[2]->sharedOlive ), 0 );
|
||||
R::getRedBean()->getAssociationManager()->unassociate( array( $wines[2] ), $cheese );
|
||||
asrt( count( $wines[0]->sharedCheese ), 3 );
|
||||
asrt( count( $wines[0]->sharedOlive ), 0 );
|
||||
asrt( count( $wines[1]->sharedCheese ), 0 );
|
||||
asrt( count( $wines[1]->sharedOlive ), 0 );
|
||||
asrt( count( $wines[2]->sharedCheese ), 0 );
|
||||
asrt( count( $wines[2]->sharedOlive ), 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests error handling related to association.
|
||||
* On database systems providing informative SQL STATE error codes
|
||||
* RedBeanPHP should not mind non-existing tables or columns in
|
||||
* fluid mode.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testErrorHandling()
|
||||
{
|
||||
R::nuke();
|
||||
list( $book, $page ) = R::dispenseAll( 'book,page' );
|
||||
$book->sharedPage[] = $page;
|
||||
R::store( $page );
|
||||
$redbean = R::getRedBean();
|
||||
$am = $redbean->getAssociationManager();
|
||||
//SQLite and CUBRID do not comply with ANSI SQLState codes.
|
||||
$catchAll = ( $this->currentlyActiveDriverID == 'sqlite' || $this->currentlyActiveDriverID === 'CUBRID' );
|
||||
try {
|
||||
$am->related( $book, 'page', 'invalid SQL' );
|
||||
if ($catchAll) pass(); else fail();
|
||||
} catch ( SQL $e ) {
|
||||
if ($catchAll) fail(); else pass();
|
||||
}
|
||||
try {
|
||||
$am->related( $book, 'cover');
|
||||
pass();
|
||||
} catch ( SQL $e ) {
|
||||
fail();
|
||||
}
|
||||
try {
|
||||
$am->related( R::dispense('cover'), 'book' );
|
||||
pass();
|
||||
} catch ( SQL $e ) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
151
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Batch.php
vendored
Normal file
151
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Batch.php
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
use RedBeanPHP\RedException\SQL as SQL;
|
||||
|
||||
/**
|
||||
* Batch
|
||||
*
|
||||
* Test whether we can load a group of beans in one go, i.e.
|
||||
* the batch loading functionality of RedBeanPHP, also in combination
|
||||
* with aliasing.
|
||||
*
|
||||
* @file RedUNIT/Base/Batch.php
|
||||
* @desc Tests batch loading of beans, i.e. loading large collections of beans in optimized way.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Batch extends Base
|
||||
{
|
||||
/**
|
||||
* Can we delete beans by find-query?
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testHunt()
|
||||
{
|
||||
R::nuke();
|
||||
$books = R::dispenseAll( 'book*3' );
|
||||
R::storeAll( $books[0] );
|
||||
pass();
|
||||
asrt( ( R::count( 'book' ) === 3 ), TRUE );
|
||||
$ids = R::getCol( 'SELECT id FROM book' );
|
||||
R::hunt( 'book', ' id IN ( '. R::genSlots( $ids ) .' ) ', $ids );
|
||||
asrt( ( R::count( 'book' ) === 0 ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests batch trashing. Can we trash beans using
|
||||
* IDs only?
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBatchTrash()
|
||||
{
|
||||
R::nuke();
|
||||
$books = R::dispenseAll( 'book*3' );
|
||||
R::storeAll( $books[0] );
|
||||
pass();
|
||||
asrt( ( R::count( 'book' ) === 3 ), TRUE );
|
||||
R::trashBatch( 'book', R::getCol( 'SELECT id FROM book' ) );
|
||||
asrt( ( R::count( 'book' ) === 0 ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin testing.
|
||||
* This method runs the actual test pack.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBatch()
|
||||
{
|
||||
R::freeze( FALSE );
|
||||
$toolbox = R::getToolBox();
|
||||
$adapter = $toolbox->getDatabaseAdapter();
|
||||
$writer = $toolbox->getWriter();
|
||||
$redbean = $toolbox->getRedBean();
|
||||
$pdo = $adapter->getDatabase();
|
||||
$page = $redbean->dispense( "page" );
|
||||
$page->name = "page no. 1";
|
||||
$page->rating = 1;
|
||||
$id1 = $redbean->store( $page );
|
||||
$page = $redbean->dispense( "page" );
|
||||
$page->name = "page no. 2";
|
||||
$id2 = $redbean->store( $page );
|
||||
$batch = $redbean->batch( "page", array( $id1, $id2 ) );
|
||||
asrt( count( $batch ), 2 );
|
||||
asrt( $batch[$id1]->getMeta( "type" ), "page" );
|
||||
asrt( $batch[$id2]->getMeta( "type" ), "page" );
|
||||
asrt( (int) $batch[$id1]->id, $id1 );
|
||||
asrt( (int) $batch[$id2]->id, $id2 );
|
||||
$book = $redbean->dispense( "book" );
|
||||
$book->name = "book 1";
|
||||
$redbean->store( $book );
|
||||
$book = $redbean->dispense( "book" );
|
||||
$book->name = "book 2";
|
||||
$redbean->store( $book );
|
||||
$book = $redbean->dispense( "book" );
|
||||
$book->name = "book 3";
|
||||
$redbean->store( $book );
|
||||
$books = $redbean->batch( "book", $adapter->getCol( "SELECT id FROM book" ) );
|
||||
asrt( count( $books ), 3 );
|
||||
$a = $redbean->batch( 'book', 9919 );
|
||||
asrt( is_array( $a ), TRUE );
|
||||
asrt( count( $a ), 0 );
|
||||
$a = $redbean->batch( 'triangle', 1 );
|
||||
asrt( is_array( $a ), TRUE );
|
||||
asrt( count( $a ), 0 );
|
||||
R::freeze( TRUE );
|
||||
$a = $redbean->batch( 'book', 9919 );
|
||||
asrt( is_array( $a ), TRUE );
|
||||
asrt( count( $a ), 0 );
|
||||
try {
|
||||
$a = $redbean->batch( 'triangle', 1 );
|
||||
fail();
|
||||
} catch(SQL $e) {
|
||||
pass();
|
||||
}
|
||||
R::freeze( FALSE );
|
||||
asrt( R::wipe( 'spaghettimonster' ), FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test missing bean scenarios.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMissingBeans()
|
||||
{
|
||||
testpack( 'deal with missing beans' );
|
||||
|
||||
$id = R::store( R::dispense( 'beer' ) );
|
||||
$bottles = R::batch( 'beer', array( $id, $id + 1, $id + 2 ) );
|
||||
|
||||
asrt( count( $bottles ), 3 );
|
||||
asrt( (int) $bottles[$id]->id, (int) $id );
|
||||
asrt( (int) $bottles[$id + 1]->id, 0 );
|
||||
asrt( (int) $bottles[$id + 2]->id, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 );
|
||||
}
|
||||
}
|
||||
1276
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Bean.php
vendored
Normal file
1276
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Bean.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
70
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Boxing.php
vendored
Normal file
70
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Boxing.php
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\SimpleModel as SimpleModel;
|
||||
|
||||
/**
|
||||
* Boxing
|
||||
*
|
||||
* Test boxing and unboxing of beans.
|
||||
*
|
||||
* @file RedUNIT/Base/Boxing.php
|
||||
* @desc Tests bean boxing and unboxing functionality.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Boxing extends Base
|
||||
{
|
||||
|
||||
/**
|
||||
* Test boxing beans.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBoxing()
|
||||
{
|
||||
R::nuke();
|
||||
$bean = R::dispense( 'boxedbean' )->box();
|
||||
R::trash( $bean );
|
||||
pass();
|
||||
$bean = R::dispense( 'boxedbean' );
|
||||
$bean->sharedBoxbean = R::dispense( 'boxedbean' )->box();
|
||||
R::store( $bean );
|
||||
pass();
|
||||
$bean = R::dispense( 'boxedbean' );
|
||||
$bean->ownBoxedbean = R::dispense( 'boxedbean' )->box();
|
||||
R::store( $bean );
|
||||
pass();
|
||||
$bean = R::dispense( 'boxedbean' );
|
||||
$bean->other = R::dispense( 'boxedbean' )->box();
|
||||
R::store( $bean );
|
||||
pass();
|
||||
$bean = R::dispense( 'boxedbean' );
|
||||
$bean->title = 'MyBean';
|
||||
$box = $bean->box();
|
||||
asrt( ( $box instanceof \Model_Boxedbean ), TRUE );
|
||||
R::store( $box );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test fix for issue #512 - thanks for reporting Bernhard H.
|
||||
* OODBBean::__toString() implementation only works with C_ERR_IGNORE
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testToStringIssue512()
|
||||
{
|
||||
R::setErrorHandlingFUSE( \RedBeanPHP\OODBBean::C_ERR_FATAL );
|
||||
$boxedBean = R::dispense( 'boxedbean' );
|
||||
$str = (string) $boxedBean;
|
||||
asrt( $str, '{"id":0}' ); //no fatal error
|
||||
R::setErrorHandlingFUSE( FALSE );
|
||||
}
|
||||
}
|
||||
135
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Chill.php
vendored
Normal file
135
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Chill.php
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
|
||||
/**
|
||||
* Chill
|
||||
*
|
||||
* Tests 'chill' mode. In this mode some bean types are frozen,
|
||||
* their schemas cannot be modified while others are fluid and
|
||||
* can still be adjusted.
|
||||
*
|
||||
* @file RedUNIT/Base/Chill.php
|
||||
* @desc Tests chill list functionality, i.e. freezing a subset of all types.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Chill extends Base
|
||||
{
|
||||
/**
|
||||
* Test Chill mode.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testChill()
|
||||
{
|
||||
$bean = R::dispense( 'bean' );
|
||||
$bean->col1 = '1';
|
||||
$bean->col2 = '2';
|
||||
R::store( $bean );
|
||||
asrt( count( R::getWriter()->getColumns( 'bean' ) ), 3 );
|
||||
$bean->col3 = '3';
|
||||
R::store( $bean );
|
||||
asrt( count( R::getWriter()->getColumns( 'bean' ) ), 4 );
|
||||
R::freeze( array( 'umbrella' ) );
|
||||
$bean->col4 = '4';
|
||||
R::store( $bean );
|
||||
asrt( count( R::getWriter()->getColumns( 'bean' ) ), 5 );
|
||||
R::freeze( array( 'bean' ) );
|
||||
$bean->col5 = '5';
|
||||
try {
|
||||
R::store( $bean );
|
||||
fail();
|
||||
} catch (\Exception $e ) {
|
||||
pass();
|
||||
}
|
||||
asrt( count( R::getWriter()->getColumns( 'bean' ) ), 5 );
|
||||
R::freeze( array() );
|
||||
$bean->col5 = '5';
|
||||
R::store( $bean );
|
||||
asrt( count( R::getWriter()->getColumns( 'bean' ) ), 6 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether we cannot add unique constraints on chilled tables,
|
||||
* otherwise you cannot avoid this from happening when adding beans to the
|
||||
* shared list :) -- this is almost a theoretical issue however we want it
|
||||
* to work according to specifications!
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDontAddUniqueConstraintForChilledBeanTypes()
|
||||
{
|
||||
R::nuke();
|
||||
$person = R::dispense( 'person' );
|
||||
$role = R::dispense( 'role' );
|
||||
$person->sharedRole[] = $role;
|
||||
R::store( $person );
|
||||
$person->sharedRole[] = R::dispense( 'role' );
|
||||
R::store( $person );
|
||||
$bean = R::getRedBean()->dispense('person_role');
|
||||
$bean->personId = $person->id;
|
||||
$bean->roleId = $role->id;
|
||||
try {
|
||||
R::store( $bean );
|
||||
fail();
|
||||
} catch(\Exception $e) {
|
||||
pass();
|
||||
}
|
||||
asrt(R::count('person_role'), 2);
|
||||
R::nuke();
|
||||
$link = R::getRedBean()->dispense('person_role');
|
||||
$person = R::dispense( 'person' );
|
||||
$role = R::dispense( 'role' );
|
||||
$link->person = $person;
|
||||
$link->role = $role;
|
||||
R::store( $link );
|
||||
R::freeze(array('person_role'));
|
||||
$person->sharedRole[] = R::dispense( 'role' );
|
||||
R::store( $person );
|
||||
$bean = R::getRedBean()->dispense('person_role');
|
||||
$bean->personId = $person->id;
|
||||
$bean->roleId = $role->id;
|
||||
try {
|
||||
R::store( $bean );
|
||||
pass();
|
||||
} catch(\Exception $e) {
|
||||
fail();
|
||||
}
|
||||
asrt(R::count('person_role'), 3);
|
||||
R::freeze( array() ); //set freeze to FALSE and clear CHILL LIST!
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether we can set and reset the chill list and check the contents
|
||||
* of the chill list.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testChillTest()
|
||||
{
|
||||
R::freeze( array( 'beer' ) );
|
||||
$oodb = R::getRedBean();
|
||||
asrt( $oodb->isChilled( 'beer' ), TRUE );
|
||||
asrt( $oodb->isChilled( 'wine' ), FALSE );
|
||||
R::freeze( FALSE );
|
||||
$oodb = R::getRedBean();
|
||||
asrt( $oodb->isChilled( 'beer' ), TRUE );
|
||||
asrt( $oodb->isChilled( 'wine' ), FALSE );
|
||||
R::freeze( TRUE );
|
||||
$oodb = R::getRedBean();
|
||||
asrt( $oodb->isChilled( 'beer' ), TRUE );
|
||||
asrt( $oodb->isChilled( 'wine' ), FALSE );
|
||||
R::freeze( array() );
|
||||
$oodb = R::getRedBean();
|
||||
asrt( $oodb->isChilled( 'beer' ), FALSE );
|
||||
asrt( $oodb->isChilled( 'wine' ), FALSE );
|
||||
}
|
||||
}
|
||||
62
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Close.php
vendored
Normal file
62
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Close.php
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\ToolBox as ToolBox;
|
||||
use RedBeanPHP\QueryWriter\SQLiteT as SQLiteT;
|
||||
|
||||
/**
|
||||
* Close
|
||||
*
|
||||
* Tests whether we can close the database connection.
|
||||
*
|
||||
* @file RedUNIT/Base/Close.php
|
||||
* @desc Tests database closing functionality.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Close extends Base
|
||||
{
|
||||
/**
|
||||
* Test closing database connection.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testClose()
|
||||
{
|
||||
// Test whether we can select a specific feature set
|
||||
R::useFeatureSet('novice/latest');
|
||||
pass();
|
||||
R::useFeatureSet('latest');
|
||||
pass();
|
||||
R::useFeatureSet('5.3');
|
||||
pass();
|
||||
R::useFeatureSet('novice/5.3');
|
||||
pass();
|
||||
try {
|
||||
R::useFeatureSet('5.2');
|
||||
fail();
|
||||
} catch ( \Exception $e ) {
|
||||
asrt( $e->getMessage(), 'Unknown feature set label.' );
|
||||
}
|
||||
try {
|
||||
R::nuke();
|
||||
fail();
|
||||
} catch( \Exception $e ) {
|
||||
asrt( $e->getMessage(), 'The nuke() command has been disabled using noNuke() or R::feature(novice/...).' );
|
||||
}
|
||||
R::useFeatureSet('latest');
|
||||
//Close
|
||||
R::getDatabaseAdapter()->setOption( 'setInitQuery', NULL );
|
||||
asrt( R::getDatabaseAdapter()->getDatabase()->isConnected(), TRUE );
|
||||
R::close();
|
||||
asrt( R::getDatabaseAdapter()->getDatabase()->isConnected(), FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
314
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Concurrency.php
vendored
Normal file
314
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Concurrency.php
vendored
Normal file
@@ -0,0 +1,314 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\RedException as RedException;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
use RedBeanPHP\QueryWriter\AQueryWriter;
|
||||
|
||||
/**
|
||||
* Concurrency
|
||||
*
|
||||
* Tests whether we can lock beans.
|
||||
*
|
||||
* @file RedUNIT/Base/Concurrency.php
|
||||
* @desc Tests concurrency scenarios
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Concurrency extends Base
|
||||
{
|
||||
/**
|
||||
* Returns the target drivers for this test.
|
||||
* This test only works with Postgres and MySQL/MariaDB.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTargetDrivers()
|
||||
{
|
||||
return array( 'pgsql','mysql' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the database connection.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function prepare()
|
||||
{
|
||||
try{
|
||||
R::close();
|
||||
} catch( \Exception $e ) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* This test has to be run manually.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function testLockException()
|
||||
{
|
||||
R::nuke();
|
||||
$lock = R::dispense('lock');
|
||||
$lock->value = 123;
|
||||
R::store($lock);
|
||||
$c = pcntl_fork();
|
||||
if ($c == -1) exit(1);
|
||||
if (!$c) {
|
||||
R::selectDatabase($this->currentlyActiveDriverID . 'c2');
|
||||
R::freeze(TRUE);
|
||||
try { R::exec('SET SESSION innodb_lock_wait_timeout=5');}catch( \Exception $e ){}
|
||||
try { R::exec('SET autocommit = 0'); }catch( \Exception $e ){}
|
||||
R::begin();
|
||||
$lock = R::loadForUpdate('lock', $lock->id);
|
||||
$lock->value = 4;
|
||||
sleep(10);
|
||||
R::store($lock);
|
||||
exit(0);
|
||||
} else {
|
||||
R::selectDatabase($this->currentlyActiveDriverID . 'c2');
|
||||
sleep(1);
|
||||
R::freeze(TRUE);
|
||||
try{ R::exec('SET SESSION innodb_lock_wait_timeout=5');}catch( \Exception $e ){}
|
||||
try{R::exec("SET lock_timeout = '1s';");}catch( \Exception $e ){}
|
||||
try { R::exec('SET autocommit = 0'); }catch( \Exception $e ){}
|
||||
R::begin();
|
||||
$exception = NULL;
|
||||
try {
|
||||
$lock = R::loadForUpdate('lock', $lock->id);
|
||||
} catch( \Exception $e ) {
|
||||
$exception = $e;
|
||||
}
|
||||
if ( !$exception ) fail();
|
||||
pass();
|
||||
$details = $exception->getDriverDetails();
|
||||
asrt( ($details[1]===1205 || $details[0]==='55P03'), TRUE );
|
||||
var_dump($lock);
|
||||
}
|
||||
try { R::exec('SET autocommit = 1'); }catch( \Exception $e ){}
|
||||
pcntl_wait($status);
|
||||
try { R::exec('SET SESSION innodb_lock_wait_timeout=50');}catch( \Exception $e ){}
|
||||
try{R::exec("SET lock_timeout = '50s';");}catch( \Exception $e ){}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests basic locking scenarios using fork().
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testConcurrency()
|
||||
{
|
||||
$c = pcntl_fork();
|
||||
if ($c == -1) exit(1);
|
||||
if (!$c) {
|
||||
R::selectDatabase($this->currentlyActiveDriverID . 'c');
|
||||
try{ R::exec('SET SESSION innodb_lock_wait_timeout=51');}catch( \Exception $e ){}
|
||||
try{R::exec("SET lock_timeout = '51s';");}catch( \Exception $e ){}
|
||||
R::exec('SET TRANSACTION ISOLATION LEVEL REPEATABLE READ');
|
||||
sleep(2);
|
||||
try { R::exec('SET autocommit = 0'); }catch( \Exception $e ){}
|
||||
R::freeze(TRUE);
|
||||
R::begin();
|
||||
echo "CHILD: SUBTRACTING 2 START\n";
|
||||
$i = R::loadForUpdate('inventory', 1);
|
||||
$i->apples -= 2;
|
||||
sleep(4);
|
||||
R::store($i);
|
||||
R::commit();
|
||||
echo "CHILD: SUBTRACTING 2 DONE\n";
|
||||
echo (R::load('inventory', 1));
|
||||
echo "\n";
|
||||
exit(0);
|
||||
} else {
|
||||
R::selectDatabase($this->currentlyActiveDriverID . 'c');
|
||||
try{ R::exec('SET SESSION innodb_lock_wait_timeout=51');}catch( \Exception $e ){}
|
||||
try{R::exec("SET lock_timeout = '51s';");}catch( \Exception $e ){}
|
||||
echo "PARENT: PREP START\n";
|
||||
R::nuke();
|
||||
$i = R::dispense('inventory');
|
||||
$i->apples = 10;
|
||||
R::store($i);
|
||||
R::exec('SET TRANSACTION ISOLATION LEVEL REPEATABLE READ');
|
||||
echo "PARENT: PREP DONE\n";
|
||||
sleep(3);
|
||||
echo "PARENT: ADDING 5 START\n";
|
||||
try { R::exec('SET autocommit = 0'); }catch( \Exception $e ){}
|
||||
R::freeze( TRUE );
|
||||
R::begin();
|
||||
$i = R::findForUpdate('inventory', ' id = ? ', array(1));
|
||||
$i = reset( $i );
|
||||
print_r($i);
|
||||
$i->apples += 5;
|
||||
R::store($i);
|
||||
R::commit();
|
||||
echo "PARENT ADDING 5 DONE\n";
|
||||
$i = R::getAll('select * from inventory where id = 1');
|
||||
print_r($i);
|
||||
asrt((int)$i[0]['apples'], 13);
|
||||
R::freeze( FALSE );
|
||||
try { R::exec('SET autocommit = 1'); }catch( \Exception $e ){}
|
||||
pcntl_wait($status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether we can use setSQLSnippet with find() and batch().
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBatchAndFind()
|
||||
{
|
||||
/* baseline */
|
||||
R::nuke();
|
||||
$beans = R::dispenseAll('bean*10');
|
||||
R::storeAll($beans[0]);
|
||||
$ids = array();
|
||||
foreach($beans[0] as $bean) $ids[] = $bean->id;
|
||||
R::debug( TRUE, 1 );
|
||||
$logs = R::getDatabaseAdapter()
|
||||
->getDatabase()
|
||||
->getLogger();
|
||||
$beans = R::batch( 'bean', $ids );
|
||||
asrt( count( $beans ), 10 );
|
||||
$entries = $logs->grep('for update');
|
||||
asrt( count( $entries ), 0 );
|
||||
$logs->clear();
|
||||
|
||||
/* findOneForUpdate */
|
||||
R::nuke();
|
||||
$beans = R::dispenseAll('bean*10');
|
||||
R::storeAll($beans[0]);
|
||||
$ids = array();
|
||||
foreach($beans[0] as $bean) $ids[] = $bean->id;
|
||||
R::debug( TRUE, 1 );
|
||||
$logs = R::getDatabaseAdapter()
|
||||
->getDatabase()
|
||||
->getLogger();
|
||||
$beans = R::findOneForUpdate( 'bean' );
|
||||
asrt( count( $beans ), 1 );
|
||||
$entries = $logs->grep('for update');
|
||||
asrt( count( $entries ), 0 );
|
||||
$logs->clear();
|
||||
|
||||
/* findForUpdate */
|
||||
R::nuke();
|
||||
$beans = R::dispenseAll('bean*10');
|
||||
R::storeAll($beans[0]);
|
||||
$ids = array();
|
||||
foreach($beans[0] as $bean) $ids[] = $bean->id;
|
||||
R::debug( TRUE, 1 );
|
||||
$logs = R::getDatabaseAdapter()
|
||||
->getDatabase()
|
||||
->getLogger();
|
||||
$beans = R::findForUpdate( 'bean' );
|
||||
asrt( count( $beans ), 10 );
|
||||
$entries = $logs->grep('for update');
|
||||
asrt( count( $entries ), 0 );
|
||||
$logs->clear();
|
||||
|
||||
/* batch + snippet */
|
||||
R::nuke();
|
||||
$beans = R::dispenseAll('bean*10');
|
||||
R::storeAll($beans[0]);
|
||||
$ids = array();
|
||||
R::getWriter()->setSQLSelectSnippet('for update');
|
||||
foreach($beans[0] as $bean) $ids[] = $bean->id;
|
||||
R::debug( TRUE, 1 );
|
||||
$logs = R::getDatabaseAdapter()
|
||||
->getDatabase()
|
||||
->getLogger();
|
||||
$beans = R::batch( 'bean', $ids );
|
||||
asrt( count( $beans ), 10 );
|
||||
$entries = $logs->grep('for update');
|
||||
asrt( count( $entries ), 1 );
|
||||
print_r( $entries );
|
||||
$logs->clear();
|
||||
|
||||
/* baseline */
|
||||
R::nuke();
|
||||
$beans = R::dispenseAll('bean*10');
|
||||
R::storeAll($beans[0]);
|
||||
$ids = array();
|
||||
foreach($beans[0] as $bean) $ids[] = $bean->id;
|
||||
R::debug( TRUE, 1 );
|
||||
$logs = R::getDatabaseAdapter()
|
||||
->getDatabase()
|
||||
->getLogger();
|
||||
$beans = R::batch( 'bean', $ids );
|
||||
asrt( count( $beans ), 10 );
|
||||
$entries = $logs->grep('for update');
|
||||
asrt( count( $entries ), 0 );
|
||||
$logs->clear();
|
||||
|
||||
/* find + snippet */
|
||||
R::nuke();
|
||||
$beans = R::dispenseAll('bean*10');
|
||||
R::storeAll($beans[0]);
|
||||
$ids = array();
|
||||
R::getWriter()->setSQLSelectSnippet('for update');
|
||||
foreach($beans[0] as $bean) $ids[] = $bean->id;
|
||||
R::debug( TRUE, 1 );
|
||||
$logs = R::getDatabaseAdapter()
|
||||
->getDatabase()
|
||||
->getLogger();
|
||||
$beans = R::find( 'bean' );
|
||||
asrt( count( $beans ), 10 );
|
||||
$entries = $logs->grep('for update');
|
||||
asrt( count( $entries ), 1 );
|
||||
print_r( $entries );
|
||||
$logs->clear();
|
||||
|
||||
/* baseline */
|
||||
R::nuke();
|
||||
$beans = R::dispenseAll('bean*10');
|
||||
R::storeAll($beans[0]);
|
||||
$ids = array();
|
||||
foreach($beans[0] as $bean) $ids[] = $bean->id;
|
||||
R::debug( TRUE, 1 );
|
||||
$logs = R::getDatabaseAdapter()
|
||||
->getDatabase()
|
||||
->getLogger();
|
||||
$beans = R::batch( 'bean', $ids );
|
||||
asrt( count( $beans ), 10 );
|
||||
$entries = $logs->grep('for update');
|
||||
asrt( count( $entries ), 0 );
|
||||
$logs->clear();
|
||||
|
||||
R::debug( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* loadForUpdate/findForUpdate should be applied even if caching is on.
|
||||
* Caching may not interfere with locking beans.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testLockAndCache()
|
||||
{
|
||||
R::nuke();
|
||||
$bean = R::dispense('lock');
|
||||
$bean->title = 'lock';
|
||||
$id = R::store( $bean );
|
||||
R::getWriter()->setUseCache( TRUE );
|
||||
$lock = R::loadForUpdate( 'lock', $id );
|
||||
R::debug( TRUE, 1 );
|
||||
$lock = R::loadForUpdate( 'lock', $id );
|
||||
$logs = R::getDatabaseAdapter()->getDatabase()->getLogger()->grep( AQueryWriter::C_SELECT_SNIPPET_FOR_UPDATE );
|
||||
asrt( count($logs), 1 ); //if no cache clear, then would have been 2
|
||||
R::debug( FALSE );
|
||||
$lock = R::findForUpdate( 'lock', 'id = ?', array( $id ) );
|
||||
R::debug( TRUE, 1 );
|
||||
$lock = R::findForUpdate( 'lock', 'id = ?', array( $id ) );
|
||||
$logs = R::getDatabaseAdapter()->getDatabase()->getLogger()->grep( AQueryWriter::C_SELECT_SNIPPET_FOR_UPDATE );
|
||||
asrt( count($logs), 1 ); //if no cache clear, then would have been 2
|
||||
R::getWriter()->setUseCache( FALSE );
|
||||
R::debug( FALSE );
|
||||
R::nuke();
|
||||
}
|
||||
}
|
||||
224
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Copy.php
vendored
Normal file
224
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Copy.php
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
|
||||
/**
|
||||
* Copy
|
||||
*
|
||||
* Tests whether we can make a copy or a deep copy of a bean
|
||||
* and whether recursion is handled well. Also tests
|
||||
* versioning: copying can be used to implement a versioning feature,
|
||||
* some test cases will reflect this particular use case.
|
||||
*
|
||||
* @file RedUNIT/Base/Copy.php
|
||||
* @desc Tests whether we can make a deep copy of a bean.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Copy extends Base
|
||||
{
|
||||
/**
|
||||
* Test whether recursion happens
|
||||
*/
|
||||
public function testCopyRecursion()
|
||||
{
|
||||
$document = R::dispense( 'document' );
|
||||
$id = R::store( $document );
|
||||
$document->ownDocument[] = $document;
|
||||
R::store( $document );
|
||||
$duplicate = R::dup( $document );
|
||||
pass(); //if RB cant handle this is will crash (nesting level error from PHP).
|
||||
$id2 = R::store( $duplicate );
|
||||
$duplicate = R::load( 'document', $id );
|
||||
asrt( (int) $document->document_id, $id );
|
||||
asrt( (int) $duplicate->document_id, $id2 );
|
||||
// Export variant
|
||||
$duplicate = R::exportAll( $document );
|
||||
asrt( (int) $duplicate[0]['document_id'], $id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test real world scenario: Versioning
|
||||
*/
|
||||
public function testVersioning()
|
||||
{
|
||||
$document = R::dispense( 'document' );
|
||||
$page = R::dispense( 'page' );
|
||||
$document->title = 'test';
|
||||
$page->content = 'lorem ipsum';
|
||||
$user = R::dispense( 'user' );
|
||||
$user->name = 'Leo';
|
||||
$document->sharedUser[] = $user;
|
||||
$document->ownPage[] = $page;
|
||||
$document->starship_id = 3;
|
||||
$document->planet = R::dispense( 'planet' );
|
||||
R::store( $document );
|
||||
$duplicate = R::dup( $document );
|
||||
R::store( $duplicate );
|
||||
$duplicate = R::dup( $document );
|
||||
R::store( $duplicate );
|
||||
asrt( R::count( 'planet' ), 1 );
|
||||
asrt( R::count( 'user' ), 1 );
|
||||
asrt( R::count( 'document' ), 3 );
|
||||
asrt( R::count( 'page' ), 3 );
|
||||
asrt( R::count( 'spaceship' ), 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as above but now with intermediate save, counts must be same
|
||||
*/
|
||||
public function testVersioningIntermediateSaves()
|
||||
{
|
||||
$document = R::dispense( 'document' );
|
||||
$page = R::dispense( 'page' );
|
||||
$document->title = 'test';
|
||||
$page->content = 'lorem ipsum';
|
||||
$user = R::dispense( 'user' );
|
||||
$user->name = 'Leo';
|
||||
$document->sharedUser[] = $user;
|
||||
$document->ownPage[] = $page;
|
||||
$document->starship_id = 3;
|
||||
$document->planet = R::dispense( 'planet' );
|
||||
R::store( $document );
|
||||
$duplicate = R::dup( $document );
|
||||
R::store( $document );
|
||||
R::store( $duplicate );
|
||||
R::store( $document );
|
||||
$duplicate = R::dup( $document );
|
||||
R::store( $document );
|
||||
R::store( $duplicate );
|
||||
asrt( R::count( 'planet' ), 1 );
|
||||
asrt( R::count( 'user' ), 1 );
|
||||
asrt( R::count( 'document' ), 3 );
|
||||
asrt( R::count( 'page' ), 3 );
|
||||
asrt( R::count( 'spaceship' ), 0 );
|
||||
// same, but now with intermediate save, counts must be same
|
||||
R::freeze( TRUE );
|
||||
$document = R::dispense( 'document' );
|
||||
$page = R::dispense( 'page' );
|
||||
$document->title = 'test';
|
||||
$page->content = 'lorem ipsum';
|
||||
$user = R::dispense( 'user' );
|
||||
$user->name = 'Leo';
|
||||
$document->sharedUser[] = $user;
|
||||
$document->ownPage[] = $page;
|
||||
$document->starship_id = 3;
|
||||
$document->planet = R::dispense( 'planet' );
|
||||
R::store( $document );
|
||||
$duplicate = R::dup( $document );
|
||||
R::store( $document );
|
||||
R::store( $duplicate );
|
||||
R::store( $document );
|
||||
$duplicate = R::dup( $document );
|
||||
R::store( $document );
|
||||
R::store( $duplicate );
|
||||
asrt( R::count( 'planet' ), 2 );
|
||||
asrt( R::count( 'user' ), 2 );
|
||||
asrt( R::count( 'document' ), 6 );
|
||||
asrt( R::count( 'page' ), 6 );
|
||||
try { asrt( R::count( 'spaceship' ), 0 ); }catch(\Exception $e){pass();}
|
||||
R::freeze( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Recursion
|
||||
*/
|
||||
public function testRecursion()
|
||||
{
|
||||
list( $d1, $d2 ) = R::dispense( 'document', 2 );
|
||||
$page = R::dispense( 'page' );
|
||||
list( $p1, $p2 ) = R::dispense( 'paragraph', 2 );
|
||||
list( $e1, $e2 ) = R::dispense( 'excerpt', 2 );
|
||||
$id2 = R::store( $d2 );
|
||||
$p1->name = 'a';
|
||||
$p2->name = 'b';
|
||||
$page->title = 'my page';
|
||||
$page->ownParagraph = array( $p1, $p2 );
|
||||
$p1->ownExcerpt[] = $e1;
|
||||
$p2->ownExcerpt[] = $e2;
|
||||
$e1->ownDocument[] = $d2;
|
||||
$e2->ownDocument[] = $d1;
|
||||
$d1->ownPage[] = $page;
|
||||
$id1 = R::store( $d1 );
|
||||
$d1 = R::load( 'document', $id1 );
|
||||
$d = R::dup( $d1 );
|
||||
$ids = array();
|
||||
asrt( ( $d instanceof OODBBean ), TRUE );
|
||||
asrt( count( $d->ownPage ), 1 );
|
||||
foreach ( end( $d->ownPage )->ownParagraph as $p ) {
|
||||
foreach ( $p->ownExcerpt as $e ) {
|
||||
$ids[] = end( $e->ownDocument )->id;
|
||||
}
|
||||
}
|
||||
sort( $ids );
|
||||
asrt( (int) $ids[0], 0 );
|
||||
asrt( (int) $ids[1], $id1 );
|
||||
R::store( $d );
|
||||
pass();
|
||||
$phillies = R::dispense( 'diner' );
|
||||
list( $lonelyman, $man, $woman ) = R::dispense( 'guest', 3 );
|
||||
$attendant = R::dispense( 'employee' );
|
||||
$lonelyman->name = 'Bennie Moten';
|
||||
$man->name = 'Daddy Stovepipe';
|
||||
$woman->name = 'Mississippi Sarah';
|
||||
$attendant->name = 'Gus Cannon';
|
||||
$phillies->sharedGuest = array( $lonelyman, $man, $woman );
|
||||
$phillies->ownEmployee[] = $attendant;
|
||||
$props = R::dispense( 'prop', 2 );
|
||||
$props[0]->kind = 'cigarette';
|
||||
$props[1]->kind = 'coffee';
|
||||
$thought = R::dispense( 'thought' );
|
||||
$thought->content = 'Blues';
|
||||
$thought2 = R::dispense( 'thought' );
|
||||
$thought2->content = 'Jazz';
|
||||
$woman->ownProp[] = $props[0];
|
||||
$man->sharedProp[] = $props[1];
|
||||
$attendant->ownThought = array( $thought, $thought2 );
|
||||
R::store( $phillies );
|
||||
$diner = R::findOne( 'diner' );
|
||||
$diner2 = R::dup( $diner );
|
||||
$id2 = R::store( $diner2 );
|
||||
$diner2 = R::load( 'diner', $id2 );
|
||||
asrt( count( $diner->ownEmployee ), 1 );
|
||||
asrt( count( $diner2->ownEmployee ), 1 );
|
||||
asrt( count( $diner->sharedGuest ), 3 );
|
||||
asrt( count( $diner2->sharedGuest ), 3 );
|
||||
$employee = reset( $diner->ownEmployee );
|
||||
asrt( count( $employee->ownThought ), 2 );
|
||||
$employee = reset( $diner2->ownEmployee );
|
||||
asrt( count( $employee->ownThought ), 2 );
|
||||
// Can we change something in the duplicate without changing the original?
|
||||
$employee->name = 'Marvin';
|
||||
$thought = R::dispense( 'thought' );
|
||||
$thought->content = 'depression';
|
||||
$employee->ownThought[] = $thought;
|
||||
array_pop( $diner2->sharedGuest );
|
||||
$guest = reset( $diner2->sharedGuest );
|
||||
$guest->name = 'Arthur Dent';
|
||||
$id2 = R::store( $diner2 );
|
||||
$diner2 = R::load( 'diner', $id2 );
|
||||
asrt( count( $diner->ownEmployee ), 1 );
|
||||
asrt( count( $diner2->ownEmployee ), 1 );
|
||||
asrt( count( $diner->sharedGuest ), 3 );
|
||||
asrt( count( $diner2->sharedGuest ), 2 );
|
||||
$employeeOld = reset( $diner->ownEmployee );
|
||||
asrt( count( $employeeOld->ownThought ), 2 );
|
||||
$employee = reset( $diner2->ownEmployee );
|
||||
asrt( count( $employee->ownThought ), 3 );
|
||||
asrt( $employee->name, 'Marvin' );
|
||||
asrt( $employeeOld->name, 'Gus Cannon' );
|
||||
// However the shared beans must not be copied
|
||||
asrt( R::count( 'guest' ), 3 );
|
||||
asrt( R::count( 'guest_prop' ), 1 );
|
||||
$arthur = R::findOne( 'guest', ' ' . R::getWriter()->esc( 'name' ) . ' = ? ', array( 'Arthur Dent' ) );
|
||||
asrt( $arthur->name, 'Arthur Dent' );
|
||||
}
|
||||
}
|
||||
226
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Count.php
vendored
Normal file
226
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Count.php
vendored
Normal file
@@ -0,0 +1,226 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\RedException as RedException;
|
||||
use RedBeanPHP\RedException\SQL as SQL;
|
||||
use RedBeanPHP\OODBBean;
|
||||
|
||||
/**
|
||||
* Count
|
||||
*
|
||||
* Tests whether we can count beans with or without
|
||||
* additional conditions and whether we can count associated
|
||||
* beans (relationCount).
|
||||
*
|
||||
* @file RedUNIT/Base/Count.php
|
||||
* @desc Tests for simple bean counting.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Count extends Base
|
||||
{
|
||||
/**
|
||||
* Tests type check and conversion in
|
||||
* OODB for count().
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCountType()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$book->sharedPage = R::dispense( 'page', 10 );
|
||||
R::store( $book );
|
||||
asrt( R::count('bookPage'), 10 );
|
||||
try {
|
||||
R::count( 'WrongTypeName' );
|
||||
fail();
|
||||
} catch ( RedException $ex ) {
|
||||
pass();
|
||||
}
|
||||
try {
|
||||
R::count( 'wrong_type_name' );
|
||||
fail();
|
||||
} catch ( RedException $ex ) {
|
||||
pass();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test count and wipe.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCountAndWipe()
|
||||
{
|
||||
testpack( "Test count and wipe" );
|
||||
$page = R::dispense( "page" );
|
||||
$page->name = "ABC";
|
||||
R::store( $page );
|
||||
$n1 = R::count( "page" );
|
||||
$page = R::dispense( "page" );
|
||||
$page->name = "DEF";
|
||||
R::store( $page );
|
||||
$n2 = R::count( "page" );
|
||||
asrt( $n1 + 1, $n2 );
|
||||
R::wipe( "page" );
|
||||
asrt( R::count( "page" ), 0 );
|
||||
asrt( R::getRedBean()->count( "page" ), 0 );
|
||||
asrt( R::getRedBean()->count( "kazoo" ), 0 ); // non existing table
|
||||
R::freeze( TRUE );
|
||||
try {
|
||||
asrt( R::getRedBean()->count( "kazoo" ), 0 ); // non existing table
|
||||
fail();
|
||||
} catch( \Exception $e ) {
|
||||
pass();
|
||||
}
|
||||
R::freeze( FALSE );
|
||||
$page = R::dispense( 'page' );
|
||||
$page->name = 'foo';
|
||||
R::store( $page );
|
||||
$page = R::dispense( 'page' );
|
||||
$page->name = 'bar';
|
||||
R::store( $page );
|
||||
asrt( R::count( 'page', ' name = ? ', array( 'foo' ) ), 1 );
|
||||
// Now count something that does not exist, this should return 0. (just be polite)
|
||||
asrt( R::count( 'teapot', ' name = ? ', array( 'flying' ) ), 0 );
|
||||
asrt( R::count( 'teapot' ), 0 );
|
||||
$currentDriver = $this->currentlyActiveDriverID;
|
||||
// Some drivers don't support that many error codes.
|
||||
if ( $currentDriver === 'mysql' || $currentDriver === 'postgres' ) {
|
||||
try {
|
||||
R::count( 'teaport', ' for tea ' );
|
||||
fail();
|
||||
} catch ( SQL $e ) {
|
||||
pass();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Can we count the number of shared beans?
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCountShared()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$book->sharedPageList = R::dispense( 'page', 5 );
|
||||
R::store( $book );
|
||||
asrt( $book->countShared('page'), 5 );
|
||||
asrt( $book->countShared('leaflet'), 0 );
|
||||
asrt( R::dispense( 'book' )->countShared('page'), 0 );
|
||||
$am = R::getRedBean()->getAssociationManager();
|
||||
asrt( $am->relatedCount( R::dispense( 'book' ), 'page' ), 0);
|
||||
try {
|
||||
$am->relatedCount( 'not a bean', 'type' );
|
||||
fail();
|
||||
} catch( RedException $e ) {
|
||||
pass();
|
||||
}
|
||||
R::getWriter()->setUseCache(TRUE);
|
||||
asrt( $book->countShared('page'), 5 );
|
||||
R::exec('DELETE FROM book_page WHERE book_id > 0 -- keep-cache');
|
||||
asrt( $book->countShared('page'), 5 );
|
||||
R::getWriter()->setUseCache(FALSE);
|
||||
asrt( $book->countShared('page'), 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test $bean->countOwn($type);
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCountOwn()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$empty = R::dispense( 'book' );
|
||||
$nothing = R::dispense( 'book' );
|
||||
$page = R::dispense( 'page' );
|
||||
$book->ownPageList[] = $page;
|
||||
R::store( $book );
|
||||
R::store( $empty );
|
||||
OODBBean::useFluidCount( FALSE );
|
||||
asrt( $book->countOwn('page'), 1 );
|
||||
asrt( $empty->countOwn('page'), 0 );
|
||||
asrt( $nothing->countOwn('page'), 0 );
|
||||
$old = OODBBean::useFluidCount( TRUE );
|
||||
asrt( $old, FALSE );
|
||||
asrt( $book->countOwn('page'), 1 );
|
||||
asrt( $empty->countOwn('page'), 0 );
|
||||
asrt( $nothing->countOwn('page'), 0 );
|
||||
R::freeze( TRUE );
|
||||
asrt( $book->countOwn('page'), 1 );
|
||||
asrt( $empty->countOwn('page'), 0 );
|
||||
asrt( $nothing->countOwn('page'), 0 );
|
||||
R::freeze( FALSE );
|
||||
R::nuke();
|
||||
asrt( $empty->countOwn('page'), 0 );
|
||||
asrt( $nothing->countOwn('page'), 0 );
|
||||
R::freeze( TRUE );
|
||||
asrt( $nothing->countOwn('page'), 0 );
|
||||
try { asrt( $empty->countOwn('page'), 0 ); fail(); } catch(\Exception $e) { pass(); }
|
||||
try { asrt( $book->countOwn('page'), 0 ); fail(); } catch(\Exception $e) { pass(); }
|
||||
R::freeze( FALSE );
|
||||
OODBBean::useFluidCount( FALSE );
|
||||
try { asrt( $empty->countOwn('page'), 0 ); fail(); } catch(\Exception $e) { pass(); }
|
||||
try { asrt( $book->countOwn('page'), 0 ); fail(); } catch(\Exception $e) { pass(); }
|
||||
OODBBean::useFluidCount( TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test $bean->withCondition( ... )->countOwn( $type );
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCountWithCondition()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$book->ownPageList[] = R::dispense( 'page' );
|
||||
R::store( $book );
|
||||
OODBBean::useFluidCount( FALSE );
|
||||
$count = $book
|
||||
->withCondition(' id > :id ', array( ':id' => 0 ) )
|
||||
->countOwn('page');
|
||||
asrt( $count, 1 );
|
||||
$count = $book
|
||||
->withCondition(' id > ? ', array( 0 ) )
|
||||
->countOwn('page');
|
||||
asrt( $count, 1 );
|
||||
$count = $book
|
||||
->withCondition(' id < :id ', array( ':id' => 0 ) )
|
||||
->countOwn('page');
|
||||
asrt( $count, 0 );
|
||||
$count = $book
|
||||
->withCondition(' id < ? ', array( 0 ) )
|
||||
->countOwn('page');
|
||||
asrt( $count, 0 );
|
||||
OODBBean::useFluidCount( TRUE );
|
||||
$count = $book
|
||||
->withCondition(' id > :id ', array( ':id' => 0 ) )
|
||||
->countOwn('page');
|
||||
asrt( $count, 1 );
|
||||
$count = $book
|
||||
->withCondition(' id > ? ', array( 0 ) )
|
||||
->countOwn('page');
|
||||
asrt( $count, 1 );
|
||||
$count = $book
|
||||
->withCondition(' id < :id ', array( ':id' => 0 ) )
|
||||
->countOwn('page');
|
||||
asrt( $count, 0 );
|
||||
$count = $book
|
||||
->withCondition(' id < ? ', array( 0 ) )
|
||||
->countOwn('page');
|
||||
asrt( $count, 0 );
|
||||
}
|
||||
}
|
||||
474
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Cross.php
vendored
Normal file
474
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Cross.php
vendored
Normal file
@@ -0,0 +1,474 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\AssociationManager as AssociationManager;
|
||||
use RedBeanPHP\RedException\SQL as SQL;
|
||||
use RedBeanPHP\RedException as RedException;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
|
||||
/**
|
||||
* Cross
|
||||
*
|
||||
* Tests self referential many-to-many relations, including the
|
||||
* aggr feature.
|
||||
*
|
||||
* @file RedUNIT/Base/Cross.php
|
||||
* @desc Tests associations within the same table (i.e. page_page2 alike)
|
||||
* Cross tables, self referential many-to-many relations
|
||||
* and aggregation techniques
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
|
||||
class Cross extends Base
|
||||
{
|
||||
|
||||
/**
|
||||
* Test how well aggr handles fields with no
|
||||
* values.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAggrNullHandling()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$page = R::dispense( 'page' );
|
||||
$page->name = 'Page 3';
|
||||
$book->xownPageList[] = $page;
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
$texts = $book->aggr( 'ownPageList', 'text' );
|
||||
pass();
|
||||
asrt( count( $texts ), 0 );
|
||||
asrt( is_array( $texts ), TRUE );
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$page1 = R::dispense( 'page' );
|
||||
$page1->name = 'Page 1';
|
||||
$text1 = R::dispense('text');
|
||||
$text1->content = 'Text 1';
|
||||
$page1->text = $text1;
|
||||
$book->xownPageList[] = $page1;
|
||||
$page2 = R::dispense( 'page' );
|
||||
$page2->name = 'Page 2';
|
||||
$text2 = R::dispense( 'text' );
|
||||
$text2->content = 'Text 2';
|
||||
$page2->text = $text2;
|
||||
$book->xownPageList[] = $page2;
|
||||
$page3 = R::dispense( 'page' );
|
||||
$page3->name = 'Page 3';
|
||||
$book->xownPageList[] = $page3;
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
$texts = $book->aggr( 'ownPageList', 'text' );
|
||||
pass();
|
||||
asrt( count( $texts ), 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test many different scenarios with self referential
|
||||
* many-to-many relations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSelfReferentialCRUD()
|
||||
{
|
||||
R::nuke();
|
||||
$buddies = R::dispense( 'buddy', 4 );
|
||||
$buddies[0]->name = 'A';
|
||||
$buddies[1]->name = 'B';
|
||||
$buddies[2]->name = 'C';
|
||||
$buddies[3]->name = 'D';
|
||||
$buddies[0]->sharedBuddyList = array( $buddies[1], $buddies[2] );
|
||||
$buddies[3]->sharedBuddyList = array( $buddies[2] );
|
||||
R::storeAll( $buddies );
|
||||
$buddies[0] = $buddies[0]->fresh();
|
||||
asrt( count( $buddies[0]->sharedBuddyList ), 2 );
|
||||
//does this yield valid combinations - cross relations / self ref n-m
|
||||
//need to symmetric....
|
||||
$names = R::gatherLabels( $buddies[0]->sharedBuddyList );
|
||||
sort( $names );
|
||||
$names = implode( ',', $names );
|
||||
asrt( $names, 'B,C' );
|
||||
unset( $buddies[0]->sharedBuddy );
|
||||
R::storeAll( $buddies );
|
||||
$buddies[0] = $buddies[0]->fresh();
|
||||
asrt( count( $buddies[0]->sharedBuddyList ), 2 );
|
||||
$buddies[3] = $buddies[3]->fresh();
|
||||
asrt( count( $buddies[3]->sharedBuddyList ), 1 );
|
||||
$names = R::gatherLabels( $buddies[3]->sharedBuddyList );
|
||||
sort( $names );
|
||||
$names = implode( ',', $names );
|
||||
asrt( $names, 'C' );
|
||||
$buddies[2] = $buddies[2]->fresh();
|
||||
asrt( count( $buddies[2]->sharedBuddyList ), 2 );
|
||||
$names = R::gatherLabels( $buddies[2]->sharedBuddyList );
|
||||
sort( $names );
|
||||
$names = implode( ',', $names );
|
||||
asrt( $names, 'A,D' );
|
||||
$buddies[1] = $buddies[1]->fresh();
|
||||
asrt( count( $buddies[1]->sharedBuddyList ), 1 );
|
||||
$names = R::gatherLabels( $buddies[1]->sharedBuddyList );
|
||||
sort( $names );
|
||||
$names = implode( ',', $names );
|
||||
asrt( $names, 'A' );
|
||||
//Can we add one?
|
||||
$buddies[1]->sharedBuddyList[] = R::dispense('buddy')->setAttr('name', 'E');
|
||||
R::store( $buddies[1] );
|
||||
$buddies[0] = $buddies[0]->fresh();
|
||||
asrt( count( $buddies[0]->sharedBuddyList ), 2 );
|
||||
$names = R::gatherLabels( $buddies[0]->sharedBuddyList );
|
||||
sort( $names );
|
||||
$names = implode( ',', $names );
|
||||
asrt( $names, 'B,C' );
|
||||
$buddies[1] = $buddies[1]->fresh();
|
||||
asrt( count( $buddies[1]->sharedBuddyList ), 2 );
|
||||
$names = R::gatherLabels( $buddies[1]->sharedBuddyList );
|
||||
sort( $names );
|
||||
$names = implode( ',', $names );
|
||||
asrt( $names, 'A,E' );
|
||||
$all = R::find( 'buddy' );
|
||||
asrt( count( $all ), 5 );
|
||||
foreach( $buddies[1]->sharedBuddy as $buddy ) {
|
||||
if ( $buddy->name === 'E' ) {
|
||||
$buddyE = $buddy;
|
||||
}
|
||||
}
|
||||
asrt( isset( $buddyE ), TRUE );
|
||||
asrt( $buddyE->name, 'E' );
|
||||
//can we update?
|
||||
foreach( $buddies[0]->sharedBuddy as $buddy ) {
|
||||
if ( $buddy->name === 'C' ) {
|
||||
$buddy->name = 'C2';
|
||||
}
|
||||
}
|
||||
R::store( $buddies[0] );
|
||||
$buddies[0] = $buddies[0]->fresh();
|
||||
asrt( count( $buddies[0]->sharedBuddyList ), 2 );
|
||||
$names = R::gatherLabels( $buddies[0]->sharedBuddyList );
|
||||
sort( $names );
|
||||
$names = implode( ',', $names );
|
||||
asrt( $names, 'B,C2' );
|
||||
$buddies[2] = $buddies[2]->fresh();
|
||||
asrt( count( $buddies[2]->sharedBuddyList ), 2 );
|
||||
$names = R::gatherLabels( $buddies[2]->sharedBuddyList );
|
||||
sort( $names );
|
||||
$names = implode( ',', $names );
|
||||
asrt( $names, 'A,D' );
|
||||
//can we delete?
|
||||
foreach( $buddies[0]->sharedBuddyList as $id => $buddy ) {
|
||||
if ( $buddy->name === 'B' ) {
|
||||
unset( $buddies[0]->sharedBuddyList[$id] );
|
||||
}
|
||||
}
|
||||
R::store( $buddies[0] );
|
||||
$buddies[0] = $buddies[0]->fresh();
|
||||
asrt( count( $buddies[0]->sharedBuddyList ), 1 );
|
||||
$names = R::gatherLabels( $buddies[0]->sharedBuddyList );
|
||||
sort( $names );
|
||||
$names = implode( ',', $names );
|
||||
asrt( $names, 'C2' );
|
||||
$buddies[1] = $buddies[1]->fresh();
|
||||
asrt( count( $buddies[1]->sharedBuddyList ), 1 );
|
||||
$names = R::gatherLabels( $buddies[1]->sharedBuddyList );
|
||||
sort( $names );
|
||||
$names = implode( ',', $names );
|
||||
asrt( $names, 'E' );
|
||||
asrt( R::count( 'buddy' ), 5 );
|
||||
asrt( R::count( 'buddyBuddy' ), 3 );
|
||||
$buddies[3] = $buddies[3]->fresh();
|
||||
asrt( count( $buddies[3]->sharedBuddyList ), 1 );
|
||||
$names = R::gatherLabels( $buddies[3]->sharedBuddyList );
|
||||
sort( $names );
|
||||
$names = implode( ',', $names );
|
||||
asrt( $names, 'C2' );
|
||||
$buddies[2] = $buddies[2]->fresh();
|
||||
asrt( count( $buddies[2]->sharedBuddyList ), 2 );
|
||||
$names = R::gatherLabels( $buddies[2]->sharedBuddyList );
|
||||
sort( $names );
|
||||
$names = implode( ',', $names );
|
||||
asrt( $names, 'A,D' );
|
||||
$buddyE = $buddyE->fresh();
|
||||
asrt( count( $buddyE->sharedBuddyList ), 1 );
|
||||
$names = R::gatherLabels( $buddyE->sharedBuddyList );
|
||||
sort( $names );
|
||||
$names = implode( ',', $names );
|
||||
asrt( $names, 'B' );
|
||||
if ( $this->currentlyActiveDriverID === 'mysql' ) {
|
||||
$buddyE = $buddyE->fresh();
|
||||
asrt( count( $buddyE->with(' HAVING linked_by > 0 ')->sharedBuddyList ), 1 );
|
||||
$buddyE = $buddyE->fresh();
|
||||
asrt( count( $buddyE->with(' HAVING linked_by < 0 ')->sharedBuddyList ), 0 );
|
||||
}
|
||||
if ( $this->currentlyActiveDriverID === 'sqlite' ) {
|
||||
$buddyE = $buddyE->fresh();
|
||||
asrt( count( $buddyE->withCondition(' linked_by > 0 ')->sharedBuddyList ), 1 );
|
||||
$buddyE = $buddyE->fresh();
|
||||
asrt( count( $buddyE->withCondition(' linked_by < 0 ')->sharedBuddyList ), 0 );
|
||||
}
|
||||
$buddyE = $buddyE->fresh();
|
||||
asrt( count( $buddyE->withCondition(' buddy_buddy.buddy_id > 0 AND buddy_buddy.buddy2_id > 0 ')->sharedBuddyList ), 1 );
|
||||
$buddyE = $buddyE->fresh();
|
||||
asrt( count( $buddyE->withCondition(' buddy_buddy.buddy_id < 0 AND buddy_buddy.buddy2_id < 0 ')->sharedBuddyList ), 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test self referential N-M relations (page_page).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSelfReferential()
|
||||
{
|
||||
$page = R::dispense( 'page' )->setAttr( 'title', 'a' );
|
||||
$page->sharedPage[] = R::dispense( 'page' )->setAttr( 'title', 'b' );
|
||||
R::store( $page );
|
||||
$page = $page->fresh();
|
||||
$page = reset( $page->sharedPage );
|
||||
asrt( $page->title, 'b' );
|
||||
$tables = array_flip( R::inspect() );
|
||||
asrt( isset( $tables['page_page'] ), TRUE );
|
||||
$columns = R::inspect( 'page_page' );
|
||||
asrt( isset( $columns['page2_id'] ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the unique constraint.
|
||||
* Just want to make sure it is not too limiting and functions
|
||||
* properly for typical RedBeanPHP usage.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testUnique()
|
||||
{
|
||||
R::nuke();
|
||||
$page1 = R::dispense( 'page' );
|
||||
$tag1 = R::dispense( 'tag' );
|
||||
$page2 = R::dispense( 'page' );
|
||||
$tag2 = R::dispense( 'tag' );
|
||||
$page3 = R::dispense( 'page' );
|
||||
$tag3 = R::dispense( 'tag' );
|
||||
$page1->sharedTag[] = $tag1;
|
||||
R::store( $page1 );
|
||||
//can we save all combinations with unique?
|
||||
asrt( R::count( 'pageTag' ), 1);
|
||||
$page1->sharedTag[] = $tag2;
|
||||
R::store( $page1 );
|
||||
asrt( R::count( 'pageTag' ), 2 );
|
||||
$page1->sharedTag[] = $tag3;
|
||||
$page2->sharedTag[] = $tag1;
|
||||
$page2->sharedTag[] = $tag2;
|
||||
$page2->sharedTag[] = $tag3;
|
||||
$page3->sharedTag[] = $tag1;
|
||||
$page3->sharedTag[] = $tag2;
|
||||
$page3->sharedTag[] = $tag3;
|
||||
R::storeAll( array( $page1, $page2, $page3 ) );
|
||||
asrt( R::count('pageTag'), 9 );
|
||||
$page1 = $page1->fresh();
|
||||
$page1->sharedTag[] = $tag3;
|
||||
R::store( $page1 );
|
||||
//cant add violates unique
|
||||
asrt( R::count( 'pageTag' ), 9 );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 aggr without the aliasing.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAggrBasic()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$page1 = R::dispense( 'page' );
|
||||
$page1->name = 'Page 1';
|
||||
$text1 = R::dispense('text');
|
||||
$text1->content = 'Text 1';
|
||||
$page1->text = $text1;
|
||||
$book->xownPageList[] = $page1;
|
||||
$page2 = R::dispense( 'page' );
|
||||
$page2->name = 'Page 2';
|
||||
$text2 = R::dispense( 'text' );
|
||||
$text2->content = 'Text 2';
|
||||
$page2->text = $text2;
|
||||
$book->xownPageList[] = $page2;
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
$texts = $book->aggr( 'ownPageList', 'text' );
|
||||
R::nuke();
|
||||
asrt( count( $texts ), 2 );
|
||||
foreach( $texts as $text ) {
|
||||
asrt( ( $text instanceof OODBBean ), TRUE );
|
||||
}
|
||||
$pages = $book->ownPageList;
|
||||
asrt( count( $pages ), 2 );
|
||||
asrt( R::count( 'page' ), 0 );
|
||||
foreach( $pages as $page ) {
|
||||
asrt( ( $page instanceof OODBBean ), TRUE );
|
||||
$text = $page->text;
|
||||
asrt( ( $text instanceof OODBBean ), TRUE );
|
||||
$text->content = 'CHANGED';
|
||||
}
|
||||
foreach( $texts as $text ) {
|
||||
asrt( $text->content, 'CHANGED' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test aggr with basic aliasing.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAggrWithOnlyAlias()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$page1 = R::dispense( 'page' );
|
||||
$page1->name = 'Page 1';
|
||||
$text1 = R::dispense( 'text' );
|
||||
$text1->content = 'Text 1';
|
||||
$page1->content = $text1;
|
||||
$book->xownPageList[] = $page1;
|
||||
$page2 = R::dispense( 'page' );
|
||||
$page2->name = 'Page 2';
|
||||
$text2 = R::dispense( 'text' );
|
||||
$text2->content = 'Text 2';
|
||||
$page2->content = $text2;
|
||||
$book->xownPageList[] = $page2;
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
$texts = $book->aggr( 'ownPageList', 'content', 'text' );
|
||||
R::nuke();
|
||||
asrt( count( $texts ), 2 );
|
||||
foreach( $texts as $text ) {
|
||||
asrt( ( $text instanceof OODBBean), TRUE );
|
||||
}
|
||||
$pages = $book->ownPageList;
|
||||
asrt( count( $pages ), 2 );
|
||||
asrt( R::count( 'page' ), 0 );
|
||||
foreach( $pages as $page ) {
|
||||
asrt( ( $page instanceof OODBBean ), TRUE );
|
||||
$text = $page->content;
|
||||
asrt( ( $text instanceof OODBBean ), TRUE );
|
||||
$text->content = 'CHANGED';
|
||||
}
|
||||
foreach( $texts as $text ) {
|
||||
asrt( $text->content, 'CHANGED' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The aggr method can only be used with own-list.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testErrorHandlingAggr()
|
||||
{
|
||||
$wrongLists = array( 'not-an-own-list', 'OWNlist', 'Ownpage', 'ownbook', 'own book', '!', 'sharedBook' );
|
||||
foreach( $wrongLists as $wrongList ) {
|
||||
$bean = R::dispense( 'bean' );
|
||||
try {
|
||||
$bean->aggr( $wrongList, 'field' );
|
||||
fail();
|
||||
} catch ( \Exception $exception ) {
|
||||
pass();
|
||||
asrt( ( $exception instanceof RedException ), TRUE );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
160
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Cursors.php
vendored
Normal file
160
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Cursors.php
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
use RedBeanPHP\QueryWriter;
|
||||
use RedBeanPHP\QueryWriter\AQueryWriter;
|
||||
|
||||
/**
|
||||
* Cursors
|
||||
*
|
||||
* Tests whether RedBeanPHP can use cursors (using the
|
||||
* findCollection method) to iterate over large data sets.
|
||||
*
|
||||
* @file RedUNIT/Base/Cursors.php
|
||||
* @desc Tests whether we can use cursors
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Cursors extends Base
|
||||
{
|
||||
/**
|
||||
* Test whether we can use cursors with raw SQL
|
||||
* from the facade (#656).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSQLCursors()
|
||||
{
|
||||
R::nuke();
|
||||
for( $i=0; $i<20; $i++ ) {
|
||||
$page = R::dispense( 'page' );
|
||||
$page->number = $i;
|
||||
$page->content = sha1( $i );
|
||||
R::store( $page );
|
||||
}
|
||||
$cursor = R::getCursor( 'SELECT * FROM page ORDER BY page.number ASC' );
|
||||
asrt( get_class( $cursor ), 'RedBeanPHP\Cursor\PDOCursor');
|
||||
$i = 0;
|
||||
$list = array();
|
||||
while( $row = $cursor->getNextItem() ) {
|
||||
asrt( is_array( $row ), TRUE );
|
||||
asrt( (string) $row['number'], strval( $i ) );
|
||||
asrt( $row['content'], sha1( $i ) );
|
||||
$list[] = $row['content'];
|
||||
$i ++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic cursor functionality.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBasicCursors()
|
||||
{
|
||||
R::nuke();
|
||||
for( $i=0; $i<20; $i++ ) {
|
||||
$page = R::dispense( 'page' );
|
||||
$page->number = $i;
|
||||
$page->content = sha1( $i );
|
||||
R::store( $page );
|
||||
}
|
||||
$collection = R::findCollection( 'page', 'ORDER BY page.number ASC' );
|
||||
asrt( get_class( $collection ), 'RedBeanPHP\BeanCollection');
|
||||
$i = 0;
|
||||
$list = array();
|
||||
while( $bean = $collection->next() ) {
|
||||
asrt( ( $bean instanceof OODBBean ), TRUE );
|
||||
asrt( (string) $bean->number, strval( $i ) );
|
||||
asrt( $bean->content, sha1( $i ) );
|
||||
$list[] = $bean->content;
|
||||
$i ++;
|
||||
}
|
||||
$collection->reset();
|
||||
$i = 0;
|
||||
while( $bean = $collection->next() ) {
|
||||
asrt( ( $bean instanceof OODBBean ), TRUE );
|
||||
asrt( (string) $bean->number, strval( $i ) );
|
||||
asrt( $bean->content, sha1( $i ) );
|
||||
$i ++;
|
||||
}
|
||||
$collection = R::findCollection( 'page', ' ORDER BY content ASC ' );
|
||||
sort( $list );
|
||||
$i = 0;
|
||||
while( $bean = $collection->next() ) {
|
||||
asrt( $bean->content, $list[$i] );
|
||||
$i ++;
|
||||
}
|
||||
$collection = R::findCollection( 'page', ' ORDER BY content ASC LIMIT 5 ' );
|
||||
sort( $list );
|
||||
$i = 0;
|
||||
while( $bean = $collection->next() ) {
|
||||
asrt( $bean->content, $list[$i] );
|
||||
$i ++;
|
||||
if ( $i > 5 ) break;
|
||||
}
|
||||
$key = array_rand( $list );
|
||||
$content = $list[ $key ];
|
||||
$collection = R::findCollection( 'page', ' content = ? ', array( $content ) );
|
||||
$bean = $collection->next();
|
||||
asrt( $bean->content, $content );
|
||||
$collection->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Can we use a filtered cursor?
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCursorWithFilter()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$book->title = 'Title';
|
||||
R::store( $book );
|
||||
$filter = array(
|
||||
QueryWriter::C_SQLFILTER_READ => array(
|
||||
'book' => array('title' => ' LOWER(book.title) ' )
|
||||
)
|
||||
);
|
||||
AQueryWriter::setSQLFilters( $filter );
|
||||
$books = R::findCollection( 'book' );
|
||||
$book = $books->next();
|
||||
asrt( $book->title, 'title' );
|
||||
AQueryWriter::setSQLFilters( array() );
|
||||
$books = R::findCollection( 'book' );
|
||||
$book = $books->next();
|
||||
asrt( $book->title, 'Title' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test empty collections (NULLCursor).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testEmptyCollection()
|
||||
{
|
||||
R::nuke();
|
||||
$page = R::dispense( 'page' );
|
||||
$page->content = 'aaa';
|
||||
R::store( $page );
|
||||
$collection = R::findCollection( 'page' );
|
||||
asrt( get_class( $collection ), 'RedBeanPHP\BeanCollection');
|
||||
$collection = R::findCollection( 'page', ' content = ?', array( 'bbb' ) );
|
||||
asrt( get_class( $collection ), 'RedBeanPHP\BeanCollection');
|
||||
asrt( is_null( $collection->next() ), TRUE );
|
||||
$collection = R::findCollection( 'something' );
|
||||
asrt( get_class( $collection ), 'RedBeanPHP\BeanCollection');
|
||||
asrt( is_null( $collection->next() ), TRUE );
|
||||
asrt( is_null( $collection->reset() ), TRUE );
|
||||
$collection->close();
|
||||
}
|
||||
}
|
||||
461
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Database.php
vendored
Normal file
461
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Database.php
vendored
Normal file
@@ -0,0 +1,461 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\QueryWriter\SQLiteT as SQLiteT;
|
||||
use RedBeanPHP\OODB as OODB;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
use RedBeanPHP\ToolBox as ToolBox;
|
||||
use RedBeanPHP\AssociationManager as AssociationManager;
|
||||
use RedBeanPHP\RedException as RedException;
|
||||
use RedBeanPHP\RedException\SQL as SQL;
|
||||
use RedBeanPHP\QueryWriter\MySQL as MySQL;
|
||||
use RedBeanPHP\QueryWriter\PostgreSQL as PostgreSQL;
|
||||
use RedBeanPHP\QueryWriter\CUBRID as CUBRID;
|
||||
use RedBeanPHP\Adapter\DBAdapter as DBAdapter;
|
||||
|
||||
/**
|
||||
* Database
|
||||
*
|
||||
* Tests basic RedBeanPHP database functionality.
|
||||
*
|
||||
* @file RedUNIT/Base/Database.php
|
||||
* @desc Tests basic database behaviors
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Database extends Base
|
||||
{
|
||||
/**
|
||||
* What drivers should be loaded for this test pack?
|
||||
*/
|
||||
public function getTargetDrivers()
|
||||
{
|
||||
return array( 'mysql', 'pgsql', 'sqlite', 'CUBRID' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Can we use meta mask with find() ?
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSelectFindOne()
|
||||
{
|
||||
R::store(R::dispense('book'));
|
||||
R::store(R::dispense('book'));
|
||||
if ($this->currentlyActiveDriverID == 'pgsql') {
|
||||
R::getWriter()->setSQLFilters(array('r'=>array('book'=>array('__meta_total'=>'COUNT(*) OVER()'))), FALSE);
|
||||
} else {
|
||||
R::getWriter()->setSQLFilters(array('r'=>array('book'=>array('__meta_total'=>'2'))), FALSE);
|
||||
}
|
||||
$books = R::find('book', 'LIMIT 1');
|
||||
$book = reset($books);
|
||||
$bundle = $book->getMeta('data.bundle');
|
||||
asrt(intval($bundle['__meta_total']),2);
|
||||
R::getWriter()->setSQLFilters(array(), FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether we cannot just bind function names but
|
||||
* also function templates, i.e. little SQL snippets.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBindFuncFunctionTemplates()
|
||||
{
|
||||
R::bindFunc('read', 'xbean.lucky', '111 * %s', TRUE);
|
||||
$bean = R::dispense('xbean');
|
||||
$bean->lucky = 7;
|
||||
$id = R::store( $bean );
|
||||
$bean = R::load( 'xbean', $id );
|
||||
asrt( intval($bean->lucky), 777 );
|
||||
R::bindFunc('write', 'xbean.triple', '3 * %s', TRUE);
|
||||
$bean->triple = 3;
|
||||
R::store($bean);
|
||||
$bean = $bean->fresh();
|
||||
asrt( intval($bean->triple), 9);
|
||||
R::bindFunc('read', 'xbean.lucky', NULL);
|
||||
R::bindFunc('write', 'xbean.triple', NULL);
|
||||
R::getRedBean()->clearAllFuncBindings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make ConvertToBean work together with getRow #759.
|
||||
* When no results are found for getRow it returns []
|
||||
* Then when you give that to convertToBean it wraps your
|
||||
* single row into an array of multiple rows, so you get [[]].
|
||||
* Then this loop has something to
|
||||
* iterate on foreach ( $rows as $row ) { ...
|
||||
* And then it crashes on: $id = $row['id'];
|
||||
*/
|
||||
public function testHarmonizeConvertToBeanAndGetRow()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::convertToBean( 'book', R::getRow( 'SELECT * FROM book' ) );
|
||||
asrt( is_null( $book ), TRUE );
|
||||
$book = R::convertToBean( 'book', array() );
|
||||
asrt( is_null( $book ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for bugfix:
|
||||
* adhere to return type specification for R::getRow #728
|
||||
* public static function getRow is documented as a function
|
||||
* that returns an array. However, in a situation
|
||||
* where the resultset is empty, this returns a boolean
|
||||
* and causes an unexpected failure in
|
||||
* code like this because it is expecting an array.
|
||||
*/
|
||||
public function testReturnTypeGetRow()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
R::store( $book );
|
||||
$row = R::getRow('SELECT * FROM book');
|
||||
asrt( is_array( $row ), TRUE );
|
||||
R::trash( $book );
|
||||
$row = R::getRow('SELECT * FROM book');
|
||||
asrt( is_array( $row ), TRUE );
|
||||
R::nuke();
|
||||
$row = R::getRow('SELECT * FROM book');
|
||||
asrt( is_array( $row ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the (protected) database capability checker method
|
||||
* of the RedBeanPHP PDO driver (RPDO).
|
||||
*/
|
||||
public function testDatabaseCapabilityChecker()
|
||||
{
|
||||
$capChecker = new \DatabaseCapabilityChecker( R::getDatabaseAdapter()->getDatabase()->getPDO() );
|
||||
$result = $capChecker->checkCapability('creativity');
|
||||
asrt( $result, FALSE ); /* nope, no strong AI yet.. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether we can obtain the PDO object from the
|
||||
* database driver for custom database operations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGetPDO()
|
||||
{
|
||||
$driver = R::getDatabaseAdapter();
|
||||
asrt( ( $driver instanceof DBAdapter), TRUE );
|
||||
$pdo = $driver->getDatabase()->getPDO();
|
||||
asrt( ( $pdo instanceof \PDO ), TRUE );
|
||||
$pdo2 = R::getPDO();
|
||||
asrt( ( $pdo2 instanceof \PDO ), TRUE );
|
||||
asrt( ( $pdo === $pdo2 ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setter maximum integer bindings.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSetMaxBind()
|
||||
{
|
||||
$driver = R::getDatabaseAdapter()->getDatabase();
|
||||
$old = $driver->setMaxIntBind( 10 );
|
||||
//use SQLite to confirm...
|
||||
if ( $this->currentlyActiveDriverID === 'sqlite' ) {
|
||||
$type = R::getCell( 'SELECT typeof( ? ) ', array( 11 ) );
|
||||
asrt( $type, 'text' );
|
||||
$type = R::getCell( 'SELECT typeof( ? ) ', array( 10 ) );
|
||||
asrt( $type, 'integer' );
|
||||
$type = R::getCell( 'SELECT typeof( ? ) ', array( 9 ) );
|
||||
asrt( $type, 'integer' );
|
||||
}
|
||||
$new = $driver->setMaxIntBind( $old );
|
||||
asrt( $new, 10 );
|
||||
try {
|
||||
$driver->setMaxIntBind( '10' );
|
||||
fail();
|
||||
} catch( RedException $e ) {
|
||||
pass();
|
||||
}
|
||||
$new = $driver->setMaxIntBind( $old );
|
||||
asrt( $new, $old );
|
||||
$new = $driver->setMaxIntBind( $old );
|
||||
asrt( $new, $old );
|
||||
}
|
||||
|
||||
/**
|
||||
* Can we use colons in SQL?
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testColonsInSQL()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$book->title = 'About :';
|
||||
R::store( $book );
|
||||
pass();
|
||||
$book = R::findOne( 'book', ' title LIKE :this ', array(
|
||||
':this' => 'About :'
|
||||
) );
|
||||
asrt( ( $book instanceof OODBBean ), TRUE );
|
||||
//without the colon?
|
||||
$book = R::findOne( 'book', ' title LIKE :this ', array(
|
||||
'this' => 'About :'
|
||||
) );
|
||||
asrt( ( $book instanceof OODBBean ), TRUE );
|
||||
$book = R::findOne( 'book', ' title LIKE :this ', array(
|
||||
':this' => '%:%'
|
||||
) );
|
||||
asrt( ( $book instanceof OODBBean ), TRUE );
|
||||
$book = R::findOne( 'book', ' title LIKE :this OR title LIKE :that', array(
|
||||
'this' => '%:%', ':that' => 'That'
|
||||
) );
|
||||
asrt( ( $book instanceof OODBBean ), TRUE );
|
||||
$records = R::getAll('SELECT * FROM book WHERE title LIKE :this', array( ':this' => 'About :' ) );
|
||||
asrt( count( $records ), 1 );
|
||||
$records = R::getAll('SELECT * FROM book WHERE title LIKE :this', array( 'this' => 'About :' ) );
|
||||
asrt( count( $records ), 1 );
|
||||
$records = R::getAll('SELECT * FROM book WHERE title LIKE :this OR title LIKE :that', array( ':this' => 'About :', ':that' => 'That' ) );
|
||||
asrt( count( $records ), 1 );
|
||||
$records = R::getRow('SELECT * FROM book WHERE title LIKE :this', array( ':this' => 'About :' ) );
|
||||
asrt( count( $records ), 2 );
|
||||
$records = R::getRow('SELECT * FROM book WHERE title LIKE :this', array( 'this' => 'About :' ) );
|
||||
asrt( count( $records ), 2 );
|
||||
$records = R::getRow('SELECT * FROM book WHERE title LIKE :this OR title LIKE :that', array( ':this' => 'About :', ':that' => 'That' ) );
|
||||
asrt( count( $records ), 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setting direct PDO.
|
||||
* Not much to test actually.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDirectPDO()
|
||||
{
|
||||
$pdo = R::getDatabaseAdapter()->getDatabase()->getPDO();
|
||||
R::getDatabaseAdapter()->getDatabase()->setPDO( $pdo );
|
||||
pass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for testConnection() method.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testConnectionTester()
|
||||
{
|
||||
asrt( R::testConnection(), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the various ways to fetch (select queries)
|
||||
* data using adapter methods in the facade.
|
||||
* Also tests the new R::getAssocRow() method,
|
||||
* as requested in issue #324.
|
||||
*/
|
||||
public function testFetchTypes()
|
||||
{
|
||||
R::nuke();
|
||||
$page = R::dispense( 'page' );
|
||||
$page->a = 'a';
|
||||
$page->b = 'b';
|
||||
R::store( $page );
|
||||
$page = R::dispense( 'page' );
|
||||
$page->a = 'c';
|
||||
$page->b = 'd';
|
||||
R::store( $page );
|
||||
$expect = '[{"id":"1","a":"a","b":"b"},{"id":"2","a":"c","b":"d"}]';
|
||||
asrt( json_encode( R::getAll( 'SELECT * FROM page' ) ), $expect );
|
||||
$expect = '{"1":"a","2":"c"}';
|
||||
asrt( json_encode( R::getAssoc( 'SELECT id, a FROM page' ) ), $expect );
|
||||
$expect = '{"1":{"a":"a","b":"b"},"2":{"a":"c","b":"d"}}';
|
||||
asrt( json_encode( R::getAssoc( 'SELECT id, a, b FROM page' ) ), $expect );
|
||||
$expect = '[{"id":"1","a":"a"},{"id":"2","a":"c"}]';
|
||||
asrt( json_encode( R::getAssocRow( 'SELECT id, a FROM page' ) ), $expect );
|
||||
$expect = '[{"id":"1","a":"a","b":"b"},{"id":"2","a":"c","b":"d"}]';
|
||||
asrt( json_encode( R::getAssocRow( 'SELECT id, a, b FROM page' ) ), $expect );
|
||||
$expect = '{"id":"1","a":"a","b":"b"}';
|
||||
asrt( json_encode( R::getRow( 'SELECT * FROM page WHERE id = 1' ) ), $expect );
|
||||
$expect = '"a"';
|
||||
asrt( json_encode( R::getCell( 'SELECT a FROM page WHERE id = 1' ) ), $expect );
|
||||
$expect = '"b"';
|
||||
asrt( json_encode( R::getCell( 'SELECT b FROM page WHERE id = 1') ), $expect );
|
||||
$expect = '"c"';
|
||||
asrt( json_encode( R::getCell('SELECT a FROM page WHERE id = 2') ), $expect );
|
||||
$expect = '["a","c"]';
|
||||
asrt( json_encode( R::getCol( 'SELECT a FROM page' ) ), $expect );
|
||||
$expect = '["b","d"]';
|
||||
asrt( json_encode( R::getCol('SELECT b FROM page') ), $expect );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether we can store an empty bean.
|
||||
* An empty bean has no properties, only ID. Normally we would
|
||||
* skip the ID field in an INSERT, this test forces the driver
|
||||
* to specify a value for the ID field. Different writers have to
|
||||
* use different values: Mysql uses NULL to insert a new auto-generated ID,
|
||||
* while Postgres has to use DEFAULT.
|
||||
*/
|
||||
public function testEmptyBean()
|
||||
{
|
||||
testpack( 'Test Empty Bean Storage.' );
|
||||
R::nuke();
|
||||
$bean = R::dispense( 'emptybean' );
|
||||
$id = R::store( $bean );
|
||||
asrt( ( $id > 0 ), TRUE );
|
||||
asrt( R::count( 'emptybean' ), 1 );
|
||||
$bean = R::dispense( 'emptybean' );
|
||||
$id = R::store( $bean );
|
||||
asrt( ( $id > 0 ), TRUE );
|
||||
asrt( R::count( 'emptybean' ), 2 );
|
||||
//also test in frozen mode
|
||||
R::freeze( TRUE );
|
||||
$bean = R::dispense( 'emptybean' );
|
||||
$id = R::store( $bean );
|
||||
asrt( ( $id > 0 ), TRUE );
|
||||
asrt( R::count( 'emptybean' ), 3 );
|
||||
R::freeze( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the database driver and low level functions.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDriver()
|
||||
{
|
||||
$currentDriver = $this->currentlyActiveDriverID;
|
||||
R::store( R::dispense( 'justabean' ) );
|
||||
$adapter = new TroubleDapter( R::getToolBox()->getDatabaseAdapter()->getDatabase() );
|
||||
$adapter->setSQLState( 'HY000' );
|
||||
$writer = new SQLiteT( $adapter );
|
||||
$redbean = new OODB( $writer );
|
||||
$toolbox = new ToolBox( $redbean, $adapter, $writer );
|
||||
// We can only test this for a known driver...
|
||||
if ( $currentDriver === 'sqlite' ) {
|
||||
try {
|
||||
$redbean->find( 'bean' );
|
||||
pass();
|
||||
} catch (\Exception $e ) {
|
||||
var_dump( $e->getSQLState() );
|
||||
fail();
|
||||
}
|
||||
}
|
||||
$adapter->setSQLState( -999 );
|
||||
try {
|
||||
$redbean->find( 'bean' );
|
||||
fail();
|
||||
} catch (\Exception $e ) {
|
||||
pass();
|
||||
}
|
||||
try {
|
||||
$redbean->wipe( 'justabean' );
|
||||
fail();
|
||||
} catch (\Exception $e ) {
|
||||
pass();
|
||||
}
|
||||
$toolbox = R::getToolBox();
|
||||
$adapter = $toolbox->getDatabaseAdapter();
|
||||
$writer = $toolbox->getWriter();
|
||||
$redbean = $toolbox->getRedBean();
|
||||
$pdo = $adapter->getDatabase();
|
||||
$page = $redbean->dispense( "page" );
|
||||
try {
|
||||
$adapter->exec( "an invalid query" );
|
||||
fail();
|
||||
} catch ( SQL $e ) {
|
||||
pass();
|
||||
}
|
||||
// Special data type description should result in magic number 99 (specified)
|
||||
if ( $currentDriver == 'mysql' ) {
|
||||
asrt( $writer->code( MySQL::C_DATATYPE_SPECIAL_DATE ), 99 );
|
||||
}
|
||||
if ( $currentDriver == 'pgsql' ) {
|
||||
asrt( $writer->code( PostgreSQL::C_DATATYPE_SPECIAL_DATE ), 99 );
|
||||
}
|
||||
if ( $currentDriver == 'CUBRID' ) {
|
||||
asrt( $writer->code( CUBRID::C_DATATYPE_SPECIAL_DATE ), 99 );
|
||||
}
|
||||
asrt( (int) $adapter->getCell( "SELECT 123" ), 123 );
|
||||
$page->aname = "my page";
|
||||
$id = (int) $redbean->store( $page );
|
||||
asrt( (int) $page->id, 1 );
|
||||
asrt( (int) $pdo->GetCell( "SELECT count(*) FROM page" ), 1 );
|
||||
asrt( $pdo->GetCell( "SELECT aname FROM page LIMIT 1" ), "my page" );
|
||||
asrt( (int) $id, 1 );
|
||||
$page = $redbean->load( "page", 1 );
|
||||
asrt( $page->aname, "my page" );
|
||||
asrt( ( (bool) $page->getMeta( "type" ) ), TRUE );
|
||||
asrt( isset( $page->id ), TRUE );
|
||||
asrt( ( $page->getMeta( "type" ) ), "page" );
|
||||
asrt( (int) $page->id, $id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test selecting.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSelects()
|
||||
{
|
||||
$rooms = R::dispense( 'room', 2 );
|
||||
$rooms[0]->kind = 'suite';
|
||||
$rooms[1]->kind = 'classic';
|
||||
$rooms[0]->number = 6;
|
||||
$rooms[1]->number = 7;
|
||||
R::store( $rooms[0] );
|
||||
R::store( $rooms[1] );
|
||||
$rooms = R::getAssoc('SELECT * FROM room WHERE id < -999');
|
||||
asrt(is_array($rooms), TRUE);
|
||||
asrt(count($rooms), 0);
|
||||
$rooms = R::getAssoc( 'SELECT ' . R::getWriter()->esc( 'number' ) . ', kind FROM room ORDER BY kind ASC' );
|
||||
foreach ( $rooms as $key => $room ) {
|
||||
asrt( ( $key === 6 || $key === 7 ), TRUE );
|
||||
asrt( ( $room == 'classic' || $room == 'suite' ), TRUE );
|
||||
}
|
||||
$rooms = R::getDatabaseAdapter()->getAssoc( 'SELECT kind FROM room' );
|
||||
foreach ( $rooms as $key => $room ) {
|
||||
asrt( ( $room == 'classic' || $room == 'suite' ), TRUE );
|
||||
asrt( $room, $key );
|
||||
}
|
||||
$rooms = R::getAssoc( 'SELECT `number`, kind FROM rooms2 ORDER BY kind ASC' );
|
||||
asrt( count( $rooms ), 0 );
|
||||
asrt( is_array( $rooms ), TRUE );
|
||||
// GetCell should return NULL in case of exception
|
||||
asrt( NULL, R::getCell( 'SELECT dream FROM fantasy' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Malfunctioning database adapter to test exceptions.
|
||||
*/
|
||||
class TroubleDapter extends DBAdapter
|
||||
{
|
||||
private $sqlState;
|
||||
public function setSQLState( $sqlState )
|
||||
{
|
||||
$this->sqlState = $sqlState;
|
||||
}
|
||||
public function get( $sql, $values = array() )
|
||||
{
|
||||
$exception = new SQL( 'Just a trouble maker' );
|
||||
$exception->setSQLState( $this->sqlState );
|
||||
$exception->setDriverDetails( array(0,1,0) );
|
||||
throw $exception;
|
||||
}
|
||||
public function getRow( $sql, $aValues = array() )
|
||||
{
|
||||
$this->get( $sql, $aValues );
|
||||
}
|
||||
public function exec( $sql, $aValues = array(), $noEvent = FALSE )
|
||||
{
|
||||
$this->get( $sql, $aValues );
|
||||
}
|
||||
}
|
||||
|
||||
182
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Dispense.php
vendored
Normal file
182
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Dispense.php
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\RedException as RedException;
|
||||
use RedBeanPHP\Facade as Facade;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
use RedBeanPHP\Util\DispenseHelper as DispenseHelper;
|
||||
|
||||
/**
|
||||
* Dispense
|
||||
*
|
||||
* Tests whether we can dispense beans and tests all
|
||||
* features of the dispense/dispenseAll functions.
|
||||
*
|
||||
* @file RedUNIT/Base/Dispense.php
|
||||
* @desc Tests bean dispensing functionality.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Dispense extends Base
|
||||
{
|
||||
/**
|
||||
* Test whether findOrDispense and findOneOrDispense
|
||||
* will trigger same validation Exception for invalid
|
||||
* bean types as R::dispense(). Github issue #546.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIssue546()
|
||||
{
|
||||
try {
|
||||
R::findOrDispense( 'invalid_type' );
|
||||
fail();
|
||||
} catch ( RedException $exception ) {
|
||||
pass();
|
||||
}
|
||||
try {
|
||||
R::findOneOrDispense( 'invalid_type' );
|
||||
fail();
|
||||
} catch ( RedException $exception ) {
|
||||
pass();
|
||||
}
|
||||
try {
|
||||
DispenseHelper::checkType( 'invalid_type' );
|
||||
fail();
|
||||
} catch ( RedException $exception ) {
|
||||
pass();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test dispense.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBasicsDispense()
|
||||
{
|
||||
$redbean = R::getRedBean();
|
||||
// Can we dispense a bean?
|
||||
$page = $redbean->dispense( "page" );
|
||||
// Does it have a meta type?
|
||||
asrt( ( (bool) $page->getMeta( "type" ) ), TRUE );
|
||||
// Does it have an ID?
|
||||
asrt( isset( $page->id ), TRUE );
|
||||
// Type should be 'page'
|
||||
asrt( ( $page->getMeta( "type" ) ), "page" );
|
||||
// ID should be 0 because bean does not exist in database yet.
|
||||
asrt( ( $page->id ), 0 );
|
||||
// Try some faulty dispense actions.
|
||||
foreach ( array( "", ".", "-") as $value ) {
|
||||
try {
|
||||
$redbean->dispense( $value );
|
||||
fail();
|
||||
} catch (RedException $e ) {
|
||||
pass();
|
||||
}
|
||||
}
|
||||
$bean = $redbean->dispense( "testbean" );
|
||||
$bean["property"] = 123;
|
||||
$bean["abc"] = "def";
|
||||
asrt( $bean["property"], 123 );
|
||||
asrt( $bean["abc"], "def" );
|
||||
asrt( $bean->abc, "def" );
|
||||
asrt( isset( $bean["abd"] ), FALSE );
|
||||
asrt( isset( $bean["abc"] ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the facade-only dispenseAll method.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDispenseAll()
|
||||
{
|
||||
list( $book, $page ) = Facade::dispenseAll( 'book,page' );
|
||||
asrt( ( $book instanceof OODBBean ), TRUE );
|
||||
asrt( ( $page instanceof OODBBean ), TRUE );
|
||||
asrt( $book->getMeta( 'type' ), 'book');
|
||||
asrt( $page->getMeta( 'type' ), 'page');
|
||||
list( $book, $page, $texts, $mark ) = R::dispenseAll( 'book,page,text*2,mark' );
|
||||
asrt( ( $book instanceof OODBBean ), TRUE );
|
||||
asrt( ( $page instanceof OODBBean ), TRUE );
|
||||
asrt( is_array( $texts ), TRUE );
|
||||
asrt( ( $mark instanceof OODBBean ), TRUE );
|
||||
asrt( $book->getMeta( 'type'), 'book' );
|
||||
asrt( $page->getMeta( 'type'), 'page' );
|
||||
asrt( $mark->getMeta( 'type'), 'mark' );
|
||||
asrt( $texts[0]->getMeta( 'type'), 'text' );
|
||||
asrt( $texts[1]->getMeta( 'type'), 'text' );
|
||||
list( $eggs, $milk, $butter ) = R::dispenseAll( 'eggs*3,milk*1,butter*9' );
|
||||
asrt( count( $eggs ), 3 );
|
||||
asrt( ( $milk instanceof OODBBean ), TRUE );
|
||||
asrt( count( $butter ), 9 );
|
||||
list( $eggs, $milk, $butter ) = R::dispenseAll( 'eggs*3,milk*1,butter*9', TRUE );
|
||||
asrt( count( $eggs ), 3 );
|
||||
asrt( count( $milk ), 1 );
|
||||
asrt( count( $eggs ), 3 );
|
||||
list( $beer ) = R::dispenseAll( 'beer*0', TRUE );
|
||||
asrt( is_array( $beer ), TRUE );
|
||||
asrt( count( $beer ), 0 );
|
||||
list( $beer ) = R::dispenseAll( 'beer*0', FALSE );
|
||||
asrt( is_array( $beer ), FALSE );
|
||||
asrt( is_null( $beer ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests different return values of dispense().
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDispenseArray()
|
||||
{
|
||||
$oodb = R::getRedBean();
|
||||
$array = $oodb->dispense( 'book', 0, TRUE );
|
||||
asrt( is_array( $array ), TRUE );
|
||||
$array = $oodb->dispense( 'book', 1, TRUE );
|
||||
asrt( is_array( $array ), TRUE );
|
||||
$array = $oodb->dispense( 'book', 2, TRUE );
|
||||
asrt( is_array( $array ), TRUE );
|
||||
$array = R::dispense( 'book', 0, TRUE );
|
||||
asrt( is_array( $array ), TRUE );
|
||||
$array = R::dispense( 'book', 1, TRUE );
|
||||
asrt( is_array( $array ), TRUE );
|
||||
$array = R::dispense( 'book', 2, TRUE );
|
||||
asrt( is_array( $array ), TRUE );
|
||||
$array = $oodb->dispense( 'book', 0, FALSE );
|
||||
asrt( is_array( $array ), FALSE );
|
||||
asrt( is_null( $array ), TRUE );
|
||||
$array = $oodb->dispense( 'book', 1, FALSE );
|
||||
asrt( is_array( $array ), FALSE );
|
||||
asrt( ( $array instanceof OODBBean ), TRUE );
|
||||
$array = $oodb->dispense( 'book', 2, FALSE );
|
||||
asrt( is_array( $array ), TRUE );
|
||||
$array = R::dispense( 'book', 0, FALSE );
|
||||
asrt( is_array( $array ), FALSE );
|
||||
$array = R::dispense( 'book', 1, FALSE );
|
||||
asrt( is_array( $array ), FALSE );
|
||||
$array = R::dispense( 'book', 2, FALSE );
|
||||
asrt( is_array( $array ), TRUE );
|
||||
$array = $oodb->dispense( 'book', 0 );
|
||||
asrt( is_array( $array ), FALSE );
|
||||
asrt( is_null( $array ), TRUE );
|
||||
$array = $oodb->dispense( 'book', 1 );
|
||||
asrt( is_array( $array ), FALSE );
|
||||
asrt( ( $array instanceof OODBBean ), TRUE );
|
||||
$array = $oodb->dispense( 'book', 2 );
|
||||
asrt( is_array( $array ), TRUE );
|
||||
$array = R::dispense( 'book', 0 );
|
||||
asrt( is_array( $array ), FALSE );
|
||||
$array = R::dispense( 'book', 1 );
|
||||
asrt( is_array( $array ), FALSE );
|
||||
$array = R::dispense( 'book', 2 );
|
||||
asrt( is_array( $array ), TRUE );
|
||||
}
|
||||
}
|
||||
647
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Dup.php
vendored
Normal file
647
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Dup.php
vendored
Normal file
@@ -0,0 +1,647 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\DuplicationManager as DuplicationManager;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
use RedBeanPHP\RedException as RedException;
|
||||
|
||||
/**
|
||||
* Dup
|
||||
*
|
||||
* Tests duplication. Like the 'copy' test suite but
|
||||
* focuses on more complex scenarios.
|
||||
*
|
||||
* @file RedUNIT/Base/Dup.php
|
||||
* @desc Intensive test for dup()
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Dup extends Base
|
||||
{
|
||||
/**
|
||||
* Tests basic export functionality
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testExport()
|
||||
{
|
||||
$bean = R::dispense('bean');
|
||||
$bean->name = R::dispense('book');
|
||||
$export = $bean->export( FALSE, FALSE, FALSE, array( 'book' ) );
|
||||
asrt( isset( $export['name'] ), TRUE );
|
||||
$export = $bean->export( FALSE, FALSE, FALSE, array( 'book2' ) );
|
||||
asrt( isset( $export['name'] ), FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the original ID is stored
|
||||
* in meta data (quite handy for ID mappings).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testKeepOldID()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$book->xownPageList[] = R::dispense( 'page' );
|
||||
R::store( $book );
|
||||
$bookID = $book->id;
|
||||
$page = reset( $book->xownPageList );
|
||||
$pageID = $page->id;
|
||||
$book = $book->fresh();
|
||||
$copy = R::duplicate( $book );
|
||||
asrt( $copy->getMeta( 'sys.dup-from-id' ), $bookID );
|
||||
$copyPage = reset( $copy->xownPageList );
|
||||
asrt( $copyPage->getMeta( 'sys.dup-from-id' ), $pageID );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test export camelCase.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testExportCamelCase()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$book->isCheap = TRUE;
|
||||
$book->hasISBNCode = FALSE;
|
||||
$page = R::dispense('page');
|
||||
$page->isWrittenWell = TRUE;
|
||||
$page->containsInterestingText = TRUE;
|
||||
$book->ownPageList[] = $page;
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
$export = R::exportAll( $book );
|
||||
asrt( isset( $export[0]['id'] ), TRUE );
|
||||
asrt( isset( $export[0]['is_cheap'] ), TRUE );
|
||||
asrt( isset( $export[0]['has_isbn_code'] ), TRUE );
|
||||
asrt( isset( $export[0]['ownPage']['0']['id'] ), TRUE );
|
||||
asrt( isset( $export[0]['ownPage']['0']['is_written_well'] ), TRUE );
|
||||
asrt( isset( $export[0]['ownPage']['0']['contains_interesting_text'] ), TRUE );
|
||||
asrt( isset( $export[0]['ownPage']['0']['book_id'] ), TRUE );
|
||||
R::useExportCase( 'camel' );
|
||||
$export = R::exportAll( $book );
|
||||
asrt( isset( $export[0]['id'] ), TRUE );
|
||||
asrt( isset( $export[0]['isCheap'] ), TRUE );
|
||||
asrt( isset( $export[0]['hasIsbnCode'] ), TRUE );
|
||||
asrt( isset( $export[0]['ownPage']['0']['id'] ), TRUE );
|
||||
asrt( isset( $export[0]['ownPage']['0']['isWrittenWell'] ), TRUE );
|
||||
asrt( isset( $export[0]['ownPage']['0']['containsInterestingText'] ), TRUE );
|
||||
asrt( isset( $export[0]['ownPage']['0']['bookId'] ), TRUE );
|
||||
R::useExportCase( 'dolphin' );
|
||||
$export = R::exportAll( $book );
|
||||
asrt( isset( $export[0]['id'] ), TRUE );
|
||||
asrt( isset( $export[0]['isCheap'] ), TRUE );
|
||||
asrt( isset( $export[0]['hasIsbnCode'] ), TRUE );
|
||||
asrt( isset( $export[0]['ownPage']['0']['id'] ), TRUE );
|
||||
asrt( isset( $export[0]['ownPage']['0']['isWrittenWell'] ), TRUE );
|
||||
asrt( isset( $export[0]['ownPage']['0']['containsInterestingText'] ), TRUE );
|
||||
asrt( isset( $export[0]['ownPage']['0']['bookID'] ), TRUE );
|
||||
R::useExportCase( 'default' );
|
||||
$export = R::exportAll( $book );
|
||||
asrt( isset( $export[0]['id'] ), TRUE );
|
||||
asrt( isset( $export[0]['is_cheap'] ), TRUE );
|
||||
asrt( isset( $export[0]['has_isbn_code'] ), TRUE );
|
||||
asrt( isset( $export[0]['ownPage']['0']['id'] ), TRUE );
|
||||
asrt( isset( $export[0]['ownPage']['0']['is_written_well'] ), TRUE );
|
||||
asrt( isset( $export[0]['ownPage']['0']['contains_interesting_text'] ), TRUE );
|
||||
asrt( isset( $export[0]['ownPage']['0']['book_id'] ), TRUE );
|
||||
try {
|
||||
R::useExportCase( 'invalid' );
|
||||
fail();
|
||||
} catch ( RedException $exception ) {
|
||||
pass();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether we can duplicate part of a tree
|
||||
* without infinite loops.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDupPortionOfATree()
|
||||
{
|
||||
R::nuke();
|
||||
$article = R::dispense( 'article' );
|
||||
$article->name = 'article 1';
|
||||
list( $article2, $article3 ) = R::dispense( 'article', 2 );
|
||||
$article2->name = 'article 2';
|
||||
$article3->name = 'article 3';
|
||||
list( $article4, $article5 ) = R::dispense( 'article' , 2);
|
||||
$article4->name = 'article 4';
|
||||
$article5->name = 'article 5';
|
||||
list( $article6, $article7 ) = R::dispense( 'article' , 2);
|
||||
$article6->name = 'article 6';
|
||||
$article7->name = 'article 7';
|
||||
$article3->xownArticleList[] = $article7;
|
||||
$article4->xownArticleList[] = $article6;
|
||||
$article2->xownArticleList = array( $article5, $article4 );
|
||||
$article->xownArticleList = array( $article2, $article3 );
|
||||
R::store( $article );
|
||||
asrt( R::count( 'article' ), 7 );
|
||||
$article2 = $article2->fresh();
|
||||
$dupArticle2 = R::duplicate( $article2 );
|
||||
$dupArticle2->name = 'article 2b';
|
||||
$dupBeans = $dupArticle2->xownArticleList;
|
||||
foreach( $dupBeans as $dupBean ) {
|
||||
$list[] = $dupBean->name;
|
||||
}
|
||||
sort( $list );
|
||||
$listStr = implode( ',', $list );
|
||||
asrt( $listStr, 'article 4,article 5' );
|
||||
foreach( $dupBeans as $dupBean ) {
|
||||
if ( $dupBean->name === 'article 4' ) {
|
||||
$dup4 = $dupBean;
|
||||
}
|
||||
}
|
||||
asrt( isset( $dup4 ), TRUE );
|
||||
$dupBeans = $dup4->xownArticleList;
|
||||
foreach( $dupBeans as $dupBean ) {
|
||||
asrt( $dupBean->name, 'article 6' );
|
||||
}
|
||||
//so we have extracted part of the tree, can we store it?
|
||||
$id = R::store( $dupArticle2 );
|
||||
asrt( ( $id > 0 ), TRUE );
|
||||
asrt( R::count( 'article' ), 11 );
|
||||
$originalArticle = $article->fresh();
|
||||
asrt( $originalArticle->name, 'article 1' );
|
||||
$subArticles = $originalArticle->xownArticleList;
|
||||
$list = array();
|
||||
foreach( $subArticles as $subArticle ) {
|
||||
$list[] = $subArticle->name;
|
||||
}
|
||||
sort( $list );
|
||||
$listStr = implode( ',', $list );
|
||||
asrt( $listStr, 'article 2,article 2b,article 3' );
|
||||
foreach( $subArticles as $subArticle ) {
|
||||
if ( $subArticle->name === 'article 2' ) {
|
||||
$sub2 = $subArticle;
|
||||
}
|
||||
if ( $subArticle->name === 'article 3' ) {
|
||||
$sub3 = $subArticle;
|
||||
}
|
||||
}
|
||||
$subArticles = $sub2->xownArticleList;
|
||||
$list = array();
|
||||
foreach( $subArticles as $subArticle ) {
|
||||
$list[] = $subArticle->name;
|
||||
}
|
||||
sort( $list );
|
||||
$listStr = implode( ',', $list );
|
||||
asrt( $listStr, 'article 4,article 5' );
|
||||
$subArticles = $sub3->xownArticleList;
|
||||
$list = array();
|
||||
foreach( $subArticles as $subArticle ) {
|
||||
$list[] = $subArticle->name;
|
||||
}
|
||||
sort( $list );
|
||||
$listStr = implode( ',', $list );
|
||||
asrt( $listStr, 'article 7' );
|
||||
$subArticles = $sub2->xownArticleList;
|
||||
foreach( $subArticles as $subArticle ) {
|
||||
if ( $subArticle->name === 'article 4' ) {
|
||||
$sub4 = $subArticle;
|
||||
}
|
||||
if ( $subArticle->name === 'article 5' ) {
|
||||
$sub5 = $subArticle;
|
||||
}
|
||||
}
|
||||
asrt( count( $sub4->xownArticleList ), 1 );
|
||||
$subBeans = $sub4->xownArticleList;
|
||||
$subBean = reset( $subBeans );
|
||||
asrt( $subBean->name, 'article 6');
|
||||
asrt( count( $sub5->xownArticleList ), 0 );
|
||||
$dupArticle2 = $dupArticle2->fresh();
|
||||
$subArticles = $dupArticle2->xownArticleList;
|
||||
$list = array();
|
||||
foreach( $subArticles as $subArticle ) {
|
||||
$list[] = $subArticle->name;
|
||||
}
|
||||
sort( $list );
|
||||
$listStr = implode( ',', $list );
|
||||
asrt( $listStr, 'article 4,article 5' );
|
||||
foreach( $subArticles as $subArticle ) {
|
||||
if ( $subArticle->name === 'article 4' ) {
|
||||
$sub4 = $subArticle;
|
||||
}
|
||||
if ( $subArticle->name === 'article 5' ) {
|
||||
$sub5 = $subArticle;
|
||||
}
|
||||
}
|
||||
asrt( count( $sub4->xownArticleList ), 1 );
|
||||
$subBeans = $sub4->xownArticleList;
|
||||
$subBean = reset( $subBeans );
|
||||
asrt( $subBean->name, 'article 6');
|
||||
asrt( count( $sub5->xownArticleList ), 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test exportAll and caching.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testExportAllAndCache()
|
||||
{
|
||||
testpack( 'exportAll() and Cache' );
|
||||
$can = R::dispense( 'can' )->setAttr( 'size', 3 );
|
||||
$can->ownCoffee[] = R::dispense( 'coffee' )->setAttr( 'color', 'black' );
|
||||
$can->sharedTag[] = R::dispense( 'tag' )->setAttr( 'name', 'cool' );
|
||||
$id = R::store( $can );
|
||||
R::debug( TRUE );
|
||||
ob_start();
|
||||
$can = R::load( 'can', $id );
|
||||
$cache = $this->getCache();
|
||||
$data = R::exportAll( array( $can ), TRUE );
|
||||
$queries = ob_get_contents();
|
||||
R::debug( FALSE );
|
||||
ob_end_clean();
|
||||
$len1 = strlen( $queries );
|
||||
$can = R::dispense( 'can' )->setAttr( 'size', 3 );
|
||||
$can->ownCoffee[] = R::dispense( 'coffee' )->setAttr( 'color', 'black' );
|
||||
$can->sharedTag[] = R::dispense( 'tag' )->setAttr( 'name', 'cool' );
|
||||
$id = R::store( $can );
|
||||
R::debug( TRUE );
|
||||
ob_start();
|
||||
$can = R::load( 'can', $id );
|
||||
$cache = $this->getCache();
|
||||
$data = R::exportAll( array( $can ), TRUE );
|
||||
$queries = ob_get_contents();
|
||||
R::debug( FALSE );
|
||||
ob_end_clean();
|
||||
$len2 = strlen( $queries );
|
||||
asrt( ( $len1 ), ( $len2 ) );
|
||||
$can = R::dispense( 'can' )->setAttr( 'size', 3 );
|
||||
$can->ownCoffee[] = R::dispense( 'coffee' )->setAttr( 'color', 'black' );
|
||||
$can->sharedTag[] = R::dispense( 'tag' )->setAttr( 'name', 'cool' );
|
||||
$id = R::store( $can );
|
||||
R::debug( TRUE );
|
||||
ob_start();
|
||||
$can = R::load( 'can', $id );
|
||||
$cache = $this->getCache();
|
||||
R::getDuplicationManager()->setTables( $cache );
|
||||
$data = R::exportAll( array( $can ), TRUE );
|
||||
$queries = ob_get_contents();
|
||||
R::debug( FALSE );
|
||||
ob_end_clean();
|
||||
$len3 = strlen( $queries );
|
||||
asrt( ( ( $len3 ) < ( $len2 ) ), TRUE );
|
||||
asrt( count( $data ), 1 );
|
||||
asrt( $data[0]['ownCoffee'][0]['color'], 'black' );
|
||||
R::getDuplicationManager()->setCacheTables( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test duplication and caching.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function DupAndCache()
|
||||
{
|
||||
testpack( 'Dup() and Cache' );
|
||||
$can = R::dispense( 'can' )->setAttr( 'size', 3 );
|
||||
$can->ownCoffee[] = R::dispense( 'coffee' )->setAttr( 'color', 'black' );
|
||||
$can->sharedTag[] = R::dispense( 'tag' )->setAttr( 'name', 'cool' );
|
||||
$can = R::load( 'can', R::store( $can ) );
|
||||
$d = new DuplicationManager( R::getToolBox() );
|
||||
$d->setCacheTables( TRUE );
|
||||
ob_start();
|
||||
R::debug( 1 );
|
||||
$x = $d->dup( $can );
|
||||
$queries = ob_get_contents();
|
||||
R::debug( 0 );
|
||||
ob_end_clean();
|
||||
$len1 = strlen( $queries );
|
||||
asrt( ( $len1 > 40 ), TRUE );
|
||||
asrt( isset( $x->ownCoffee ), TRUE );
|
||||
asrt( count( $x->ownCoffee ), 1 );
|
||||
asrt( isset( $x->sharedTag ), TRUE );
|
||||
asrt( count( $x->sharedTag ), 1 );
|
||||
$cache = $d->getSchema();
|
||||
R::nuke();
|
||||
$can = R::dispense( 'can' )->setAttr( 'size', 3 );
|
||||
$can->ownCoffee[] = R::dispense( 'coffee' )->setAttr( 'color', 'black' );
|
||||
$can->sharedTag[] = R::dispense( 'tag' )->setAttr( 'name', 'cool' );
|
||||
$can = R::load( 'can', R::store( $can ) );
|
||||
$d = new DuplicationManager( R::getToolBox() );
|
||||
|
||||
/**
|
||||
* $cache = '{"book": {
|
||||
* "id": "INTEGER",
|
||||
* "title": "TEXT"
|
||||
* }, "bean": {
|
||||
* "id": "INTEGER",
|
||||
* "prop": "INTEGER"
|
||||
* }, "pessoa": {
|
||||
* "id": "INTEGER",
|
||||
* "nome": "TEXT",
|
||||
* "nome_meio": "TEXT",
|
||||
* "sobrenome": "TEXT",
|
||||
* "nascimento": "NUMERIC",
|
||||
* "reg_owner": "TEXT"
|
||||
* }, "documento": {
|
||||
* "id": "INTEGER",
|
||||
* "nome_documento": "TEXT",
|
||||
* "numero_documento": "TEXT",
|
||||
* "reg_owner": "TEXT",
|
||||
* "ownPessoa_id": "INTEGER"
|
||||
* }, "can": {
|
||||
* "id": "INTEGER",
|
||||
* "size": "INTEGER"
|
||||
* }, "coffee": {
|
||||
* "id": "INTEGER",
|
||||
* "color": "TEXT",
|
||||
* "can_id": "INTEGER"
|
||||
* }, "tag": {
|
||||
* "id": "INTEGER",
|
||||
* "name": "TEXT"
|
||||
* }, "can_tag": {
|
||||
* "id": "INTEGER",
|
||||
* "tag_id": "INTEGER",
|
||||
* "can_id": "INTEGER"
|
||||
* }}'
|
||||
*/
|
||||
|
||||
$d->setTables( $cache );
|
||||
ob_start();
|
||||
R::debug( 1 );
|
||||
$x = $d->dup( $can );
|
||||
$queries = ob_get_contents();
|
||||
ob_end_clean();
|
||||
R::debug( 0 );
|
||||
$len2 = strlen( $queries );
|
||||
asrt( isset( $x->ownCoffee ), TRUE );
|
||||
asrt( count( $x->ownCoffee ), 1 );
|
||||
asrt( isset( $x->sharedTag ), TRUE );
|
||||
asrt( count( $x->sharedTag ), 1 );
|
||||
asrt( json_encode( $cache ), json_encode( $d->getSchema() ) );
|
||||
asrt( ( $len1 > $len2 ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test duplication and tainting.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDupAndExportNonTainting()
|
||||
{
|
||||
testpack( 'Dup() and Export() should not taint beans' );
|
||||
$p = R::dispense( 'page' );
|
||||
$b = R::dispense( 'book' );
|
||||
$b->ownPage[] = $p;
|
||||
$b->title = 'a';
|
||||
$id = R::store( $b );
|
||||
$b = R::load( 'book', $id );
|
||||
asrt( ( !$b->getMeta( 'tainted' ) ), TRUE );
|
||||
R::exportAll( $b );
|
||||
asrt( ( !$b->getMeta( 'tainted' ) ), TRUE );
|
||||
R::dup( $b );
|
||||
asrt( ( !$b->getMeta( 'tainted' ) ), TRUE );
|
||||
testpack( 'Test issue with ownItems and stealing Ids.' );
|
||||
R::nuke();
|
||||
$bill = R::dispense( 'bill' );
|
||||
$item = R::dispense( 'item' );
|
||||
$element = R::dispense( 'element' );
|
||||
$bill->ownItem[] = $item;
|
||||
$bill->sharedElement[] = $element;
|
||||
R::store( $bill );
|
||||
$bill = R::load( 'bill', 1 );
|
||||
$bill->ownItem;
|
||||
$bill->sharedElement;
|
||||
$copy = R::dup( $bill );
|
||||
R::store( $copy );
|
||||
$rows = ( R::getAll( 'select * from bill_element' ) );
|
||||
asrt( count( $rows ), 2 );
|
||||
$rows = ( R::getAll( 'select * from item' ) );
|
||||
foreach ( $rows as $row ) {
|
||||
asrt( ( $row['bill_id'] > 0 ), TRUE );
|
||||
}
|
||||
R::nuke();
|
||||
$this->runOnce();
|
||||
R::freeze( TRUE );
|
||||
$this->runOnce( FALSE );
|
||||
R::freeze( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test exporting with filters.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function ExportWithFilters()
|
||||
{
|
||||
testpack( 'Export with filters' );
|
||||
$book = R::dispense( 'book' );
|
||||
$pages = R::dispense( 'page', 2 );
|
||||
$texts = R::dispense( 'text', 2 );
|
||||
$images = R::dispense( 'image', 2 );
|
||||
$author = R::dispense( 'author' );
|
||||
$pub = R::dispense( 'publisher' );
|
||||
$bookmarks = R::dispense( 'bookmark', 2 );
|
||||
$pages[0]->ownText = array( $texts[0] );
|
||||
$pages[0]->ownImage = array( $images[0] );
|
||||
$pages[1]->ownText = array( $texts[1] );
|
||||
$pages[1]->ownImage = array( $images[1] );
|
||||
$pages[0]->sharedBookmark[] = $bookmarks[0];
|
||||
$pages[1]->sharedBookmark[] = $bookmarks[1];
|
||||
$bookmarks[0]->ownNote[] = R::dispense( 'note' )->setAttr( 'text', 'a note' );
|
||||
$bookmarks[1]->ownNote[] = R::dispense( 'note' )->setAttr( 'text', 'a note' );
|
||||
$book->ownPage = $pages;
|
||||
$book->author = $author;
|
||||
$author->publisher = $pub;
|
||||
$bookID = R::store( $book );
|
||||
R::getDuplicationManager()->setTables( R::getWriter()->getTables() );
|
||||
$objects = ( R::exportAll( array( $book ), TRUE, array() ) );
|
||||
asrt( isset( $objects[0]['ownPage'] ), TRUE );
|
||||
asrt( count( $objects[0]['ownPage'] ), 2 );
|
||||
asrt( isset( $objects[0]['author'] ), TRUE );
|
||||
asrt( isset( $objects[0]['ownPage'][0]['ownText'] ), TRUE );
|
||||
asrt( count( $objects[0]['ownPage'][0]['ownText'] ), 1 );
|
||||
asrt( isset( $objects[0]['ownPage'][0]['ownImage'] ), TRUE );
|
||||
asrt( count( $objects[0]['ownPage'][0]['ownImage'] ), 1 );
|
||||
$objects = ( R::exportAll( array( $book ), TRUE, array( 'page', 'author', 'text', 'image' ) ) );
|
||||
asrt( isset( $objects[0]['ownPage'] ), TRUE );
|
||||
asrt( count( $objects[0]['ownPage'] ), 2 );
|
||||
asrt( isset( $objects[0]['author'] ), TRUE );
|
||||
asrt( isset( $objects[0]['ownPage'][0]['ownText'] ), TRUE );
|
||||
asrt( count( $objects[0]['ownPage'][0]['ownText'] ), 1 );
|
||||
asrt( isset( $objects[0]['ownPage'][0]['ownImage'] ), TRUE );
|
||||
asrt( count( $objects[0]['ownPage'][0]['ownImage'] ), 1 );
|
||||
$objects = ( R::exportAll( array( $book ), TRUE, 'author' ) );
|
||||
asrt( isset( $objects[0]['ownPage'] ), FALSE );
|
||||
asrt( isset( $objects[0]['ownPage'][0]['ownText'] ), FALSE );
|
||||
$objects = ( R::exportAll( array( $book ), TRUE, array( 'page' ) ) );
|
||||
asrt( isset( $objects[0]['author'] ), FALSE );
|
||||
asrt( isset( $objects[0]['ownPage'][0]['ownText'] ), FALSE );
|
||||
$objects = ( R::exportAll( array( $book ), TRUE, array( 'page', 'text' ) ) );
|
||||
asrt( isset( $objects[0]['author'] ), FALSE );
|
||||
asrt( isset( $objects[0]['ownPage'] ), TRUE );
|
||||
asrt( isset( $objects[0]['ownPage'][0]['ownText'] ), TRUE );
|
||||
asrt( count( $objects[0]['ownPage'][0]['ownText'] ), 1 );
|
||||
asrt( isset( $objects[0]['ownPage'][0]['ownImage'] ), FALSE );
|
||||
$objects = ( R::exportAll( array( $book ), TRUE, array( 'none' ) ) );
|
||||
asrt( isset( $objects[0]['author'] ), FALSE );
|
||||
asrt( isset( $objects[0]['ownPage'] ), FALSE );
|
||||
$texts = R::find( 'text' );
|
||||
R::getDuplicationManager()->setCacheTables( FALSE );
|
||||
testpack( 'Keyless export' );
|
||||
$book = R::load( 'book', $bookID );
|
||||
$book->ownPage;
|
||||
$export = $book->export();
|
||||
asrt( isset( $export['ownPage'][0] ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function getCache().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getCache()
|
||||
{
|
||||
return array(
|
||||
'coffee' => array(
|
||||
'color' => 'color',
|
||||
'id' => 'id',
|
||||
'can_id' => 'can_id'
|
||||
),
|
||||
'can' => array(
|
||||
'size' => 'size',
|
||||
'id' => 'id'
|
||||
),
|
||||
'can_tag' => array(
|
||||
'id' => 'id',
|
||||
'can_id' => 'can_id',
|
||||
'tag_id' => 'tag_id'
|
||||
),
|
||||
'tag' => array(
|
||||
'id' => 'id',
|
||||
'name' => 'name' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares object with export
|
||||
*
|
||||
* @param type $object
|
||||
* @param type $array
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function compare( $object, $array )
|
||||
{
|
||||
foreach ( $object as $property => $value ) {
|
||||
if ( is_array( $value ) ) {
|
||||
foreach ( $value as $index => $nestedObject ) {
|
||||
if ( $nestedObject->id ) {
|
||||
$foundMatch = FALSE;
|
||||
//order might be different
|
||||
foreach ( $array[$property] as $k => $a ) {
|
||||
if ( $a['id'] == $nestedObject->id ) {
|
||||
$foundMatch = TRUE;
|
||||
$index = $k;
|
||||
}
|
||||
}
|
||||
if ( !$foundMatch ) throw new\Exception( 'failed to find match for object ' . $nestedObject->id );
|
||||
}
|
||||
$this->compare( $nestedObject, $array[$property][$index] );
|
||||
}
|
||||
} elseif ( !is_object( $value ) ) {
|
||||
asrt( strval( $array[$property] ), strval( $value ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run tests
|
||||
*/
|
||||
private function runOnce( $n = TRUE )
|
||||
{
|
||||
$books = R::dispense( 'book', 10 );
|
||||
$pages = R::dispense( 'page', 10 );
|
||||
$readers = R::dispense( 'reader', 10 );
|
||||
$texts = R::dispense( 'text', 10 );
|
||||
$i = 0;
|
||||
foreach ( $books as $book ) $book->name = 'book-' . ( $i++ );
|
||||
$i = 0;
|
||||
foreach ( $pages as $page ) $page->name = 'page-' . ( $i++ );
|
||||
$i = 0;
|
||||
foreach ( $readers as $reader ) $reader->name = 'reader-' . ( $i++ );
|
||||
$i = 0;
|
||||
foreach ( $texts as $text ) $text->content = 'lorem ipsum -' . ( $i++ );
|
||||
|
||||
foreach ( $texts as $text ) {
|
||||
$pages[array_rand( $pages )]->ownText[] = $text;
|
||||
}
|
||||
foreach ( $pages as $page ) {
|
||||
$books[array_rand( $books )]->ownPage[] = $page;
|
||||
}
|
||||
foreach ( $readers as $reader ) {
|
||||
$books[array_rand( $books )]->sharedReader[] = $reader;
|
||||
}
|
||||
$i = $noOfReaders = $noOfPages = $noOfTexts = 0;
|
||||
foreach ( $books as $key => $book ) {
|
||||
$i++;
|
||||
$noOfPages += count( $book->ownPage );
|
||||
$noOfReaders += count( $book->sharedReader );
|
||||
foreach ( $book->ownPage as $page ) $noOfTexts += count( $page->ownText );
|
||||
$arr = R::exportAll( $book );
|
||||
echo "\nIntermediate info: " . json_encode( $arr ) . ": Totals = $i,$noOfPages,$noOfReaders,$noOfTexts ";
|
||||
$this->compare( $book, $arr[0] );
|
||||
$copiedBook = R::dup( $book );
|
||||
$copiedBookArray = R::exportAll( $copiedBook );
|
||||
$this->compare( $book, $copiedBookArray[0] );
|
||||
$copiedBookArrayII = $copiedBook->export();
|
||||
$this->compare( $book, $copiedBookArrayII );
|
||||
$copyFromCopy = R::dup( $copiedBook );
|
||||
$copyFromCopyArray = R::exportAll( $copyFromCopy );
|
||||
$this->compare( $book, $copyFromCopyArray[0] );
|
||||
$copyFromCopyArrayII = $copyFromCopy->export();
|
||||
$this->compare( $book, $copyFromCopyArrayII );
|
||||
$id = R::store( $book );
|
||||
$copiedBook = R::dup( $book );
|
||||
R::store( $book ); //should not be damaged
|
||||
$copiedBookArray = R::exportAll( $copiedBook );
|
||||
$originalBookArray = R::exportAll( $book );
|
||||
$this->compare( $copiedBook, $copiedBookArray[0] );
|
||||
$this->compare( $book, $originalBookArray[0] );
|
||||
$book = R::load( 'book', $id );
|
||||
$this->compare( $book, $originalBookArray[0] );
|
||||
$copiedBook = R::dup( $book );
|
||||
$this->compare( $copiedBook, $copiedBook->export() );
|
||||
R::store( $copiedBook );
|
||||
$this->compare( $copiedBook, $copiedBook->export() );
|
||||
$copyFromCopy = R::dup( $copiedBook );
|
||||
$this->compare( $copyFromCopy, $copyFromCopy->export() );
|
||||
R::store( $copyFromCopy );
|
||||
$newPage = R::dispense( 'page' );
|
||||
$newPage->name = 'new';
|
||||
$copyFromCopy->ownPage[] = $newPage;
|
||||
$modifiedCopy = R::dup( $copyFromCopy );
|
||||
$exportMod = R::exportAll( $modifiedCopy );
|
||||
$this->compare( $modifiedCopy, $exportMod[0] );
|
||||
asrt( count( $modifiedCopy->ownPage ), count( $copiedBook->ownPage ) + 1 );
|
||||
R::store( $modifiedCopy );
|
||||
if ( $n ) {
|
||||
asrt( (int) R::getCell( 'SELECT count(*) FROM book' ), $i * 4 );
|
||||
asrt( (int) R::getCell( 'SELECT count(*) FROM page' ), ( $noOfPages * 4 ) + $i );
|
||||
asrt( (int) R::getCell( 'SELECT count(*) FROM text' ), $noOfTexts * 4 );
|
||||
asrt( (int) R::getCell( 'SELECT count(*) FROM book_reader' ), $noOfReaders * 4 );
|
||||
asrt( (int) R::getCell( 'SELECT count(*) FROM reader' ), $noOfReaders );
|
||||
}
|
||||
}
|
||||
if ( $n ) {
|
||||
asrt( $noOfTexts, 10 );
|
||||
asrt( $noOfReaders, 10 );
|
||||
asrt( $noOfPages, 10 );
|
||||
asrt( $i, 10 );
|
||||
}
|
||||
}
|
||||
}
|
||||
166
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Exceptions.php
vendored
Normal file
166
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Exceptions.php
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\RedException as RedException;
|
||||
use RedBeanPHP\RedException\SQL as SQLException;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
use RedBeanPHP\Adapter\DBAdapter;
|
||||
use RedBeanPHP\ToolBox;
|
||||
use RedBeanPHP\QueryWriter\SQLiteT;
|
||||
use RedBeanPHP\QueryWriter\AQueryWriter;
|
||||
use RedBeanPHP\QueryWriter;
|
||||
use RedBeanPHP\OODB;
|
||||
use RedBeanPHP\Driver\RPDO;
|
||||
|
||||
/**
|
||||
* Exceptions
|
||||
*
|
||||
* Tests exception handling in various scenarios as well
|
||||
* as exception related functionalities.
|
||||
*
|
||||
* @file RedUNIT/Base/Exceptions.php
|
||||
* @desc Tests exception handling
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Exceptions extends Base {
|
||||
|
||||
/**
|
||||
* Tests load exceptions.
|
||||
* Load Exceptions (version 5+)
|
||||
*
|
||||
* - If a bean does not exist,
|
||||
* R::load() and R::loadForUpdate() will return an empty bean.
|
||||
* - If there is an error because of a missing table or column,
|
||||
* both methods will return an empty bean in fluid mode
|
||||
* and throw an exception in frozen mode.
|
||||
* - If something else happens (lock timeout for instance)
|
||||
* both methods will always throw an exception, even in fluid mode.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testLoadExceptions()
|
||||
{
|
||||
/* bean does not exist, and table does not exist */
|
||||
R::nuke();
|
||||
$book = R::load( 'book', 1 );
|
||||
pass();
|
||||
asrt( $book->id, 0 );
|
||||
R::freeze( TRUE );
|
||||
$exception = NULL;
|
||||
try {
|
||||
$book = R::load( 'book', 1 );
|
||||
} catch( RedException $exception ) {}
|
||||
asrt( ( $exception instanceof RedException ), TRUE );
|
||||
R::freeze( FALSE );
|
||||
R::store( $book );
|
||||
/* bean does not exist - table exists */
|
||||
$book = R::load( 'book', 2 );
|
||||
pass();
|
||||
asrt( $book->id, 0 );
|
||||
R::freeze( TRUE );
|
||||
$book = R::load( 'book', 2 );
|
||||
pass();
|
||||
asrt( $book->id, 0 );
|
||||
/* other error */
|
||||
if ( !( R::getWriter() instanceof SQLiteT ) ) {
|
||||
R::freeze( FALSE );
|
||||
$exception = NULL;
|
||||
try {
|
||||
$book = R::load( 'book', 1, 'invalid sql' );
|
||||
} catch( RedException $exception ) {}
|
||||
//not supported for CUBRID
|
||||
if ($this->currentlyActiveDriverID !== 'CUBRID') {
|
||||
asrt( ( $exception instanceof RedException ), TRUE );
|
||||
}
|
||||
} else {
|
||||
/* error handling in SQLite is suboptimal */
|
||||
R::freeze( FALSE );
|
||||
$book = R::load( 'book', 1, 'invalid sql' );
|
||||
pass();
|
||||
asrt( $book->id, 0 );
|
||||
}
|
||||
R::freeze( TRUE );
|
||||
$exception = NULL;
|
||||
try {
|
||||
$book = R::load( 'book', 1, 'invalid sql' );
|
||||
} catch( RedException $exception ) {}
|
||||
asrt( ( $exception instanceof RedException ), TRUE );
|
||||
R::freeze( FALSE );
|
||||
R::nuke();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test delete exceptions
|
||||
*
|
||||
* - in fluid mode no complaining about missing structures
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDeleteExceptions()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
R::store( $book );
|
||||
R::nuke();
|
||||
R::trash( $book );
|
||||
R::freeze( TRUE );
|
||||
$exception = NULL;
|
||||
try {
|
||||
R::trash( $book );
|
||||
} catch( RedException $exception ) {}
|
||||
asrt( ( $exception instanceof RedException ), TRUE );
|
||||
R::freeze( FALSE );
|
||||
$adapter = R::getDatabaseAdapter();
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
R::store( $book );
|
||||
$broken = new BrokenWriter( $adapter );
|
||||
$redbean = R::getRedBean();
|
||||
$oodb = new OODB( $broken, $redbean->isFrozen() );
|
||||
R::setRedBean( $oodb );
|
||||
$exception = NULL;
|
||||
try {
|
||||
R::trash( $book );
|
||||
} catch( RedException $exception ) {}
|
||||
asrt( ( $exception instanceof RedException ), TRUE );
|
||||
R::freeze( TRUE );
|
||||
$exception = NULL;
|
||||
try {
|
||||
R::trash( $book );
|
||||
} catch( RedException $exception ) {}
|
||||
asrt( ( $exception instanceof RedException ), TRUE );
|
||||
R::setRedBean( $redbean );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test chaining of exceptions.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testChainingExceptions()
|
||||
{
|
||||
R::freeze( TRUE );
|
||||
$exception = NULL;
|
||||
try {
|
||||
$book = R::load( 'book', 1, 'invalid sql' );
|
||||
} catch( RedException $exception ) {}
|
||||
pass();
|
||||
asrt( ( $exception instanceof RedException ), TRUE );
|
||||
asrt( ( $exception->getPrevious() instanceof \Exception ), TRUE );
|
||||
}
|
||||
}
|
||||
|
||||
class BrokenWriter extends SQLiteT {
|
||||
public function deleteRecord( $type, $conditions = array(), $addSql = NULL, $bindings = array() )
|
||||
{
|
||||
throw new SQLException('oops');
|
||||
}
|
||||
}
|
||||
137
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Facade.php
vendored
Normal file
137
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Facade.php
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\AssociationManager as AssociationManager;
|
||||
use RedBeanPHP\OODB as OODB;
|
||||
use RedBeanPHP\ToolBox as ToolBox;
|
||||
use RedBeanPHP\Adapter as Adapter;
|
||||
use RedBeanPHP\QueryWriter as QueryWriter;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
|
||||
/**
|
||||
* Facade
|
||||
*
|
||||
* Tests the facade. The facade is a single class (often aliased with R)
|
||||
* that provides access to all (or most) RedBeanPHP functionality without
|
||||
* the need to interact with all the objects involved. The facade has
|
||||
* been designed to be as 'straightfoward' as possible, many methods
|
||||
* of the facade class should be 'almost identical' to simple calls
|
||||
* to objects behind the facade. This test focuses on basic usage
|
||||
* scenarios. Complex scenarios are tested in other suites because
|
||||
* we often test 'the complete route' as the facade code path always
|
||||
* includes the non-facade code path as well (as proven by the coverage numbers).
|
||||
*
|
||||
* @file RedUNIT/Base/Facade.php
|
||||
* @desc Tests basic functions through facade.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Facade extends Base
|
||||
{
|
||||
/**
|
||||
* What drivers should be loaded for this test pack?
|
||||
* This pack contains some SQL incomp. with OCI
|
||||
*/
|
||||
public function getTargetDrivers()
|
||||
{
|
||||
return array( 'mysql', 'pgsql', 'sqlite', 'CUBRID' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests quick trash method: R::trash( type, id ).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testQuickTrash()
|
||||
{
|
||||
R::nuke();
|
||||
$bean = R::dispense( 'bean' );
|
||||
$id = R::store( $bean );
|
||||
asrt( R::count( 'bean' ), 1 );
|
||||
R::trash( 'bean', $id );
|
||||
asrt( R::count( 'bean' ), 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test common Facade usage scenarios.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCommonUsageFacade()
|
||||
{
|
||||
$toolbox = R::getToolBox();
|
||||
$adapter = $toolbox->getDatabaseAdapter();
|
||||
$writer = $toolbox->getWriter();
|
||||
$redbean = $toolbox->getRedBean();
|
||||
$pdo = $adapter->getDatabase();
|
||||
$a = new AssociationManager( $toolbox );
|
||||
asrt( R::getRedBean() instanceof OODB, TRUE );
|
||||
asrt( R::getToolBox() instanceof ToolBox, TRUE );
|
||||
asrt( R::getDatabaseAdapter() instanceof Adapter, TRUE );
|
||||
asrt( R::getWriter() instanceof QueryWriter, TRUE );
|
||||
$book = R::dispense( "book" );
|
||||
asrt( $book instanceof OODBBean, TRUE );
|
||||
$book->title = "a nice book";
|
||||
$id = R::store( $book );
|
||||
asrt( ( $id > 0 ), TRUE );
|
||||
$book = R::load( "book", (int) $id );
|
||||
asrt( $book->title, "a nice book" );
|
||||
asrt( R::load( 'book', 999 )->title, NULL );
|
||||
R::freeze( TRUE );
|
||||
try {
|
||||
R::load( 'bookies', 999 );
|
||||
fail();
|
||||
} catch (\Exception $e ) {
|
||||
pass();
|
||||
}
|
||||
R::freeze( FALSE );
|
||||
$author = R::dispense( "author" );
|
||||
$author->name = "me";
|
||||
R::store( $author );
|
||||
$book9 = R::dispense( "book" );
|
||||
$author9 = R::dispense( "author" );
|
||||
$author9->name = "mr Nine";
|
||||
$a9 = R::store( $author9 );
|
||||
$book9->author_id = $a9;
|
||||
$bk9 = R::store( $book9 );
|
||||
$book9 = R::load( "book", $bk9 );
|
||||
$author = R::load( "author", $book9->author_id );
|
||||
asrt( $author->name, "mr Nine" );
|
||||
R::trash( $author );
|
||||
R::trash( $book9 );
|
||||
pass();
|
||||
$book2 = R::dispense( "book" );
|
||||
$book2->title = "second";
|
||||
R::store( $book2 );
|
||||
$book3 = R::dispense( "book" );
|
||||
$book3->title = "third";
|
||||
R::store( $book3 );
|
||||
asrt( count( R::find( "book" ) ), 3 );
|
||||
asrt( count( R::findAll( "book" ) ), 3 );
|
||||
asrt( count( R::findAll( "book", " LIMIT 2" ) ), 2 );
|
||||
asrt( count( R::find( "book", " id=id " ) ), 3 );
|
||||
asrt( count( R::find( "book", " title LIKE ?", array( "third" ) ) ), 1 );
|
||||
asrt( count( R::find( "book", " title LIKE ?", array( "%d%" ) ) ), 2 );
|
||||
// Find without where clause
|
||||
asrt( count( R::findAll( 'book', ' order by id' ) ), 3 );
|
||||
R::trash( $book3 );
|
||||
R::trash( $book2 );
|
||||
asrt( count( R::getAll( "SELECT * FROM book " ) ), 1 );
|
||||
asrt( count( R::getCol( "SELECT title FROM book " ) ), 1 );
|
||||
asrt( (int) R::getCell( "SELECT 123 " ), 123 );
|
||||
$book = R::dispense( "book" );
|
||||
$book->title = "not so original title";
|
||||
$author = R::dispense( "author" );
|
||||
$author->name = "Bobby";
|
||||
R::store( $book );
|
||||
$aid = R::store( $author );
|
||||
$author = R::findOne( "author", " name = ? ", array( "Bobby" ) );
|
||||
}
|
||||
}
|
||||
1336
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Finding.php
vendored
Normal file
1336
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Finding.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
329
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Foreignkeys.php
vendored
Normal file
329
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Foreignkeys.php
vendored
Normal file
@@ -0,0 +1,329 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\Observer as Observer;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
use RedBeanPHP\Adapter as Adapter;
|
||||
use RedBeanPHP\QueryWriter\AQueryWriter as AQueryWriter;
|
||||
|
||||
/**
|
||||
* Foreignkeys
|
||||
*
|
||||
* Tests whether foreign keys are correctly generated and whether
|
||||
* depending beans are correctly removed. Also tests auto resolving
|
||||
* types inferred by inspecting foreign keys.
|
||||
*
|
||||
* @file RedUNIT/Base/Foreignkeys.php
|
||||
* @desc Tests foreign key handling and dynamic foreign keys with
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Foreignkeys extends Base implements Observer
|
||||
{
|
||||
/**
|
||||
* To log the queries
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $queries = array();
|
||||
|
||||
/**
|
||||
* Test whether unique constraints are properly created using
|
||||
* reflection.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testUniqueInspect()
|
||||
{
|
||||
$writer = R::getWriter();
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$category = R::dispense( 'category' );
|
||||
$book->sharedCategory[] = $category;
|
||||
R::store( $book );
|
||||
asrt( count( get_uniques_for_type('book_category') ), 1 );
|
||||
asrt( are_cols_in_unique( 'book_category', array( 'book_id', 'category_id' ) ), TRUE );
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$category = R::dispense( 'category' );
|
||||
$book->via( 'library' )->sharedCategory[] = $category;
|
||||
R::store( $book );
|
||||
asrt( count( get_uniques_for_type('book_category') ), 0 );
|
||||
asrt( are_cols_in_unique( 'book_category', array( 'book_id', 'category_id' ) ), FALSE );
|
||||
asrt( count( get_uniques_for_type('library') ), 1 );
|
||||
asrt( are_cols_in_unique( 'library', array( 'book_id', 'category_id' ) ), TRUE );
|
||||
AQueryWriter::clearRenames();
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$category = R::dispense( 'category' );
|
||||
$book->sharedCategory[] = $category;
|
||||
R::store( $book );
|
||||
asrt( count( get_uniques_for_type('book_category') ), 1 );
|
||||
asrt( are_cols_in_unique( 'book_category', array( 'book_id', 'category_id' ) ), TRUE );
|
||||
asrt( count( get_uniques_for_type('library') ), 0 );
|
||||
asrt( are_cols_in_unique( 'library', array( 'book_id', 'category_id' ) ), FALSE );
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$book2 = R::dispense( 'book' );
|
||||
$book->sharedBook[] = $book2;
|
||||
R::store( $book );
|
||||
asrt( count( get_uniques_for_type('book_book') ), 1 );
|
||||
asrt( are_cols_in_unique( 'book_book', array( 'book_id', 'book2_id' ) ), TRUE );
|
||||
try {
|
||||
$result = R::getWriter()->addUniqueConstraint( 'nonexistant', array( 'a', 'b' ) );
|
||||
} catch( \Exception $e ) {
|
||||
print_r( $e ); exit;
|
||||
}
|
||||
pass(); //dont crash!
|
||||
asrt( $result, FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests foreign keys but checks using ProxyWriter.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testFKInspect()
|
||||
{
|
||||
$faultyWriter = new \FaultyWriter( R::getDatabaseAdapter() );
|
||||
try {
|
||||
$null = \ProxyWriter::callMethod( $faultyWriter, 'getForeignKeyForTypeProperty', 'test', 'test' );
|
||||
pass();
|
||||
} catch( \Exception $e ) {
|
||||
fail();
|
||||
}
|
||||
asrt( is_null( $null ), TRUE );
|
||||
$writer = R::getWriter();
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$page = R::dispense( 'page' );
|
||||
$book->xownPage[] = $page;
|
||||
R::store( $book );
|
||||
$keys = \ProxyWriter::callMethod( $writer, 'getForeignKeyForTypeProperty', 'page', 'book_id' );
|
||||
asrt( is_array( $keys ), TRUE );
|
||||
asrt( $keys['on_delete'], 'CASCADE' );
|
||||
$keys = \ProxyWriter::callMethod( $writer, 'getForeignKeyForTypeProperty', 'page', 'id' );
|
||||
asrt( is_null( $keys ), TRUE );
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$page = R::dispense( 'page' );
|
||||
$book->ownPage[] = $page;
|
||||
R::store( $book );
|
||||
$keys = \ProxyWriter::callMethod( $writer, 'getForeignKeyForTypeProperty', 'page', 'book_id' );
|
||||
asrt( is_array( $keys ), TRUE );
|
||||
asrt( $keys['on_delete'], 'SET NULL' );
|
||||
$keys = \ProxyWriter::callMethod( $writer, 'getForeignKeyForTypeProperty', 'page', 'id' );
|
||||
asrt( is_null( $keys ), TRUE );
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$page = R::dispense( 'page' );
|
||||
$book->alias('magazine')->xownPage[] = $page;
|
||||
R::store( $book );
|
||||
$keys = \ProxyWriter::callMethod( $writer, 'getForeignKeyForTypeProperty', 'page', 'magazine_id' );
|
||||
asrt( is_array( $keys ), TRUE );
|
||||
asrt( $keys['on_delete'], 'CASCADE' );
|
||||
$keys = \ProxyWriter::callMethod( $writer, 'getForeignKeyForTypeProperty', 'page', 'book_id' );
|
||||
asrt( is_null( $keys ), TRUE );
|
||||
$keys = \ProxyWriter::callMethod( $writer, 'getForeignKeyForTypeProperty', 'page', 'id' );
|
||||
asrt( is_null( $keys ), TRUE );
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$page = R::dispense( 'page' );
|
||||
$book->cover= $page;
|
||||
R::store( $book );
|
||||
$keys = \ProxyWriter::callMethod( $writer, 'getForeignKeyForTypeProperty', 'book', 'cover_id' );
|
||||
asrt( is_array( $keys ), TRUE );
|
||||
asrt( $keys['on_delete'], 'SET NULL' );
|
||||
$keys = \ProxyWriter::callMethod( $writer, 'getForeignKeyForTypeProperty', 'book', 'page_id' );
|
||||
asrt( is_null( $keys ), TRUE );
|
||||
$keys = \ProxyWriter::callMethod( $writer, 'getForeignKeyForTypeProperty', 'book', 'id' );
|
||||
asrt( is_null( $keys ), TRUE );
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$category = R::dispense( 'category' );
|
||||
$book->sharedTag[] = $category;
|
||||
R::store( $book );
|
||||
$keys = \ProxyWriter::callMethod( $writer, 'getForeignKeyForTypeProperty', 'book_category', 'book_id' );
|
||||
asrt( is_array( $keys ), TRUE );
|
||||
$keys = \ProxyWriter::callMethod( $writer, 'getForeignKeyForTypeProperty', 'book_category', 'category_id' );
|
||||
asrt( is_array( $keys ), TRUE );
|
||||
$keys = \ProxyWriter::callMethod( $writer, 'getForeignKeyForTypeProperty', 'book_category', 'id' );
|
||||
asrt( is_null( $keys ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test dependencies.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDependency()
|
||||
{
|
||||
$can = $this->createBeanInCan( FALSE );
|
||||
asrt( R::count( 'bean' ), 1 );
|
||||
R::trash( $can );
|
||||
// Bean stays
|
||||
asrt( R::count( 'bean' ), 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test dependencies (variation).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDependency2()
|
||||
{
|
||||
$can = $this->createBeanInCan( TRUE );
|
||||
asrt( R::count( 'bean' ), 1 );
|
||||
R::trash( $can );
|
||||
// Bean gone
|
||||
asrt( R::count( 'bean' ), 0 );
|
||||
$can = $this->createBeanInCan( FALSE );
|
||||
asrt( R::count( 'bean' ), 1 );
|
||||
R::trash( $can );
|
||||
// Bean stays, constraint removed
|
||||
asrt( R::count( 'bean' ), 0 );
|
||||
//need to recreate table to get rid of constraint!
|
||||
R::nuke();
|
||||
$can = $this->createBeanInCan( FALSE );
|
||||
asrt( R::count( 'bean' ), 1 );
|
||||
R::trash( $can );
|
||||
// Bean stays, constraint removed
|
||||
asrt( R::count( 'bean' ), 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests dependencies (variation).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDependency3()
|
||||
{
|
||||
R::nuke();
|
||||
$can = $this->createCanForBean();
|
||||
asrt( R::count( 'bean' ), 1 );
|
||||
R::trash( $can );
|
||||
asrt( R::count( 'bean' ), 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests dependencies (variation).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDependency4()
|
||||
{
|
||||
R::nuke();
|
||||
$can = $this->createBeanInCan( TRUE );
|
||||
R::store( $can );
|
||||
R::trash( $can );
|
||||
$can = $this->createCanForBean();
|
||||
asrt( R::count( 'bean' ), 1 );
|
||||
R::trash( $can );
|
||||
asrt( R::count( 'bean' ), 0 );
|
||||
$can = $this->createBeanInCan( TRUE );
|
||||
R::store( $can );
|
||||
R::trash( $can );
|
||||
$can = $this->createCanForBean();
|
||||
asrt( R::count( 'bean' ), 1 );
|
||||
R::trash( $can );
|
||||
asrt( R::count( 'bean' ), 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue #171
|
||||
* The index name argument is not unique in processEmbeddedBean etc.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIssue171()
|
||||
{
|
||||
R::getDatabaseAdapter()->addEventListener( 'sql_exec', $this );
|
||||
$account = R::dispense( 'account' );
|
||||
$user = R::dispense( 'user' );
|
||||
$player = R::dispense( 'player' );
|
||||
$account->ownUser[] = $user;
|
||||
R::store( $account );
|
||||
asrt( strpos( implode( ',', $this->queries ), 'index_foreignkey_user_account' ) !== FALSE, TRUE );
|
||||
$this->queries = array();
|
||||
$account->ownPlayer[] = $player;
|
||||
R::store( $account );
|
||||
asrt( strpos( implode( ',', $this->queries ), 'index_foreignkey_player_accou' ) !== FALSE, TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether foreign keys are created correctly for certain
|
||||
* relations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCreationOfForeignKeys()
|
||||
{
|
||||
$this->queries = array();
|
||||
$account = R::dispense( 'account' );
|
||||
$user = R::dispense( 'user' );
|
||||
$player = R::dispense( 'player' );
|
||||
$user->account = $account;
|
||||
R::store( $user );
|
||||
asrt( strpos( implode( ',', $this->queries ), 'index_foreignkey_user_account' ) !== FALSE, TRUE );
|
||||
$this->queries = array();
|
||||
$player->account = $account;
|
||||
R::store( $player );
|
||||
asrt( strpos( implode( ',', $this->queries ), 'index_foreignkey_player_accou' ) !== FALSE, TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test helper method.
|
||||
* Creates a bean in a can. The bean will get a reference
|
||||
* to the can and can be made dependent.
|
||||
*
|
||||
* @return OODBBean $can
|
||||
*/
|
||||
private function createBeanInCan( $isExcl )
|
||||
{
|
||||
$can = R::dispense( 'can' );
|
||||
$bean = R::dispense( 'bean' );
|
||||
$can->name = 'bakedbeans';
|
||||
$bean->taste = 'salty';
|
||||
if ($isExcl) {
|
||||
$can->xownBean[] = $bean;
|
||||
} else {
|
||||
$can->ownBean[] = $bean;
|
||||
}
|
||||
R::store( $can );
|
||||
return $can;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test helper method.
|
||||
* Creates a bean in a can beginning with the bean. The bean will get a reference
|
||||
* to the can and can be made dependent.
|
||||
*
|
||||
* @return OODBBean $can
|
||||
*/
|
||||
private function createCanForBean()
|
||||
{
|
||||
$can = R::dispense( 'can' );
|
||||
$bean = R::dispense( 'bean' );
|
||||
$bean->can = $can;
|
||||
R::store( $bean );
|
||||
return $can;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log queries
|
||||
*
|
||||
* @param string $event
|
||||
* @param Adapter $info
|
||||
*/
|
||||
public function onEvent( $event, $info )
|
||||
{
|
||||
$this->queries[] = $info->getSQL();
|
||||
}
|
||||
}
|
||||
104
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Frozen.php
vendored
Normal file
104
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Frozen.php
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\RedException as RedException;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
|
||||
/**
|
||||
* Frozen
|
||||
*
|
||||
* Frozen mode tests
|
||||
* When I split the repositories in frozen and fluid I discovered some missed
|
||||
* code-paths in the tests.
|
||||
* These tests are here to make sure the following scenarios work properly
|
||||
* in frozen mode as well.
|
||||
*
|
||||
* @file RedUNIT/Base/Frozen.php
|
||||
* @desc Test some scenarios we haven't covered for frozen mode.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Frozen extends Base
|
||||
{
|
||||
/**
|
||||
* Tests the handling of trashed beans in frozen mode.
|
||||
* Are the lists unset etc?
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTrash()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$book->xownPageList[] = R::dispense( 'page' );
|
||||
$book->sharedTagList[] = R::dispense( 'tag' );
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
R::freeze( TRUE );
|
||||
$book->xownPageList = array();
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
asrt( R::count('page'), 0 );
|
||||
$book->xownPageList[] = R::dispense( 'page' );
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
asrt( R::count('page'), 1 );
|
||||
$book->xownPageList;
|
||||
$book->sharedTagList;
|
||||
R::trash( $book );
|
||||
asrt( R::count('book'), 0 );
|
||||
asrt( R::count('page'), 0 );
|
||||
asrt( R::count('tag'), 1 );
|
||||
asrt( R::count('book_tag'), 0 );
|
||||
R::freeze( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether invalid list checks are
|
||||
* operational in frozen mode.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testInvalidList()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$book->xownPageList[] = R::dispense( 'page' );
|
||||
$book->sharedTagList[] = R::dispense( 'tag' );
|
||||
R::store( $book );
|
||||
R::freeze( TRUE );
|
||||
$book = R::dispense( 'book' );
|
||||
$book->xownPageList[] = 'nonsense';
|
||||
try {
|
||||
R::store( $book );
|
||||
fail();
|
||||
} catch( \Exception $e ) {
|
||||
pass();
|
||||
}
|
||||
R::freeze( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether loading non-existant beans
|
||||
* returns the same results in frozen mode.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public function testLoadNonExistant()
|
||||
{
|
||||
R::nuke();
|
||||
R::store( R::dispense( 'bean' ) );
|
||||
R::freeze( TRUE );
|
||||
$bean = R::load( 'bean', 123 );
|
||||
R::freeze( FALSE );
|
||||
asrt( ( $bean instanceof OODBBean ), TRUE );
|
||||
asrt( $bean->id, 0 );
|
||||
}
|
||||
}
|
||||
420
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Fuse.php
vendored
Normal file
420
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Fuse.php
vendored
Normal file
@@ -0,0 +1,420 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\ModelHelper as ModelHelper;
|
||||
use RedBeanPHP\RedException as RedException;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
use RedBeanPHP\OODB as OODB;
|
||||
use RedBeanPHP\ToolBox as ToolBox;
|
||||
use RedBeanPHP\QueryWriter as QueryWriter;
|
||||
use RedBeanPHP\Adapter as Adapter;
|
||||
use RedBeanPHP\BeanHelper\SimpleFacadeBeanHelper as SimpleFacadeBeanHelper;
|
||||
|
||||
/**
|
||||
* FUSE
|
||||
*
|
||||
* Tests whether we can associate model logic on-the-fly
|
||||
* by defining models extending from SimpleModel. Tests
|
||||
* whether the calls to facade trigger the corresponding
|
||||
* methods on the model.
|
||||
*
|
||||
* @file RedUNIT/Base/Fuse.php
|
||||
* @desc Tests Fuse feature; coupling beans to models.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Fuse extends Base
|
||||
{
|
||||
/**
|
||||
* Hook into the jsonSerialize function #651
|
||||
* Allow models to provide a jsonSerialize return.
|
||||
* This test uses the Coffee Helper Model to add
|
||||
* a description to the JSON representation of the bean.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testFUSEJSonSerialize()
|
||||
{
|
||||
if ( phpversion() < 5.4 ) return;
|
||||
$coffee = R::dispense( 'coffee' );
|
||||
$coffee->variant = 'Tropical';
|
||||
$coffee->strength = 4;
|
||||
$json = json_encode( $coffee );
|
||||
$array = json_decode( $json, TRUE );
|
||||
asrt( isset( $array['description'] ), TRUE );
|
||||
asrt( $array['description'], 'Tropical.4' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether we can override the getModelForBean() method
|
||||
* of the BeanHelper and use a custom BeanHelper to attach a model
|
||||
* based on type.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCustomBeanHelper()
|
||||
{
|
||||
$customBeanHelper = new \SoupBeanHelper( R::getToolbox() );
|
||||
$oldBeanHelper = R::getRedBean()->getBeanHelper();
|
||||
asrt( ( $oldBeanHelper instanceof SimpleFacadeBeanHelper ), TRUE );
|
||||
R::getRedBean()->setBeanHelper( $customBeanHelper );
|
||||
$meal = R::dispense( 'meal' );
|
||||
asrt( ( $meal->box() instanceof \Model_Soup ), TRUE );
|
||||
$cake = R::dispense( 'cake' );
|
||||
asrt( is_null( $cake->box() ), TRUE );
|
||||
$bean = R::dispense( 'coffee' );
|
||||
asrt( ( $bean->box() instanceof \Model_Coffee ), TRUE );
|
||||
$meal->setFlavour( 'tomato' );
|
||||
asrt( $meal->getFlavour(), 'tomato' );
|
||||
$meal->rating = 5;
|
||||
R::store( $meal );
|
||||
asrt( $meal->getFlavour(), 'tomato' );
|
||||
$meal = $meal->unbox();
|
||||
asrt( $meal->getFlavour(), 'tomato' );
|
||||
$meal = R::findOne( 'meal' );
|
||||
asrt( ( $meal->box() instanceof \Model_Soup ), TRUE );
|
||||
asrt( $meal->getFlavour(), '' );
|
||||
$meal->setFlavour( 'tomato' );
|
||||
asrt( $meal->getFlavour(), 'tomato' );
|
||||
$meal = $meal->unbox();
|
||||
asrt( $meal->getFlavour(), 'tomato' );
|
||||
R::getRedBean()->setBeanHelper( $oldBeanHelper );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test FUSE hooks (i.e. open, update, update_after etc..)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testHooks()
|
||||
{
|
||||
R::nuke();
|
||||
$probe = R::dispense( 'probe' );
|
||||
$probe->name = 'test';
|
||||
asrt( $probe->getLogActionCount(), 1 );
|
||||
asrt( $probe->getLogActionCount( 'dispense' ), 1 );
|
||||
asrt( $probe->getLogActionCount( 'open' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'update' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'after_update' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'delete' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'after_delete' ), 0 );
|
||||
asrt( ( $probe->getDataFromLog( 0, 'bean' ) === $probe ), TRUE );
|
||||
R::store( $probe );
|
||||
asrt( $probe->getLogActionCount(), 3 );
|
||||
asrt( $probe->getLogActionCount( 'dispense' ), 1 );
|
||||
asrt( $probe->getLogActionCount( 'open' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'update' ), 1 );
|
||||
asrt( $probe->getLogActionCount( 'after_update' ), 1 );
|
||||
asrt( $probe->getLogActionCount( 'delete' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'after_delete' ), 0 );
|
||||
asrt( ( $probe->getDataFromLog( 2, 'bean' ) === $probe ), TRUE );
|
||||
$probe = R::load( 'probe', $probe->id );
|
||||
asrt( $probe->getLogActionCount(), 2 );
|
||||
asrt( $probe->getLogActionCount( 'dispense' ), 1 );
|
||||
asrt( $probe->getLogActionCount( 'open' ), 1 );
|
||||
asrt( $probe->getLogActionCount( 'update' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'after_update' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'delete' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'after_delete' ), 0 );
|
||||
asrt( ( $probe->getDataFromLog( 0, 'bean' ) === $probe ), TRUE );
|
||||
asrt( ( $probe->getDataFromLog( 1, 'id' ) === $probe->id ), TRUE );
|
||||
$probe->clearLog();
|
||||
R::trash( $probe );
|
||||
asrt( $probe->getLogActionCount(), 2 );
|
||||
asrt( $probe->getLogActionCount( 'dispense' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'open' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'update' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'after_update' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'delete' ), 1 );
|
||||
asrt( $probe->getLogActionCount( 'after_delete' ), 1 );
|
||||
asrt( ( $probe->getDataFromLog( 0, 'bean' ) === $probe ), TRUE );
|
||||
asrt( ( $probe->getDataFromLog( 1, 'bean' ) === $probe ), TRUE );
|
||||
//less 'normal scenarios'
|
||||
$probe = R::dispense( 'probe' );
|
||||
$probe->name = 'test';
|
||||
asrt( $probe->getLogActionCount(), 1 );
|
||||
asrt( $probe->getLogActionCount( 'dispense' ), 1 );
|
||||
asrt( $probe->getLogActionCount( 'open' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'update' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'after_update' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'delete' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'after_delete' ), 0 );
|
||||
asrt( ( $probe->getDataFromLog( 0, 'bean' ) === $probe ), TRUE );
|
||||
R::store( $probe );
|
||||
asrt( $probe->getLogActionCount(), 3 );
|
||||
asrt( $probe->getLogActionCount( 'dispense' ), 1 );
|
||||
asrt( $probe->getLogActionCount( 'open' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'update' ), 1 );
|
||||
asrt( $probe->getLogActionCount( 'after_update' ), 1 );
|
||||
asrt( $probe->getLogActionCount( 'delete' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'after_delete' ), 0 );
|
||||
asrt( ( $probe->getDataFromLog( 2, 'bean' ) === $probe ), TRUE );
|
||||
asrt( $probe->getMeta( 'tainted' ), FALSE );
|
||||
asrt( $probe->getMeta( 'changed' ), FALSE );
|
||||
R::store( $probe ); //not tainted, no FUSE save!
|
||||
asrt( $probe->getLogActionCount(), 3 );
|
||||
asrt( $probe->getLogActionCount( 'dispense' ), 1 );
|
||||
asrt( $probe->getLogActionCount( 'open' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'update' ), 1 );
|
||||
asrt( $probe->getLogActionCount( 'after_update' ), 1 );
|
||||
asrt( $probe->getLogActionCount( 'delete' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'after_delete' ), 0 );
|
||||
asrt( ( $probe->getDataFromLog( 2, 'bean' ) === $probe ), TRUE );
|
||||
$probe->xownProbeList[] = R::dispense( 'probe' );
|
||||
//tainted, not changed, triggers FUSE
|
||||
asrt( $probe->getMeta( 'tainted' ), TRUE );
|
||||
asrt( $probe->getMeta( 'changed' ), FALSE );
|
||||
R::store( $probe );
|
||||
asrt( $probe->getMeta( 'tainted' ), FALSE );
|
||||
asrt( $probe->getMeta( 'changed' ), FALSE );
|
||||
asrt( $probe->getLogActionCount(), 5 );
|
||||
asrt( $probe->getLogActionCount( 'dispense' ), 1 );
|
||||
asrt( $probe->getLogActionCount( 'open' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'update' ), 2 );
|
||||
asrt( $probe->getLogActionCount( 'after_update' ), 2 );
|
||||
asrt( $probe->getLogActionCount( 'delete' ), 0 );
|
||||
asrt( $probe->getLogActionCount( 'after_delete' ), 0 );
|
||||
asrt( ( $probe->getDataFromLog( 2, 'bean' ) === $probe ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the SimpleFacadeBeanHelper factory setter.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testFactory()
|
||||
{
|
||||
SimpleFacadeBeanHelper::setFactoryFunction( function( $name ) {
|
||||
$model = new $name();
|
||||
$model->setNote( 'injected', 'dependency' );
|
||||
return $model;
|
||||
} );
|
||||
$bean = R::dispense( 'band' )->box();
|
||||
asrt( ( $bean instanceof \Model_Band ), TRUE );
|
||||
asrt( ( $bean->getNote('injected') ), 'dependency' );
|
||||
SimpleFacadeBeanHelper::setFactoryFunction( NULL );
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that beans of type book_page can be fused with
|
||||
* models like BookPage (beautified) as well as Book_Page (non-beautified).
|
||||
*/
|
||||
public function testBeutificationOfLinkModel()
|
||||
{
|
||||
$page = R::dispense( 'page' );
|
||||
$widget = R::dispense( 'widget' );
|
||||
$page->sharedWidgetList[] = $widget;
|
||||
R::store( $page );
|
||||
$testReport = \Model_PageWidget::getTestReport();
|
||||
asrt( $testReport, 'didSave' );
|
||||
$page = R::dispense( 'page' );
|
||||
$gadget = R::dispense( 'gadget' );
|
||||
$page->sharedGadgetList[] = $gadget;
|
||||
R::store( $page );
|
||||
$testReport = \Model_Gadget_Page::getTestReport();
|
||||
asrt( $testReport, 'didSave' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Only theoretical.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTheoreticalBeautifications()
|
||||
{
|
||||
$bean = R::dispense('bean');
|
||||
$bean->setMeta('type', 'a_b_c');
|
||||
R::store($bean);
|
||||
$testReport = \Model_A_B_C::getTestReport();
|
||||
asrt( $testReport, 'didSave' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test extraction of toolbox.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGetExtractedToolBox()
|
||||
{
|
||||
$helper = new SimpleFacadeBeanHelper;
|
||||
list( $redbean, $database, $writer, $toolbox ) = $helper->getExtractedToolbox();
|
||||
asrt( ( $redbean instanceof OODB ), TRUE );
|
||||
asrt( ( $database instanceof Adapter ), TRUE );
|
||||
asrt( ( $writer instanceof QueryWriter ), TRUE );
|
||||
asrt( ( $toolbox instanceof ToolBox ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test FUSE and model formatting.
|
||||
*
|
||||
* @todo move tagging tests to tag tester.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testFUSE()
|
||||
{
|
||||
$toolbox = R::getToolBox();
|
||||
$adapter = $toolbox->getDatabaseAdapter();
|
||||
$blog = R::dispense( 'blog' );
|
||||
$blog->title = 'testing';
|
||||
$blog->blog = 'tesing';
|
||||
R::store( $blog );
|
||||
$blogpost = R::load( "blog", 1 );
|
||||
$post = R::dispense( "post" );
|
||||
$post->message = "hello";
|
||||
$blog->sharedPost[] = $post;
|
||||
R::store($blog);
|
||||
$a = R::getAll( "select * from blog " );
|
||||
R::tag( $post, "lousy,smart" );
|
||||
asrt( implode( ',', R::tag( $post ) ), "lousy,smart" );
|
||||
R::tag( $post, "clever,smart" );
|
||||
$tagz = implode( ',', R::tag( $post ) );
|
||||
asrt( ( $tagz == "smart,clever" || $tagz == "clever,smart" ), TRUE );
|
||||
R::tag( $blog, array( "smart", "interesting" ) );
|
||||
asrt( implode( ',', R::tag( $blog ) ), "smart,interesting" );
|
||||
try {
|
||||
R::tag( $blog, array( "smart", "interesting", "lousy!" ) );
|
||||
pass();
|
||||
} catch ( RedException $e ) {
|
||||
fail();
|
||||
}
|
||||
asrt( implode( ',', R::tag( $blog ) ), "smart,interesting,lousy!" );
|
||||
asrt( implode( ",", R::tag( $blog ) ), "smart,interesting,lousy!" );
|
||||
R::untag( $blog, array( "smart", "interesting" ) );
|
||||
asrt( implode( ",", R::tag( $blog ) ), "lousy!" );
|
||||
asrt( R::hasTag( $blog, array( "lousy!" ) ), TRUE );
|
||||
asrt( R::hasTag( $blog, array( "lousy!", "smart" ) ), TRUE );
|
||||
asrt( R::hasTag( $blog, array( "lousy!", "smart" ), TRUE ), FALSE );
|
||||
R::tag( $blog, FALSE );
|
||||
asrt( count( R::tag( $blog ) ), 0 );
|
||||
R::tag( $blog, array( "funny", "comic" ) );
|
||||
asrt( count( R::tag( $blog ) ), 2 );
|
||||
R::addTags( $blog, array( "halloween" ) );
|
||||
asrt( count( R::tag( $blog ) ), 3 );
|
||||
asrt( R::hasTag( $blog, array( "funny", "commic", "halloween" ), TRUE ), FALSE );
|
||||
R::unTag( $blog, array( "funny" ) );
|
||||
R::addTags( $blog, "horror" );
|
||||
asrt( count( R::tag( $blog ) ), 3 );
|
||||
asrt( R::hasTag( $blog, array( "horror", "commic", "halloween" ), TRUE ), FALSE );
|
||||
// No double tags
|
||||
R::addTags( $blog, "horror" );
|
||||
asrt( R::hasTag( $blog, array( "horror", "commic", "halloween" ), TRUE ), FALSE );
|
||||
asrt( count( R::tag( $blog ) ), 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test error handling options FUSE.
|
||||
*/
|
||||
public function testModelErrorHandling()
|
||||
{
|
||||
$test = R::dispense( 'feed' );
|
||||
$test->nonExistantMethod();
|
||||
pass();
|
||||
$old = R::setErrorHandlingFUSE( OODBBean::C_ERR_LOG );
|
||||
asrt( is_array( $old ), TRUE );
|
||||
asrt( count( $old ), 2 );
|
||||
asrt( $old[0], FALSE );
|
||||
asrt( $old[1], NULL);
|
||||
$test->nonExistantMethod(); //we cant really test this... :(
|
||||
pass();
|
||||
$old = R::setErrorHandlingFUSE( OODBBean::C_ERR_NOTICE );
|
||||
asrt( is_array( $old ), TRUE );
|
||||
asrt( count( $old ), 2 );
|
||||
asrt( $old[0], OODBBean::C_ERR_LOG );
|
||||
asrt( $old[1], NULL);
|
||||
set_error_handler(function($error, $str) {
|
||||
asrt( $str, 'FUSE: method does not exist in model: nonExistantMethod' );
|
||||
}, E_USER_NOTICE);
|
||||
$test->nonExistantMethod();
|
||||
restore_error_handler();
|
||||
$old = OODBBean::setErrorHandlingFUSE( OODBBean::C_ERR_WARN );
|
||||
asrt( is_array( $old ), TRUE );
|
||||
asrt( count( $old ), 2 );
|
||||
asrt( $old[0], OODBBean::C_ERR_NOTICE );
|
||||
asrt( $old[1], NULL);
|
||||
set_error_handler(function($error, $str) {
|
||||
asrt( $str, 'FUSE: method does not exist in model: nonExistantMethod' );
|
||||
}, E_USER_WARNING);
|
||||
$test->nonExistantMethod();
|
||||
restore_error_handler();
|
||||
$old = OODBBean::setErrorHandlingFUSE( OODBBean::C_ERR_FATAL );
|
||||
asrt( is_array( $old ), TRUE );
|
||||
asrt( count( $old ), 2 );
|
||||
asrt( $old[0], OODBBean::C_ERR_WARN );
|
||||
asrt( $old[1], NULL);
|
||||
set_error_handler(function($error, $str) {
|
||||
asrt( $str, 'FUSE: method does not exist in model: nonExistantMethod' );
|
||||
}, E_USER_ERROR);
|
||||
$test->nonExistantMethod();
|
||||
restore_error_handler();
|
||||
$old = OODBBean::setErrorHandlingFUSE( OODBBean::C_ERR_EXCEPTION );
|
||||
asrt( is_array( $old ), TRUE );
|
||||
asrt( count( $old ), 2 );
|
||||
asrt( $old[0], OODBBean::C_ERR_FATAL );
|
||||
asrt( $old[1], NULL);
|
||||
try {
|
||||
$test->nonExistantMethod();
|
||||
fail();
|
||||
} catch (\Exception $e) {
|
||||
pass();
|
||||
}
|
||||
global $test_bean;
|
||||
$test_bean = $test;
|
||||
global $has_executed_error_func_fuse;
|
||||
$has_executed_error_func_fuse = FALSE;
|
||||
$old = OODBBean::setErrorHandlingFUSE( OODBBean::C_ERR_FUNC, function( $info ){
|
||||
global $has_executed_error_func_fuse;
|
||||
global $test_bean;
|
||||
$has_executed_error_func_fuse = TRUE;
|
||||
asrt( is_array( $info ), TRUE );
|
||||
asrt( $info['method'], 'nonExistantMethod' );
|
||||
asrt( json_encode( $info['bean']->export() ), json_encode( $test_bean->export() ) );
|
||||
asrt( $info['message'], 'FUSE: method does not exist in model: nonExistantMethod' );
|
||||
} );
|
||||
asrt( is_array( $old ), TRUE );
|
||||
asrt( count( $old ), 2 );
|
||||
asrt( $old[0], OODBBean::C_ERR_EXCEPTION );
|
||||
asrt( $old[1], NULL);
|
||||
$test->nonExistantMethod();
|
||||
asrt( $has_executed_error_func_fuse, TRUE );
|
||||
$old = OODBBean::setErrorHandlingFUSE( OODBBean::C_ERR_IGNORE );
|
||||
asrt( is_array( $old ), TRUE );
|
||||
asrt( count( $old ), 2 );
|
||||
asrt( $old[0], OODBBean::C_ERR_FUNC );
|
||||
asrt( is_callable( $old[1] ), TRUE );
|
||||
$old = OODBBean::setErrorHandlingFUSE( OODBBean::C_ERR_IGNORE );
|
||||
asrt( is_array( $old ), TRUE );
|
||||
asrt( count( $old ), 2 );
|
||||
asrt( $old[0], OODBBean::C_ERR_IGNORE );
|
||||
asrt( $old[1], NULL);
|
||||
try {
|
||||
OODBBean::setErrorHandlingFUSE( 900 );
|
||||
fail();
|
||||
} catch (\Exception $e) {
|
||||
pass();
|
||||
asrt( $e->getMessage(), 'Invalid error mode selected' );
|
||||
}
|
||||
try {
|
||||
OODBBean::setErrorHandlingFUSE( OODBBean::C_ERR_FUNC, 'hello' );
|
||||
fail();
|
||||
} catch (\Exception $e) {
|
||||
pass();
|
||||
asrt( $e->getMessage(), 'Invalid error handler' );
|
||||
}
|
||||
OODBBean::setErrorHandlingFUSE( OODBBean::C_ERR_EXCEPTION );
|
||||
//make sure ignore FUSE events
|
||||
$test = R::dispense('feed');
|
||||
R::store( $test );
|
||||
$test = $test->fresh();
|
||||
R::trash( $test );
|
||||
pass();
|
||||
OODBBean::setErrorHandlingFUSE( OODBBean::C_ERR_IGNORE );
|
||||
}
|
||||
}
|
||||
175
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Hybrid.php
vendored
Normal file
175
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Hybrid.php
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
|
||||
/**
|
||||
* Hybrid
|
||||
*
|
||||
* Test Hybrid mode where the database can be unfozen
|
||||
* in case of an exception during storing.
|
||||
*
|
||||
* @file RedUNIT/Base/Hybrid.php
|
||||
* @desc Tests hybrid mode
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Hybrid extends Base
|
||||
{
|
||||
/**
|
||||
* Tests hybrid mode.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testHybrid()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense('book');
|
||||
$book->pages = 123;
|
||||
$id = R::store( $book );
|
||||
R::freeze( TRUE );
|
||||
R::setAllowHybridMode( FALSE );
|
||||
$book->title = 'Tales of a misfit';
|
||||
try {
|
||||
R::store( $book, TRUE );
|
||||
fail();
|
||||
} catch(\Exception $e) {
|
||||
pass();
|
||||
}
|
||||
try {
|
||||
R::store( $book, FALSE );
|
||||
fail();
|
||||
} catch(\Exception $e) {
|
||||
pass();
|
||||
}
|
||||
$book = $book->fresh();
|
||||
asrt( is_null( $book->title ), TRUE );
|
||||
R::setAllowHybridMode( TRUE );
|
||||
$book->title = 'Tales of a misfit';
|
||||
try {
|
||||
R::store( $book );
|
||||
fail();
|
||||
} catch(\Exception $e) {
|
||||
pass();
|
||||
}
|
||||
try {
|
||||
R::store( $book, FALSE );
|
||||
fail();
|
||||
} catch(\Exception $e) {
|
||||
pass();
|
||||
}
|
||||
try {
|
||||
R::store( $book, TRUE );
|
||||
pass();
|
||||
} catch(\Exception $e) {
|
||||
fail();
|
||||
}
|
||||
$book = $book->fresh();
|
||||
asrt( $book->title, 'Tales of a misfit' );
|
||||
R::setAllowHybridMode( FALSE );
|
||||
R::freeze( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether we can use Hybrid mode to alter columns.
|
||||
* This won't work for SQLite.
|
||||
*/
|
||||
public function testHybridDataType()
|
||||
{
|
||||
R::nuke();
|
||||
if ($this->currentlyActiveDriverID == 'mysql') {
|
||||
R::exec('SET @@SESSION.sql_mode=\'STRICT_TRANS_TABLES\';');
|
||||
}
|
||||
if ($this->currentlyActiveDriverID == 'sqlite') return;
|
||||
$book = R::dispense('book');
|
||||
$book->pages = 1;
|
||||
$id = R::store( $book, TRUE );
|
||||
R::freeze( TRUE );
|
||||
asrt( R::getRedBean()->isFrozen(), TRUE );
|
||||
R::setAllowHybridMode( FALSE );
|
||||
$book->pages = 'too many';
|
||||
try {
|
||||
R::store( $book, TRUE );
|
||||
fail();
|
||||
} catch(\Exception $e) {
|
||||
pass();
|
||||
}
|
||||
asrt( R::getRedBean()->isFrozen(), TRUE );
|
||||
R::setAllowHybridMode( TRUE );
|
||||
asrt( R::getRedBean()->isFrozen(), TRUE );
|
||||
R::debug(1);
|
||||
try {
|
||||
R::store( $book, TRUE );
|
||||
pass();
|
||||
} catch(\Exception $e) {
|
||||
fail();
|
||||
}
|
||||
asrt( R::getRedBean()->isFrozen(), TRUE );
|
||||
$book = $book->fresh();
|
||||
echo $book;
|
||||
asrt( $book->pages, 'too many' );
|
||||
R::setAllowHybridMode( FALSE );
|
||||
R::freeze( FALSE );
|
||||
if ($this->currentlyActiveDriverID == 'mysql') {
|
||||
R::exec('SET @@SESSION.sql_mode=\'\';');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Other exceptions must fall through...
|
||||
*/
|
||||
public function testHybridNonSQLException()
|
||||
{
|
||||
R::nuke();
|
||||
$toy = R::dispense('brokentoy');
|
||||
R::freeze( TRUE );
|
||||
R::setAllowHybridMode( TRUE );
|
||||
try {
|
||||
R::store( $toy, TRUE );
|
||||
fail();
|
||||
} catch(\Exception $e) {
|
||||
pass();
|
||||
}
|
||||
R::setAllowHybridMode( FALSE );
|
||||
R::nuke();
|
||||
$toy = R::dispense('toy');
|
||||
R::freeze( TRUE );
|
||||
R::setAllowHybridMode( TRUE );
|
||||
try {
|
||||
R::store( $toy, TRUE );
|
||||
pass();
|
||||
} catch(\Exception $e) {
|
||||
fail();
|
||||
}
|
||||
R::setAllowHybridMode( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether Hybrid mode is only activated
|
||||
* for latest or 5.4 without novice and ensure
|
||||
* maintaining backward compatibility by not setting
|
||||
* Hybrid allowed for 5.3 and earlier.
|
||||
*/
|
||||
public function testVersions()
|
||||
{
|
||||
R::useFeatureSet('novice/latest');
|
||||
asrt( R::setAllowHybridMode( FALSE ), FALSE );
|
||||
R::useFeatureSet('latest');
|
||||
asrt( R::setAllowHybridMode( FALSE ), TRUE );
|
||||
R::useFeatureSet('novice/5.4');
|
||||
asrt( R::setAllowHybridMode( FALSE ), FALSE );
|
||||
R::useFeatureSet('5.4');
|
||||
asrt( R::setAllowHybridMode( FALSE ), TRUE );
|
||||
R::useFeatureSet('novice/5.3');
|
||||
asrt( R::setAllowHybridMode( FALSE ), FALSE );
|
||||
R::useFeatureSet('5.3');
|
||||
asrt( R::setAllowHybridMode( FALSE ), FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
136
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Indexes.php
vendored
Normal file
136
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Indexes.php
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
|
||||
/**
|
||||
* Indexes
|
||||
*
|
||||
* Tests whether indexes are created properly and whether
|
||||
* index creation errors are supressed (they are not important
|
||||
* enough to cause exceptions during development phase).
|
||||
*
|
||||
* @file RedUNIT/Base/Indexes.php
|
||||
* @desc Tests whether indexes are applied properly.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Indexes extends Base {
|
||||
|
||||
/**
|
||||
* Tests whether a regular index is created properly.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIndexCreation()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$page = R::dispense( 'page' );
|
||||
$book->ownPageList[] = $page;
|
||||
R::store( $book );
|
||||
$indexes = getIndexes( 'page' );
|
||||
asrt( in_array( 'index_foreignkey_page_book', $indexes ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests indexes on parent beans.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIndexCreationParentBean()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$page = R::dispense( 'page' );
|
||||
$page->book = $book;
|
||||
R::store( $page );
|
||||
$indexes = getIndexes( 'page' );
|
||||
asrt( in_array( 'index_foreignkey_page_book', $indexes ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests indexes on link tables.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIndexCreationMany2Many()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$category = R::dispense( 'category' );
|
||||
$book->sharedCategoryList[] = $category;
|
||||
R::store( $book );
|
||||
$indexes = getIndexes( 'book_category' );
|
||||
asrt( in_array( 'index_foreignkey_book_category_book', $indexes ), TRUE );
|
||||
asrt( in_array( 'index_foreignkey_book_category_category', $indexes ), TRUE );
|
||||
R::nuke();
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$category = R::dispense( 'category' );
|
||||
$category->sharedBookList[] = $book;
|
||||
R::store( $category );
|
||||
$indexes = getIndexes( 'book_category' );
|
||||
asrt( in_array( 'index_foreignkey_book_category_book', $indexes ), TRUE );
|
||||
asrt( in_array( 'index_foreignkey_book_category_category', $indexes ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests indexes on aliases.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIndexCreationAlias()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$author = R::dispense( 'author' );
|
||||
$book->coAuthor = $author;
|
||||
R::store( $book );
|
||||
$indexes = getIndexes( 'book' );
|
||||
asrt( in_array( 'index_foreignkey_book_co_author', $indexes ), TRUE );
|
||||
R::nuke();
|
||||
$project = R::dispense( 'project' );
|
||||
$person = R::dispense( 'person' );
|
||||
$person->alias( 'teacher' )->ownProject[] = $project;
|
||||
$person2 = R::dispense( 'person' );
|
||||
$person2->alias( 'student' )->ownProject[] = $project;
|
||||
R::store( $person );
|
||||
$indexes = getIndexes( 'project' );
|
||||
asrt( in_array( 'index_foreignkey_project_teacher', $indexes ), TRUE );
|
||||
R::store( $person2 );
|
||||
$indexes = getIndexes( 'project' );
|
||||
asrt( in_array( 'index_foreignkey_project_student', $indexes ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests index fails.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIndexCreationFail()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$book->author_id = '999';
|
||||
R::store( $book );
|
||||
$indexes = getIndexes( 'book' );
|
||||
//should just work fine
|
||||
asrt( in_array( 'index_foreignkey_book_author', $indexes ), TRUE );
|
||||
//these should just pass, no indexes but no errors as well
|
||||
R::getWriter()->addIndex( 'book', 'bla', 'nonexist' );
|
||||
pass();
|
||||
R::getWriter()->addIndex( 'book', '@#$', 'nonexist' );
|
||||
pass();
|
||||
R::getWriter()->addIndex( 'nonexist', 'bla', 'nonexist' );
|
||||
pass();
|
||||
$indexesAfter = getIndexes( 'book' );
|
||||
asrt( count( $indexesAfter ), count( $indexes ) );
|
||||
}
|
||||
}
|
||||
68
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Issue259.php
vendored
Normal file
68
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Issue259.php
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\SimpleModel as SimpleModel;
|
||||
|
||||
/**
|
||||
* Issue259
|
||||
*
|
||||
* Tests whether this specific issue on github has been resolved.
|
||||
* Issue #259 - Stash Cache breaks model delegation in open().
|
||||
*
|
||||
* @file RedUNIT/Base/Issue259.php
|
||||
* @desc Issue #259 - Stash cache breaks model delegation in open().
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Issue259 extends Base
|
||||
{
|
||||
/**
|
||||
* Test to make sure stash cache works with recursively opening models
|
||||
* with FUSE.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIssue259()
|
||||
{
|
||||
testpack( 'Testing Issue #259 - Stash Cache breaks model delegation in open().' );
|
||||
$mother = R::dispense( 'mother' );
|
||||
$mother->desc = 'I am mother';
|
||||
R::store( $mother );
|
||||
$child = R::dispense( 'child' );
|
||||
$child->mother = $mother;
|
||||
$child->desc = 'I am child';
|
||||
$id = R::store( $child );
|
||||
R::findOne( 'child', ' id = ?', array( $id ) );
|
||||
R::find( 'child', ' id = ? ', array( $id ) );
|
||||
R::load( 'child', $id );
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Mock Model.
|
||||
*/
|
||||
class Model_Mother extends SimpleModel
|
||||
{
|
||||
public function open()
|
||||
{
|
||||
$bean = $this->bean;
|
||||
asrt( $this->bean->desc, 'I am mother' );
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Mock Model.
|
||||
*/
|
||||
class Model_Child extends SimpleModel
|
||||
{
|
||||
public function open()
|
||||
{
|
||||
$this->bean->mother;
|
||||
asrt( $this->bean->desc, 'I am child' );
|
||||
}
|
||||
}
|
||||
55
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Issue303.php
vendored
Normal file
55
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Issue303.php
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\RedException as RedException;
|
||||
|
||||
/**
|
||||
* Issue303
|
||||
*
|
||||
* Tests whether this specific issue on github has been resolved.
|
||||
* Test whether we have two different exception messages for
|
||||
* properties and values.
|
||||
*
|
||||
* @file RedUNIT/Base/Issue303.php
|
||||
* @desc Issue #303 - Split bean property exception.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Issue303 extends Base
|
||||
{
|
||||
/**
|
||||
* Test whether we have two different exception messages for
|
||||
* properties and values.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIssue303()
|
||||
{
|
||||
testpack( 'Testing Issue #303 - Test splitting bean exception property/value.' );
|
||||
try {
|
||||
R::store( R::dispense( 'invalidbean' )->setAttr( 'invalid.property', 'value' ) );
|
||||
fail();
|
||||
} catch (RedException $e ) {
|
||||
asrt( $e->getMessage(), 'Invalid Bean property: property invalid.property' );
|
||||
}
|
||||
try {
|
||||
R::store( R::dispense( 'invalidbean' )->setAttr( 'property', array() ) );
|
||||
fail();
|
||||
} catch (RedException $e ) {
|
||||
asrt( $e->getMessage(), 'Invalid Bean value: property property' );
|
||||
}
|
||||
try {
|
||||
R::store( R::dispense( 'invalidbean' )->setAttr( 'property', new \stdClass ) );
|
||||
fail();
|
||||
} catch (RedException $e ) {
|
||||
asrt( $e->getMessage(), 'Invalid Bean value: property property' );
|
||||
}
|
||||
}
|
||||
}
|
||||
82
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Issue408.php
vendored
Normal file
82
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Issue408.php
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
|
||||
/**
|
||||
* Issue 408
|
||||
*
|
||||
* Tests whether this specific issue on github has been resolved.
|
||||
* Tests whether we can use export on beans having arrays in properties.
|
||||
*
|
||||
* @file RedUNIT/Mysql/Issue408.php
|
||||
* @desc Test whether we can export beans with arrays in properties
|
||||
* (deserialized/serialized on open/update).
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Issue408 extends Base
|
||||
{
|
||||
|
||||
/**
|
||||
* In the past it was not possible to export beans
|
||||
* like 'feed' (Model_Feed).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testExportIssue()
|
||||
{
|
||||
R::nuke();
|
||||
$feed = R::dispense( 'feed' );
|
||||
$feed->post = array(
|
||||
'first',
|
||||
'second'
|
||||
);
|
||||
R::store( $feed );
|
||||
$rows = R::getAll('SELECT * FROM feed');
|
||||
asrt( $rows[0]['post'], '["first","second"]' );
|
||||
$feed = $feed->fresh();
|
||||
asrt( is_array( $feed->post ), TRUE );
|
||||
asrt( $feed->post[0], 'first' );
|
||||
asrt( $feed->post[1], 'second' );
|
||||
R::store( $feed );
|
||||
$rows = R::getAll('SELECT * FROM feed');
|
||||
asrt( $rows[0]['post'], '["first","second"]' );
|
||||
$feed = R::load( 'feed', $feed->id );
|
||||
$feed->post[] = 'third';
|
||||
R::store( $feed );
|
||||
$rows = R::getAll('SELECT * FROM feed');
|
||||
asrt( $rows[0]['post'], '["first","second","third"]' );
|
||||
$feed = $feed->fresh();
|
||||
asrt( is_array( $feed->post ), TRUE );
|
||||
asrt( $feed->post[0], 'first' );
|
||||
asrt( $feed->post[1], 'second' );
|
||||
asrt( $feed->post[2], 'third' );
|
||||
//now the catch: can we use export?
|
||||
//PHP Fatal error: Call to a member function export() on a non-object
|
||||
$feeds = R::exportAll( R::find( 'feed' ) );
|
||||
asrt( is_array( $feeds ), TRUE );
|
||||
$feed = reset( $feeds );
|
||||
asrt( $feed['post'][0], 'first' );
|
||||
asrt( $feed['post'][1], 'second' );
|
||||
asrt( $feed['post'][2], 'third' );
|
||||
//can we also dup()?
|
||||
$feedOne = R::findOne( 'feed' );
|
||||
R::store( R::dup( $feedOne ) );
|
||||
asrt( R::count( 'feed' ), 2 );
|
||||
//can we delete?
|
||||
R::trash( $feedOne );
|
||||
asrt( R::count( 'feed' ), 1 );
|
||||
$feedTwo = R::findOne( 'feed' );
|
||||
$feed = $feedTwo->export();
|
||||
asrt( $feed['post'][0], 'first' );
|
||||
asrt( $feed['post'][1], 'second' );
|
||||
asrt( $feed['post'][2], 'third' );
|
||||
}
|
||||
}
|
||||
52
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Issue841.php
vendored
Normal file
52
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Issue841.php
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
|
||||
/**
|
||||
* Issue 841
|
||||
*
|
||||
* After bindFunc() Shared List cannot remove items.
|
||||
*
|
||||
* @file RedUNIT/Base/Issue841.php
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Issue841 extends Base
|
||||
{
|
||||
|
||||
/**
|
||||
* After bindFunc() Shared List cannot remove items.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIssue841()
|
||||
{
|
||||
R::nuke();
|
||||
R::bindFunc( 'read', 'record.point', 'abs' );
|
||||
R::bindFunc( 'write', 'record.point', 'abs' );
|
||||
for($i = 0;$i < 3;$i++){
|
||||
$tag = R::dispense('tag');
|
||||
$tag->name = 'TAG_'.$i;
|
||||
R::store($tag);
|
||||
}
|
||||
$record = R::dispense('record');
|
||||
$record->point = rand(-100,-1);
|
||||
$record->sharedTagList[] = R::load('tag',2);
|
||||
R::store($record);
|
||||
asrt(count($record->sharedTagList),1);
|
||||
$record = R::load('record',1);
|
||||
$record->sharedTagList = array();
|
||||
R::store($record);
|
||||
$record = R::load('record',1);
|
||||
asrt(count($record->sharedTagList),0);
|
||||
R::bindFunc( 'read', 'record.point', null );
|
||||
R::bindFunc( 'write', 'record.point', null );
|
||||
}
|
||||
}
|
||||
44
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Issue90.php
vendored
Normal file
44
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Issue90.php
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
|
||||
/**
|
||||
* Issue90
|
||||
*
|
||||
* Tests whether this specific issue on github has been resolved.
|
||||
* Checking 'own' relationship, makes it impossible to trash a bean.
|
||||
*
|
||||
* @file RedUNIT/Base/Issue90.php
|
||||
* @desc Issue #90 - cannot trash bean with ownproperty if checked in model.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Issue90 extends Base
|
||||
{
|
||||
/**
|
||||
* Test for issue90.
|
||||
* Checking 'own' relationship, makes it impossible to trash a bean.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIssue90()
|
||||
{
|
||||
$s = R::dispense( 'box' );
|
||||
$s->name = 'a';
|
||||
$f = R::dispense( 'bottle' );
|
||||
$s->ownBottle[] = $f;
|
||||
R::store( $s );
|
||||
$s2 = R::dispense( 'box' );
|
||||
$s2->name = 'a';
|
||||
R::store( $s2 );
|
||||
R::trash( $s2 );
|
||||
pass();
|
||||
}
|
||||
}
|
||||
988
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Joins.php
vendored
Normal file
988
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Joins.php
vendored
Normal file
@@ -0,0 +1,988 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
|
||||
/**
|
||||
* Joins
|
||||
*
|
||||
* Tests the @joined keyword, this keyword in an SQL snippet
|
||||
* allows you to join another table and use one or more of its columns
|
||||
* in the query snippet, for instance for sorting or filtering.
|
||||
*
|
||||
* @file RedUNIT/Base/Joins.php
|
||||
* @desc Tests joins in ownLists and trees.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Joins extends Base
|
||||
{
|
||||
|
||||
private function quickTestBeans( $beans, $property ) {
|
||||
$list = array();
|
||||
foreach( $beans as $bean ) {
|
||||
$list[] = $bean->{$property};
|
||||
}
|
||||
sort($list);
|
||||
return implode(',', $list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether we can use [via] notation in parsed joins.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testParsedJoinsWithVia()
|
||||
{
|
||||
$project1 = R::dispense('project');
|
||||
$project2 = R::dispense('project');
|
||||
$project1->title = 'project1';
|
||||
$project2->title = 'project2';
|
||||
$employee1 = R::dispense('employee');
|
||||
$employee2 = R::dispense('employee');
|
||||
$employee1->name = 'a';
|
||||
$employee2->name = 'b';
|
||||
$participant1 = R::dispense('participant');
|
||||
$participant2 = R::dispense('participant');
|
||||
$participant3 = R::dispense('participant');
|
||||
$participant1->employee = $employee1;
|
||||
$participant2->employee = $employee1;
|
||||
$participant3->employee = $employee2;
|
||||
$participant1->project = $project1;
|
||||
$participant2->project = $project2;
|
||||
$participant3->project = $project2;
|
||||
R::storeAll(array($participant1,$participant2,$participant3));
|
||||
$projects = R::find('project', ' @shared.employee[via:participant].name LIKE ? ', array('a'));
|
||||
asrt(count($projects),2);
|
||||
$projects = R::find('project', ' @shared.employee[via:participant].name LIKE ? AND project.title = ? ', array('a','project1'));
|
||||
asrt(count($projects),1);
|
||||
$projects = R::find('project', ' @shared.employee[via:participant].name LIKE ? AND project.title = ? ', array('a','project2'));
|
||||
asrt(count($projects),1);
|
||||
$projects = R::find('project', ' @shared.employee[via:participant].name LIKE ? ', array('b'));
|
||||
asrt(count($projects),1);
|
||||
$projects = R::find('project', ' @shared.employee[via:participant].name LIKE ? AND project.title = ? ', array('b','project1'));
|
||||
asrt(count($projects),0);
|
||||
$projects = R::find('project', ' @shared.employee[via:participant].name LIKE ? AND project.title = ? ', array('b','project2'));
|
||||
asrt(count($projects),1);
|
||||
/* shouldnt work if no [via:...] and no global aliases */
|
||||
$projects = R::find('project', ' @shared.participant.name LIKE ? ', array('a'));
|
||||
asrt(count($projects),0);
|
||||
$projects = R::find('project', ' @shared.participant.name LIKE ? AND project.title = ? ', array('a','project1'));
|
||||
asrt(count($projects),0);
|
||||
$projects = R::find('project', ' @shared.participant.name LIKE ? AND project.title = ? ', array('a','project2'));
|
||||
asrt(count($projects),0);
|
||||
$projects = R::find('project', ' @shared.participant.name LIKE ? ', array('b'));
|
||||
asrt(count($projects),0);
|
||||
$projects = R::find('project', ' @shared.participant.name LIKE ? AND project.title = ? ', array('b','project1'));
|
||||
asrt(count($projects),0);
|
||||
$projects = R::find('project', ' @shared.participant.name LIKE ? AND project.title = ? ', array('b','project2'));
|
||||
asrt(count($projects),0);
|
||||
R::aliases(array('work'=>'project'));
|
||||
$company1 = R::dispense('company');
|
||||
$company2 = R::dispense('company');
|
||||
$company1->work = $project1;
|
||||
$company2->work = $project2;
|
||||
R::storeAll( array( $company1, $company2 ) );
|
||||
$companies = R::find('company', ' @joined.work.shared.employee[via:participant].name LIKE ? ', array('a'));
|
||||
asrt(count($companies),2);
|
||||
$companies = R::find('company', ' @joined.work.shared.employee[via:participant].name LIKE ? AND @joined.work.title = ? ', array('a','project1'));
|
||||
asrt(count($companies),1);
|
||||
$companies = R::find('company', ' @joined.work.shared.employee[via:participant].name LIKE ? AND @joined.work.title = ? ', array('a','project2'));
|
||||
asrt(count($companies),1);
|
||||
$companies = R::find('company', ' @joined.work.shared.employee[via:participant].name LIKE ? ', array('b'));
|
||||
asrt(count($companies),1);
|
||||
$companies = R::find('company', ' @joined.work.shared.employee[via:participant].name LIKE ? AND @joined.work.title = ?', array('b','project1'));
|
||||
asrt(count($companies),0);
|
||||
$companies = R::find('company', ' @joined.work.shared.employee[via:participant].name LIKE ? AND @joined.work.title = ? ', array('b','project2'));
|
||||
asrt(count($companies),1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Can we use joins with aliases?
|
||||
* Can we perform bean->alias->ownlist and bean->fetchas->other
|
||||
* like operation in SQL as well?
|
||||
*
|
||||
* In this test:
|
||||
* Albert: Almanac, Study Guide
|
||||
* Bob: Poetry Bundle, Study Guide (coauthor)
|
||||
*
|
||||
* Texts:
|
||||
* Example -> in Study Guide (as source)
|
||||
* Essay -> in Study Guide (as book)
|
||||
* Poem -> in Poetry Bundle (as book)
|
||||
* Poem -> also in Almanac (as magazine)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testParsedJoinsWithAliasing()
|
||||
{
|
||||
R::nuke();
|
||||
R::aliases(array());
|
||||
$albert = R::dispense('person');
|
||||
$bob = R::dispense('person');
|
||||
$guide = R::dispense('book');
|
||||
$almanac= R::dispense('book');
|
||||
$poetry = R::dispense('book');
|
||||
$albert->firstname = 'Albert';
|
||||
$bob->firstname = 'Bob';
|
||||
$guide->title = 'Study Guide';
|
||||
$almanac->title = 'Almanac';
|
||||
$poetry->title = 'Poems';
|
||||
$guide->author = $albert;
|
||||
$guide->coauthor = $bob;
|
||||
$almanac->author = $albert;
|
||||
$poetry->author = $bob;
|
||||
$poem = R::dispense('text');
|
||||
$essay = R::dispense('text');
|
||||
$example = R::dispense('text');
|
||||
$poem->content = 'poem';
|
||||
$essay->content = 'essay';
|
||||
$example->content = 'example';
|
||||
$poem->magazine = $almanac;
|
||||
$poem->book = $poetry;
|
||||
$essay->book = $guide;
|
||||
$example->source = $guide;
|
||||
$fiction = R::dispense('tag');
|
||||
$nonfiction = R::dispense('tag');
|
||||
$fiction->description = 'fiction';
|
||||
$nonfiction->description = 'non-fiction';
|
||||
$example->sharedTag[] = $nonfiction;
|
||||
$poem->sharedTag[] = $fiction;
|
||||
$essay->sharedTag = array( $nonfiction, $fiction );
|
||||
R::storeAll( array( $poem, $essay, $example ) );
|
||||
$books = R::find('book', ' @joined.author.firstname = ? ', array('Bob'));
|
||||
asrt(count($books), 0);
|
||||
$books = R::find('book', ' @joined.author.firstname = ? ', array('Albert'));
|
||||
asrt(count($books), 0);
|
||||
$books = R::find('book', ' @joined.person[as:author].firstname = ? ', array('Bob'));
|
||||
asrt(count($books), 1);
|
||||
$books = R::find('book', ' @joined.person[as:author].firstname = ? ', array('Albert'));
|
||||
asrt(count($books), 2);
|
||||
R::freeze( TRUE );
|
||||
try { $books = R::find('book', ' @joined.author.firstname = ? ', array('Bob')); fail(); } catch ( \Exception $e ) { pass(); }
|
||||
try { $books = R::find('book', ' @joined.author.firstname = ? ', array('Albert')); fail(); } catch ( \Exception $e ) {pass();}
|
||||
$books = R::find('book', ' @joined.person[as:author].firstname = ? ', array('Bob'));
|
||||
asrt(count($books), 1);
|
||||
$books = R::find('book', ' @joined.person[as:author].firstname = ? ', array('Albert'));
|
||||
asrt(count($books), 2);
|
||||
R::aliases(array('author' => 'person','coauthor' => 'person'));
|
||||
$books = R::find('book', ' @joined.author.firstname = ? ', array('Bob'));
|
||||
asrt(count($books), 1);
|
||||
$books = R::find('book', ' @joined.author.firstname = ? ', array('Albert'));
|
||||
asrt(count($books), 2);
|
||||
$books = R::find('book', ' @joined.person[as:author].firstname = ? ', array('Bob'));
|
||||
asrt(count($books), 1);
|
||||
$books = R::find('book', ' @joined.person[as:author].firstname = ? ', array('Albert'));
|
||||
asrt(count($books), 2);
|
||||
R::freeze( FALSE );
|
||||
R::aliases(array());
|
||||
//If we want to find all the people who authored books like X
|
||||
$authors = R::find( 'person', ' @own.book[author].title LIKE ? ', array( '%Study%' ) );
|
||||
asrt( count($authors), 1 );
|
||||
$authors = R::find( 'person', ' @own.book[alias:author].title LIKE ? ', array( '%Study%' ) );
|
||||
asrt( count($authors), 1 );
|
||||
//yields Almanac and Poems
|
||||
$authors = R::find( 'person', ' @own.book[author].title LIKE ? ', array( '%m%' ) );
|
||||
asrt( count($authors), 2 );
|
||||
//yields Almanac and Poems
|
||||
$authors = R::find( 'person', ' @own.book[alias:author].title LIKE ? ', array( '%m%' ) );
|
||||
asrt( count($authors), 2 );
|
||||
//yields nothing
|
||||
$authors = R::find( 'person', ' @own.book[author].title LIKE ? ', array( '%x%' ) );
|
||||
asrt( count($authors), 0 );
|
||||
//yields nothing
|
||||
$authors = R::find( 'person', ' @own.book[alias:author].title LIKE ? ', array( '%x%' ) );
|
||||
asrt( count($authors), 0 );
|
||||
//If we want to find all the people who authored books starting with X
|
||||
$authors = R::find( 'person', ' @own.book[coauthor].title LIKE ? ', array( '%Study%' ) );
|
||||
asrt( count($authors), 1 );
|
||||
R::freeze( TRUE );
|
||||
$authors = R::find( 'person', ' @own.book[author].title LIKE ? ', array( '%Study%' ) );
|
||||
asrt( count($authors), 1 );
|
||||
$authors = R::find( 'person', ' @own.book[alias:author].title LIKE ? ', array( '%Study%' ) );
|
||||
asrt( count($authors), 1 );
|
||||
//yields Almanac and Poems
|
||||
$authors = R::find( 'person', ' @own.book[author].title LIKE ? ', array( '%m%' ) );
|
||||
asrt( count($authors), 2 );
|
||||
//yields Almanac and Poems
|
||||
$authors = R::find( 'person', ' @own.book[alias:author].title LIKE ? ', array( '%m%' ) );
|
||||
asrt( count($authors), 2 );
|
||||
asrt( $this->quickTestBeans( $authors, 'firstname' ), 'Albert,Bob');
|
||||
//yields nothing
|
||||
$authors = R::find( 'person', ' @own.book[author].title LIKE ? ', array( '%x%' ) );
|
||||
asrt( count($authors), 0 );
|
||||
//yields nothing
|
||||
$authors = R::find( 'person', ' @own.book[alias:author].title LIKE ? ', array( '%x%' ) );
|
||||
asrt( count($authors), 0 );
|
||||
$authors = R::find( 'person', ' @own.book[coauthor].title LIKE ? ', array( '%Study%' ) );
|
||||
asrt( count($authors), 1 );
|
||||
asrt( $this->quickTestBeans( $authors, 'firstname' ), 'Bob');
|
||||
R::freeze(FALSE);
|
||||
$books = R::find( 'book', ' @joined.person[author/coauthor].firstname = ?', array( 'Bob' ) );
|
||||
asrt( count($books), 2 );
|
||||
asrt( $this->quickTestBeans( $books, 'title' ), 'Poems,Study Guide');
|
||||
//If we want all books where the author or the coauthor is named 'Bob':
|
||||
$books = R::find( 'book', ' @joined.person[as:author/coauthor].firstname = ?', array( 'Bob' ) );
|
||||
asrt( count($books), 2 );
|
||||
asrt( $this->quickTestBeans( $books, 'title' ), 'Poems,Study Guide');
|
||||
//If we want all books where the author or the coauthor is named 'Albert':
|
||||
$books = R::find( 'book', ' @joined.person[as:author/].firstname = ?', array( 'Albert' ) );
|
||||
asrt( count($books), 2 );
|
||||
asrt( $this->quickTestBeans( $books, 'title' ), 'Almanac,Study Guide');
|
||||
$books = R::find( 'book', ' @joined.person[as:coauthor/author].firstname = ?', array( 'Albert' ) );
|
||||
asrt( count($books), 2 );
|
||||
$authors = R::find( 'person', ' @own.book[alias:author/coauthor].title LIKE ?', array( '%Study%' ) );
|
||||
asrt( count($authors), 2 );
|
||||
$authors = R::find( 'person', ' @own.book[alias:author/coauthor].title LIKE ?', array( '%Poem%' ) );
|
||||
asrt( count($authors), 1 );
|
||||
asrt( $this->quickTestBeans( $authors, 'firstname' ), 'Bob');
|
||||
$authors = R::find( 'person', ' @own.book[alias:author/coauthor].title LIKE ?', array( '%Alm%' ) );
|
||||
asrt( $this->quickTestBeans( $authors, 'firstname' ), 'Albert');
|
||||
asrt( count($authors), 1 );
|
||||
R::freeze(TRUE);
|
||||
$books = R::find( 'book', ' @joined.person[author/coauthor].firstname = ?', array( 'Bob' ) );
|
||||
asrt( count($books), 2 );
|
||||
$books = R::find( 'book', ' @joined.person[as:author/coauthor].firstname = ?', array( 'Bob' ) );
|
||||
asrt( count($books), 2 );
|
||||
$books = R::find( 'book', ' @joined.person[as:author/coauthor].firstname = ?', array( 'Albert' ) );
|
||||
asrt( count($books), 2 );
|
||||
$books = R::find( 'book', ' @joined.person[as:author/coauthor].firstname = ?', array( 'Albert' ) );
|
||||
asrt( count($books), 2 );
|
||||
$authors = R::find( 'person', ' @own.book[alias:author/coauthor].title LIKE ?', array( '%Study%' ) );
|
||||
asrt( count($authors), 2 );
|
||||
$authors = R::find( 'person', ' @own.book[alias:author/coauthor].title LIKE ?', array( '%Poem%' ) );
|
||||
asrt( count($authors), 1 );
|
||||
$authors = R::find( 'person', ' @own.book[alias:author/coauthor].title LIKE ?', array( '%Alm%' ) );
|
||||
asrt( count($authors), 1 );
|
||||
R::freeze(FALSE);
|
||||
//2 people as author/coauthor have written a book (study guide) that contains the essay
|
||||
$authors = R::find( 'person', ' @own.book[alias:author/coauthor].own.text.content = ?', array( 'essay' ) );
|
||||
asrt( count($authors), 2 );
|
||||
//2 people as author/coauthor have written a book as source that contains the example
|
||||
$authors = R::find( 'person', ' @own.book[alias:author/coauthor].own.text[alias:source].content = ?', array( 'example' ) );
|
||||
asrt( count($authors), 2 );
|
||||
//1 person as author/coauthor has written a book as magazine/source that contains the poem
|
||||
$authors = R::find( 'person', ' @own.book[alias:author/coauthor].own.text[alias:source/magazine].content = ?', array( 'poem' ) );
|
||||
asrt( count($authors), 1 );
|
||||
//If we include book, we get 2 authors because the poem is also in the poetry bundle (book)
|
||||
$authors = R::find( 'person', ' @own.book[alias:author/coauthor].own.text[alias:book/source/magazine].content = ?', array( 'poem' ) );
|
||||
asrt( count($authors), 2 );
|
||||
R::freeze(TRUE);
|
||||
//2 people as author/coauthor have written a book (study guide) that contains the essay
|
||||
$authors = R::find( 'person', ' @own.book[alias:author/coauthor].own.text.content = ?', array( 'essay' ) );
|
||||
asrt( count($authors), 2 );
|
||||
//2 people as author/coauthor have written a book as source that contains the example
|
||||
$authors = R::find( 'person', ' @own.book[alias:author/coauthor].own.text[alias:source].content = ?', array( 'example' ) );
|
||||
asrt( count($authors), 2 );
|
||||
//1 person as author/coauthor has written a book as magazine/source that contains the poem
|
||||
$authors = R::find( 'person', ' @own.book[alias:author/coauthor].own.text[alias:source/magazine].content = ?', array( 'poem' ) );
|
||||
asrt( count($authors), 1 );
|
||||
//If we include book, we get 2 authors because the poem is also in the poetry bundle (book)
|
||||
$authors = R::find( 'person', ' @own.book[alias:author/coauthor].own.text[alias:book/source/magazine].content = ?', array( 'poem' ) );
|
||||
asrt( count($authors), 2 );
|
||||
R::freeze(FALSE);
|
||||
//Get all texts in books authored by Bob
|
||||
$texts = R::find('text', ' @joined.book.joined.person[as:author].firstname = ? ',array('Bob'));
|
||||
asrt( count($texts), 1 );
|
||||
//Get all texts in books authored by Bob as author/coauthor
|
||||
$texts = R::find('text', ' @joined.book.joined.person[as:author/coauthor].firstname = ? ',array('Bob'));
|
||||
asrt( count($texts), 2 );
|
||||
//Get all texts in books as magazines or sources authored by Bob as author/coauthor
|
||||
$texts = R::find('text', ' @joined.book[as:magazine/source].joined.person[as:author/coauthor].firstname = ? ',array('Bob'));
|
||||
asrt( count($texts), 1 );
|
||||
//Get all texts in books as magazines or sources or books authored by Bob as author/coauthor
|
||||
$texts = R::find('text', ' @joined.book[as:magazine/source/book].joined.person[as:author/coauthor].firstname = ? ',array('Bob'));
|
||||
asrt( count($texts), 3 );
|
||||
//Get all texts in books as magazines or sources or books authored by Albert as author/coauthor
|
||||
$texts = R::find('text', ' @joined.book[as:magazine/source/book].joined.person[as:author/coauthor].firstname = ? ',array('Albert'));
|
||||
asrt( count($texts), 3 );
|
||||
R::freeze(TRUE);
|
||||
//Get all texts in books authored by Bob
|
||||
$texts = R::find('text', ' @joined.book.joined.person[as:author].firstname = ? ',array('Bob'));
|
||||
asrt( count($texts), 1 );
|
||||
//Get all texts in books authored by Bob as author/coauthor
|
||||
$texts = R::find('text', ' @joined.book.joined.person[as:author/coauthor].firstname = ? ',array('Bob'));
|
||||
asrt( count($texts), 2 );
|
||||
//Get all texts in books as magazines or sources authored by Bob as author/coauthor
|
||||
$texts = R::find('text', ' @joined.book[as:magazine/source].joined.person[as:author/coauthor].firstname = ? ',array('Bob'));
|
||||
asrt( count($texts), 1 );
|
||||
//Get all texts in books as magazines or sources or books authored by Bob as author/coauthor
|
||||
$texts = R::find('text', ' @joined.book[as:magazine/source/book].joined.person[as:author/coauthor].firstname = ? ',array('Bob'));
|
||||
asrt( count($texts), 3 );
|
||||
//Get all texts in books as magazines or sources or books authored by Albert as author/coauthor
|
||||
$texts = R::find('text', ' @joined.book[as:magazine/source/book].joined.person[as:author/coauthor].firstname = ? ',array('Albert'));
|
||||
asrt( count($texts), 3 );
|
||||
R::freeze(FALSE);
|
||||
//Get all texts in books as magazines or sources or books authored by Albert as author/coauthor that have been tagged
|
||||
//as non-fiction, i.e. the example text and the essay.
|
||||
$texts = R::find('text', '
|
||||
@joined.book[as:magazine/source/book].joined.person[as:author/coauthor].firstname = ?
|
||||
AND
|
||||
@shared.tag.description = ?
|
||||
',array('Albert', 'non-fiction'));
|
||||
asrt( count($texts), 2 );
|
||||
//Get all texts in books or sources or books authored by Albert as author/coauthor that have been tagged
|
||||
//as non-fiction, i.e. nothing, only the essay
|
||||
$texts = R::find('text', '
|
||||
@joined.book[as:source/book].joined.person[as:author/coauthor].firstname = ?
|
||||
AND
|
||||
@shared.tag.description = ?
|
||||
',array('Albert', 'fiction'));
|
||||
asrt( count($texts), 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Non-join keywords starting with @ should be
|
||||
* left untouched.
|
||||
*/
|
||||
public function testNonJoinsLeftUntouched()
|
||||
{
|
||||
$writer = R::getWriter();
|
||||
$types = array( 'book', 'cafe', 'bean' );
|
||||
$sqls = array(
|
||||
'@version',
|
||||
'@oined.satire',
|
||||
'@oined.satire.laugh',
|
||||
'@hared.lookalike.title',
|
||||
'@powned.by.a.hacker',
|
||||
'nothing here!',
|
||||
'shared.person.name',
|
||||
'owned.thing.name',
|
||||
'joined.thing.name',
|
||||
'shared.person.shared.tag.name',
|
||||
'owned.thing.shared.tag.name',
|
||||
'joined.thing.shared.tag.name',
|
||||
'shared.person.joined.tag.name',
|
||||
'owned.thing.joined.tag.name',
|
||||
'joined.thing.joined.tag.name',
|
||||
'shared.person.owned.tag.name',
|
||||
'owned.thing.owned.tag.name',
|
||||
'joined.thing.owned.tag.name'
|
||||
);
|
||||
$ctes = array( TRUE, FALSE );
|
||||
foreach($types as $type) {
|
||||
foreach($sqls as $sql) {
|
||||
foreach($ctes as $cte) {
|
||||
$same = $writer->parseJoin( $type, $sql, $cte );
|
||||
asrt( trim($same), trim($sql) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Can we join multiple tables with the same parent?
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMultipleJoinsSameParent()
|
||||
{
|
||||
R::nuke();
|
||||
$TheHagueNorthEnd = R::dispense(array(
|
||||
'_type' => 'painting',
|
||||
'title' => 'Northend, The Hague',
|
||||
'artist' => array(
|
||||
'_type' => 'artist',
|
||||
'name' => 'Isaac Israels',
|
||||
'sharedCategory' => array(
|
||||
array( '_type' => 'category', 'label' => 'Haagse School' )
|
||||
)
|
||||
),
|
||||
'ownDetail' => array(
|
||||
array(
|
||||
'_type' => 'detail',
|
||||
'description' => 'awnings',
|
||||
'sharedCategory' => array(
|
||||
array( '_type' => 'category', 'label' => 'object' )
|
||||
)
|
||||
),
|
||||
array(
|
||||
'_type' => 'detail',
|
||||
'description' => 'sunlight',
|
||||
'sharedCategory' => array(
|
||||
array( '_type' => 'category', 'label' => 'daytime' )
|
||||
)
|
||||
),
|
||||
)
|
||||
));
|
||||
$Nighthawks = R::dispense(array(
|
||||
'_type' => 'painting',
|
||||
'title' => 'Nighthawks',
|
||||
'artist' => array(
|
||||
'_type' => 'artist',
|
||||
'name' => 'Hopper',
|
||||
'sharedCategory' => array(
|
||||
array( '_type' => 'category', 'label' => 'American Realism' )
|
||||
)
|
||||
),
|
||||
'ownDetail' => array(
|
||||
array(
|
||||
'_type' => 'detail',
|
||||
'description' => 'percolator',
|
||||
'sharedCategory' => array(
|
||||
array( '_type' => 'category', 'label' => 'object' )
|
||||
)
|
||||
),
|
||||
array(
|
||||
'_type' => 'detail',
|
||||
'description' => 'cigarette',
|
||||
'sharedCategory' => array(
|
||||
array( '_type' => 'category', 'label' => 'object' )
|
||||
)
|
||||
),
|
||||
array(
|
||||
'_type' => 'detail',
|
||||
'description' => 'night',
|
||||
'sharedCategory' => array(
|
||||
array( '_type' => 'category', 'label' => 'nocturnal' )
|
||||
)
|
||||
)
|
||||
)
|
||||
));
|
||||
R::storeAll( array( $Nighthawks, $TheHagueNorthEnd ) );
|
||||
$paintings = R::find('painting', '
|
||||
@joined.artist.shared.category.label = ?
|
||||
OR
|
||||
@own.detail.shared.category.label= ?
|
||||
', array('American Realism', 'nocturnal'));
|
||||
asrt(count($paintings),1);
|
||||
$painting = reset($paintings);
|
||||
asrt($painting->title, 'Nighthawks');
|
||||
$paintings = R::find('painting', '
|
||||
@joined.artist.shared.category.label = ?
|
||||
OR
|
||||
@own.detail.shared.category.label= ?
|
||||
', array('Haagse School', 'daytime'));
|
||||
asrt(count($paintings),1);
|
||||
$painting = reset($paintings);
|
||||
asrt($painting->title, 'Northend, The Hague');
|
||||
$paintings = R::find('painting', '
|
||||
@own.detail.shared.category.label= ?
|
||||
', array('object'));
|
||||
asrt(count($paintings),2);
|
||||
$paintings = R::find('painting', '
|
||||
@own.detail.shared.category.label= ?
|
||||
AND @own.detail.description= ?
|
||||
', array('object', 'percolator'));
|
||||
asrt(count($paintings),1);
|
||||
$painting = reset($paintings);
|
||||
asrt($painting->title, 'Nighthawks');
|
||||
$paintings = R::find('painting', '
|
||||
@own.detail.shared.category.label= ?
|
||||
AND @own.detail.description= ?
|
||||
', array('object', 'ashtray'));
|
||||
asrt(count($paintings),0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Complex tests for the parsed joins featured.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testComplexParsedJoins()
|
||||
{
|
||||
R::nuke();
|
||||
$other = R::dispense('book');
|
||||
R::store( $other );
|
||||
$book = R::dispense('book');
|
||||
$page = R::dispense('page');
|
||||
$paragraph = R::dispense('paragraph');
|
||||
$paragraph->title = 'hello';
|
||||
$book->title = 'book';
|
||||
$book->ownPage[] = $page;
|
||||
$page->ownParagraph[] = $paragraph;
|
||||
$figure = R::dispense('figure');
|
||||
$chart = R::dispense('chart');
|
||||
$chart->title = 'results';
|
||||
$page->ownFigure[] = $figure;
|
||||
$figure->ownChart[] = $chart;
|
||||
R::store($book);
|
||||
$books = R::find('book',' @own.page.own.paragraph.title = ? OR @own.page.own.figure.own.chart.title = ?', array('hello','results'));
|
||||
asrt(count($books),1);
|
||||
$book = reset($books);
|
||||
asrt($book->title, 'book');
|
||||
R::nuke();
|
||||
R::aliases(array( 'author' => 'person' ));
|
||||
$book = R::dispense('book');
|
||||
$author = R::dispense('person');
|
||||
$detail = R::dispense('detail');
|
||||
$shop = R::dispense('shop');
|
||||
$shop->name = 'Books4you';
|
||||
$shop2 = R::dispense('shop');
|
||||
$shop2->name = 'Readers Delight';
|
||||
$author->name = 'Albert';
|
||||
$detail->title = 'Book by Albert';
|
||||
$book->ownDetailList[] = $detail;
|
||||
$book->author = $author;
|
||||
$shop->sharedBookList[] = $book;
|
||||
$book2 = R::dispense('book');
|
||||
$author2 = R::dispense('person');
|
||||
$detail2 = R::dispense('detail');
|
||||
$author2->name = 'Bert';
|
||||
$detail2->title = 'Book by Bert';
|
||||
$book2->ownDetailList[] = $detail2;
|
||||
$book2->author = $author2;
|
||||
$shop->sharedBookList[] = $book2;
|
||||
$shop2->sharedBookList[] = $book2;
|
||||
R::store($shop);
|
||||
R::store($shop2);
|
||||
//joined+own
|
||||
$books = R::find('book', ' @joined.author.name LIKE ? AND @own.detail.title LIKE ? ', array('Albert', 'Book by Albert'));
|
||||
asrt(count($books),1);
|
||||
$books = R::find('book', ' @joined.author.name LIKE ? AND @own.detail.title LIKE ? ', array('%ert%', '%Book by%'));
|
||||
asrt(count($books),2);
|
||||
$books = R::find('book', ' @joined.author.name LIKE ? AND @own.detail.title LIKE ? ', array('%ert%', '%'));
|
||||
asrt(count($books),2);
|
||||
$books = R::find('book', ' @joined.author.name LIKE ? AND @own.detail.title LIKE ? ', array('%ert%', 'Old Bookshop'));
|
||||
asrt(count($books),0);
|
||||
//joined+shared
|
||||
$books = R::find('book', ' @joined.author.name LIKE ? AND @shared.shop.name LIKE ? ', array('%ert%', '%Books%'));
|
||||
asrt(count($books),2);
|
||||
$books = R::find('book', ' @joined.author.name LIKE ? AND @shared.shop.name LIKE ? ', array('%ert%', '%Read%'));
|
||||
asrt(count($books),1);
|
||||
$books = R::find('book', ' @joined.author.name LIKE ? AND @shared.shop.name LIKE ? ', array('%ert%', '%'));
|
||||
asrt(count($books),2);
|
||||
$books = R::find('book', ' @joined.author.name LIKE ? AND @shared.shop.name LIKE ? ', array('%ert%', 'Old Bookshop'));
|
||||
asrt(count($books),0);
|
||||
//own+shared
|
||||
$books = R::find('book', ' @own.detail.title LIKE ? AND @shared.shop.name LIKE ? ', array('%ert%', '%Read%'));
|
||||
asrt(count($books),1);
|
||||
$books = R::find('book', ' @own.detail.title LIKE ? AND @shared.shop.name LIKE ? ', array('%ert%', '%Book%'));
|
||||
asrt(count($books),2);
|
||||
$books = R::find('book', ' @own.detail.title LIKE ? AND @shared.shop.name LIKE ? ', array('%ert%', '%'));
|
||||
asrt(count($books),2);
|
||||
$books = R::find('book', ' @own.detail.title LIKE ? AND @shared.shop.name LIKE ? ', array('%ert%', 'Old Bookshop'));
|
||||
asrt(count($books),0);
|
||||
//joined+own+shared
|
||||
$books = R::find('book', ' @joined.author.name LIKE ? AND @own.detail.title LIKE ? AND @shared.shop.name LIKE ? ', array('%ert%', '%Book by%', 'Books%'));
|
||||
asrt(count($books),2);
|
||||
$books = R::find('book', ' @joined.author.name LIKE ? AND @own.detail.title LIKE ? AND @shared.shop.name LIKE ? ', array('%ert%', '%Book by%', 'Read%'));
|
||||
asrt(count($books),1);
|
||||
$books = R::find('book', ' @joined.author.name LIKE ? AND @own.detail.title LIKE ? AND @shared.shop.name LIKE ? ', array('%ert%', '%Book by%', 'Old'));
|
||||
asrt(count($books),0);
|
||||
$books = R::find('book', ' @joined.author.name LIKE ? AND @own.detail.title LIKE ? AND @shared.shop.name LIKE ? ', array('%ert%', '%Book by%', '%'));
|
||||
asrt(count($books),2);
|
||||
//joined+joined
|
||||
$page = R::dispense('page');
|
||||
$page->text = 'Lorem Ipsum';
|
||||
$category = R::dispense('category');
|
||||
$category->name = 'biography';
|
||||
$publisher = R::dispense('publisher');
|
||||
$publisher->name = 'Good Books';
|
||||
$book->publisher = $publisher;
|
||||
$book->ownPageList[] = $page;
|
||||
$category->sharedBookList[] = $book;
|
||||
$page2 = R::dispense('page');
|
||||
$page2->text = 'Blah Blah';
|
||||
$category2 = R::dispense('category');
|
||||
$category2->name = 'fiction';
|
||||
$publisher2 = R::dispense('publisher');
|
||||
$publisher2->name = 'Gutenberg';
|
||||
$book2->publisher = $publisher2;
|
||||
$book2->ownPageList = array($page2);
|
||||
$category2->sharedBookList[] = $book2;
|
||||
R::store($category);
|
||||
R::store($category2);
|
||||
$books = R::find('book', ' @joined.author.name LIKE ? AND @joined.publisher.name LIKE ?', array('%ert%', 'Good Books'));
|
||||
asrt(count($books),1);
|
||||
$books = R::find('book', ' @joined.author.name LIKE ? AND @joined.publisher.name LIKE ?', array('%ert%', '%'));
|
||||
asrt(count($books),2);
|
||||
$books = R::find('book', ' @joined.author.name LIKE ? AND @joined.publisher.name LIKE ?', array('Unknown', '%'));
|
||||
asrt(count($books),0);
|
||||
$books = R::find('book', ' @joined.author.name LIKE ? AND @joined.publisher.name LIKE ?', array('%', '%'));
|
||||
asrt(count($books),2);
|
||||
//shared+shared
|
||||
$books = R::find('book', ' @shared.shop.name LIKE ? AND @shared.category.name LIKE ?', array('Reader%', 'fiction'));
|
||||
asrt(count($books),1);
|
||||
$books = R::find('book', ' @shared.shop.name LIKE ? AND @shared.category.name LIKE ?', array('Book%', '%'));
|
||||
asrt(count($books),2);
|
||||
$books = R::find('book', ' @shared.shop.name LIKE ? AND @shared.category.name LIKE ?', array('Book%', 'biography'));
|
||||
asrt(count($books),1);
|
||||
$books = R::find('book', ' @shared.shop.name LIKE ? AND @shared.category.name LIKE ?', array('Old Bookshop', '%'));
|
||||
asrt(count($books),0);
|
||||
$books = R::find('book', ' @shared.shop.name LIKE ? AND @shared.category.name LIKE ?', array('%', 'horror'));
|
||||
asrt(count($books),0);
|
||||
//own+own
|
||||
$books = R::find('book', ' @own.detail.title LIKE ? AND @own.page.text LIKE ?', array('Book%', 'Blah%'));
|
||||
asrt(count($books),1);
|
||||
$books = R::find('book', ' @own.detail.title LIKE ? AND @own.page.text LIKE ?', array('Book%', 'Lorem%'));
|
||||
asrt(count($books),1);
|
||||
$books = R::find('book', ' @own.detail.title LIKE ? AND @own.page.text LIKE ?', array('Book%', '%'));
|
||||
asrt(count($books),2);
|
||||
$books = R::find('book', ' @own.detail.title LIKE ? AND @own.page.text LIKE ?', array('%', '%'));
|
||||
asrt(count($books),2);
|
||||
$books = R::find('book', ' @own.detail.title LIKE ? AND @own.page.text LIKE ?', array('%', 'Nah'));
|
||||
asrt(count($books),0);
|
||||
$books = R::find('book', ' @own.detail.title LIKE ? AND @own.page.text LIKE ?', array('Nah', '%'));
|
||||
asrt(count($books),0);
|
||||
//joined+joined+shared+shared+own+own
|
||||
$books = R::find('book', ' @own.detail.title LIKE ? AND @own.page.text LIKE ?
|
||||
AND @joined.publisher.name LIKE ? AND @joined.author.name LIKE ?
|
||||
AND @shared.shop.name LIKE ? AND @shared.category.name LIKE ?', array('Book%', 'Lorem%','Good%','Albert','Books4%','bio%'));
|
||||
asrt(count($books),1);
|
||||
$books = R::find('book', ' @own.detail.title LIKE ? AND @own.page.text LIKE ?
|
||||
AND @joined.publisher.name LIKE ? AND @joined.author.name LIKE ?
|
||||
AND @shared.shop.name LIKE ? AND @shared.category.name LIKE ?', array('%', '%','%','%','%','%'));
|
||||
asrt(count($books),2);
|
||||
//in order clause
|
||||
$book = R::findOne('book', ' ORDER BY @shared.category.name ASC LIMIT 1');
|
||||
asrt($book->author->name, 'Albert');
|
||||
$book = R::findOne('book', ' ORDER BY @shared.category.name DESC LIMIT 1');
|
||||
asrt($book->author->name, 'Bert');
|
||||
$book = R::findOne('book', ' ORDER BY @own.detail.title ASC LIMIT 1');
|
||||
asrt($book->author->name, 'Albert');
|
||||
$book = R::findOne('book', ' ORDER BY @own.detail.title DESC LIMIT 1');
|
||||
asrt($book->author->name, 'Bert');
|
||||
//order+criteria
|
||||
$book = R::findOne('book', ' @joined.publisher.name LIKE ? ORDER BY @shared.category.name ASC LIMIT 1', array('%'));
|
||||
asrt($book->author->name, 'Albert');
|
||||
$book = R::findOne('book', ' @joined.publisher.name LIKE ? ORDER BY @shared.category.name DESC LIMIT 1', array('%'));
|
||||
asrt($book->author->name, 'Bert');
|
||||
$book = R::findOne('book', ' @joined.publisher.name LIKE ? ORDER BY @own.detail.title ASC LIMIT 1', array('%'));
|
||||
asrt($book->author->name, 'Albert');
|
||||
$book = R::findOne('book', ' @joined.publisher.name LIKE ? ORDER BY @own.detail.title DESC LIMIT 1', array('%'));
|
||||
asrt($book->author->name, 'Bert');
|
||||
$books = R::find('book', ' @own.detail.title LIKE ? AND @own.page.text LIKE ?
|
||||
AND @joined.publisher.name LIKE ? AND @joined.author.name LIKE ?
|
||||
AND @shared.shop.name LIKE ? AND @shared.category.name LIKE ?
|
||||
ORDER BY @own.detail.title ASC
|
||||
', array('%', '%','%','%','%','%'));
|
||||
asrt(count($books),2);
|
||||
$first = reset($books);
|
||||
$last = end($books);
|
||||
asrt($first->author->name, 'Albert');
|
||||
asrt($last->author->name, 'Bert');
|
||||
$books = R::find('book', ' @own.detail.title LIKE ? AND @own.page.text LIKE ?
|
||||
AND @joined.publisher.name LIKE ? AND @joined.author.name LIKE ?
|
||||
AND @shared.shop.name LIKE ? AND @shared.category.name LIKE ?
|
||||
ORDER BY
|
||||
@shared.shop.name DESC,
|
||||
@own.detail.title ASC
|
||||
', array('%', '%','%','%','%','%'));
|
||||
asrt(count($books),2);
|
||||
$first = reset($books);
|
||||
$last = end($books);
|
||||
asrt($first->author->name, 'Bert');
|
||||
asrt($last->author->name, 'Albert');
|
||||
$books = R::find('book', ' @own.detail.title LIKE ? AND @own.page.text LIKE ?
|
||||
AND @joined.publisher.name LIKE ? AND @joined.author.name LIKE ?
|
||||
AND @shared.shop.name LIKE ? AND @shared.category.name LIKE ?
|
||||
ORDER BY
|
||||
@joined.publisher.name ASC,
|
||||
@shared.shop.name DESC,
|
||||
@own.detail.title ASC
|
||||
', array('%', '%','%','%','%','%'));
|
||||
asrt(count($books),2);
|
||||
$first = reset($books);
|
||||
$last = end($books);
|
||||
asrt($first->author->name, 'Albert');
|
||||
asrt($last->author->name, 'Bert');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests new parsed joins.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testParsedJoins()
|
||||
{
|
||||
$person = R::dispense('person');
|
||||
$person->name = 'Albert';
|
||||
$book = R::dispense('book');
|
||||
$book->title = 'Book by Albert.';
|
||||
$book->author = $person;
|
||||
$person->movement = R::dispense(array('_type'=>'movement','name'=>'romanticism'));
|
||||
R::store( $book );
|
||||
$albert = $person;
|
||||
$person = R::dispense('person');
|
||||
$person->name = 'Bert';
|
||||
$book = R::dispense('book');
|
||||
$book->title = 'Book by Bert.';
|
||||
$book->author = $person;
|
||||
$bert = $person;
|
||||
$person->movement = R::dispense(array('_type'=>'movement','name'=>'gothic'));
|
||||
R::store( $book );
|
||||
R::aliases(array( 'author' => 'person' ));
|
||||
$books = R::find( 'book', ' @joined.author.name LIKE ? ', array('A%'));
|
||||
asrt(count($books), 1);
|
||||
$book = reset($books);
|
||||
asrt($book->title,'Book by Albert.');
|
||||
asrt($book->fetchAs('person')->author->name,'Albert');
|
||||
$people = R::find( 'person', ' @joined.movement.name = ? ', array('romanticism')); // This works (aliases not involved)
|
||||
asrt(count($people), 1);
|
||||
$people = R::find( 'person', ' @joined.movement.name = ? ', array('gothic')); // This works (aliases not involved)
|
||||
asrt(count($people), 1);
|
||||
$people = R::find( 'person', ' @joined.movement.name = ? ', array('popscience')); // This works (aliases not involved)
|
||||
asrt(count($people), 0);
|
||||
$movements = R::find( 'movement', ' @own.author.name LIKE ? ', array( 'A%' )); // This works
|
||||
asrt(count($movements), 1);
|
||||
$movement = reset($movements);
|
||||
asrt($movement->name, 'romanticism');
|
||||
R::freeze(TRUE);
|
||||
try{
|
||||
R::find( 'person', ' @own.book.title LIKE ? ', array( 'A%' )); // This doesn't work as RedBean cannot guess which column it should bind the person to in the book table.
|
||||
fail();
|
||||
} catch(\Exception $e) {
|
||||
pass();
|
||||
}
|
||||
R::freeze(FALSE);
|
||||
$group = R::dispense('group');
|
||||
$group->name = 'a';
|
||||
$group->sharedAuthorList = array($bert, $albert);
|
||||
R::store($group);
|
||||
$group = R::dispense('group');
|
||||
$group->name = 'b';
|
||||
$group->sharedAuthorList = array($bert);
|
||||
R::store($group);
|
||||
$groups = R::find( 'group', ' @shared.author.name = ? ', array( 'Bert' )); // This works
|
||||
asrt(count($groups),2);
|
||||
R::tag($albert, array('male','writer'));
|
||||
R::tag($bert, array('male'));
|
||||
$people = R::find( 'person', ' @shared.tag.title = ? ', array( 'writer' )); // This works (aliases not involved)
|
||||
asrt(count($people),1);
|
||||
R::tag($albert, array('male','writer'));
|
||||
R::tag($bert, array('male'));
|
||||
$people = R::find( 'person', ' @shared.tag.title = ? ', array( 'male' )); // This works (aliases not involved)
|
||||
asrt(count($people),2);
|
||||
$user1 = R::dispense('user');
|
||||
$user1->name = 'user1';
|
||||
$user2 = R::dispense('user');
|
||||
$user2->name = 'user2';
|
||||
$status = R::dispense('status');
|
||||
$status->whitelist = TRUE;
|
||||
$user1->status = $status;
|
||||
$status2 = R::dispense('status');
|
||||
$status2->whitelist = FALSE;
|
||||
$user2->status = $status2;
|
||||
R::storeAll(array($user1,$user2));
|
||||
$whitelisted = R::find( 'user', ' @joined.status.whitelist = ? ', array( 1 ) );
|
||||
asrt(count($whitelisted), 1);
|
||||
$user = reset($whitelisted);
|
||||
asrt($user->name, 'user1');
|
||||
$whitelisted = R::find( 'user', ' @joined.status.whitelist = ? ', array( 0 ) );
|
||||
R::debug(0);
|
||||
asrt(count($whitelisted), 1);
|
||||
$user = reset($whitelisted);
|
||||
asrt($user->name, 'user2');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests joins with ownCount().
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testJoinsInCount()
|
||||
{
|
||||
R::nuke();
|
||||
$author = R::dispense( 'author' );
|
||||
$book = R::dispense( 'book' );
|
||||
$info = R::dispense( 'info' );
|
||||
$info->title = 'x';
|
||||
$author->xownBookList[] = $book;
|
||||
$book->info = $info;
|
||||
$book = R::dispense( 'book' );
|
||||
$info = R::dispense( 'info' );
|
||||
$info->title = 'y';
|
||||
$author->xownBookList[] = $book;
|
||||
$book->info = $info;
|
||||
R::store( $author );
|
||||
$author = $author->fresh();
|
||||
$books = $author->withCondition(' @joined.info.title != ? ', array('x'))->countOwn('book');
|
||||
asrt($books, 1);
|
||||
$books = $author->withCondition(' @joined.info.title != ? ', array('y'))->countOwn('book');
|
||||
asrt($books, 1);
|
||||
$books = $author->withCondition(' @joined.info.title IN (?,?) ', array('x','y'))->countOwn('book');
|
||||
asrt($books, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for the next test.
|
||||
*
|
||||
* @param array $books the books we are going to check
|
||||
* @param string $numberList the numbers that are expected
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function checkBookNumbers( $books, $numberList )
|
||||
{
|
||||
$numbers = explode( ',', $numberList );
|
||||
asrt( is_array( $books ), TRUE );
|
||||
asrt( count( $books ), count( $numbers ) );
|
||||
$bookNumbers = '';
|
||||
$bookNumberArray = array();
|
||||
foreach( $books as $book ) {
|
||||
asrt( isset( $book->num ), TRUE );
|
||||
asrt( isset( $book->title), FALSE );
|
||||
$bookNumberArray[] = $book->num;
|
||||
}
|
||||
$bookNumbers = implode( ',', $bookNumberArray);
|
||||
asrt( $bookNumbers, $numberList );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the more complicated scenarios for
|
||||
* with-joins.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function testComplexCombinationsJoins()
|
||||
{
|
||||
$author = R::dispense( 'author' );
|
||||
$books = R::dispense( 'book', 4 );
|
||||
$books[0]->num = 0;
|
||||
$books[1]->num = 1;
|
||||
$books[2]->num = 2;
|
||||
$books[3]->num = 3;
|
||||
$books[0]->info = R::dispense('info')->setAttr('title', 'Learning PHP');
|
||||
$books[1]->info = R::dispense('info')->setAttr('title', 'Learning PHP and JavaScript');
|
||||
$books[2]->info = R::dispense('info')->setAttr('title', 'Learning Cobol');
|
||||
$books[3]->info = R::dispense('info')->setAttr('title','Gardening for Beginners');
|
||||
$books[0]->category = R::dispense('category')->setAttr('title', 'computers');
|
||||
$books[1]->category = R::dispense('category')->setAttr('title', 'computers');
|
||||
$books[2]->category = R::dispense('category')->setAttr('title', 'computers');
|
||||
$books[3]->category = R::dispense('category')->setAttr('title','gardening');
|
||||
$author->ownBookList = $books;
|
||||
R::store($author);
|
||||
//Base test...
|
||||
$books = $author->ownBookList;
|
||||
$this->checkBookNumbers( $books, '0,1,2,3' );
|
||||
//Just a basic Join...
|
||||
$books = $author->withCondition(' @joined.info.title LIKE ? ORDER BY book.num ASC ', array( '%PHP%' ) )->ownBookList;
|
||||
$this->checkBookNumbers( $books, '0,1' );
|
||||
//Mix Join and criteria
|
||||
$books = $author->withCondition(' @joined.info.title LIKE ? AND num > 0 ORDER BY book.num ASC ', array( '%PHP%' ) )->ownBookList;
|
||||
$this->checkBookNumbers( $books, '1' );
|
||||
//Basic join
|
||||
$books = $author->withCondition(' @joined.info.title LIKE ? ORDER BY book.num ASC', array( '%ing%' ) )->ownBookList;
|
||||
$this->checkBookNumbers( $books, '0,1,2,3' );
|
||||
//Two joins
|
||||
$books = $author->withCondition(' @joined.info.title LIKE ? AND @joined.category.title = ? ORDER BY book.num ASC', array( '%ing%', 'computers' ) )->ownBookList;
|
||||
$this->checkBookNumbers( $books, '0,1,2' );
|
||||
//Join the same type twice... and order
|
||||
$books = $author->withCondition(' @joined.info.title LIKE ? AND @joined.category.title = ? ORDER BY @joined.info.title ASC ', array( '%ing%', 'computers' ) )->ownBookList;
|
||||
$this->checkBookNumbers( $books, '2,0,1' );
|
||||
//Join the same type twice
|
||||
$books = $author->withCondition(' @joined.info.title LIKE ? AND @joined.info.title LIKE ? ORDER BY book.num ASC', array( '%ing%', '%Learn%' ) )->ownBookList;
|
||||
$this->checkBookNumbers( $books, '0,1,2' );
|
||||
//Join the same type 3 times and order
|
||||
$books = $author->withCondition(' @joined.info.title LIKE ? AND @joined.info.title LIKE ? ORDER BY @joined.info.title DESC', array( '%ing%', '%Learn%' ) )->ownBookList;
|
||||
$this->checkBookNumbers( $books, '1,0,2' );
|
||||
//Join the same type 3 times and order and limit
|
||||
$books = $author->withCondition(' @joined.info.title LIKE ? AND @joined.info.title LIKE ? ORDER BY @joined.info.title DESC LIMIT 1', array( '%ing%', '%Learn%' ) )->ownBookList;
|
||||
$this->checkBookNumbers( $books, '1' );
|
||||
//Other combinations I can think of...
|
||||
$books = $author->withCondition(' @joined.category.title LIKE ? ORDER BY @joined.info.title DESC', array( '%ing%' ) )->ownBookList;
|
||||
$this->checkBookNumbers( $books, '3' );
|
||||
$books = $author->withCondition(' @joined.category.title LIKE ? AND num < 4 ORDER BY @joined.info.title DESC', array( '%ing%' ) )->ownBookList;
|
||||
$this->checkBookNumbers( $books, '3' );
|
||||
//multiple ordering
|
||||
$books = $author->with(' ORDER BY @joined.category.title ASC, @joined.info.title ASC' )->ownBookList;
|
||||
$this->checkBookNumbers( $books, '2,0,1,3' );
|
||||
$books = $author->with(' ORDER BY @joined.category.title DESC, @joined.info.title ASC' )->ownBookList;
|
||||
$this->checkBookNumbers( $books, '3,2,0,1' );
|
||||
$books = $author->with(' ORDER BY @joined.category.title DESC, @joined.info.title ASC LIMIT 2' )->ownBookList;
|
||||
$this->checkBookNumbers( $books, '3,2' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the more complicated scenarios for
|
||||
* with-joins.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testComplexInFrozenMode()
|
||||
{
|
||||
R::freeze( FALSE );
|
||||
$this->testComplexCombinationsJoins();
|
||||
R::freeze( TRUE );
|
||||
$this->testComplexCombinationsJoins();
|
||||
R::freeze( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests R::setNarrowFieldMode() and
|
||||
* OODBBean::ignoreJoinFeature().
|
||||
*/
|
||||
public function testSystemWideSettingsForJoins()
|
||||
{
|
||||
R::nuke();
|
||||
$author = R::dispense( 'author' );
|
||||
$book = R::dispense( 'book' );
|
||||
$info = R::dispense( 'info' );
|
||||
$info->title = 'x';
|
||||
$author->xownBookList[] = $book;
|
||||
$book->info = $info;
|
||||
R::store( $author );
|
||||
$author = $author->fresh();
|
||||
$books = $author->withCondition(' @joined.info.title != ? ', array('y1') )->xownBookList;
|
||||
$firstBook = reset( $books );
|
||||
asrt( isset( $firstBook->title ), FALSE );
|
||||
R::setNarrowFieldMode( FALSE );
|
||||
$author = $author->fresh();
|
||||
$books = $author->withCondition(' @joined.info.title != ? ', array('y2') )->xownBookList;
|
||||
$firstBook = reset( $books );
|
||||
asrt( isset( $firstBook->title ), TRUE );
|
||||
R::setNarrowFieldMode( TRUE );
|
||||
}
|
||||
}
|
||||
71
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Keywords.php
vendored
Normal file
71
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Keywords.php
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
|
||||
/**
|
||||
* Keywords
|
||||
*
|
||||
* Tests whether we can use keywords as bean types and
|
||||
* property names without running into security or stablity issues.
|
||||
* RedBeanPHP should properly escape all bean types and properties
|
||||
* so we may use whatever string we want.
|
||||
*
|
||||
* @file RedUNIT/Base/Keywords.php
|
||||
* @desc Tests for possible keyword clashes.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Keywords extends Base
|
||||
{
|
||||
/**
|
||||
* What drivers should be loaded for this test pack?
|
||||
*
|
||||
* CUBRID has inescapable keywords :/
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTargetDrivers()
|
||||
{
|
||||
return array( 'mysql', 'pgsql', 'sqlite' ); // CUBRID excluded for now.
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if RedBeanPHP can properly handle keywords.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testKeywords()
|
||||
{
|
||||
$keywords = array(
|
||||
'anokeyword', 'znokeyword', 'group', 'drop',
|
||||
'inner', 'join', 'select', 'table',
|
||||
'int', 'cascade', 'float', 'call',
|
||||
'in', 'status', 'order', 'limit',
|
||||
'having', 'else', 'if', 'while',
|
||||
'distinct', 'like'
|
||||
);
|
||||
foreach ( $keywords as $k ) {
|
||||
R::nuke();
|
||||
$bean = R::dispense( $k );
|
||||
$bean->$k = $k;
|
||||
$id = R::store( $bean );
|
||||
$bean = R::load( $k, $id );
|
||||
$bean2 = R::dispense( 'other' );
|
||||
$bean2->name = $k;
|
||||
$bean->bean = $bean2;
|
||||
$bean->ownBean[] = $bean2;
|
||||
$bean->sharedBean[] = $bean2;
|
||||
$id = R::store( $bean );
|
||||
R::trash( $bean );
|
||||
pass();
|
||||
}
|
||||
}
|
||||
}
|
||||
42
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Largenum.php
vendored
Normal file
42
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Largenum.php
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
|
||||
/**
|
||||
* Large Number Limit Test (issue #386)
|
||||
*
|
||||
* Tests whether we can use large numbers for limit clause.
|
||||
*
|
||||
* @file RedUNIT/Base/Largenum.php
|
||||
* @desc Test whether we can use large numbers in LIMIT clause (PDO bindings).
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Largenum extends Base
|
||||
{
|
||||
/**
|
||||
* Test for issue #386.
|
||||
* Can we use large numbers in LIMIT ?
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testLargeNum()
|
||||
{
|
||||
if ( defined( 'HHVM_VERSION' ) ) return; //oops hhvm has incorrect binding for large nums.
|
||||
$number = R::dispense( 'number' );
|
||||
$number->name = 'big number';
|
||||
R::store( $number );
|
||||
//This should not cause an error... (some people use LIMIT 0, HUGE to simulate OFFSET on MYSQL).
|
||||
$beans = R::findAll( 'number', ' LIMIT ? ', array( PHP_INT_MAX ) );
|
||||
asrt( is_array( $beans ), TRUE );
|
||||
asrt( count( $beans ), 1 );
|
||||
pass();
|
||||
}
|
||||
}
|
||||
256
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Logging.php
vendored
Normal file
256
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Logging.php
vendored
Normal file
@@ -0,0 +1,256 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\Logger as Logger;
|
||||
use RedBeanPHP\Logger\RDefault as RDefault;
|
||||
use RedBeanPHP\Logger\RDefault\Debug as Debug;
|
||||
|
||||
/**
|
||||
* Logging
|
||||
*
|
||||
* Tests the Query Logging tools that are part of RedBeanPHP.
|
||||
*
|
||||
* @file RedUNIT/Base/Logging.php
|
||||
* @desc Tests Logging facilities.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Logging extends Base
|
||||
{
|
||||
/**
|
||||
* Test basic logging functionality.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBasicLogging()
|
||||
{
|
||||
R::nuke();
|
||||
R::startLogging();
|
||||
R::store( R::dispense( 'book' ) );
|
||||
$logs = R::getLogs();
|
||||
$count = count( $logs );
|
||||
asrt( ( count( $logs ) > 0 ), TRUE );
|
||||
asrt( ( R::getLogger() instanceof Logger ), TRUE );
|
||||
R::stopLogging();
|
||||
R::store( R::dispense( 'book' ) );
|
||||
$logs = R::getLogs();
|
||||
asrt( ( count( $logs ) === 0 ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for Issue #751 (Update Logger to accept parameter typed bindings):
|
||||
* While debugging some of our queries, we noticed
|
||||
* the logger would often display
|
||||
* 'Array' as value for the bindings,
|
||||
* even when the SQL query seemed to work correctly.
|
||||
* Debugging this, it appeared the debug logger did
|
||||
* not support the new parameter type bindings added in 5.3.
|
||||
* This merge request adds support for
|
||||
* the PDO::PARAM_INT and PDO::PARAM_STR
|
||||
* to the Debug logger, as well as a visible support
|
||||
* for the RPDO flagUseStringOnlyBinding flag.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIssue751()
|
||||
{
|
||||
R::nuke();
|
||||
$debugger = new Debug;
|
||||
$database = R::getDatabaseAdapter()->getDatabase();
|
||||
$database->setLogger( $debugger );
|
||||
asrt( $database->getLogger(), $debugger );
|
||||
$database->setEnableLogging( TRUE );
|
||||
$debugger->setMode( RDefault::C_LOGGER_ARRAY );
|
||||
/* debug logger with nostringonlybinding should have unquoted ints */
|
||||
R::store( R::dispense( 'book' ) );
|
||||
R::getAll( 'SELECT * FROM book WHERE id < ?', array( array( 999, \PDO::PARAM_INT ) ) );
|
||||
asrt( count( $debugger->grep('999') ), 1 );
|
||||
asrt( count( $debugger->grep('\'999\'') ), 0 );
|
||||
asrt( count( $debugger->grep('rray') ), 0 );
|
||||
$debugger->setUseStringOnlyBinding( FALSE );
|
||||
$debugger->clear();
|
||||
R::getAll( 'SELECT * FROM book WHERE id < ?', array( array( 999, \PDO::PARAM_STR ) ) );
|
||||
/* ...but quoted strings */
|
||||
asrt( count( $debugger->grep('\'999\'') ), 1 );
|
||||
asrt( count( $debugger->grep('rray') ), 0 );
|
||||
$debugger->setUseStringOnlyBinding( FALSE );
|
||||
$debugger->clear();
|
||||
/* even if PARAM INT if stringonlybinding then override */
|
||||
$debugger->setUseStringOnlyBinding( TRUE );
|
||||
R::getAll( 'SELECT * FROM book WHERE id < ?', array( array( 999, \PDO::PARAM_INT ) ) );
|
||||
asrt( count( $debugger->grep('\'999\'') ), 1 );
|
||||
asrt( count( $debugger->grep('rray') ), 0 );
|
||||
/* if no type and stringonlybinding always quote */
|
||||
$debugger->clear();
|
||||
R::getAll( 'SELECT * FROM book WHERE id < ?', array( 999 ) );
|
||||
asrt( count( $debugger->grep('\'999\'') ), 1 );
|
||||
asrt( count( $debugger->grep('rray') ), 0 );
|
||||
/* a more closer inspection */
|
||||
/* log implicit INT param without StringOnly */
|
||||
$debugger->clear();
|
||||
$debugger->setUseStringOnlyBinding( FALSE );
|
||||
$debugger->log(' Hello ? ', array( 123 ) );
|
||||
asrt( count( $debugger->grep('123') ), 1 );
|
||||
asrt( count( $debugger->grep('\'123\'') ), 0 );
|
||||
/* log implicit STR param without StringOnly */
|
||||
$debugger->clear();
|
||||
$debugger->setUseStringOnlyBinding( FALSE );
|
||||
$debugger->log(' Hello ? ', array( 'abc' ) );
|
||||
asrt( count( $debugger->grep('\'abc\'') ), 1 );
|
||||
/* log NULL param without StringOnly */
|
||||
$debugger->clear();
|
||||
$debugger->setUseStringOnlyBinding( FALSE );
|
||||
$debugger->log(' Hello ? ', array( NULL ) );
|
||||
asrt( count( $debugger->grep('NULL') ), 1 );
|
||||
asrt( count( $debugger->grep('\'NULL\'') ), 0 );
|
||||
/* log explicit INT param without StringOnly */
|
||||
$debugger->clear();
|
||||
$debugger->setUseStringOnlyBinding( FALSE );
|
||||
$debugger->log(' Hello ? ', array( 123, \PDO::PARAM_INT ) );
|
||||
asrt( count( $debugger->grep('123') ), 1 );
|
||||
asrt( count( $debugger->grep('\'123\'') ), 0 );
|
||||
/* log explicit STR param without StringOnly */
|
||||
$debugger->clear();
|
||||
$debugger->setUseStringOnlyBinding( FALSE );
|
||||
$debugger->log(' Hello ? ', array( 'abc', \PDO::PARAM_STR ) );
|
||||
asrt( count( $debugger->grep('\'abc\'') ), 1 );
|
||||
/* log NULL with explicit param type without StringOnly */
|
||||
$debugger->clear();
|
||||
$debugger->setUseStringOnlyBinding( FALSE );
|
||||
$debugger->log(' Hello ? ', array( NULL, \PDO::PARAM_STR ) );
|
||||
asrt( count( $debugger->grep('NULL') ), 1 );
|
||||
asrt( count( $debugger->grep('\'NULL\'') ), 0 );
|
||||
$debugger->clear();
|
||||
$debugger->setUseStringOnlyBinding( FALSE );
|
||||
$debugger->log(' Hello ? ', array( NULL, \PDO::PARAM_INT ) );
|
||||
asrt( count( $debugger->grep('NULL') ), 1 );
|
||||
asrt( count( $debugger->grep('\'NULL\'') ), 0 );
|
||||
/* log implicit INT param with StringOnly */
|
||||
$debugger->clear();
|
||||
$debugger->setUseStringOnlyBinding( TRUE );
|
||||
$debugger->log(' Hello ? ', array( 123 ) );
|
||||
asrt( count( $debugger->grep('\'123\'') ), 1 );
|
||||
/* log implicit STR param with StringOnly */
|
||||
$debugger->clear();
|
||||
$debugger->setUseStringOnlyBinding( TRUE );
|
||||
$debugger->log(' Hello ? ', array( 'abc' ) );
|
||||
asrt( count( $debugger->grep('\'abc\'') ), 1 );
|
||||
/* log NULL param with StringOnly */
|
||||
$debugger->clear();
|
||||
$debugger->setUseStringOnlyBinding( TRUE );
|
||||
$debugger->log(' Hello ? ', array( NULL ) );
|
||||
asrt( count( $debugger->grep('\'NULL\'') ), 1 );
|
||||
/* log explicit INT param with StringOnly */
|
||||
$debugger->clear();
|
||||
$debugger->setUseStringOnlyBinding( TRUE );
|
||||
$debugger->log(' Hello ? ', array( 123, \PDO::PARAM_INT ) );
|
||||
asrt( count( $debugger->grep('\'123\'') ), 1 );
|
||||
/* log explicit STR param with StringOnly */
|
||||
$debugger->clear();
|
||||
$debugger->setUseStringOnlyBinding( TRUE );
|
||||
$debugger->log(' Hello ? ', array( 'abc', \PDO::PARAM_STR ) );
|
||||
asrt( count( $debugger->grep('\'abc\'') ), 1 );
|
||||
/* log NULL with explicit param type with StringOnly - remains just NULL */
|
||||
$debugger->clear();
|
||||
$debugger->setUseStringOnlyBinding( FALSE );
|
||||
$debugger->log(' Hello ? ', array( NULL, \PDO::PARAM_STR ) );
|
||||
asrt( count( $debugger->grep('NULL') ), 1 );
|
||||
asrt( count( $debugger->grep('\'NULL\'') ), 0 );
|
||||
$debugger->clear();
|
||||
$debugger->setUseStringOnlyBinding( FALSE );
|
||||
$debugger->log(' Hello ? ', array( NULL, \PDO::PARAM_INT ) );
|
||||
asrt( count( $debugger->grep('NULL') ), 1 );
|
||||
asrt( count( $debugger->grep('\'NULL\'') ), 0 );
|
||||
$debugger->setUseStringOnlyBinding( FALSE );
|
||||
/* Does stringonly mode switch along with Database mode ? */
|
||||
$database->setUseStringOnlyBinding( TRUE );
|
||||
$debugger->clear();
|
||||
$debugger->log(' Hello ? ', array( 123, \PDO::PARAM_INT ) );
|
||||
asrt( count( $debugger->grep('\'123\'') ), 1 );
|
||||
$database->setUseStringOnlyBinding( FALSE );
|
||||
$debugger->clear();
|
||||
$debugger->log(' Hello ? ', array( 123, \PDO::PARAM_INT ) );
|
||||
asrt( count( $debugger->grep('\'123\'') ), 0 );
|
||||
asrt( count( $debugger->grep('123') ), 1 );
|
||||
$database->setUseStringOnlyBinding( TRUE );
|
||||
$debugger->clear();
|
||||
$debugger->log(' Hello ? ', array( 123, \PDO::PARAM_INT ) );
|
||||
asrt( count( $debugger->grep('\'123\'') ), 1 );
|
||||
$database->setUseStringOnlyBinding( FALSE );
|
||||
$debugger->setUseStringOnlyBinding( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Can we manually set a logger and enable logging?
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCanSetLogger()
|
||||
{
|
||||
R::nuke();
|
||||
R::store( R::dispense( 'bean' ) );
|
||||
$logger = new RDefault;
|
||||
$logger->setMode( RDefault::C_LOGGER_ARRAY );
|
||||
$database = R::getDatabaseAdapter()->getDatabase();
|
||||
$database->setLogger( $logger );
|
||||
asrt( $database->getLogger(), $logger );
|
||||
$database->setEnableLogging( FALSE );
|
||||
$logs = $logger->getLogs();
|
||||
asrt( is_array( $logs ), TRUE );
|
||||
asrt( count( $logs ), 0 );
|
||||
$database->setEnableLogging( TRUE );
|
||||
$logs = $logger->getLogs();
|
||||
asrt( is_array( $logs ), TRUE );
|
||||
asrt( count( $logs ), 0 );
|
||||
R::findOne( 'bean' ); //writes 3 log entries
|
||||
$logs = $logger->getLogs();
|
||||
asrt( is_array( $logs ), TRUE );
|
||||
asrt( count( $logs ), 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test query counter.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testQueryCount()
|
||||
{
|
||||
R::nuke();
|
||||
R::store( R::dispense( 'bean' ) );
|
||||
R::resetQueryCount();
|
||||
asrt( R::getQueryCount(), 0 );
|
||||
R::findOne( 'bean' );
|
||||
asrt( R::getQueryCount(), 1 );
|
||||
R::resetQueryCount();
|
||||
asrt( R::getQueryCount(), 0 );
|
||||
R::findOne( 'bean' );
|
||||
R::findOne( 'bean' );
|
||||
R::findOne( 'bean' );
|
||||
asrt( R::getQueryCount(), 0 );
|
||||
R::store( R::dispense( 'bean2' ) );
|
||||
R::resetQueryCount();
|
||||
R::findOne( 'bean' );
|
||||
R::findOne( 'bean2' );
|
||||
asrt( R::getQueryCount(), 2 );
|
||||
R::resetQueryCount();
|
||||
R::findOne( 'bean', ' id < 100' );
|
||||
R::findOne( 'bean', ' id < 101' );
|
||||
R::findOne( 'bean', ' id < 102' );
|
||||
R::findOne( 'bean', ' id < 103' );
|
||||
asrt( R::getQueryCount(), 4 );
|
||||
R::findOne( 'bean', ' id < 100' );
|
||||
R::findOne( 'bean', ' id < 101' );
|
||||
R::findOne( 'bean', ' id < 102' );
|
||||
R::findOne( 'bean', ' id < 103' );
|
||||
asrt( R::getQueryCount(), 4 );
|
||||
R::findOne( 'bean', ' id < 104' );
|
||||
asrt( R::getQueryCount(), 5 );
|
||||
}
|
||||
}
|
||||
653
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Misc.php
vendored
Normal file
653
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Misc.php
vendored
Normal file
@@ -0,0 +1,653 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\Logger\RDefault as RDefault;
|
||||
use RedBeanPHP\Logger as Logger;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
use RedBeanPHP\OODB as OODB;
|
||||
use RedBeanPHP\Adapter as Adapter;
|
||||
use RedBeanPHP\QueryWriter as QueryWriter;
|
||||
use RedBeanPHP\RedException as RedException;
|
||||
use RedBeanPHP\RedException\SQL as SQL;
|
||||
use RedBeanPHP\Driver\RPDO as RPDO;
|
||||
use RedBeanPHP\SimpleModel as SimpleModel;
|
||||
|
||||
/**
|
||||
* Misc
|
||||
*
|
||||
* @file RedUNIT/Base/Misc.php
|
||||
* @desc Various tests.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Misc extends Base
|
||||
{
|
||||
/**
|
||||
* Can we use data definition templates?
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDDLTemplates()
|
||||
{
|
||||
R::nuke();
|
||||
R::debug( TRUE, 1 );
|
||||
$writer = R::getWriter();
|
||||
$writer->setDDLTemplate( 'createTable', 'joke', $writer->getDDLTemplate( 'createTable', 'joke' ) . ' /* haha */ ' );
|
||||
$writer->setDDLTemplate( 'addColumn', 'joke', $writer->getDDLTemplate( 'addColumn', 'joke' ) . ' /* hihi */ ' );
|
||||
$writer->setDDLTemplate( 'widenColumn', 'joke', $writer->getDDLTemplate( 'widenColumn', 'joke' ) . ' /* hoho */ ' );
|
||||
$joke = R::dispense('joke');
|
||||
R::store( $joke );
|
||||
$logs = R::getDatabaseAdapter()->getDatabase()->getLogger()->grep( 'haha' );
|
||||
asrt( count( $logs ), 1 );
|
||||
$joke->punchline = 1;
|
||||
R::store( $joke );
|
||||
$logs = R::getDatabaseAdapter()->getDatabase()->getLogger()->grep( 'hihi' );
|
||||
asrt( count( $logs ), 1 );
|
||||
$joke->punchline = '...';
|
||||
R::store( $joke );
|
||||
$logs = R::getDatabaseAdapter()->getDatabase()->getLogger()->grep( 'hoho' );
|
||||
asrt( count( $logs ), 1 );
|
||||
R::debug( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Github issue:
|
||||
* Remove $NULL to directly return NULL #625
|
||||
* @@ -1097,8 +1097,7 @@ public function &__get( $property )
|
||||
* $this->all = FALSE;
|
||||
* $this->via = NULL;
|
||||
*
|
||||
* - $NULL = NULL;
|
||||
* - return $NULL;
|
||||
* + return NULL;
|
||||
*
|
||||
* leads to regression:
|
||||
* PHP Stack trace:
|
||||
* PHP 1. {main}() testje.php:0
|
||||
* PHP 2. RedBeanPHP\OODBBean->__get() testje.php:22
|
||||
* Notice: Only variable references should be returned by reference in rb.php on line 2529
|
||||
*/
|
||||
public function testReferencedGetInBeans()
|
||||
{
|
||||
$bean = R::dispense( 'bean' );
|
||||
//this will trigger notice if &__get() returns NULL instead of $NULL.#625
|
||||
$x = $bean->hello;
|
||||
pass();
|
||||
$x = $bean->reference;
|
||||
pass();
|
||||
$x = $bean->nullvalue;
|
||||
pass();
|
||||
}
|
||||
|
||||
|
||||
public static $setupPartialBeansTestDone = 0;
|
||||
/**
|
||||
* Check partial beans at setup()
|
||||
*/
|
||||
public function testPartialBeansAtSetup()
|
||||
{
|
||||
if (self::$setupPartialBeansTestDone) return; /* only needs to be tested once */
|
||||
$currentDB = R::$currentDB;
|
||||
$key = 'partialBeanBase' . time();
|
||||
$dsn = 'sqlite:/tmp/test.txt';
|
||||
$user = '';
|
||||
$pass = '';
|
||||
$frozen = FALSE;
|
||||
$partialBeans = TRUE;
|
||||
R::addDatabase( $key, $dsn, $user, $pass, $frozen, $partialBeans);
|
||||
$redbean = R::getRedBean();
|
||||
$wasItSet = $redbean->getCurrentRepository()->usePartialBeans( FALSE );
|
||||
R::selectDatabase( $key );
|
||||
$redbean = R::getRedBean();
|
||||
$wasItSet = $redbean->getCurrentRepository()->usePartialBeans( FALSE );
|
||||
asrt( $wasItSet, TRUE );
|
||||
self::$setupPartialBeansTestDone = 1;
|
||||
R::selectDatabase( $currentDB );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether we can set the 'auto clear'
|
||||
* option in OODB.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAutoClearHistory()
|
||||
{
|
||||
testpack( 'Auto clear history' );
|
||||
$book = R::dispense( 'book' );
|
||||
$book->pages = 100;
|
||||
$book->title = 'book';
|
||||
R::store( $book );
|
||||
$book = R::findOne( 'book' );
|
||||
asrt( $book->hasChanged( 'title' ), FALSE );
|
||||
$book->title = 'yes';
|
||||
R::store( $book );
|
||||
asrt( $book->hasChanged( 'title' ), TRUE );
|
||||
OODB::autoClearHistoryAfterStore( TRUE );
|
||||
$book = R::findOne( 'book' );
|
||||
asrt( $book->hasChanged( 'title' ), FALSE );
|
||||
$book->title = 'yes2';
|
||||
R::store( $book );
|
||||
asrt( $book->hasChanged( 'title' ), FALSE );
|
||||
OODB::autoClearHistoryAfterStore( FALSE );
|
||||
$book = R::findOne( 'book' );
|
||||
asrt( $book->hasChanged( 'title' ), FALSE );
|
||||
$book->title = 'yes';
|
||||
R::store( $book );
|
||||
asrt( $book->hasChanged( 'title' ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the R::inspect() method on the Facade.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testInspect() {
|
||||
|
||||
testpack( 'Test R::inspect() ' );
|
||||
R::nuke();
|
||||
R::store( R::dispense( 'book' )->setAttr( 'title', 'book' ) );
|
||||
$info = R::inspect();
|
||||
asrt( count( $info ), 1 );
|
||||
asrt( strtolower( $info[0] ), 'book' );
|
||||
$info = R::inspect( 'book' );
|
||||
asrt( count( $info ), 2 );
|
||||
$keys = array_keys( $info );
|
||||
sort($keys);
|
||||
asrt( strtolower( $keys[0] ), 'id' );
|
||||
asrt( strtolower( $keys[1] ), 'title' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether we can use the tableExist() method in OODB
|
||||
* instances directly to help us determine
|
||||
* the existance of a table.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTableExist()
|
||||
{
|
||||
R::nuke();
|
||||
R::store( R::dispense( 'book' ) );
|
||||
R::freeze( FALSE );
|
||||
asrt( R::getRedBean()->tableExists( 'book' ), TRUE );
|
||||
asrt( R::getRedBean()->tableExists( 'book2' ), FALSE );
|
||||
R::freeze( TRUE );
|
||||
asrt( R::getRedBean()->tableExists( 'book' ), TRUE );
|
||||
asrt( R::getRedBean()->tableExists( 'book2' ), FALSE );
|
||||
R::freeze( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Normally the check() method is always called indirectly when
|
||||
* dealing with beans. This test ensures we can call check()
|
||||
* directly. Even though frozen repositories do not rely on
|
||||
* bean checking to improve performance the method should still
|
||||
* offer the same functionality when called directly.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCheckDirectly()
|
||||
{
|
||||
$bean = new OODBBean;
|
||||
$bean->setProperty('id', 0);
|
||||
$bean->setMeta( 'type', 'book' );
|
||||
R::getRedBean()->check( $bean );
|
||||
$bean->setMeta( 'type', '.' );
|
||||
try {
|
||||
R::getRedBean()->check( $bean );
|
||||
fail();
|
||||
} catch ( \Exception $e ) {
|
||||
pass();
|
||||
}
|
||||
//check should remain the same even if frozen repo is used, method is public after all!
|
||||
//we dont want to break the API!
|
||||
R::freeze( TRUE );
|
||||
try {
|
||||
R::getRedBean()->check( $bean );
|
||||
fail();
|
||||
} catch ( \Exception $e ) {
|
||||
pass();
|
||||
}
|
||||
R::freeze( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Backward compatibility writer ESC-method.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testLegacyCode()
|
||||
{
|
||||
testpack( 'Test Backward compatibility methods in writer.' );
|
||||
asrt( R::getWriter()->safeColumn( 'column', TRUE ), R::getWriter()->esc( 'column', TRUE ) );
|
||||
asrt( R::getWriter()->safeColumn( 'column', FALSE ), R::getWriter()->esc( 'column', FALSE ) );
|
||||
asrt( R::getWriter()->safeTable( 'table', TRUE ), R::getWriter()->esc( 'table', TRUE ) );
|
||||
asrt( R::getWriter()->safeTable( 'table', FALSE ), R::getWriter()->esc( 'table', FALSE ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test beautification and array functions.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBeauficationAndArrayFunctions()
|
||||
{
|
||||
$bean = R::dispense( 'bean' );
|
||||
$bean->isReallyAwesome = TRUE;
|
||||
asrt( isset( $bean->isReallyAwesome ), TRUE );
|
||||
asrt( isset( $bean->is_really_awesome ), TRUE );
|
||||
unset( $bean->is_really_awesome );
|
||||
asrt( isset( $bean->isReallyAwesome ), FALSE );
|
||||
asrt( isset( $bean->is_really_awesome ), FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test beautification of column names.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBeautifulColumnNames()
|
||||
{
|
||||
testpack( 'Beautiful column names' );
|
||||
$town = R::dispense( 'town' );
|
||||
$town->isCapital = FALSE;
|
||||
$town->hasTrainStation = TRUE;
|
||||
$town->name = 'BeautyVille';
|
||||
$houses = R::dispense( 'house', 2 );
|
||||
$houses[0]->isForSale = TRUE;
|
||||
$town->ownHouse = $houses;
|
||||
R::store( $town );
|
||||
$town = R::load( 'town', $town->id );
|
||||
asrt( ( $town->isCapital == FALSE ), TRUE );
|
||||
asrt( ( $town->hasTrainStation == TRUE ), TRUE );
|
||||
asrt( ( $town->name == 'BeautyVille' ), TRUE );
|
||||
testpack( 'Accept datetime objects.' );
|
||||
$cal = R::dispense( 'calendar' );
|
||||
$cal->when = new\DateTime( '2000-01-01', new\DateTimeZone( 'Pacific/Nauru' ) );
|
||||
asrt( $cal->when, '2000-01-01 00:00:00' );
|
||||
testpack( 'Affected rows test' );
|
||||
$currentDriver = $this->currentlyActiveDriverID;
|
||||
$toolbox = R::getToolBox();
|
||||
$adapter = $toolbox->getDatabaseAdapter();
|
||||
$writer = $toolbox->getWriter();
|
||||
$redbean = $toolbox->getRedBean();
|
||||
$pdo = $adapter->getDatabase();
|
||||
$bean = $redbean->dispense( 'bean' );
|
||||
$bean->prop = 3; //make test run with strict mode as well
|
||||
$redbean->store( $bean );
|
||||
$adapter->exec( 'UPDATE bean SET prop = 2' );
|
||||
asrt( $adapter->getAffectedRows(), 1 );
|
||||
testpack( 'Testing Logger' );
|
||||
R::getDatabaseAdapter()->getDatabase()->setLogger( new RDefault );
|
||||
asrt( ( R::getDatabaseAdapter()->getDatabase()->getLogger() instanceof Logger ), TRUE );
|
||||
asrt( ( R::getDatabaseAdapter()->getDatabase()->getLogger() instanceof RDefault ), TRUE );
|
||||
$bean = R::dispense( 'bean' );
|
||||
$bean->property = 1;
|
||||
$bean->unsetAll( array( 'property' ) );
|
||||
asrt( $bean->property, NULL );
|
||||
asrt( ( $bean->setAttr( 'property', 2 ) instanceof OODBBean ), TRUE );
|
||||
asrt( $bean->property, 2 );
|
||||
asrt( preg_match( '/\d\d\d\d\-\d\d\-\d\d/', R::isoDate() ), 1 );
|
||||
asrt( preg_match( '/\d\d\d\d\-\d\d\-\d\d\s\d\d:\d\d:\d\d/', R::isoDateTime() ), 1 );
|
||||
$redbean = R::getRedBean();
|
||||
$adapter = R::getDatabaseAdapter();
|
||||
$writer = R::getWriter();
|
||||
asrt( ( $redbean instanceof OODB ), TRUE );
|
||||
asrt( ( $adapter instanceof Adapter ), TRUE );
|
||||
asrt( ( $writer instanceof QueryWriter ), TRUE );
|
||||
R::setRedBean( $redbean );
|
||||
pass(); //cant really test this
|
||||
R::setDatabaseAdapter( $adapter );
|
||||
pass(); //cant really test this
|
||||
R::setWriter( $writer );
|
||||
pass(); //cant really test this
|
||||
$u1 = R::dispense( 'user' );
|
||||
$u1->name = 'Gabor';
|
||||
$u1->login = 'g';
|
||||
$u2 = R::dispense( 'user' );
|
||||
$u2->name = 'Eric';
|
||||
$u2->login = 'e';
|
||||
R::store( $u1 );
|
||||
R::store( $u2 );
|
||||
$list = R::getAssoc( 'select login,' . R::getWriter()->esc( 'name' ) . ' from ' . R::getWriter()->esc( 'user' ) . ' ' );
|
||||
asrt( $list['e'], 'Eric' );
|
||||
asrt( $list['g'], 'Gabor' );
|
||||
$painting = R::dispense( 'painting' );
|
||||
$painting->name = 'Nighthawks';
|
||||
$id = R::store( $painting );
|
||||
testpack( 'Testing SQL Error Types' );
|
||||
foreach ( $writer->typeno_sqltype as $code => $text ) {
|
||||
asrt( is_integer( $code ), TRUE );
|
||||
asrt( is_string( $text ), TRUE );
|
||||
}
|
||||
foreach ( $writer->sqltype_typeno as $text => $code ) {
|
||||
asrt( is_integer( $code ), TRUE );
|
||||
asrt( is_string( $text ), TRUE );
|
||||
}
|
||||
testpack( 'Testing Nowhere Pt. 1 (unfrozen)' );
|
||||
foreach (
|
||||
array(
|
||||
'exec', 'getAll', 'getCell', 'getAssoc', 'getRow', 'getCol'
|
||||
)
|
||||
as $method ) {
|
||||
R::$method( 'select * from nowhere' );
|
||||
pass();
|
||||
}
|
||||
testpack( 'Testing Nowhere Pt. 2 (frozen)' );
|
||||
R::freeze( TRUE );
|
||||
foreach (
|
||||
array(
|
||||
'exec', 'getAll', 'getCell', 'getAssoc', 'getRow', 'getCol'
|
||||
)
|
||||
as $method ) {
|
||||
try {
|
||||
R::$method( 'select * from nowhere' );
|
||||
fail();
|
||||
} catch ( SQL $e ) {
|
||||
pass();
|
||||
}
|
||||
}
|
||||
R::freeze( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test reflectional functions of database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDatabaseProperties()
|
||||
{
|
||||
testpack( 'Testing Database Properties' );
|
||||
$adapter = R::getDatabaseAdapter();
|
||||
if ( method_exists( R::getDatabaseAdapter()->getDatabase(), 'getPDO' ) ){
|
||||
asrt( $adapter->getDatabase()->getPDO() instanceof \PDO, TRUE );
|
||||
}
|
||||
asrt( strlen( $adapter->getDatabase()->getDatabaseVersion() ) > 0, TRUE );
|
||||
asrt( strlen( $adapter->getDatabase()->getDatabaseType() ) > 0, TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Transactions.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTransactions()
|
||||
{
|
||||
testpack( 'transactions' );
|
||||
$false = R::begin();
|
||||
asrt( $false, FALSE );
|
||||
$bean = R::dispense( 'bean' );
|
||||
R::store( $bean );
|
||||
R::commit();
|
||||
asrt( R::count( 'bean' ), 1 );
|
||||
R::trash( $bean );
|
||||
R::setAllowFluidTransactions( TRUE );
|
||||
asrt( R::begin(), TRUE );
|
||||
$bean = R::dispense( 'bean' );
|
||||
R::store( $bean );
|
||||
asrt( R::commit(), TRUE );
|
||||
asrt( R::count( 'bean' ), 1 );
|
||||
R::trash( $bean );
|
||||
asrt( R::begin(), TRUE );
|
||||
$bean = R::dispense( 'bean' );
|
||||
R::store( $bean );
|
||||
R::rollback();
|
||||
asrt( R::count( 'bean' ), 0 );
|
||||
R::setAllowFluidTransactions( FALSE );
|
||||
R::wipe('bean');
|
||||
R::freeze( TRUE );
|
||||
R::begin();
|
||||
$bean = R::dispense( 'bean' );
|
||||
R::store( $bean );
|
||||
R::rollback();
|
||||
asrt( R::count( 'bean' ), 0 );
|
||||
R::freeze( FALSE );
|
||||
testpack( 'genSlots' );
|
||||
asrt( R::genSlots( array( 'a', 'b' ) ), '?,?' );
|
||||
asrt( R::genSlots( array( 'a' ) ), '?' );
|
||||
asrt( R::genSlots( array() ), '' );
|
||||
asrt( R::genSlots( array('a', 'b'), ' IN( %s ) ' ), ' IN( ?,? ) ' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test nested FUSE scenarios.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testFUSEnested()
|
||||
{
|
||||
testpack( 'FUSE models cant touch nested beans in update() - issue 106' );
|
||||
$spoon = R::dispense( 'spoon' );
|
||||
$spoon->name = 'spoon for test bean';
|
||||
$deep = R::dispense( 'deep' );
|
||||
$deep->name = 'deepbean';
|
||||
$item = R::dispense( 'item' );
|
||||
$item->val = 'Test';
|
||||
$item->deep = $deep;
|
||||
$test = R::dispense( 'test' );
|
||||
$test->item = $item;
|
||||
$test->sharedSpoon[] = $spoon;
|
||||
$test->isnowtainted = TRUE;
|
||||
$id = R::store( $test );
|
||||
$test = R::load( 'test', $id );
|
||||
asrt( $test->item->val, 'Test2' );
|
||||
$can = reset( $test->ownCan );
|
||||
$spoon = reset( $test->sharedSpoon );
|
||||
asrt( $can->name, 'can for bean' );
|
||||
asrt( $spoon->name, 'S2' );
|
||||
asrt( $test->item->deep->name, '123' );
|
||||
asrt( count( $test->ownCan ), 1 );
|
||||
asrt( count( $test->sharedSpoon ), 1 );
|
||||
asrt( count( $test->sharedPeas ), 10 );
|
||||
asrt( count( $test->ownChip ), 9 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests FUSE and lists, FUSE enforces no more than
|
||||
* 3 sugar cubes in coffee.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCoffeeWithSugarAndFUSE()
|
||||
{
|
||||
$coffee = R::dispense( 'coffee' );
|
||||
$coffee->size = 'XL';
|
||||
$coffee->ownSugar = R::dispense( 'sugar', 5 );
|
||||
$id = R::store( $coffee );
|
||||
$coffee = R::load( 'coffee', $id );
|
||||
asrt( count( $coffee->ownSugar ), 3 );
|
||||
$coffee->ownSugar = R::dispense( 'sugar', 2 );
|
||||
$id = R::store( $coffee );
|
||||
$coffee = R::load( 'coffee', $id );
|
||||
asrt( count( $coffee->ownSugar ), 2 );
|
||||
$cocoa = R::dispense( 'cocoa' );
|
||||
$cocoa->name = 'Fair Cocoa';
|
||||
list( $taste1, $taste2 ) = R::dispense( 'taste', 2 );
|
||||
$taste1->name = 'sweet';
|
||||
$taste2->name = 'bitter';
|
||||
$cocoa->ownTaste = array( $taste1, $taste2 );
|
||||
R::store( $cocoa );
|
||||
$cocoa->name = 'Koko';
|
||||
R::store( $cocoa );
|
||||
if ( method_exists( R::getDatabaseAdapter()->getDatabase(), 'getPDO' ) ) {
|
||||
$pdo = R::getDatabaseAdapter()->getDatabase()->getPDO();
|
||||
$driver = new RPDO( $pdo );
|
||||
pass();
|
||||
asrt( $pdo->getAttribute(\PDO::ATTR_ERRMODE ),\PDO::ERRMODE_EXCEPTION );
|
||||
asrt( $pdo->getAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE ),\PDO::FETCH_ASSOC );
|
||||
asrt( strval( $driver->GetCell( 'select 123' ) ), '123' );
|
||||
}
|
||||
$a = new SQL;
|
||||
$a->setSqlState( 'test' );
|
||||
$b = strval( $a );
|
||||
asrt( ( strpos( $b, '[test] - ' ) === 0 ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* ENUM Basic tests.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testENUMBasics() {
|
||||
asrt( R::enum( 'gender:male' )->name, 'MALE' );
|
||||
asrt( R::enum( 'country:South-Africa' )->name, 'SOUTH_AFRICA' );
|
||||
asrt( R::enum( 'tester:T@E S_t' )->name, 'T_E_S_T' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test ENUM in Queries and with short hand notation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testENUMInQuery()
|
||||
{
|
||||
testpack('Test ENUM in Query and test ENUM short notation');
|
||||
R::nuke();
|
||||
$coffee = R::dispense( 'coffee' );
|
||||
$coffee->taste = R::enum( 'flavour:mocca' );
|
||||
R::store( $coffee );
|
||||
$coffee = R::dispense( 'coffee' );
|
||||
$coffee->taste = R::enum( 'flavour:banana' );
|
||||
R::store( $coffee );
|
||||
$coffee = R::dispense( 'coffee' );
|
||||
$coffee->taste = R::enum( 'flavour:banana' );
|
||||
R::store( $coffee );
|
||||
//now we have two flavours
|
||||
asrt( R::count('flavour'), 2 );
|
||||
//use in query
|
||||
asrt( R::count( 'coffee', ' taste_id = ? ', array( R::enum( 'flavour:mocca' )->id ) ), 1);
|
||||
//use in quer with short notation
|
||||
asrt( R::count( 'coffee', ' taste_id = ? ', array( EID( 'flavour:mocca' ) ) ), 1);
|
||||
//use in query
|
||||
asrt( R::count( 'coffee', ' taste_id = ? ', array( R::enum( 'flavour:banana' )->id ) ), 2);
|
||||
//use in quer with short notation
|
||||
asrt( R::count( 'coffee', ' taste_id = ? ', array( EID( 'flavour:banana' ) ) ), 2);
|
||||
//use in query
|
||||
asrt( R::count( 'coffee', ' taste_id = ? ', array( R::enum( 'flavour:strawberry' )->id ) ), 0);
|
||||
//use in quer with short notation
|
||||
asrt( R::count( 'coffee', ' taste_id = ? ', array( EID( 'flavour:strawberry' ) ) ), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test ENUM functionality offered by Label Maker.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testENUM() {
|
||||
testpack('test ENUM');
|
||||
$coffee = R::dispense( 'coffee' );
|
||||
$coffee->taste = R::enum( 'flavour:mocca' );
|
||||
//did we create an enum?
|
||||
asrt( implode( '', R::gatherLabels( R::enum( 'flavour' ) ) ), 'MOCCA' );
|
||||
R::store( $coffee );
|
||||
$coffee = $coffee->fresh();
|
||||
//test enum identity check - with alias
|
||||
asrt( $coffee->fetchAs( 'flavour' )->taste->equals( R::enum('flavour:mocca') ), TRUE );
|
||||
asrt( $coffee->fetchAs( 'flavour' )->taste->equals( R::enum('flavour:banana') ), FALSE );
|
||||
//now we have two flavours
|
||||
asrt( R::count( 'flavour' ), 2 );
|
||||
asrt( implode( ',', R::gatherLabels( R::enum( 'flavour') ) ), 'BANANA,MOCCA' );
|
||||
$coffee->flavour = R::enum( 'flavour:mocca' );
|
||||
R::store($coffee);
|
||||
//same results, can we have multiple flavours?
|
||||
asrt( $coffee->fetchAs( 'flavour' )->taste->equals( R::enum( 'flavour:mocca' ) ), TRUE );
|
||||
asrt( $coffee->fetchAs( 'flavour' )->taste->equals( R::enum( 'flavour:banana' ) ), FALSE );
|
||||
asrt( $coffee->flavour->equals( R::enum( 'flavour:mocca' ) ), TRUE );
|
||||
//no additional mocca enum...
|
||||
asrt( R::count( 'flavour' ), 2 );
|
||||
$drink = R::dispense( 'drink' );
|
||||
$drink->flavour = R::enum( 'flavour:choco' );
|
||||
R::store( $drink );
|
||||
//now we have three!
|
||||
asrt( R::count('flavour'), 3 );
|
||||
$drink = R::load( 'drink', $drink->id );
|
||||
asrt( $drink->flavour->equals( R::enum('flavour:mint') ), FALSE );
|
||||
asrt( $drink->flavour->equals( R::enum('flavour:choco') ), TRUE );
|
||||
asrt( R::count( 'flavour' ), 4 );
|
||||
//trash should not affect flavour!
|
||||
R::trash( $drink );
|
||||
asrt( R::count( 'flavour' ), 4 );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Bean identity equality.
|
||||
*/
|
||||
public function testBeanIdentityEquality() {
|
||||
$beanA = R::dispense( 'bean' );
|
||||
$beanB = R::dispense( 'bean' );
|
||||
$beanA->id = 1;
|
||||
$beanB->id = 1;
|
||||
asrt( $beanA->equals( $beanB ), TRUE );
|
||||
asrt( $beanB->equals( $beanA ), TRUE );
|
||||
asrt( $beanA->equals( $beanA ), TRUE );
|
||||
asrt( $beanB->equals( $beanB ), TRUE );
|
||||
$beanB->id = 2;
|
||||
asrt( $beanA->equals( $beanB ), FALSE );
|
||||
asrt( $beanB->equals( $beanA ), FALSE );
|
||||
$beanA->id = '2';
|
||||
asrt( $beanA->equals( $beanB ), TRUE );
|
||||
asrt( $beanB->equals( $beanA ), TRUE );
|
||||
$beanB = R::dispense( 'carrot' );
|
||||
$beanB->id = $beanA->id;
|
||||
asrt( $beanA->equals( $beanB ), FALSE );
|
||||
asrt( $beanB->equals( $beanA ), FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if adding SimpleModles to a shared list will auto unbox them.
|
||||
*/
|
||||
public function testSharedListsAutoUnbox()
|
||||
{
|
||||
$boxedBean = R::dispense( 'boxedbean' );
|
||||
$bean = R::dispense( 'bean' );
|
||||
$model = new SimpleModel();
|
||||
$model->loadBean($boxedBean);
|
||||
$bean->ownBoxedbeanList[] = $model;
|
||||
try {
|
||||
R::store( $bean );
|
||||
pass();
|
||||
} catch ( \Exception $e ) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if we can obtain a database server version string
|
||||
* from the Facade.
|
||||
*/
|
||||
public function testGetDatabaseServerVersion()
|
||||
{
|
||||
$version = R::getDatabaseServerVersion();
|
||||
asrt(is_string($version), TRUE);
|
||||
asrt(strlen($version)>0, TRUE);
|
||||
}
|
||||
}
|
||||
103
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Namedparams.php
vendored
Normal file
103
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Namedparams.php
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
|
||||
/**
|
||||
* Namedparams
|
||||
*
|
||||
* Tests whether we can use named parameters in queries and
|
||||
* SQL snippets.
|
||||
*
|
||||
* @file RedUNIT/Base/Namedparams.php
|
||||
* @desc Test whether you can use named parameters in SQL snippets.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Namedparams extends Base
|
||||
{
|
||||
/**
|
||||
* Test usage of named parameters in SQL snippets.
|
||||
* Issue #299 on Github.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testNamedParamsInSnippets()
|
||||
{
|
||||
testpack( 'Test whether we can use named parameters in SQL snippets.' );
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$page = R::dispense( 'page' );
|
||||
$book->title = 'book';
|
||||
$book->sharedPage[] = $page;
|
||||
R::store($book);
|
||||
//should not give error like: Uncaught [HY093] - SQLSTATE[HY093]: Invalid parameter number: mixed named and positional parameters
|
||||
$books = $page->withCondition(' title = :title ', array( ':title' => 'book' ) )->sharedBook;
|
||||
asrt( count( $books ), 1 );
|
||||
//should not give error...
|
||||
$books = $page->withCondition( ' title = :title ', array( ':title' => 'book' ) )->sharedBook;
|
||||
asrt( count( $books ), 1 );
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$page = R::dispense( 'page' );
|
||||
$book->title = 'book';
|
||||
$book->comment = 'comment';
|
||||
$page->title = 'page';
|
||||
$book->ownPage[] = $page;
|
||||
R::store( $book );
|
||||
//should also not give error..
|
||||
$count = $book->countOwn( 'page' );
|
||||
asrt( $count, 1 );
|
||||
$book = $book->fresh();
|
||||
//should also not give error..
|
||||
$count = $book->withCondition( ' title = ? ', array( 'page' ) )->countOwn( 'page' );
|
||||
asrt( $count, 1 );
|
||||
$book = $book->fresh();
|
||||
//should also not give error..
|
||||
$count = $book->withCondition( ' title = :title ', array( ':title' => 'page' ) )->countOwn( 'page' );
|
||||
asrt( $count, 1 );
|
||||
$book = $book->fresh();
|
||||
$pages = $book->withCondition( ' title = :title ', array( ':title' => 'page' ) )->ownPage;
|
||||
asrt( count( $pages ), 1 );
|
||||
//test with duplicate slots...
|
||||
$page = reset( $pages );
|
||||
$page2 = R::dispense( 'page' );
|
||||
$page2->ownPage[] = $page;
|
||||
R::store( $page2 );
|
||||
$page2 = $page2->fresh();
|
||||
$pages = $page2->withCondition( ' title = :title ', array( ':title' => 'page' ) )->ownPage;
|
||||
asrt( count( $pages ), 1 );
|
||||
//test with find()
|
||||
$books = R::getRedBean()->find( 'book',
|
||||
array(
|
||||
'title' => array('book')),
|
||||
' AND title = :title ', array(':title'=>'book'));
|
||||
asrt( count( $books ), 1 );
|
||||
$books = R::getRedBean()->find( 'book',
|
||||
array(
|
||||
'title' => array('book', 'book2'),
|
||||
'comment' => array('comment', 'comment2')),
|
||||
' AND title = :title ', array(':title'=>'book'));
|
||||
asrt( count( $books ), 1 );
|
||||
//just check numeric works as well...
|
||||
$books = R::getRedBean()->find( 'book',
|
||||
array(
|
||||
'title' => array('book', 'book2'),
|
||||
'comment' => array('comment', 'comment2')),
|
||||
' AND title = ? ', array('book'));
|
||||
asrt( count( $books ), 1 );
|
||||
//just extra check to verify glue works
|
||||
$books = R::getRedBean()->find( 'book',
|
||||
array(
|
||||
'title' => array('book', 'book2'),
|
||||
'comment' => array('comment', 'comment2')),
|
||||
' ORDER BY id ');
|
||||
asrt( count( $books ), 1 );
|
||||
}
|
||||
}
|
||||
91
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Nuke.php
vendored
Normal file
91
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Nuke.php
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
|
||||
/**
|
||||
* Nuke
|
||||
*
|
||||
* Tests the nuke() command. The nuke command empties an entire database
|
||||
* and should also be capable of removing all foreign keys, constraints and
|
||||
* indexes.
|
||||
*
|
||||
* @file RedUNIT/Base/Nuke.php
|
||||
* @desc Test the nuke() function.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Nuke extends Base
|
||||
{
|
||||
/**
|
||||
* Test wipeAll().
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testWipe()
|
||||
{
|
||||
R::nuke();
|
||||
$bean = R::dispense( 'bean' );
|
||||
asrt( count( R::inspect() ), 0 );
|
||||
R::store( $bean );
|
||||
asrt( count( R::inspect() ), 1 );
|
||||
asrt( R::count( 'bean' ), 1 );
|
||||
R::debug(1);
|
||||
R::wipeAll();
|
||||
asrt( count( R::inspect() ), 1 );
|
||||
asrt( R::count( 'bean' ), 0 );
|
||||
R::wipeAll( TRUE );
|
||||
asrt( count( R::inspect() ), 0 );
|
||||
asrt( R::count( 'bean' ), 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Nuclear test suite.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testNuke()
|
||||
{
|
||||
$bean = R::dispense( 'bean' );
|
||||
R::store( $bean );
|
||||
asrt( count( R::getWriter()->getTables() ), 1 );
|
||||
R::nuke();
|
||||
asrt( count( R::getWriter()->getTables() ), 0 );
|
||||
$bean = R::dispense( 'bean' );
|
||||
R::store( $bean );
|
||||
asrt( count( R::getWriter()->getTables() ), 1 );
|
||||
R::freeze();
|
||||
R::nuke();
|
||||
// No effect
|
||||
asrt( count( R::getWriter()->getTables() ), 1 );
|
||||
R::freeze( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test noNuke().
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testNoNuke() {
|
||||
$bean = R::dispense( 'bean' );
|
||||
R::store( $bean );
|
||||
asrt( count( R::getWriter()->getTables() ), 1 );
|
||||
R::noNuke( TRUE );
|
||||
try {
|
||||
R::nuke();
|
||||
fail();
|
||||
} catch( \Exception $e ) {
|
||||
pass();
|
||||
}
|
||||
asrt( count( R::getWriter()->getTables() ), 1 );
|
||||
R::noNuke( FALSE );
|
||||
R::nuke();
|
||||
asrt( count( R::getWriter()->getTables() ), 0 );
|
||||
}
|
||||
}
|
||||
55
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Observers.php
vendored
Normal file
55
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Observers.php
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\Adapter\DBAdapter as DBAdapter;
|
||||
use RedBeanPHP\QueryWriter as QueryWriter;
|
||||
use RedBeanPHP\OODB as OODB;
|
||||
|
||||
/**
|
||||
* Observers
|
||||
*
|
||||
* Tests the basic observer pattern used in RedBeanPHP.
|
||||
*
|
||||
* @file RedUNIT/Base/Observers.php
|
||||
* @desc Tests the observer pattern in RedBeanPHP.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Observers extends Base
|
||||
{
|
||||
/**
|
||||
* Test RedBeanPHP observers.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testObserverMechanism()
|
||||
{
|
||||
$toolbox = R::getToolBox();
|
||||
$adapter = $toolbox->getDatabaseAdapter();
|
||||
$writer = $toolbox->getWriter();
|
||||
$redbean = $toolbox->getRedBean();
|
||||
asrt( ( $adapter instanceof DBAdapter ), TRUE );
|
||||
asrt( ( $writer instanceof QueryWriter ), TRUE );
|
||||
asrt( ( $redbean instanceof OODB ), TRUE );
|
||||
$observable = new \ObservableMock();
|
||||
$observer = new \ObserverMock();
|
||||
$observable->addEventListener( "event1", $observer );
|
||||
$observable->addEventListener( "event3", $observer );
|
||||
$observable->test( "event1", "testsignal1" );
|
||||
asrt( $observer->event, "event1" );
|
||||
asrt( $observer->info, "testsignal1" );
|
||||
$observable->test( "event2", "testsignal2" );
|
||||
asrt( $observer->event, "event1" );
|
||||
asrt( $observer->info, "testsignal1" );
|
||||
$observable->test( "event3", "testsignal3" );
|
||||
asrt( $observer->event, "event3" );
|
||||
asrt( $observer->info, "testsignal3" );
|
||||
}
|
||||
}
|
||||
262
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Partial.php
vendored
Normal file
262
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Partial.php
vendored
Normal file
@@ -0,0 +1,262 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
|
||||
/**
|
||||
* Partial Beans
|
||||
*
|
||||
* Test whether we can use 'partial bean mode'.
|
||||
* In 'partial bean mode' only changed properties of a bean
|
||||
* will get updated in the database. This feature has been designed
|
||||
* to deal with 'incompatible table fields'. The specific case that
|
||||
* led to this feature is available as test Postgres/Partial and is
|
||||
* based on Github issue #547. This test only covers the basic functionality.
|
||||
*
|
||||
* @file RedUNIT/Base/Partial.php
|
||||
* @desc Tests Partial Beans Mode
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Partial extends Base {
|
||||
|
||||
/**
|
||||
* Github Issue #754.
|
||||
* If I set up the default values to some specific columns,
|
||||
* these columns can not act the same expectation in partial bean mode. #754.
|
||||
* "When I upgrade my code to Redbean 5.4 and turn on the partial bean mode,
|
||||
* I found this issue I mentioned.
|
||||
* As Redbean recommends, I set up the default values
|
||||
* to some specific columns before I use them.
|
||||
* And then I use the partial bean mode to store
|
||||
* the columns updated rather than the entire bean.
|
||||
* But I found if I set up the default values,
|
||||
* it will change the changelist in the bean which is the
|
||||
* foundation of the partial bean mode."
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testChangeListIssue()
|
||||
{
|
||||
R::nuke();
|
||||
R::usePartialBeans( TRUE );
|
||||
\Model_Coffee::$defaults = array(
|
||||
'strength' => 'strong',
|
||||
'beans' => 'Arabica',
|
||||
'preparation' => 'Kettle'
|
||||
);
|
||||
$coffee = R::dispense('coffee');
|
||||
$changelist = $coffee->getMeta('changelist');
|
||||
asrt( count( $changelist), 3 );
|
||||
$coffee->preparation = 'Espresso';
|
||||
$changelist = $coffee->getMeta('changelist');
|
||||
asrt( count( $changelist), 4 );
|
||||
$id = R::store( $coffee );
|
||||
$coffee = R::load( 'coffee', $id );
|
||||
$changelist = $coffee->getMeta('changelist');
|
||||
asrt( count( $changelist), 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Github Issue #754.
|
||||
* The importRow() function should clear the changeList.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testChangeListImportRow()
|
||||
{
|
||||
R::usePartialBeans( TRUE );
|
||||
$bean = R::dispense( 'bean' );
|
||||
asrt( count( $bean->getMeta('changelist') ), 0 );
|
||||
$bean->property = 'abc';
|
||||
asrt( count( $bean->getMeta('changelist') ), 1 );
|
||||
$bean->importRow( array( 'property' => 123 ) );
|
||||
asrt( count( $bean->getMeta('changelist') ), 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the basic scenarios for Partial Beans.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testPartialBeans()
|
||||
{
|
||||
R::nuke();
|
||||
R::usePartialBeans( FALSE );
|
||||
$book = R::dispense( 'book' );
|
||||
$book->title = 'A book about half beans';
|
||||
$book->price = 99;
|
||||
$book->pages = 60;
|
||||
$id = R::store( $book );
|
||||
/* test baseline condition */
|
||||
$book = R::load( 'book', $id );
|
||||
asrt( $book->title, 'A book about half beans' );
|
||||
asrt( (integer) $book->pages, 60 );
|
||||
$book->pages++;
|
||||
R::exec( 'UPDATE book SET title = ? ', array( 'Another Title' ) );
|
||||
$id = R::store( $book );
|
||||
$book = R::load( 'book', $id );
|
||||
asrt( $book->title, 'A book about half beans' );
|
||||
asrt( (integer) $book->pages, 61 );
|
||||
/* now test partial beans mode */
|
||||
R::usePartialBeans( TRUE );
|
||||
$book->pages++;
|
||||
R::exec( 'UPDATE book SET title = ? ', array( 'Another Title' ) );
|
||||
$id = R::store( $book );
|
||||
$book = R::load( 'book', $id );
|
||||
asrt( $book->title, 'Another Title' );
|
||||
asrt( (integer) $book->pages, 62 );
|
||||
/* mask should be cleared... */
|
||||
R::exec( 'UPDATE book SET pages = ? ', array( 64 ) );
|
||||
$book->price = 92;
|
||||
$id = R::store( $book );
|
||||
$book = R::load( 'book', $id );
|
||||
asrt( (integer) $book->pages, 64 );
|
||||
asrt( $book->title, 'Another Title' );
|
||||
asrt( (integer) $book->price, 92 );
|
||||
R::usePartialBeans( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether we can pass a list of specific bean types
|
||||
* to apply partial saving to.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testPartialBeansTypeList()
|
||||
{
|
||||
R::nuke();
|
||||
R::usePartialBeans( array( 'notbook' ) );
|
||||
$book = R::dispense( 'book' );
|
||||
$book->title = 'A book about half beans';
|
||||
$book->price = 99;
|
||||
$book->pages = 60;
|
||||
$id = R::store( $book );
|
||||
/* test baseline condition */
|
||||
$book = R::load( 'book', $id );
|
||||
asrt( $book->title, 'A book about half beans' );
|
||||
asrt( (integer) $book->pages, 60 );
|
||||
$book->pages++;
|
||||
R::exec( 'UPDATE book SET title = ? ', array( 'Another Title' ) );
|
||||
$id = R::store( $book );
|
||||
$book = R::load( 'book', $id );
|
||||
asrt( $book->title, 'A book about half beans' );
|
||||
asrt( (integer) $book->pages, 61 );
|
||||
/* now test partial beans mode */
|
||||
R::usePartialBeans( array( 'book', 'more' ) );
|
||||
$book->pages++;
|
||||
R::exec( 'UPDATE book SET title = ? ', array( 'Another Title' ) );
|
||||
$id = R::store( $book );
|
||||
$book = R::load( 'book', $id );
|
||||
asrt( $book->title, 'Another Title' );
|
||||
asrt( (integer) $book->pages, 62 );
|
||||
/* mask should be cleared... */
|
||||
R::exec( 'UPDATE book SET pages = ? ', array( 64 ) );
|
||||
$book->price = 92;
|
||||
$id = R::store( $book );
|
||||
$book = R::load( 'book', $id );
|
||||
asrt( (integer) $book->pages, 64 );
|
||||
asrt( $book->title, 'Another Title' );
|
||||
asrt( (integer) $book->price, 92 );
|
||||
R::usePartialBeans( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the basic scenarios for Partial Beans.
|
||||
* Frozen.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testPartialBeansFrozen()
|
||||
{
|
||||
R::nuke();
|
||||
R::usePartialBeans( FALSE );
|
||||
$book = R::dispense( 'book' );
|
||||
$book->title = 'A book about half beans';
|
||||
$book->price = 99;
|
||||
$book->pages = 60;
|
||||
$id = R::store( $book );
|
||||
/* test baseline condition */
|
||||
$book = R::load( 'book', $id );
|
||||
asrt( $book->title, 'A book about half beans' );
|
||||
asrt( (integer) $book->pages, 60 );
|
||||
$book->pages++;
|
||||
R::exec( 'UPDATE book SET title = ? ', array( 'Another Title' ) );
|
||||
$id = R::store( $book );
|
||||
$book = R::load( 'book', $id );
|
||||
asrt( $book->title, 'A book about half beans' );
|
||||
asrt( (integer) $book->pages, 61 );
|
||||
/* now test partial beans mode */
|
||||
R::freeze( TRUE );
|
||||
R::usePartialBeans( TRUE );
|
||||
$book->pages++;
|
||||
R::exec( 'UPDATE book SET title = ? ', array( 'Another Title' ) );
|
||||
$id = R::store( $book );
|
||||
$book = R::load( 'book', $id );
|
||||
asrt( $book->title, 'Another Title' );
|
||||
asrt( (integer) $book->pages, 62 );
|
||||
/* mask should be cleared... */
|
||||
R::exec( 'UPDATE book SET pages = ? ', array( 64 ) );
|
||||
$book->price = 92;
|
||||
$id = R::store( $book );
|
||||
$book = R::load( 'book', $id );
|
||||
asrt( (integer) $book->pages, 64 );
|
||||
asrt( $book->title, 'Another Title' );
|
||||
asrt( (integer) $book->price, 92 );
|
||||
R::usePartialBeans( FALSE );
|
||||
R::freeze( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether we can pass a list of specific bean types
|
||||
* to apply partial saving to.
|
||||
* Frozen.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testPartialBeansTypeListFrozen()
|
||||
{
|
||||
R::nuke();
|
||||
R::usePartialBeans( array( 'notbook' ) );
|
||||
$book = R::dispense( 'book' );
|
||||
$book->title = 'A book about half beans';
|
||||
$book->price = 99;
|
||||
$book->pages = 60;
|
||||
$id = R::store( $book );
|
||||
/* test baseline condition */
|
||||
$book = R::load( 'book', $id );
|
||||
asrt( $book->title, 'A book about half beans' );
|
||||
asrt( (integer) $book->pages, 60 );
|
||||
$book->pages++;
|
||||
R::exec( 'UPDATE book SET title = ? ', array( 'Another Title' ) );
|
||||
$id = R::store( $book );
|
||||
$book = R::load( 'book', $id );
|
||||
asrt( $book->title, 'A book about half beans' );
|
||||
asrt( (integer) $book->pages, 61 );
|
||||
/* now test partial beans mode */
|
||||
R::freeze( TRUE );
|
||||
R::usePartialBeans( array( 'book', 'more' ) );
|
||||
$book->pages++;
|
||||
R::exec( 'UPDATE book SET title = ? ', array( 'Another Title' ) );
|
||||
$id = R::store( $book );
|
||||
$book = R::load( 'book', $id );
|
||||
asrt( $book->title, 'Another Title' );
|
||||
asrt( (integer) $book->pages, 62 );
|
||||
/* mask should be cleared... */
|
||||
R::exec( 'UPDATE book SET pages = ? ', array( 64 ) );
|
||||
$book->price = 92;
|
||||
$id = R::store( $book );
|
||||
$book = R::load( 'book', $id );
|
||||
asrt( (integer) $book->pages, 64 );
|
||||
asrt( $book->title, 'Another Title' );
|
||||
asrt( (integer) $book->price, 92 );
|
||||
R::usePartialBeans( FALSE );
|
||||
R::freeze( FALSE );
|
||||
}
|
||||
}
|
||||
126
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Performance.php
vendored
Normal file
126
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Performance.php
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\RedException as RedException;
|
||||
|
||||
/**
|
||||
* Performance
|
||||
*
|
||||
* This performance test is used with runperf and xdebug profiler.
|
||||
*
|
||||
* @file RedUNIT/Base/Performance.php
|
||||
* @desc Performance testing.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Performance extends Base
|
||||
{
|
||||
/**
|
||||
* Setup
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setup()
|
||||
{
|
||||
R::nuke();
|
||||
|
||||
//Prepare structure
|
||||
$book = R::dispense( 'book' );
|
||||
$book->title = 'book';
|
||||
$pages = R::dispense( 'page', 10 );
|
||||
foreach( $pages as $page ) {
|
||||
$page->content = 'lorem ipsum';
|
||||
$page->title = 'data';
|
||||
$page->sequence = 'data';
|
||||
$page->order = 'data';
|
||||
$page->columns = 'data';
|
||||
$page->paragraphs = 'data';
|
||||
$page->paragraphs1 = 'data';
|
||||
$page->paragraphs2 = 'data';
|
||||
$page->paragraphs3 = 'data';
|
||||
$page->paragraphs4 = 'data';
|
||||
}
|
||||
$book->xownPageList = $pages;
|
||||
$tags = R::dispense( 'tag', 6 );
|
||||
foreach( $tags as $tag ) {
|
||||
$tag->label = 'tag';
|
||||
}
|
||||
$book->sharedTagList = $tags;
|
||||
R::store( $book );
|
||||
}
|
||||
|
||||
/**
|
||||
* CRUD performance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function crud()
|
||||
{
|
||||
R::freeze( TRUE );
|
||||
|
||||
$book = R::dispense( 'book' );
|
||||
$book->title = 'Book';
|
||||
$page = R::dispense('page');
|
||||
$page->content = 'Content';
|
||||
$page->title = 'data';
|
||||
$page->sequence = 'data';
|
||||
$page->order = 'data';
|
||||
$page->columns = 'data';
|
||||
$page->paragraphs = 'data';
|
||||
$page->paragraphs1 = 'data';
|
||||
$page->paragraphs2 = 'data';
|
||||
$page->paragraphs3 = 'data';
|
||||
$page->paragraphs4 = 'data';
|
||||
$tag = R::dispense('tag');
|
||||
$tag->label = 'Tag ';
|
||||
$book->noLoad()->ownPage[] = $page;
|
||||
$book->noLoad()->sharedTag[] = $tag;
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
$book->ownPage;
|
||||
$book->sharedTag;
|
||||
R::trash( $book );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* CRUD performance Array Access.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function crudaa()
|
||||
{
|
||||
R::freeze( TRUE );
|
||||
|
||||
$book = R::dispense( 'book' );
|
||||
$book['title'] = 'Book';
|
||||
$page = R::dispense('page');
|
||||
$page['content'] = 'Content';
|
||||
$page['title'] = 'data';
|
||||
$page['sequence'] = 'data';
|
||||
$page['order'] = 'data';
|
||||
$page['columns'] = 'data';
|
||||
$page['paragraphs'] = 'data';
|
||||
$page['paragraphs1'] = 'data';
|
||||
$page['paragraphs2'] = 'data';
|
||||
$page['paragraphs3'] = 'data';
|
||||
$page['paragraphs4'] = 'data';
|
||||
$tag = R::dispense('tag');
|
||||
$tag['label'] = 'Tag ';
|
||||
$book->ownPage[] = $page;
|
||||
$book->noLoad()->sharedTag[] = $tag;
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
$book->ownPage;
|
||||
$book->sharedTag;
|
||||
R::trash( $book );
|
||||
|
||||
}
|
||||
}
|
||||
269
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Prefixes.php
vendored
Normal file
269
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Prefixes.php
vendored
Normal file
@@ -0,0 +1,269 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
use RedBeanPHP\QueryWriter\AQueryWriter as AQueryWriter;
|
||||
|
||||
R::ext('xdispense', function($type){
|
||||
return R::getRedBean()->dispense($type);
|
||||
});
|
||||
|
||||
define('BOOK', 'tbl_book');
|
||||
define('AUTHOR', 'tbl_author');
|
||||
define('COAUTHOR', 'coAuthor');
|
||||
define('FRIEND', 'tbl_friend');
|
||||
define('PUBLISHER', 'tbl_publisher');
|
||||
define('BOOKLIST', 'ownTbl_book');
|
||||
define('FRIENDLIST', 'sharedTbl_friend');
|
||||
|
||||
/**
|
||||
* Prefixes
|
||||
*
|
||||
* Tests whether we can use tables with prefixes.
|
||||
* Some people seem to like that.
|
||||
*
|
||||
* @file RedUNIT/Base/Prefixes.php
|
||||
* @desc Tests whether you can use RedBeanPHP with table prefixes.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Prefixes extends Base
|
||||
{
|
||||
/**
|
||||
* Test prerequisites.
|
||||
*/
|
||||
public function testPrerequisites()
|
||||
{
|
||||
R::nuke();
|
||||
$bean = R::xdispense( 'type_with_underscore' );
|
||||
asrt( ( $bean instanceof OODBBean ), TRUE );
|
||||
asrt( constant( 'BOOK' ), 'tbl_book' );
|
||||
asrt( constant( 'AUTHOR' ), 'tbl_author' );
|
||||
asrt( constant( 'PUBLISHER' ), 'tbl_publisher' );
|
||||
asrt( constant( 'FRIEND' ), 'tbl_friend' );
|
||||
asrt( constant( 'BOOKLIST' ), 'ownTbl_book' );
|
||||
asrt( constant( 'FRIENDLIST' ), 'sharedTbl_friend' );
|
||||
asrt( constant( 'COAUTHOR' ), 'coAuthor' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic CRUD operations.
|
||||
*/
|
||||
public function testBasicOperations()
|
||||
{
|
||||
//Can we dispense a naughty bean? (with underscore)
|
||||
$author = R::xdispense( AUTHOR );
|
||||
asrt( ( $author instanceof OODBBean ), TRUE );
|
||||
asrt( $author->getMeta('type'), AUTHOR );
|
||||
$author->name = 'Mr. Quill';
|
||||
$book = R::xdispense( BOOK );
|
||||
asrt( ( $book instanceof OODBBean ), TRUE );
|
||||
asrt( $book->getMeta('type'), BOOK );
|
||||
$book->title = 'Good Stories';
|
||||
$friend = R::xdispense( FRIEND );
|
||||
$friend->name = 'Muse';
|
||||
asrt( ( $friend instanceof OODBBean ), TRUE );
|
||||
asrt( $friend->getMeta('type'), FRIEND );
|
||||
$publisher = R::xdispense( PUBLISHER );
|
||||
$publisher->name = 'Good Books';
|
||||
asrt( ( $publisher instanceof OODBBean ), TRUE );
|
||||
asrt( $publisher->getMeta('type'), PUBLISHER );
|
||||
asrt( is_array( $author->{BOOKLIST} ), TRUE );
|
||||
//add books to the book list using the constant
|
||||
$author->{BOOKLIST}[] = $book;
|
||||
asrt( count( $author->{BOOKLIST} ), 1 );
|
||||
//can we also add friends? (N-M)
|
||||
$author->{FRIENDLIST}[] = $friend;
|
||||
$author->{PUBLISHER} = $publisher;
|
||||
$id = R::store( $author );
|
||||
asrt( ( $id > 0 ), TRUE );
|
||||
$author = $author->fresh();
|
||||
//Can we add another friend after reload?
|
||||
$author->{FRIENDLIST}[] = R::xdispense( FRIEND )->setAttr( 'name', 'buddy' );
|
||||
R::store($author);
|
||||
$author = $author->fresh();
|
||||
//Now check the contents of the bean, its lists (books,friends) and parent (publisher)
|
||||
asrt( $author->name, 'Mr. Quill' );
|
||||
asrt( count( $author->{BOOKLIST} ), 1 );
|
||||
$firstBook = reset( $author->{BOOKLIST} );
|
||||
asrt( $firstBook->title, 'Good Stories' );
|
||||
asrt( count( $author->{FRIENDLIST} ), 2 );
|
||||
$firstFriend = reset( $author->{FRIENDLIST} );
|
||||
$parent = $author->{PUBLISHER};
|
||||
asrt( ( $parent instanceof OODBBean ), TRUE );
|
||||
$tables = R::inspect();
|
||||
//have all tables been prefixed?
|
||||
foreach( $tables as $table ) asrt( strpos( $table, 'tbl_' ), 0 );
|
||||
//Can we make an export?
|
||||
$export = R::exportAll( R::findOne( AUTHOR ), TRUE );
|
||||
$export = reset( $export );
|
||||
asrt( isset( $export[ PUBLISHER ] ), TRUE );
|
||||
asrt( isset( $export[ BOOKLIST ] ), TRUE );
|
||||
asrt( isset( $export[ FRIENDLIST ] ), TRUE );
|
||||
asrt( isset( $export[ 'ownBook' ] ), FALSE );
|
||||
asrt( isset( $export[ 'sharedFriend' ] ), FALSE );
|
||||
asrt( isset( $export[ 'publisher' ] ), FALSE );
|
||||
//Can we duplicate?
|
||||
$copy = R::dup( $author );
|
||||
$copy->name = 'Mr. Clone';
|
||||
R::store( $copy );
|
||||
$copy = $copy->fresh();
|
||||
asrt( $copy->name, 'Mr. Clone' );
|
||||
asrt( count( $copy->{BOOKLIST} ), 1 );
|
||||
$firstBook = reset( $copy->{BOOKLIST} );
|
||||
asrt( $firstBook->title, 'Good Stories' );
|
||||
asrt( count( $copy->{FRIENDLIST} ), 2 );
|
||||
$firstFriend = reset( $copy->{FRIENDLIST} );
|
||||
$parent = $copy->{PUBLISHER};
|
||||
asrt( ( $parent instanceof OODBBean ), TRUE );
|
||||
//Can we count?
|
||||
asrt( R::count( AUTHOR ), 2 );
|
||||
$copy = $copy->fresh();
|
||||
asrt( $copy->countOwn( BOOK ), 1 );
|
||||
asrt( $copy->countShared( FRIEND ), 2 );
|
||||
//Can we delete?
|
||||
R::trash( $author );
|
||||
asrt( R::count( AUTHOR ), 1 );
|
||||
//Can we nuke?
|
||||
R::nuke();
|
||||
asrt( R::count( AUTHOR ), 0 );
|
||||
asrt( count( R::inspect() ), 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic operations in frozen mode.
|
||||
*/
|
||||
public function testBasicOperationsFrozen()
|
||||
{
|
||||
R::nuke();
|
||||
$author = R::xdispense( AUTHOR );
|
||||
$author->name = 'Mr. Quill';
|
||||
$book = R::xdispense( BOOK );
|
||||
$book->title = 'Good Stories';
|
||||
$book2 = R::xdispense( BOOK );
|
||||
$book2->title = 'Good Stories 2';
|
||||
$friend = R::xdispense( FRIEND );
|
||||
$friend->name = 'Muse';
|
||||
$publisher = R::xdispense( PUBLISHER );
|
||||
$publisher->name = 'Good Books';
|
||||
$author->{BOOKLIST} = array( $book, $book2 );
|
||||
$author->{FRIENDLIST}[] = $friend;
|
||||
$author->{PUBLISHER} = $publisher;
|
||||
$coAuthor = R::xdispense( AUTHOR );
|
||||
$coAuthor->name = 'Xavier';
|
||||
$book2->{COAUTHOR} = $coAuthor;
|
||||
R::store( $author );
|
||||
R::freeze( TRUE );
|
||||
asrt( $author->name, 'Mr. Quill' );
|
||||
asrt( count( $author->{BOOKLIST} ), 2 );
|
||||
$firstBook = reset( $author->{BOOKLIST} );
|
||||
asrt( $firstBook->title, 'Good Stories' );
|
||||
asrt( count( $author->{FRIENDLIST} ), 1 );
|
||||
$firstFriend = reset( $author->{FRIENDLIST} );
|
||||
$parent = $author->{PUBLISHER};
|
||||
asrt( ( $parent instanceof OODBBean ), TRUE );
|
||||
$tables = R::inspect();
|
||||
//have all tables been prefixed?
|
||||
foreach( $tables as $table ) asrt( strpos( $table, 'tbl_' ), 0 );
|
||||
//Can we make an export?
|
||||
$export = R::exportAll( R::findOne( AUTHOR ), TRUE );
|
||||
$export = reset( $export );
|
||||
asrt( isset( $export[ PUBLISHER ] ), TRUE );
|
||||
asrt( isset( $export[ BOOKLIST ] ), TRUE );
|
||||
asrt( isset( $export[ FRIENDLIST ] ), TRUE );
|
||||
asrt( isset( $export[ 'ownBook' ] ), FALSE );
|
||||
asrt( isset( $export[ 'sharedFriend' ] ), FALSE );
|
||||
asrt( isset( $export[ 'publisher' ] ), FALSE );
|
||||
R::freeze( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test conditions and aliases.
|
||||
*/
|
||||
public function testConditionsAndAliases()
|
||||
{
|
||||
R::nuke();
|
||||
$author = R::xdispense( AUTHOR );
|
||||
$author->name = 'Mr. Quill';
|
||||
$book = R::xdispense( BOOK );
|
||||
$book->title = 'Good Stories';
|
||||
$book2 = R::xdispense( BOOK );
|
||||
$book2->title = 'Good Stories 2';
|
||||
$friend = R::xdispense( FRIEND );
|
||||
$friend->name = 'Muse';
|
||||
$publisher = R::xdispense( PUBLISHER );
|
||||
$publisher->name = 'Good Books';
|
||||
$author->{BOOKLIST} = array( $book, $book2 );
|
||||
$author->{FRIENDLIST}[] = $friend;
|
||||
$author->{PUBLISHER} = $publisher;
|
||||
$coAuthor = R::xdispense( AUTHOR );
|
||||
$coAuthor->name = 'Xavier';
|
||||
$book2->{COAUTHOR} = $coAuthor;
|
||||
R::store( $author );
|
||||
$author = $author->fresh();
|
||||
asrt( R::count( AUTHOR ), 2 );
|
||||
//Can we use with and withCondition?
|
||||
asrt( count( $author->{BOOKLIST} ), 2 );
|
||||
asrt( count( $author->with(' LIMIT 1 ')->{BOOKLIST} ), 1 );
|
||||
asrt( count( $author->withCondition(' title LIKE ? ', array( '%2%' ) )->{BOOKLIST} ), 1 );
|
||||
//Can we use an alias?
|
||||
$book2 = $book2->fresh();
|
||||
asrt( $book2->fetchAs( AUTHOR )->{COAUTHOR}->name, 'Xavier' );
|
||||
$coAuthor = $book2->fetchAs( AUTHOR )->{COAUTHOR}->fresh();
|
||||
asrt( count( $coAuthor->alias( COAUTHOR )->{BOOKLIST} ), 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test prettier tables using via().
|
||||
*/
|
||||
public function testViaPrettification()
|
||||
{
|
||||
R::nuke();
|
||||
R::renameAssociation( 'tbl_author_tbl_friend', 'tbl_author_friend' );
|
||||
$author = R::xdispense( AUTHOR );
|
||||
$author->name = 'Mr. Quill';
|
||||
$friend = R::xdispense( FRIEND );
|
||||
$friend->name = 'Muse';
|
||||
$author->{FRIENDLIST}[] = $friend;
|
||||
$id = R::store( $author );
|
||||
//print_r(R::inspect()); exit;
|
||||
$author = R::load( AUTHOR, $id );
|
||||
$tables = array_flip( R::inspect() );
|
||||
asrt( isset( $tables[ 'tbl_author_friend' ] ), TRUE );
|
||||
asrt( isset( $tables[ 'tbl_author_tbl_friend' ] ), FALSE );
|
||||
asrt( count( $author->{FRIENDLIST} ), 1 );
|
||||
AQueryWriter::clearRenames();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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' );
|
||||
}
|
||||
}
|
||||
233
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Productivity.php
vendored
Normal file
233
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Productivity.php
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\RedException as RedException;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
use RedBeanPHP\Util\MatchUp;
|
||||
use RedBeanPHP\Util\Look;
|
||||
|
||||
/**
|
||||
* MatchUp
|
||||
*
|
||||
* Tests the MatchUp functionality.
|
||||
* Tired of creating login systems and password-forget systems?
|
||||
* MatchUp is an ORM-translation of these kind of problems.
|
||||
* A matchUp is a match-and-update combination in terms of beans.
|
||||
* Typically login related problems are all about a match and
|
||||
* a conditional update.
|
||||
*
|
||||
* @file RedUNIT/Base/Matchup.php
|
||||
* @desc Tests MatchUp
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Productivity extends Base
|
||||
{
|
||||
/**
|
||||
* Test matchup
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testPasswordForget()
|
||||
{
|
||||
R::nuke();
|
||||
$account = R::dispense( 'account' );
|
||||
$account->uname = 'Shawn';
|
||||
$account->pass = sha1( 'sheep' );
|
||||
$account->archived = 0;
|
||||
$account->attempts = 1;
|
||||
|
||||
R::store( $account );
|
||||
$matchUp = new MatchUp( R::getToolbox() );
|
||||
|
||||
/* simulate a token generation script */
|
||||
$account = NULL;
|
||||
$didGenToken = $matchUp->matchUp( 'account', ' uname = ? AND archived = ?', array('Shawn',0), array(
|
||||
'token' => sha1(rand(0,9000) . time()),
|
||||
'tokentime' => time()
|
||||
), NULL, $account );
|
||||
|
||||
asrt( $didGenToken, TRUE );
|
||||
asrt( !is_null( $account->token ) , TRUE );
|
||||
asrt( !is_null( $account->tokentime ) , TRUE );
|
||||
|
||||
/* simulate a password reset script */
|
||||
$newpass = '1234';
|
||||
$didResetPass = $matchUp->matchUp( 'account', ' token = ? AND tokentime > ? ', array( $account->token, time()-100 ), array(
|
||||
'pass' => $newpass,
|
||||
'token' => ''
|
||||
), NULL, $account );
|
||||
asrt( $account->pass, '1234' );
|
||||
asrt( $account->token, '' );
|
||||
|
||||
/* simulate a login */
|
||||
$didFindUsr = $matchUp->matchUp( 'account', ' uname = ? ', array( 'Shawn' ), array(
|
||||
'attempts' => function( $acc ) {
|
||||
return ( $acc->pass !== '1234' ) ? ( $acc->attempts + 1 ) : 0;
|
||||
}
|
||||
), NULL, $account);
|
||||
|
||||
asrt( $didFindUsr, TRUE );
|
||||
asrt( $account->attempts, 0 );
|
||||
|
||||
/* Login failure */
|
||||
$didFindUsr = $matchUp->matchUp( 'account', ' uname = ? ', array( 'Shawn' ), array(
|
||||
'attempts' => function( $acc ) {
|
||||
return ( $acc->pass !== '1236' ) ? ( $acc->attempts + 1 ) : 0;
|
||||
}
|
||||
), NULL, $account);
|
||||
|
||||
/* Create user if not exists */
|
||||
$didFindUsr = R::matchUp( 'account', ' uname = ? ', array( 'Anonymous' ), array(
|
||||
), array(
|
||||
'uname' => 'newuser'
|
||||
), $account);
|
||||
asrt( $didFindUsr, FALSE );
|
||||
asrt( $account->uname, 'newuser' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the look function.
|
||||
*/
|
||||
public function testLook()
|
||||
{
|
||||
R::nuke();
|
||||
$beans = R::dispenseAll( 'color*3' );
|
||||
list( $red, $green, $blue ) = $beans[0];
|
||||
$red->name = 'red';
|
||||
$green->name = 'green';
|
||||
$blue->name = 'blue';
|
||||
$red->thevalue = 'r';
|
||||
$green->thevalue = 'g';
|
||||
$blue->thevalue = 'b';
|
||||
R::storeAll( array( $red, $green, $blue ) );
|
||||
$look = R::getLook();
|
||||
asrt( ( $look instanceof Look ), TRUE );
|
||||
$str = R::getLook()->look( 'SELECT * FROM color WHERE thevalue != ? ORDER BY thevalue ASC', array( 'g' ), array( 'thevalue', 'name' ),
|
||||
'<option value="%s">%s</option>', 'strtoupper', "\n"
|
||||
);
|
||||
asrt( $str,
|
||||
"<option value=\"B\">BLUE</option>\n<option value=\"R\">RED</option>"
|
||||
);
|
||||
$str = R::look( 'SELECT * FROM color WHERE thevalue != ? ORDER BY thevalue ASC', array( 'g' ), array( 'thevalue', 'name' ),
|
||||
'<option value="%s">%s</option>', 'strtoupper', "\n"
|
||||
);
|
||||
asrt( $str,
|
||||
"<option value=\"B\">BLUE</option>\n<option value=\"R\">RED</option>"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Bean differ.
|
||||
*/
|
||||
public function testDiff()
|
||||
{
|
||||
R::nuke();
|
||||
$ad = R::dispense( 'ad' );
|
||||
$ad->title = 'dog looking for new home';
|
||||
$ad->created = time();
|
||||
$ad->modified = time();
|
||||
$ad->ownDog[] = R::dispense( 'dog' );
|
||||
$ad->ownDog[0]->name = 'Dweep';
|
||||
$ad->ownDog[0]->color = 'green';
|
||||
$ad->author = R::dispense('user');
|
||||
$ad->author->name = 'John';
|
||||
R::store( $ad );
|
||||
$ad->title = 'green dog';
|
||||
$diff = R::diff( $ad->fresh(), $ad );
|
||||
/* simple case, property changed */
|
||||
var_dump( $diff );
|
||||
asrt( is_array( $diff ), TRUE );
|
||||
asrt( count( $diff ), 1 );
|
||||
asrt( $diff['ad.1.title'][0], 'dog looking for new home' );
|
||||
asrt( $diff['ad.1.title'][1], 'green dog' );
|
||||
/* test use specific format */
|
||||
$diff = R::diff( $ad->fresh(), $ad, array(), '%1$s.%3$s' );
|
||||
asrt( is_array( $diff ), TRUE );
|
||||
asrt( count( $diff ), 1 );
|
||||
asrt( $diff['ad.title'][0], 'dog looking for new home' );
|
||||
asrt( $diff['ad.title'][1], 'green dog' );
|
||||
/* skip created modified */
|
||||
$ad = $ad->fresh();
|
||||
$ad->modified = 111;
|
||||
$ad->created = 111;
|
||||
$diff = R::diff( $ad->fresh(), $ad );
|
||||
asrt( is_array( $diff ), TRUE );
|
||||
asrt( count( $diff ), 0 );
|
||||
/* unless we set anothe filter */
|
||||
$ad = $ad->fresh();
|
||||
$ad->modified = 111;
|
||||
$ad->created = 111;
|
||||
$ad->name = 'x';
|
||||
$diff = R::diff( $ad->fresh(), $ad, array( 'name' ) );
|
||||
asrt( is_array( $diff ), TRUE );
|
||||
asrt( count( $diff ), 2 );
|
||||
asrt( $diff['ad.1.modified'][1], 111 );
|
||||
asrt( $diff['ad.1.created'][1], 111 );
|
||||
$ad = $ad->fresh();
|
||||
/* also diff changes in related beans */
|
||||
$ad->fetchAs('user')->author->name = 'Fred';
|
||||
$dog = reset( $ad->ownDog );
|
||||
$dog->color = 999;
|
||||
$old = $ad->fresh();
|
||||
$old->ownDog;
|
||||
$old->fetchAs('user')->author;
|
||||
$diff = R::diff( $ad, $old );
|
||||
asrt( is_array( $diff ), TRUE );
|
||||
asrt( count( $diff ), 2 );
|
||||
asrt( $diff['ad.1.ownDog.1.color'][1], 'green' );
|
||||
asrt( $diff['ad.1.ownDog.1.color'][0], 999 );
|
||||
asrt( $diff['ad.1.author.1.name'][1], 'John' );
|
||||
asrt( $diff['ad.1.author.1.name'][0], 'Fred' );
|
||||
$diff = R::diff( $ad, null );
|
||||
asrt( is_array( $diff ), TRUE );
|
||||
asrt( count( $diff ), 0 );
|
||||
$diff = R::diff( null, $ad );
|
||||
asrt( is_array( $diff ), TRUE );
|
||||
asrt( count( $diff ), 0 );
|
||||
|
||||
/* demo case */
|
||||
list($book,$pages) = R::dispenseAll('book,page*2');
|
||||
$book->title = 'Old Book';
|
||||
$book->price = 999;
|
||||
$book->ownPageList = $pages;
|
||||
$pages[0]->text = 'abc';
|
||||
$pages[1]->text = 'def';
|
||||
R::store($book);
|
||||
$book->title = 'new Book';
|
||||
$page = end($book->ownPageList);
|
||||
$page->text = 'new';
|
||||
$oldBook = $book->fresh();
|
||||
$oldBook->ownPageList;
|
||||
$diff = R::diff($oldBook, $book);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test misc. matchUp scenarios.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMatchUpMisc()
|
||||
{
|
||||
R::nuke();
|
||||
asrt( R::count( 'bean' ), 0 );
|
||||
$found = R::matchUp( 'bean', ' id = ? ', array(1), array(), array(
|
||||
'notfound' => function( $bean ) {
|
||||
$bean->status = 'not found';
|
||||
}
|
||||
) );
|
||||
asrt( $found, FALSE );
|
||||
asrt( R::count( 'bean' ), 1 );
|
||||
$bean = R::findOne( 'bean' );
|
||||
asrt( $bean->status, 'not found' );
|
||||
$null = R::matchUp( 'bean', ' id = ? ', array( $bean->id ) );
|
||||
asrt( is_null( $null ), TRUE );
|
||||
}
|
||||
}
|
||||
51
vendor/gabordemooij/redbean/testing/RedUNIT/Base/PullRequest530.php
vendored
Normal file
51
vendor/gabordemooij/redbean/testing/RedUNIT/Base/PullRequest530.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
|
||||
/**
|
||||
* PullRequest530
|
||||
*
|
||||
* Tests whether this specific issue on github has been resolved.
|
||||
* Pull Request #530 - OODBBean __set() checks if $property is a field link
|
||||
*
|
||||
* @file RedUNIT/Base/PullRequest530.php
|
||||
* @desc Pull Request #530 - OODBBean __set() checks if $property is a field link
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
|
||||
class PullRequest530 extends Base
|
||||
{
|
||||
/**
|
||||
* testPullRequest530
|
||||
*
|
||||
* Test to check if OODBBean correctly stores a bean if a field link is set directly.
|
||||
* (We have to unset the linked bean (if loaded), so that the Repository::processEmbeddedBean
|
||||
* function call does not update the field link property and overwrites the change
|
||||
* in the following statement: <code>if ($bean->$linkField != $id) $bean->$linkField = $id;</code>
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testPullRequest530()
|
||||
{
|
||||
testpack( 'Testing Pull Request #530 - OODBBean __set() checks if $property is a field link' );
|
||||
R::freeze( FALSE );
|
||||
$linkedObjects = R::dispense('linked', 2);
|
||||
R::storeAll($linkedObjects);
|
||||
$tester = R::dispense('parent');
|
||||
$tester->linked = $linkedObjects[0];
|
||||
R::store($tester);
|
||||
$tester = R::findOne('parent');
|
||||
asrt($tester->linked->id, $linkedObjects[0]->id);
|
||||
$tester->linked_id = $linkedObjects[1]->id;
|
||||
R::store($tester);
|
||||
asrt($tester->linked->id, $linkedObjects[1]->id);
|
||||
}
|
||||
}
|
||||
43
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Quickexport.php
vendored
Normal file
43
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Quickexport.php
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\RedException as RedException;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
|
||||
/**
|
||||
* QuickExport
|
||||
*
|
||||
* Tests the Quick Export functionality.
|
||||
* The Quick Export Utility Class provides functionality to easily
|
||||
* expose the result of SQL queries as well-known formats like CSV.
|
||||
*
|
||||
* @file RedUNIT/Base/Quickexport.php
|
||||
* @desc Tests Quick Export
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Quickexport extends Base
|
||||
{
|
||||
/**
|
||||
* Test whether we can generate a CSV file from a query.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCSV()
|
||||
{
|
||||
if ( phpversion() < 5.5 || strpos( strtolower( phpversion() ), 'hhvm' ) !== FALSE ) return;
|
||||
R::store( R::dispense( array( '_type'=>'bean', 'a' => 1, 'b' => 2, 'c' => 3 ) ) );
|
||||
$path = '/tmp/redbeantest.txt';
|
||||
R::csv( 'SELECT a,b,c FROM bean', array(), array( 'A', 'B', 'C' ), $path, FALSE );
|
||||
$csv = file_get_contents( $path );
|
||||
$expected = "A,B,C\n1,2,3";
|
||||
asrt( strpos($csv, $expected) !== FALSE, TRUE );
|
||||
}
|
||||
}
|
||||
1250
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Relations.php
vendored
Normal file
1250
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Relations.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
221
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Tags.php
vendored
Normal file
221
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Tags.php
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\RedException as RedException;
|
||||
|
||||
/**
|
||||
* Tags
|
||||
*
|
||||
* Tests RedBeanPHP tagging functionality, should be easy
|
||||
* to tag beans, collect tags and integrate tags in SQL
|
||||
* snippets. Tags automatically result in N-M relations, i.e.
|
||||
* shared lists.
|
||||
*
|
||||
* @file RedUNIT/Base/Tags.php
|
||||
* @desc Tests the tagging of beans.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Tags extends Base
|
||||
{
|
||||
public function testTagsCache()
|
||||
{
|
||||
R::nuke();
|
||||
R::getWriter()->setUseCache( TRUE );
|
||||
list( $beer1, $beer2, $beer3 ) = R::dispense( 'beer', 3 );
|
||||
$beer1->title = 'b1';
|
||||
$beer2->title = 'b2';
|
||||
$beer3->title = 'b3';
|
||||
R::tag( $beer1, 'stout' );
|
||||
R::tag( $beer2, 'porter' );
|
||||
R::tag( $beer3, 'lager,popular' );
|
||||
$beers = R::tagged( 'beer', 'lager,popular' );
|
||||
asrt(count($beers),1);
|
||||
R::exec( 'DELETE FROM beer_tag WHERE beer_id = ? -- keep-cache', array( $beer3->id ) );
|
||||
$beers = R::tagged( 'beer', 'lager,popular' );
|
||||
asrt(count($beers),1);
|
||||
R::getWriter()->setUseCache( FALSE );
|
||||
$beers = R::tagged( 'beer', 'lager,popular' );
|
||||
asrt(count($beers),0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests tags with SQL.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTagsWithSQL()
|
||||
{
|
||||
R::nuke();
|
||||
list( $m1, $m2, $m3 ) = R::dispense( 'movie', 3 );
|
||||
$m1->title = 'Frankenstein';
|
||||
$m2->title = 'Fall of the House Usher';
|
||||
$m3->title = 'Sleepy Hollow';
|
||||
R::tag($m1, 'horror,gothic');
|
||||
R::tag($m2, 'horror,gothic,short');
|
||||
R::tag($m3, 'horror,legend');
|
||||
asrt( count( R::tagged( 'movie', 'horror' ) ), 3);
|
||||
asrt( count( R::tagged( 'movie', 'horror', ' LIMIT 2' ) ), 2);
|
||||
asrt( count( R::tagged( 'movie', 'horror', ' LIMIT ?', array( 2 ) ) ), 2);
|
||||
asrt( count( R::tagged( 'movie', 'horror', ' ORDER BY movie.title DESC LIMIT ?', array( 2 ) ) ), 2);
|
||||
asrt( count( R::tagged( 'movie', 'horror,gothic', ' ORDER BY movie.title DESC LIMIT ?', array( 1 ) ) ), 1);
|
||||
asrt( count( R::tagged( 'movie', 'horror,gothic') ), 3 );
|
||||
asrt( count( R::taggedAll( 'movie', 'horror,gothic') ), 2 );
|
||||
asrt( R::countTaggedAll( 'movie', 'horror,gothic'), 2 );
|
||||
asrt( count( R::tagged( 'movie', 'horror,gothic', ' LIMIT ? ', array( 2 ) ) ), 2 );
|
||||
asrt( ( R::countTagged( 'movie', 'horror,gothic', ' LIMIT ? ', array( 2 ) ) ), 2 );
|
||||
asrt( count( R::taggedAll( 'movie', 'horror,gothic', ' LIMIT ? ', array( 2 ) ) ), 2 );
|
||||
asrt( R::countTaggedAll( 'movie', 'horror,gothic', ' LIMIT ? ', array( 2 ) ), 2 );
|
||||
asrt( count( R::tagged( 'movie', 'horror,gothic', ' LIMIT ? ', array( 1 ) ) ), 1 );
|
||||
asrt( ( R::countTagged( 'movie', 'horror,gothic', ' LIMIT ? ', array( 1 ) ) ), 1 );
|
||||
asrt( count( R::taggedAll( 'movie', 'horror,gothic', ' LIMIT ? ', array( 1 ) ) ), 1 );
|
||||
asrt( ( R::countTaggedAll( 'movie', 'horror,gothic', ' LIMIT ? ', array( 1 ) ) ), 1 );
|
||||
asrt( count( R::tagged( 'movie', 'horror,legend', ' LIMIT ? ', array( 1 ) ) ), 1 );
|
||||
asrt( ( R::countTagged( 'movie', 'horror,legend', ' LIMIT ? ', array( 1 ) ) ), 1 );
|
||||
asrt( count( R::taggedAll( 'movie', 'horror,legend', ' LIMIT ? ', array( 1 ) ) ), 1 );
|
||||
asrt( ( R::countTaggedAll( 'movie', 'horror,legend', ' LIMIT ? ', array( 1 ) ) ), 1 );
|
||||
asrt( count( R::tagged( 'movie', 'gothic,legend', ' LIMIT ? ', array( 1 ) ) ), 1 );
|
||||
asrt( ( R::countTagged( 'movie', 'gothic,legend', ' LIMIT ? ', array( 1 ) ) ), 1 );
|
||||
asrt( count( R::taggedAll( 'movie', 'gothic,legend', ' LIMIT ? ', array( 1 ) ) ), 0 );
|
||||
asrt( ( R::countTaggedAll( 'movie', 'gothic,legend', ' LIMIT ? ', array( 1 ) ) ), 0 );
|
||||
asrt( count( R::tagged( 'movie', 'romance', ' LIMIT ? ', array( 1 ) ) ), 0 );
|
||||
asrt( ( R::countTagged( 'movie', 'romance', ' LIMIT ? ', array( 1 ) ) ), 0 );
|
||||
asrt( count( R::taggedAll( 'movie', 'romance', ' LIMIT ? ', array( 1 ) ) ), 0 );
|
||||
asrt( ( R::countTaggedAll( 'movie', 'romance', ' LIMIT ? ', array( 1 ) ) ), 0 );
|
||||
asrt( count( R::tagged( 'movie', 'romance,xmas', ' LIMIT ? ', array( 1 ) ) ), 0 );
|
||||
asrt( ( R::countTagged( 'movie', 'romance,xmas', ' LIMIT ? ', array( 1 ) ) ), 0 );
|
||||
asrt( count( R::taggedAll( 'movie', 'romance,xmas', ' LIMIT ? ', array( 1 ) ) ), 0 );
|
||||
asrt( ( R::countTaggedAll( 'movie', 'romance,xmas', ' LIMIT ? ', array( 1 ) ) ), 0 );
|
||||
asrt( count( R::tagged( 'movie', 'gothic,short', ' LIMIT ? ', array( 4 ) ) ), 2 );
|
||||
asrt( ( R::countTagged( 'movie', 'gothic,short', ' LIMIT ? ', array( 4 ) ) ), 2 );
|
||||
asrt( count( R::taggedAll( 'movie', 'gothic,short', ' LIMIT ? ', array( 4 ) ) ), 1 );
|
||||
asrt( ( R::countTaggedAll( 'movie', 'gothic,short', ' LIMIT ? ', array( 4 ) ) ), 1 );
|
||||
asrt( count( R::tagged( 'movie', 'gothic,short', ' LIMIT 4 ' ) ), 2 );
|
||||
asrt( ( R::countTagged( 'movie', 'gothic,short', ' LIMIT 4 ' ) ), 2 );
|
||||
asrt( count( R::taggedAll( 'movie', 'gothic,short', ' LIMIT 4 ' ) ), 1 );
|
||||
asrt( ( R::countTaggedAll( 'movie', 'gothic,short', ' LIMIT 4 ' ) ), 1 );
|
||||
asrt( count( R::tagged( 'movie', 'gothic,short', ' ORDER BY movie.id DESC LIMIT 4 ' ) ), 2 );
|
||||
asrt( ( R::countTagged( 'movie', 'gothic,short', ' ORDER BY movie.id DESC LIMIT 4 ' ) ), 2 );
|
||||
asrt( count( R::taggedAll( 'movie', 'gothic,short', ' ORDER BY movie.id DESC LIMIT 4 ' ) ), 1 );
|
||||
asrt( ( R::countTaggedAll( 'movie', 'gothic,short', ' ORDER BY movie.id DESC LIMIT 4 ' ) ), 1 );
|
||||
asrt( count( R::tagged( 'movie', 'short', ' LIMIT ? ', array( 4 ) ) ), 1 );
|
||||
asrt( ( R::countTagged( 'movie', 'short', ' LIMIT ? ', array( 4 ) ) ), 1 );
|
||||
asrt( count( R::taggedAll( 'movie', 'short', ' LIMIT ? ', array( 4 ) ) ), 1 );
|
||||
asrt( ( R::countTaggedAll( 'movie', 'short', ' LIMIT ? ', array( 4 ) ) ), 1 );
|
||||
asrt( count( R::tagged( 'movie', '', ' LIMIT ? ', array( 4 ) ) ), 0 );
|
||||
asrt( ( R::countTagged( 'movie', '', ' LIMIT ? ', array( 4 ) ) ), 0 );
|
||||
asrt( count( R::taggedAll( 'movie', '', ' LIMIT ? ', array( 4 ) ) ), 0 );
|
||||
asrt( ( R::countTaggedAll( 'movie', '', ' LIMIT ? ', array( 4 ) ) ), 0 );
|
||||
asrt( count( R::tagged( 'movie', '', ' LIMIT 4 ' ) ), 0 );
|
||||
asrt( ( R::countTagged( 'movie', '', ' LIMIT 4 ' ) ), 0 );
|
||||
asrt( count( R::taggedAll( 'movie', '', ' LIMIT 4 ' ) ), 0 );
|
||||
asrt( ( R::countTaggedAll( 'movie', '', ' LIMIT 4 ' ) ), 0 );
|
||||
asrt( count( R::tagged( 'movie', '', '' ) ), 0 );
|
||||
asrt( ( R::countTagged( 'movie', '', '' ) ), 0 );
|
||||
asrt( count( R::taggedAll( 'movie', '', '' ) ), 0 );
|
||||
asrt( ( R::countTaggedAll( 'movie', '', '' ) ), 0 );
|
||||
asrt( count( R::tagged( 'movie', '' ) ), 0 );
|
||||
asrt( ( R::countTagged( 'movie', '' ) ), 0 );
|
||||
asrt( count( R::taggedAll( 'movie', '' ) ), 0 );
|
||||
asrt( ( R::countTaggedAll( 'movie', '' ) ), 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Some basic tests.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTags()
|
||||
{
|
||||
list( $c, $d, $e, $f ) = R::dispense( 'coffee', 4 );
|
||||
R::tag( $c, 'strong,black' );
|
||||
R::tag( $d, 'black' );
|
||||
R::tag( $e, 'strong,sweet' );
|
||||
R::tag( $f, 'black,strong' );
|
||||
asrt( count( R::taggedAll( 'coffee', 'strong,sweet' ) ), 1 );
|
||||
asrt( count( R::taggedAll( 'coffee', 'strong' ) ), 3 );
|
||||
asrt( count( R::taggedAll( 'coffee', '' ) ), 0 );
|
||||
asrt( count( R::taggedAll( 'coffee', 'sweet' ) ), 1 );
|
||||
asrt( count( R::taggedAll( 'coffee', 'sweet,strong' ) ), 1 );
|
||||
asrt( count( R::taggedAll( 'coffee', 'black,strong' ) ), 2 );
|
||||
asrt( count( R::taggedAll( 'coffee', array( 'black', 'strong' ) ) ), 2 );
|
||||
asrt( count( R::taggedAll( 'coffee', 'salty' ) ), 0 );
|
||||
$blog = R::dispense( 'blog' );
|
||||
$blog->title = 'testing';
|
||||
$blog->blog = 'tesing';
|
||||
R::store( $blog );
|
||||
$blogpost = ( R::load( "blog", 1 ) );
|
||||
$post = R::dispense( "post" );
|
||||
$post->message = "hello";
|
||||
R::tag( $post, "lousy,smart" );
|
||||
asrt( implode( ',', R::tag( $post ) ), "lousy,smart" );
|
||||
R::tag( $post, "clever,smart" );
|
||||
$tagz = implode( ',', R::tag( $post ) );
|
||||
asrt( ( $tagz == "smart,clever" || $tagz == "clever,smart" ), TRUE );
|
||||
R::tag( $blog, array( "smart", "interesting" ) );
|
||||
asrt( implode( ',', R::tag( $blog ) ), "smart,interesting" );
|
||||
try {
|
||||
R::tag( $blog, array( "smart", "interesting", "lousy!" ) );
|
||||
pass();
|
||||
} catch ( RedException $e ) {
|
||||
fail();
|
||||
}
|
||||
asrt( implode( ',', R::tag( $blog ) ), "smart,interesting,lousy!" );
|
||||
R::untag( $blog, array( "smart", "interesting" ) );
|
||||
asrt( implode( ",", R::tag( $blog ) ), "lousy!" );
|
||||
asrt( R::hasTag( $blog, array( "lousy!" ) ), TRUE );
|
||||
asrt( R::hasTag( $blog, array( "lousy!", "smart" ) ), TRUE );
|
||||
asrt( R::hasTag( $blog, array( "lousy!", "smart" ), TRUE ), FALSE );
|
||||
R::tag( $blog, FALSE );
|
||||
asrt( count( R::tag( $blog ) ), 0 );
|
||||
R::tag( $blog, array( "funny", "comic" ) );
|
||||
asrt( count( R::tag( $blog ) ), 2 );
|
||||
R::addTags( $blog, array( "halloween" ) );
|
||||
asrt( count( R::tag( $blog ) ), 3 );
|
||||
asrt( R::hasTag( $blog, array( "funny", "commic", "halloween" ), TRUE ), FALSE );
|
||||
R::unTag( $blog, "funny" );
|
||||
R::addTags( $blog, "horror" );
|
||||
asrt( count( R::tag( $blog ) ), 3 );
|
||||
asrt( R::hasTag( $blog, array( "horror", "commic", "halloween" ), TRUE ), FALSE );
|
||||
//no double tags
|
||||
R::addTags( $blog, "horror" );
|
||||
asrt( R::hasTag( $blog, array( "horror", "commic", "halloween" ), TRUE ), FALSE );
|
||||
asrt( R::hasTag( $blog, "horror,commic,halloween", TRUE ), FALSE );
|
||||
asrt( count( R::tag( $blog ) ), 3 );
|
||||
testpack( "fetch tagged items" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetching tagged items.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function fetchTaggedItems()
|
||||
{
|
||||
$b = R::dispense( "book" );
|
||||
$b->title = 'horror';
|
||||
R::store( $b );
|
||||
$c = R::dispense( "book" );
|
||||
$c->title = 'creepy';
|
||||
R::store( $c );
|
||||
$d = R::dispense( "book" );
|
||||
$d->title = "chicklit";
|
||||
R::store( $d );
|
||||
R::tag( $b, "horror,classic" );
|
||||
R::tag( $d, "women,classic" );
|
||||
R::tag( $c, "horror" );
|
||||
$x = R::tagged( "book", "classic" );
|
||||
asrt( count( $x ), 2 );
|
||||
$x = R::tagged( "book", "classic,horror" );
|
||||
asrt( count( $x ), 3 );
|
||||
$x = R::tagged( "book", array( "classic", "horror" ) );
|
||||
asrt( count( $x ), 3 );
|
||||
}
|
||||
}
|
||||
129
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Threeway.php
vendored
Normal file
129
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Threeway.php
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\RedException as RedException;
|
||||
use RedBeanPHP\QueryWriter\AQueryWriter as AQueryWriter;
|
||||
|
||||
/**
|
||||
* Threeway
|
||||
*
|
||||
* Tests link/via relations, i.e. N-M tables with additional
|
||||
* columns.
|
||||
*
|
||||
* @file RedUNIT/Base/Threeway.php
|
||||
* @desc Various tests for 3-way tables or X-way tables.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Threeway extends Base
|
||||
{
|
||||
/**
|
||||
* Test whether we can use threeway tables without being
|
||||
* bothered by unique constraints.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testUniqueConstraintOnThreeways()
|
||||
{
|
||||
AQueryWriter::clearRenames();
|
||||
R::nuke();
|
||||
$person = R::dispense( 'person' );
|
||||
$role = R::dispense( 'role' );
|
||||
$person->sharedRole[] = $role;
|
||||
R::store( $person );
|
||||
$person->link( 'person_role', array(
|
||||
'unit' => R::dispense('unit')
|
||||
))->role = $role;
|
||||
//Can we add a duplicate role now? - No because we started with a simple N-M table
|
||||
//and unique constraint has been applied accordingly, manually change database.
|
||||
asrt( R::count( 'person_role' ), 1 );
|
||||
R::nuke();
|
||||
$person = R::dispense( 'person' );
|
||||
$role = R::dispense( 'role' );
|
||||
$person->via('participant')->sharedRole[] = $role;
|
||||
R::store( $person );
|
||||
$person->link( 'participant', array(
|
||||
'unit' => R::dispense('unit')
|
||||
))->role = $role;
|
||||
//Can we add a duplicate role now? - No because we started with a simple N-M table
|
||||
//and unique constraint has been applied accordingly, manually change database.
|
||||
asrt( R::count( 'participant' ), 1 );
|
||||
R::nuke();
|
||||
$participant = R::dispense( 'participant' );
|
||||
$person = R::dispense( 'person' );
|
||||
$role = R::dispense( 'role' );
|
||||
$unit = R::dispense( 'unit' );
|
||||
$participant->person = $person;
|
||||
$participant->role = $role;
|
||||
$participant->unit = $unit;
|
||||
R::store( $participant );
|
||||
$person->link( 'participant', array(
|
||||
'unit' => R::dispense('unit')
|
||||
))->role = $role;
|
||||
R::store( $person );
|
||||
//Can we add a duplicate role now?
|
||||
asrt( R::count( 'participant' ), 2 );
|
||||
AQueryWriter::clearRenames();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether a duplicate bean in the list isnt saved.
|
||||
* This was an issue with Postgres while testing the threeway tables.
|
||||
* Postgres returned the ID as a string while other drivers returned
|
||||
* a numeric value causing different outcome in array_diff when
|
||||
* calculating the shared additions.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIssueWithDriverReturnID()
|
||||
{
|
||||
AQueryWriter::clearRenames();
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$page = R::dispense( 'page' );
|
||||
$book->sharedPageList[] = $page;
|
||||
R::store( $book );
|
||||
asrt( R::count( 'page' ), 1 );
|
||||
$book = $book->fresh();
|
||||
$book->sharedPageList[] = $page;
|
||||
R::store( $book );
|
||||
//don't save the duplicate bean!
|
||||
asrt( R::count( 'page' ), 1 );
|
||||
$book = $book->fresh();
|
||||
$page->item = 2; //even if we change a property ?
|
||||
$book->sharedPageList[] = $page;
|
||||
R::store( $book );
|
||||
foreach( $book->sharedPageList as $listItem) {
|
||||
asrt( is_string( $listItem->id ), TRUE );
|
||||
}
|
||||
//same test but for own-list
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$page = R::dispense( 'page' );
|
||||
$book->ownPageList[] = $page;
|
||||
R::store( $book );
|
||||
asrt( R::count( 'page' ), 1 );
|
||||
$book = $book->fresh();
|
||||
$book->ownPageList[] = $page;
|
||||
R::store( $book );
|
||||
//don't save the duplicate bean!
|
||||
asrt( R::count( 'page' ), 1 );
|
||||
$book = $book->fresh();
|
||||
$book->ownPageList[] = $page;
|
||||
$page->item = 3;
|
||||
R::store( $book );
|
||||
//don't save the duplicate bean!
|
||||
asrt( R::count( 'page' ), 1 );
|
||||
foreach( $book->ownPageList as $listItem) {
|
||||
asrt( is_string( $listItem->id ), TRUE );
|
||||
}
|
||||
AQueryWriter::clearRenames();
|
||||
}
|
||||
}
|
||||
49
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Trash.php
vendored
Normal file
49
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Trash.php
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
|
||||
/**
|
||||
* Trash
|
||||
*
|
||||
* Test trashing of beans.
|
||||
*
|
||||
* @file RedUNIT/Base/Trash.php
|
||||
* @desc Tests R::trash()
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Trash extends Base
|
||||
{
|
||||
/**
|
||||
* Test whether R::trash/trashAll() returns the correct
|
||||
* number of deleted beans.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTrash()
|
||||
{
|
||||
R::nuke();
|
||||
$id = R::store(R::dispense(array(
|
||||
'_type'=>'book',
|
||||
'pages'=>3
|
||||
)
|
||||
));
|
||||
asrt( R::count('book'), 1 );
|
||||
$n = R::trash(R::findOne('book'));
|
||||
asrt( $n, 1 );
|
||||
asrt( R::count('book'), 0 );
|
||||
list($books) = R::dispenseAll('book*10');
|
||||
R::storeAll( $books );
|
||||
asrt( R::count('book'), 10 );
|
||||
$n = R::trashAll( $books );
|
||||
asrt( R::count('book'), 0 );
|
||||
}
|
||||
}
|
||||
249
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Traverse.php
vendored
Normal file
249
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Traverse.php
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\RedException as RedException;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
|
||||
/**
|
||||
* Traverse
|
||||
*
|
||||
* Tests whether RedBeanPHP can easily deal with hierarchies
|
||||
* of beans.
|
||||
*
|
||||
* @file RedUNIT/Base/Traverse.php
|
||||
* @desc Tests traversal functionality
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Traverse extends Base
|
||||
{
|
||||
/**
|
||||
* Very simple traverse case (one-level).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSimplestTraversal()
|
||||
{
|
||||
R::nuke();
|
||||
$books = R::dispense( 'book', 10 );
|
||||
$i = 1;
|
||||
foreach( $books as $book ) {
|
||||
$book->title = 'Book ' . ( $i++ );
|
||||
}
|
||||
$books[5]->marked = TRUE;
|
||||
$shelf = R::dispense( 'shelf' );
|
||||
$shelf->ownBook = $books;
|
||||
$found = NULL;
|
||||
$shelf->traverse('ownBookList', function( $book ) use ( &$found ) {
|
||||
if ( $book->marked ) $found = $book;
|
||||
});
|
||||
asrt( ( $found->marked == TRUE ), TRUE );
|
||||
asrt( $found->title, 'Book 6' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests basic traversal.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBasicTraversal()
|
||||
{
|
||||
R::nuke();
|
||||
$pageA = R::dispense( 'page' )->setAttr( 'title', 'a' );
|
||||
$pageB = R::dispense( 'page' )->setAttr( 'title', 'b' );
|
||||
$pageC = R::dispense( 'page' )->setAttr( 'title', 'c' );
|
||||
$pageD = R::dispense( 'page' )->setAttr( 'title', 'd' );
|
||||
$pageE = R::dispense( 'page' )->setAttr( 'title', 'e' );
|
||||
$pageF = R::dispense( 'page' )->setAttr( 'title', 'f' );
|
||||
$pageG = R::dispense( 'page' )->setAttr( 'title', 'g' );
|
||||
$pageH = R::dispense( 'page' )->setAttr( 'title', 'h' );
|
||||
$pageA->ownPage = array( $pageB, $pageC );
|
||||
$pageB->ownPage = array( $pageD );
|
||||
$pageC->ownPage = array( $pageE, $pageF );
|
||||
$pageD->ownPage = array( $pageG );
|
||||
$pageF->ownPage = array( $pageH );
|
||||
R::store( $pageA );
|
||||
$pageA = $pageA->fresh();
|
||||
//also tests non-existant column handling by count().
|
||||
asrt( R::count( 'page', ' price = ? ', array( '5' ) ), 0);
|
||||
asrt( R::count( 'tag', ' title = ? ', array( 'new' ) ), 0);
|
||||
$pageA->traverse( 'ownPageList', function( $bean ) {
|
||||
$bean->price = 5;
|
||||
});
|
||||
R::store( $pageA );
|
||||
asrt( R::count( 'page', ' price = ? ', array( '5' ) ), 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test traversing paths, ancestry.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTraversePaths()
|
||||
{
|
||||
R::nuke();
|
||||
$pageA = R::dispense( 'page' )->setAttr( 'title', 'a' );
|
||||
$pageB = R::dispense( 'page' )->setAttr( 'title', 'b' );
|
||||
$pageC = R::dispense( 'page' )->setAttr( 'title', 'c' );
|
||||
$pageD = R::dispense( 'page' )->setAttr( 'title', 'd' );
|
||||
$pageE = R::dispense( 'page' )->setAttr( 'title', 'e' );
|
||||
$pageF = R::dispense( 'page' )->setAttr( 'title', 'f' );
|
||||
$pageG = R::dispense( 'page' )->setAttr( 'title', 'g' );
|
||||
$pageH = R::dispense( 'page' )->setAttr( 'title', 'h' );
|
||||
$pageA->ownPage = array( $pageB, $pageC );
|
||||
$pageB->ownPage = array( $pageD );
|
||||
$pageC->ownPage = array( $pageE, $pageF );
|
||||
$pageD->ownPage = array( $pageG );
|
||||
$pageF->ownPage = array( $pageH );
|
||||
R::store( $pageA );
|
||||
$parents = array();
|
||||
$pageF->traverse( 'page', function( $page ) use ( &$parents ) {
|
||||
$parents[] = $page->title;
|
||||
} );
|
||||
asrt( implode( ',', $parents ), 'c,a' );
|
||||
$parents = array();
|
||||
$pageH->traverse( 'page', function( $page ) use ( &$parents ) {
|
||||
$parents[] = $page->title;
|
||||
} );
|
||||
asrt( implode( ',', $parents ), 'f,c,a' );
|
||||
$parents = array();
|
||||
$pageG->traverse( 'page', function( $page ) use ( &$parents ) {
|
||||
$parents[] = $page->title;
|
||||
} );
|
||||
asrt( implode( ',', $parents ), 'd,b,a' );
|
||||
$path = array();
|
||||
$pageA->traverse( 'ownPageList', function( $page ) use ( &$path ) {
|
||||
$path[] = $page->title;
|
||||
} );
|
||||
asrt( implode( ',', $path ), 'b,d,g,c,e,f,h' );
|
||||
$path = array();
|
||||
$pageC->traverse( 'ownPageList', function( $page ) use ( &$path ) {
|
||||
$path[] = $page->title;
|
||||
} );
|
||||
asrt( implode( ',', $path ), 'e,f,h' );
|
||||
$path = array();
|
||||
$pageA->traverse( 'ownPageList', function( $page ) use ( &$path ) {
|
||||
$path[] = $page->title;
|
||||
}, 2 );
|
||||
asrt( implode( ',', $path ), 'b,d,c,e,f' );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 traversal with aliases.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTraversalWithAlias()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$cats = R::dispense( 'category', 3 );
|
||||
$cats[0]->gname = 'SF';
|
||||
$cats[1]->gname = 'Fantasy';
|
||||
$cats[2]->gname = 'Horror';
|
||||
$book->genre = $cats[0];
|
||||
$book->name = 'Space Story';
|
||||
$cats[0]->genre = $cats[1];
|
||||
$cats[2]->genre = $cats[1];
|
||||
R::store( $book );
|
||||
$book2 = R::dispense( 'book' );
|
||||
$book2->genre = $cats[2];
|
||||
$book2->name = 'Ghost Story';
|
||||
R::store( $book2 );
|
||||
$fantasy = R::load( 'category', $cats[1]->id );
|
||||
$cats = array();
|
||||
$book = $book->fresh();
|
||||
$book->fetchAs( 'category' )->traverse( 'genre', function( $cat ) use ( &$cats ) {
|
||||
$cats[] = $cat->gname;
|
||||
} );
|
||||
asrt( implode( ',', $cats ), 'SF,Fantasy' );
|
||||
$catList = array();
|
||||
$fantasy->alias( 'genre' )
|
||||
->with( ' ORDER BY gname ASC ' )
|
||||
->traverse( 'ownCategory', function( $cat ) use ( &$catList ) {
|
||||
$catList[] = $cat->gname;
|
||||
} );
|
||||
asrt( implode( ',', $catList ), 'Horror,SF' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverse can only work with own-lists, otherwise infinite loops.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSharedTraversal()
|
||||
{
|
||||
$friend = R::dispense( 'friend' );
|
||||
try {
|
||||
$friend->traverse( 'sharedFriend', function( $friend ){ } );
|
||||
fail();
|
||||
} catch( RedException $e ) {
|
||||
pass();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether traverse() passes the depth of the
|
||||
* current item in the tree along with the bean.
|
||||
*/
|
||||
public function testDepthCount()
|
||||
{
|
||||
R::nuke();
|
||||
$page = R::dispense('page');
|
||||
$page->num = 1;
|
||||
$root = $page;
|
||||
for($i = 2; $i < 10; $i++) {
|
||||
$child = R::dispense('page');
|
||||
$page->ownPageList[] = $child;
|
||||
$child->num = $i;
|
||||
$page = $child;
|
||||
}
|
||||
R::store($root);
|
||||
$total = 0;
|
||||
$page = $root->fresh();
|
||||
$page->traverse('ownPageList', function( $child, $count ) use(&$total) {
|
||||
asrt( $count+1, intval($child->num) );
|
||||
$total += $count;
|
||||
});
|
||||
asrt( $total, 36 );
|
||||
}
|
||||
}
|
||||
151
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Typechecking.php
vendored
Normal file
151
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Typechecking.php
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\RedException as RedException;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
|
||||
/**
|
||||
* Typechecking
|
||||
*
|
||||
* Tests whether RedBeanPHP handles type casting correctly.
|
||||
*
|
||||
* @file RedUNIT/Base/Typechecking.php
|
||||
* @desc Tests basic bean validation rules; invalid bean handling.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Typechecking extends Base
|
||||
{
|
||||
/**
|
||||
* Test types.
|
||||
* Test how RedBeanPHP OODB and OODBBean handle type and type casts.
|
||||
*
|
||||
* Rules:
|
||||
*
|
||||
* 1. before storing a bean all types are preserved except booleans (they are converted to STRINGS '0' or '1')
|
||||
* 2. after store-reload all bean property values are STRINGS or NULL
|
||||
* (or ARRAYS but that's only from a user perspective because these are lazy loaded)
|
||||
* 3. the ID returned by store() is an INTEGER (if possible; on 32 bit systems overflowing values will be cast to STRINGS!)
|
||||
*
|
||||
* After loading:
|
||||
* ALL VALUES EXCEPT NULL -> STRING
|
||||
* NULL -> NULL
|
||||
*
|
||||
* @note Why not simply return bean->id in store()? Because not every driver returns the same type:
|
||||
* databases without insert_id support require a separate query or a suffix returning STRINGS, not INTEGERS.
|
||||
*
|
||||
* @note Why not preserve types? I.e. I store integer, why do I get back a string?
|
||||
* Answer: types are handled different across database platforms, would cause overhead to inspect every value for type,
|
||||
* also PHP is a dynamically typed language so types should not matter that much. Another reason: due to the nature
|
||||
* of RB columns in the database might change (INT -> STRING) this would cause return types to change as well which would
|
||||
* cause 'cascading errors', i.e. a column gets widened and suddenly your code would break.
|
||||
*
|
||||
* @note Unfortunately the 32/64-bit issue cannot be tested fully. Return-strategy store() is probably the safest
|
||||
* solution.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTypes()
|
||||
{
|
||||
testpack( 'Beans can only contain STRING and NULL after reload' );
|
||||
R::nuke();
|
||||
$bean = R::dispense( 'bean' );
|
||||
$bean->number = 123;
|
||||
$bean->float = 12.3;
|
||||
$bean->bool = FALSE;
|
||||
$bean->bool2 = TRUE;
|
||||
$bean->text = 'abc';
|
||||
$bean->null = null;
|
||||
$bean->datetime = new\DateTime( 'NOW', new\DateTimeZone( 'Europe/Amsterdam' ) );
|
||||
$id = R::store( $bean );
|
||||
asrt( is_int( $id ), TRUE );
|
||||
asrt( is_float( $bean->float ), TRUE );
|
||||
asrt( is_integer( $bean->number ), TRUE );
|
||||
asrt( is_string( $bean->bool ), TRUE );
|
||||
asrt( is_string( $bean->bool2 ), TRUE );
|
||||
asrt( is_string( $bean->datetime ), TRUE );
|
||||
asrt( is_string( $bean->text ), TRUE );
|
||||
asrt( is_null( $bean->null ), TRUE );
|
||||
$bean = R::load('bean', $id );
|
||||
asrt( is_string( $bean->id ), TRUE );
|
||||
asrt( is_string( $bean->float ), TRUE );
|
||||
asrt( is_string( $bean->number ), TRUE );
|
||||
asrt( is_string( $bean->bool ), TRUE );
|
||||
asrt( is_string( $bean->bool2 ), TRUE );
|
||||
asrt( is_string( $bean->datetime ), TRUE );
|
||||
asrt( is_string( $bean->text ), TRUE );
|
||||
asrt( is_null( $bean->null ), TRUE );
|
||||
asrt( $bean->bool, '0' );
|
||||
asrt( $bean->bool2, '1' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test bean type checking.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBeanTypeChecking()
|
||||
{
|
||||
$redbean = R::getRedBean();
|
||||
$bean = $redbean->dispense( "page" );
|
||||
// Set some illegal values in the bean; this should trigger Security exceptions.
|
||||
// Arrays are not allowed.
|
||||
$bean->name = array( "1" );
|
||||
try {
|
||||
$redbean->store( $bean );
|
||||
fail();
|
||||
} catch ( RedException $e ) {
|
||||
pass();
|
||||
}
|
||||
try {
|
||||
$redbean->check( $bean );
|
||||
fail();
|
||||
} catch ( RedException $e ) {
|
||||
pass();
|
||||
}
|
||||
$bean->name = new OODBBean;
|
||||
try {
|
||||
$redbean->check( $bean );
|
||||
fail();
|
||||
} catch ( RedException $e ) {
|
||||
pass();
|
||||
}
|
||||
// Property names should be alphanumeric
|
||||
$prop = ".";
|
||||
$bean->$prop = 1;
|
||||
try {
|
||||
$redbean->store( $bean );
|
||||
fail();
|
||||
} catch ( RedException $e ) {
|
||||
pass();
|
||||
}
|
||||
try {
|
||||
$redbean->check( $bean );
|
||||
fail();
|
||||
} catch ( RedException $e ) {
|
||||
pass();
|
||||
}
|
||||
// Really...
|
||||
$prop = "-";
|
||||
$bean->$prop = 1;
|
||||
try {
|
||||
$redbean->store( $bean );
|
||||
fail();
|
||||
} catch ( RedException $e ) {
|
||||
pass();
|
||||
}
|
||||
try {
|
||||
$redbean->check( $bean );
|
||||
fail();
|
||||
} catch ( RedException $e ) {
|
||||
pass();
|
||||
}
|
||||
}
|
||||
}
|
||||
448
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Update.php
vendored
Normal file
448
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Update.php
vendored
Normal file
@@ -0,0 +1,448 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\RedException as RedException;
|
||||
use RedBeanPHP\QueryWriter as QueryWriter;
|
||||
use RedBeanPHP\QueryWriter\AQueryWriter as AQueryWriter;
|
||||
use RedBeanPHP\Logger\RDefault as Logger;
|
||||
|
||||
/**
|
||||
* Update
|
||||
*
|
||||
* Tests basic update functionality - however this test suite
|
||||
* has grown to cover various other scenarios involving updates as
|
||||
* well, including setting of property filters (necessary for
|
||||
* spatial tools in MySQL), storiging INF value and more...
|
||||
*
|
||||
* @file RedUNIT/Base/Update.php
|
||||
* @desc Tests basic storage features through OODB class.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Update extends Base
|
||||
{
|
||||
/**
|
||||
* Tests whether no unncessary DESCRIBE-queries are executed,
|
||||
* (Commit 3b8ce88e5b796bfde6485ab0a51a4fcfb1bcf0fa by davidsickmiller).
|
||||
* Even thtough we add 2 properties, only 1 DESCRIBE query is necessary
|
||||
* to load the column cache.
|
||||
*/
|
||||
public function testModifySchemaColCache()
|
||||
{
|
||||
R::nuke();
|
||||
$toolbox = R::getToolbox();
|
||||
$repository = $toolbox->getRedBean()->getCurrentRepository();
|
||||
$database = $toolbox->getDatabaseAdapter()->getDatabase();
|
||||
$logger = new Logger;
|
||||
$database->setLogger( $logger );
|
||||
$bean = R::dispense('bean');
|
||||
$bean->property1 = 'test';
|
||||
$bean->property2 = 'test'; //should not cause 2nd DESCRIBE.
|
||||
R::startLogging();
|
||||
R::store( $bean );
|
||||
$logger = R::getLogger();
|
||||
asrt(
|
||||
count( $logger->grep('DESCRIBE') ) +
|
||||
count( $logger->grep('SELECT column_name') ) +
|
||||
count( $logger->grep('SHOW COLUMNS') ) + //CUBRID
|
||||
count( $logger->grep('PRAGMA table_info') )
|
||||
, 1);
|
||||
R::stopLogging();
|
||||
//new round, same results, no cache between beans
|
||||
R::nuke();
|
||||
$bean = R::dispense('bean');
|
||||
$bean->property1 = 'test';
|
||||
$bean->property2 = 'test'; //should not cause 2nd DESCRIBE.
|
||||
R::startLogging();
|
||||
R::store( $bean );
|
||||
$logger = R::getLogger();
|
||||
asrt(
|
||||
count( $logger->grep('DESCRIBE') ) +
|
||||
count( $logger->grep('SELECT column_name') ) +
|
||||
count( $logger->grep('SHOW COLUMNS') ) + //CUBRID
|
||||
count( $logger->grep('PRAGMA table_info') )
|
||||
, 1);
|
||||
R::stopLogging();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether we can use SQL filters and
|
||||
* whether they are being applied properly for
|
||||
* different types of SELECT queries in the QueryWriter.
|
||||
*/
|
||||
public function testSQLFilters()
|
||||
{
|
||||
R::nuke();
|
||||
AQueryWriter::setSQLFilters(array(
|
||||
QueryWriter::C_SQLFILTER_READ => array(
|
||||
'book' => array( 'title' => ' LOWER(book.title) '),
|
||||
),
|
||||
QueryWriter::C_SQLFILTER_WRITE => array(
|
||||
'book' => array( 'title' => ' UPPER(?) '),
|
||||
),
|
||||
));
|
||||
|
||||
$book = R::dispense( 'book' );
|
||||
$book->title = 'story';
|
||||
R::store( $book );
|
||||
asrt( R::getCell( 'SELECT title FROM book WHERE id = ?', array( $book->id ) ), 'STORY' );
|
||||
$book = $book->fresh();
|
||||
asrt( $book->title, 'story' );
|
||||
$library = R::dispense( 'library' );
|
||||
$library->sharedBookList[] = $book;
|
||||
R::store( $library );
|
||||
$library = $library->fresh();
|
||||
$books = $library->sharedBookList;
|
||||
$book = reset( $books );
|
||||
asrt( $book->title, 'story' );
|
||||
$otherBook = R::dispense('book');
|
||||
$otherBook->sharedBook[] = $book;
|
||||
R::store( $otherBook );
|
||||
$otherBook = $otherBook->fresh();
|
||||
$books = $otherBook->sharedBookList;
|
||||
$book = reset( $books );
|
||||
asrt( $book->title, 'story' );
|
||||
$links = $book->ownBookBookList;
|
||||
$link = reset( $links );
|
||||
$link->shelf = 'x13';
|
||||
AQueryWriter::setSQLFilters(array(
|
||||
QueryWriter::C_SQLFILTER_READ => array(
|
||||
'book' => array( 'title' => ' LOWER(book.title) '),
|
||||
'book_book' => array( 'shelf' => ' LOWER(book_book.shelf) '),
|
||||
),
|
||||
QueryWriter::C_SQLFILTER_WRITE => array(
|
||||
'book' => array( 'title' => ' UPPER(?) '),
|
||||
'book_book' => array( 'shelf' => ' UPPER(?) ')
|
||||
),
|
||||
));
|
||||
R::store( $link );
|
||||
asrt( R::getCell( 'SELECT shelf FROM book_book WHERE id = ?', array( $link->id ) ), 'X13' );
|
||||
$otherBook = $otherBook->fresh();
|
||||
unset($book->sharedBookList[$otherBook->id]);
|
||||
R::store( $book );
|
||||
AQueryWriter::setSQLFilters(array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test unsetting properties.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testUnsetUpdate()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$book->name = 'x';
|
||||
$book->price = 40;
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
$book->name = 'y';
|
||||
unset( $book->name );
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
asrt( $book->name, 'x' );
|
||||
asrt( (int) $book->price, 40 );
|
||||
$book->price = 30;
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
asrt( $book->name, 'x' );
|
||||
asrt( (int) $book->price, 30 );
|
||||
$book->price = 20;
|
||||
unset( $book->price );
|
||||
$book->name = 'y';
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
asrt( $book->name, 'y' );
|
||||
asrt( (int) $book->price, 30 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether we can update or unset a parent bean
|
||||
* with an alias without having to use fetchAs and
|
||||
* without loading the aliased bean causing table-not-found
|
||||
* errors.
|
||||
*/
|
||||
public function testUpdatingParentBeansWithAliases()
|
||||
{
|
||||
testpack( 'Test updating parent beans with aliases' );
|
||||
R::nuke();
|
||||
$trans = R::dispense( 'transaction' );
|
||||
$seller = R::dispense( 'user' );
|
||||
$trans->seller = $seller;
|
||||
$id = R::store( $trans );
|
||||
R::freeze( TRUE );
|
||||
$trans = R::load( 'transaction', $id );
|
||||
//should not try to load seller, should not require fetchAs().
|
||||
try {
|
||||
$trans->seller = R::dispense( 'user' );
|
||||
pass();
|
||||
} catch( Exception $e ) {
|
||||
fail();
|
||||
}
|
||||
$trans = R::load( 'transaction', $id );
|
||||
//same for unset...
|
||||
try {
|
||||
unset( $trans->seller );
|
||||
pass();
|
||||
} catch ( Exception $e ) {
|
||||
fail();
|
||||
}
|
||||
R::freeze( FALSE );
|
||||
$account = R::dispense( 'user' );
|
||||
asrt( count( $account->alias( 'seller' )->ownTransaction ), 0 );
|
||||
$account->alias( 'seller' )->ownTransaction = R::dispense( 'transaction', 10 );
|
||||
$account->alias( 'boo' ); //try to trick me...
|
||||
$id = R::store( $account );
|
||||
R::freeze( TRUE );
|
||||
$account = R::load( 'user', $id );
|
||||
asrt( count( $account->alias( 'seller' )->ownTransaction ), 10 );
|
||||
//you cannot unset a list
|
||||
unset( $account->alias( 'seller' )->ownTransaction );
|
||||
$id = R::store( $account );
|
||||
$account = R::load( 'user', $id );
|
||||
asrt( count( $account->alias( 'seller' )->ownTransaction ), 10 );
|
||||
$account->alias( 'seller' )->ownTransaction = array();
|
||||
$id = R::store( $account );
|
||||
$account = R::load( 'user', $id );
|
||||
asrt(count($account->alias( 'seller' )->ownTransaction), 0 );
|
||||
asrt(count($account->ownTransaction), 0 );
|
||||
R::freeze( FALSE );
|
||||
//but also make sure we don't cause extra column issue #335
|
||||
R::nuke();
|
||||
$building = R::dispense('building');
|
||||
$village = R::dispense('village');
|
||||
$building->village = $village;
|
||||
R::store($building);
|
||||
$building = $building->fresh();
|
||||
$building->village = NULL;
|
||||
R::store($building);
|
||||
$building = $building->fresh();
|
||||
$columns = R::inspect('building');
|
||||
asrt( isset( $columns['village'] ), FALSE );
|
||||
asrt( isset( $building->village ), FALSE );
|
||||
R::nuke();
|
||||
$building = R::dispense('building');
|
||||
$village = R::dispense('village');
|
||||
$building->village = $village;
|
||||
R::store($building);
|
||||
$building = $building->fresh();
|
||||
unset($building->village);
|
||||
R::store($building);
|
||||
$building = $building->fresh();
|
||||
$columns = R::inspect('building');
|
||||
asrt( isset( $columns['village'] ), FALSE );
|
||||
asrt( isset( $building->village ), FALSE );
|
||||
$building = R::dispense('building');
|
||||
$village = R::dispense('village');
|
||||
$building->village = $village;
|
||||
R::store($building);
|
||||
$building = $building->fresh();
|
||||
$building->village = FALSE;
|
||||
R::store($building);
|
||||
$building = $building->fresh();
|
||||
$columns = R::inspect('building');
|
||||
asrt( isset( $columns['village'] ), FALSE );
|
||||
asrt( isset( $building->village ), FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* All kinds of tests for basic CRUD.
|
||||
*
|
||||
* Does the data survive?
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testUpdatingBeans()
|
||||
{
|
||||
testpack( 'Test basic support UUID/override ID default value' );
|
||||
$bean = R::dispense( 'bean' );
|
||||
R::store( $bean );
|
||||
if ($this->currentlyActiveDriverID === 'mysql') {
|
||||
//otherwise UTF8 causes index overflow in mysql: SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes
|
||||
R::exec('alter table bean modify column id char(3);');
|
||||
} else {
|
||||
R::getWriter()->widenColumn( 'bean', 'id', R::getWriter()->scanType( 'abc' ) );
|
||||
}
|
||||
$bean->id = 'abc';
|
||||
R::store( $bean );
|
||||
asrt( $bean->id, 'abc' );
|
||||
testpack( 'Test Update' );
|
||||
try {
|
||||
R::store( array() );
|
||||
fail();
|
||||
} catch ( RedException $e ) {
|
||||
pass();
|
||||
}
|
||||
$toolbox = R::getToolBox();
|
||||
$adapter = $toolbox->getDatabaseAdapter();
|
||||
$writer = $toolbox->getWriter();
|
||||
$redbean = $toolbox->getRedBean();
|
||||
$pdo = $adapter->getDatabase();
|
||||
$page = $redbean->dispense( "page" );
|
||||
$page->name = "old name";
|
||||
$id = $redbean->store( $page );
|
||||
asrt( $page->getMeta( 'tainted' ), FALSE );
|
||||
$page->setAttr( 'name', "new name" );
|
||||
asrt( $page->getMeta( 'tainted' ), TRUE );
|
||||
$id = $redbean->store( $page );
|
||||
$page = $redbean->load( "page", $id );
|
||||
asrt( $page->name, "new name" );
|
||||
// Null should == NULL after saving
|
||||
$page->rating = NULL;
|
||||
$newid = $redbean->store( $page );
|
||||
$page = $redbean->load( "page", $id );
|
||||
asrt( $page->name, "new name" );
|
||||
asrt( ( $page->rating === NULL ), TRUE );
|
||||
asrt( !$page->rating, TRUE );
|
||||
$page->rating = FALSE;
|
||||
$newid = $redbean->store( $page );
|
||||
asrt( $newid, $id );
|
||||
$page = $redbean->load( "page", $id );
|
||||
asrt( $page->name, "new name" );
|
||||
asrt( (bool) $page->rating, FALSE );
|
||||
asrt( ( $page->rating == FALSE ), TRUE );
|
||||
asrt( !$page->rating, TRUE );
|
||||
$page->rating = TRUE;
|
||||
$newid = $redbean->store( $page );
|
||||
asrt( $newid, $id );
|
||||
$page = $redbean->load( "page", $id );
|
||||
asrt( $page->name, "new name" );
|
||||
asrt( (bool) $page->rating, TRUE );
|
||||
asrt( ( $page->rating == TRUE ), TRUE );
|
||||
asrt( ( $page->rating == TRUE ), TRUE );
|
||||
$page->rating = NULL;
|
||||
R::store( $page );
|
||||
$page = R::load( 'page', $page->id );
|
||||
asrt( $page->rating, NULL );
|
||||
$page->rating = '1';
|
||||
$newid = $redbean->store( $page );
|
||||
asrt( $newid, $id );
|
||||
$page = $redbean->load( "page", $id );
|
||||
asrt( $page->name, "new name" );
|
||||
asrt( $page->rating, "1" );
|
||||
$page->rating = "0";
|
||||
$newid = $redbean->store( $page );
|
||||
asrt( $page->rating, "0" );
|
||||
$page->rating = 0;
|
||||
$newid = $redbean->store( $page );
|
||||
asrt( $page->rating, 0 );
|
||||
$page->rating = "0";
|
||||
$newid = $redbean->store( $page );
|
||||
asrt( $newid, $id );
|
||||
$page = $redbean->load( "page", $id );
|
||||
asrt( $page->name, "new name" );
|
||||
asrt( !$page->rating, TRUE );
|
||||
asrt( ( $page->rating == 0 ), TRUE );
|
||||
asrt( ( $page->rating == FALSE ), TRUE );
|
||||
$page->rating = 5;
|
||||
$newid = $redbean->store( $page );
|
||||
asrt( $newid, $id );
|
||||
$page = $redbean->load( "page", $id );
|
||||
asrt( $page->name, "new name" );
|
||||
asrt( strval( $page->rating ), "5" );
|
||||
$page->rating = 300;
|
||||
$newid = $redbean->store( $page );
|
||||
asrt( $newid, $id );
|
||||
$page = $redbean->load( "page", $id );
|
||||
asrt( $page->name, "new name" );
|
||||
asrt( strval( $page->rating ), "300" );
|
||||
$page->rating = -2;
|
||||
$newid = $redbean->store( $page );
|
||||
asrt( $newid, $id );
|
||||
$page = $redbean->load( "page", $id );
|
||||
asrt( $page->name, "new name" );
|
||||
asrt( strval( $page->rating ), "-2" );
|
||||
$page->rating = 2.5;
|
||||
$newid = $redbean->store( $page );
|
||||
asrt( $newid, $id );
|
||||
$page = $redbean->load( "page", $id );
|
||||
asrt( $page->name, "new name" );
|
||||
asrt( ( $page->rating == 2.5 ), TRUE );
|
||||
$page->rating = -3.3;
|
||||
$newid = $redbean->store( $page );
|
||||
asrt( $newid, $id );
|
||||
$page = $redbean->load( "page", $id );
|
||||
asrt( $page->name, "new name" );
|
||||
asrt( ( $page->rating == -3.3 ), TRUE );
|
||||
$page->rating = "good";
|
||||
$newid = $redbean->store( $page );
|
||||
asrt( $newid, $id );
|
||||
$page = $redbean->load( "page", $id );
|
||||
asrt( $page->name, "new name" );
|
||||
asrt( $page->rating, "good" );
|
||||
$longtext = str_repeat( 'great! because..', 100 );
|
||||
$page->rating = $longtext;
|
||||
$newid = $redbean->store( $page );
|
||||
asrt( $newid, $id );
|
||||
$page = $redbean->load( "page", $id );
|
||||
asrt( $page->name, "new name" );
|
||||
asrt( $page->rating, $longtext );
|
||||
// Test leading zeros
|
||||
$numAsString = "0001";
|
||||
$page->numasstring = $numAsString;
|
||||
$redbean->store( $page );
|
||||
$page = $redbean->load( "page", $id );
|
||||
asrt( $page->numasstring, "0001" );
|
||||
$page->numnotstring = "0.123";
|
||||
$redbean->store( $page );
|
||||
$page = $redbean->load( "page", $id );
|
||||
asrt( $page->numnotstring == 0.123, TRUE );
|
||||
$page->numasstring2 = "00.123";
|
||||
$redbean->store( $page );
|
||||
$page = $redbean->load( "page", $id );
|
||||
asrt( $page->numasstring2, "00.123" );
|
||||
try {
|
||||
$redbean->trash( array() );
|
||||
fail();
|
||||
} catch ( RedException $e ) {
|
||||
pass();
|
||||
}
|
||||
$redbean->trash( $page );
|
||||
asrt( (int) $pdo->GetCell( "SELECT count(*) FROM page" ), 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether empty strings are preserved as such.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testEmptyStringShouldNotBeStoredAsInteger()
|
||||
{
|
||||
R::nuke();
|
||||
$bean = R::dispense('bean');
|
||||
$bean->str = '';
|
||||
R::store($bean);
|
||||
$bean = $bean->fresh();
|
||||
asrt( ( $bean->str === '' ), TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test handling of infinity values.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testStoringInf()
|
||||
{
|
||||
R::nuke();
|
||||
$bean = R::dispense( 'bean' );
|
||||
$bean->inf = INF;
|
||||
R::store( $bean );
|
||||
$bean = $bean->fresh();
|
||||
asrt( ( $bean->inf === 'INF' ), TRUE );
|
||||
asrt( ( $bean->inf == 'INF' ), TRUE );
|
||||
$bean->modifyme = 'yes';
|
||||
R::store( $bean );
|
||||
$bean = $bean->fresh();
|
||||
asrt( ( $bean->inf === 'INF' ), TRUE );
|
||||
asrt( ( $bean->inf == 'INF' ), TRUE );
|
||||
$bean->modifyme = 'yes';
|
||||
}
|
||||
}
|
||||
|
||||
58
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Utf8.php
vendored
Normal file
58
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Utf8.php
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
|
||||
/**
|
||||
* Utf8
|
||||
*
|
||||
* Tests whether we can store and retrive unicode characters.
|
||||
*
|
||||
* @file RedUNIT/Base/UTF8.php
|
||||
* @desc Tests handling of NULL values.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Utf8 extends Base
|
||||
{
|
||||
/**
|
||||
* Tests whether we can process malformed strings in beans.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMalformed()
|
||||
{
|
||||
$byte = pack( 'I', 129 );
|
||||
$bean = R::dispense( 'bean' );
|
||||
$bean->byte = $byte;
|
||||
OODBBean::setEnforceUTF8encoding( TRUE );
|
||||
$str = strval( $bean );
|
||||
OODBBean::setEnforceUTF8encoding( FALSE );
|
||||
pass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test UTF8 handling.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testUTF8()
|
||||
{
|
||||
//skip if < 5.3
|
||||
if (version_compare(PHP_VERSION, '5.4', '<')) return pass();
|
||||
$str = '𠜎ὃ𠻗𠻹𠻺𠼭𠼮𠽌𠾴𠾼𠿪𡁜';
|
||||
$bean = R::dispense( 'bean' );
|
||||
$bean->bla = $str;
|
||||
R::store( $bean );
|
||||
$bean = R::load( 'bean', $bean->id );
|
||||
asrt( $bean->bla, $str );
|
||||
pass();
|
||||
}
|
||||
}
|
||||
330
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Via.php
vendored
Normal file
330
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Via.php
vendored
Normal file
@@ -0,0 +1,330 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\ToolBox as ToolBox;
|
||||
use RedBeanPHP\AssociationManager as AssociationManager;
|
||||
use RedBeanPHP\RedException\SQL as SQL;
|
||||
use RedBeanPHP\QueryWriter\AQueryWriter as AQueryWriter;
|
||||
|
||||
/**
|
||||
* Via
|
||||
*
|
||||
* Tests the via() function to hop over an N-M table to
|
||||
* obtain a indirectly related bean, i.e. given person, participant
|
||||
* and project you should be able to obtain a the project associated
|
||||
* with a certain person via() the participant entity.
|
||||
*
|
||||
* @file RedUNIT/Base/Via.php
|
||||
* @desc Via tests
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Via extends Base
|
||||
{
|
||||
/**
|
||||
* Tests fix for issue #378.
|
||||
* Via property does not get cleared properly.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIssue378()
|
||||
{
|
||||
R::nuke();
|
||||
$mediaBean = R::dispense('media');
|
||||
$fooPerson = R::dispense('person');
|
||||
$mediaBean->sharedPersonList[] = $fooPerson;
|
||||
R::store($mediaBean);
|
||||
asrt( count( $mediaBean->sharedPersonList ), 1 );
|
||||
$person = R::findOne('person');
|
||||
$person->via('relation')->sharedMarriageList[] = R::dispense('marriage');
|
||||
//this second one caused the via property to not get cleared
|
||||
$person->via('relation')->sharedMarriageList;
|
||||
asrt( count( $person->sharedMediaList ), 1 );
|
||||
//also found this scenario, non-existing property
|
||||
$book = R::dispense('book');
|
||||
$book->sharedPage[] = R::dispense('page');
|
||||
R::store($book);
|
||||
$book = $book->fresh();
|
||||
$book->via('garbage')->nothing;
|
||||
asrt( count( $book->sharedPageList ), 1 );
|
||||
//yet another
|
||||
$book = R::dispense('magazine');
|
||||
$book->ownAdList[] = R::dispense('ad');
|
||||
$book->sharedPage[] = R::dispense('page');
|
||||
R::store($book);
|
||||
$book = $book->fresh();
|
||||
$book->via('garbage')->ownAdList;
|
||||
asrt( count( $book->sharedPageList ), 1 );
|
||||
$book = R::dispense('folder');
|
||||
$book->sharedPage[] = R::dispense('page');
|
||||
R::store($book);
|
||||
$book = $book->fresh();
|
||||
$book->via('garbage')->sharedItemList[] = R::dispense('item');
|
||||
asrt( count( $book->sharedPageList ), 1 );
|
||||
$book = R::dispense('folder2');
|
||||
$book->sharedPage[] = R::dispense('page');
|
||||
R::store($book);
|
||||
$book = $book->fresh();
|
||||
$book->via('garbage')->sharedItemList[] = R::dispense('item');
|
||||
$book->via('garbage')->sharedItemList[] = R::dispense('item');
|
||||
asrt( count( $book->sharedPageList ), 1 );
|
||||
$book = R::dispense('folder3');
|
||||
$book->sharedPage[] = R::dispense('page');
|
||||
R::store($book);
|
||||
$book = $book->fresh();
|
||||
$book->via('garbage')->item = R::dispense('item');
|
||||
asrt( count( $book->sharedPageList ), 1 );
|
||||
$book = R::dispense('folder3');
|
||||
$book->sharedPage[] = R::dispense('page');
|
||||
R::store($book);
|
||||
$book = $book->fresh();
|
||||
$book->via('garbage')->item = 'test';
|
||||
asrt( count( $book->sharedPageList ), 1 );
|
||||
//yet another
|
||||
$book = R::dispense('leaflet');
|
||||
$book->title = 'leaflet';
|
||||
$book->sharedPage[] = R::dispense('page');
|
||||
R::store($book);
|
||||
$book = $book->fresh();
|
||||
$book->via('garbage')->title;
|
||||
asrt( count( $book->sharedPageList ), 1 );
|
||||
//yet another
|
||||
$book = R::dispense('paper');
|
||||
$book->author = R::dispense('author');
|
||||
$book->sharedPage[] = R::dispense('page');
|
||||
R::store($book);
|
||||
$book = $book->fresh();
|
||||
$book->via('garbage')->author;
|
||||
asrt( count( $book->sharedPageList ), 1 );
|
||||
$book = R::dispense('paper2');
|
||||
$book->sharedPage[] = R::dispense('page');
|
||||
R::store($book);
|
||||
$book = $book->fresh();
|
||||
$book->via('garbage')->author;
|
||||
asrt( count( $book->sharedPageList ), 1 );
|
||||
//yet another one
|
||||
$book = R::dispense('archive');
|
||||
$book->sharedItem[] = R::dispense('item');
|
||||
$book->sharedPage[] = R::dispense('page');
|
||||
R::store($book);
|
||||
$book = $book->fresh();
|
||||
unset( $book->via('garbage')->sharedItem );
|
||||
asrt( count( $book->sharedPageList ), 1 );
|
||||
//theoretic cases
|
||||
$book = R::dispense('guide');
|
||||
$book->sharedItem[] = R::dispense('item');
|
||||
$book->sharedPage[] = R::dispense('page');
|
||||
R::store($book);
|
||||
$book = $book->fresh();
|
||||
$book->via('relation')->countShared('item');
|
||||
$book->via('relation')->countShared('item');
|
||||
asrt( count( $book->sharedPageList ), 1 );
|
||||
$book = R::dispense('catalogue');
|
||||
$book->sharedPage[] = R::dispense('page');
|
||||
R::store($book);
|
||||
$book = $book->fresh();
|
||||
$book->via('relation')->countShared('item');
|
||||
$book->via('relation')->countShared('item');
|
||||
asrt( count( $book->sharedPageList ), 1 );
|
||||
$book = R::dispense('tabloid');
|
||||
$book->ownItemList[] = R::dispense('item');
|
||||
$book->sharedPage[] = R::dispense('page');
|
||||
R::store($book);
|
||||
$book = $book->fresh();
|
||||
$book->via('relation')->countOwn('item');
|
||||
$book->via('relation')->countOwn('item');
|
||||
asrt( count( $book->sharedPageList ), 1 );
|
||||
$book = R::dispense('booklet');
|
||||
$book->ownItemList[] = R::dispense('item');
|
||||
$book->sharedPage[] = R::dispense('page');
|
||||
R::store($book);
|
||||
$book = $book->fresh();
|
||||
$book->via('relation')->countOwn('item');
|
||||
$book->via('relation')->countOwn('item');
|
||||
asrt( count( $book->sharedPageList ), 1 );
|
||||
AQueryWriter::clearRenames();
|
||||
}
|
||||
|
||||
/**
|
||||
* Via specific tests.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testViaAndSQL()
|
||||
{
|
||||
R::nuke();
|
||||
list($p1, $p2) = R::dispense('participant', 2);
|
||||
list($e1, $e2) = R::dispense('employee', 2);
|
||||
list($x1, $x2) = R::dispense('project', 2);
|
||||
$e1->name = 'Anna';
|
||||
$e2->name = 'John';
|
||||
$p1->project = $x1;
|
||||
$p1->employee = $e1;
|
||||
$p1->arole = 'designer';
|
||||
$p2->project = $x1;
|
||||
$p2->employee = $e2;
|
||||
$p2->arole = 'coder';
|
||||
R::storeAll(array( $p1, $p2 ));
|
||||
$project = R::load('project', $x1->id);
|
||||
$designers = $project
|
||||
->withCondition(' participant.arole = ? ', array( 'designer' ) )
|
||||
->via( 'participant' )
|
||||
->sharedEmployeeList;
|
||||
$anna = reset( $designers );
|
||||
asrt(count($designers), 1);
|
||||
asrt($anna->name, 'Anna');
|
||||
$coders = $project
|
||||
->withCondition(' participant.arole = ? ', array( 'coder' ) )
|
||||
->via( 'participant' )
|
||||
->sharedEmployeeList;
|
||||
$john = reset( $coders );
|
||||
asrt(count($coders), 1);
|
||||
asrt($john->name, 'John');
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 effect of via on shared list removal of beans.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testViaAndRemove()
|
||||
{
|
||||
R::nuke();
|
||||
$project = R::dispense( 'project' );
|
||||
$employees = R::dispense( 'employee', 2);
|
||||
$project->via( 'partcipant' )->sharedEmployeeList = $employees;
|
||||
R::store( $project );
|
||||
asrt( R::count('employee'), 2 );
|
||||
asrt( R::count('participant'), 2 );
|
||||
$project = $project->fresh();
|
||||
$project->sharedEmployee = array();
|
||||
R::store( $project );
|
||||
asrt( R::count( 'employee' ), 2 );
|
||||
asrt( R::count( 'participant' ), 0 );
|
||||
}
|
||||
}
|
||||
581
vendor/gabordemooij/redbean/testing/RedUNIT/Base/With.php
vendored
Normal file
581
vendor/gabordemooij/redbean/testing/RedUNIT/Base/With.php
vendored
Normal file
@@ -0,0 +1,581 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
|
||||
/**
|
||||
* With
|
||||
*
|
||||
* With/WithCondition can be used to fetch bean lists with additional
|
||||
* requirements, filters or ordering specification using SQL snippets.
|
||||
* This suite tests the handling of with() and withCondition() snippets.
|
||||
* Additionally this test suite also tests noLoad() and all() modifiers.
|
||||
*
|
||||
* @file RedUNIT/Base/With.php
|
||||
* @desc Tests query modification of own-lists with prefix-with
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class With extends Base
|
||||
{
|
||||
|
||||
/**
|
||||
* This test suite uses specific SQL, only suited for MySQL.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTargetDrivers()
|
||||
{
|
||||
return array( 'mysql' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests no-load modifier for lists.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testNoLoad()
|
||||
{
|
||||
$book = R::dispense( array(
|
||||
'_type' => 'book',
|
||||
'title' => 'Book of Lorem Ipsum',
|
||||
'ownPage' => array(
|
||||
array(
|
||||
'_type' => 'page',
|
||||
'content' => 'Lorem Ipsum',
|
||||
)
|
||||
),
|
||||
'sharedTag' => array(
|
||||
array(
|
||||
'_type' => 'tag',
|
||||
'label' => 'testing'
|
||||
)
|
||||
)
|
||||
) );
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
asrt( R::count( 'book' ), 1 );
|
||||
asrt( count( $book->ownPage ), 1 );
|
||||
//now try with no-load
|
||||
$book = $book->fresh();
|
||||
asrt( count( $book->noLoad()->ownPage ), 0 );
|
||||
asrt( count( $book->noLoad()->sharedTag ), 0 );
|
||||
//now try to add with no-load
|
||||
$book = $book->fresh();
|
||||
$book->noLoad()->xownPageList[] = R::dispense( 'page' );
|
||||
$book->noLoad()->sharedTagList[] = R::dispense( 'tag' );
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
asrt( count( $book->ownPage ), 2 );
|
||||
asrt( count( $book->sharedTagList ), 2 );
|
||||
//no-load overrides with and withCondition
|
||||
$book = $book->fresh();
|
||||
asrt( count( $book->with(' invalid sql ')->noLoad()->ownPage ), 0 );
|
||||
asrt( count( $book->withCondition(' invalid sql ')->noLoad()->sharedTag ), 0 );
|
||||
//no-load overrides all and alias
|
||||
$book = $book->fresh();
|
||||
asrt( count( $book->all()->noLoad()->ownPage ), 0 );
|
||||
asrt( count( $book->alias('nothing')->noLoad()->sharedTag ), 0 );
|
||||
//no-load gets cleared
|
||||
$book = $book->fresh();
|
||||
asrt( count( $book->ownPage ), 2 );
|
||||
asrt( count( $book->sharedTagList ), 2 );
|
||||
//We cant clear with no-load accidentally?
|
||||
$book = $book->fresh();
|
||||
$book->noLoad()->ownPage = array();
|
||||
$book->noLoad()->sharedTagList = array();
|
||||
R::store( $book );
|
||||
asrt( count( $book->ownPage ), 2 );
|
||||
asrt( count( $book->sharedTagList ), 2 );
|
||||
//No-load does not have effect if list is already cached
|
||||
$book = $book->fresh();
|
||||
$book->ownPage;
|
||||
$book->sharedTag;
|
||||
asrt( count( $book->ownPage ), 2 );
|
||||
asrt( count( $book->sharedTagList ), 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test all().
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAll()
|
||||
{
|
||||
$book = R::dispense( 'book' );
|
||||
$book->ownPage = R::dispense( 'page', 10 );
|
||||
R::store( $book );
|
||||
asrt( count( $book->with( ' LIMIT 3 ' )->ownPage ), 3 );
|
||||
asrt( count( $book->ownPage ), 3 );
|
||||
asrt( count( $book->all()->ownPage ), 10 );
|
||||
asrt( count( $book->ownPage ), 10 );
|
||||
R::nuke();
|
||||
asrt( count( $book->ownPage ), 10 );
|
||||
asrt( count( $book->all()->ownPage ), 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test embedded SQL snippets using with and withCondition.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testEmbeddedSQL()
|
||||
{
|
||||
list( $page1, $page2, $page3 ) = R::dispense( 'page', 3 );
|
||||
list( $ad1, $ad2, $ad3 ) = R::dispense( 'ad', 3 );
|
||||
$ad2->name = 'shampoo';
|
||||
$page3->name = 'homepage';
|
||||
$page1->sharedAd = array( $ad1, $ad3 );
|
||||
$page2->sharedAd = array( $ad2, $ad3 );
|
||||
$page3->sharedAd = array( $ad3, $ad2, $ad1 );
|
||||
R::storeAll( array( $page1, $page2, $page3 ) );
|
||||
$page1 = R::load( 'page', $page1->id );
|
||||
asrt( 1, count( $page1->with( ' LIMIT 1 ' )->sharedAd ) );
|
||||
$page2 = R::load( 'page', $page2->id );
|
||||
$adsOnPage2 = $page2->withCondition( ' `name` = ? ', array( 'shampoo' ) )->sharedAd;
|
||||
asrt( 1, count( $adsOnPage2 ) );
|
||||
$ad = reset( $adsOnPage2 );
|
||||
asrt( $ad->name, 'shampoo' );
|
||||
$ad = R::load( 'ad', $ad->id );
|
||||
asrt( count( $ad->sharedPage ), 2 );
|
||||
$ad = R::load( 'ad', $ad->id );
|
||||
$homepage = reset( $ad->withCondition( ' `name` LIKE ? AND page.id > 0 ORDER BY id DESC ', array( '%ome%' ) )->sharedPage );
|
||||
asrt( $homepage->name, 'homepage' );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 );
|
||||
$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 when to reload and when to NOT reload beans.
|
||||
* Use UNSET to reload a parent bean. Use UNSET or
|
||||
* a modifier (with, withCondition, all) to reload a list.
|
||||
* Use noLoad() to obtain an empty list - does not reload
|
||||
* but sets an empty array.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testWhenToReload()
|
||||
{
|
||||
$book = R::dispense( 'book' );
|
||||
$book->ownPage = R::dispense( 'page', 3 );
|
||||
$book->author = R::dispense( 'author' );
|
||||
$book->coauthor = R::dispense( 'author' );
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
$firstPage = reset( $book->ownPage );
|
||||
$id = $firstPage->id;
|
||||
$book->ownPage[ $id ]->title = 'a';
|
||||
//Do not reload an own list after manipulations
|
||||
asrt( $book->ownPage[ $id ]->title, 'a' ); //dont reload!
|
||||
$book->ownPage[] = R::dispense( 'page' ); //dont reload!
|
||||
asrt( $book->ownPage[ $id ]->title, 'a' ); //dont reload!
|
||||
asrt( $book->ownPageList[ $id ]->title, 'a' ); //dont reload!
|
||||
asrt( $book->xownPageList[ $id ]->title, 'a' ); //dont reload!
|
||||
asrt( $book->xownPage[ $id ]->title, 'a' ); //dont reload!
|
||||
asrt( count( $book->ownPageList ), 4 );
|
||||
//now trigger reload
|
||||
unset( $book->ownPageList );
|
||||
asrt( count( $book->ownPageList ), 3 );
|
||||
$book->ownPage[] = R::dispense( 'page' );
|
||||
asrt( count( $book->ownPageList ), 4 );
|
||||
//now trigger reload
|
||||
unset( $book->xownPageList );
|
||||
asrt( count( $book->ownPageList ), 3 );
|
||||
$book->ownPage[] = R::dispense( 'page' );
|
||||
asrt( count( $book->ownPageList ), 4 );
|
||||
//now trigger reload
|
||||
unset( $book->xownPage );
|
||||
asrt( count( $book->ownPageList ), 3 );
|
||||
$book->ownPage[] = R::dispense( 'page' );
|
||||
asrt( count( $book->ownPageList ), 4 );
|
||||
//now trigger reload
|
||||
unset( $book->ownPage );
|
||||
asrt( count( $book->ownPageList ), 3 );
|
||||
$book->ownPage[] = R::dispense( 'page' );
|
||||
asrt( count( $book->ownPageList ), 4 );
|
||||
//now trigger reload
|
||||
$book->all()->ownPage;
|
||||
asrt( count( $book->ownPageList ), 3 );
|
||||
$book->ownPage[] = R::dispense( 'page' );
|
||||
asrt( count( $book->ownPageList ), 4 );
|
||||
//now trigger reload
|
||||
$book->all()->xownPage;
|
||||
asrt( count( $book->ownPageList ), 3 );
|
||||
$book->ownPage[] = R::dispense( 'page' );
|
||||
asrt( count( $book->ownPageList ), 4 );
|
||||
//now trigger reload
|
||||
$book->all()->ownPageList;
|
||||
asrt( count( $book->ownPageList ), 3 );
|
||||
$book->ownPage[] = R::dispense( 'page' );
|
||||
asrt( count( $book->ownPageList ), 4 );
|
||||
//now trigger reload
|
||||
$book->all()->xownPageList;
|
||||
asrt( count( $book->ownPageList ), 3 );
|
||||
$book->ownPage[] = R::dispense( 'page' );
|
||||
asrt( count( $book->ownPageList ), 4 );
|
||||
//Do not reload an own list if told to not reload using noLoad()
|
||||
$book->noLoad()->with(' LIMIT 1 ')->ownPage; //dont reload!
|
||||
asrt( count( $book->xownPage ), 0); //dont reload!
|
||||
$book->noLoad()->all()->ownPage; //dont reload!
|
||||
asrt( count( $book->xownPage ), 0); //dont reload!
|
||||
$book->noLoad()->alias('magazine')->ownPage; //dont reload!
|
||||
asrt( count( $book->xownPage ), 0); //dont reload!
|
||||
$book->noLoad()->withCondition('')->ownPage; //dont reload!
|
||||
asrt( count( $book->xownPage ), 0); //dont reload!
|
||||
//even if modifiers proceed noLoad()
|
||||
$book->with(' LIMIT 1 ')->noLoad()->ownPage; //dont reload!
|
||||
asrt( count( $book->xownPage ), 0); //dont reload!
|
||||
$book->all()->noLoad()->ownPage; //dont reload!
|
||||
asrt( count( $book->xownPage ), 0); //dont reload!
|
||||
$book->alias('magazine')->noLoad()->ownPage; //dont reload!
|
||||
asrt( count( $book->xownPage ), 0); //dont reload!
|
||||
$book->withCondition('')->noLoad()->ownPage; //dont reload!
|
||||
asrt( count( $book->xownPage ), 0); //dont reload!
|
||||
//even in combinations
|
||||
$book->all()->with(' LIMIT 1 ')->noLoad()->ownPage; //dont reload!
|
||||
asrt( count( $book->xownPage ), 0); //dont reload!
|
||||
$book->alias('magazine')->all()->noLoad()->ownPage; //dont reload!
|
||||
asrt( count( $book->xownPage ), 0); //dont reload!
|
||||
$book->alias('magazine')->with('LIMIT 1')->noLoad()->ownPage; //dont reload!
|
||||
asrt( count( $book->xownPage ), 0); //dont reload!
|
||||
$book->alias('magazine')->withCondition('')->noLoad()->ownPage; //dont reload!
|
||||
asrt( count( $book->xownPage ), 0); //dont reload!
|
||||
//now test shared list
|
||||
$book->sharedTag = R::dispense( 'tag', 16 );
|
||||
asrt( count( $book->sharedTag ), 16 );
|
||||
$book->sharedTag[] = R::dispense( 'tag' );
|
||||
asrt( count( $book->sharedTag ), 17 ); //dont reload after adding
|
||||
$last = end( $book->sharedTagList );
|
||||
$id = $last->id;
|
||||
$book->sharedTag[ $id ]->title = 'b';
|
||||
asrt( count( $book->sharedTag ), 17 ); //dont reload after manipulation
|
||||
unset( $book->sharedTagList[ $id ] );
|
||||
asrt( count( $book->sharedTag ), 16 ); //dont reload after manipulation
|
||||
//now trigger reload
|
||||
unset( $book->sharedTagList );
|
||||
asrt( count( $book->sharedTag ), 0 );
|
||||
$book->sharedTag = R::dispense( 'tag', 16 );
|
||||
asrt( count( $book->sharedTag ), 16 );
|
||||
//now trigger reload
|
||||
unset( $book->sharedTag );
|
||||
asrt( count( $book->sharedTag ), 0 );
|
||||
$book->sharedTag = R::dispense( 'tag', 16 );
|
||||
asrt( count( $book->sharedTag ), 16 );
|
||||
//now trigger reload
|
||||
$book->all()->sharedTag;
|
||||
asrt( count( $book->sharedTag ), 0 );
|
||||
$book->sharedTag = R::dispense( 'tag', 16 );
|
||||
asrt( count( $book->sharedTag ), 16 );
|
||||
//now trigger reload
|
||||
$book->all()->sharedTagList;
|
||||
asrt( count( $book->sharedTag ), 0 );
|
||||
$book->sharedTag = R::dispense( 'tag', 16 );
|
||||
asrt( count( $book->sharedTag ), 16 );
|
||||
//Do not reload a sharedTag list if told to not reload using noLoad()
|
||||
$book->noLoad()->with(' LIMIT 1 ')->sharedTag; //dont reload!
|
||||
asrt( count( $book->sharedTag ), 0); //dont reload!
|
||||
$book->noLoad()->all()->sharedTag; //dont reload!
|
||||
asrt( count( $book->sharedTag ), 0); //dont reload!
|
||||
$book->noLoad()->alias('magazine')->sharedTag; //dont reload!
|
||||
asrt( count( $book->sharedTag ), 0); //dont reload!
|
||||
$book->noLoad()->withCondition('')->sharedTag; //dont reload!
|
||||
asrt( count( $book->sharedTag ), 0); //dont reload!
|
||||
//even if modifiers proceed noLoad()
|
||||
$book->with(' LIMIT 1 ')->noLoad()->sharedTag; //dont reload!
|
||||
asrt( count( $book->sharedTag ), 0); //dont reload!
|
||||
$book->all()->noLoad()->sharedTag; //dont reload!
|
||||
asrt( count( $book->sharedTag ), 0); //dont reload!
|
||||
$book->alias('magazine')->noLoad()->sharedTag; //dont reload!
|
||||
asrt( count( $book->sharedTag ), 0); //dont reload!
|
||||
$book->withCondition('')->noLoad()->ownPage; //dont reload!
|
||||
asrt( count( $book->sharedTag ), 0); //dont reload!
|
||||
//even in combinations
|
||||
$book->all()->with(' LIMIT 1 ')->noLoad()->sharedTag; //dont reload!
|
||||
asrt( count( $book->sharedTag ), 0); //dont reload!
|
||||
$book->alias('magazine')->all()->noLoad()->sharedTag; //dont reload!
|
||||
asrt( count( $book->sharedTag ), 0); //dont reload!
|
||||
$book->alias('magazine')->with('LIMIT 1')->noLoad()->sharedTag; //dont reload!
|
||||
asrt( count( $book->sharedTag ), 0); //dont reload!
|
||||
$book->alias('magazine')->withCondition('')->noLoad()->sharedTag; //dont reload!
|
||||
asrt( count( $book->sharedTag ), 0); //dont reload!
|
||||
//test do not reload parent bean
|
||||
$book->author->name = 'me';
|
||||
asrt( $book->author->name, 'me' );
|
||||
$book->fetchAs('author')->coauthor;
|
||||
asrt( $book->author->name, 'me' );
|
||||
$book->fetchAs('author')->author;
|
||||
asrt( $book->author->name, 'me' );
|
||||
$book->with(' LIMIT 1 ')->author;
|
||||
asrt( $book->author->name, 'me' );
|
||||
$book->withCondition('')->author;
|
||||
asrt( $book->author->name, 'me' );
|
||||
$book->all()->author;
|
||||
asrt( $book->author->name, 'me' );
|
||||
$book->noLoad()->author;
|
||||
asrt( $book->author->name, 'me' );
|
||||
$book->noLoad()->all()->author;
|
||||
asrt( $book->author->name, 'me' );
|
||||
$book->with('LIMIT 1')->noLoad()->all()->author;
|
||||
asrt( $book->author->name, 'me' );
|
||||
//now trigger reload
|
||||
unset( $book->author );
|
||||
asrt( $book->author->name, NULL );
|
||||
$book->author->name = 'me';
|
||||
asrt( $book->author->name, 'me' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether modifiers are cleared after reading or
|
||||
* writing a bean property.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testClearanceOfModFlags()
|
||||
{
|
||||
//test base condition, retrieving list or parent should not set flags
|
||||
$book = R::dispense( 'book' );
|
||||
asrt( $book->getModFlags(), '' );
|
||||
$book->ownPage = R::dispense( 'page', 2 );
|
||||
asrt( $book->getModFlags(), '' );
|
||||
$book->xownPage = R::dispense( 'page', 2 );
|
||||
asrt( $book->getModFlags(), '' );
|
||||
$book->ownPageList = R::dispense( 'page', 2 );
|
||||
asrt( $book->getModFlags(), '' );
|
||||
$book->xownPageList = R::dispense( 'page', 2 );
|
||||
asrt( $book->getModFlags(), '' );
|
||||
$book->ownPage[] = R::dispense( 'page', 1 );
|
||||
asrt( $book->getModFlags(), '' );
|
||||
$book->xownPage[] = R::dispense( 'page', 1 );
|
||||
asrt( $book->getModFlags(), '' );
|
||||
$book->ownPageList[] = R::dispense( 'page', 1 );
|
||||
asrt( $book->getModFlags(), '' );
|
||||
$book->xownPageList[] = R::dispense( 'page', 1 );
|
||||
asrt( $book->getModFlags(), '' );
|
||||
$book->sharedPage = R::dispense( 'page', 2 );
|
||||
asrt( $book->getModFlags(), '' );
|
||||
$book->sharedPageList = R::dispense( 'page', 2 );
|
||||
asrt( $book->getModFlags(), '' );
|
||||
$book->sharedPage[] = R::dispense( 'page', 1 );
|
||||
asrt( $book->getModFlags(), '' );
|
||||
$book->sharedPageList[] = R::dispense( 'page', 1 );
|
||||
asrt( $book->getModFlags(), '' );
|
||||
$book->author = R::dispense( 'author' );
|
||||
asrt( $book->getModFlags(), '' );
|
||||
$book->title = 'title';
|
||||
//Test whether appropriate flags are set and whether they are cleared after
|
||||
//accessing a property.
|
||||
$modifiers = array('with'=>'w', 'withCondition'=>'w', 'alias'=>'a', 'fetchAs'=>'f', 'all'=>'r', 'noLoad'=>'n');
|
||||
$properties = array('ownPage', 'ownPageList', 'xownPage', 'xownPageList', 'sharedPage', 'sharedPageList', 'author', 'title');
|
||||
foreach( $modifiers as $modifier => $flag ) {
|
||||
foreach( $properties as $property ) {
|
||||
$book = R::dispense( 'book' );
|
||||
$book->$modifier('something');
|
||||
$flags = $book->getModFlags();
|
||||
$expect = $flag;
|
||||
asrt( $flags, $expect );
|
||||
$book->$property;
|
||||
$flags = $book->getModFlags();
|
||||
asrt( $flags, '' );
|
||||
}
|
||||
}
|
||||
//now test combinations and also test whether we can
|
||||
//clear modifiers manually using the clearModifiers() method.
|
||||
foreach( $modifiers as $modifier => $flag ) {
|
||||
foreach( $modifiers as $modifier2 => $flag2 ) {
|
||||
foreach( $properties as $property ) {
|
||||
$book = R::dispense( 'book' );
|
||||
$book->$modifier( 'something' )->$modifier2( 'something' );
|
||||
$flags = $book->getModFlags();
|
||||
$expect = array($flag, $flag2);
|
||||
$expect = array_unique( $expect );
|
||||
sort( $expect );
|
||||
$expect = implode( '', $expect );
|
||||
asrt( $flags, $expect );
|
||||
$book->$modifier( 'something' )->$modifier2( 'something' )->clearModifiers();
|
||||
$flags = $book->getModFlags();
|
||||
asrt( $flags, '' );
|
||||
$book->$modifier( 'something' )->$modifier2( 'something' )->clearModifiers();
|
||||
$book->$property;
|
||||
$flags = $book->getModFlags();
|
||||
asrt( $flags, '' );
|
||||
}
|
||||
}
|
||||
}
|
||||
$book = R::dispense( 'book' );
|
||||
$book->ownPage = R::dispense( 'page', 2 );
|
||||
$book->sharedPage = R::dispense( 'page', 2 );
|
||||
R::store( $book );
|
||||
$book = R::dispense( 'book' );
|
||||
$book->alias('magazine')->ownPage = R::dispense( 'page', 2 );
|
||||
R::store( $book );
|
||||
//test modifier with countOwn and countShared methods
|
||||
foreach( $modifiers as $modifier => $flag ) {
|
||||
$book = R::dispense( 'book' );
|
||||
if ($modifier === 'withCondition') $book->$modifier( ' 1 ' );
|
||||
elseif ($modifier === 'with') $book->$modifier( ' LIMIT 1 ' );
|
||||
elseif ($modifier === 'alias') $book->$modifier('magazine');
|
||||
else $book->$modifier('something');
|
||||
$flags = $book->getModFlags();
|
||||
$expect = $flag;
|
||||
asrt( $flags, $expect );
|
||||
$book->countOwn('page');
|
||||
$flags = $book->getModFlags();
|
||||
asrt( $flags, '' );
|
||||
if ($modifier === 'withCondition') $book->$modifier( ' 1 ' );
|
||||
elseif ($modifier === 'with') $book->$modifier( ' LIMIT 1 ' );
|
||||
elseif ($modifier === 'alias') $book->$modifier('magazine');
|
||||
else $book->$modifier('something');
|
||||
$flags = $book->getModFlags();
|
||||
$expect = $flag;
|
||||
asrt( $flags, $expect );
|
||||
$book->countShared('page');
|
||||
$flags = $book->getModFlags();
|
||||
asrt( $flags, '' );
|
||||
if ($modifier === 'withCondition') $book->$modifier( ' 1 ' );
|
||||
elseif ($modifier === 'with') $book->$modifier( ' LIMIT 1 ' );
|
||||
elseif ($modifier === 'alias') $book->$modifier('magazine');
|
||||
else $book->$modifier('something');
|
||||
$flags = $book->getModFlags();
|
||||
$expect = $flag;
|
||||
asrt( $flags, $expect );
|
||||
unset( $book->author );
|
||||
$flags = $book->getModFlags();
|
||||
asrt( $flags, '' );
|
||||
}
|
||||
}
|
||||
}
|
||||
427
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Writecache.php
vendored
Normal file
427
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Writecache.php
vendored
Normal file
@@ -0,0 +1,427 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
|
||||
/**
|
||||
* Writecache
|
||||
*
|
||||
* The Query Writer Cache tries to avoid unnecessary queries
|
||||
* by using cache markers. This means repeatingly fetching the
|
||||
* same parent bean for instance (in loop) won't hurt performance.
|
||||
* The Query Writer Cache gets emptied if the chain of markers
|
||||
* gets broken. All 'non destructive' queries are marked, as long
|
||||
* as no other queries have been executed we can safely assume
|
||||
* nothing in the database has changed for the current request.
|
||||
* You might want to turn this form of caching off in long running
|
||||
* PHP processes.
|
||||
*
|
||||
* @file RedUNIT/Base/Writecache.php
|
||||
* @desc Tests the Query Writer cache implemented in the
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Writecache extends Base
|
||||
{
|
||||
|
||||
/**
|
||||
* What drivers should be loaded for this test pack?
|
||||
*/
|
||||
public function getTargetDrivers()
|
||||
{
|
||||
return array( 'mysql', 'pgsql', 'sqlite', 'CUBRID' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Lynesth:
|
||||
* Using flushCache() obviously fixes it.
|
||||
* The example might be a bit stupid but it gets to the point.
|
||||
* Someone might be using a specific query more than once with
|
||||
* getCell (or any other) and thinking the
|
||||
* cache works for those as well, try to make use of it.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCacheFail()
|
||||
{
|
||||
R::nuke();
|
||||
R::freeze( FALSE );
|
||||
$author = R::dispense('author');
|
||||
$author->name = "John";
|
||||
$id = R::store($author);
|
||||
$author = R::load('author', 1); // This gets cached
|
||||
$author = $author->fresh(); // This gets cached
|
||||
$author = R::findOne('author', ' id = ? ', array( 1 )); // This gets cached
|
||||
asrt($author->name, 'John');
|
||||
R::exec('UPDATE author SET name = "Bob" WHERE id = 1');
|
||||
// It's broken because there's no cache check between those two calls
|
||||
//more realistic query: 'SELECT MAX(id) FROM author -- keep-cache');
|
||||
R::getCell('SELECT 123 -- keep-cache');
|
||||
$author = R::load('author', $id);
|
||||
asrt($author->name, 'John');
|
||||
$author = $author->fresh();
|
||||
asrt($author->name, 'John');
|
||||
$author = R::findOne('author', ' id = ? ', array( 1 ));
|
||||
asrt($author->name, 'John');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether cache size remains constant (per type).
|
||||
* Avoiding potential memory leaks. (Issue #424).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCacheSize()
|
||||
{
|
||||
R::nuke();
|
||||
R::useWriterCache( TRUE );
|
||||
$writer = R::getWriter();
|
||||
$bean = R::dispense( 'bean' );
|
||||
$bean->prop = 1;
|
||||
R::store( $bean );
|
||||
$writer->flushCache( 20 );
|
||||
$count = $writer->flushCache();
|
||||
asrt( $count, 0 );
|
||||
R::find( 'bean', ' prop < ? ', array( 1 ) );
|
||||
$count = $writer->flushCache();
|
||||
asrt( $count, 2 );
|
||||
R::find( 'bean', ' prop < ? ', array( 2 ) );
|
||||
$count = $writer->flushCache();
|
||||
asrt( $count, 5 );
|
||||
R::find( 'bean', ' prop < ? ', array( 2 ) );
|
||||
$count = $writer->flushCache();
|
||||
asrt( $count, 5 );
|
||||
for( $i = 0; $i < 40; $i ++ ) {
|
||||
R::find( 'bean', ' prop < ? ', array( $i ) );
|
||||
}
|
||||
$count = $writer->flushCache();
|
||||
asrt( $count, 85 );
|
||||
for( $i = 0; $i < 120; $i ++ ) {
|
||||
R::find( 'bean', ' prop < ? ', array( $i ) );
|
||||
}
|
||||
$count = $writer->flushCache( 1 );
|
||||
asrt( $count, 85 );
|
||||
for( $i = 0; $i < 20; $i ++ ) {
|
||||
R::find( 'bean', ' prop < ? ', array( $i ) );
|
||||
}
|
||||
$count = $writer->flushCache( 20 );
|
||||
asrt( $count, 9 );
|
||||
}
|
||||
|
||||
/**
|
||||
* When using fetchAs(), Query Cache does not recognize objects
|
||||
* that have been previously fetched, see issue #400.
|
||||
*/
|
||||
public function testCachingAndFetchAs()
|
||||
{
|
||||
testpack( 'Testing whether you can cache multiple records of the same type' );
|
||||
R::debug( TRUE, 1 );
|
||||
$logger = R::getDatabaseAdapter()->getDatabase()->getLogger();
|
||||
R::nuke();
|
||||
$coauthor1 = R::dispense( 'author' );
|
||||
$coauthor1->name = 'John';
|
||||
$book = R::dispense( 'book' );
|
||||
$book->title = 'a Funny Tale';
|
||||
$book->coauthor = $coauthor1;
|
||||
$id = R::store( $book );
|
||||
$coauthor = R::dispense( 'author' );
|
||||
$coauthor->name = 'Pete';
|
||||
$book = R::dispense( 'book' );
|
||||
$book->title = 'a Funny Tale 2';
|
||||
$book->coauthor = $coauthor;
|
||||
$id = R::store( $book );
|
||||
$book = R::dispense( 'book' );
|
||||
$book->title = 'a Funny Tale 3';
|
||||
$book->coauthor = $coauthor1;
|
||||
$id = R::store( $book );
|
||||
$books = R::find( 'book' );
|
||||
$logger->clear();
|
||||
$authors = array();
|
||||
$authorsByName = array();
|
||||
foreach($books as $book) {
|
||||
$coAuthor = $book->with( ' ORDER BY title ASC ' )
|
||||
->fetchAs( 'author' )->coauthor;
|
||||
$authors[] = $coAuthor->name;
|
||||
$authorsByName[ $coAuthor->name ] = $coAuthor;
|
||||
}
|
||||
asrt( count( $logger->grep( 'SELECT' ) ), 2 ); //must be 2! 3 if cache does not work!
|
||||
asrt( count( $authors ), 3 );
|
||||
asrt( isset( $authorsByName[ 'John' ] ), TRUE );
|
||||
asrt( isset( $authorsByName[ 'Pete' ] ), TRUE );
|
||||
$logger->clear();
|
||||
$authors = array();
|
||||
$authorsByName = array();
|
||||
foreach($books as $book) {
|
||||
$coAuthor = $book->with( ' ORDER BY title DESC ' )
|
||||
->fetchAs( 'author' )->coauthor;
|
||||
$authors[] = $coAuthor->name;
|
||||
$authorsByName[ $coAuthor->name ] = $coAuthor;
|
||||
}
|
||||
asrt( count( $logger->grep( 'SELECT' ) ), 0 ); //must be 0!
|
||||
asrt( count( $authors ), 3 );
|
||||
asrt( isset( $authorsByName[ 'John' ] ), TRUE );
|
||||
asrt( isset( $authorsByName[ 'Pete' ] ), TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test effects of cache.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCachingEffects()
|
||||
{
|
||||
testpack( 'Testing WriteCache Query Writer Cache' );
|
||||
R::setNarrowFieldMode( FALSE );
|
||||
R::useWriterCache( FALSE );
|
||||
R::debug( TRUE, 1 );
|
||||
$logger = R::getDatabaseAdapter()->getDatabase()->getLogger();
|
||||
$book = R::dispense( 'book' )->setAttr( 'title', 'ABC' );
|
||||
$book->ownPage[] = R::dispense( 'page' );
|
||||
$id = R::store( $book );
|
||||
// Test load cache -- without
|
||||
$logger->clear();
|
||||
$book = R::load( 'book', $id );
|
||||
$book = R::load( 'book', $id );
|
||||
asrt( count( $logger->grep( 'SELECT' ) ), 2 );
|
||||
// With cache
|
||||
R::useWriterCache( TRUE );
|
||||
$logger->clear();
|
||||
$book = R::load( 'book', $id );
|
||||
$book = R::load( 'book', $id );
|
||||
asrt( count( $logger->grep( 'SELECT' ) ), 1 );
|
||||
R::useWriterCache( FALSE );
|
||||
// Test find cache
|
||||
$logger->clear();
|
||||
$book = R::find( 'book' );
|
||||
$book = R::find( 'book' );
|
||||
asrt( count( $logger->grep( 'SELECT' ) ), 2 );
|
||||
// With cache
|
||||
R::getWriter()->setUseCache( TRUE );
|
||||
$logger->clear();
|
||||
$book = R::find( 'book' );
|
||||
$book = R::find( 'book' );
|
||||
asrt( count( $logger->grep( 'SELECT' ) ), 1 );
|
||||
R::getWriter()->setUseCache( FALSE );
|
||||
// Test combinations
|
||||
$logger->clear();
|
||||
$book = R::findOne( 'book', ' id = ? ', array( $id ) );
|
||||
$book->ownPage;
|
||||
R::batch( 'book', array( $id ) );
|
||||
$book = R::findOne( 'book', ' id = ? ', array( $id ) );
|
||||
$book->ownPage;
|
||||
R::batch( 'book', array( $id ) );
|
||||
asrt( count( $logger->grep( 'SELECT' ) ), 6 );
|
||||
// With cache
|
||||
R::getWriter()->setUseCache( TRUE );
|
||||
$logger->clear();
|
||||
R::batch( 'book', array( $id ) );
|
||||
$book = R::findOne( 'book', ' id = ? ', array( $id ) );
|
||||
$book->ownPage;
|
||||
$book = R::findOne( 'book', ' id = ? ', array( $id ) );
|
||||
$book->ownPage;
|
||||
asrt( count( $logger->grep( 'SELECT' ) ), 3 );
|
||||
R::getWriter()->setUseCache( FALSE );
|
||||
// Test auto flush
|
||||
$logger->clear();
|
||||
$book = R::findOne( 'book' );
|
||||
$book->name = 'X';
|
||||
R::store( $book );
|
||||
$book = R::findOne( 'book' );
|
||||
asrt( count( $logger->grep( 'SELECT *' ) ), 2 );
|
||||
// With cache
|
||||
R::getWriter()->setUseCache( TRUE );
|
||||
$logger->clear();
|
||||
$book = R::findOne( 'book' );
|
||||
$book->name = 'Y';
|
||||
// Will flush
|
||||
R::store( $book );
|
||||
$book = R::findOne( 'book' );
|
||||
// Now the same, auto flushed
|
||||
asrt( count( $logger->grep( 'SELECT *' ) ), 2 );
|
||||
R::getWriter()->setUseCache( FALSE );
|
||||
// Test whether delete flushes as well (because uses selectRecord - might be a gotcha!)
|
||||
R::store( R::dispense( 'garbage' ) );
|
||||
$garbage = R::findOne( 'garbage' );
|
||||
$logger->clear();
|
||||
$book = R::findOne( 'book' );
|
||||
R::trash( $garbage );
|
||||
$book = R::findOne( 'book' );
|
||||
asrt( count( $logger->grep( 'SELECT *' ) ), 2 );
|
||||
R::store( R::dispense( 'garbage' ) );
|
||||
$garbage = R::findOne( 'garbage' );
|
||||
// With cache
|
||||
R::getWriter()->setUseCache( TRUE );
|
||||
$logger->clear();
|
||||
$book = R::findOne( 'book' );
|
||||
R::trash( $garbage );
|
||||
$book = R::findOne( 'book' );
|
||||
// Now the same, auto flushed
|
||||
asrt( count( $logger->grep( 'SELECT *' ) ), 2 );
|
||||
R::getWriter()->setUseCache( FALSE );
|
||||
R::store( R::dispense( 'garbage' ) );
|
||||
$garbage = R::findOne( 'garbage' );
|
||||
// With cache
|
||||
R::getWriter()->setUseCache( TRUE );
|
||||
$logger->clear();
|
||||
$book = R::findOne( 'book' );
|
||||
R::getWriter()->queryRecord( 'garbage', array( 'id' => array( $garbage->id ) ) );
|
||||
$book = R::findOne( 'book' );
|
||||
// Now the same, auto flushed
|
||||
asrt( count( $logger->grep( 'SELECT *' ) ), 2 );
|
||||
$page = R::dispense('page');
|
||||
$book->sharedPage[] = $page;
|
||||
R::store( $book );
|
||||
$logger->clear();
|
||||
$link = R::getWriter()->queryRecordLink( 'book', 'page', $book->id, $page->id );
|
||||
asrt( count( $logger->grep( 'SELECT' ) ), 1 );
|
||||
$link = R::getWriter()->queryRecordLink( 'book', 'page', $book->id, $page->id );
|
||||
asrt( count( $logger->grep( 'SELECT' ) ), 1 );
|
||||
R::getWriter()->setUseCache( FALSE );
|
||||
$link = R::getWriter()->queryRecordLink( 'book', 'page', $book->id, $page->id );
|
||||
asrt( count( $logger->grep( 'SELECT' ) ), 2 );
|
||||
R::getWriter()->setUseCache( TRUE );
|
||||
R::setNarrowFieldMode( TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to fool the cache :)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testRegressions()
|
||||
{
|
||||
testpack( 'Testing possible regressions: Try to fool the cache' );
|
||||
$str = 'SELECT * FROM ' . R::getWriter()->esc( 'bean', TRUE ) . ' WHERE ( ' . R::getWriter()->esc( 'id', TRUE ) . ' IN ( 1) ) ';
|
||||
$bean = R::dispense( 'bean' );
|
||||
$bean->title = 'abc';
|
||||
$id = R::store( $bean );
|
||||
$bean = R::load( 'bean', $id );
|
||||
$bean->title = 'xxx';
|
||||
R::store( $bean );
|
||||
// Fire exact same query so cache may think no other query has been fired
|
||||
R::exec( $str );
|
||||
$bean = R::load( 'bean', $id );
|
||||
asrt( $bean->title, 'xxx' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test keep-cache comment.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testKeepCacheCommentInSQL()
|
||||
{
|
||||
$bean = R::dispense( 'bean' );
|
||||
$bean->title = 'abc';
|
||||
$id = R::store( $bean );
|
||||
$bean = R::load( 'bean', $id );
|
||||
$bean->title = 'xxx';
|
||||
R::store( $bean );
|
||||
// Causes flush even though it contains -- keep-cache (not at the end, not intended)
|
||||
R::findOne( 'bean', ' title = ? ', array( '-- keep-cache' ) );
|
||||
$bean = R::load( 'bean', $id );
|
||||
asrt( $bean->title, 'xxx' );
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Same as above.. test keep cache.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testInstructNoDrop()
|
||||
{
|
||||
$str = 'SELECT * FROM ' . R::getWriter()->esc( 'bean', TRUE ) . ' -- keep-cache';
|
||||
$bean = R::dispense( 'bean' );
|
||||
$bean->title = 'abc';
|
||||
$id = R::store( $bean );
|
||||
$bean = R::load( 'bean', $id );
|
||||
$bean->title = 'xxx';
|
||||
R::store( $bean );
|
||||
R::exec( $str );
|
||||
$bean = R::load( 'bean', $id );
|
||||
asrt( $bean->title, 'abc' );
|
||||
R::nuke();
|
||||
// Now INSTRUCT the cache to not drop the cache CASE 2
|
||||
$str = 'SELECT * FROM ' . R::getWriter()->esc( 'bean', TRUE ) . ' -- keep-cache';
|
||||
$bean = R::dispense( 'bean' );
|
||||
$bean->title = 'abc';
|
||||
$id = R::store( $bean );
|
||||
$bean = R::load( 'bean', $id );
|
||||
$bean->title = 'xxx';
|
||||
R::store( $bean );
|
||||
R::findOne( 'bean', ' title = ? ', array( 'cache' ) );
|
||||
$bean = R::load( 'bean', $id );
|
||||
asrt( $bean->title, 'xxx' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Can we confuse the cache?
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testConfusionRegression()
|
||||
{
|
||||
testpack( 'Testing possible confusion regression' );
|
||||
$bean = R::dispense( 'bean' );
|
||||
$bean->title = 'abc';
|
||||
$id1 = R::store( $bean );
|
||||
$bean = R::dispense( 'bean' );
|
||||
$bean->title = 'abc2';
|
||||
$id2 = R::store( $bean );
|
||||
$bean = R::load( 'bean', $id1 );
|
||||
asrt( $bean->title, 'abc' );
|
||||
$bean = R::load( 'bean', $id2 );
|
||||
asrt( $bean->title, 'abc2' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Ghost beans....
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGhostBeans()
|
||||
{
|
||||
testpack( 'Testing ghost beans' );
|
||||
$bean = R::dispense( 'bean' );
|
||||
$bean->title = 'abc';
|
||||
$id1 = R::store( $bean );
|
||||
R::trash( $bean );
|
||||
$bean = R::load( 'bean', $id1 );
|
||||
asrt( (int) $bean->id, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test explicit flush.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testExplicitCacheFlush()
|
||||
{
|
||||
testpack( 'Test cache flush (explicit)' );
|
||||
R::setNarrowFieldMode( FALSE );
|
||||
R::debug( TRUE, 1 );
|
||||
$logger = R::getDatabaseAdapter()->getDatabase()->getLogger();
|
||||
$bean = R::dispense( 'bean' );
|
||||
$bean->title = 'abc';
|
||||
$id1 = R::store( $bean );
|
||||
$logger->clear();
|
||||
$bean = R::load( 'bean', $id1 );
|
||||
asrt( $bean->title, 'abc' );
|
||||
asrt( count( $logger->grep( 'SELECT *' ) ), 1 );
|
||||
$bean = R::load( 'bean', $id1 );
|
||||
asrt( count( $logger->grep( 'SELECT *' ) ), 1 );
|
||||
R::getWriter()->flushCache();
|
||||
$bean = R::load( 'bean', $id1 );
|
||||
asrt( count( $logger->grep( 'SELECT *' ) ), 2 );
|
||||
R::getWriter()->flushCache();
|
||||
R::getWriter()->setUseCache( FALSE );
|
||||
R::setNarrowFieldMode( TRUE );
|
||||
}
|
||||
}
|
||||
280
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Xnull.php
vendored
Normal file
280
vendor/gabordemooij/redbean/testing/RedUNIT/Base/Xnull.php
vendored
Normal file
@@ -0,0 +1,280 @@
|
||||
<?php
|
||||
|
||||
namespace RedUNIT\Base;
|
||||
|
||||
use RedUNIT\Base as Base;
|
||||
use RedBeanPHP\Facade as R;
|
||||
use RedBeanPHP\OODBBean as OODBBean;
|
||||
|
||||
/**
|
||||
* Null
|
||||
*
|
||||
* Tests NULL handling.
|
||||
*
|
||||
* @file RedUNIT/Base/Xnull.php
|
||||
* @desc Tests handling of NULL values.
|
||||
* @author Gabor de Mooij and the RedBeanPHP Community
|
||||
* @license New BSD/GPLv2
|
||||
*
|
||||
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
|
||||
* This source file is subject to the New BSD/GPLv2 License that is bundled
|
||||
* with this source code in the file license.txt.
|
||||
*/
|
||||
class Xnull extends Base
|
||||
{
|
||||
/**
|
||||
* Tests whether we can create queries containing IS-NULL with
|
||||
* the IS-NULL-Condition flag.
|
||||
*/
|
||||
public function testISNULLConditions()
|
||||
{
|
||||
R::nuke();
|
||||
R::useISNULLConditions( FALSE );
|
||||
$book = R::dispense('book');
|
||||
$book->title = 'Much ado about Null';
|
||||
R::store( $book );
|
||||
$book = R::dispense('book');
|
||||
$book->title = NULL;
|
||||
R::store( $book );
|
||||
$books = R::findLike('book', array( 'title' => NULL ) );
|
||||
asrt(count($books), 2);
|
||||
$wasFalse = R::useISNULLConditions( TRUE );
|
||||
asrt( $wasFalse, FALSE );
|
||||
$books = R::findLike('book', array( 'title' => NULL ) );
|
||||
asrt(count($books), 1);
|
||||
$books = R::find('book', ' title = :title ', array( 'title' => NULL ) );
|
||||
asrt(count($books), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Null bindings.
|
||||
*/
|
||||
public function testBindings()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$book->content = NULL;
|
||||
//can we store a NULL?
|
||||
asrt( is_null( $book->content ), TRUE );
|
||||
R::store( $book );
|
||||
//did we really store the NULL value ?
|
||||
$book = R::findOne( 'book', ' content IS NULL ' );
|
||||
asrt( ( $book instanceof OODBBean ), TRUE );
|
||||
//still NULL, not empty STRING ?
|
||||
asrt( is_null( $book->content ), TRUE );
|
||||
$book->pages = 100;
|
||||
R::store( $book );
|
||||
//did we save it once again as NULL?
|
||||
$book = R::findOne( 'book', ' content IS NULL ' );
|
||||
asrt( ( $book instanceof OODBBean ), TRUE );
|
||||
asrt( is_null( $book->content ), TRUE );
|
||||
asrt( gettype( $book->pages ), 'string' );
|
||||
$otherBook = R::dispense( 'book' );
|
||||
$otherBook->pages = 99;
|
||||
//also if the column is VARCHAR-like?
|
||||
$otherBook->content = 'blah blah';
|
||||
R::store( $otherBook );
|
||||
$book = R::findOne( 'book', ' content IS NULL ' );
|
||||
asrt( ( $book instanceof OODBBean ), TRUE );
|
||||
asrt( is_null( $book->content ), TRUE );
|
||||
asrt( intval( $book->pages ), 100 );
|
||||
//can we query not NULL as well?
|
||||
$book = R::findOne( 'book', ' content IS NOT NULL ' );
|
||||
asrt( ( $book instanceof OODBBean ), TRUE );
|
||||
asrt( is_null( $book->content ), FALSE );
|
||||
asrt( intval( $book->pages ), 99 );
|
||||
asrt( $book->content, 'blah blah' );
|
||||
//Can we bind NULL directly?
|
||||
$book->isGood = FALSE;
|
||||
//Is NULL the default? And... no confusion with boolean FALSE?
|
||||
R::store( $book );
|
||||
$book = R::findOne( 'book', ' is_good IS NULL' );
|
||||
asrt( ( $book instanceof OODBBean ), TRUE );
|
||||
asrt( is_null( $book->content ), TRUE );
|
||||
asrt( intval( $book->pages ), 100 );
|
||||
$book = R::findOne( 'book', ' is_good = ?', array( 0 ) );
|
||||
asrt( ( $book instanceof OODBBean ), TRUE );
|
||||
asrt( is_null( $book->content ), FALSE );
|
||||
asrt( intval( $book->pages ), 99 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether we can NULLify a parent bean
|
||||
* page->book if the parent (book) is already
|
||||
* NULL. (isset vs array_key_exists bug).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testUnsetParent()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$book->title = 'My Book';
|
||||
$page = R::dispense( 'page' );
|
||||
$page->text = 'Lorem Ipsum';
|
||||
$book->ownPage[] = $page;
|
||||
R::store( $book );
|
||||
$page = $page->fresh();
|
||||
R::freeze( TRUE );
|
||||
asrt( (int) $page->book->id, (int) $book->id );
|
||||
unset( $page->book );
|
||||
R::store( $page );
|
||||
$page = $page->fresh();
|
||||
asrt( (int) $page->book->id, (int) $book->id );
|
||||
$page->book = NULL;
|
||||
R::store( $page );
|
||||
$page = $page->fresh();
|
||||
asrt( $page->book, NULL );
|
||||
asrt( $page->book_id, NULL );
|
||||
asrt( $page->bookID, NULL );
|
||||
asrt( $page->bookId, NULL );
|
||||
$page = R::dispense( 'page' );
|
||||
$page->text = 'Another Page';
|
||||
$page->book = NULL;
|
||||
try {
|
||||
R::store( $page );
|
||||
fail();
|
||||
} catch( \Exception $exception ) {
|
||||
pass();
|
||||
}
|
||||
unset($page->book);
|
||||
R::store($page);
|
||||
$page = $page->fresh();
|
||||
$page->book = NULL; //this must set field id to NULL not ADD column!
|
||||
try {
|
||||
R::store($page);
|
||||
pass();
|
||||
} catch( \Exception $exception ) {
|
||||
fail();
|
||||
}
|
||||
$page = $page->fresh();
|
||||
$page->book = NULL;
|
||||
R::store( $page );
|
||||
$page = $page->fresh();
|
||||
asrt( is_null( $page->book_id ), TRUE );
|
||||
$page->book = $book;
|
||||
R::store( $page );
|
||||
$page = $page->fresh();
|
||||
asrt( (int) $page->book->id, (int) $book->id );
|
||||
$page->book = NULL;
|
||||
R::store( $page );
|
||||
asrt( is_null( $page->book_id ), TRUE );
|
||||
asrt( is_null( $page->book ), TRUE );
|
||||
R::freeze( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test nullifying aliased parent.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testUnsetAliasedParent()
|
||||
{
|
||||
R::nuke();
|
||||
$book = R::dispense( 'book' );
|
||||
$author = R::dispense( 'author' );
|
||||
$book->coauthor = $author;
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
asrt( is_null( $book->fetchAs('author')->coauthor ), FALSE );
|
||||
unset( $book->coauthor );
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
asrt( is_null( $book->fetchAs('author')->coauthor ), FALSE );
|
||||
$book->coauthor = NULL;
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
asrt( is_null( $book->fetchAs('author')->coauthor ), TRUE );
|
||||
R::trash( $book );
|
||||
R::trash( $author );
|
||||
R::freeze( TRUE );
|
||||
$book = R::dispense( 'book' );
|
||||
$author = R::dispense( 'author' );
|
||||
$book->coauthor = $author;
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
asrt( is_null( $book->fetchAs('author')->coauthor ), FALSE );
|
||||
unset( $book->coauthor );
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
asrt( is_null( $book->fetchAs('author')->coauthor ), FALSE );
|
||||
$book->coauthor = NULL;
|
||||
R::store( $book );
|
||||
$book = $book->fresh();
|
||||
asrt( is_null( $book->fetchAs('author')->coauthor ), TRUE );
|
||||
R::trash( $book );
|
||||
R::trash( $author );
|
||||
R::freeze( FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test NULL handling, setting a property to NULL must
|
||||
* cause a change.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBasicNullHandling()
|
||||
{
|
||||
// NULL can change bean
|
||||
$bean = R::dispense( 'bean' );
|
||||
$bean->bla = 'a';
|
||||
R::store( $bean );
|
||||
$bean = $bean->fresh();
|
||||
asrt( $bean->hasChanged( 'bla' ), FALSE );
|
||||
$bean->bla = NULL;
|
||||
asrt( $bean->hasChanged( 'bla' ), TRUE );
|
||||
// NULL test
|
||||
$page = R::dispense( 'page' );
|
||||
$book = R::dispense( 'book' );
|
||||
$page->title = 'a NULL page';
|
||||
$page->book = $book;
|
||||
$book->title = 'Why NUll is painful..';
|
||||
R::store( $page );
|
||||
$bookid = $page->book->id;
|
||||
unset( $page->book );
|
||||
$id = R::store( $page );
|
||||
$page = R::load( 'page', $id );
|
||||
$page->title = 'another title';
|
||||
R::store( $page );
|
||||
pass();
|
||||
$page = R::load( 'page', $id );
|
||||
$page->title = 'another title';
|
||||
$page->book_id = NULL;
|
||||
R::store( $page );
|
||||
pass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Here we test whether the column type is set correctly.
|
||||
* Normally if you store NULL, the smallest type (bool/set) will
|
||||
* be selected. However in case of a foreign key type INT should
|
||||
* be selected because fks columns require matching types.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function ColumnType()
|
||||
{
|
||||
|
||||
$book = R::dispense( 'book' );
|
||||
$page = R::dispense( 'page' );
|
||||
$book->ownPage[] = $page;
|
||||
R::store( $book );
|
||||
pass();
|
||||
asrt( $page->getMeta( 'cast.book_id' ), 'id' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test meta column type.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function TypeColumn()
|
||||
{
|
||||
$book = R::dispense( 'book' );
|
||||
$page = R::dispense( 'page' );
|
||||
$page->book = $book;
|
||||
R::store( $page );
|
||||
pass();
|
||||
asrt( $page->getMeta( 'cast.book_id' ), 'id' );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user