From 3d32eaf9b8cd900632051eae841380dbc8c1c925 Mon Sep 17 00:00:00 2001
From: marcingy <marcingy@gmail.com>
Date: Sun, 10 Apr 2011 18:50:19 -0600
Subject: [PATCH] reworking index logic

---
 resources/comment_resource.inc  |   70 ++++++++++++++++++++
 resources/file_resource.inc     |   70 +++++++++++++++++++-
 resources/node_resource.inc     |   29 ++-------
 resources/taxonomy_resource.inc |  138 +++++++++++++++++++++++++++++++++++++++
 resources/user_resource.inc     |   31 ++-------
 services.module                 |   51 ++++++++++++++
 6 files changed, 339 insertions(+), 50 deletions(-)

diff --git a/resources/comment_resource.inc b/resources/comment_resource.inc
index 949d033..69f951c 100644
--- a/resources/comment_resource.inc
+++ b/resources/comment_resource.inc
@@ -85,6 +85,39 @@ function _comment_resource_definition() {
           ),
         ),
       ),
+      'index' => array(
+        'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/comment_resource'),
+        'callback' => '_comment_resource_index',
+        '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' => NULL,
+            'source' => array('param' => 'parameters'),
+          ),
+        ),
+        'access callback' => '_comment_resource_access',
+        'access arguments' => array('view'),
+        'access arguments append' => TRUE,
+      ),
       'actions' => array(
         'countAll' => array(
           'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/comment_resource'),
@@ -236,6 +269,43 @@ function _comment_resource_delete($cid) {
   cache_clear_all();
   return TRUE;
 }
+/**
+ * Return an array of optionally paged cids baed on a set of criteria.
+ *
+ * An example request might look like
+ *
+ * http://domain/endpoint/comment?fields=cid,nid&parameters[nid]=7&parameters[uid]=2
+ *
+ * This would return an array of objects with only cid and nid defined, where
+ * nid = 7 and uid = 1.
+ *
+ * @param $page
+ *   Page number of results to return (in pages of 20).
+ * @param $fields
+ *   The fields you want returned.
+ * @param $parameters
+ *   An array of fields and values used to build a sql WHERE clause indicating
+ *   what items should be deleted.
+ * @return
+ *   An array of comment objects.
+ *
+ * @see _node_resource_index() for more notes
+ **/
+function _comment_resource_index($page, $fields, $parameters) {
+  $comment_select = db_select('comment', 't')
+    ->orderBy('sticky', 'DESC')
+    ->orderBy('created', 'DESC');
+
+  services_resource_build_index_query($comment_select, $page, $fields, $parameter);
+
+  if (!user_access('administer comments')) {
+    $comment_select->condition('status', COMMENT_PUBLISHED);
+  }
+
+  $results = $comment_select->execute();
+
+  return services_resource_build_index_list($results, 'comment', 'cid');
+}
 
 /**
  * Returns the number of comments on a given node id.
diff --git a/resources/file_resource.inc b/resources/file_resource.inc
index a3580ed..7bf87cb 100644
--- a/resources/file_resource.inc
+++ b/resources/file_resource.inc
@@ -13,7 +13,6 @@
 function _file_resource_definition() {
   return array(
     'file' => array(
-
       'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/file_resource'),
       'create' => array(
         'help' => 'Creates a file',
@@ -31,7 +30,6 @@ function _file_resource_definition() {
           ),
         ),
       ),
-
       'retrieve' => array(
         'help' => 'Retrieves a file',
         'callback' => '_file_resource_retrieve',
@@ -56,7 +54,6 @@ function _file_resource_definition() {
           ),
         ),
       ),
-
       'delete' => array(
         'help' => 'Deletes a file',
         'callback' => '_file_resource_delete',
@@ -73,6 +70,39 @@ function _file_resource_definition() {
           ),
         ),
       ),
+      'index' => array(
+        'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/file_resource'),
+        'callback' => '_file_resource_index',
+        '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' => NULL,
+            'source' => array('param' => 'parameters'),
+          ),
+        ),
+        'access callback' => '_file_resource_access',
+        'access arguments' => array('view'),
+        'access arguments append' => TRUE,
+      ),
     ),
   );
 }
@@ -171,6 +201,40 @@ function _file_resource_delete($fid) {
 }
 
 /**
+ * Return an array of optionally paged fids baed on a set of criteria.
+ *
+ * An example request might look like
+ *
+ * http://domain/endpoint/file?fields=fid,filename&parameters[fid]=7&parameters[uid]=1
+ *
+ * This would return an array of objects with only fid and filename defined, where
+ * fid = 7 and uid = 1.
+ *
+ * @param $page
+ *   Page number of results to return (in pages of 20).
+ * @param $fields
+ *   The fields you want returned.
+ * @param $parameters
+ *   An array of fields and values used to build a sql WHERE clause indicating
+ *   what items should be deleted.
+ * @return
+ *   An array of file objects.
+ *
+ * @see _node_resource_index() for more notes
+ **/
+function _file_resource_index($page, $fields, $parameters) {
+  $file_select = db_select('files', 't')
+    ->orderBy('timestamp', 'DESC');
+
+  $results = $file_select->execute();
+
+  services_resource_build_index_query($file_select, $page, $fields, $parameter);
+
+  // Put together array of matching files to return.
+  return services_resource_build_index_list($results, 'file', 'fid');
+}
+
+/**
  * Access check callback for file controllers.
  */
 function _file_resource_access($op = 'view', $args = array()) {
diff --git a/resources/node_resource.inc b/resources/node_resource.inc
index 5f7872f..d755dee 100644
--- a/resources/node_resource.inc
+++ b/resources/node_resource.inc
@@ -335,39 +335,20 @@ function _node_resource_delete($nid) {
  *       for index requests more straightforward?
  */
 function _node_resource_index($page, $fields, $parameters) {
-  $node_select = db_select('node', 'n')
+  $node_select = db_select('node', 't')
     ->addTag('node_access')
     ->orderBy('sticky', 'DESC')
-    ->orderBy('created', 'DESC')
-    ->range($page * 20, 20);
+    ->orderBy('created', 'DESC');
 
-  if ($fields == '*') {
-    $node_select->fields('n');
-  }
-  else {
-    $fields = explode(',', $fields);
-    $node_select->fields('n', $fields);
-  }
+  services_resource_build_index_query($node_select, $page, $fields, $parameter);
 
   if (!user_access('administer nodes')) {
     $node_select->condition('status', 1);
   }
 
-  foreach ($parameters as $parameter => $parameter_value) {
-    $node_select->condition($parameter, $parameter_value, '=');
-  }
-
-  $result = $node_select->execute();
-
-  $nodes = array();
-  foreach ($result as $node) {
-    if ($uri = services_resource_uri(array('node', $node->nid))) {
-      $node->uri = $uri;
-    }
-    $nodes[] = $node;
-  }
+  $results = $node_select->execute();
 
-  return $nodes;
+  return services_resource_build_index_list($results, 'node', 'nid');
 }
 
 /**
diff --git a/resources/taxonomy_resource.inc b/resources/taxonomy_resource.inc
index 39c8e55..efd926c 100644
--- a/resources/taxonomy_resource.inc
+++ b/resources/taxonomy_resource.inc
@@ -76,6 +76,39 @@ function _taxonomy_resource_definition() {
         'access arguments append' => TRUE,
         'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/taxonomy_resource'),
       ),
+      'index' => array(
+        'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/taxonomy_resource'),
+        'callback' => '_taxonomy_term_resource_index',
+        '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' => NULL,
+            'source' => array('param' => 'parameters'),
+          ),
+        ),
+        'access callback' => '_taxonomy_resource_access',
+        'access arguments' => array('view'),
+        'access arguments append' => TRUE,
+      ),
       'actions' => array(
         'selectNodes' => array(
           'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/taxonomy_resource'),
@@ -182,6 +215,39 @@ function _taxonomy_resource_definition() {
         'access arguments' => array('administer taxonomy'),
         'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/taxonomy_resource'),
       ),
+      'index' => array(
+        'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/taxonomy_resource'),
+        'callback' => '_taxonomy_vocabulary_resource_index',
+        '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' => NULL,
+            'source' => array('param' => 'parameters'),
+          ),
+        ),
+        'access callback' => '_taxonomy_resource_access',
+        'access arguments' => array('view'),
+        'access arguments append' => TRUE,
+      ),
       'actions' => array(
         'getTree' => array(
           'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/taxonomy_resource'),
@@ -445,3 +511,75 @@ function _taxonomy_resource_delete_access($tid) {
   }
   return user_access('delete terms in ' . $term->vid) || user_access('administer taxonomy');
 }
+
+/**
+ * Return an array of optionally paged tids baed on a set of criteria.
+ *
+ * An example request might look like
+ *
+ * http://domain/endpoint/taxonomy_term?fields=tid,name&parameters[tid]=7&parameters[vid]=1
+ *
+ * This would return an array of objects with only tid and name defined, where
+ * tid = 7 and vid = 1.
+ *
+ * @param $page
+ *   Page number of results to return (in pages of 20).
+ * @param $fields
+ *   The fields you want returned.
+ * @param $parameters
+ *   An array of fields and values used to build a sql WHERE clause indicating
+ *   what items should be returned.
+ * @return
+ *   An array of term objects.
+ *
+ * @see _node_resource_index() for more notes
+ **/
+function _taxonomy_term_resource_index($page, $fields, $parameters) {
+  $taxonomy_select = db_select('taxonomy_term_data', 't')
+    ->orderBy('vid', 'DESC')
+    ->orderBy('weight', 'DESC')
+    ->orderBy('name', 'DESC');
+
+  services_resource_build_index_query($taxonomy_select, $page, $fields, $parameter);
+
+  $results = $taxonomy_select->execute();
+
+  return services_resource_build_index_list($results, 'taxonomy_term', 'tid');
+}
+
+/**
+ * Return an array of optionally paged vids baed on a set of criteria.
+ *
+ * An example request might look like
+ *
+ * http://domain/endpoint/taxonomy_vocabulary?fields=vid,name&parameters[vid]=2
+ *
+ * This would return an array of objects with only vid and name defined, where
+ * vid = 2.
+ *
+ * @param $page
+ *   Page number of results to return (in pages of 20).
+ * @param $fields
+ *   The fields you want returned.
+ * @param $parameters
+ *   An array of fields and values used to build a sql WHERE clause indicating
+ *   what items should be returned.
+ * @return
+ *   An array of vocabulary objects.
+ *
+ * @todo
+ *   Support node types as parameters.
+ *
+ * @see _node_resource_index() for more notes
+ **/
+function _taxonomy_vocabulary_resource_index($page, $fields, $parameters) {
+  $taxonomy_select = db_select('vocabulary', 't')
+    ->orderBy('weight', 'DESC')
+    ->orderBy('name', 'DESC');
+
+  services_resource_build_index_query($taxonomy_select, $page, $fields, $parameter);
+
+  $results = $taxonomy_select->execute();
+
+  return services_resource_build_index_list($results, 'taxonomy_vocabulary', 'vid');
+}
\ No newline at end of file
diff --git a/resources/user_resource.inc b/resources/user_resource.inc
index 0067cb4..4cb0537 100644
--- a/resources/user_resource.inc
+++ b/resources/user_resource.inc
@@ -400,29 +400,14 @@ function _user_resource_logout() {
  * @see _node_resource_index() for more notes
  */
 function _user_resource_index($page, $fields, $parameters) {
-  $user_select = db_select('users', 'u');
-  if ($fields == '*') {
-    $user_select->fields('u');
-  }
-  else {
-    $fields = explode(',', $fields);
-    $user_select->fields('u', $fields);
-  }
-  foreach ($parameters as $key => $value) {
-    $user_select->condition('u.' . $key, $value, '=');
-  }
-  $user_select->orderBy('created', 'DESC');
-  $user_select->range($page * 20, 20);
-
-  $result = $user_select->execute();
-  $users = array();
-  foreach ($result as $user) {
-    if ($uri = services_resource_uri(array('user', $user->uid))) {
-      $user->uri = $uri;
-    }
-    $users[] = $user;
-  }
-  return $users;
+  $user_select = db_select('users', 't')
+    ->orderBy('created', 'DESC');
+
+  services_resource_build_index_query($user_select, $page, $fields, $parameter);
+
+  $results = $user_select->execute();
+
+  return services_resource_build_index_list($results, 'user', 'uid');
 }
 
 /**
diff --git a/services.module b/services.module
index b725b2b..6139f26 100644
--- a/services.module
+++ b/services.module
@@ -447,3 +447,54 @@ function _services_resource_controller_as_procedure($resource, $name, $controlle
 
   return $method;
 }
+
+/**
+ * Helper function to build index queries.
+ *
+ * @param $query
+ *   Object database query object.
+ * @param $page
+ *   Integer page number we are requesting.
+ * @param $fields
+ *   Array fields to return.
+ * @param $parameter
+ *   Array parameters to add to the index query.
+ */
+function services_resource_build_index_query($query, $page, $fields, $parameter) {
+  $page_size = variable_get('services_index_page_size', 20);
+  $query->range($page * $page_size, $page_size)
+  if ($fields == '*') {
+    $query->fields('t');
+  }
+  else {
+    $fields = explode(',', $fields);
+    $query->fields('t', $explode(',', $fields));
+  }
+
+  foreach ($parameters as $parameter => $parameter_value) {
+    $query->condition($parameter, $parameter_value, '=');
+  }
+}
+
+/**
+ * Helper function to build a list of items satisfying the index query.
+ *
+ * @param $results
+ *   Object database query results object.
+ * @param $type
+ *   String type of index that is being processed.
+ * @param $field
+ *   String field to use for looking up uri.
+ */
+function services_resource_process_list($results, $type, $field) {
+  // Put together array of matching items to return.
+  $items = array();
+  foreach ($results as $result) {{
+    if ($uri = services_resource_uri(array($type, $result->{$field}))) {
+      $result->uri = $uri;
+    }
+    $items[] = $result;
+  }
+
+  return $items;
+}
\ No newline at end of file
-- 
1.7.4

