The attached patch adds a second block to the poll module: a random active poll. Unlike the current block which only displays the most recent poll, this additional block randomly displays any active poll. I wanted my pages to display any open poll, not only the most recent. Hopefully others will find this useful also.

The patch applies to both HEAD and 4.4 as of 2004-03-23.

Comments

jhriggs’s picture

Ugh...wasn't logged in when I submitted this issue. Let me know if you have any problems with the patch.

dries’s picture

Instead of adding a second block, we should try to make the existing poll block configurable. Setting this to 'active'.

jhriggs’s picture

What if someone wants both blocks, though, or perhaps want the most recent on some pages and a random one on others?

jhriggs’s picture

StatusFileSize
new3.37 KB

Attaching an updated patch. Any takers on this? Am I the only one with interest in displaying a random poll rather than just the last one?

dries’s picture

I don't intend to commit this unless there is more demand for it.

alliax’s picture

I would like this too.
In my case I'd prefer have the poll block configured to randomly display active polls.
But I also like the idea of showing a specific poll in the block for specific nodes.

mikeryan’s picture

Count me in... I've coded this already as a custom block, if there's interest I could produce a patch to add it to the core module... One question, is ORDER BY RAND() supported by pgsql?

An additional wrinkle I implemented - if there are any sticky active polls, one of them will be randomly selected, otherwise it will just be any random active poll.

To try it, create a new PHP block with the following content:

$sql = db_rewrite_sql("SELECT n.nid FROM {node} n INNER JOIN {poll} p ON p.nid = n.nid WHERE n.status = 1 AND p.active = 1 AND n.moderate = 0 AND n.sticky=1 ORDER BY RAND()");
$nid = db_result(db_query_range($sql, 0, 1));
if (!$nid) {
  $sql = db_rewrite_sql("SELECT n.nid FROM {node} n INNER JOIN {poll} p ON p.nid = n.nid WHERE n.status = 1 AND p.active = 1 AND n.moderate = 0 ORDER BY RAND()");
  $nid = db_result(db_query_range($sql, 0, 1));
}
if ($nid) {
  $poll = node_load(array('type' => 'poll', 'nid' => $nid, 'moderate' => 0, 'status' => 1));
  if ($poll->nid) {
    // poll_view() dumps the output into $poll->body.
    poll_view($poll, 1, 0, 1);
  }
}
return $poll->body;
antarus’s picture

StatusFileSize
new2.79 KB

I've got a patch against cvs that adds this as well,although I did the randomizing in php as opposed to sql since I figure array_rand() was more portable.

saml’s picture

Version: x.y.z » 4.7.x-dev

On what version of Drupal is this patch supposed to work?
(I had to specify a version to be allowed to post, but I don't know if 4.7.x-dev is correct?!)

I have problems using it on 4.7.2. After enabling the poll module I see the message:

user warning: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(n.nid) FROM drupal_node n INNER JOIN drupal_poll p ON p.nid = n.nid WHERE n.sta' at line 1 query: SELECT p.DISTINCT(n.nid) FROM drupal_node n INNER JOIN drupal_poll p ON p.nid = n.nid WHERE n.status = 1 AND p.active = 1 AND n.moderate = 0 in /hsphere/local/home/.../testlabbet/includes/database.mysql.inc on line 120.

(I'm using table prefixes)

Also the random poll block doesn't show up, while the "latest poll" block still works.

BTW, any update for 5.0 on this one?

saml’s picture

Hmm... testing on Drupal 4.7.6 works fine, also with tableprefixes. Must be either some issue with this version of Drupal, or with applying the patch while having existing poll content. Will report if I find a solution on this.

saml’s picture

I noticed that when you are logged out, polls that you have already voted on are show the radiobuttons and not the results (even though voting doesn't work the second time, as expected), which should be the case.

tengoku’s picture

hi, i have a same problem that you mention here, but in diferent way.
i wanted a fixed poll that can be selected on block admin. so this is my code:

function poll_block($op = 'list', $delta = 0, $edit = array()) {
	if (user_access('access content')) {
		if ($op == 'list') {
			$blocks[0]['info'] = t('Most recent poll');
			$blocks[1]['info'] = t('Choosen poll');
			return $blocks;
		}
		else if($op == 'configure') {
			switch($delta) {
			case(1):
				// Configuration settings for block
				$sql = db_rewrite_sql("Select p.nid,n.title FROM {node} n INNER JOIN {poll} p ON p.nid = n.nid where n.status = 1 AND p.active = 1 AND n.moderate = 0");
				$polls = db_query($sql);
				$poll_options=array();
				while ($row=db_fetch_array($polls)){
					$poll_options[$row["nid"]]=$row["title"];
				}
				$form["id_to_show"] = array(
				'#type' => 'select',
				'#title' => t("Poll to show"),
				'#default_value' => variable_get("poll_block_id_to_show", 0),
				'#options' => $poll_options,
				'#description' => t("Poll to show in this block"),);
				return $form;
				break;
			}
		}
		else if ($op == 'save' && $delta == 1) {
			variable_set('poll_block_id_to_show', $edit['id_to_show']);
		}
		else if ($op == 'view') {
			switch($delta) {
			case "0":
				// Retrieve the latest poll.
				$sql = db_rewrite_sql("SELECT MAX(n.created) FROM {node} n INNER JOIN {poll} p ON p.nid = n.nid WHERE n.status = 1 AND p.active = 1 AND n.moderate = 0");
				$timestamp = db_result(db_query($sql));
				if ($timestamp) {
					$poll = node_load(array('type' => 'poll', 'created' => $timestamp, 'moderate' => 0, 'status' => 1));

					if ($poll->nid) {
						// poll_view() dumps the output into $poll->body.
						poll_view($poll, 1, 0, 1);
					}
				}
				$block['subject'] = t('Poll');
				$block['content'] = $poll->body;
				return $block;
				break;
			case "1":
				// Retrieve all polls id.
				$sql = db_rewrite_sql("SELECT p.nid FROM {node} n INNER JOIN {poll} p ON p.nid = n.nid WHERE n.status = 1 AND p.active = 1 AND n.moderate = 0 AND p.nid=".variable_get("poll_block_id_to_show", 0)."");
				$pollid = db_result(db_query($sql));
				if($pollid) {
					$poll = node_load(array('type' => 'poll', 'nid' => $pollid, 'moderate' => 0, 'status' => 1));

					if ($poll->nid) {
						// poll_view() dumps the output into $poll->body.
						poll_view($poll, 1, 0, 1);
					}
				}
				$block['subject'] = t('Poll');
				$block['content'] = $poll->body;
				return $block;
				break;
			}
		}
	}
}

i'm an ultra-junior developer. so any fix will be appreciated. thanks. greetings from colombia

ekrispin’s picture

Version: 4.7.x-dev » 5.1

A version of #7 block that works with Drupal 5:

<?php
$sql = db_rewrite_sql("SELECT n.nid FROM {node} n INNER JOIN {poll} p ON p.nid = n.nid WHERE n.status = 1 AND p.active = 1 AND n.moderate = 0 AND n.sticky=1 ORDER BY RAND()");
$nid = db_result(db_query_range($sql, 0, 1));
if (!$nid) {
  $sql = db_rewrite_sql("SELECT n.nid FROM {node} n INNER JOIN {poll} p ON p.nid = n.nid WHERE n.status = 1 AND p.active = 1 AND n.moderate = 0 ORDER BY RAND()");
  $nid = db_result(db_query_range($sql, 0, 1));
}
if ($nid) {
  $poll = node_load(array('type' => 'poll', 'nid' => $nid, 'moderate' => 0, 'status' => 1));
  if ($poll->nid) {
    // poll_view() dumps the output into $poll->content.
    poll_view($poll, TRUE, FALSE, TRUE);
  }
}
return drupal_render($poll->content);
?>
Camario39’s picture

Version: 5.1 » 6.0
StatusFileSize
new7.32 KB

First time commenting here and newbie Drupal user.

For 6.0 I simply changed the SQL statement that searches for most current poll to the following:

SELECT n.created FROM {node} n INNER JOIN {poll} p ON p.nid = n.nid 
WHERE n.status = 1 AND p.active = 1 
ORDER BY RAND() LIMIT 1

vs

SELECT MAX(n.created) FROM {node} n INNER JOIN {poll} p ON p.nid = n.nid 
WHERE n.status = 1 AND p.active = 1 

Hope this helps. I dont know how to create patches or contribute correctly, but I thought i would put this out there.

pasqualle’s picture

Version: 6.0 » 7.x-dev
Status: Active » Needs work
mcurry’s picture

Subscribe

JeremyFrench’s picture

I have written some code to do this on Drupal 6 (as part of another module). It is a little more complex. It displays a random poll that the user hasn't voted on, but if they vote it shows them the results of the poll they just voted on, it may need a bit of work but I can upload a D7 patch later today.

This is a very useful feature, more so than the latest poll block to my mind.

JeremyFrench’s picture

I am still working on a patch for this, work has taken over for a bit. However I am having a problem simpletesting the submit function as I am unable to determine the id for the options outside of the drupalPost method. So can't select a valid id to post.

JeremyFrench’s picture

StatusFileSize
new14.36 KB

Uploaded patch. It is my first enhancement so please review well.

There are several points of contention I should imagine.

Order by rand(), I don’t know if this is acceptable, it will work with mysql but I am not sure about other databases, I can think of a couple of ways round this but they all involve running two queries instead of one.

$select->leftJoin('poll_vote', 'pv', 'pv.nid = n.nid and pv.uid =' . $user->uid);
I would prefer to use a param for the uid, but I don’t think this is possible in the left join statement.

Putting poll_random_voted_id in the user object. I wasn’t sure if I should use this or the session object, this seemed more Drupalish, but I think there may be an issue with anonymous users.

In the poll test I created a poll post method to get round a particular problem with testing when the form changes on a page load. I think this is unusual enough to warrant it.

Coder was giving me this message ‘@see references should be separated by "," followed by a single space and with no trailing punctuation’ but I am not quite sure what to make of it, it could be something with coder as the code that it reports hasn’t changed.

I am sure there is plenty else that may need looking at, but this is a nice feature and I have had to implement it on the D6 site that I help maintain so I am happy to try and fix any issues. It would be nice to get some feedback about the issues I have mentioned as well I don't know if they are bad or not.

JeremyFrench’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch failed testing.

JeremyFrench’s picture

Status: Needs work » Needs review
StatusFileSize
new14.4 KB

Needed to change links to /admin/structure on the tests

stewsnooze’s picture

subscribe

Queeq’s picture

Interested. Subscribed.

amc’s picture

Issue tags: +block, +poll

This would be great.

berdir’s picture

Status: Needs review » Needs work
+          $select->leftJoin('poll_vote', 'pv', 'pv.nid = n.nid and pv.uid =' . $user->uid);

You can use placeholders in joins:

+          $select->leftJoin('poll_vote', 'pv', 'pv.nid = n.nid and pv.uid = :uid', array(':uid' => $user->uid));
+          $select->orderBy('RAND()', 'ASC');

Someone needs to test this on PostgreSQL/Sqlite/... :) Random ordering in SQL is a tricky thing, syntax and performance wise....

JeremyFrench’s picture

Status: Needs work » Needs review
StatusFileSize
new14.87 KB

New patch uploaded.

Changed:
now uses a placeholder in the join.
Does a count and then changes the range to aviod the order by rand();

Status: Needs review » Needs work

The last submitted patch failed testing.

raju4u52’s picture

Version: 7.x-dev » 6.x-dev
Assigned: Unassigned » raju4u52
Status: Needs work » Active
truyenle’s picture

Status: Active » Needs review
Issue tags: -block, -poll
truyenle’s picture

Issue tags: +block, +poll

#27: random-poll.patch queued for re-testing.

JeremyFrench’s picture

@truyenle

Patch #27 won't work on D6, among other things it uses the D7 database API.

amc’s picture

Version: 6.x-dev » 8.x-dev

In any case, I'd guess this has to wait for D8.

truyenle’s picture

Thank JeremyFrench.

robato’s picture

Is there a way to do this without hacking core?

Bojhan’s picture

Status: Needs review » Closed (won't fix)

I definitely don't see any reason to add this to the core block, something like http://drupal.org/project/advpoll should take care of these kind of usecases.

Satalink’s picture

Nice job