From e109ac072f5c9ec5e0abe501ccd0043433ac132e Mon Sep 17 00:00:00 2001
From: Henrique Recidive <recidive@gmail.com>
Date: Thu, 3 May 2012 18:31:38 -0300
Subject: [PATCH] Issue #1559944: Add support for Services module.

---
 bean_service/bean_service.inc    |  162 ++++++++++++++++++++++++++++++++++++++
 bean_service/bean_service.info   |    8 ++
 bean_service/bean_service.module |  134 +++++++++++++++++++++++++++++++
 3 files changed, 304 insertions(+), 0 deletions(-)
 create mode 100644 bean_service/bean_service.inc
 create mode 100644 bean_service/bean_service.info
 create mode 100644 bean_service/bean_service.module

diff --git a/bean_service/bean_service.inc b/bean_service/bean_service.inc
new file mode 100644
index 0000000..f062510
--- /dev/null
+++ b/bean_service/bean_service.inc
@@ -0,0 +1,162 @@
+<?php
+
+/**
+ * @file
+ * Contains callbacks for service resource manipulation.
+ */
+
+/**
+ * Adds a new bean to a node and returns the bid.
+ *
+ * @param $bean
+ *   An object as would be returned from bean_load().
+ * @return
+ *   Unique identifier for the bean (bid) or errors if there was a problem.
+ */
+function bean_service_create($bean) {
+  // Adds backwards compatibility with regression fixed in #1083242.
+  $bean = _services_arg_value($bean, 'bean');
+
+  if (empty($bean['type'])) {
+    return services_error(t('A type must be provided.'));
+  }
+
+  // Setup form_state.
+  $form_state = array();
+  $form_state['values'] = $bean;
+  $form_state['values']['op'] = t('Save');
+
+  $bean_new = bean_create(array('type' => $bean['type']));
+
+  $ret = drupal_form_submit('bean_form', $form_state, $bean_new);
+
+  // Error if needed.
+  if ($errors = form_get_errors()) {
+    return services_error(implode(" ", $errors), 406, array('form_errors' => $errors));
+  }
+
+  $bean = $form_state['bean'];
+
+  return array(
+    'bid' => $bean->bid,
+    'uri' => services_resource_uri(array('bean', $bean->bid)),
+  );
+}
+
+/**
+ * Updates a bean and returns the bid.
+ *
+ * @param $bid
+ *   Unique identifier for this bean.
+ * @param $bean
+ *   An object as would be returned from bean_load().
+ * @return
+ *   Unique identifier for the bean (bid) or FALSE if there was a problem.
+ */
+function bean_service_update($bid, $bean) {
+  // Adds backwards compatibility with regression fixed in #1083242.
+  $bean = _services_arg_value($bean, 'data');
+  $bean['bid'] = $bid;
+
+  $old_bean = bean_load($bid);
+  if (empty($old_bean)) {
+    return services_error(t('Bean @bid not found.', array('@bid' => $bid)), 404);
+  }
+
+  // Setup form_state.
+  $form_state = array();
+  $form_state['values'] = $bean;
+  $form_state['values']['op'] = t('Save');
+  $form_state['bean'] = $old_bean;
+
+  drupal_form_submit('bean_form', $form_state, $old_bean);
+
+  if ($errors = form_get_errors()) {
+    return services_error(implode(" ", $errors), 406, array('form_errors' => $errors));
+  }
+
+  return $bid;
+}
+
+/**
+ * Returns a specified bean.
+ *
+ * @param $bid
+ *   Unique identifier for the specified bean.
+ * @return
+ *   The bean object.
+ */
+function bean_service_retrieve($bid) {
+  return bean_load($bid);
+}
+
+/**
+ * Delete a bean.
+ *
+ * @param $bid
+ *   Unique identifier of the bean to delete.
+ * @return
+ *   True.
+ */
+function bean_service_delete($bid) {
+  $bean = bean_load($bid);
+  if (empty($bean)) {
+    return services_error(t('There is no bean found with id @bid.', array('@bid' => $bid)), 404);
+  }
+
+  // Delete bean.
+  bean_delete($bean);
+
+  // Clear the cache so an anonymous user sees that his bean was deleted.
+  cache_clear_all();
+  return TRUE;
+}
+
+/**
+ * Return an array of optionally paged bids based on a set of criteria.
+ *
+ * An example request might look like:
+ *
+ * http://domain/endpoint/bean?fields=bid,label&parameters[type]=mytype
+ *
+ * This would return an array of objects with only bid and label defined, where
+ * type = 'mytype'.
+ *
+ * @param $page
+ *   Page number of results to return (in pages of 20).
+ * @param $fields
+ *   The fields you want returned.
+ * @param $parameters
+ *   An array containing fields and values used to build a sql WHERE clause
+ *   indicating items to retrieve.
+ * @param $page_size
+ *   Integer number of items to be returned.
+ * @return
+ *   An array of bean objects.
+ **/
+function bean_service_index($page, $fields, $parameters, $page_size) {
+  $bean_select = db_select('bean', 'b')
+    ->orderBy('created', 'DESC');
+
+  services_resource_build_index_query($bean_select, $page, $fields, $parameters, $page_size, 'bean');
+
+  $results = services_resource_execute_index_query($bean_select);
+
+  return services_resource_build_index_list($results, 'bean', 'bid');
+}
+
+/**
+ * Access callback for the bean resource.
+ *
+ * @param $op
+ *  The operation that's going to be performed.
+ * @param $args
+ *  The arguments that will be passed to the callback.
+ * @return
+ *  Whether access is given or not.
+ */
+function bean_service_access($op, $args) {
+  $bean = empty($args[0]) ? NULL : $args[0];
+
+  return bean_access($op, $bean);
+}
diff --git a/bean_service/bean_service.info b/bean_service/bean_service.info
new file mode 100644
index 0000000..b2e81eb
--- /dev/null
+++ b/bean_service/bean_service.info
@@ -0,0 +1,8 @@
+name = Bean Service
+description = Provides a service resource for manipulating beans through webservices provided by Services module.
+package = Services
+
+dependencies[] = bean
+dependencies[] = services
+
+core = 7.x
diff --git a/bean_service/bean_service.module b/bean_service/bean_service.module
new file mode 100644
index 0000000..9905fce
--- /dev/null
+++ b/bean_service/bean_service.module
@@ -0,0 +1,134 @@
+<?php
+
+/**
+ * @file
+ * Provide services integration for Bean module.
+ */
+
+/**
+ * Implements hook_services_resources().
+ */
+function bean_service_services_resources() {
+  return array(
+    'bean' => array(
+      'retrieve' => array(
+        'help' => 'Retrieves a bean',
+        'file' => array('file' => 'inc', 'module' => 'bean_service'),
+        'callback' => 'bean_service_retrieve',
+        'access callback' => 'bean_service_access',
+        'access arguments' => array('view'),
+        'access arguments append' => TRUE,
+        'args' => array(
+          array(
+            'name' => 'bid',
+            'type' => 'int',
+            'description' => 'The id of the bean to get',
+            'source' => array('path' => '0'),
+            'optional' => FALSE,
+          ),
+        ),
+      ),
+      'create' => array(
+        'help' => 'Creates a bean',
+        'file' => array('file' => 'inc', 'module' => 'bean_service'),
+        'callback' => 'bean_service_create',
+        'access callback' => 'bean_service_access',
+        'access arguments' => array('add'),
+        'access arguments append' => TRUE,
+        'args' => array(
+          array(
+            'name' => 'data',
+            'type' => 'struct',
+            'description' => 'The bean object',
+            'source' => 'data',
+            'optional' => FALSE,
+          ),
+        ),
+      ),
+      'update' => array(
+        'help' => 'Updates a bean',
+        'file' => array('file' => 'inc', 'module' => 'bean_service'),
+        'callback' => 'bean_service_update',
+        'access callback' => 'bean_service_access',
+        'access arguments' => array('edit'),
+        'access arguments append' => TRUE,
+        'args' => array(
+          array(
+            'name' => 'bid',
+            'type' => 'int',
+            'description' => 'The id of the bean to update',
+            'source' => array('path' => '0'),
+            'optional' => FALSE,
+          ),
+          array(
+            'name' => 'data',
+            'type' => 'struct',
+            'description' => 'The bean data object',
+            'source' => 'data',
+            'optional' => FALSE,
+          ),
+        ),
+      ),
+      'delete' => array(
+        'help' => 'Deletes a bean',
+        'file' => array('file' => 'inc', 'module' => 'bean_service'),
+        'callback' => 'bean_service_delete',
+        'access callback' => 'bean_service_access',
+        'access arguments' => array('delete'),
+        'access arguments append' => TRUE,
+        'args' => array(
+          array(
+            'name' => 'bid',
+            'type' => 'int',
+            'description' => 'The id of the bean to delete',
+            'source' => array('path' => '0'),
+            'optional' => FALSE,
+          ),
+        ),
+      ),
+      'index' => array(
+        'help' => 'Retrieves a listing of beans',
+        'file' => array('file' => 'inc', 'module' => 'bean_service'),
+        'callback' => 'bean_service_index',
+        // TODO: not sure what permission is required here.
+        'access callback' => 'user_access',
+        'access arguments' => array('access content'),
+        'access arguments append' => FALSE,
+        'args' => array(
+          array(
+            'name' => 'page',
+            'optional' => TRUE,
+            'type' => 'int',
+            'description' => 'The zero-based index of the page to get, defaults to 0.',
+            'default value' => 0,
+            'source' => array('param' => 'page'),
+          ),
+          array(
+            'name' => 'fields',
+            'optional' => TRUE,
+            'type' => 'string',
+            'description' => 'The fields to get.',
+            'default value' => '*',
+            'source' => array('param' => 'fields'),
+          ),
+          array(
+            'name' => 'parameters',
+            'optional' => TRUE,
+            'type' => 'array',
+            'description' => 'Parameters',
+            'default value' => array(),
+            'source' => array('param' => 'parameters'),
+          ),
+          array(
+            'name' => 'pagesize',
+            'optional' => TRUE,
+            'type' => 'int',
+            'description' => 'Number of records to get per page.',
+            'default value' => 20,
+            'source' => array('param' => 'pagesize'),
+          ),
+        ),
+      ),
+    ),
+  );
+}
-- 
1.7.9.1

