Important announcements from CouchCMS team
39 posts Page 1 of 4
Hi Everybody,

Lately I had to work on something which, I think, many others would find useful too.
It's a single module that covers (or can be extended to cover) almost any kind of votes/ratings/polls function.

I am attaching it here for all fellow couchers to review before it makes its way into the core.
install.zip
(13 KiB) Downloaded 2451 times
https://github.com/CouchCMS/Votes


A little description of the addon -
Using this module assumes at least a passing familiarity with Databound forms (http://www.couchcms.com/docs/concepts/d ... forms.html) as it piggy-backs on that module.

It has been designed to work with the Members module (http://www.couchcms.com/forum/viewtopic.php?f=5&t=8063). However, if you wish you may use it in a standalone fashion for only anonymous voting.

INSTALLATION:

Extracting the zip attached with this post will yield a folder named 'install'.
1. Please copy the 'install/couch/parser/parser.php' file and paste it within the 'couch/parser/' folder of your Couch installation (effectively overwriting the original 'parser.php' that ships with Couch - this step is a temporary measure and won't be required when the next version of Couch is released).

2. Next, copy the 'votes' folder (found below 'install/couch/addons/') and place it within the 'couch/addons' folder of your Couch installation and add the following line to 'couch/addons/kfunctions.php' of your installation (you might have to rename kfunctions.example.php to kfunctions.php for newer installations)
Code: Select all
require_once( K_COUCH_DIR.'addons/votes/votes.php' );

3. The 'config.php' file within the 'votes' folder has a couple of optional settings that can be changed to suit your needs.

USAGE:

a. Defining the regions:
As of now this module offers three new types of editable regions (it can be easily extended to create more but these are included by default):

1. vote_updown
2. vote_stars
3. vote_poll

The 'vote_updown' can be used for simple 'Likes' (where only 'ups' are submitted) or 'Thumbs-Up/Thumbs-Down', 'Vote-Up/Vote-Down' etc. (where two distinct votes i.e. 'ups' and 'downs' can be submitted).

The 'vote_stars' can be used for 5-stars rating (can also accept an optional '0' star vote).

The 'vote_poll' can be used to create polls (with a maximum number of 10 options).

All the above-mentioned editable regions are created the usual way e.g.
Code: Select all
<cms:editable type='vote_updown' search_type='decimal' name='my_vote' />
<cms:editable type='vote_stars' search_type='decimal' allow_zero_stars='0' name='my_stars' />
<cms:editable type='vote_poll' search_type='decimal' name='my_poll' />

Points to note:
a. The 'search_type' should be set to 'decimal' as we'll use these fields for finding/sorting pages according to the
votes (e.g. most voted, highest starred etc.).

b. The 'vote_stars' type supports an optional parameter named 'allow_zero_stars' which can be set to '1' to allow (real pissed-off) visitors submit a rating of zero stars :)

c. The 'vote_updown' and 'vote_stars' regions will normally be added to existing templates (e.g. products.php, reviews.php etc.) to allow voting on individual pages of the templates.
The 'vote_poll' region, however, will normally get a template of its own (e.g. polls.php) where each cloned page of the template will represent a distinct poll. As is normal with all cloned-pages in Couch, data from any of the polls can be displayed absolutely anywhere else on the site (a full example follows later in this post).

After defining any of these regions visit the admin-panel and you'll find that, unlike other editable regions in Couch, these do not offer any kind of input box for entering data.

That is understandable because the data these regions will hold would be the votes submitted by visitors.
This will require using the 'data-bound-form' feature of Couch to create forms on the front-end. The visitors will use these forms to submit their votes.

b. Create front-end forms for submitting votes.
You'll recall from our documentation about 'DataBound Forms' that, we can directly change a field's value by specifying that field's name as a parameter of the cms:db_persist_form tag e.g. in the snippet below
Code: Select all
..
<cms:if k_success>
    <cms:db_persist_form
        my_field='hello world'
    />
</cms:if>
..

whenever the form gets submitted, the field named 'my_field' gets saved with a value of 'hello world'.

Now, if we were to replace the above field with the name of any of the three 'votes' type region we have seen e.g.
Code: Select all
..
<cms:if k_success>
    <cms:db_persist_form
        my_stars='5'
    />
</cms:if>..
   

where 'my_stars' is the name of a region of type 'vote_stars' that we defined for the template, every time this form gets submitted a vote of value '5' stars gets submitted.
Not a very democratic way of voting, I am sure you'll agree, but this snippet demonstrates the crucial point of how we actually input a vote into the three editable regions of ours.

If now we could offer an appropriate set of options to the visitor (e.g. 1 to 5 stars or '1' for 'Up' and '-1' for 'Down') to choose his vote from, we can input that chosen value into the field e.g.
Code: Select all
..
<cms:if k_success>
    <cms:db_persist_form
        my_stars=frm_stars
    />
</cms:if>
..

In the snippet above, the 'frm_stars' variable holds the value submitted through an input named 'stars'

The bottom-line (and one that I'd like to emphasize) here is that, this votes module does NOT offer (or force upon, depending on how you look at it) a GUI for actually inputting the vote.

It is totally up to you to use any kind of JS library or any other method to display the '5 stars' or the 'Reddit or Digg type' updown vote buttons.

The only thing that matters to the votes module is the value that you feed it through the cms:db_persist_form tag.

To give you some complete working examples, I'll use the plain-Jane cms:inputs available with Couch forms to create the options.

Example 1 (type='vote_updown')
Assuming that we have defined a region of type 'vote_updown' by the name of 'my_vote' in a clonable template (e.g.
blog.php) as follows -
Code: Select all
<cms:editable type='vote_updown' search_type='decimal' name='my_vote' />

- the following code placed in the page-view of the template will allow visitors to vote on each cloned-page (e.g. on
every blog post) -
Code: Select all
<cms:form
    masterpage=k_template_name
    mode='edit'
    page_id=k_page_id
    anchor='0'
    method='post'
    >

    <cms:if k_success>
        <cms:db_persist_form
            my_vote=frm_vote
        />
        <cms:redirect k_page_link />
    </cms:if>


    <cms:input type='radio' name='vote' opt_values='Up=1 || Down=-1' /><br />


    <input type="submit" name="submit" value="Vote"/>

</cms:form>

Please note that the 'vote_updown' type accepts only two values - '1' or '-1'. In the snippet above, these are the two values that the 'Up' and 'Down' submit.

Example 2 (type='vote_stars')
Assuming that we have defined a region of type 'vote_stars' by the name of 'my_stars' in a clonable template (e.g. blog.php) as follows -
Code: Select all
<cms:editable type='vote_stars' search_type='decimal' name='my_stars' />

- the following code placed in the page-view of the template will allow visitors to star rate each cloned-page (e.g. on every blog post) -
Code: Select all
<cms:form
    masterpage=k_template_name
    mode='edit'
    page_id=k_page_id
    anchor='0'
    method='post'
    >

    <cms:if k_success>
        <cms:db_persist_form
            my_stars=frm_stars
        />
        <cms:redirect k_page_link />
    </cms:if>

    <cms:input type='dropdown' name='stars' opt_values=' 1 | 2 | 3 | 4 | 5' /><br />


    <input type="submit" name="submit" value="Vote"/>

</cms:form>

Please note that the 'vote_stars' type accepts only these values - 0, 1, 2, 3, 4 or 5 (For '0' to be accepted, the region needs to be defined with the 'allow_zero_stars' parameter set to '1'). In the snippet above, each of the 'stars'
submits one of these values.

Example 3 (type='vote_poll')
The type 'vote_poll' poll is slightly different from its two siblings we saw above -

a. Instead of adding a poll region directly to an existing template (e.g. blog.php in the examples above), we use a separate clonable template where each cloned-page represents a separate poll.

b. For a poll, we also need a way to input the various poll options (else what are we holding the poll for?)

So, to allow creation of polls, we use a dedicated cloned template, say named 'polls.php' and define a vote field of type 'vote_poll' in it.

As we have already seen, these vote regions do not offer any customary input widgets for data entry (e.g. a textbox). So to address the second point above, we define a companion field of type textarea along with the poll field.
The site-owner is expected to input up to 10 poll options in this textarea with each option being on a separate line.

Following is how our definitions for the two fields could look like -
Code: Select all
<cms:editable type='vote_poll' search_type='decimal' name='test_poll' />

<cms:editable type='textarea' name='poll_options' desc='Place each option on a new line. You may enter up to 10 options.' />

To create a poll, the site-owner can now create a new cloned-page, use the title of the page as the poll question and fill the poll=options in the textarea. (If using the system title field for the poll-question does not appeal you, go ahead and create a dedicated text field for the purpose).

On the front-end side, you can either offer the poll form on the page-view of the poll template itself or (as is normally seen) place the form on the home-page of the site etc.

Following is an example of how to display the latest poll on any page of the site (for displaying the poll on the poll template's page-view, the cms:pages block will be unnecessary) -
Code: Select all
<!-- poll start -->
<cms:set page_to_redirect=k_page_link />

<cms:pages masterpage='polls.php' limit='1' >

    <cms:each poll_options sep='\n'>
        <cms:if k_count lt '10' >
            <cms:php>global $CTX; $CTX->set( 'item',str_replace('|', '\\|', $CTX->get('item')) );</cms:php>
            <cms:set my_poll_options="<cms:concat my_poll_options '||' item '=' k_count />"  scope='global'/>
        </cms:if>
    </cms:each>

    <cms:if "<cms:not_empty my_poll_options />" >
        <cms:form
            masterpage=k_template_name
            mode='edit'
            page_id=k_page_id
            anchor='0'
            method='post'
            >

            <cms:if k_success>
                <cms:dump />
                <cms:db_persist_form
                    test_poll=frm_poll
                />
                <cms:redirect page_to_redirect />
            </cms:if>


            <cms:input type='radio' name='poll' opt_values=my_poll_options /><br />


            <input type="submit" name="submit" value="Vote"/>

        </cms:form>

    </cms:if>
</cms:pages>
<!-- end poll -->

As you can see, the way the poll results are submitted into the system remains exactly the same as the other two vote types.
The 'vote_poll' type only accepts numbers ranging from 0 to 9.
Since the submitted number will represent an option from the textarea, the only piece of complexity above is where we use the cms:each to loop through the options and use the line-number for the options' value.

c. Display the poll results
Finally, we come to the part where we display the results of our polls.

We have two ways of getting the results -
1.
To get a detailed analysis of the votes, this module ships with an auxiliary tag that can be used with all the three votes types - cms:show_votes.

Provide this tag the name of a vote editable region in context and it'll make available all the analyzed data for the region as variables (the variables will differ with the type of the region). These values then can be displayed using cms:show.

(IMP: Please make sure to place <cms:no_cache /> tag on the templates displaying these results to prevent Couch from showing cached (and hence stale) data).

To see for yourself what these variables are, use cms:dump tag e.g.
Code: Select all
<cms:show_votes 'test_vote' >
    <cms:dump />
</cms:show_votes>

The variables for type 'vote_updown' region (named 'test_vote' in example above) will be these -
count
sum
count_up
count_down
percent_up
percent_down
already_voted
last_vote_value
vote_type

For a region of type 'vote_stars', the variables will become -
count
avg
count_0
count_1
count_2
count_3
count_4
count_5
percent_0
percent_1
percent_2
percent_3
percent_4
percent_5
already_voted
last_vote_value
vote_type
allow_zero_stars

As can be seen, detailed analysis per option (up/down or each star) is made available.
The 'already_voted' and 'last_vote_value' variables show if the member or visitor has already voted and the value of that vote. These variables can be used to conditionally hide/display the voting form.

Similarly, for a region of type 'vote_poll', the variables will display data about each options from 0 to 9 -
e.g.
count_0
..
count_9
percent_0
..
percent_9

To covert the generic 'count_n' or 'percent_n' into the actual text for the option (as inputted by the site-owner), we can use the following -
Code: Select all
<cms:show_votes 'test_poll' >
    <ul>
    <cms:each poll_options sep='\n'>
        <li><cms:show item /> <small>(<cms:get "percent_<cms:show k_count />" />%, <cms:get "count_<cms:show k_count
        />" /> Votes)</small>
    </cms:each>
    </ul>
    <p>Total Voters: <strong><cms:show count /></strong></p>
</cms:show_votes>

This will output something like -
White (32%, 1047 Votes)
Blue (28%, 916 Votes)
Red (24%, 801 Votes)
Purple (9%, 307 Votes)
Green (7%, 227 Votes)

Total Voters: 3298

2.
Instead of getting a detailed analysis of the votes, as we did above, if we simply use cms:show with the vote region i.e. like this -
Code: Select all
<cms:show test_stars />

- it will print out a single numeric value representing a summary of the total votes.

Each of the three vote types uses a different function to calculate this summary value -
The 'vote_updown' type will output the 'sum' of the total votes polled (i.e. positive votes minus the negative votes).
The 'vote_stars' type will output the 'average' of all stars submitted (e.g. 3.4)
The 'vote_poll' will simply output the 'total' number of votes polled.

One very important thing that we can do with these summary values is use them to list the 'Top-rated 5 pages' or 'Most liked 5 pages' (i.e. pages with most stars or highest sum of up/down votes).
Nothing could be easier as we can use our trusty cms:pages for this e.g.
Code: Select all
<cms:pages orderby='test_stars' order='asc' limit='5' >
    ... this will list the top 5 pages with highest star ratings ..
</cms:pages>

The key above is the use of the vote type region with the 'orderby' parameter.

Finally..
In closing, an appeal to all designers in our community -
as you have seen, this deceptively simple polls module gives us a powerful way to store and analyze vote data.
The front-end part (e.g. the way the 'stars' or the 'thumbs-up/thumbs-down' icons are shown) has been deliberately omitted, in deference to Couch's philosophy, so as to make this module work with any custom HTML markup.

However, there would be people who'd like to have a ready-made solution to use on their sites e.g. a star-rating complete with HTML/JS/CSS etc.
So please try this addon and do share your solutions here as they would be helpful to others.

As always, your feedback is solicited :)
And as always, thank you.

I should probably release digest and compilation of all couch addons. I pretty much download all of them and add a little description, might as well post them in forum.
Mr Kashif! :D
Let me start by pointing out what I think are mistakes so others don't bombard you with questions (after my questions :P).
I have attached an image pointing at the codes my_vote=my_vote that I think is a mistake? ..and should be my_vote=frm_vote instead?
Second isn't in the code, just the title, no biggie...

And now... Questions!
The vote_updown region yields the total number of votes from users right? As in if 10 people each voted, the total votes is 10. But in the admin panel I noticed "1 points from 1 votes (1 up, 0 down)".
I want the codes that displays those figures in the brackets, because my site shows how many "good" votes and how many "bad"... separately.
If you did write down how to achieve that, please forgive me its 3am here :D

PS: Would it be beyond the scope of this addon to have it incorporate a page-views system?
I'd rather everything is handled by Couch than various third party codes here and there.

Thanks!

Attachments

---
You live many times, but only ever remember your lives.length - 1
---
Image
Thanks for the heads-up, Simmons. My belief stands confirmed that it is easier to code than to document the code :)
I've rectified the typos in the original post above.

Answering your questions -
The vote_updown region yields the total number of votes from users right? As in if 10 people each voted, the total votes is 10. But in the admin panel I noticed "1 points from 1 votes (1 up, 0 down)".

If suppose 10 people voted where 6 voted up while 4 voted down, cms:show_votes will give the following variables -
count: 10
sum: 2
count_up: 6
count_down: 4
percent_up: 60
percent_down: 40

As you can see,
sum = upvotes - downvotes
So, what you see in the admin stands for
"Sum of votes from total votes (total up, totaldown)"
I want the codes that displays those figures in the brackets, because my site shows how many "good" votes and how many "bad"... separately.

On the front-end you have seen the variables thayt you can use.
If you want to change the way things get displayed in the back-end, you'll have to modify the source file.

Hope this helps.
Wow, Kamran... you never cease to amaze me.

Just today I needed a rating solution for my site, and what do you know? The new Votes, Ratings & Polls module is now available for testing... AWESOME!

However I'm also wondering if there is any "follow" feature that can be implemented with this new module? Say to follow another member or a published article? It would kind of work like the votes system (where a registered user chooses what is relevant to them), right?

@KK, THANKS for all your work and the help!
-Izzy
Hello,

This is my first post. And, Im new to Couch! :)

The limit of 10 questions for the poll is a technical issue? You can leave unlimited, at least in the final version?

Congratulations for the good work it has been doing with Couch!

Luiz
Code: Select all
<cms:editable name='banner' type='message'>
<cms:show_votes 'test_poll' >
<ul>
<cms:each poll_options sep='\n'>
<li><cms:show item /> <small>(<cms:get "percent_<cms:show k_count />" />%, <cms:get "count_<cms:show k_count
/>" /> Votes)</small>
</cms:each>
</ul>
<p>Total Voters: <strong><cms:show count /></strong></p>
</cms:show_votes></cms:editable>

Using the <cms:editable> type of Message can put the results of the poll in the admin panel. Very useful.

EDIT : Only works on non-clonable polls.
Is it possible to reset a poll using
Code: Select all
<cms:db_delete>
Is it possible to reset a poll using <cms:db_delete>

cms:db_delete will delete the poll (the cloned-page containing the poll actually) completely.
I don't think that is what you have in mind. I suppose you want to remove all casted votes so as to make the vote-count zero. Right?

To be honest, the possibility that someone would want to do this never crossed my mind :)
For now, I am afraid, we'll have to manipulate the database directly to pull this off.
We are only using a non-clonable template to enable us to embed the results of the poll onto the admin panel itself. Is it possible to do so with a cloned template?

Thanks for your help!
39 posts Page 1 of 4