### Eclipse Workspace Patch 1.0
#P dr7
Index: modules/poll/poll.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/poll/poll.test,v
retrieving revision 1.21
diff -u -r1.21 poll.test
--- modules/poll/poll.test	20 Jul 2009 18:51:33 -0000	1.21
+++ modules/poll/poll.test	30 Jul 2009 16:16:53 -0000
@@ -82,6 +82,55 @@
     $this->drupalPost('node/' . $nid . '/edit', $edit, t('Save'));
     $this->assertText(t('@type @title has been updated.', array('@type' => node_type_get_name('poll'), '@title' => $title)), 'Poll has been updated.');
   }
+  
+  /* This function is a cut down version of drupal post which dosn't do a get first
+   * it is needed to test the random poll functions as you can't know what form fields
+   * are available before a drupalGet with the random poll block
+   */
+  function pollPost( $edit, $submit, array $options = array(), array $headers = array()) {
+    $submit_matches = FALSE;
+    if ($this->parse()) {
+      $edit_save = $edit;
+      // Let's iterate over all the forms.
+      $forms = $this->xpath('//form');
+      foreach ($forms as $form) {
+        // We try to set the fields of this form as specified in $edit.
+        $edit = $edit_save;
+        $post = array();
+        $upload = array();
+        $submit_matches = $this->handleForm($post, $edit, $upload, $submit, $form);
+        $action = isset($form['action']) ? $this->getAbsoluteUrl($form['action']) : $this->getUrl();
+
+        // We post only if we managed to handle every field in edit and the
+        // submit button matches.
+        if (!$edit && $submit_matches) {
+          $post_array = $post;
+          foreach ($post as $key => $value) {
+            // Encode according to application/x-www-form-urlencoded
+            // Both names and values needs to be urlencoded, according to
+            // http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1
+            $post[$key] = urlencode($key) . '=' . urlencode($value);
+            }
+          $post = implode('&', $post);
+          $out = $this->curlExec(array(CURLOPT_URL => $action, CURLOPT_POST => TRUE, CURLOPT_POSTFIELDS => $post, CURLOPT_HTTPHEADER => $headers));
+          // Ensure that any changes to variables in the other thread are picked up.
+          $this->refreshVariables();
+
+          // Replace original page output with new output from redirected page(s).
+          if (($new = $this->checkForMetaRefresh())) {
+            $out = $new;
+          }
+          return $out;
+        }
+      }
+      // We have not found a form which contained all fields of $edit.
+      foreach ($edit as $name => $value) {
+        $this->fail(t('Failed to set field @name to @value', array('@name' => $name, '@value' => $value)));
+      }
+      $this->assertTrue($submit_matches, t('Found the @submit button', array('@submit' => $submit)));
+      $this->fail(t('Found the requested form fields at @path', array('@path' => $path)));
+    }
+  }
 }
 
 class PollCreateTestCase extends PollTestCase {
@@ -244,7 +293,7 @@
   public static function getInfo() {
     return array(
       'name' => 'Block availability',
-      'description' => 'Check if the most recent poll block is available.',
+      'description' => 'Check if the most recent poll block, and random poll block are available and work as expected.',
       'group' => 'Poll',
     );
   }
@@ -259,11 +308,16 @@
 
   function testRecentBlock() {
     // Set block title to confirm that the interface is available.
-    $this->drupalPost('admin/structure/block/configure/poll/recent', array('title' => $this->randomName(8)), t('Save block'));
+    $this->drupalPost('admin/structure/block/configure/poll/' . POLL_RECENT, array('title' => $this->randomName(8)), t('Save block'));
     $this->assertText(t('The block configuration has been saved.'), t('Block configuration set.'));
 
     // Set the block to a region to confirm block is available.
     $edit = array();
+
+    
+    $edit['poll_' . POLL_RECENT . '[region]'] = 'footer';
+    $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
+
     $edit['poll_recent[region]'] = 'footer';
     $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
     $this->assertText(t('The block settings have been updated.'), t('Block successfully move to footer region.'));
@@ -305,6 +359,113 @@
     $this->drupalGet('user/' . $content_user->uid);
     $this->assertNoText($title, 'Poll no longer appears in block.');
   }
+  
+  function testRandomBlock() {
+    //the number of polls to create to check randomness
+    $polls_created = 2;
+    
+    // Set block title to confirm that the interface is available.
+    $this->drupalPost('admin/structure/block/configure/poll/' . POLL_RANDOM, array('title' => $this->randomName(8)), t('Save block'));
+    $this->assertText(t('The block configuration has been saved.'), t('Block configuration set.'));
+
+    // Set the block to a region to confirm block is available.
+    $edit = array();
+    $edit['poll_' . POLL_RANDOM . '[region]'] = 'footer';
+    $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
+    $this->assertText(t('The block settings have been updated.'), t('Block successfully move to footer region.'));
+
+    // Create a number of polls which should appear in random polls block.
+    $polls = array();
+    for ($i =0; $i<$polls_created; $i++) {
+        $title = $this->randomName();
+        $choices = $this->_generateChoices(7);
+        $poll_nid = $this->pollCreate($title, $choices, TRUE);
+        $polls[] = array('title' => $title,
+                        'choices' => $choices,
+                        'poll_nid' => $poll_nid                
+        );
+      }
+
+    // Verify poll appears in a block.
+    // View user page so we're not matching the poll node on front page.
+    $content_user = $this->drupalCreateUser(array('create poll content', 'edit any poll content', 'access content'));
+    $this->drupalGet('user/' . $content_user->uid);
+
+    // Check that the page contains one of the polls which was created.
+    $found_title = FALSE;
+    $this_content = $this->drupalGetContent();
+    $title_found = $this->randomName();
+    for ($i =0; $i< $polls_created; $i++) {
+      $title_found = $polls[$i]['title'];
+      if (strpos($this_content, $polls[$i]['title'])) {
+        $found_title = TRUE;
+        $title_found = $polls[$i]['title'];
+      }
+    }
+    
+    $this->assertTrue($found_title, 'Random Poll should appear, in block.');
+
+    // Try page again, and see if we get a different poll
+    // Due to ranomness we may need to check a few times.
+    $poll_is_random = FALSE;
+    
+    for ($i =1; $i<100; $i++) {
+      $this->drupalGet('user');
+      if (!(strpos($this->drupalGetContent(), $title_found))) {
+        $poll_is_random = TRUE;
+        break;
+      }
+    }
+    // Note, this has a 1 in $polls_created^100 chance of giving a false positive.
+    $this->assertTrue($poll_is_random, 'Random Poll changes after reload.');
+
+    // Logout and login back in as a user who can vote.
+    $this->drupalLogout();
+    $vote_user = $this->drupalCreateUser(array('cancel own vote', 'inspect all votes', 'vote on polls', 'access content'));
+    $this->drupalLogin($vote_user);
+
+    for ($i =0; $i<$polls_created; $i++) {
+      if (strpos($this->drupalGetContent(), $polls[$i]['title'])) {
+        $title_found = $polls[$i]['title'];
+      }
+    }
+
+    // Find a valid choice value.
+    preg_match("/edit.choice.([0-9]+)/", $this->drupalGetContent(), $matches);
+    $valid_choice = $matches[1];
+
+    // Verify we can vote via the block.
+    $edit = array(
+      'choice' => $valid_choice,
+    );
+        
+    $this->pollPost($edit, t('Vote'));
+    $this->assertText('Your vote was recorded.', 'Your vote was recorded.');
+    $this->assertText('Total votes: 1', 'Vote count updated correctly.');
+    $this->assertText($title_found, 'After posting vote on random poll the results remain');
+    // Check that the reload function removes the voted on poll.
+    $this->drupalGet('user/' . $vote_user->uid);
+    $this->assertNoText($title_found, 'reloading after post should show new poll that has not been voted on');
+
+    // Vote on all polls and check that the block no longer appears.
+    for ($i =1; $i< $polls_created; $i++) {
+      preg_match("/edit.choice.([0-9]+)/", $this->drupalGetContent(), $matches);
+      $valid_choice = $matches[1];
+      $edit = array(
+        'choice' => $valid_choice,
+      );
+      $this->pollPost($edit, t('Vote'));
+      $this->drupalGet('user/' . $vote_user->uid);        
+    }    
+
+    $found_title = FALSE;
+    for ($i =0; $i< $polls_created; $i++) {
+      if (strpos($this->drupalGetContent(), $polls[$i]['title'])) {
+        $found_title = TRUE;
+      }
+    }
+    $this->assertFalse($found_title, 'after voting on all random polls no poll title appears' );    
+  }
 }
 
 /**
Index: modules/poll/poll.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/poll/poll.module,v
retrieving revision 1.301
diff -u -r1.301 poll.module
--- modules/poll/poll.module	5 Jul 2009 18:00:09 -0000	1.301
+++ modules/poll/poll.module	30 Jul 2009 16:16:53 -0000
@@ -7,6 +7,10 @@
  * choice questions.
  */
 
+/* define block ids */
+define('POLL_RECENT', 'recent');
+define('POLL_RANDOM', 'random');
+
 /**
  * Implement hook_help().
  */
@@ -133,7 +137,9 @@
  */
 function poll_block_list() {
   if (user_access('access content')) {
-    $blocks['recent']['info'] = t('Most recent poll');
+    $blocks[POLL_RECENT]['info'] = t('Most recent poll');
+    $blocks[POLL_RANDOM]['info'] = t('random active poll');
+    $blocks[POLL_RANDOM]['cache'] = BLOCK_NO_CACHE;
     return $blocks;
   }
 }
@@ -141,28 +147,56 @@
 /**
  * Implement hook_block_view().
  *
- * Generates a block containing the latest poll.
+ * Generates a block containing the latest or random poll.
  */
 function poll_block_view($delta = '') {
+  
   if (user_access('access content')) {
-    // Retrieve the latest poll.
+    global $user;
     $select = db_select('node', 'n');
     $select->join('poll', 'p', 'p.nid = n.nid');
     $select->fields('n', array('nid'))
       ->condition('n.status', 1)
       ->condition('p.active', 1)
-      ->orderBy('n.created', 'DESC')
       ->range(0, 1)
       ->addTag('node_access');
-
+    // If the user has voted on a random poll then show the result
+    // Otherwise work as normal.
+    if (isset($user->poll_random_voted_id) && is_numeric($user->poll_random_voted_id)) {
+      $select->condition('n.nid', $user->poll_random_voted_id);
+      user_save($user, array('poll_random_voted_id' => ''));  
+    }
+    else {
+      switch ($delta) {
+        case POLL_RECENT:
+          // Retrieve the latest poll.
+          $select->orderBy('n.created', 'DESC');
+          break;
+        case POLL_RANDOM:
+          // Retrieve a random poll.
+          $select->orderBy('RAND()', 'ASC');
+          $select->leftJoin('poll_vote', 'pv', 'pv.nid = n.nid and pv.uid =' . $user->uid);
+          $select->isNull('pv.nid');
+          break;
+      }
+    }        
     $record = $select->execute()->fetchObject();
     if ($record) {
       $poll = node_load($record->nid);
       if ($poll->nid) {
-        $poll = poll_block_latest_poll_view($poll);
-        $block['subject'] = t('Poll');
-        $block['content'] = $poll->content;
-        return $block;
+        switch ($delta) {
+          case POLL_RECENT:
+            $poll = poll_block_latest_poll_view($poll);
+            break;
+          case POLL_RANDOM:
+            $poll = poll_block_random_poll_view($poll);
+            break;
+        }
+        if ($delta == POLL_RECENT || $delta == POLL_RANDOM) {
+          $block['subject'] = t('Poll');
+          $block['content'] = $poll->content;
+          return $block;
+        }  
       }
     }
   }
@@ -571,7 +605,7 @@
   $node->links = $links;
 
   if (!empty($node->allowvotes)) {
-    $node->content['poll_view_voting'] = drupal_get_form('poll_view_voting', $node, TRUE);
+    $node->content['poll_view_voting'] = drupal_get_form('poll_view_voting', $node, POLL_RECENT);
   }
   else {
     $node->content['poll_view_results'] = array('#markup' => poll_view_results($node, TRUE, TRUE));
@@ -580,6 +614,45 @@
   return $node;
 }
 
+/**
+ * Return content for 'latest poll' block.
+ *
+ * @param $node
+ *   The node object to load.
+ */
+function poll_block_random_poll_view($node) {
+  global $user;
+  $output = '';
+
+  // This is necessary for shared objects because PHP doesn't copy objects, but
+  // passes them by reference.  So when the objects are cached it can result in
+  // the wrong output being displayed on subsequent calls.  The cloning and
+  // unsetting of $node->content prevents the block output from being the same
+  // as the node output.
+  $node = clone $node;
+
+  unset($node->content);
+
+  // No 'read more' link.
+  $node->readmore = FALSE;
+  $node->teaser = '';
+
+  $links = module_invoke_all('link', 'node', $node, 1);
+  if ($node->allowvotes) {
+    $links[] = array('title' => t('Results'), 'href' => 'node/' . $node->nid . '/results', 'attributes' => array('title' => t('View the current poll results.')));
+  }
+
+  $node->links = $links;
+
+  if (!empty($node->allowvotes)) {
+    $node->content['poll_view_voting'] = drupal_get_form('poll_view_voting', $node, POLL_RANDOM);
+  }
+  else {
+    $node->content['poll_view_results'] = array('#markup' => poll_view_results($node, TRUE, TRUE));
+  }
+
+  return $node;
+}
 
 /**
  * Implement hook_view().
@@ -617,6 +690,7 @@
 /**
  * Generates the voting form for a poll.
  *
+ *
  * @ingroup forms
  * @see poll_vote()
  * @see phptemplate_preprocess_poll_vote()
@@ -687,7 +761,14 @@
 
   cache_clear_all();
   drupal_set_message(t('Your vote was recorded.'));
-
+  // If the form was submitted from the random poll block
+  // we need to store some state so that the block can 
+  // display the results rather than the next random poll.
+  if ($form['#block'] == POLL_RANDOM) {
+    $poll_vote_data = array('poll_random_voted_id' => $node->nid);
+    user_save($user, $poll_vote_data);
+  }
+  
   // Return the user to whatever page they voted from.
 }
 
