The toolbox is an integral part of RedBeanPHP providing the basic architectural building blocks to manager objects, helpers and additional tools like plugins. A toolbox contains the three core components of RedBeanPHP: the adapter, the query writer and the core functionality of RedBeanPHP in OODB.
Author: Gabor de Mooij and the RedBeanPHP community
Example #1
0
 /**
  * Returns a label or an array of labels for use as ENUMs.
  * 
  * @param string $enum ENUM specification for label
  * 
  * @return array|OODBBean
  */
 public function enum($enum)
 {
     $oodb = $this->toolbox->getRedBean();
     if (strpos($enum, ':') === FALSE) {
         $type = $enum;
         $value = FALSE;
     } else {
         list($type, $value) = explode(':', $enum);
         $value = preg_replace('/\\W+/', '_', strtoupper(trim($value)));
     }
     $values = $oodb->find($type);
     if ($value === FALSE) {
         return $values;
     }
     foreach ($values as $enumItem) {
         if ($enumItem->name === $value) {
             return $enumItem;
         }
     }
     $newEnumItems = $this->dispenseLabels($type, array($value));
     $newEnumItem = reset($newEnumItems);
     $oodb->store($newEnumItem);
     return $newEnumItem;
 }
Example #2
0
 /**
  * Makes a copy of a bean. This method makes a deep copy
  * of the bean.The copy will have the following features.
  * - All beans in own-lists will be duplicated as well
  * - All references to shared beans will be copied but not the shared beans themselves
  * - All references to parent objects (_id fields) will be copied but not the parents themselves
  * In most cases this is the desired scenario for copying beans.
  * This function uses a trail-array to prevent infinite recursion, if a recursive bean is found
  * (i.e. one that already has been processed) the ID of the bean will be returned.
  * This should not happen though.
  *
  * Note:
  * This function does a reflectional database query so it may be slow.
  *
  * Note:
  * this function actually passes the arguments to a protected function called
  * duplicate() that does all the work. This method takes care of creating a clone
  * of the bean to avoid the bean getting tainted (triggering saving when storing it).
  *
  * @param OODBBean $bean        bean to be copied
  * @param array    $trail       for internal usage, pass array()
  * @param boolean  $preserveIDs for internal usage
  *
  * @return OODBBean
  */
 public function dup(OODBBean $bean, $trail = array(), $preserveIDs = FALSE)
 {
     if (!count($this->tables)) {
         $this->tables = $this->toolbox->getWriter()->getTables();
     }
     if (!count($this->columns)) {
         foreach ($this->tables as $table) {
             $this->columns[$table] = $this->toolbox->getWriter()->getColumns($table);
         }
     }
     $rs = $this->duplicate(clone $bean, $trail, $preserveIDs);
     if (!$this->cacheTables) {
         $this->tables = array();
         $this->columns = array();
     }
     return $rs;
 }
Example #3
0
 /**
  * Configures the facade, want to have a new Writer? A new Object Database or a new
  * Adapter and you want it on-the-fly? Use this method to hot-swap your facade with a new
  * toolbox.
  *
  * @param ToolBox $tb toolbox to configure facade with
  *
  * @return ToolBox
  */
 public static function configureFacadeWithToolbox(ToolBox $tb)
 {
     $oldTools = self::$toolbox;
     self::$toolbox = $tb;
     self::$writer = self::$toolbox->getWriter();
     self::$adapter = self::$toolbox->getDatabaseAdapter();
     self::$redbean = self::$toolbox->getRedBean();
     self::$finder = new Finder(self::$toolbox);
     self::$associationManager = new AssociationManager(self::$toolbox);
     self::$redbean->setAssociationManager(self::$associationManager);
     self::$labelMaker = new LabelMaker(self::$toolbox);
     $helper = new SimpleModelHelper();
     $helper->attachEventListeners(self::$redbean);
     self::$redbean->setBeanHelper(new SimpleFacadeBeanHelper());
     self::$duplicationManager = new DuplicationManager(self::$toolbox);
     self::$tagManager = new TagManager(self::$toolbox);
     return $oldTools;
 }
Example #4
0
 /**
  * Fetches an ENUM from the database and creates it if necessary.
  * An ENUM has the following format:
  *
  * <code>
  * ENUM:VALUE
  * </code>
  *
  * If you pass 'ENUM' only, this method will return an array of its
  * values:
  *
  * <code>
  * implode( ',', R::gatherLabels( R::enum( 'flavour' ) ) ) //'BANANA,MOCCA'
  * </code>
  *
  * If you pass 'ENUM:VALUE' this method will return the specified enum bean
  * and create it in the database if it does not exist yet:
  *
  * <code>
  * $bananaFlavour = R::enum( 'flavour:banana' );
  * $bananaFlavour->name;
  * </code>
  *
  * So you can use this method to set an ENUM value in a bean:
  *
  * <code>
  * $shake->flavour = R::enum( 'flavour:banana' );
  * </code>
  *
  * the property flavour now contains the enum bean, a parent bean.
  * In the database, flavour_id will point to the flavour record with name 'banana'.
  *
  * @param string $enum ENUM specification for label
  *
  * @return array|OODBBean
  */
 public function enum($enum)
 {
     $oodb = $this->toolbox->getRedBean();
     if (strpos($enum, ':') === FALSE) {
         $type = $enum;
         $value = FALSE;
     } else {
         list($type, $value) = explode(':', $enum);
         $value = preg_replace('/\\W+/', '_', strtoupper(trim($value)));
     }
     /**
      * We use simply find here, we could use inspect() in fluid mode etc,
      * but this would be useless. At first sight it looks clean, you could even
      * bake this into find(), however, find not only has to deal with the primary
      * search type, people can also include references in the SQL part, so avoiding
      * find failures does not matter, this is still the quickest way making use
      * of existing functionality.
      *
      * @note There seems to be a bug in XDebug v2.3.2 causing suppressed
      * exceptions like these to surface anyway, to prevent this use:
      *
      * "xdebug.default_enable = 0"
      *
      *  Also see Github Issue #464
      */
     $values = $oodb->find($type);
     if ($value === FALSE) {
         return $values;
     }
     foreach ($values as $enumItem) {
         if ($enumItem->name === $value) {
             return $enumItem;
         }
     }
     $newEnumItems = $this->dispenseLabels($type, array($value));
     $newEnumItem = reset($newEnumItems);
     $oodb->store($newEnumItem);
     return $newEnumItem;
 }
 /**
  * Constructor
  *
  * @param ToolBox $tools toolbox
  */
 public function __construct(ToolBox $tools)
 {
     $this->oodb = $tools->getRedBean();
     $this->adapter = $tools->getDatabaseAdapter();
     $this->writer = $tools->getWriter();
     $this->toolbox = $tools;
 }
Example #6
0
 /**
  * Constructor.
  * The Finder requires a toolbox.
  *
  * @param ToolBox $toolbox
  */
 public function __construct(ToolBox $toolbox)
 {
     $this->toolbox = $toolbox;
     $this->redbean = $toolbox->getRedBean();
 }
Example #7
0
 /**
  * Constructor.
  * The tag manager offers an easy way to quickly implement basic tagging
  * functionality.
  *
  * @param ToolBox $toolbox
  */
 public function __construct(ToolBox $toolbox)
 {
     $this->toolbox = $toolbox;
     $this->redbean = $toolbox->getRedBean();
     $this->associationManager = $this->redbean->getAssociationManager();
 }
Example #8
0
 /**
  * Returns all beans that have been tagged with ALL of the tags given.
  *
  * Tag list can be either an array with tag names or a comma separated list
  * of tag names.
  *
  * @param string        $beanType type of bean you are looking for
  * @param array|string  $tagList  list of tags to match
  *
  * @return array
  */
 public function taggedAll($beanType, $tagList, $sql = '', $bindings = array())
 {
     $tags = $this->extractTagsIfNeeded($tagList);
     $records = $this->toolbox->getWriter()->queryTagged($beanType, $tags, TRUE, $sql, $bindings);
     return $this->redbean->convertToBeans($beanType, $records);
 }
Example #9
0
 /**
  * Returns a hashmap with bean arrays keyed by type using an SQL
  * query as its resource. Given an SQL query like 'SELECT movie.*, review.* FROM movie... JOIN review'
  * this method will return movie and review beans.
  *
  * Example:
  *
  * $stuff = $finder->findMulti('movie,review', '
  *          SELECT movie.*, review.* FROM movie
  *          LEFT JOIN review ON review.movie_id = movie.id');
  *
  * After this operation, $stuff will contain an entry 'movie' containing all
  * movies and an entry named 'review' containing all reviews (all beans).
  * You can also pass bindings.
  *
  * If you want to re-map your beans, so you can use $movie->ownReviewList without
  * having RedBeanPHP executing an SQL query you can use the fourth parameter to
  * define a selection of remapping closures.
  *
  * The remapping argument (optional) should contain an array of arrays.
  * Each array in the remapping array should contain the following entries:
  *
  * array(
  * 	'a'       => TYPE A
  *    'b'       => TYPE B
  *    'matcher' => MATCHING FUNCTION ACCEPTING A, B and ALL BEANS
  *    'do'      => OPERATION FUNCTION ACCEPTING A, B, ALL BEANS, ALL REMAPPINGS
  * )
  *
  * Using this mechanism you can build your own 'preloader' with tiny function
  * snippets (and those can be re-used and shared online of course).
  *
  * Example:
  *
  * array(
  * 	'a'       => 'movie'     //define A as movie
  *    'b'       => 'review'    //define B as review
  *    'matcher' => function( $a, $b ) {
  *       return ( $b->movie_id == $a->id );  //Perform action if review.movie_id equals movie.id
  *    }
  *    'do'      => function( $a, $b ) {
  *       $a->noLoad()->ownReviewList[] = $b; //Add the review to the movie
  *       $a->clearHistory();                 //optional, act 'as if these beans have been loaded through ownReviewList'.
  *    }
  * )
  *
  * The Query Template parameter is optional as well but can be used to
  * set a different SQL template (sprintf-style) for processing the original query.
  *
  * @note the SQL query provided IS NOT THE ONE used internally by this function,
  * this function will pre-process the query to get all the data required to find the beans.
  *
  * @note if you use the 'book.*' notation make SURE you're
  * selector starts with a SPACE. ' book.*' NOT ',book.*'. This is because
  * it's actually an SQL-like template SLOT, not real SQL.
  *
  * @note instead of an SQL query you can pass a result array as well.
  *
  * @param string|array $types         a list of types (either array or comma separated string)
  * @param string|array $sqlOrArr      an SQL query or an array of prefetched records
  * @param array        $bindings      optional, bindings for SQL query
  * @param array        $remappings    optional, an array of remapping arrays
  * @param string       $queryTemplate optional, query template
  *
  * @return array
  */
 public function findMulti($types, $sql, $bindings = array(), $remappings = array(), $queryTemplate = ' %s.%s AS %s__%s')
 {
     if (!is_array($types)) {
         $types = explode(',', $types);
     }
     if (!is_array($sql)) {
         $writer = $this->toolbox->getWriter();
         $adapter = $this->toolbox->getDatabaseAdapter();
         //Repair the query, replace book.* with book.id AS book_id etc..
         foreach ($types as $type) {
             $pattern = " {$type}.*";
             if (strpos($sql, $pattern) !== FALSE) {
                 $newSelectorArray = array();
                 $columns = $writer->getColumns($type);
                 foreach ($columns as $column => $definition) {
                     $newSelectorArray[] = sprintf($queryTemplate, $type, $column, $type, $column);
                 }
                 $newSelector = implode(',', $newSelectorArray);
                 $sql = str_replace($pattern, $newSelector, $sql);
             }
         }
         $rows = $adapter->get($sql, $bindings);
     } else {
         $rows = $sql;
     }
     //Gather the bean data from the query results using the prefix
     $wannaBeans = array();
     foreach ($types as $type) {
         $wannaBeans[$type] = array();
         $prefix = "{$type}__";
         foreach ($rows as $rowkey => $row) {
             $wannaBean = array();
             foreach ($row as $cell => $value) {
                 if (strpos($cell, $prefix) === 0) {
                     $property = substr($cell, strlen($prefix));
                     unset($rows[$rowkey][$cell]);
                     $wannaBean[$property] = $value;
                 }
             }
             if (!isset($wannaBean['id'])) {
                 continue;
             }
             if (is_null($wannaBean['id'])) {
                 continue;
             }
             $wannaBeans[$type][$wannaBean['id']] = $wannaBean;
         }
     }
     //Turn the rows into beans
     $beans = array();
     foreach ($wannaBeans as $type => $wannabees) {
         $beans[$type] = $this->redbean->convertToBeans($type, $wannabees);
     }
     //Apply additional re-mappings
     foreach ($remappings as $remapping) {
         $a = $remapping['a'];
         $b = $remapping['b'];
         $matcher = $remapping['matcher'];
         $do = $remapping['do'];
         foreach ($beans[$a] as $bean) {
             foreach ($beans[$b] as $putBean) {
                 if ($matcher($bean, $putBean, $beans)) {
                     $do($bean, $putBean, $beans, $remapping);
                 }
             }
         }
     }
     return $beans;
 }