/** * 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 dump(). * * @return void */ public function testDump() { $beans = R::dispense('bean', 2); $beans[0]->name = 'hello'; $beans[1]->name = 'world'; $array = R::dump($beans); asrt(is_array($array), TRUE); foreach ($array as $item) { asrt(is_string($item), TRUE); } $beans[1]->name = 'world, and a very long string that should be shortened'; $array = R::dump($beans); asrt(is_array($array), TRUE); asrt(strpos($array[1], '...'), 35); //just to get 100% test cov, we dont need to test this dmp($beans); pass(); //test wrong input asrt(is_array(R::dump(NULL)), TRUE); asrt(count(R::dump(NULL)), 0); asrt(is_array(R::dump('')), TRUE); asrt(count(R::dump('')), 0); asrt(is_array(R::dump(1)), TRUE); asrt(count(R::dump(1)), 0); asrt(is_array(R::dump(TRUE)), TRUE); asrt(count(R::dump(FALSE)), 0); }
/** * Test SQLite table rebuilding. * * @return void */ public function testRebuilder() { $toolbox = R::getToolBox(); $adapter = $toolbox->getDatabaseAdapter(); $writer = $toolbox->getWriter(); $redbean = $toolbox->getRedBean(); $pdo = $adapter->getDatabase(); $book = R::dispense('book'); $page = R::dispense('page'); $book->xownPage[] = $page; $id = R::store($book); $book = R::load('book', $id); asrt(count($book->xownPage), 1); asrt((int) R::getCell('SELECT COUNT(*) FROM page'), 1); R::trash($book); asrt((int) R::getCell('SELECT COUNT(*) FROM page'), 0); $book = R::dispense('book'); $page = R::dispense('page'); $book->xownPage[] = $page; $id = R::store($book); $book = R::load('book', $id); asrt(count($book->xownPage), 1); asrt((int) R::getCell('SELECT COUNT(*) FROM page'), 1); $book->added = 2; R::store($book); $book->added = 'added'; R::store($book); R::trash($book); asrt((int) R::getCell('SELECT COUNT(*) FROM page'), 0); }
/** * Tests R::getInsertID convenience method. * * @return void */ public function testGetInsertID() { R::nuke(); $id = R::store(R::dispense('book')); $id2 = R::getInsertID(); asrt($id, $id2); }
function createPackageCost($label, $cost) { $packageCost = R::dispense('packageCost'); $packageCost->label = $label; $packageCost->cost = $cost; return json_encode(R::exportAll($packageCost)); }
/** * Test varchar 191 condition. * * @return void */ public function testInnoDBIndexLimit() { R::nuke(); $book = R::dispense('book'); $book->text = 'abcd'; R::store($book); $columns = R::inspect('book'); asrt(isset($columns['text']), TRUE); asrt($columns['text'], 'varchar(191)'); $book = $book->fresh(); $book->text = str_repeat('x', 190); R::store($book); $columns = R::inspect('book'); asrt(isset($columns['text']), TRUE); asrt($columns['text'], 'varchar(191)'); $book = $book->fresh(); $book->text = str_repeat('x', 191); R::store($book); $columns = R::inspect('book'); asrt(isset($columns['text']), TRUE); asrt($columns['text'], 'varchar(191)'); $book = $book->fresh(); $book->text = str_repeat('x', 192); R::store($book); $columns = R::inspect('book'); asrt(isset($columns['text']), TRUE); asrt($columns['text'], 'varchar(255)'); }
/** * Test tainted. * * @return void */ public function testTainted() { testpack('Original Tainted Tests'); $redbean = R::getRedBean(); $spoon = $redbean->dispense("spoon"); asrt($spoon->getMeta("tainted"), TRUE); $spoon->dirty = "yes"; asrt($spoon->getMeta("tainted"), TRUE); testpack('Tainted List test'); $note = R::dispense('note'); $note->text = 'abc'; $note->ownNote[] = R::dispense('note')->setAttr('text', 'def'); $id = R::store($note); $note = R::load('note', $id); asrt($note->isTainted(), FALSE); // Shouldn't affect tainted $note->text; asrt($note->isTainted(), FALSE); $note->ownNote; asrt($note->isTainted(), TRUE); testpack('Tainted Test Old Value'); $text = $note->old('text'); asrt($text, 'abc'); asrt($note->hasChanged('text'), FALSE); $note->text = 'xxx'; asrt($note->hasChanged('text'), TRUE); $text = $note->old('text'); asrt($text, 'abc'); testpack('Tainted Non-exist'); asrt($note->hasChanged('text2'), FALSE); testpack('Misc Tainted Tests'); $bean = R::dispense('bean'); $bean->hasChanged('prop'); $bean->old('prop'); }
/** * Test foreign keys with SQLite. * * @return void */ public function testForeignKeysWithSQLite() { $book = R::dispense('book'); $page = R::dispense('page'); $cover = R::dispense('cover'); list($g1, $g2) = R::dispense('genre', 2); $g1->name = '1'; $g2->name = '2'; $book->ownPage = array($page); $book->cover = $cover; $book->sharedGenre = array($g1, $g2); R::store($book); $fkbook = R::getAll('pragma foreign_key_list(book)'); $fkgenre = R::getAll('pragma foreign_key_list(book_genre)'); $fkpage = R::getAll('pragma foreign_key_list(page)'); asrt($fkpage[0]['from'], 'book_id'); asrt($fkpage[0]['to'], 'id'); asrt($fkpage[0]['table'], 'book'); asrt(count($fkgenre), 2); if ($fkgenre[0]['from'] == 'book') { asrt($fkgenre[0]['to'], 'id'); asrt($fkgenre[0]['table'], 'book'); } if ($fkgenre[0]['from'] == 'genre') { asrt($fkgenre[0]['to'], 'id'); asrt($fkgenre[0]['table'], 'genre'); } asrt($fkbook[0]['from'], 'cover_id'); asrt($fkbook[0]['to'], 'id'); asrt($fkbook[0]['table'], 'cover'); }
/** * Test boxing. * * @return void */ public function testBasicBox() { $soup = R::dispense('soup'); $soup->flavour = 'tomato'; $this->giveMeSoup($soup->box()); $this->giveMeBean($soup->box()->unbox()); $this->giveMeBean($soup); }
/** * Cant have underscored beans * @expectedException \RedBeanPHP\RedException */ public function testTwoWordsUnderscoredBean() { R::freeze(false); $testName = R::dispense('test_name'); $id = R::store($testName); R::load('test_name', $id); R::freeze($this->frozen); }
/** * 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); }
/** * 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'); }
/** * 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); }
/** * Test UTF8 handling. * * @return void */ public function testUTF8() { $str = '𠜎ὃ𠻗𠻹𠻺𠼭𠼮𠽌𠾴𠾼𠿪𡁜'; $bean = R::dispense('bean'); $bean->bla = $str; R::store($bean); $bean = R::load('bean', $bean->id); asrt($bean->bla, $str); pass(); }
/** * You cant access meta data using the array accessors. * * @return void */ public function testNoArrayMetaAccess() { $bean = R::dispense('bean'); $bean->setMeta('greet', 'hello'); asrt(isset($bean['greet']), FALSE); asrt(isset($bean['__info']['greet']), FALSE); asrt(isset($bean['__info']), FALSE); asrt(isset($bean['meta']), FALSE); asrt(count($bean), 1); }
/** * Test for issue #386. * Can we use large numbers in LIMIT ? * * @return void */ public function testLargeNum() { $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(); }
/** * Store a new record. * * @param Request $request * @return Response */ public function store(Request $request) { $item_id = $request->input('item_id'); $item = R::load('item', $item_id); $attribute = R::dispense('attribute'); $attribute->key = $request->input('key'); $attribute->value = $request->input('value'); $item->ownAttributeList[] = $attribute; R::store($item); echo "<pre>\n"; var_dump($attribute->export()); var_dump($item->export()); }
/** * 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 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(); }
/** * 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); }
/** * 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(); }
/** * Test query building. * * @return void */ public function testQueryBuilderMix() { $toolbox = R::getToolBox(); $adapter = $toolbox->getDatabaseAdapter(); $mixer = new SQLHelper($adapter); $now = $mixer->now(); asrt(is_string($now), TRUE); asrt(strlen($now) > 5, TRUE); $bean = R::dispense('bean'); $bean->field1 = 'a'; $bean->field2 = 'b'; R::store($bean); $data = $mixer->begin()->select('*')->from('bean')->where(' field1 = ? ')->put('a')->get(); asrt(is_array($data), TRUE); $row = array_pop($data); asrt(is_array($row), TRUE); asrt($row['field1'], 'a'); asrt($row['field2'], 'b'); $row = $mixer->begin()->select('field1', 'field2')->from('bean')->where(' 1 ')->limit('1')->get('row'); asrt(is_array($row), TRUE); asrt($row['field1'], 'a'); asrt($row['field2'], 'b'); $cell = $mixer->begin()->select('field1')->from('bean')->get('cell'); asrt($cell, 'a'); $cell = $mixer->begin()->select_field1_from('bean')->get('cell'); asrt($cell, 'a'); // Now switch back to non-capture mode (issue #142) $value = $mixer->now(); asrt(is_object($value), FALSE); asrt(is_scalar($value), TRUE); asrt($value > 0, TRUE); $mixer->begin()->select_field1_from('bean'); $mixer->clear(); $value = $mixer->now(); asrt(is_scalar($value), TRUE); // Test open and close block commands $bean = R::dispense('bean'); $bean->num = 2; R::store($bean); $value = $mixer->begin()->select('num')->from('bean')->where('num IN')->open()->addSQL('2')->close()->get('cell'); asrt($value == 2, TRUE); // Test nesting $bean = R::dispense('bean'); $bean->num = 2; R::store($bean); $value = $mixer->begin()->select('num')->from('bean')->where('num IN')->nest($mixer->getNew()->begin()->addSQL(' ( 2 ) '))->get('cell'); asrt($value == 2, TRUE); }
/** * 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 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); $collection->close(); }
/** * 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'); }
/** * 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(); } }
/** * Test parameter binding. * * @return void */ public function testParamBindingWithPostgres() { testpack("param binding pgsql"); $page = R::dispense("page"); $page->name = "abc"; $page->number = 2; R::store($page); R::exec("insert into page (name) values(:name) ", array(":name" => "my name")); R::exec("insert into page (number) values(:one) ", array(":one" => 1)); R::exec("insert into page (number) values(:one) ", array(":one" => "1")); R::exec("insert into page (number) values(:one) ", array(":one" => "1234")); R::exec("insert into page (number) values(:one) ", array(":one" => "-21")); pass(); testpack('Test whether we can properly bind and receive NULL values'); $adapter = R::getDatabaseAdapter(); asrt($adapter->getCell('SELECT TEXT( :nil ) ', array(':nil' => 'NULL')), 'NULL'); asrt($adapter->getCell('SELECT TEXT( :nil ) ', array(':nil' => NULL)), NULL); asrt($adapter->getCell('SELECT TEXT( ? ) ', array('NULL')), 'NULL'); asrt($adapter->getCell('SELECT TEXT( ? ) ', array(NULL)), NULL); }
/** * 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'); } }
/** * 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 special data types. * * @return void */ public function testSpecialDataTypes() { testpack('Special data types'); $bean = R::dispense('bean'); $bean->date = 'someday'; R::store($bean); $cols = R::getColumns('bean'); asrt($cols['date'], 'TEXT'); $bean = R::dispense('bean'); $bean->date = '2011-10-10'; R::nuke(); $bean = R::dispense('bean'); $bean->date = '2011-10-10'; R::store($bean); $cols = R::getColumns('bean'); asrt($cols['date'], 'NUMERIC'); }