Begin Refactor

This commit is contained in:
color.diff=auto
2021-03-21 13:47:29 -06:00
parent 7622dc0d02
commit 018931d7ae
197 changed files with 47799 additions and 6 deletions

View File

@@ -0,0 +1,246 @@
<?php
namespace RedBeanPHP\Plugin;
use RedBeanPHP\ToolBox;
use RedBeanPHP\OODBBean;
/**
* @experimental
*
* PoolDB
*
* Experimental plugin that makes bean automatically connect
* to the database they come from.
*/
/**
* NonStaticBeanHelper
*
* The NonStaticBeanHelper is used by the database pool class PoolDB.
*/
class NonStaticBeanHelper extends RedBeanPHP\BeanHelper\SimpleFacadeBeanHelper {
/**
* Returns the extracted toolbox.
*
* @return ToolBox
*/
public function getExtractedToolbox()
{
$toolbox = $this->toolbox;
return array( $toolbox->getRedbean(), $toolbox->getDatabaseAdapter(), $toolbox->getWriter(), $toolbox );
}
/**
* Constructor
*
* Creates a new instance of the NonStaticBeanHelper.
* The NonStaticBeanHelper is used by the database pool class PoolDB.
*/
public function __construct($toolbox)
{
$this->toolbox = $toolbox;
}
}
/**
* PoolDB
*
* Represents a pool of databases that will have persisting
* associations with the beans they dispense. Saving a bean from
* a pooled database will make sure that the bean will be stored
* in the database it originated from instead of the currently
* selected database.
*
* @experimental
* This is an experimental plugin, added for testing purposes
* only.
*
* Usage:
*
* <code>
* // Let's add some databases
* R::addPoolDatabase( 'db1', 'sqlite:/tmp/db1.txt' );
* R::nuke();
* R::addPoolDatabase( 'db2', 'sqlite:/tmp/db2.txt' );
* R::nuke();
* R::addPoolDatabase( 'db3', 'sqlite:/tmp/db3.txt' );
* R::nuke();
*
* // create a book and page in db1
* R::selectDatabase('db1');
* $book = R::dispense(array(
* '_type' => 'book',
* 'title' => 'Databases for Beans',
* 'ownPageList' => array(
* 0 => array(
* '_type' => 'page',
* 'content' => 'Lorem Ipsum'
* )
* )
* ));
* R::store($book);
*
* //switch to db2
* R::selectDatabase( 'db2' );
* //obtain pages (from db1)
* $pages = count($book->ownPageList);
* echo "I found {$pages} pages in db1.\n";
*
* $pages = R::count('page');
* echo "There are {$pages} pages in db2.\n";
*
* // create pizza in db 2
* $pizza = R::dispense('pizza');
*
* // switch to db3
* R::selectDatabase( 'db3' );
*
* // store pizza in db2
* $pizza->pepperoni = true;
* R::store($pizza);
*
* $pizzas = R::count('pizza');
* echo "There are {$pizzas} in pizzas db3.\n";
* R::selectDatabase('db2');
* $pizzas = R::count('pizza');
* echo "There are {$pizzas} pizzas in db2.\n";
* </code>
*
* @file RedBeanPHP/Plugin/Pool.php
* @author RedBeanPHP Community
* @license BSD/GPLv2
*
* @copyright
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
* This source file is subject to the BSD/GPLv2 License that is bundled
* with this source code in the file license.txt.
*/
class PoolDB extends \RedBeanPHP\OODB {
/**
* @var array
*/
private static $pool = array();
/**
* @var ToolBox
*/
private $toolbox;
/**
* @var OODB
*/
private $oodb;
/**
* @var string
*/
private $key;
/**
* @var NonStaticBeanHelper
*/
private $beanHelper;
/**
* Constructor
*
* creates a new instance of the database pool.
*
* @param string $key key
* @param OODB $oodb oodb instance
*/
public function __construct( $key, $oodb)
{
self::$pool[$key] = $oodb;
$this->oodb = $oodb;
$this->key = $key;
parent::__construct( $oodb->writer, $oodb->isFrozen );
}
/**
* Sets the toolbox to be used by the database pool.
*
* @param ToolBox $toolbox toolbox
*
* @return void
*/
public function setToolBox( $toolbox )
{
$this->toolbox = $toolbox;
$this->beanHelper = new NonStaticBeanHelper( $this->toolbox );
$this->beanHelper->key = $this->key;
$this->oodb->setBeanHelper( $this->beanHelper );
}
/**
* Returns the bean helper of the database pool.
*
* @return BeanHelper
*/
public function getBeanHelper()
{
return $this->beanHelper;
}
/**
* Implements the find operation.
*
* @see OODB::find
*/
public function find( $type, $conditions=array(), $sql=NULL, $bindings=array())
{
return parent::find($type, $conditions, $sql, $bindings);
}
/**
* Dispenses a new bean from the database pool.
* A bean that has been dispensed by the pool will have a special
* meta attribute called sys.source containing the key identifying
* the database in the pool it originated from.
*
* @see OODB::dispense
*/
public function dispense( $type, $number = 1, $alwaysReturnArray = FALSE )
{
$bean = $this->oodb->dispense( $type, $number, $alwaysReturnArray );
foreach( self::$pool as $key => $db ) {
if ( $this->oodb === $db ) {
$bean->setMeta( 'sys.source',$key );
}
}
return $bean;
}
/**
* Stores the specified bean in the database in the pool
* it originated from by looking up the sys.source attribute.
*
* @see OODB::store
*/
public function store( $bean )
{
$dataSource = $bean->getMeta('sys.source');
if ( !is_null( $dataSource ) ) {
$result = self::$pool[$dataSource]->store( $bean );
} else {
$result = parent::store( $bean );
}
return $result;
}
}
R::ext( 'addPoolDatabase', function( $dbName, $dsn, $user=NULL, $pass=NULL ) {
R::addDatabase( $dbName, $dsn, $user, $pass );
R::selectDatabase( $dbName );
list($oodb, $adapter, $writer, ) = R::getExtractedToolbox();
$poolDB = new PoolDB( $dbName, $oodb );
$toolbox = new ToolBox( $poolDB, $adapter, $writer );
$poolDB->setToolBox( $toolbox );
R::$toolboxes[$dbName]=$toolbox;
R::selectDatabase( $dbName, TRUE );
} );

View File

@@ -0,0 +1,86 @@
<?php
/**
* Short Query Notation Library
*
* SQN is a small library that allows you to write
* convention based SQL queries using a short notation.
* SQL is a very flexible and powerful language. Since SQL
* does not rely on assumptions you have to specify a lot.
* The SQN-library uses some basic assumptions regarding
* naming conventions and in return it gives you a shorter notation.
*
* Usage:
*
* R::sqn('shop<product<price'); - left joins shop, product and price
* R::sqn('book<<tag'); - doubly left joins book, and tag using book_tag
*
* SQN assumes id fields follow the following conventions:
*
* Primary key: id
* Foreign key: {table}_id
* No table prefix.
*
* SQN can also generate additional aliases:
*
* R::sqn( ..., 'area/x,y;place/x,y' ) - area_x area_y place_x place_y
*
* @author Gabor de Mooij
* @license BSD/GPLv2
*
* @copyright
* copyright (c) G.J.G.T. (Gabor) de Mooij
* This source file is subject to the BSD License that is bundled
* with this source code in the file license.txt.
*/
R::ext('sqn', function( $query, $aliases = null, $q = '`' ) {
$map = [
'|' => 'INNER JOIN',
'||' => 'INNER JOIN',
'>' => 'RIGHT JOIN',
'>>' => 'RIGHT JOIN',
'<' => 'LEFT JOIN',
'<<' => 'LEFT JOIN',
];
$select = [];
$from = '';
$joins = [];
$prev = '';
$ents = preg_split( '/[^\w_]+/', $query );
$tokens = preg_split( '/[\w_]+/', $query );
array_pop($tokens);
foreach( $ents as $i => $ent ) {
$select[] = " {$q}{$ent}{$q}.* ";
if (!$i) {
$from = $ent;
$prev = $ent;
continue;
}
if ( $tokens[$i] == '<' || $tokens[$i] == '>' || $tokens[$i] == '|') {
$join[] = " {$map[$tokens[$i]]} {$q}{$ent}{$q} ON {$q}{$ent}{$q}.{$prev}_id = {$q}{$prev}{$q}.id ";
}
if ( $tokens[$i] == '<<' || $tokens[$i] == '>>' || $tokens[$i] == '||') {
$combi = [$prev, $ent];
sort( $combi );
$combi = implode( '_', $combi );
$select[] = " {$q}{$combi}{$q}.* ";
$join[] = " {$map[$tokens[$i]]} {$q}{$combi}{$q} ON {$q}{$combi}{$q}.{$prev}_id = {$q}{$prev}{$q}.id ";
$join[] = " {$map[$tokens[$i]]} {$q}{$ent}{$q} ON {$q}{$combi}{$q}.{$ent}_id = {$q}{$ent}{$q}.id ";
}
$prev = $ent;
}
if (!is_null($aliases)) {
$aliases = explode(';', $aliases);
foreach($aliases as $alias) {
list($table, $cols) = explode('/', $alias);
$cols = explode(',', $cols);
foreach($cols as $col) {
$select[] = " {$q}{$table}{$q}.{$q}{$col}{$q} AS {$q}{$table}_{$col}{$q} ";
}
}
}
$selectSQL = implode( ",\n", $select );
$joinSQL = implode( "\n", $join );
return "SELECT{$selectSQL}\n FROM {$q}{$from}{$q}\n{$joinSQL}";
});

View File

@@ -0,0 +1,56 @@
<?php
/**
* Tiny Query Builder
*
* <code>
* $sql = build_query([
* [ 'SELECT * FROM book'],
* [$title ,'WHERE','title = ?'],
* [$price ,'AND','price < ?'],
* [$order ,'ORDER BY ? ASC'],
* [$limit ,'LIMIT ?']
* ]);
* </code>
*
* Now, if we have a $title and a $price the query will be:
* 'SELECT * FROM book WHERE title = ? AND price < ? '
* If we only have a $price and a $limit:
* 'SELECT * FROM book WHERE price < ? LIMIT ?'
* The Query Builder works very easy, it simply loops through the array,
* each element is another array inside this main array,
* let's call this inner array a 'piece'.
* A piece can have one, two or three elements.
* If it has one element, the element is simply concatenated to the final query.
* If a piece has two elements, the second element will be
* concatenated only if the first evaluates to TRUE.
* Finally a piece having three elements works the same as a piece with two elements,
* except that it will use the glue provided in the second element
* to concat the value of the third element. The glue acts as a little tube of glue.
* If there is still glue left in the tube (WHERE) it will preserve this
* until it can be applied (so the first AND will be ignored in case of a WHERE condition).
*/
R::ext('buildQuery', function($pieces) {
$sql = '';
$glue = NULL;
foreach( $pieces as $piece ) {
$n = count( $piece );
switch( $n ) {
case 1:
$sql .= " {$piece[0]} ";
break;
case 2:
$glue = NULL;
if (!is_null($piece[0])) $sql .= " {$piece[1]} ";
break;
case 3:
$glue = ( is_null( $glue ) ) ? $piece[1] : $glue;
if (!is_null($piece[0])) {
$sql .= " {$glue} {$piece[2]} ";
$glue = NULL;
}
break;
}
}
return $sql;
});

View File

@@ -0,0 +1,2 @@
This folder has been reserved for your plugins