├── .gitignore
├── .travis.yml
├── README.markdown
├── RedBeanPHP
├── Adapter.php
├── Adapter
│ └── DBAdapter.php
├── AssociationManager.php
├── BeanCollection.php
├── BeanHelper.php
├── BeanHelper
│ ├── DynamicBeanHelper.php
│ └── SimpleFacadeBeanHelper.php
├── Cursor.php
├── Cursor
│ ├── NullCursor.php
│ └── PDOCursor.php
├── Driver.php
├── Driver
│ └── RPDO.php
├── DuplicationManager.php
├── Facade.php
├── Finder.php
├── Functions.php
├── LabelMaker.php
├── Logger.php
├── Logger
│ ├── RDefault.php
│ └── RDefault
│ │ └── Debug.php
├── OODB.php
├── OODBBean.php
├── Observable.php
├── Observer.php
├── Plugin.php
├── Plugin
│ ├── Pool.php
│ ├── SQN.php
│ ├── TinyQueryBuilder.php
│ └── put_your_plugins_here.txt
├── QueryWriter.php
├── QueryWriter
│ ├── AQueryWriter.php
│ ├── CUBRID.php
│ ├── Firebird.php
│ ├── MySQL.php
│ ├── PostgreSQL.php
│ └── SQLiteT.php
├── R.php
├── RedException.php
├── RedException
│ └── SQL.php
├── Repository.php
├── Repository
│ ├── Fluid.php
│ └── Frozen.php
├── SimpleModel.php
├── SimpleModelHelper.php
├── SimpleModelInterface.php
├── TagManager.php
├── ToolBox.php
├── TypedModel.php
├── Util
│ ├── ArrayTool.php
│ ├── Diff.php
│ ├── DispenseHelper.php
│ ├── Dump.php
│ ├── Either.php
│ ├── Feature.php
│ ├── Look.php
│ ├── MatchUp.php
│ ├── MultiLoader.php
│ ├── QuickExport.php
│ ├── Transaction.php
│ └── Tree.php
├── license.txt
└── loader.php
├── composer.json
├── p533patch.php
├── replica2-win.php
├── replica2.php
├── run_all_tests.sh
├── run_single_test.sh
├── test-dist.ini
└── testing
├── RedUNIT.php
├── RedUNIT
├── Base.php
├── Base
│ ├── Aliasing.php
│ ├── Arrays.php
│ ├── Association.php
│ ├── Batch.php
│ ├── Bean.php
│ ├── Boxing.php
│ ├── Chill.php
│ ├── Close.php
│ ├── Concurrency.php
│ ├── Copy.php
│ ├── Count.php
│ ├── Cross.php
│ ├── Cursors.php
│ ├── Database.php
│ ├── Dispense.php
│ ├── Dup.php
│ ├── Either.php
│ ├── Exceptions.php
│ ├── Facade.php
│ ├── Finding.php
│ ├── Foreignkeys.php
│ ├── Frozen.php
│ ├── Fuse.php
│ ├── Hybrid.php
│ ├── Indexes.php
│ ├── Issue259.php
│ ├── Issue303.php
│ ├── Issue408.php
│ ├── Issue841.php
│ ├── Issue90.php
│ ├── Joins.php
│ ├── Keywords.php
│ ├── Largenum.php
│ ├── Logging.php
│ ├── Misc.php
│ ├── Namedparams.php
│ ├── Nuke.php
│ ├── Observers.php
│ ├── Partial.php
│ ├── Performance.php
│ ├── Prefixes.php
│ ├── Productivity.php
│ ├── PullRequest530.php
│ ├── Quickexport.php
│ ├── Relations.php
│ ├── Tags.php
│ ├── Threeway.php
│ ├── Trash.php
│ ├── Traverse.php
│ ├── Typechecking.php
│ ├── Update.php
│ ├── Utf8.php
│ ├── Via.php
│ ├── With.php
│ ├── Writecache.php
│ └── Xnull.php
├── Blackhole.php
├── Blackhole
│ ├── Debug.php
│ ├── Export.php
│ ├── Fusebox.php
│ ├── Glue.php
│ ├── Import.php
│ ├── Labels.php
│ ├── Meta.php
│ ├── Misc.php
│ ├── Plugins.php
│ ├── Stub.php
│ ├── Tainted.php
│ ├── Toolbox.php
│ └── Version.php
├── CUBRID.php
├── CUBRID
│ ├── Setget.php
│ └── Writer.php
├── Mysql.php
├── Mysql
│ ├── Bigint.php
│ ├── Double.php
│ ├── Foreignkeys.php
│ ├── Freeze.php
│ ├── Issue411.php
│ ├── Parambind.php
│ ├── Preexist.php
│ ├── Setget.php
│ ├── Uuid.php
│ └── Writer.php
├── Postgres.php
├── Postgres
│ ├── Bigint.php
│ ├── Foreignkeys.php
│ ├── Parambind.php
│ ├── Partial.php
│ ├── Setget.php
│ ├── Trees.php
│ ├── Uuid.php
│ └── Writer.php
├── Pretest.php
├── Sqlite.php
└── Sqlite
│ ├── Foreignkeys.php
│ ├── Parambind.php
│ ├── Rebuild.php
│ ├── Setget.php
│ └── Writer.php
├── cli
├── plugins
│ └── myhooks.php
├── runperf.php
├── runtests.php
├── test_hook_example.php
└── testcontainer
│ └── put-rb-file-here.txt
├── config
├── test-dist.ini
└── test-travis.ini
├── helpers
├── classes.php
└── functions.php
└── notes.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled source #
2 | ###################
3 | *.com
4 | *.class
5 | *.dll
6 | *.exe
7 | *.o
8 | *.so
9 | *.pyc
10 |
11 | # Logs and databases #
12 | ######################
13 | *.log
14 |
15 | # OS generated files #
16 | ######################
17 | .DS_Store*
18 | ehthumbs.db
19 | Icon?
20 | Thumbs.db
21 | /.project
22 | /.settings/org.eclipse.php.core.prefs
23 | /.settings/org.eclipse.php.debug.core.Debug_Process_Preferences.prefs
24 | /rb.phar
25 | /rb.php
26 | /rb-mysql.php
27 | /rb-postgres.php
28 | /rb-sqlite.php
29 | build/
30 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | services:
4 | - mysql
5 | - postgresql
6 |
7 | matrix:
8 | include:
9 | - php: 5.3
10 | dist: precise
11 | group: legacy
12 | - php: 5.4
13 | dist: trusty
14 | - php: 5.5
15 | dist: trusty
16 | - php: 5.6
17 | dist: trusty
18 | - php: 7.0
19 | dist: trusty
20 | - php: 7.1
21 | dist: trusty
22 | - php: 7.2
23 | dist: trusty
24 | - php: 7.3
25 | dist: trusty
26 | - php: 7.4
27 | dist: trusty
28 | - php: 8.0
29 | dist: xenial
30 | - php: 8.1.0
31 | dist: bionic
32 | - php: 8.2.0
33 | dist: focal
34 | - php: 8.3.0
35 | dist: bionic
36 | - php: 8.4.0
37 | dist: noble
38 | allow_failures: true
39 |
40 | env:
41 | global:
42 | - PGUSER=postgres
43 | - PGPORT=5432
44 | - PGHOST=localhost
45 | - XDEBUG_MODE=coverage
46 |
47 | before_install:
48 | - if [[ "$TRAVIS_DIST" == "focal" ]]; then sudo apt-get install libonig5 ;fi
49 | - if [[ "$TRAVIS_DIST" == "focal" ]]; then sudo service postgresql restart ;fi
50 |
51 | before_script:
52 | - touch /tmp/oodb.db
53 | - mysql -e 'create database oodb;'
54 | - psql template1 -c 'CREATE EXTENSION "uuid-ossp";' -U postgres
55 | - psql -c 'create database oodb;' -U postgres
56 | - php replica2.php onlyphp
57 | - cp rb.php testing/cli/testcontainer/rb.php
58 | - cd testing/cli
59 |
60 |
61 | script: php runtests.php
62 |
--------------------------------------------------------------------------------
/README.markdown:
--------------------------------------------------------------------------------
1 | RedBeanPHP 5
2 | ============
3 |
4 | [](https://travis-ci.org/gabordemooij/redbean)
5 |
6 | RedBeanPHP is an easy to use ORM tool for PHP.
7 |
8 | * Automatically creates tables and columns as you go
9 | * No configuration, just fire and forget
10 | * No complicated package tools, no autoloaders, just ONE file
11 |
12 | Installation (recommended)
13 | ---------------------------
14 |
15 | Download RedBeanPHP from the website:
16 |
17 | https://redbeanphp.com/download
18 |
19 | Extract the archive and put it in your PHP project, voila!
20 |
21 | Optional: sha256sum and check signature.
22 |
23 |
24 | Installation via Composer (not recommended)
25 | -----------------------------------------
26 |
27 | Just open your composer.json file and add the package name ```(e.g. "gabordemooij/redbean": "dev-master")``` in your require list.
28 |
29 | ```json
30 | {
31 | "require": {
32 | "gabordemooij/redbean": "dev-master"
33 | }
34 | }
35 | ```
36 |
37 | **NOTE**:
38 | You will find many examples on the RedBean website make use of RedBean's `R` class. Because of namespaced autoloading in Composer, this class will be available as `\RedbeanPHP\R` instead of `R`. If you desire to use the much shorter `R` alias, you can add a `use` statement at the beginning of your code:
39 |
40 | ```php
41 | use \RedBeanPHP\R as R;
42 | ```
43 | **NOTE:**
44 | It is important to note that when using RedBeanPHP with Composer, there are some extra precautions needed when working with [Models](https://redbeanphp.com/index.php?p=/models). Due to the namespace requirements of Composer, when creating Models we need to use the `SimpleModel` to extend, not `RedBean_SimpleModel`. Furthermore, we need to specify the namespace of the `SimpleModel`, so a full example of using a Model with RedBean with Composer is as follows:
45 |
46 | ```php
47 | use \RedBeanPHP\R;
48 |
49 | class User extends \RedBeanPHP\SimpleModel
50 | {
51 | ...
52 | }
53 | ```
54 | Notice that we also need to add the `use \RedBeanPHP\R` statement so that we can use the `R::` shortcut within the Model.
55 |
56 |
57 | Quick Example
58 | -------------
59 |
60 | How we store a book object with RedBeanPHP:
61 | ```php
62 | $book = R::dispense("book");
63 | $book->author = "Santa Claus";
64 | $book->title = "Secrets of Christmas";
65 | $id = R::store( $book );
66 | ```
67 |
68 | Yep, it's that simple.
69 |
70 |
71 | More information
72 | ----------------
73 |
74 | For more information about RedBeanPHP please consult
75 | the RedBeanPHP website:
76 |
77 | https://www.redbeanphp.com/
78 |
--------------------------------------------------------------------------------
/RedBeanPHP/BeanCollection.php:
--------------------------------------------------------------------------------
1 | type = $type;
66 | $this->cursor = $cursor;
67 | $this->repository = $repository;
68 | $this->mask = $mask;
69 | }
70 |
71 | /**
72 | * Returns the next bean in the collection.
73 | * If called the first time, this will return the first bean in the collection.
74 | * If there are no more beans left in the collection, this method
75 | * will return NULL.
76 | *
77 | * @return OODBBean|NULL
78 | */
79 | public function next()
80 | {
81 | $row = $this->cursor->getNextItem();
82 | if ( $row ) {
83 | $beans = $this->repository->convertToBeans( $this->type, array( $row ), $this->mask );
84 | return reset( $beans );
85 | }
86 | return NULL;
87 | }
88 |
89 | /**
90 | * Resets the collection from the start, like a fresh() on a bean.
91 | *
92 | * @return void
93 | */
94 | public function reset()
95 | {
96 | $this->cursor->reset();
97 | }
98 |
99 | /**
100 | * Closes the underlying cursor (needed for some databases).
101 | *
102 | * @return void
103 | */
104 | public function close()
105 | {
106 | $this->cursor->close();
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/RedBeanPHP/BeanHelper.php:
--------------------------------------------------------------------------------
1 |
41 | * R::addDatabase( ..., new DynamicBeanHelper('Prefix1_') );
42 | *
43 | *
44 | * @param string $modelPrefix prefix
45 | */
46 | public function __construct( $modelPrefix ) {
47 | $this->modelPrefix = $modelPrefix;
48 | }
49 |
50 | /**
51 | * @see BeanHelper::getModelForBean
52 | */
53 | public function getModelForBean( OODBBean $bean )
54 | {
55 | return $this->resolveModel( $this->modelPrefix, $bean->getMeta( 'type' ), $bean );
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/RedBeanPHP/BeanHelper/SimpleFacadeBeanHelper.php:
--------------------------------------------------------------------------------
1 | getMeta( 'type' );
78 | $prefix = defined( 'REDBEAN_MODEL_PREFIX' ) ? REDBEAN_MODEL_PREFIX : '\\Model_';
79 |
80 | return $this->resolveModel($prefix, $model, $bean);
81 | }
82 |
83 | /**
84 | * Resolves the model associated with the bean using the model name (type),
85 | * the prefix and the bean.
86 | *
87 | * @note
88 | * If REDBEAN_CLASS_AUTOLOAD is defined this will be passed to class_exist as
89 | * autoloading flag.
90 | *
91 | * @param string $prefix Prefix to use for resolution
92 | * @param string $model Type name
93 | * @param OODBBean $bean Bean to resolve model for
94 | *
95 | * @return SimpleModel|SimpleModelInterface|NULL
96 | */
97 | protected function resolveModel($prefix, $model, $bean) {
98 |
99 | /* Determine autoloading preference */
100 | $autoloadFlag = ( defined( 'REDBEAN_CLASS_AUTOLOAD' ) ? REDBEAN_CLASS_AUTOLOAD : TRUE );
101 |
102 | if ( strpos( $model, '_' ) !== FALSE ) {
103 | $modelParts = explode( '_', $model );
104 | $modelName = '';
105 | foreach( $modelParts as $part ) {
106 | $modelName .= ucfirst( $part );
107 | }
108 | $modelName = $prefix . $modelName;
109 | if ( !class_exists( $modelName ) ) {
110 | $modelName = $prefix . ucfirst( $model );
111 | if ( !class_exists( $modelName, $autoloadFlag ) ) {
112 | return NULL;
113 | }
114 | }
115 | } else {
116 | $modelName = $prefix . ucfirst( $model );
117 | if ( !class_exists( $modelName, $autoloadFlag ) ) {
118 | return NULL;
119 | }
120 | }
121 | $obj = self::factory( $modelName );
122 | $obj->loadBean( $bean );
123 | return $obj;
124 | }
125 |
126 | /**
127 | * @see BeanHelper::getExtractedToolbox
128 | */
129 | public function getExtractedToolbox()
130 | {
131 | return Facade::getExtractedToolbox();
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/RedBeanPHP/Cursor.php:
--------------------------------------------------------------------------------
1 | res = $res;
47 | $this->fetchStyle = $fetchStyle;
48 | }
49 |
50 | /**
51 | * @see Cursor::getNextItem
52 | */
53 | public function getNextItem()
54 | {
55 | return $this->res->fetch();
56 | }
57 |
58 | /**
59 | * @see Cursor::reset
60 | */
61 | public function reset()
62 | {
63 | $this->close();
64 | $this->res->execute();
65 | }
66 |
67 | /**
68 | * @see Cursor::close
69 | */
70 | public function close()
71 | {
72 | $this->res->closeCursor();
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/RedBeanPHP/Functions.php:
--------------------------------------------------------------------------------
1 |
23 | * R::find( 'paint', ' color_id = ? ', [ EID('color:yellow') ] );
24 | *
25 | *
26 | * If a function called EID() already exists you'll have to write this
27 | * wrapper yourself ;)
28 | *
29 | * @param string $enumName enum code as you would pass to R::enum()
30 | *
31 | * @return mixed
32 | */
33 | if (!function_exists('EID')) {
34 |
35 | function EID($enumName)
36 | {
37 | return \RedBeanPHP\Facade::enum( $enumName )->id;
38 | }
39 |
40 | }
41 |
42 | /**
43 | * Prints the result of R::dump() to the screen using
44 | * print_r.
45 | *
46 | * @param mixed $data data to dump
47 | *
48 | * @return void
49 | */
50 | if ( !function_exists( 'dmp' ) ) {
51 |
52 | function dmp( $list )
53 | {
54 | print_r( \RedBeanPHP\Facade::dump( $list ) );
55 | }
56 | }
57 |
58 | /**
59 | * Function alias for R::genSlots().
60 | */
61 | if ( !function_exists( 'genslots' ) ) {
62 |
63 | function genslots( $slots, $tpl = NULL )
64 | {
65 | return \RedBeanPHP\Facade::genSlots( $slots, $tpl );
66 | }
67 | }
68 |
69 | /**
70 | * Function alias for R::flat().
71 | */
72 | if ( !function_exists( 'array_flatten' ) ) {
73 |
74 | function array_flatten( $array )
75 | {
76 | return \RedBeanPHP\Facade::flat( $array );
77 | }
78 | }
79 |
80 | /**
81 | * Function pstr() generates [ $value, \PDO::PARAM_STR ]
82 | * Ensures that your parameter is being treated as a string.
83 | *
84 | * Usage:
85 | *
86 | *
87 | * R::find('book', 'title = ?', [ pstr('1') ]);
88 | *
89 | */
90 | if ( !function_exists( 'pstr' ) ) {
91 |
92 | function pstr( $value )
93 | {
94 | return array( strval( $value ) , \PDO::PARAM_STR );
95 | }
96 | }
97 |
98 |
99 | /**
100 | * Function pint() generates [ $value, \PDO::PARAM_INT ]
101 | * Ensures that your parameter is being treated as an integer.
102 | *
103 | * Usage:
104 | *
105 | *
106 | * R::find('book', ' pages > ? ', [ pint(2) ] );
107 | *
108 | */
109 | if ( !function_exists( 'pint' ) ) {
110 |
111 | function pint( $value )
112 | {
113 | return array( intval( $value ) , \PDO::PARAM_INT );
114 | }
115 | }
116 |
117 | /**
118 | * Function DBPrefix() is a simple function to allow you to
119 | * quickly set a different namespace for FUSE model resolution
120 | * per database connection. It works by creating a new DynamicBeanHelper
121 | * with the specified string as model prefix.
122 | *
123 | * Usage:
124 | *
125 | *
126 | * R::addDatabase( ..., DBPrefix( 'Prefix1_' ) );
127 | *
128 | */
129 | if ( !function_exists( 'DBPrefix' ) ) {
130 |
131 | function DBPrefix( $prefix = '\\Model' ) {
132 | return new \RedBeanPHP\BeanHelper\DynamicBeanHelper( $prefix );
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/RedBeanPHP/Logger.php:
--------------------------------------------------------------------------------
1 | mode === self::C_LOGGER_ECHO ) {
56 | echo $log;
57 | } else {
58 | $this->logs[] = $log;
59 | }
60 | } else {
61 | if ( $this->mode === self::C_LOGGER_ECHO ) {
62 | echo $argument;
63 | } else {
64 | $this->logs[] = $argument;
65 | }
66 | }
67 |
68 | if ( $this->mode === self::C_LOGGER_ECHO ) echo "
" . PHP_EOL;
69 | }
70 | }
71 |
72 | /**
73 | * Returns the internal log array.
74 | * The internal log array is where all log messages are stored.
75 | *
76 | * @return array
77 | */
78 | public function getLogs()
79 | {
80 | return $this->logs;
81 | }
82 |
83 | /**
84 | * Clears the internal log array, removing all
85 | * previously stored entries.
86 | *
87 | * @return self
88 | */
89 | public function clear()
90 | {
91 | $this->logs = array();
92 | return $this;
93 | }
94 |
95 | /**
96 | * Selects a logging mode.
97 | * There are several options available.
98 | *
99 | * * C_LOGGER_ARRAY - log silently, stores entries in internal log array only
100 | * * C_LOGGER_ECHO - also forward log messages directly to STDOUT
101 | *
102 | * @param integer $mode mode of operation for logging object
103 | *
104 | * @return self
105 | */
106 | public function setMode( $mode )
107 | {
108 | if ($mode !== self::C_LOGGER_ARRAY && $mode !== self::C_LOGGER_ECHO ) {
109 | throw new RedException( 'Invalid mode selected for logger, use C_LOGGER_ARRAY or C_LOGGER_ECHO.' );
110 | }
111 | $this->mode = $mode;
112 | return $this;
113 | }
114 |
115 | /**
116 | * Searches for all log entries in internal log array
117 | * for $needle and returns those entries.
118 | * This method will return an array containing all matches for your
119 | * search query.
120 | *
121 | * @param string $needle phrase to look for in internal log array
122 | *
123 | * @return array
124 | */
125 | public function grep( $needle )
126 | {
127 | $found = array();
128 | foreach( $this->logs as $logEntry ) {
129 | if ( strpos( $logEntry, $needle ) !== FALSE ) $found[] = $logEntry;
130 | }
131 | return $found;
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/RedBeanPHP/Observable.php:
--------------------------------------------------------------------------------
1 | observers[$eventname] ) ) {
42 | $this->observers[$eventname] = array();
43 | }
44 |
45 | if ( in_array( $observer, $this->observers[$eventname] ) ) {
46 | return;
47 | }
48 |
49 | $this->observers[$eventname][] = $observer;
50 | }
51 |
52 | /**
53 | * Notifies listeners.
54 | * Sends the signal $eventname, the event identifier and a message object
55 | * to all observers that have been registered to receive notification for
56 | * this event. Part of the observer pattern implementation in RedBeanPHP.
57 | *
58 | * @param string $eventname event you want signal
59 | * @param mixed $info message object to send along
60 | *
61 | * @return void
62 | */
63 | public function signal( $eventname, $info )
64 | {
65 | if ( !isset( $this->observers[$eventname] ) ) {
66 | $this->observers[$eventname] = array();
67 | }
68 |
69 | foreach ( $this->observers[$eventname] as $observer ) {
70 | $observer->onEvent( $eventname, $info );
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/RedBeanPHP/Observer.php:
--------------------------------------------------------------------------------
1 |
16 | * R::sqn('shop
19 | *
20 | * SQN assumes id fields follow the following conventions:
21 | *
22 | * Primary key: id
23 | * Foreign key: {table}_id
24 | * No table prefix.
25 | *
26 | * SQN can also generate additional aliases:
27 | *
28 | *
29 | * R::sqn( ..., 'area/x,y;place/x,y' ) - area_x area_y place_x place_y
30 | *
31 | *
32 | * @author Gabor de Mooij
33 | * @license BSD/GPLv2
34 | *
35 | * @copyright
36 | * copyright (c) G.J.G.T. (Gabor) de Mooij
37 | * This source file is subject to the BSD License that is bundled
38 | * with this source code in the file license.txt.
39 | */
40 | R::ext('sqn', function( $query, $aliases = null, $q = '`' ) {
41 | $map = [
42 | '|' => 'INNER JOIN',
43 | '||' => 'INNER JOIN',
44 | '>' => 'RIGHT JOIN',
45 | '>>' => 'RIGHT JOIN',
46 | '<' => 'LEFT JOIN',
47 | '<<' => 'LEFT JOIN',
48 | ];
49 | $select = [];
50 | $from = '';
51 | $joins = [];
52 | $prev = '';
53 | $ents = preg_split( '/[^\w_]+/', $query );
54 | $tokens = preg_split( '/[\w_]+/', $query );
55 | array_pop($tokens);
56 | foreach( $ents as $i => $ent ) {
57 | $select[] = " {$q}{$ent}{$q}.* ";
58 | if (!$i) {
59 | $from = $ent;
60 | $prev = $ent;
61 | continue;
62 | }
63 | if ( $tokens[$i] == '<' || $tokens[$i] == '>' || $tokens[$i] == '|') {
64 | $join[] = " {$map[$tokens[$i]]} {$q}{$ent}{$q} ON {$q}{$ent}{$q}.{$prev}_id = {$q}{$prev}{$q}.id ";
65 | }
66 | if ( $tokens[$i] == '<<' || $tokens[$i] == '>>' || $tokens[$i] == '||') {
67 | $combi = [$prev, $ent];
68 | sort( $combi );
69 | $combi = implode( '_', $combi );
70 | $select[] = " {$q}{$combi}{$q}.* ";
71 | $join[] = " {$map[$tokens[$i]]} {$q}{$combi}{$q} ON {$q}{$combi}{$q}.{$prev}_id = {$q}{$prev}{$q}.id ";
72 | $join[] = " {$map[$tokens[$i]]} {$q}{$ent}{$q} ON {$q}{$combi}{$q}.{$ent}_id = {$q}{$ent}{$q}.id ";
73 | }
74 | $prev = $ent;
75 | }
76 | if (!is_null($aliases)) {
77 | $aliases = explode(';', $aliases);
78 | foreach($aliases as $alias) {
79 | list($table, $cols) = explode('/', $alias);
80 | $cols = explode(',', $cols);
81 | foreach($cols as $col) {
82 | $select[] = " {$q}{$table}{$q}.{$q}{$col}{$q} AS {$q}{$table}_{$col}{$q} ";
83 | }
84 | }
85 | }
86 | $selectSQL = implode( ",\n", $select );
87 | $joinSQL = implode( "\n", $join );
88 | return "SELECT{$selectSQL}\n FROM {$q}{$from}{$q}\n{$joinSQL}";
89 | });
90 |
91 |
--------------------------------------------------------------------------------
/RedBeanPHP/Plugin/TinyQueryBuilder.php:
--------------------------------------------------------------------------------
1 |
7 | * $sql = build_query([
8 | * [ 'SELECT * FROM book'],
9 | * [$title ,'WHERE','title = ?'],
10 | * [$price ,'AND','price < ?'],
11 | * [$order ,'ORDER BY ? ASC'],
12 | * [$limit ,'LIMIT ?']
13 | * ]);
14 | *
15 | *
16 | * Now, if we have a $title and a $price the query will be:
17 | * 'SELECT * FROM book WHERE title = ? AND price < ? '
18 | * If we only have a $price and a $limit:
19 | * 'SELECT * FROM book WHERE price < ? LIMIT ?'
20 | * The Query Builder works very easy, it simply loops through the array,
21 | * each element is another array inside this main array,
22 | * let's call this inner array a 'piece'.
23 | * A piece can have one, two or three elements.
24 | * If it has one element, the element is simply concatenated to the final query.
25 | * If a piece has two elements, the second element will be
26 | * concatenated only if the first evaluates to TRUE.
27 | * Finally a piece having three elements works the same as a piece with two elements,
28 | * except that it will use the glue provided in the second element
29 | * to concat the value of the third element. The glue acts as a little tube of glue.
30 | * If there is still glue left in the tube (WHERE) it will preserve this
31 | * until it can be applied (so the first AND will be ignored in case of a WHERE condition).
32 | */
33 | R::ext('buildQuery', function($pieces) {
34 | $sql = '';
35 | $glue = NULL;
36 | foreach( $pieces as $piece ) {
37 | $n = count( $piece );
38 | switch( $n ) {
39 | case 1:
40 | $sql .= " {$piece[0]} ";
41 | break;
42 | case 2:
43 | $glue = NULL;
44 | if (!is_null($piece[0])) $sql .= " {$piece[1]} ";
45 | break;
46 | case 3:
47 | $glue = ( is_null( $glue ) ) ? $piece[1] : $glue;
48 | if (!is_null($piece[0])) {
49 | $sql .= " {$glue} {$piece[2]} ";
50 | $glue = NULL;
51 | }
52 | break;
53 | }
54 | }
55 | return $sql;
56 | });
57 |
--------------------------------------------------------------------------------
/RedBeanPHP/Plugin/put_your_plugins_here.txt:
--------------------------------------------------------------------------------
1 | This folder has been reserved for your plugins
2 |
3 |
--------------------------------------------------------------------------------
/RedBeanPHP/R.php:
--------------------------------------------------------------------------------
1 | driverDetails;
38 | }
39 |
40 | /**
41 | * @param array $driverDetails
42 | *
43 | * @return void
44 | */
45 | public function setDriverDetails($driverDetails)
46 | {
47 | $this->driverDetails = $driverDetails;
48 | }
49 |
50 | /**
51 | * Returns an ANSI-92 compliant SQL state.
52 | *
53 | * @return string
54 | */
55 | public function getSQLState()
56 | {
57 | return $this->sqlState;
58 | }
59 |
60 | /**
61 | * Returns the raw SQL STATE, possibly compliant with
62 | * ANSI SQL error codes - but this depends on database driver.
63 | *
64 | * @param string $sqlState SQL state error code
65 | *
66 | * @return void
67 | */
68 | public function setSQLState( $sqlState )
69 | {
70 | $this->sqlState = $sqlState;
71 | }
72 |
73 | /**
74 | * To String prints both code and SQL state.
75 | *
76 | * @return string
77 | */
78 | public function __toString()
79 | {
80 | return '[' . $this->getSQLState() . '] - ' . $this->getMessage()."\n".
81 | 'trace: ' . $this->getTraceAsString();
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/RedBeanPHP/SimpleModel.php:
--------------------------------------------------------------------------------
1 | bean = $bean;
42 | }
43 |
44 | /**
45 | * Magic Getter to make the bean properties available from
46 | * the $this-scope.
47 | *
48 | * @note this method returns a value, not a reference!
49 | * To obtain a reference unbox the bean first!
50 | *
51 | * @param string $prop property to get
52 | *
53 | * @return mixed
54 | */
55 | public function __get( $prop )
56 | {
57 | return $this->bean->$prop;
58 | }
59 |
60 | /**
61 | * Magic Setter.
62 | * Sets the value directly as a bean property.
63 | *
64 | * @param string $prop property to set value of
65 | * @param mixed $value value to set
66 | *
67 | * @return void
68 | */
69 | public function __set( $prop, $value )
70 | {
71 | $this->bean->$prop = $value;
72 | }
73 |
74 | /**
75 | * Isset implementation.
76 | * Implements the isset function for array-like access.
77 | *
78 | * @param string $key key to check
79 | *
80 | * @return boolean
81 | */
82 | public function __isset( $key )
83 | {
84 | return isset( $this->bean->$key );
85 | }
86 |
87 | /**
88 | * Box the bean using the current model.
89 | * This method wraps the current bean in this model.
90 | * This method can be reached using FUSE through a simple
91 | * OODBBean. The method returns a RedBeanPHP Simple Model.
92 | * This is useful if you would like to rely on PHP type hinting.
93 | * You can box your beans before passing them to functions or methods
94 | * with typed parameters.
95 | *
96 | * Note about beans vs models:
97 | * Use unbox to obtain the bean powering the model. If you want to use bean functionality,
98 | * you should -always- unbox first. While some functionality (like magic get/set) is
99 | * available in the model, this is just read-only. To use a model as a typical RedBean
100 | * OODBBean you should always unbox the model to a bean. Models are meant to
101 | * expose only domain logic added by the developer (business logic, no ORM logic).
102 | *
103 | * @return SimpleModel|SimpleModelInterface
104 | */
105 | public function box()
106 | {
107 | return $this;
108 | }
109 |
110 | /**
111 | * Unbox the bean from the model.
112 | * This method returns the bean inside the model.
113 | *
114 | * Note about beans vs models:
115 | * Use unbox to obtain the bean powering the model. If you want to use bean functionality,
116 | * you should -always- unbox first. While some functionality (like magic get/set) is
117 | * available in the model, this is just read-only. To use a model as a typical RedBean
118 | * OODBBean you should always unbox the model to a bean. Models are meant to
119 | * expose only domain logic added by the developer (business logic, no ORM logic).
120 | *
121 | * @return OODBBean
122 | */
123 | public function unbox()
124 | {
125 | return $this->bean;
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/RedBeanPHP/SimpleModelHelper.php:
--------------------------------------------------------------------------------
1 | $eventName();
40 | }
41 |
42 | /**
43 | * Attaches the FUSE event listeners. Now the Model Helper will listen for
44 | * CRUD events. If a CRUD event occurs it will send a signal to the model
45 | * that belongs to the CRUD bean and this model will take over control from
46 | * there. This method will attach the following event listeners to the observable:
47 | *
48 | * - 'update' (gets called by R::store, before the records gets inserted / updated)
49 | * - 'after_update' (gets called by R::store, after the records have been inserted / updated)
50 | * - 'open' (gets called by R::load, after the record has been retrieved)
51 | * - 'delete' (gets called by R::trash, before deletion of record)
52 | * - 'after_delete' (gets called by R::trash, after deletion)
53 | * - 'dispense' (gets called by R::dispense)
54 | *
55 | * For every event type, this method will register this helper as a listener.
56 | * The observable will notify the listener (this object) with the event ID and the
57 | * affected bean. This helper will then process the event (onEvent) by invoking
58 | * the event on the bean. If a bean offers a method with the same name as the
59 | * event ID, this method will be invoked.
60 | *
61 | * @param Observable $observable object to observe
62 | *
63 | * @return void
64 | */
65 | public function attachEventListeners( Observable $observable )
66 | {
67 | foreach ( array( 'update', 'open', 'delete', 'after_delete', 'after_update', 'dispense' ) as $eventID ) {
68 | $observable->addEventListener( $eventID, $this );
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/RedBeanPHP/SimpleModelInterface.php:
--------------------------------------------------------------------------------
1 | box();
35 | }
36 | }
--------------------------------------------------------------------------------
/RedBeanPHP/Util/ArrayTool.php:
--------------------------------------------------------------------------------
1 |
39 | * R::genSlots( array( 'a', 'b' ) );
40 | *
41 | *
42 | * The statement in the example will produce the string:
43 | * '?,?'.
44 | *
45 | * Another example, using a template string:
46 | *
47 | *
48 | * R::genSlots( array('a', 'b'), ' IN( %s ) ' );
49 | *
50 | *
51 | * The statement in the example will produce the string:
52 | * ' IN( ?,? ) '.
53 | *
54 | * @param array $array array to generate question mark slots for
55 | * @param string|NULL $template template to use
56 | *
57 | * @return string
58 | */
59 | public static function genSlots( $array, $template = NULL )
60 | {
61 | $str = count( $array ) ? implode( ',', array_fill( 0, count( $array ), '?' ) ) : '';
62 | return ( is_null( $template ) || $str === '' ) ? $str : sprintf( $template, $str );
63 | }
64 |
65 | /**
66 | * Flattens a multi dimensional bindings array for use with genSlots().
67 | *
68 | * Usage:
69 | *
70 | *
71 | * R::flat( array( 'a', array( 'b' ), 'c' ) );
72 | *
73 | *
74 | * produces an array like: [ 'a', 'b', 'c' ]
75 | *
76 | * @param array $array array to flatten
77 | * @param array $result result array parameter (for recursion)
78 | *
79 | * @return array
80 | */
81 | public static function flat( $array, $result = array() )
82 | {
83 | foreach( $array as $value ) {
84 | if ( is_array( $value ) ) $result = self::flat( $value, $result );
85 | else $result[] = $value;
86 | }
87 | return $result;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/RedBeanPHP/Util/Diff.php:
--------------------------------------------------------------------------------
1 | toolbox = $toolbox;
41 | }
42 |
43 | /**
44 | * Calculates a diff between two beans (or arrays of beans).
45 | * The result of this method is an array describing the differences of the second bean compared to
46 | * the first, where the first bean is taken as reference. The array is keyed by type/property, id and property name, where
47 | * type/property is either the type (in case of the root bean) or the property of the parent bean where the type resides.
48 | * The diffs are mainly intended for logging, you cannot apply these diffs as patches to other beans.
49 | * However this functionality might be added in the future.
50 | *
51 | * The keys of the array can be formatted using the $format parameter.
52 | * A key will be composed of a path (1st), id (2nd) and property (3rd).
53 | * Using printf-style notation you can determine the exact format of the key.
54 | * The default format will look like:
55 | *
56 | * 'book.1.title' => array( , )
57 | *
58 | * If you only want a simple diff of one bean and you don't care about ids,
59 | * you might pass a format like: '%1$s.%3$s' which gives:
60 | *
61 | * 'book.1.title' => array( , )
62 | *
63 | * The filter parameter can be used to set filters, it should be an array
64 | * of property names that have to be skipped. By default this array is filled with
65 | * two strings: 'created' and 'modified'.
66 | *
67 | * @param OODBBean|array $beans reference beans
68 | * @param OODBBean|array $others beans to compare
69 | * @param array $filters names of properties of all beans to skip
70 | * @param string $format the format of the key, defaults to '%s.%s.%s'
71 | * @param string|NULL $type type/property of bean to use for key generation
72 | *
73 | * @return array
74 | */
75 | public function diff( $beans, $others, $filters = array( 'created', 'modified' ), $format = '%s.%s.%s', $type = NULL )
76 | {
77 | $diff = array();
78 |
79 | if ( !is_array( $beans ) ) $beans = array( $beans );
80 | $beansI = array();
81 | foreach ( $beans as $bean ) {
82 | if ( !( $bean instanceof OODBBean ) ) continue;
83 | $beansI[$bean->id] = $bean;
84 | }
85 |
86 | if ( !is_array( $others ) ) $others = array( $others );
87 | $othersI = array();
88 | foreach ( $others as $other ) {
89 | if ( !( $other instanceof OODBBean ) ) continue;
90 | $othersI[$other->id] = $other;
91 | }
92 |
93 | if ( count( $beansI ) == 0 || count( $othersI ) == 0 ) {
94 | return array();
95 | }
96 |
97 | $type = $type != NULL ? $type : reset($beansI)->getMeta( 'type' );
98 |
99 | foreach( $beansI as $id => $bean ) {
100 | if ( !isset( $othersI[$id] ) ) continue;
101 | $other = $othersI[$id];
102 | foreach( $bean as $property => $value ) {
103 | if ( in_array( $property, $filters ) ) continue;
104 | $key = vsprintf( $format, array( $type, $bean->id, $property ) );
105 | $compare = $other->{$property};
106 | if ( !is_object( $value ) && !is_array( $value ) && $value != $compare ) {
107 | $diff[$key] = array( $value, $compare );
108 | } else {
109 | $diff = array_merge( $diff, $this->diff( $value, $compare, $filters, $format, $key ) );
110 | }
111 | }
112 | }
113 |
114 | return $diff;
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/RedBeanPHP/Util/Dump.php:
--------------------------------------------------------------------------------
1 |
38 | * echo R::dump( $bean );
39 | *
40 | *
41 | * The example shows how to echo the result of a simple
42 | * dump. This will print the string representation of the
43 | * specified bean to the screen, limiting the output per bean
44 | * to 35 characters to improve readability. Nested beans will
45 | * also be dumped.
46 | *
47 | * @param OODBBean|array $data either a bean or an array of beans
48 | *
49 | * @return array
50 | */
51 | public static function dump( $data )
52 | {
53 | $array = array();
54 | if ( $data instanceof OODBBean ) {
55 | $str = strval( $data );
56 | if (strlen($str) > 35) {
57 | $beanStr = substr( $str, 0, 35 ).'... ';
58 | } else {
59 | $beanStr = $str;
60 | }
61 | return $beanStr;
62 | }
63 | if ( is_array( $data ) ) {
64 | foreach( $data as $key => $item ) {
65 | $array[$key] = self::dump( $item );
66 | }
67 | }
68 | return $array;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/RedBeanPHP/Util/Either.php:
--------------------------------------------------------------------------------
1 |
35 | * $author = $text
36 | * ->either()
37 | * ->page
38 | * ->book
39 | * ->autor
40 | * ->name
41 | * ->or('unknown');
42 | *
43 | *
44 | * The Either-class lets you access bean properties without having to do
45 | * NULL-checks. The mechanism resembles the use of the ?? somewhat but
46 | * offers backward compatibility with older PHP versions. The mechanism also works
47 | * on arrays.
48 | *
49 | *
50 | * $budget = $company
51 | * ->either()
52 | * ->sharedProject
53 | * ->first()
54 | * ->budget
55 | * ->or(0);
56 | *
57 | */
58 | public function __construct($result) {
59 | $this->result = $result;
60 | }
61 |
62 | /**
63 | * Extracts a value from the wrapped object and stores
64 | * it in the internal result object. If the desired
65 | * value cannot be found, the internal result object will be set
66 | * to NULL. Chainable.
67 | *
68 | * @param string $something name of the property you wish to extract the value of
69 | *
70 | * @return self
71 | */
72 | public function __get($something) {
73 | if (is_object($this->result)) {
74 | $this->result = $this->result->{$something};
75 | } else {
76 | $this->result = NULL;
77 | }
78 | return $this;
79 | }
80 |
81 | /**
82 | * Extracts the first element of the array in the internal result
83 | * object and stores it as the new value of the internal result object.
84 | * Chainable.
85 | *
86 | * @return self
87 | */
88 | public function first() {
89 | if (is_array($this->result)) {
90 | reset($this->result);
91 | $key = key($this->result);
92 | if (isset($this->result[$key])) {
93 | $this->result = $this->result[$key];
94 | } else {
95 | $this->result = NULL;
96 | }
97 | }
98 | return $this;
99 | }
100 |
101 | /**
102 | * Extracts the last element of the array in the internal result
103 | * object and stores it as the new value of the internal result object.
104 | * Chainable.
105 | *
106 | * @return self
107 | */
108 | public function last() {
109 | if (is_array($this->result)) {
110 | end($this->result);
111 | $key = key($this->result);
112 | if (isset($this->result[$key])) {
113 | $this->result = $this->result[$key];
114 | } else {
115 | $this->result = NULL;
116 | }
117 | }
118 | return $this;
119 | }
120 |
121 | /**
122 | * Extracts the specified element of the array in the internal result
123 | * object and stores it as the new value of the internal result object.
124 | * Chainable.
125 | *
126 | * @return self
127 | */
128 | public function index( $key = 0 ) {
129 | if (is_array($this->result)) {
130 | if (isset($this->result[$key])) {
131 | $this->result = $this->result[$key];
132 | } else {
133 | $this->result = NULL;
134 | }
135 | }
136 | return $this;
137 | }
138 |
139 | /**
140 | * Resolves the Either-instance to a final value, either the value
141 | * contained in the internal result object or the value specified
142 | * in the or() function.
143 | *
144 | * @param mixed $value value to resolve to if internal result equals NULL
145 | *
146 | * @return mixed
147 | */
148 | public function _or( $value ) {
149 | $reference = (is_null($this->result)) ? $value : $this->result;
150 | return $reference;
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/RedBeanPHP/Util/Feature.php:
--------------------------------------------------------------------------------
1 |
60 | * R::useFeatureSet( 'novice/latest' );
61 | *
62 | *
63 | * @param string $label label
64 | *
65 | * @return void
66 | */
67 | public static function feature( $label ) {
68 | switch( $label ) {
69 | case self::C_FEATURE_NOVICE_LATEST:
70 | case self::C_FEATURE_NOVICE_5_4:
71 | case self::C_FEATURE_NOVICE_5_5:
72 | OODBBean::useFluidCount( TRUE );
73 | R::noNuke( TRUE );
74 | R::setAllowHybridMode( FALSE );
75 | R::useISNULLConditions( TRUE );
76 | break;
77 | case self::C_FEATURE_LATEST:
78 | case self::C_FEATURE_5_4:
79 | case self::C_FEATURE_5_5:
80 | OODBBean::useFluidCount( TRUE );
81 | R::noNuke( FALSE );
82 | R::setAllowHybridMode( TRUE );
83 | R::useISNULLConditions( TRUE );
84 | break;
85 | case self::C_FEATURE_NOVICE_5_3:
86 | OODBBean::useFluidCount( TRUE );
87 | R::noNuke( TRUE );
88 | R::setAllowHybridMode( FALSE );
89 | R::useISNULLConditions( FALSE );
90 | break;
91 | case self::C_FEATURE_5_3:
92 | OODBBean::useFluidCount( TRUE );
93 | R::noNuke( FALSE );
94 | R::setAllowHybridMode( FALSE );
95 | R::useISNULLConditions( FALSE );
96 | break;
97 | case self::C_FEATURE_ORIGINAL:
98 | OODBBean::useFluidCount( TRUE );
99 | R::noNuke( FALSE );
100 | R::setAllowHybridMode( FALSE );
101 | R::useISNULLConditions( FALSE );
102 | break;
103 | default:
104 | throw new \Exception("Unknown feature set label.");
105 | break;
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/RedBeanPHP/Util/Look.php:
--------------------------------------------------------------------------------
1 | toolbox = $toolbox;
41 | }
42 |
43 | /**
44 | * Takes an full SQL query with optional bindings, a series of keys, a template
45 | * and optionally a filter function and glue and assembles a view from all this.
46 | * This is the fastest way from SQL to view. Typically this function is used to
47 | * generate pulldown (select tag) menus with options queried from the database.
48 | *
49 | * Usage:
50 | *
51 | *
52 | * $htmlPulldown = R::look(
53 | * 'SELECT * FROM color WHERE value != ? ORDER BY value ASC',
54 | * [ 'g' ],
55 | * [ 'value', 'name' ],
56 | * '',
57 | * 'strtoupper',
58 | * "\n"
59 | * );
60 | *
61 | *
62 | * The example above creates an HTML fragment like this:
63 | *
64 | *
65 | *
66 | *
67 | * to pick a color from a palette. The HTML fragment gets constructed by
68 | * an SQL query that selects all colors that do not have value 'g' - this
69 | * excludes green. Next, the bean properties 'value' and 'name' are mapped to the
70 | * HTML template string, note that the order here is important. The mapping and
71 | * the HTML template string follow vsprintf-rules. All property values are then
72 | * passed through the specified filter function 'strtoupper' which in this case
73 | * is a native PHP function to convert strings to uppercase characters only.
74 | * Finally the resulting HTML fragment strings are glued together using a
75 | * newline character specified in the last parameter for readability.
76 | *
77 | * In previous versions of RedBeanPHP you had to use:
78 | * R::getLook()->look() instead of R::look(). However to improve useability of the
79 | * library the look() function can now directly be invoked from the facade.
80 | *
81 | * @param string $sql query to execute
82 | * @param array $bindings parameters to bind to slots mentioned in query or an empty array
83 | * @param array $keys names in result collection to map to template
84 | * @param string $template HTML template to fill with values associated with keys, use printf notation (i.e. %s)
85 | * @param callable $filter function to pass values through (for translation for instance)
86 | * @param string $glue optional glue to use when joining resulting strings
87 | *
88 | * @return string
89 | */
90 | public function look( $sql, $bindings = array(), $keys = array( 'selected', 'id', 'name' ), $template = '', $filter = 'trim', $glue = '' )
91 | {
92 | $adapter = $this->toolbox->getDatabaseAdapter();
93 | $lines = array();
94 | $rows = $adapter->get( $sql, $bindings );
95 | foreach( $rows as $row ) {
96 | $values = array();
97 | foreach( $keys as $key ) {
98 | if (!empty($filter)) {
99 | $values[] = call_user_func_array( $filter, array( $row[$key] ) );
100 | } else {
101 | $values[] = $row[$key];
102 | }
103 | }
104 | $lines[] = vsprintf( $template, $values );
105 | }
106 | $string = implode( $glue, $lines );
107 | return $string;
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/RedBeanPHP/Util/MatchUp.php:
--------------------------------------------------------------------------------
1 | toolbox = $toolbox;
44 | }
45 |
46 | /**
47 | * MatchUp is a powerful productivity boosting method that can replace simple control
48 | * scripts with a single RedBeanPHP command. Typically, matchUp() is used to
49 | * replace login scripts, token generation scripts and password reset scripts.
50 | * The MatchUp method takes a bean type, an SQL query snippet (starting at the WHERE clause),
51 | * SQL bindings, a pair of task arrays and a bean reference.
52 | *
53 | * If the first 3 parameters match a bean, the first task list will be considered,
54 | * otherwise the second one will be considered. On consideration, each task list,
55 | * an array of keys and values will be executed. Every key in the task list should
56 | * correspond to a bean property while every value can either be an expression to
57 | * be evaluated or a closure (PHP 5.3+). After applying the task list to the bean
58 | * it will be stored. If no bean has been found, a new bean will be dispensed.
59 | *
60 | * This method will return TRUE if the bean was found and FALSE if not AND
61 | * there was a NOT-FOUND task list. If no bean was found AND there was also
62 | * no second task list, NULL will be returned.
63 | *
64 | * To obtain the bean, pass a variable as the sixth parameter.
65 | * The function will put the matching bean in the specified variable.
66 | *
67 | * Usage (this example resets a password in one go):
68 | *
69 | *
70 | * $newpass = '1234';
71 | * $didResetPass = R::matchUp(
72 | * 'account', ' token = ? AND tokentime > ? ',
73 | * [ $token, time()-100 ],
74 | * [ 'pass' => $newpass, 'token' => '' ],
75 | * NULL,
76 | * $account );
77 | *
78 | *
79 | * @param string $type type of bean you're looking for
80 | * @param string $sql SQL snippet (starting at the WHERE clause, omit WHERE-keyword)
81 | * @param array $bindings array of parameter bindings for SQL snippet
82 | * @param array|NULL $onFoundDo task list to be considered on finding the bean
83 | * @param array|NULL $onNotFoundDo task list to be considered on NOT finding the bean
84 | * @param OODBBean|NULL &$bean reference to obtain the found bean
85 | *
86 | * @return bool|NULL
87 | */
88 | public function matchUp( $type, $sql, $bindings = array(), $onFoundDo = NULL, $onNotFoundDo = NULL, &$bean = NULL )
89 | {
90 | $finder = new Finder( $this->toolbox );
91 | $oodb = $this->toolbox->getRedBean();
92 | $bean = $finder->findOne( $type, $sql, $bindings );
93 | if ( $bean && $onFoundDo ) {
94 | foreach( $onFoundDo as $property => $value ) {
95 | if ( function_exists('is_callable') && is_callable( $value ) ) {
96 | $bean[$property] = call_user_func_array( $value, array( $bean ) );
97 | } else {
98 | $bean[$property] = $value;
99 | }
100 | }
101 | $oodb->store( $bean );
102 | return TRUE;
103 | }
104 | if ( $onNotFoundDo ) {
105 | $bean = $oodb->dispense( $type );
106 | foreach( $onNotFoundDo as $property => $value ) {
107 | if ( function_exists('is_callable') && is_callable( $value ) ) {
108 | $bean[$property] = call_user_func_array( $value, array( $bean ) );
109 | } else {
110 | $bean[$property] = $value;
111 | }
112 | }
113 | $oodb->store( $bean );
114 | return FALSE;
115 | }
116 | return NULL;
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/RedBeanPHP/Util/MultiLoader.php:
--------------------------------------------------------------------------------
1 |
41 | * list( $author, $bio ) = R::loadMulti( 'author, bio', $id );
42 | *
43 | *
44 | * @param OODB $oodb OODB object
45 | * @param string|array $types the set of types to load at once
46 | * @param mixed $id the common ID
47 | *
48 | * @return OODBBean[]
49 | */
50 | public static function load( OODB $oodb, $types, $id )
51 | {
52 | if ( is_string( $types ) ) $types = explode( ',', $types );
53 | if ( !is_array( $types ) ) return array();
54 | foreach ( $types as $k => $typeItem ) {
55 | $types[$k] = $oodb->load( $typeItem, $id );
56 | }
57 | return $types;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/RedBeanPHP/Util/QuickExport.php:
--------------------------------------------------------------------------------
1 | toolbox = $toolbox;
45 | }
46 |
47 | /**
48 | * Makes csv() testable.
49 | *
50 | * @param string $name
51 | * @param mixed $arg1
52 | * @param boolean $arg2
53 | *
54 | * @return mixed
55 | */
56 | public static function operation( $name, $arg1, $arg2 = TRUE ) {
57 | $out = '';
58 | switch( $name ) {
59 | case 'test':
60 | self::$test = (boolean) $arg1;
61 | break;
62 | case 'header':
63 | $out = ( self::$test ) ? $arg1 : header( $arg1, $arg2 );
64 | break;
65 | case 'readfile':
66 | $out = ( self::$test ) ? file_get_contents( $arg1 ) : readfile( $arg1 );
67 | break;
68 | case 'exit':
69 | $out = ( self::$test ) ? 'exit' : exit();
70 | break;
71 | }
72 | return $out;
73 | }
74 |
75 | /**
76 | * Exposes the result of the specified SQL query as a CSV file.
77 | *
78 | * Usage:
79 | *
80 | *
81 | * R::csv( 'SELECT
82 | * `name`,
83 | * population
84 | * FROM city
85 | * WHERE region = :region ',
86 | * array( ':region' => 'Denmark' ),
87 | * array( 'city', 'population' ),
88 | * '/tmp/cities.csv'
89 | * );
90 | *
91 | *
92 | * The command above will select all cities in Denmark
93 | * and create a CSV with columns 'city' and 'population' and
94 | * populate the cells under these column headers with the
95 | * names of the cities and the population numbers respectively.
96 | *
97 | * @param string $sql SQL query to expose result of
98 | * @param array $bindings parameter bindings
99 | * @param array $columns column headers for CSV file
100 | * @param string $path path to save CSV file to
101 | * @param boolean $output TRUE to output CSV directly using readfile
102 | * @param array $options delimiter, quote and escape character respectively
103 | *
104 | * @return string|NULL
105 | */
106 | public function csv( $sql = '', $bindings = array(), $columns = NULL, $path = '/tmp/redexport_%s.csv', $output = TRUE, $options = array(',','"','\\') )
107 | {
108 | list( $delimiter, $enclosure, $escapeChar ) = $options;
109 | $path = sprintf( $path, date('Ymd_his') );
110 | $handle = fopen( $path, 'w' );
111 | if ($columns) if (PHP_VERSION_ID>=505040) fputcsv($handle, $columns, $delimiter, $enclosure, $escapeChar ); else fputcsv($handle, $columns, $delimiter, $enclosure );
112 | $cursor = $this->toolbox->getDatabaseAdapter()->getCursor( $sql, $bindings );
113 | while( $row = $cursor->getNextItem() ) {
114 | if (PHP_VERSION_ID>=505040) fputcsv($handle, $row, $delimiter, $enclosure, $escapeChar ); else fputcsv($handle, $row, $delimiter, $enclosure );
115 | }
116 | fclose($handle);
117 | if ( $output ) {
118 | $file = basename($path);
119 | $out = self::operation('header',"Pragma: public");
120 | $out .= self::operation('header',"Expires: 0");
121 | $out .= self::operation('header',"Cache-Control: must-revalidate, post-check=0, pre-check=0");
122 | $out .= self::operation('header',"Cache-Control: private", FALSE );
123 | $out .= self::operation('header',"Content-Type: text/csv");
124 | $out .= self::operation('header',"Content-Disposition: attachment; filename={$file}" );
125 | $out .= self::operation('header',"Content-Transfer-Encoding: binary");
126 | $out .= self::operation('readfile',$path );
127 | @unlink( $path );
128 | self::operation('exit', FALSE);
129 | return $out;
130 | }
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/RedBeanPHP/Util/Transaction.php:
--------------------------------------------------------------------------------
1 |
43 | * $from = 1;
44 | * $to = 2;
45 | * $amount = 300;
46 | *
47 | * R::transaction(function() use($from, $to, $amount)
48 | * {
49 | * $accountFrom = R::load('account', $from);
50 | * $accountTo = R::load('account', $to);
51 | * $accountFrom->money -= $amount;
52 | * $accountTo->money += $amount;
53 | * R::store($accountFrom);
54 | * R::store($accountTo);
55 | * });
56 | *
57 | *
58 | * @param Adapter $adapter Database Adapter providing transaction mechanisms.
59 | * @param callable $callback Closure (or other callable) with the transaction logic
60 | *
61 | * @return mixed
62 | */
63 | public static function transaction( Adapter $adapter, $callback )
64 | {
65 | if ( !is_callable( $callback ) ) {
66 | throw new RedException( 'R::transaction needs a valid callback.' );
67 | }
68 |
69 | static $depth = 0;
70 | $result = null;
71 | try {
72 | if ( $depth == 0 ) {
73 | $adapter->startTransaction();
74 | }
75 | $depth++;
76 | $result = call_user_func( $callback ); //maintain 5.2 compatibility
77 | $depth--;
78 | if ( $depth == 0 ) {
79 | $adapter->commit();
80 | }
81 | } catch ( \Exception $exception ) {
82 | $depth--;
83 | if ( $depth == 0 ) {
84 | $adapter->rollback();
85 | }
86 | throw $exception;
87 | }
88 | return $result;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/RedBeanPHP/loader.php:
--------------------------------------------------------------------------------
1 | =5.3.4"
16 | },
17 | "autoload": {
18 | "psr-4": {
19 | "RedBeanPHP\\" : "RedBeanPHP"
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/p533patch.php:
--------------------------------------------------------------------------------
1 | 0) {
12 | echo 'Applied patch for PHP < 5.3.3';
13 | echo PHP_EOL;
14 | exit;
15 | } else {
16 | echo 'Somthing went wrong.';
17 | echo PHP_EOL;
18 | exit;
19 | }
20 |
--------------------------------------------------------------------------------
/replica2-win.php:
--------------------------------------------------------------------------------
1 | buildFromDirectory('./build');
28 | echo "Done.\n";
29 |
30 | echo "Adding stub... ";
31 | $phar->setStub($phar->createDefaultStub("loader.php"));
32 | echo "Done.\n";
33 |
34 | echo "Your PHAR file has been generated.\n";
35 |
--------------------------------------------------------------------------------
/replica2.php:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | $code, 'rb-mysql.php' => $codeMySQL, 'rb-postgres.php' => $codePostgres, 'rb-sqlite.php' => $codeSQLite );
112 | foreach( $files as $file => $content ) {
113 | echo 'Okay, seems we have all the code.. now writing file: ', $file ,PHP_EOL;
114 | $b = file_put_contents($file, $content);
115 | echo 'Written: ',$b,' bytes.',PHP_EOL;
116 | if ($b > 0) {
117 | echo 'Done!' ,PHP_EOL;
118 | } else {
119 | echo 'Hm, something seems to have gone wrong... ',PHP_EOL;
120 | }
121 | }
122 |
123 |
124 |
125 |
--------------------------------------------------------------------------------
/run_all_tests.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | php replica2.php
3 | cp rb.php testing/cli/testcontainer/rb.php
4 | cd testing
5 | cd cli
6 | php runtests.php
7 |
--------------------------------------------------------------------------------
/run_single_test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | if [ -z "$1" ]
3 | then
4 | echo "Please enter the name of a test suite, example: Blackhole/Version"
5 | exit
6 | fi
7 | php replica2.php
8 | cp rb.php testing/cli/testcontainer/rb.php
9 | cd testing
10 | cd cli
11 | php runtests.php $1
12 |
--------------------------------------------------------------------------------
/test-dist.ini:
--------------------------------------------------------------------------------
1 | ; Test suite database config
2 | ; Rename this file to test.ini if you are done
3 |
4 | [mysql]
5 | host = "localhost"
6 | schema = "oodb"
7 | user = "root"
8 | pass = "password"
9 |
10 | [pgsql]
11 | host = "localhost"
12 | schema = "oodb"
13 | user = "postgres"
14 | pass = "password"
15 |
16 | [sqlite]
17 | file = "/tmp/database.db"
18 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Base.php:
--------------------------------------------------------------------------------
1 | box();
35 | R::trash( $bean );
36 | pass();
37 | $bean = R::dispense( 'boxedbean' );
38 | $bean->sharedBoxbean = R::dispense( 'boxedbean' )->box();
39 | R::store( $bean );
40 | pass();
41 | $bean = R::dispense( 'boxedbean' );
42 | $bean->ownBoxedbean = R::dispense( 'boxedbean' )->box();
43 | R::store( $bean );
44 | pass();
45 | $bean = R::dispense( 'boxedbean' );
46 | $bean->other = R::dispense( 'boxedbean' )->box();
47 | R::store( $bean );
48 | pass();
49 | $bean = R::dispense( 'boxedbean' );
50 | $bean->title = 'MyBean';
51 | $box = $bean->box();
52 | asrt( ( $box instanceof \Model_Boxedbean ), TRUE );
53 | R::store( $box );
54 | }
55 |
56 | /**
57 | * Test fix for issue #512 - thanks for reporting Bernhard H.
58 | * OODBBean::__toString() implementation only works with C_ERR_IGNORE
59 | *
60 | * @return void
61 | */
62 | public function testToStringIssue512()
63 | {
64 | R::setErrorHandlingFUSE( \RedBeanPHP\OODBBean::C_ERR_FATAL );
65 | $boxedBean = R::dispense( 'boxedbean' );
66 | $str = (string) $boxedBean;
67 | asrt( $str, '{"id":0}' ); //no fatal error
68 | R::setErrorHandlingFUSE( FALSE );
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Base/Chill.php:
--------------------------------------------------------------------------------
1 | col1 = '1';
35 | $bean->col2 = '2';
36 | R::store( $bean );
37 | asrt( count( R::getWriter()->getColumns( 'bean' ) ), 3 );
38 | $bean->col3 = '3';
39 | R::store( $bean );
40 | asrt( count( R::getWriter()->getColumns( 'bean' ) ), 4 );
41 | R::freeze( array( 'umbrella' ) );
42 | $bean->col4 = '4';
43 | R::store( $bean );
44 | asrt( count( R::getWriter()->getColumns( 'bean' ) ), 5 );
45 | R::freeze( array( 'bean' ) );
46 | $bean->col5 = '5';
47 | try {
48 | R::store( $bean );
49 | fail();
50 | } catch (\Exception $e ) {
51 | pass();
52 | }
53 | asrt( count( R::getWriter()->getColumns( 'bean' ) ), 5 );
54 | R::freeze( array() );
55 | $bean->col5 = '5';
56 | R::store( $bean );
57 | asrt( count( R::getWriter()->getColumns( 'bean' ) ), 6 );
58 | }
59 |
60 | /**
61 | * Test whether we cannot add unique constraints on chilled tables,
62 | * otherwise you cannot avoid this from happening when adding beans to the
63 | * shared list :) -- this is almost a theoretical issue however we want it
64 | * to work according to specifications!
65 | *
66 | * @return void
67 | */
68 | public function testDontAddUniqueConstraintForChilledBeanTypes()
69 | {
70 | R::nuke();
71 | $person = R::dispense( 'person' );
72 | $role = R::dispense( 'role' );
73 | $person->sharedRole[] = $role;
74 | R::store( $person );
75 | $person->sharedRole[] = R::dispense( 'role' );
76 | R::store( $person );
77 | $bean = R::getRedBean()->dispense('person_role');
78 | $bean->personId = $person->id;
79 | $bean->roleId = $role->id;
80 | try {
81 | R::store( $bean );
82 | fail();
83 | } catch(\Exception $e) {
84 | pass();
85 | }
86 | asrt(R::count('person_role'), 2);
87 | R::nuke();
88 | $link = R::getRedBean()->dispense('person_role');
89 | $person = R::dispense( 'person' );
90 | $role = R::dispense( 'role' );
91 | $link->person = $person;
92 | $link->role = $role;
93 | R::store( $link );
94 | R::freeze(array('person_role'));
95 | $person->sharedRole[] = R::dispense( 'role' );
96 | R::store( $person );
97 | $bean = R::getRedBean()->dispense('person_role');
98 | $bean->personId = $person->id;
99 | $bean->roleId = $role->id;
100 | try {
101 | R::store( $bean );
102 | pass();
103 | } catch(\Exception $e) {
104 | fail();
105 | }
106 | asrt(R::count('person_role'), 3);
107 | R::freeze( array() ); //set freeze to FALSE and clear CHILL LIST!
108 | }
109 |
110 | /**
111 | * Test whether we can set and reset the chill list and check the contents
112 | * of the chill list.
113 | *
114 | * @return void
115 | */
116 | public function testChillTest()
117 | {
118 | R::freeze( array( 'beer' ) );
119 | $oodb = R::getRedBean();
120 | asrt( $oodb->isChilled( 'beer' ), TRUE );
121 | asrt( $oodb->isChilled( 'wine' ), FALSE );
122 | R::freeze( FALSE );
123 | $oodb = R::getRedBean();
124 | asrt( $oodb->isChilled( 'beer' ), TRUE );
125 | asrt( $oodb->isChilled( 'wine' ), FALSE );
126 | R::freeze( TRUE );
127 | $oodb = R::getRedBean();
128 | asrt( $oodb->isChilled( 'beer' ), TRUE );
129 | asrt( $oodb->isChilled( 'wine' ), FALSE );
130 | R::freeze( array() );
131 | $oodb = R::getRedBean();
132 | asrt( $oodb->isChilled( 'beer' ), FALSE );
133 | asrt( $oodb->isChilled( 'wine' ), FALSE );
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Base/Close.php:
--------------------------------------------------------------------------------
1 | getMessage(), 'Unknown feature set label.' );
47 | }
48 | try {
49 | R::nuke();
50 | fail();
51 | } catch( \Exception $e ) {
52 | asrt( $e->getMessage(), 'The nuke() command has been disabled using noNuke() or R::feature(novice/...).' );
53 | }
54 | R::useFeatureSet('latest');
55 | //Close
56 | R::getDatabaseAdapter()->setOption( 'setInitQuery', NULL );
57 | asrt( R::getDatabaseAdapter()->getDatabase()->isConnected(), TRUE );
58 | R::close();
59 | asrt( R::getDatabaseAdapter()->getDatabase()->isConnected(), FALSE );
60 | }
61 | }
62 |
63 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Base/Either.php:
--------------------------------------------------------------------------------
1 | 'book',
35 | 'title' => 'Socratic Questions',
36 | 'ownPageList' => array(
37 | array(
38 | '_type'=> 'page',
39 | 'ownParagraphList' => array(
40 | array(
41 | '_type'=>'paragraph',
42 | 'text' => 'What is a Bean?',
43 | )
44 | )
45 | )
46 | )
47 | )));
48 | $book = R::load('book', $id);
49 | asrt($book->either()->title->_or('nothing'),'Socratic Questions');
50 | $pageId = R::findOne('page')->id;
51 | asrt($book->either()->ownPageList->index($pageId)->id->_or(0), $pageId);
52 | asrt($book->either()->ownPageList->index($pageId+1)->ownTextList->index(1)->_or(0), 0);
53 | $textId = $book->either()->ownPageList->first()->ownParagraphList->last()->id->_or(0);
54 | asrt($textId > 0, TRUE);
55 | $text = R::load('paragraph', $textId);
56 | asrt($text->either()->page->book->title->_or('nothing'), 'Socratic Questions');
57 | asrt($book->either()->ownPageList->last()->id->_or(-1),$pageId);
58 | asrt($book->either()->ownPageList->id->_or(-1),-1);
59 | asrt($book->either()->ownPageList->first()->ownQuoteList->first()->_or('?'),'?');
60 | }
61 | }
--------------------------------------------------------------------------------
/testing/RedUNIT/Base/Frozen.php:
--------------------------------------------------------------------------------
1 | xownPageList[] = R::dispense( 'page' );
41 | $book->sharedTagList[] = R::dispense( 'tag' );
42 | R::store( $book );
43 | $book = $book->fresh();
44 | R::freeze( TRUE );
45 | $book->xownPageList = array();
46 | R::store( $book );
47 | $book = $book->fresh();
48 | asrt( R::count('page'), 0 );
49 | $book->xownPageList[] = R::dispense( 'page' );
50 | R::store( $book );
51 | $book = $book->fresh();
52 | asrt( R::count('page'), 1 );
53 | $book->xownPageList;
54 | $book->sharedTagList;
55 | R::trash( $book );
56 | asrt( R::count('book'), 0 );
57 | asrt( R::count('page'), 0 );
58 | asrt( R::count('tag'), 1 );
59 | asrt( R::count('book_tag'), 0 );
60 | R::freeze( FALSE );
61 | }
62 |
63 | /**
64 | * Tests whether invalid list checks are
65 | * operational in frozen mode.
66 | *
67 | * @return void
68 | */
69 | public function testInvalidList()
70 | {
71 | R::nuke();
72 | $book = R::dispense( 'book' );
73 | $book->xownPageList[] = R::dispense( 'page' );
74 | $book->sharedTagList[] = R::dispense( 'tag' );
75 | R::store( $book );
76 | R::freeze( TRUE );
77 | $book = R::dispense( 'book' );
78 | $book->xownPageList[] = 'nonsense';
79 | try {
80 | R::store( $book );
81 | fail();
82 | } catch( \Exception $e ) {
83 | pass();
84 | }
85 | R::freeze( FALSE );
86 | }
87 |
88 | /**
89 | * Tests whether loading non-existant beans
90 | * returns the same results in frozen mode.
91 | *
92 | * @return
93 | */
94 | public function testLoadNonExistant()
95 | {
96 | R::nuke();
97 | R::store( R::dispense( 'bean' ) );
98 | R::freeze( TRUE );
99 | $bean = R::load( 'bean', 123 );
100 | R::freeze( FALSE );
101 | asrt( ( $bean instanceof OODBBean ), TRUE );
102 | asrt( $bean->id, 0 );
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Base/Indexes.php:
--------------------------------------------------------------------------------
1 | ownPageList[] = $page;
37 | R::store( $book );
38 | $indexes = getIndexes( 'page' );
39 | asrt( in_array( 'index_foreignkey_page_book', $indexes ), TRUE );
40 | }
41 |
42 | /**
43 | * Tests indexes on parent beans.
44 | *
45 | * @return void
46 | */
47 | public function testIndexCreationParentBean()
48 | {
49 | R::nuke();
50 | $book = R::dispense( 'book' );
51 | $page = R::dispense( 'page' );
52 | $page->book = $book;
53 | R::store( $page );
54 | $indexes = getIndexes( 'page' );
55 | asrt( in_array( 'index_foreignkey_page_book', $indexes ), TRUE );
56 | }
57 |
58 | /**
59 | * Tests indexes on link tables.
60 | *
61 | * @return void
62 | */
63 | public function testIndexCreationMany2Many()
64 | {
65 | R::nuke();
66 | $book = R::dispense( 'book' );
67 | $category = R::dispense( 'category' );
68 | $book->sharedCategoryList[] = $category;
69 | R::store( $book );
70 | $indexes = getIndexes( 'book_category' );
71 | asrt( in_array( 'index_foreignkey_book_category_book', $indexes ), TRUE );
72 | asrt( in_array( 'index_foreignkey_book_category_category', $indexes ), TRUE );
73 | R::nuke();
74 | R::nuke();
75 | $book = R::dispense( 'book' );
76 | $category = R::dispense( 'category' );
77 | $category->sharedBookList[] = $book;
78 | R::store( $category );
79 | $indexes = getIndexes( 'book_category' );
80 | asrt( in_array( 'index_foreignkey_book_category_book', $indexes ), TRUE );
81 | asrt( in_array( 'index_foreignkey_book_category_category', $indexes ), TRUE );
82 | }
83 |
84 | /**
85 | * Tests indexes on aliases.
86 | *
87 | * @return void
88 | */
89 | public function testIndexCreationAlias()
90 | {
91 | R::nuke();
92 | $book = R::dispense( 'book' );
93 | $author = R::dispense( 'author' );
94 | $book->coAuthor = $author;
95 | R::store( $book );
96 | $indexes = getIndexes( 'book' );
97 | asrt( in_array( 'index_foreignkey_book_co_author', $indexes ), TRUE );
98 | R::nuke();
99 | $project = R::dispense( 'project' );
100 | $person = R::dispense( 'person' );
101 | $person->alias( 'teacher' )->ownProject[] = $project;
102 | $person2 = R::dispense( 'person' );
103 | $person2->alias( 'student' )->ownProject[] = $project;
104 | R::store( $person );
105 | $indexes = getIndexes( 'project' );
106 | asrt( in_array( 'index_foreignkey_project_teacher', $indexes ), TRUE );
107 | R::store( $person2 );
108 | $indexes = getIndexes( 'project' );
109 | asrt( in_array( 'index_foreignkey_project_student', $indexes ), TRUE );
110 | }
111 |
112 | /**
113 | * Tests index fails.
114 | *
115 | * @return void
116 | */
117 | public function testIndexCreationFail()
118 | {
119 | R::nuke();
120 | $book = R::dispense( 'book' );
121 | $book->author_id = '999';
122 | R::store( $book );
123 | $indexes = getIndexes( 'book' );
124 | //should just work fine
125 | asrt( in_array( 'index_foreignkey_book_author', $indexes ), TRUE );
126 | //these should just pass, no indexes but no errors as well
127 | R::getWriter()->addIndex( 'book', 'bla', 'nonexist' );
128 | pass();
129 | R::getWriter()->addIndex( 'book', '@#$', 'nonexist' );
130 | pass();
131 | R::getWriter()->addIndex( 'nonexist', 'bla', 'nonexist' );
132 | pass();
133 | $indexesAfter = getIndexes( 'book' );
134 | asrt( count( $indexesAfter ), count( $indexes ) );
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Base/Issue259.php:
--------------------------------------------------------------------------------
1 | desc = 'I am mother';
37 | R::store( $mother );
38 | $child = R::dispense( 'child' );
39 | $child->mother = $mother;
40 | $child->desc = 'I am child';
41 | $id = R::store( $child );
42 | R::findOne( 'child', ' id = ?', array( $id ) );
43 | R::find( 'child', ' id = ? ', array( $id ) );
44 | R::load( 'child', $id );
45 | }
46 | }
47 | /**
48 | * Mock Model.
49 | */
50 | class Model_Mother extends SimpleModel
51 | {
52 | public function open()
53 | {
54 | $bean = $this->bean;
55 | asrt( $this->bean->desc, 'I am mother' );
56 | }
57 | }
58 | /**
59 | * Mock Model.
60 | */
61 | class Model_Child extends SimpleModel
62 | {
63 | public function open()
64 | {
65 | $this->bean->mother;
66 | asrt( $this->bean->desc, 'I am child' );
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Base/Issue303.php:
--------------------------------------------------------------------------------
1 | setAttr( 'invalid.property', 'value' ) );
38 | fail();
39 | } catch (RedException $e ) {
40 | asrt( $e->getMessage(), 'Invalid Bean property: property invalid.property' );
41 | }
42 | try {
43 | R::store( R::dispense( 'invalidbean' )->setAttr( 'property', array() ) );
44 | fail();
45 | } catch (RedException $e ) {
46 | asrt( $e->getMessage(), 'Invalid Bean value: property property' );
47 | }
48 | try {
49 | R::store( R::dispense( 'invalidbean' )->setAttr( 'property', new \stdClass ) );
50 | fail();
51 | } catch (RedException $e ) {
52 | asrt( $e->getMessage(), 'Invalid Bean value: property property' );
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Base/Issue408.php:
--------------------------------------------------------------------------------
1 | post = array(
38 | 'first',
39 | 'second'
40 | );
41 | R::store( $feed );
42 | $rows = R::getAll('SELECT * FROM feed');
43 | asrt( $rows[0]['post'], '["first","second"]' );
44 | $feed = $feed->fresh();
45 | asrt( is_array( $feed->post ), TRUE );
46 | asrt( $feed->post[0], 'first' );
47 | asrt( $feed->post[1], 'second' );
48 | R::store( $feed );
49 | $rows = R::getAll('SELECT * FROM feed');
50 | asrt( $rows[0]['post'], '["first","second"]' );
51 | $feed = R::load( 'feed', $feed->id );
52 | $feed->post[] = 'third';
53 | R::store( $feed );
54 | $rows = R::getAll('SELECT * FROM feed');
55 | asrt( $rows[0]['post'], '["first","second","third"]' );
56 | $feed = $feed->fresh();
57 | asrt( is_array( $feed->post ), TRUE );
58 | asrt( $feed->post[0], 'first' );
59 | asrt( $feed->post[1], 'second' );
60 | asrt( $feed->post[2], 'third' );
61 | //now the catch: can we use export?
62 | //PHP Fatal error: Call to a member function export() on a non-object
63 | $feeds = R::exportAll( R::find( 'feed' ) );
64 | asrt( is_array( $feeds ), TRUE );
65 | $feed = reset( $feeds );
66 | asrt( $feed['post'][0], 'first' );
67 | asrt( $feed['post'][1], 'second' );
68 | asrt( $feed['post'][2], 'third' );
69 | //can we also dup()?
70 | $feedOne = R::findOne( 'feed' );
71 | R::store( R::dup( $feedOne ) );
72 | asrt( R::count( 'feed' ), 2 );
73 | //can we delete?
74 | R::trash( $feedOne );
75 | asrt( R::count( 'feed' ), 1 );
76 | $feedTwo = R::findOne( 'feed' );
77 | $feed = $feedTwo->export();
78 | asrt( $feed['post'][0], 'first' );
79 | asrt( $feed['post'][1], 'second' );
80 | asrt( $feed['post'][2], 'third' );
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Base/Issue841.php:
--------------------------------------------------------------------------------
1 | name = 'TAG_'.$i;
37 | R::store($tag);
38 | }
39 | $record = R::dispense('record');
40 | $record->point = rand(-100,-1);
41 | $record->sharedTagList[] = R::load('tag',2);
42 | R::store($record);
43 | asrt(count($record->sharedTagList),1);
44 | $record = R::load('record',1);
45 | $record->sharedTagList = array();
46 | R::store($record);
47 | $record = R::load('record',1);
48 | asrt(count($record->sharedTagList),0);
49 | R::bindFunc( 'read', 'record.point', null );
50 | R::bindFunc( 'write', 'record.point', null );
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Base/Issue90.php:
--------------------------------------------------------------------------------
1 | name = 'a';
35 | $f = R::dispense( 'bottle' );
36 | $s->ownBottle[] = $f;
37 | R::store( $s );
38 | $s2 = R::dispense( 'box' );
39 | $s2->name = 'a';
40 | R::store( $s2 );
41 | R::trash( $s2 );
42 | pass();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Base/Keywords.php:
--------------------------------------------------------------------------------
1 | $k = $k;
59 | $id = R::store( $bean );
60 | $bean = R::load( $k, $id );
61 | $bean2 = R::dispense( 'other' );
62 | $bean2->name = $k;
63 | $bean->bean = $bean2;
64 | $bean->ownBean[] = $bean2;
65 | $bean->sharedBean[] = $bean2;
66 | $id = R::store( $bean );
67 | R::trash( $bean );
68 | pass();
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Base/Largenum.php:
--------------------------------------------------------------------------------
1 | name = 'big number';
35 | R::store( $number );
36 | //This should not cause an error... (some people use LIMIT 0, HUGE to simulate OFFSET on MYSQL).
37 | $beans = R::findAll( 'number', ' LIMIT ? ', array( PHP_INT_MAX ) );
38 | asrt( is_array( $beans ), TRUE );
39 | asrt( count( $beans ), 1 );
40 | pass();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Base/Namedparams.php:
--------------------------------------------------------------------------------
1 | title = 'book';
38 | $book->sharedPage[] = $page;
39 | R::store($book);
40 | //should not give error like: Uncaught [HY093] - SQLSTATE[HY093]: Invalid parameter number: mixed named and positional parameters
41 | $books = $page->withCondition(' title = :title ', array( ':title' => 'book' ) )->sharedBook;
42 | asrt( count( $books ), 1 );
43 | //should not give error...
44 | $books = $page->withCondition( ' title = :title ', array( ':title' => 'book' ) )->sharedBook;
45 | asrt( count( $books ), 1 );
46 | R::nuke();
47 | $book = R::dispense( 'book' );
48 | $page = R::dispense( 'page' );
49 | $book->title = 'book';
50 | $book->comment = 'comment';
51 | $page->title = 'page';
52 | $book->ownPage[] = $page;
53 | R::store( $book );
54 | //should also not give error..
55 | $count = $book->countOwn( 'page' );
56 | asrt( $count, 1 );
57 | $book = $book->fresh();
58 | //should also not give error..
59 | $count = $book->withCondition( ' title = ? ', array( 'page' ) )->countOwn( 'page' );
60 | asrt( $count, 1 );
61 | $book = $book->fresh();
62 | //should also not give error..
63 | $count = $book->withCondition( ' title = :title ', array( ':title' => 'page' ) )->countOwn( 'page' );
64 | asrt( $count, 1 );
65 | $book = $book->fresh();
66 | $pages = $book->withCondition( ' title = :title ', array( ':title' => 'page' ) )->ownPage;
67 | asrt( count( $pages ), 1 );
68 | //test with duplicate slots...
69 | $page = reset( $pages );
70 | $page2 = R::dispense( 'page' );
71 | $page2->ownPage[] = $page;
72 | R::store( $page2 );
73 | $page2 = $page2->fresh();
74 | $pages = $page2->withCondition( ' title = :title ', array( ':title' => 'page' ) )->ownPage;
75 | asrt( count( $pages ), 1 );
76 | //test with find()
77 | $books = R::getRedBean()->find( 'book',
78 | array(
79 | 'title' => array('book')),
80 | ' AND title = :title ', array(':title'=>'book'));
81 | asrt( count( $books ), 1 );
82 | $books = R::getRedBean()->find( 'book',
83 | array(
84 | 'title' => array('book', 'book2'),
85 | 'comment' => array('comment', 'comment2')),
86 | ' AND title = :title ', array(':title'=>'book'));
87 | asrt( count( $books ), 1 );
88 | //just check numeric works as well...
89 | $books = R::getRedBean()->find( 'book',
90 | array(
91 | 'title' => array('book', 'book2'),
92 | 'comment' => array('comment', 'comment2')),
93 | ' AND title = ? ', array('book'));
94 | asrt( count( $books ), 1 );
95 | //just extra check to verify glue works
96 | $books = R::getRedBean()->find( 'book',
97 | array(
98 | 'title' => array('book', 'book2'),
99 | 'comment' => array('comment', 'comment2')),
100 | ' ORDER BY id ');
101 | asrt( count( $books ), 1 );
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Base/Nuke.php:
--------------------------------------------------------------------------------
1 | getTables() ), 1 );
58 | R::nuke();
59 | asrt( count( R::getWriter()->getTables() ), 0 );
60 | $bean = R::dispense( 'bean' );
61 | R::store( $bean );
62 | asrt( count( R::getWriter()->getTables() ), 1 );
63 | R::freeze();
64 | R::nuke();
65 | // No effect
66 | asrt( count( R::getWriter()->getTables() ), 1 );
67 | R::freeze( FALSE );
68 | }
69 |
70 | /**
71 | * Test noNuke().
72 | *
73 | * @return void
74 | */
75 | public function testNoNuke() {
76 | $bean = R::dispense( 'bean' );
77 | R::store( $bean );
78 | asrt( count( R::getWriter()->getTables() ), 1 );
79 | R::noNuke( TRUE );
80 | try {
81 | R::nuke();
82 | fail();
83 | } catch( \Exception $e ) {
84 | pass();
85 | }
86 | asrt( count( R::getWriter()->getTables() ), 1 );
87 | R::noNuke( FALSE );
88 | R::nuke();
89 | asrt( count( R::getWriter()->getTables() ), 0 );
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Base/Observers.php:
--------------------------------------------------------------------------------
1 | getDatabaseAdapter();
36 | $writer = $toolbox->getWriter();
37 | $redbean = $toolbox->getRedBean();
38 | asrt( ( $adapter instanceof DBAdapter ), TRUE );
39 | asrt( ( $writer instanceof QueryWriter ), TRUE );
40 | asrt( ( $redbean instanceof OODB ), TRUE );
41 | $observable = new \ObservableMock();
42 | $observer = new \ObserverMock();
43 | $observable->addEventListener( "event1", $observer );
44 | $observable->addEventListener( "event3", $observer );
45 | $observable->test( "event1", "testsignal1" );
46 | asrt( $observer->event, "event1" );
47 | asrt( $observer->info, "testsignal1" );
48 | $observable->test( "event2", "testsignal2" );
49 | asrt( $observer->event, "event1" );
50 | asrt( $observer->info, "testsignal1" );
51 | $observable->test( "event3", "testsignal3" );
52 | asrt( $observer->event, "event3" );
53 | asrt( $observer->info, "testsignal3" );
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Base/Performance.php:
--------------------------------------------------------------------------------
1 | title = 'book';
37 | $pages = R::dispense( 'page', 10 );
38 | foreach( $pages as $page ) {
39 | $page->content = 'lorem ipsum';
40 | $page->title = 'data';
41 | $page->sequence = 'data';
42 | $page->order = 'data';
43 | $page->columns = 'data';
44 | $page->paragraphs = 'data';
45 | $page->paragraphs1 = 'data';
46 | $page->paragraphs2 = 'data';
47 | $page->paragraphs3 = 'data';
48 | $page->paragraphs4 = 'data';
49 | }
50 | $book->xownPageList = $pages;
51 | $tags = R::dispense( 'tag', 6 );
52 | foreach( $tags as $tag ) {
53 | $tag->label = 'tag';
54 | }
55 | $book->sharedTagList = $tags;
56 | R::store( $book );
57 | }
58 |
59 | /**
60 | * CRUD performance.
61 | *
62 | * @return void
63 | */
64 | public function crud()
65 | {
66 | R::freeze( TRUE );
67 |
68 | $book = R::dispense( 'book' );
69 | $book->title = 'Book';
70 | $page = R::dispense('page');
71 | $page->content = 'Content';
72 | $page->title = 'data';
73 | $page->sequence = 'data';
74 | $page->order = 'data';
75 | $page->columns = 'data';
76 | $page->paragraphs = 'data';
77 | $page->paragraphs1 = 'data';
78 | $page->paragraphs2 = 'data';
79 | $page->paragraphs3 = 'data';
80 | $page->paragraphs4 = 'data';
81 | $tag = R::dispense('tag');
82 | $tag->label = 'Tag ';
83 | $book->noLoad()->ownPage[] = $page;
84 | $book->noLoad()->sharedTag[] = $tag;
85 | R::store( $book );
86 | $book = $book->fresh();
87 | $book->ownPage;
88 | $book->sharedTag;
89 | R::trash( $book );
90 |
91 | }
92 |
93 | /**
94 | * CRUD performance Array Access.
95 | *
96 | * @return void
97 | */
98 | public function crudaa()
99 | {
100 | R::freeze( TRUE );
101 |
102 | $book = R::dispense( 'book' );
103 | $book['title'] = 'Book';
104 | $page = R::dispense('page');
105 | $page['content'] = 'Content';
106 | $page['title'] = 'data';
107 | $page['sequence'] = 'data';
108 | $page['order'] = 'data';
109 | $page['columns'] = 'data';
110 | $page['paragraphs'] = 'data';
111 | $page['paragraphs1'] = 'data';
112 | $page['paragraphs2'] = 'data';
113 | $page['paragraphs3'] = 'data';
114 | $page['paragraphs4'] = 'data';
115 | $tag = R::dispense('tag');
116 | $tag['label'] = 'Tag ';
117 | $book->ownPage[] = $page;
118 | $book->noLoad()->sharedTag[] = $tag;
119 | R::store( $book );
120 | $book = $book->fresh();
121 | $book->ownPage;
122 | $book->sharedTag;
123 | R::trash( $book );
124 |
125 | }
126 | }
--------------------------------------------------------------------------------
/testing/RedUNIT/Base/PullRequest530.php:
--------------------------------------------------------------------------------
1 | if ($bean->$linkField != $id) $bean->$linkField = $id;
33 | *
34 | * @return void
35 | */
36 | public function testPullRequest530()
37 | {
38 | testpack( 'Testing Pull Request #530 - OODBBean __set() checks if $property is a field link' );
39 | R::freeze( FALSE );
40 | $linkedObjects = R::dispense('linked', 2);
41 | R::storeAll($linkedObjects);
42 | $tester = R::dispense('parent');
43 | $tester->linked = $linkedObjects[0];
44 | R::store($tester);
45 | $tester = R::findOne('parent');
46 | asrt($tester->linked->id, $linkedObjects[0]->id);
47 | $tester->linked_id = $linkedObjects[1]->id;
48 | R::store($tester);
49 | asrt($tester->linked->id, $linkedObjects[1]->id);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Base/Quickexport.php:
--------------------------------------------------------------------------------
1 | 'bean', 'a' => 1, 'b' => 2, 'c' => 3 ) ) );
37 | $path = '/tmp/redbeantest.txt';
38 | R::csv( 'SELECT a,b,c FROM bean', array(), array( 'A', 'B', 'C' ), $path, FALSE );
39 | $csv = file_get_contents( $path );
40 | $expected = "A,B,C\n1,2,3";
41 | asrt( strpos($csv, $expected) !== FALSE, TRUE );
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Base/Threeway.php:
--------------------------------------------------------------------------------
1 | sharedRole[] = $role;
40 | R::store( $person );
41 | $person->link( 'person_role', array(
42 | 'unit' => R::dispense('unit')
43 | ))->role = $role;
44 | //Can we add a duplicate role now? - No because we started with a simple N-M table
45 | //and unique constraint has been applied accordingly, manually change database.
46 | asrt( R::count( 'person_role' ), 1 );
47 | R::nuke();
48 | $person = R::dispense( 'person' );
49 | $role = R::dispense( 'role' );
50 | $person->via('participant')->sharedRole[] = $role;
51 | R::store( $person );
52 | $person->link( 'participant', array(
53 | 'unit' => R::dispense('unit')
54 | ))->role = $role;
55 | //Can we add a duplicate role now? - No because we started with a simple N-M table
56 | //and unique constraint has been applied accordingly, manually change database.
57 | asrt( R::count( 'participant' ), 1 );
58 | R::nuke();
59 | $participant = R::dispense( 'participant' );
60 | $person = R::dispense( 'person' );
61 | $role = R::dispense( 'role' );
62 | $unit = R::dispense( 'unit' );
63 | $participant->person = $person;
64 | $participant->role = $role;
65 | $participant->unit = $unit;
66 | R::store( $participant );
67 | $person->link( 'participant', array(
68 | 'unit' => R::dispense('unit')
69 | ))->role = $role;
70 | R::store( $person );
71 | //Can we add a duplicate role now?
72 | asrt( R::count( 'participant' ), 2 );
73 | AQueryWriter::clearRenames();
74 | }
75 |
76 | /**
77 | * Test whether a duplicate bean in the list isnt saved.
78 | * This was an issue with Postgres while testing the threeway tables.
79 | * Postgres returned the ID as a string while other drivers returned
80 | * a numeric value causing different outcome in array_diff when
81 | * calculating the shared additions.
82 | *
83 | * @return void
84 | */
85 | public function testIssueWithDriverReturnID()
86 | {
87 | AQueryWriter::clearRenames();
88 | R::nuke();
89 | $book = R::dispense( 'book' );
90 | $page = R::dispense( 'page' );
91 | $book->sharedPageList[] = $page;
92 | R::store( $book );
93 | asrt( R::count( 'page' ), 1 );
94 | $book = $book->fresh();
95 | $book->sharedPageList[] = $page;
96 | R::store( $book );
97 | //don't save the duplicate bean!
98 | asrt( R::count( 'page' ), 1 );
99 | $book = $book->fresh();
100 | $page->item = 2; //even if we change a property ?
101 | $book->sharedPageList[] = $page;
102 | R::store( $book );
103 | foreach( $book->sharedPageList as $listItem) {
104 | asrt( is_string( $listItem->id ), TRUE );
105 | }
106 | //same test but for own-list
107 | R::nuke();
108 | $book = R::dispense( 'book' );
109 | $page = R::dispense( 'page' );
110 | $book->ownPageList[] = $page;
111 | R::store( $book );
112 | asrt( R::count( 'page' ), 1 );
113 | $book = $book->fresh();
114 | $book->ownPageList[] = $page;
115 | R::store( $book );
116 | //don't save the duplicate bean!
117 | asrt( R::count( 'page' ), 1 );
118 | $book = $book->fresh();
119 | $book->ownPageList[] = $page;
120 | $page->item = 3;
121 | R::store( $book );
122 | //don't save the duplicate bean!
123 | asrt( R::count( 'page' ), 1 );
124 | foreach( $book->ownPageList as $listItem) {
125 | asrt( is_string( $listItem->id ), TRUE );
126 | }
127 | AQueryWriter::clearRenames();
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Base/Trash.php:
--------------------------------------------------------------------------------
1 | 'book',
36 | 'pages'=>3
37 | )
38 | ));
39 | asrt( R::count('book'), 1 );
40 | $n = R::trash(R::findOne('book'));
41 | asrt( $n, 1 );
42 | asrt( R::count('book'), 0 );
43 | list($books) = R::dispenseAll('book*10');
44 | R::storeAll( $books );
45 | asrt( R::count('book'), 10 );
46 | $n = R::trashAll( $books );
47 | asrt( R::count('book'), 0 );
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Base/Utf8.php:
--------------------------------------------------------------------------------
1 | byte = $byte;
35 | OODBBean::setEnforceUTF8encoding( TRUE );
36 | $str = strval( $bean );
37 | OODBBean::setEnforceUTF8encoding( FALSE );
38 | pass();
39 | }
40 |
41 | /**
42 | * Test UTF8 handling.
43 | *
44 | * @return void
45 | */
46 | public function testUTF8()
47 | {
48 | //skip if < 5.3
49 | if (version_compare(PHP_VERSION, '5.4', '<')) return pass();
50 | $str = '𠜎ὃ𠻗𠻹𠻺𠼭𠼮𠽌𠾴𠾼𠿪𡁜';
51 | $bean = R::dispense( 'bean' );
52 | $bean->bla = $str;
53 | R::store( $bean );
54 | $bean = R::load( 'bean', $bean->id );
55 | asrt( $bean->bla, $str );
56 | pass();
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Blackhole.php:
--------------------------------------------------------------------------------
1 | taste() );
38 | asrt( 'tomato', $soup->flavour );
39 | }
40 |
41 | /**
42 | * Test unboxing
43 | *
44 | * @param OODBBean $bean
45 | */
46 | private function giveMeBean( OODBBean $bean )
47 | {
48 | asrt( ( $bean instanceof OODBBean ), TRUE );
49 | asrt( 'A bit too salty', $bean->taste() );
50 | asrt( 'tomato', $bean->flavour );
51 | }
52 |
53 | /**
54 | * Test boxing.
55 | *
56 | * @return void
57 | */
58 | public function testBasicBox()
59 | {
60 | $soup = R::dispense( 'soup' );
61 | $soup->flavour = 'tomato';
62 | $this->giveMeSoup( $soup->box() );
63 | $this->giveMeBean( $soup->box()->unbox() );
64 | $this->giveMeBean( $soup );
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Blackhole/Glue.php:
--------------------------------------------------------------------------------
1 | glueSQLCondition( ' name = ? '), ' WHERE name = ? ' );
47 | asrt( $writer->glueSQLCondition( ' value1 > ? OR value < ? '), ' WHERE value1 > ? OR value < ? ' );
48 | //Does it recognize NON-WHERE conditions? - usual suspects
49 | asrt( $writer->glueSQLCondition( ' ORDER BY name '), ' ORDER BY name ' );
50 | asrt( $writer->glueSQLCondition( ' LIMIT 10 '), ' LIMIT 10 ' );
51 | asrt( $writer->glueSQLCondition( ' OFFSET 20 '), ' OFFSET 20 ' );
52 | //highly doubtful but who knows... - I think nobody will ever use this in a query snippet.
53 | asrt( $writer->glueSQLCondition( ' GROUP BY grp '), ' GROUP BY grp ' );
54 | asrt( $writer->glueSQLCondition( ' HAVING x = ? '), ' HAVING x = ? ' );
55 | //can we replace WHERE with AND ?
56 | asrt( $writer->glueSQLCondition( ' AND name = ? ', QueryWriter::C_GLUE_WHERE ), ' WHERE name = ? ' );
57 | //can we glue with AND instead of WHERE ?
58 | asrt( $writer->glueSQLCondition( ' value1 > ? OR value < ? ', QueryWriter::C_GLUE_AND ), ' AND value1 > ? OR value < ? ' );
59 | //non-cases
60 | asrt( $writer->glueSQLCondition( ' GROUP BY grp ', QueryWriter::C_GLUE_WHERE ), ' GROUP BY grp ' );
61 | asrt( $writer->glueSQLCondition( ' GROUP BY grp ', QueryWriter::C_GLUE_AND ), ' GROUP BY grp ' );
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Blackhole/Labels.php:
--------------------------------------------------------------------------------
1 | setMeta( "this.is.a.custom.metaproperty", "yes" );
40 | asrt( $bean->getMeta( "this.is.a.custom.metaproperty" ), "yes" );
41 | asrt( $bean->getMeta( "nonexistant" ), NULL );
42 | asrt( $bean->getMeta( "nonexistant", "abc" ), "abc" );
43 | asrt( $bean->getMeta( "nonexistant.nested" ), NULL );
44 | asrt( $bean->getMeta( "nonexistant,nested", "abc" ), "abc" );
45 | $bean->setMeta( "test.two", "second" );
46 | asrt( $bean->getMeta( "test.two" ), "second" );
47 | $bean->setMeta( "another.little.property", "yes" );
48 | asrt( $bean->getMeta( "another.little.property" ), "yes" );
49 | asrt( $bean->getMeta( "test.two" ), "second" );
50 | // Copy Metadata
51 | $bean = new OODBBean;
52 | $bean->setMeta( "meta.meta", "123" );
53 | $bean2 = new OODBBean;
54 | asrt( $bean2->getMeta( "meta.meta" ), NULL );
55 | $bean2->copyMetaFrom( $bean );
56 | asrt( $bean2->getMeta( "meta.meta" ), "123" );
57 | }
58 |
59 | /**
60 | * Meta properties should not be saved.
61 | *
62 | * @return void
63 | */
64 | public function testMetaPersist()
65 | {
66 | $bean = R::dispense( 'bean' );
67 | $bean->property = 'test';
68 | $bean->setMeta( 'meta', 'hello' );
69 | R::store( $bean );
70 | asrt( $bean->getMeta( 'meta' ), 'hello' );
71 | $bean = $bean->fresh();
72 | asrt( $bean->getMeta( 'meta' ), NULL );
73 | }
74 |
75 | /**
76 | * You cant access meta data using the array accessors.
77 | *
78 | * @return void
79 | */
80 | public function testNoArrayMetaAccess()
81 | {
82 | $bean = R::dispense( 'bean' );
83 | $bean->setMeta( 'greet', 'hello' );
84 | asrt( isset( $bean['greet'] ), FALSE );
85 | asrt( isset( $bean['__info']['greet'] ), FALSE );
86 | asrt( isset( $bean['__info'] ), FALSE );
87 | asrt( isset( $bean['meta'] ), FALSE );
88 | asrt( count( $bean ), 1 );
89 | }
90 |
91 | /**
92 | * Test meta masks.
93 | *
94 | * @return void
95 | */
96 | public function testMetaMask()
97 | {
98 | $rows = array(
99 | array('id'=>1, 'name'=>'a', '__meta_rows'=>2, '__meta_columns'=>4),
100 | array('id'=>2, 'name'=>'b', '__meta_rows'=>2, '__meta_columns'=>4)
101 | );
102 | $books = R::convertToBeans( 'book', $rows, '__meta' );
103 | $book = reset($books);
104 | $data = $book->getMeta('data.bundle');
105 | asrt( $data['__meta_rows'], 2 );
106 | asrt( $data['__meta_columns'], 4 );
107 | $books = R::convertToBeans( 'book', $rows, array( '__meta_rows', '__meta_columns' ) );
108 | $book = reset($books);
109 | $data = $book->getMeta('data.bundle');
110 | asrt( $data['__meta_rows'], 2 );
111 | asrt( $data['__meta_columns'], 4 );
112 | $books = R::convertToBeans( 'book', $rows, array( '__meta_rows' ) );
113 | $book = reset($books);
114 | $data = $book->getMeta('data.bundle');
115 | asrt( $data['__meta_rows'], 2 );
116 | asrt( isset($data['__meta_columns']), FALSE );
117 | $books = R::convertToBeans( 'book', $rows, array( '__meta_rows', TRUE ) );
118 | $book = reset($books);
119 | $data = $book->getMeta('data.bundle');
120 | asrt( isset($data['__meta_rows']), FALSE );
121 | asrt( isset($data['__meta_columns']), FALSE );
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Blackhole/Plugins.php:
--------------------------------------------------------------------------------
1 | getMessage(), 'Plugin name may only contain alphanumeric characters and underscores and cannot start with a number.' );
57 | }
58 | try {
59 | R::__callStatic( '---', function() {} );
60 | fail();
61 | } catch ( RedException $e ) {
62 | asrt( $e->getMessage(), 'Plugin name may only contain alphanumeric characters and underscores and cannot start with a number.' );
63 | }
64 | try {
65 | R::invalidMethod();
66 | fail();
67 | } catch ( RedException $e ) {
68 | asrt( $e->getMessage(), 'Plugin \'invalidMethod\' does not exist, add this plugin using: R::ext(\'invalidMethod\')' );
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Blackhole/Tainted.php:
--------------------------------------------------------------------------------
1 | hasListChanged( 'ownPage' ), FALSE );
36 | $book->ownPage[] = $page;
37 | asrt( $book->hasListChanged( 'ownPage' ), TRUE );
38 | R::store( $book );
39 | $book = $book->fresh();
40 | asrt( $book->hasListChanged( 'ownPage' ), FALSE );
41 | $page = R::dispense( 'page' );
42 | $book->ownPageList[] = $page;
43 | asrt( $book->hasListChanged( 'ownPage' ), TRUE );
44 | R::store( $book );
45 | $book = $book->fresh();
46 | asrt( $book->hasListChanged( 'ownPage' ), FALSE );
47 | asrt( count( $book->ownPageList ), 2 );
48 | array_pop( $book->ownPageList );
49 | asrt( count( $book->ownPageList ), 1 );
50 | asrt( $book->hasListChanged( 'ownPage' ), TRUE );
51 | array_pop( $book->ownPageList );
52 | asrt( count( $book->ownPageList ), 0 );
53 | asrt( $book->hasListChanged( 'ownPage' ), TRUE );
54 | $book = $book->fresh();
55 | asrt( $book->hasListChanged( 'ownPage' ), FALSE );
56 | asrt( count( $book->ownPageList ), 2 );
57 | $otherPage = R::dispense( 'page' );
58 | array_pop( $book->ownPageList );
59 | $book->ownPageList[] = $otherPage;
60 | asrt( count( $book->ownPageList ), 2 );
61 | asrt( $book->hasListChanged( 'ownPage' ), TRUE );
62 | $book = $book->fresh();
63 | $firstPage = reset( $book->ownPageList );
64 | $firstPage->content = 'abc';
65 | asrt( $book->hasListChanged( 'ownPage' ), FALSE );
66 | $book = $book->fresh();
67 | asrt( $book->hasListChanged( 'ownPage' ), FALSE );
68 | $lastPage = end( $book->ownPageList );
69 | $lastPage->ownText[] = R::dispense( 'text' );
70 | asrt( $book->hasListChanged( 'ownPage' ), FALSE );
71 | }
72 |
73 | /**
74 | * Tests whether we can clear the history of a bean.
75 | *
76 | * @return void
77 | */
78 | public function testClearHist()
79 | {
80 | R::nuke();
81 | $book = R::dispense( 'book' );
82 | asrt( $book->hasChanged( 'title' ), FALSE );
83 | $book->title = 'book';
84 | asrt( $book->hasChanged( 'title' ), TRUE );
85 | R::store( $book );
86 | asrt( $book->hasChanged( 'title' ), TRUE );
87 | $book->clearHistory();
88 | asrt( $book->hasChanged( 'title' ), FALSE );
89 | }
90 |
91 | /**
92 | * Test tainted.
93 | *
94 | * @return void
95 | */
96 | public function testTainted()
97 | {
98 | testpack( 'Original Tainted Tests' );
99 | $redbean = R::getRedBean();
100 | $spoon = $redbean->dispense( "spoon" );
101 | asrt( $spoon->getMeta( "tainted" ), TRUE );
102 | $spoon->dirty = "yes";
103 | asrt( $spoon->getMeta( "tainted" ), TRUE );
104 | testpack( 'Tainted List test' );
105 | $note = R::dispense( 'note' );
106 | $note->text = 'abc';
107 | $note->ownNote[] = R::dispense( 'note' )->setAttr( 'text', 'def' );
108 | $id = R::store( $note );
109 | $note = R::load( 'note', $id );
110 | asrt( $note->isTainted(), FALSE );
111 | // Shouldn't affect tainted
112 | $note->text;
113 | asrt( $note->isTainted(), FALSE );
114 | $note->ownNote;
115 | asrt( $note->isTainted(), TRUE );
116 | testpack( 'Tainted Test Old Value' );
117 | $text = $note->old( 'text' );
118 | asrt( $text, 'abc' );
119 | asrt( $note->hasChanged( 'text' ), FALSE );
120 | $note->text = 'xxx';
121 | asrt( $note->hasChanged( 'text' ), TRUE );
122 | $text = $note->old( 'text' );
123 | asrt( $text, 'abc' );
124 | testpack( 'Tainted Non-exist' );
125 | asrt( $note->hasChanged( 'text2' ), FALSE );
126 | testpack( 'Misc Tainted Tests' );
127 | $bean = R::dispense( 'bean' );
128 | $bean->hasChanged( 'prop' );
129 | $bean->old( 'prop' );
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Blackhole/Version.php:
--------------------------------------------------------------------------------
1 | getFeatureFlags(), '1,0,0,0,0' );
86 | R::useFeatureSet('5.3');
87 | asrt( $this->getFeatureFlags(), '1,0,0,0,0' );
88 | R::useFeatureSet('novice/5.3');
89 | asrt( $this->getFeatureFlags(), '1,1,0,0,0' );
90 | R::useFeatureSet('5.4');
91 | asrt( $this->getFeatureFlags(), '1,0,0,1,1' );
92 | R::useFeatureSet('latest');
93 | asrt( $this->getFeatureFlags(), '1,0,0,1,1' );
94 | R::useFeatureSet('novice/5.4');
95 | asrt( $this->getFeatureFlags(), '1,1,0,0,1' );
96 | R::useFeatureSet('5.5');
97 | asrt( $this->getFeatureFlags(), '1,0,0,1,1' );
98 | R::useFeatureSet('novice/5.5');
99 | asrt( $this->getFeatureFlags(), '1,1,0,0,1' );
100 | R::useFeatureSet('novice/latest');
101 | asrt( $this->getFeatureFlags(), '1,1,0,0,1' );
102 | R::useFeatureSet('original');
103 | asrt( $this->getFeatureFlags(), '1,0,0,0,0' );
104 | }
105 |
106 | /**
107 | * Test whether an invalid feature set label will
108 | * cause an exception.
109 | *
110 | * @return void
111 | */
112 | public function testInvalidFeatureLabel()
113 | {
114 | try {
115 | R::useFeatureSet('Invalid');
116 | fail();
117 | } catch( \Exception $e ) {
118 | pass();
119 | }
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/testing/RedUNIT/CUBRID.php:
--------------------------------------------------------------------------------
1 | getDatabaseAdapter();
34 | $writer = $toolbox->getWriter();
35 | $redbean = $toolbox->getRedBean();
36 | $pdo = $adapter->getDatabase();
37 | $writer->createTable( "testtable" );
38 | $writer->addColumn( "testtable", "special", CUBRID::C_DATATYPE_SPECIAL_DATE );
39 | $cols = $writer->getColumns( "testtable" );
40 | asrt( $writer->code( $cols['special'], TRUE ), CUBRID::C_DATATYPE_SPECIAL_DATE );
41 | asrt( $writer->code( $cols['special'], FALSE ), CUBRID::C_DATATYPE_SPECIFIED );
42 | $writer->addColumn( "testtable", "special2", CUBRID::C_DATATYPE_SPECIAL_DATETIME );
43 | $cols = $writer->getColumns( "testtable" );
44 | asrt( $writer->code( $cols['special2'], TRUE ), CUBRID::C_DATATYPE_SPECIAL_DATETIME );
45 | asrt( $writer->code( $cols['special'], FALSE ), CUBRID::C_DATATYPE_SPECIFIED );
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Mysql.php:
--------------------------------------------------------------------------------
1 | id, $book1ID );
111 | asrt( $book1->title, 'book 1' );
112 | $book2 = R::load( 'book', $book2ID );
113 | asrt( $book2->id, $book2ID );
114 | asrt( $book2->title, 'book 2' );
115 | asrt( count( $book1->ownPage ), 2 );
116 | asrt( count( $book1->fresh()->with( 'LIMIT 1' )->ownPage ), 1 );
117 | asrt( count( $book1->fresh()->withCondition( ' title = ? ', array('page 2 of book 1'))->ownPage ), 1 );
118 | asrt( count($book2->ownPage), 1 );
119 | asrt( $book2->fresh()->countOwn( 'page' ), 1 );
120 | $page1 = R::load( 'page', $page1ID );
121 | asrt( count( $page1->sharedPage ), 0 );
122 | asrt( $page1->fetchAs( 'book' )->magazine->id, $book2ID );
123 | $page2 = R::load( 'page', $page2ID );
124 | asrt( count($page2->sharedPage), 1 );
125 | asrt( $page2->fresh()->countShared( 'page' ), 1 );
126 | $page3 = R::findOne( 'page', ' title = ? ', array( 'page 1 of book 2' ) );
127 | asrt( $page3->id, $page3ID );
128 | asrt( $page3->book->id, $book2ID );
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Mysql/Double.php:
--------------------------------------------------------------------------------
1 | getDatabaseAdapter();
34 | $writer = $toolbox->getWriter();
35 | $redbean = $toolbox->getRedBean();
36 | $pdo = $adapter->getDatabase();
37 | $largeDouble = 999999888889999922211111; //8.88889999922211e+17;
38 | $page = $redbean->dispense( "page" );
39 | $page->weight = $largeDouble;
40 | $id = $redbean->store( $page );
41 | $cols = $writer->getColumns( 'page' );
42 | asrt( $cols['weight'], 'double' );
43 | $page = $redbean->load( 'page', $id );
44 | $page->name = 'dont change the numbers!';
45 | $redbean->store( $page );
46 | $page = $redbean->load( 'page', $id );
47 | $cols = $writer->getColumns( 'page' );
48 | asrt( $cols['weight'], 'double' );
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Mysql/Freeze.php:
--------------------------------------------------------------------------------
1 | getDatabaseAdapter();
38 | $writer = $toolbox->getWriter();
39 | $redbean = $toolbox->getRedBean();
40 | $pdo = $adapter->getDatabase();
41 | $a = new AssociationManager( $toolbox );
42 | $post = $redbean->dispense( 'post' );
43 | $post->title = 'title';
44 | $redbean->store( $post );
45 | $page = $redbean->dispense( 'page' );
46 | $page->name = 'title';
47 | $redbean->store( $page );
48 | $page = $redbean->dispense( "page" );
49 | $page->name = "John's page";
50 | $idpage = $redbean->store( $page );
51 | $page2 = $redbean->dispense( "page" );
52 | $page2->name = "John's second page";
53 | $idpage2 = $redbean->store( $page2 );
54 | $a->associate( $page, $page2 );
55 | $redbean->freeze( TRUE );
56 | $page = $redbean->dispense( "page" );
57 | $page->sections = 10;
58 | $page->name = "half a page";
59 | try {
60 | $id = $redbean->store( $page );
61 | fail();
62 | } catch ( SQL $e ) {
63 | pass();
64 | }
65 | $post = $redbean->dispense( "post" );
66 | $post->title = "existing table";
67 | try {
68 | $id = $redbean->store( $post );
69 | pass();
70 | } catch ( SQL $e ) {
71 | fail();
72 | }
73 | asrt( in_array( "name", array_keys( $writer->getColumns( "page" ) ) ), TRUE );
74 | asrt( in_array( "sections", array_keys( $writer->getColumns( "page" ) ) ), FALSE );
75 | $newtype = $redbean->dispense( "newtype" );
76 | $newtype->property = 1;
77 | try {
78 | $id = $redbean->store( $newtype );
79 | fail();
80 | } catch ( SQL $e ) {
81 | pass();
82 | }
83 | $logger = R::debug( TRUE, 1 );
84 | // Now log and make sure no 'describe SQL' happens
85 | $page = $redbean->dispense( "page" );
86 | $page->name = "just another page that has been frozen...";
87 | $id = $redbean->store( $page );
88 | $page = $redbean->load( "page", $id );
89 | $page->name = "just a frozen page...";
90 | $redbean->store( $page );
91 | $page2 = $redbean->dispense( "page" );
92 | $page2->name = "an associated frozen page";
93 | $a->associate( $page, $page2 );
94 | $a->related( $page, "page" );
95 | $a->unassociate( $page, $page2 );
96 | $a->clearRelations( $page, "page" );
97 | $items = $redbean->find( "page", array(), array( "1" ) );
98 | $redbean->trash( $page );
99 | $redbean->freeze( FALSE );
100 | asrt( count( $logger->grep( "SELECT" ) ) > 0, TRUE );
101 | asrt( count( $logger->grep( "describe" ) ) < 1, TRUE );
102 | asrt( is_array( $logger->getLogs() ), TRUE );
103 | R::debug( FALSE );
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Mysql/Issue411.php:
--------------------------------------------------------------------------------
1 | text = 'abcd';
39 | R::store( $book );
40 | $columns = R::inspect( 'book' );
41 | asrt( isset( $columns['text'] ), TRUE );
42 | asrt( $columns['text'], 'varchar(191)' );
43 | $book = $book->fresh();
44 | $book->text = str_repeat( 'x', 190 );
45 | R::store( $book );
46 | $columns = R::inspect( 'book' );
47 | asrt( isset( $columns['text'] ), TRUE );
48 | asrt( $columns['text'], 'varchar(191)' );
49 | $book = $book->fresh();
50 | $book->text = str_repeat( 'x', 191 );
51 | R::store( $book );
52 | $columns = R::inspect( 'book' );
53 | asrt( isset( $columns['text'] ), TRUE );
54 | asrt( $columns['text'], 'varchar(191)' );
55 | $book = $book->fresh();
56 | $book->text = str_repeat( 'x', 192 );
57 | R::store( $book );
58 | $columns = R::inspect( 'book' );
59 | asrt( isset( $columns['text'] ), TRUE );
60 | asrt( $columns['text'], 'varchar(255)' );
61 | }
62 | }
63 |
64 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Mysql/Parambind.php:
--------------------------------------------------------------------------------
1 | getDatabaseAdapter();
36 | $writer = $toolbox->getWriter();
37 | $redbean = $toolbox->getRedBean();
38 | $pdo = $adapter->getDatabase();
39 | R::getDatabaseAdapter()->getDatabase()->setUseStringOnlyBinding( TRUE );
40 | try {
41 | R::getAll( "select * from job limit ? ", array( 1 ) );
42 | fail();
43 | } catch (\Exception $e ) {
44 | pass();
45 | }
46 | try {
47 | R::getAll( "select * from job limit :l ", array( ":l" => 1 ) );
48 | fail();
49 | } catch (\Exception $e ) {
50 | pass();
51 | }
52 | try {
53 | R::exec( "select * from job limit ? ", array( 1 ) );
54 | fail();
55 | } catch (\Exception $e ) {
56 | pass();
57 | }
58 | try {
59 | R::exec( "select * from job limit :l ", array( ":l" => 1 ) );
60 | fail();
61 | } catch (\Exception $e ) {
62 | pass();
63 | }
64 | R::getDatabaseAdapter()->getDatabase()->setUseStringOnlyBinding( FALSE );
65 | try {
66 | R::getAll( "select * from job limit ? ", array( 1 ) );
67 | pass();
68 | } catch (\Exception $e ) {
69 | fail();
70 | }
71 | try {
72 | R::getAll( "select * from job limit :l ", array( ":l" => 1 ) );
73 | pass();
74 | } catch (\Exception $e ) {
75 | fail();
76 | }
77 | try {
78 | R::exec( "select * from job limit ? ", array( 1 ) );
79 | pass();
80 | } catch (\Exception $e ) {
81 | fail();
82 | }
83 | try {
84 | R::exec( "select * from job limit :l ", array( ":l" => 1 ) );
85 | pass();
86 | } catch (\Exception $e ) {
87 | fail();
88 | }
89 | testpack( "Test findOrDispense" );
90 | $person = R::findOrDispense( "person", " job = ? ", array( "developer" ) );
91 | asrt( ( count( $person ) > 0 ), TRUE );
92 | $person = R::findOrDispense( "person", " job = ? ", array( "musician" ) );
93 | asrt( ( count( $person ) > 0 ), TRUE );
94 | $musician = array_pop( $person );
95 | asrt( intval( $musician->id ), 0 );
96 | try {
97 | $adapter->exec( "an invalid query" );
98 | fail();
99 | } catch ( SQL $e ) {
100 | pass();
101 | }
102 | asrt( (int) $adapter->getCell( "SELECT 123" ), 123 );
103 | asrt( (int) $adapter->getCell( "SELECT ?", array( "987" ) ), 987 );
104 | asrt( (int) $adapter->getCell( "SELECT ?+?", array( "987", "2" ) ), 989 );
105 | asrt( (int) $adapter->getCell( "SELECT :numberOne+:numberTwo", array(
106 | ":numberOne" => 42, ":numberTwo" => 50 ) ), 92 );
107 | $pair = $adapter->getAssoc( "SELECT 'thekey','thevalue' " );
108 | asrt( is_array( $pair ), TRUE );
109 | asrt( count( $pair ), 1 );
110 | asrt( isset( $pair["thekey"] ), TRUE );
111 | asrt( $pair["thekey"], "thevalue" );
112 | testpack( 'Test whether we can properly bind and receive NULL values' );
113 | asrt( $adapter->getCell( 'SELECT :nil ', array( ':nil' => 'NULL' ) ), 'NULL' );
114 | asrt( $adapter->getCell( 'SELECT :nil ', array( ':nil' => NULL ) ), NULL );
115 | asrt( $adapter->getCell( 'SELECT ? ', array( 'NULL' ) ), 'NULL' );
116 | asrt( $adapter->getCell( 'SELECT ? ', array( NULL ) ), NULL );
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Mysql/Preexist.php:
--------------------------------------------------------------------------------
1 | getDatabaseAdapter();
35 | $writer = $toolbox->getWriter();
36 | $redbean = $toolbox->getRedBean();
37 | $pdo = $adapter->getDatabase();
38 | $a = new AssociationManager( $toolbox );
39 | $page = $redbean->dispense( "page" );
40 | $page->name = "John's page";
41 | $idpage = $redbean->store( $page );
42 | $page2 = $redbean->dispense( "page" );
43 | $page2->name = "John's second page";
44 | $idpage2 = $redbean->store( $page2 );
45 | $a->associate( $page, $page2 );
46 | $adapter->exec( "ALTER TABLE " . $writer->esc( 'page' ) . "
47 | CHANGE " . $writer->esc( 'name' ) . " " . $writer->esc( 'name' ) . "
48 | VARCHAR( 254 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL " );
49 | $page = $redbean->dispense( "page" );
50 | $page->name = "Just Another Page In a Table";
51 | $cols = $writer->getColumns( "page" );
52 | asrt( $cols["name"], "varchar(254)" );
53 | $redbean->store( $page );
54 | pass(); // No crash?
55 | $cols = $writer->getColumns( "page" );
56 | asrt( $cols["name"], "varchar(254)" ); //must still be same
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Postgres.php:
--------------------------------------------------------------------------------
1 | id, $book1ID );
101 | asrt( $book1->title, 'book 1' );
102 | $book2 = R::load( 'book', $book2ID );
103 | asrt( $book2->id, $book2ID );
104 | asrt( $book2->title, 'book 2' );
105 | asrt( count( $book1->ownPage ), 2 );
106 | asrt( count( $book1->fresh()->with( 'LIMIT 1' )->ownPage ), 1 );
107 | asrt( count( $book1->fresh()->withCondition( ' title = ? ', array('page 2 of book 1'))->ownPage ), 1 );
108 | asrt( count($book2->ownPage), 1 );
109 | asrt( $book2->fresh()->countOwn( 'page' ), 1 );
110 | $page1 = R::load( 'page', $page1ID );
111 | asrt( count( $page1->sharedPage ), 0 );
112 | asrt( $page1->fetchAs( 'book' )->magazine->id, $book2ID );
113 | $page2 = R::load( 'page', $page2ID );
114 | asrt( count($page2->sharedPage), 1 );
115 | asrt( $page2->fresh()->countShared( 'page' ), 1 );
116 | $page3 = R::findOne( 'page', ' title = ? ', array( 'page 1 of book 2' ) );
117 | asrt( $page3->id, $page3ID );
118 | asrt( $page3->book->id, $book2ID );
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Postgres/Parambind.php:
--------------------------------------------------------------------------------
1 | name = "abc";
36 | $page->number = 2;
37 | R::store( $page );
38 | R::exec( "insert into page (name) values(:name) ", array( ":name" => "my name" ) );
39 | R::exec( "insert into page (number) values(:one) ", array( ":one" => 1 ) );
40 | R::exec( "insert into page (number) values(:one) ", array( ":one" => "1" ) );
41 | R::exec( "insert into page (number) values(:one) ", array( ":one" => "1234" ) );
42 | R::exec( "insert into page (number) values(:one) ", array( ":one" => "-21" ) );
43 | pass();
44 | testpack( 'Test whether we can properly bind and receive NULL values' );
45 | $adapter = R::getDatabaseAdapter();
46 | asrt( $adapter->getCell( 'SELECT TEXT( :nil ) ', array( ':nil' => 'NULL' ) ), 'NULL' );
47 | asrt( $adapter->getCell( 'SELECT TEXT( :nil ) ', array( ':nil' => NULL ) ), NULL );
48 | asrt( $adapter->getCell( 'SELECT TEXT( ? ) ', array( 'NULL' ) ), 'NULL' );
49 | asrt( $adapter->getCell( 'SELECT TEXT( ? ) ', array( NULL ) ), NULL );
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Pretest.php:
--------------------------------------------------------------------------------
1 | getDatabaseAdapter();
35 | $writer = $toolbox->getWriter();
36 | $redbean = $toolbox->getRedBean();
37 | $pdo = $adapter->getDatabase();
38 | asrt( (int) $adapter->getCell( "SELECT 123" ), 123 );
39 | asrt( (int) $adapter->getCell( "SELECT ?", array( "987" ) ), 987 );
40 | asrt( (int) $adapter->getCell( "SELECT ?+?", array( "987", "2" ) ), 989 );
41 | asrt( (int) $adapter->getCell(
42 | "SELECT :numberOne+:numberTwo",
43 | array(
44 | ":numberOne" => 42,
45 | ":numberTwo" => 50 )
46 | ),
47 | 92
48 | );
49 | $pair = $adapter->getAssoc( "SELECT 'thekey','thevalue' " );
50 | asrt( is_array( $pair ), TRUE );
51 | asrt( count( $pair ), 1 );
52 | asrt( isset( $pair["thekey"] ), TRUE );
53 | asrt( $pair["thekey"], "thevalue" );
54 | testpack( 'Test whether we can properly bind and receive NULL values' );
55 | asrt( $adapter->getCell( 'SELECT :nil ', array( ':nil' => 'NULL' ) ), 'NULL' );
56 | asrt( $adapter->getCell( 'SELECT :nil ', array( ':nil' => NULL ) ), NULL );
57 | asrt( $adapter->getCell( 'SELECT ? ', array( 'NULL' ) ), 'NULL' );
58 | asrt( $adapter->getCell( 'SELECT ? ', array( NULL ) ), NULL );
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Sqlite/Rebuild.php:
--------------------------------------------------------------------------------
1 | getDatabaseAdapter();
37 | $writer = $toolbox->getWriter();
38 | $redbean = $toolbox->getRedBean();
39 | $pdo = $adapter->getDatabase();
40 | $book = R::dispense( 'book' );
41 | $page = R::dispense( 'page' );
42 | $book->xownPage[] = $page;
43 | $id = R::store( $book );
44 | $book = R::load( 'book', $id );
45 | asrt( count( $book->xownPage ), 1 );
46 | asrt( (int) R::getCell( 'SELECT COUNT(*) FROM page' ), 1 );
47 | R::trash( $book );
48 | asrt( (int) R::getCell( 'SELECT COUNT(*) FROM page' ), 0 );
49 | $book = R::dispense( 'book' );
50 | $page = R::dispense( 'page' );
51 | $book->xownPage[] = $page;
52 | $id = R::store( $book );
53 | $book = R::load( 'book', $id );
54 | asrt( count( $book->xownPage ), 1 );
55 | asrt( (int) R::getCell( 'SELECT COUNT(*) FROM page' ), 1 );
56 | $book->added = 2;
57 | R::store( $book );
58 | $book->added = 'added';
59 | R::store( $book );
60 | R::trash( $book );
61 | asrt( (int) R::getCell( 'SELECT COUNT(*) FROM page' ), 0 );
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/testing/RedUNIT/Sqlite/Setget.php:
--------------------------------------------------------------------------------
1 | setTimeZone( new \DateTimeZone( 'Europe/Amsterdam' ) );
46 | $dt->setDate( 1981, 5, 1 );
47 | $dt->setTime( 3, 13, 13 );
48 | asrt( setget( $dt ), '1981-05-01 03:13:13' );
49 | $bean = R::dispense( 'bean' );
50 | $bean->dt = $dt;
51 | }
52 |
53 | /**
54 | * Test numbers.
55 | *
56 | * @return void
57 | */
58 | public function testNumbers()
59 | {
60 | asrt( setget( "-1" ), "-1" );
61 | asrt( setget( -1 ), "-1" );
62 | asrt( setget( "-0.25" ), "-0.25" );
63 | asrt( setget( -0.25 ), "-0.25" );
64 | asrt( setget( "1.0" ), "1" );
65 | asrt( setget( 1.0 ), "1" );
66 | asrt( setget( "0.12345678" ), "0.12345678" );
67 | asrt( setget( 0.12345678 ), "0.12345678" );
68 | asrt( setget( "-0.12345678" ), "-0.12345678" );
69 | asrt( setget( -0.12345678 ), "-0.12345678" );
70 | asrt( setget( "2147483647" ), "2147483647" );
71 | asrt( setget( 2147483647 ), "2147483647" );
72 | asrt( setget( -2147483647 ), "-2147483647" );
73 | asrt( setget( "-2147483647" ), "-2147483647" );
74 | asrt( setget( "2147483648" ), "2147483648" );
75 | asrt( setget( "-2147483648" ), "-2147483648" );
76 | $x = setget( "199936710040730" );
77 | asrt( $x === "199936710040730" || $x === "1.9993671004073E+14", TRUE );
78 | $x = setget( "-199936710040730" );
79 | asrt( $x === "-199936710040730" || $x === "-1.9993671004073E+14", TRUE );
80 | //asrt( setget( "199936710040730" ), "199936710040730" );
81 | //asrt( setget( "-199936710040730" ), "-199936710040730" );
82 | }
83 |
84 | /**
85 | * Test dates.
86 | *
87 | * @return void
88 | */
89 | public function testDates()
90 | {
91 | asrt( setget( "2010-10-11" ), "2010-10-11" );
92 | asrt( setget( "2010-10-11 12:10" ), "2010-10-11 12:10" );
93 | asrt( setget( "2010-10-11 12:10:11" ), "2010-10-11 12:10:11" );
94 | asrt( setget( "x2010-10-11 12:10:11" ), "x2010-10-11 12:10:11" );
95 | }
96 |
97 | /**
98 | * Test strings.
99 | *
100 | * @return void
101 | */
102 | public function testStrings()
103 | {
104 | asrt( setget( "a" ), "a" );
105 | asrt( setget( "." ), "." );
106 | asrt( setget( "\"" ), "\"" );
107 | asrt( setget( "just some text" ), "just some text" );
108 | }
109 |
110 | /**
111 | * Test booleans.
112 | *
113 | * @return void
114 | */
115 | public function testBool()
116 | {
117 | asrt( setget( TRUE ), "1" );
118 | asrt( setget( FALSE ), "0" );
119 | asrt( setget( "TRUE" ), "TRUE" );
120 | asrt( setget( "FALSE" ), "FALSE" );
121 | }
122 |
123 | /**
124 | * Test NULL.
125 | *
126 | * @return void
127 | */
128 | public function testNull()
129 | {
130 | asrt( setget( "NULL" ), "NULL" );
131 | asrt( setget( "NULL" ), "NULL" );
132 | asrt( setget( NULL ), NULL );
133 | asrt( ( setget( 0 ) == 0 ), TRUE );
134 | asrt( ( setget( 1 ) == 1 ), TRUE );
135 | asrt( ( setget( TRUE ) == TRUE ), TRUE );
136 | asrt( ( setget( FALSE ) == FALSE ), TRUE );
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/testing/cli/plugins/myhooks.php:
--------------------------------------------------------------------------------
1 | 'localhost',
17 | 'schema' => 'cubase',
18 | 'user' => 'dba',
19 | 'pass' => ''
20 | );
21 |
22 | $colorMap[ 'CUBRID' ] = '0;35';
23 |
24 | $dsn = "cubrid:host={$ini['CUBRID']['host']};port=33000;dbname={$ini['CUBRID']['schema']}";
25 | R::addDatabase( 'CUBRID', $dsn, $ini['CUBRID']['user'], $ini['CUBRID']['pass'], FALSE );
26 | R::selectDatabase( 'CUBRID' );
27 | R::exec( 'AUTOCOMMIT IS ON' );
28 |
--------------------------------------------------------------------------------
/testing/cli/runperf.php:
--------------------------------------------------------------------------------
1 | getTargetDrivers();
52 |
53 | foreach ( $drivers as $driver ) {
54 |
55 | if ( !isset( $ini[$driver] ) ) continue;
56 | if ( !isset( $_SERVER['argv'][1])) die('Missing parameter. Usage: php runperf.php ');
57 |
58 | $method = $_SERVER['argv'][1];
59 |
60 | if ($method === 'setup') {
61 |
62 | echo 'Setup...'.PHP_EOL;
63 |
64 | $test->$method();
65 |
66 | echo 'READY'.PHP_EOL;
67 |
68 | } else {
69 |
70 | $times = 100;
71 | if (isset($_SERVER['argv'][2])) {
72 | $times = (int) $_SERVER['argv'][2];
73 | }
74 |
75 | echo "Performing test: $method with driver $driver ".PHP_EOL;
76 |
77 | for ($j=0; $j<$times; $j++) {
78 |
79 | $t1 = microtime( TRUE );
80 |
81 | $test->$method();
82 |
83 | $t2 = microtime( TRUE );
84 |
85 | $d[] = ($t2 - $t1);
86 |
87 | }
88 |
89 | $s = array_sum($d);
90 | $a = ($s / $times);
91 | $mx = max($d);
92 | $mn = min($d);
93 |
94 | echo PHP_EOL."AVG: $a, MAX: $mx, MIN: $mn, TOTAL: $s, TIMES: $times ".PHP_EOL;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/testing/cli/test_hook_example.php:
--------------------------------------------------------------------------------
1 | add 1 additional path which will be searched for unit tests
11 | * $extraTestsFromHook -> array with additional test packs (will be executed if you pass 'all' argument to CLI runner)
12 | *
13 | *
14 | */
--------------------------------------------------------------------------------
/testing/cli/testcontainer/put-rb-file-here.txt:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Put the rb.php file in this directory
4 |
5 | */
6 |
--------------------------------------------------------------------------------
/testing/config/test-dist.ini:
--------------------------------------------------------------------------------
1 | ; Test suite database config
2 | ; Rename this file to test.ini if you are done
3 |
4 | [mysql]
5 | host = "localhost"
6 | schema = ""
7 | user = ""
8 | pass = ""
9 |
10 | [pgsql]
11 | host = "localhost"
12 | schema = ""
13 | user = ""
14 | pass = ""
15 |
16 | [sqlite]
17 | file = "/tmp/database.db"
18 |
--------------------------------------------------------------------------------
/testing/config/test-travis.ini:
--------------------------------------------------------------------------------
1 | ; Test suite database config
2 | ; Rename this file to test.ini if you are done
3 |
4 | [mysql]
5 | host = "localhost"
6 | schema = "oodb"
7 | user = "root"
8 | pass = ""
9 |
10 | [pgsql]
11 | host = "localhost"
12 | schema = "oodb"
13 | user = "postgres"
14 | pass = ""
15 |
16 | [sqlite]
17 | file = "/tmp/oodb.db"
18 |
19 |
--------------------------------------------------------------------------------
/testing/notes.txt:
--------------------------------------------------------------------------------
1 |
2 | Test notes
3 | ==========
4 |
5 | * PostgreSQL tests perform a text-to-money cast test, make sure lc_monetary is set to en_US
6 | in your postgres.conf
7 | * PostgreSQL tests need the ossp extension, to enable this, install the postgres-contrib package and run SQL: CREATE EXTENSION "uuid-ossp";
8 | * XDebug is NOT required but recommended
9 |
--------------------------------------------------------------------------------