Permalink
Browse files

Added link() for on-the-fly intermediate bean creation.

  • Loading branch information...
1 parent 060c195 commit f1694235b5024e77e7acb39038f1f976df6e969d @gabordemooij committed Dec 1, 2012
Showing with 78 additions and 2 deletions.
  1. +42 −0 RedBean/OODBBean.php
  2. +36 −2 testing/RedUNIT/Base/Relations.php
View
@@ -727,6 +727,48 @@ public function hasChanged($property) {
if (!isset($this->properties[$property])) return false;
return ($this->old($property)!=$this->properties[$property]);
}
+
+ /**
+ * Creates a N-M relation by linking an intermediate bean.
+ * This method can be used to quickly connect beans using indirect
+ * relations. For instance, given an album and a song you can connect the two
+ * using a track with a number like this:
+ *
+ * Usage:
+ *
+ * $album->link('track',array('number'=>1))->song = $song;
+ *
+ * or:
+ *
+ * $album->link($trackBean)->song = $song;
+ *
+ * What this method does is adding the link bean to the own-list, in this case
+ * ownTrack. If the first argument is a string and the second is an array or
+ * a JSON string then the linking bean gets dispensed on-the-fly as seen in
+ * example #1. After preparing the linking bean, the bean is returned thus
+ * allowing the chained setter: ->song = $song.
+ *
+ * @param string|RedBean_OODBBean $type type of bean to dispense or the full bean
+ * @param string|array $qualification JSON string or array (optional)
+ */
+ public function link($typeOrBean,$qualification = array()) {
+ if (is_string($typeOrBean)) {
+ $bean = $this->beanHelper->getToolBox()->getRedBean()->dispense($typeOrBean);
+ if (is_string($qualification)) {
+ $data = json_decode($qualification, true);
+ } else {
+ $data = $qualification;
+ }
+ foreach($data as $key=>$value) {
+ $bean->$key = $value;
+ }
+ } else {
+ $bean = $typeOrBean;
+ }
+ $list = 'own'.ucfirst($bean->getMeta('type'));
+ array_push($this->$list,$bean);
+ return $bean;
+ }
}
@@ -481,8 +481,42 @@ public function run() {
asrt(R::count('village'),1);
asrt(R::count('building'),0);
-
-
+ //test N-M relations through intermediate beans
+ R::nuke();
+ list($mrA,$mrB,$mrC) = R::dispense('person',3);
+ list($projA,$projB,$projC) = R::dispense('project',3);
+ $projA->title = 'A';
+ $projB->title = 'B';
+ $projC->title = 'C';
+ $participant = R::dispense('participant');
+ $projA->link('participant',array('role'=>'manager'))->person = $mrA;
+ $projA->link($participant->setAttr('role','developer'))->person = $mrB;
+ $projB->link(R::dispense('participant')->setAttr('role','developer'))->person = $mrB;
+ $projB->link('participant','{"role":"helpdesk"}')->person = $mrC;
+ $projC->link('participant','{"role":"sales"}')->person = $mrC;
+ R::storeAll(array($projA,$projB,$projC));
+ $a = R::findOne('project',' title = ? ',array('A'));
+ $b = R::findOne('project',' title = ? ',array('B'));
+ $c = R::findOne('project',' title = ? ',array('C'));
+ asrt(count($a->ownParticipant),2);
+ asrt(count($b->ownParticipant),2);
+ asrt(count($c->ownParticipant),1);
+ $managers = $developers = 0;
+ foreach($a->ownParticipant as $p) {
+ if ($p->role === 'manager') {
+ $managers ++;
+ }
+ if ($p->role === 'developer') {
+ $developers ++;
+ }
+ }
+ $p = reset($a->ownParticipant);
+ asrt($p->person->getMeta('type'),'person');
+ asrt(($p->person->id >0),true);
+ asrt($managers,1);
+ asrt($developers,1);
+ asrt((int)R::count('participant'),5);
+ asrt((int)R::count('person'),3);
}
}

0 comments on commit f169423

Please sign in to comment.