From cc1c347cf1444c74748b9bf07432509f573ff8af Mon Sep 17 00:00:00 2001
From: Kyle Browning <kylebrowning@me.com>
Date: Mon, 31 Oct 2011 17:00:55 -0700
Subject: [PATCH] testing

---
 resources/comment_resource.inc                  |    2 +-
 resources/file_resource.inc                     |    2 +-
 resources/node_resource.inc                     |    2 +-
 resources/taxonomy_resource.inc                 |    4 +-
 resources/user_resource.inc                     |    2 +-
 services.module                                 |   12 +++++-
 tests/functional/ServicesResourceNodeTests.test |   53 +++++++++++++++++++++-
 tests/unit/TestServicesModule.test              |   49 ---------------------
 8 files changed, 67 insertions(+), 59 deletions(-)

diff --git a/resources/comment_resource.inc b/resources/comment_resource.inc
index a7c5b52..2a61e9d 100644
--- a/resources/comment_resource.inc
+++ b/resources/comment_resource.inc
@@ -196,7 +196,7 @@ function _comment_resource_index($page, $fields, $parameters, $page_title) {
   if (!user_access('administer comments')) {
     $parameters['status'] = 1;
   }
-  $query = services_resource_build_index_query('comments', 'c.timestamp DESC', $page, $fields, $parameters, 'c', 'cid', $page_title);
+  $query = services_resource_build_index_query('comments', 'c.timestamp DESC', $page, $fields, $parameters, 'c', 'cid', $page_title, 'comment');
   // Put together array of matching nodes to return.
   $results = array();
   while ($comments = db_fetch_object($query)) {
diff --git a/resources/file_resource.inc b/resources/file_resource.inc
index 0d30512..55d248c 100644
--- a/resources/file_resource.inc
+++ b/resources/file_resource.inc
@@ -143,7 +143,7 @@ function _file_resource_definition() {
  **/
 function _file_resource_index($page, $fields, $parameters, $page_size) {
 
-  $query = services_resource_build_index_query('files', 'f.timestamp', $page, $fields, $parameters, 'f', 'fid', $page_size);
+  $query = services_resource_build_index_query('files', 'f.timestamp', $page, $fields, $parameters, 'f', 'fid', $page_size, 'file');
   // Put together array of matching nodes to return.
   $results = array();
   while ($comments = db_fetch_object($query)) {
diff --git a/resources/node_resource.inc b/resources/node_resource.inc
index 1ae1445..c7a507f 100644
--- a/resources/node_resource.inc
+++ b/resources/node_resource.inc
@@ -417,7 +417,7 @@ function _node_resource_index($page, $fields, $parameters, $page_size) {
   if (!user_access('administer nodes')) {
     $parameters['status'] = 1;
   }
-  $query = services_resource_build_index_query('node', 'n.sticky DESC, n.created DESC', $page, $fields, $parameters, 'n', 'nid', $page_size);
+  $query = services_resource_build_index_query('node', 'n.sticky DESC, n.created DESC', $page, $fields, $parameters, 'n', 'nid', $page_size, 'node');
   // Put together array of matching nodes to return.
   $results = array();
   while ($node = db_fetch_object($query)) {
diff --git a/resources/taxonomy_resource.inc b/resources/taxonomy_resource.inc
index d96e2b3..643213f 100644
--- a/resources/taxonomy_resource.inc
+++ b/resources/taxonomy_resource.inc
@@ -352,7 +352,7 @@ function _taxonomy_resource_definition() {
  * @see _node_resource_index() for more notes
  **/
 function _taxonomy_term_resource_index($page, $fields, $parameters, $page_size) {
-  $query = services_resource_build_index_query('term_data', 't.vid DESC, t.weight DESC, t.name DESC', $page, $fields, $parameters, 't', 'tid', $page_size);
+  $query = services_resource_build_index_query('term_data', 't.vid DESC, t.weight DESC, t.name DESC', $page, $fields, $parameters, 't', 'tid', $page_size, 'taxonomy_term');
 
   $results = array();
   while ($taxonomy = db_fetch_object($query)) {
@@ -389,7 +389,7 @@ function _taxonomy_term_resource_index($page, $fields, $parameters, $page_size)
  * @see _node_resource_index() for more notes
  **/
 function _taxonomy_vocabulary_resource_index($page, $fields, $parameters, $page_size) {
-  $query = services_resource_build_index_query('vocabulary', 'v.weight DESC, v.name DESC', $page, $fields, $parameters, 'v', 'vid', $page_size);
+  $query = services_resource_build_index_query('vocabulary', 'v.weight DESC, v.name DESC', $page, $fields, $parameters, 'v', 'vid', $page_size,'taxonomy_term');
 
   $results = array();
   while ($taxonomy = db_fetch_object($query)) {
diff --git a/resources/user_resource.inc b/resources/user_resource.inc
index f6cb764..1b7927a 100644
--- a/resources/user_resource.inc
+++ b/resources/user_resource.inc
@@ -435,7 +435,7 @@ function _user_resource_index($page, $fields, $parameters, $page_size) {
   if (!user_access('administer users')) {
     $parameters['active'] = 1;
   }
-  $query = services_resource_build_index_query('users', 'u.created DESC', $page, $fields, $parameters, 'u', 'uid', $page_size);
+  $query = services_resource_build_index_query('users', 'u.created DESC', $page, $fields, $parameters, 'u', 'uid', $page_size, 'user');
 
   $results = array();
   while ($user = db_fetch_object($query)) {
diff --git a/services.module b/services.module
index 91062dd..8efd298 100644
--- a/services.module
+++ b/services.module
@@ -43,6 +43,8 @@ function services_perm() {
     // System resource permissions
     'get a system variable',
     'set a system variable',
+    // Query permissions
+    'perform unlimited index queries',
   );
 }
 
@@ -444,8 +446,10 @@ function _services_resource_controller_as_procedure($resource, $name, $controlle
  *   Array parameters to add to the index query.
  * @param $page_size
  *   Integer number of items to be returned.
+ * @param $resource
+ *   String name of the resource building the index query
  */
-function services_resource_build_index_query($schema, $order, $page, $fields, $parameters = array(), $primary_table, $primary_field, $page_size) {
+function services_resource_build_index_query($schema, $order, $page, $fields, $parameters = array(), $primary_table, $primary_field, $page_size, $resource) {
   $where = array();
   $fields = db_escape_string($fields);
 
@@ -471,6 +475,12 @@ function services_resource_build_index_query($schema, $order, $page, $fields, $p
   // Now implode that array into an actual WHERE clause.
   $where = !empty($where) ? ' WHERE '. implode(' AND ', $where) : '';
 
+  // Apply page size limits.
+  $default_limit = variable_get("services_{$resource}_index_page_size", 20);
+  if (!user_access('perform unlimited index queries') && $page_size > $default_limit) {
+      $page_size = $default_limit;
+  }
+
   // Run through db_rewrite_sql to make sure proper access checks are applied.
   $sql = "SELECT $fields FROM {{$table}} AS $primary_table $where ORDER BY $order";
   $sql = db_rewrite_sql($sql, $primary_table, $primary_field);
diff --git a/tests/functional/ServicesResourceNodeTests.test b/tests/functional/ServicesResourceNodeTests.test
index 4d11e10..f883b18 100644
--- a/tests/functional/ServicesResourceNodeTests.test
+++ b/tests/functional/ServicesResourceNodeTests.test
@@ -54,12 +54,59 @@ class ServicesResourceNodetests extends ServicesWebtestCase {
     // Create and log in our privileged user.
     $this->privilegedUser = $this->drupalCreateUser(array(
       'administer services',
+      'perform unlimited index queries',
     ));
     $this->drupalLogin($this->privilegedUser);
 
-    $node = $this->drupalCreateNode();
-    $responseArray = $this->servicesGet($this->endpoint->path . '/node');
-    $this->assertTrue($node->title == $responseArray['body'][0]->title, t('Successfully received Node info'), 'NodeResource: Index');
+    // Create a set of nodes. The node resource returns 20 returns at a time,
+    // so we create two pages and a half worth.
+    $nodes = array();
+    $count = 50;
+    for ($i = 0; $i < $count; $i++) {
+      $node = $this->drupalCreateNode();
+      $nodes[$node->nid] = $node;
+    }
+
+    // Get the content.
+    $page_count = ceil(count($nodes) / 20);
+    $retrieved_nodes = array();
+    for ($page = 0; $page < $page_count; $page++) {
+      $responseArray = $this->servicesGet($this->endpoint->path . '/node', array('page' => $page, 'fields' => 'nid,title'));
+      $this->assertTrue(count($responseArray['body']) <= 20, t('Correct number of items returned'));
+
+      // Store the returned node IDs.
+      foreach ($responseArray['body'] as $node) {
+        if (isset($retrieved_nodes[$node->nid])) {
+          $this->fail(t('Duplicate node @nid returned.', array('@nid' => $node->nid)));
+        }
+        $retrieved_nodes[$node->nid] = TRUE;
+
+        $this->assertTrue($nodes[$node->nid]->title == $node->title, t('Successfully received Node info'), 'NodeResource: Index');
+      }
+    }
+
+    // We should have got all the nodes.
+    $expected_nids = array_keys($nodes);
+    sort($expected_nids);
+    $retrieved_nids = array_keys($retrieved_nodes);
+    sort($retrieved_nids);
+    $this->assertEqual($expected_nids, $retrieved_nids, t('Retrieved all nodes'));
+
+    // The n+1 page should be empty.
+    $responseArray = $this->servicesGet($this->endpoint->path . '/node', array('page' => $page_count + 1));
+    $this->assertEqual(count($responseArray['body']), 0, t('The n+1 page is empty'));
+
+    // Adjust the pager size.
+    $responseArray = $this->servicesGet($this->endpoint->path . '/node', array('fields' => 'nid,title', 'pagesize' => 40));
+    $this->assertTrue(count($responseArray['body']) == 40, t('Correct number of items returned'));
+
+    // Swap to user that can only use the default pager size.
+    $this->lessPrivilegedUser = $this->drupalCreateUser(array(
+      'administer services',
+    ));
+    $this->drupalLogin($this->lessPrivilegedUser);
+    $responseArray = $this->servicesGet($this->endpoint->path . '/node', array('fields' => 'nid,title', 'pagesize' => 40));
+    $this->assertTrue(count($responseArray['body']) == 20, t('Correct number of items returned'));
   }
 
   /**
diff --git a/tests/unit/TestServicesModule.test b/tests/unit/TestServicesModule.test
index 9061dd7..039d024 100644
--- a/tests/unit/TestServicesModule.test
+++ b/tests/unit/TestServicesModule.test
@@ -58,55 +58,6 @@ class ServicesModuleTests extends DrupalWebTestCase {
   }
 
   /**
-   * Test services_perm results.
-   */
-  public function testServicesPerm() {
-    $resultArray = services_perm() ;
-    $message = t('services_perm should return an array') ;
-    $this->assertTrue(gettype($resultArray)=='array', $message) ;
-
-    $message = t('There should be 7 permission types') ;
-    $this->assertEqual(count($resultArray), 7, $message) ;
-
-    $permission = 'administer services' ;
-    $this->helperPermExists($resultArray, $permission) ;
-
-    $permission = 'get any binary files' ;
-    $this->helperPermExists($resultArray, $permission) ;
-
-    $permission = 'get own binary files' ;
-    $this->helperPermExists($resultArray, $permission) ;
-
-    $permission = 'save file information' ;
-    $this->helperPermExists($resultArray, $permission) ;
-
-    $permission = 'get a system variable' ;
-    $this->helperPermExists($resultArray, $permission) ;
-
-    $permission = 'set a system variable' ;
-    $this->helperPermExists($resultArray, $permission) ;
-  } // function
-
-  /**
-   * Helper function to do the same checks on every permission.
-   *
-   * @param $array_to_search
-   * Usually an array from the hook_perm implementation.
-   *
-   * @param $perm
-   * The permission to verify exists
-   *
-   * @return
-   * Void. The asserts in the code provide feedback via the test harness.__PHP_Incomplete_Class
-   */
-  protected function helperPermExists($arrayToSearch, $perm) {
-    $result = array_search($perm, $arrayToSearch) ;
-    $message = t("There should be a '$perm' permission") ;
-    $this->assertNotIdentical($result, FALSE, $message) ;
-  } // function
-
-
-  /**
    * Test thta adding a menu endpoint creates an menu path for that item.
    */
   public function testEndpointMenu() {
-- 
1.7.5.4

