Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

RESTful BeanCan

  • Loading branch information...
commit ade919e616e2a745f921b81d71f248b9cf73ee1b 1 parent 26c77d8
@gabordemooij authored
View
36 RedBean/Finder.php
@@ -132,17 +132,39 @@ public function findOrDispense($type, $sql = null, $values = array()) {
$foundBeans = $this->find($type, $sql, $values);
if (count($foundBeans) == 0) return array($this->redbean->dispense($type)); else return $foundBeans;
}
-
-
+ /**
+ * Returns the bean identified by the RESTful path.
+ * For instance:
+ *
+ * $user
+ * /site/1/page/3
+ *
+ * returns page with ID 3 in ownPage of site 1 in ownSite of
+ * $user bean.
+ *
+ * Works with shared lists as well:
+ *
+ * $user
+ * /site/1/page/3/shared-ad/4
+ *
+ * Note that this method will open all intermediate beans so you can
+ * attach access control rules to each bean in the path.
+ *
+ * @param RedBean_OODBBean $bean
+ * @param array $steps (an array representation of a REST path)
+ *
+ * @return RedBean_OODBBean
+ */
public function findByPath($bean, $steps) {
$n = count($steps);
if ($n % 2) throw new RedBean_Exception_Security('Invalid path: needs 1 more element.');
for($i = 0; $i < $n; $i += 2) {
- $listName = 'own'.ucfirst($steps[$i]);
- $bean = $bean->withCondition(' id = ? ',array($steps[$i + 1]))->$listName[$steps[$i + 1]];
- return null;
+ if (strpos($steps[$i],'shared-') === false) $listName = 'own'.ucfirst($steps[$i]); else $listName = 'shared'.ucfirst(substr($steps[$i],7));
+ $list = $bean->withCondition(' id = ? ',array($steps[$i + 1]))->$listName;
+ if (!is_array($list)) throw new RedBean_Exception_Security('Cannot access list.');
+ if (!isset($list[$steps[$i + 1]])) throw new RedBean_Exception_Security('Cannot access bean.');
+ $bean = $list[$steps[$i + 1]];
}
return $bean;
}
-
-}
+}
View
48 RedBean/Plugin/BeanCan.php
@@ -162,10 +162,20 @@ public function handleRESTGetRequest($pathToResource) {
}
}
-
+ /**
+ * Handles a REST request.
+ * Returns a JSON response string.
+ *
+ * @param RedBean_Bean $root root bean for REST action
+ * @param string $uri the URI of the RESTful operation
+ * @param string $method the method you want to apply
+ * @param array $payload payload (for POSTs)
+ *
+ * @return string
+ */
public function handleREST($root, $uri, $method, $payload = array()) {
try {
- $finder = new RedBean_Finder(RedBean_Facade::getToolbox());
+ $finder = new RedBean_Finder(RedBean_Facade::$toolbox);
$uri = explode('/', $uri);
if ($method == 'PUT') {
$list = array_pop($uri); //grab the list
@@ -174,26 +184,29 @@ public function handleREST($root, $uri, $method, $payload = array()) {
if ($bean) {
if ($method == 'GET') {
return $this->resp($bean->export());
- }
- elseif ($method == 'DELETE') {
+ } elseif ($method == 'DELETE') {
RedBean_Facade::trash($bean);
return $this->resp('OK');
- }
- elseif ($method == 'POST') {
+ } elseif ($method == 'POST') {
$bean->import($payload['bean']);
$id = RedBean_Facade::store($bean);
- return $this->resp($id);
- }
- elseif ($method == 'PUT') {
+ $bean = RedBean_Facade::load($bean->getMeta('type'), $bean->id);
+ return $this->resp($bean->export());
+ } elseif ($method == 'PUT') {
$newBean = RedBean_Facade::dispense($payload['type']);
$newBean->import($payload['bean']);
- $bean->$list[] = $newBean;
+ if (strpos($list, 'shared-') === false) {
+ $listName = 'own'.ucfirst($list);
+ } else {
+ $listName = 'shared'.ucfirst(substr($list,7));
+ }
+ array_push($bean->$listName, $newBean);
RedBean_Facade::store($bean);
- return $this->resp($newBean->id);
- }
- else {
- $answer = call_user_func(array($bean,$payload['param']));
- $this->resp($answer);
+ $newBean = RedBean_Facade::load($newBean->getMeta('type'), $newBean->id);
+ return $this->resp($newBean->export());
+ } else {
+ $answer = call_user_func_array(array($bean,$method),$payload['param']);
+ return $this->resp($answer);
}
}
}
@@ -201,7 +214,4 @@ public function handleREST($root, $uri, $method, $payload = array()) {
return $this->resp(null, 0, -32099);
}
}
-
-
-
-}
+}
View
117 testing/RedUNIT/Plugin/Beancan.php
@@ -35,17 +35,105 @@ public function run() {
$site->name = 'site 1';
$page = R::dispense('page');
$page->name = 'page 1';
- $site->sharedPage[] = $page;
+ $ad = R::dispense('ad');
+ $ad->name = 'an ad';
+ $ad2 = R::dispense('ad');
+ $ad2->name = 'an ad2';
+ $page->sharedAd[] = $ad;
+ $page->sharedAd[] = $ad2;
+ $site->ownPage[] = $page;
$user->ownSite[] = $site;
R::store($user);
$can = new RedBean_Plugin_BeanCan;
-
- $resp = $can->handleREST($user, 'page/'.$page->id , 'GET');
- echo $resp;
+ //Send a GET /site/1 request to BeanCan Server
+ $resp = $can->handleREST($user, 'site/'.$site->id , 'GET');
+ $resp = json_decode($resp, true);
+ asrt((string)$resp['result']['id'], (string)$site->id);
+ asrt((string)$resp['result']['name'], (string)$site->name);
+ asrt((string)$resp['result']['user_id'], (string)$site->user_id);
+ //Send a GET /site/1/page/1 request to BeanCan Server
+ $resp = $can->handleREST($user, 'site/'.$site->id.'/page/'.$page->id , 'GET');
+ $resp = json_decode($resp, true);
+ asrt((string)$resp['result']['id'], (string)$page->id);
+ asrt((string)$resp['result']['name'], (string)$page->name);
+ asrt((string)$resp['result']['site_id'], (string)$page->site_id);
+ //Send a GET /site/1/page/1/shared-ad/1
+ $resp = $can->handleREST($user, 'site/'.$site->id.'/page/'.$page->id.'/shared-ad/'.$ad->id, 'GET');
+ $resp = json_decode($resp, true);
+ asrt((string)$resp['result']['id'], (string)$ad->id);
+ asrt((string)$resp['result']['name'], (string)$ad->name);
+ //Send a PUT /site/1/page
+ $payLoad = array(
+ 'type' => 'page',
+ 'bean' => array(
+ 'name' => 'my new page'
+ )
+ );
+ $resp = $can->handleREST($user, 'site/'.$site->id.'/page', 'PUT', $payLoad);
+ $resp = json_decode($resp, true);
+ $newPage = R::findOne('page',' name = ? ',array('my new page'));
+ asrt((string)$resp['result']['id'], (string)$newPage->id);
+ asrt((string)$resp['result']['name'], (string)$newPage->name);
+ //Send a PUT /site/1/page/2/shared-ad
+ $payLoad = array(
+ 'type' => 'ad',
+ 'bean' => array(
+ 'name' => 'my new ad'
+ )
+ );
+ $resp = $can->handleREST($user, 'site/'.$site->id.'/page/'.$page->id.'/shared-ad', 'PUT', $payLoad);
+ $resp = json_decode($resp, true);
+ $newAd = R::findOne('ad',' name = ? ',array('my new ad'));
+ asrt((string)$resp['result']['id'], (string)$newAd->id);
+ asrt((string)$resp['result']['name'], (string)$newAd->name);
+ //Send a POST /site/1
+ $payLoad = array(
+ 'bean' => array(
+ 'name' => 'The Original'
+ )
+ );
+ $resp = $can->handleREST($user, 'site/'.$site->id, 'POST', $payLoad);
+ $resp = json_decode($resp, true);
+ asrt((string)$resp['result']['id'], (string)$site->id);
+ asrt((string)$resp['result']['name'], 'The Original');
+
+ //Send a DELETE /site/1/page/2/shared-ad/2
+ $resp = $can->handleREST($user, 'site/'.$site->id.'/page/'.$page->id.'/shared-ad/'.$newAd->id, 'DELETE');
+ $resp = json_decode($resp, true);
+ $newAd = R::findOne('ad',' name = ? ',array('my new ad'));
+ asrt((string)$resp['result'], 'OK');
+ asrt($newAd, null);
+
+ //Send a MAIL /site/1/page/1
+ $resp = $can->handleREST($user, 'site/'.$site->id.'/page/'.$page->id, 'mail', array('param'=>array('me')));
+ $resp = json_decode($resp, true);
+ asrt((string)$resp['result'], 'mail has been sent to me');
+
+ //test Access control
+ $setting = R::dispense('setting');
+ $option = R::dispense('option');
+ $setting->ownOption[] = $option;
+ $user->ownSetting[] = $setting;
+ $option->name = 'secret';
+ R::store($user);
+ $resp = $can->handleREST($user, 'setting/'.$setting->id.'/option/'.$option->id, 'GET');
+ $resp = json_decode($resp, true);
+ asrt($resp['result']['name'], 'secret');
+ $user2 = R::load('user', R::store(R::dispense('user')));
+ $resp = $can->handleREST($user2, 'setting/'.$setting->id.'/option/'.$option->id, 'GET');
+ $resp = json_decode($resp, true);
+ asrt(isset($resp['error']),true);
+ Model_Setting::$closed = true;
+ $resp = $can->handleREST($user, 'setting/'.$setting->id.'/option/'.$option->id, 'GET');
+ $resp = json_decode($resp, true);
+ asrt(isset($resp['error']),true);
+ Model_Setting::$closed = false;
+
+ testpack("Test BeanCan Server 1 / create");
+ R::nuke();
$rs = ( s("candybar:store",array( array("brand"=>"funcandy","taste"=>"sweet") ) ) );
- testpack("Test create");
asrt(is_string($rs),true);
$rs = json_decode($rs,true);
asrt(is_array($rs),true);
@@ -325,9 +413,20 @@ public function run() {
$can->setWhitelist('all');
$rs = json_decode( $can->handleJSONRequest('{"jsonrpc":"2.0","method":"foo:load","params":['.$id.'],"id":0}'), true);
asrt(isset($rs['id']),true);
- asrt($rs['id'],0);
-
+ asrt($rs['id'],0);
}
-
-
}
+
+
+class Model_Page extends RedBean_SimpleModel {
+ public function mail($who) {
+ return 'mail has been sent to '.$who;
+ }
+}
+
+class Model_Setting extends RedBean_SimpleModel {
+ public static $closed = false;
+ public function open() {
+ if (self::$closed) throw new Exception('closed');
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.