paul@36 | 1 | # -*- coding: iso-8859-1 -*- |
paul@36 | 2 | """ |
paul@36 | 3 | MoinMoin - VoteRecorder Macro |
paul@36 | 4 | |
paul@36 | 5 | @copyright: 2008 by Paul Boddie <paul@boddie.org.uk> |
paul@36 | 6 | @license: GNU GPL (v2 or later), see COPYING.txt for details. |
paul@36 | 7 | |
paul@36 | 8 | This is like the VotingStars macro except that votes are logged for later |
paul@36 | 9 | counting, and the current state of the poll is not shown during voting. |
paul@36 | 10 | """ |
paul@36 | 11 | |
paul@37 | 12 | from MoinMoin.util import filesys, lock |
paul@36 | 13 | from MoinMoin import wikiutil |
paul@36 | 14 | import os |
paul@37 | 15 | try: |
paul@37 | 16 | import cPickle as pickle |
paul@37 | 17 | except ImportError: |
paul@37 | 18 | import pickle |
paul@36 | 19 | |
paul@37 | 20 | Dependencies = ["time"] |
paul@36 | 21 | |
paul@37 | 22 | def get_vote_directory(page, name): |
paul@36 | 23 | votes_dir = page.getPagePath("poll") |
paul@36 | 24 | if not os.path.exists(votes_dir): |
paul@36 | 25 | filesys.makeDirs(votes_dir) |
paul@37 | 26 | return votes_dir |
paul@37 | 27 | |
paul@37 | 28 | def get_vote_pathname(page, name): |
paul@37 | 29 | votes_dir = get_vote_directory(page, name) |
paul@36 | 30 | filename = wikiutil.quoteWikinameFS(name) |
paul@36 | 31 | return os.path.join(votes_dir, filename) |
paul@36 | 32 | |
paul@37 | 33 | def get_lock_directory(page, name): |
paul@37 | 34 | votes_dir = get_vote_directory(page, name) |
paul@37 | 35 | return os.path.join(votes_dir, "__lock__") |
paul@37 | 36 | |
paul@37 | 37 | def save_votes(page, poll_name, votes): |
paul@37 | 38 | vote_lock = lock.WriteLock(get_lock_directory(page, poll_name)) |
paul@37 | 39 | vote_lock.acquire() |
paul@36 | 40 | try: |
paul@37 | 41 | _save_votes(page, poll_name, votes) |
paul@37 | 42 | finally: |
paul@37 | 43 | vote_lock.release() |
paul@37 | 44 | |
paul@37 | 45 | def _save_votes(page, poll_name, votes): |
paul@37 | 46 | path = get_vote_pathname(page, poll_name) |
paul@37 | 47 | f = open(path, "wb") |
paul@37 | 48 | try: |
paul@37 | 49 | pickle.dump(votes, f) |
paul@36 | 50 | finally: |
paul@36 | 51 | f.close() |
paul@36 | 52 | |
paul@37 | 53 | def get_all_votes(page, poll_name): |
paul@37 | 54 | vote_lock = lock.ReadLock(get_lock_directory(page, poll_name)) |
paul@37 | 55 | vote_lock.acquire() |
paul@36 | 56 | try: |
paul@37 | 57 | return _get_all_votes(page, poll_name) |
paul@37 | 58 | finally: |
paul@37 | 59 | vote_lock.release() |
paul@37 | 60 | |
paul@37 | 61 | def _get_all_votes(page, poll_name): |
paul@37 | 62 | path = get_vote_pathname(page, poll_name) |
paul@37 | 63 | if not os.path.exists(path): |
paul@37 | 64 | return {} |
paul@37 | 65 | f = open(path, "rb") |
paul@37 | 66 | try: |
paul@37 | 67 | voting = pickle.load(f) |
paul@36 | 68 | return voting |
paul@36 | 69 | finally: |
paul@36 | 70 | f.close() |
paul@36 | 71 | |
paul@36 | 72 | def execute(macro, args): |
paul@36 | 73 | request = macro.request |
paul@36 | 74 | form = macro.form |
paul@36 | 75 | fmt = macro.formatter |
paul@36 | 76 | page = fmt.page |
paul@36 | 77 | |
paul@36 | 78 | output = [] |
paul@36 | 79 | |
paul@36 | 80 | # Obtain the poll name for presentation purposes. |
paul@36 | 81 | |
paul@36 | 82 | args = args.split(",") |
paul@36 | 83 | if args: |
paul@36 | 84 | poll_name = args[0] |
paul@36 | 85 | else: |
paul@36 | 86 | output.append(fmt.sysmsg(on=1)) |
paul@36 | 87 | output.append(fmt.text("Please specify a poll name!")) |
paul@36 | 88 | output.append(fmt.sysmsg(on=0)) |
paul@36 | 89 | return ''.join(output) |
paul@36 | 90 | |
paul@36 | 91 | # Show a message if the user is not logged in. |
paul@36 | 92 | |
paul@36 | 93 | # Get the user, if known. |
paul@36 | 94 | |
paul@36 | 95 | if not request.user.valid: |
paul@36 | 96 | output.append(fmt.emphasis(on=1)) |
paul@36 | 97 | output.append(fmt.text("Please log in to vote!")) |
paul@36 | 98 | output.append(fmt.emphasis(on=0)) |
paul@36 | 99 | return ''.join(output) |
paul@36 | 100 | |
paul@36 | 101 | username = request.user.name |
paul@37 | 102 | votes = get_all_votes(page, poll_name) |
paul@36 | 103 | |
paul@36 | 104 | # Handle any vote. |
paul@36 | 105 | |
paul@36 | 106 | if form and form.has_key("vote") and form.has_key("poll"): |
paul@36 | 107 | poll = form["poll"][0] |
paul@36 | 108 | if poll == poll_name: |
paul@37 | 109 | votes[username] = int(form["vote"][0]) |
paul@37 | 110 | save_votes(page, poll_name, votes) |
paul@36 | 111 | output.append(fmt.emphasis(on=1)) |
paul@36 | 112 | output.append(fmt.text("Vote submitted!")) |
paul@36 | 113 | output.append(fmt.emphasis(on=0)) |
paul@36 | 114 | return ''.join(output) |
paul@36 | 115 | |
paul@36 | 116 | # Show the choices. |
paul@36 | 117 | |
paul@36 | 118 | values = { |
paul@36 | 119 | "poll" : poll_name, "url" : page.url(request), |
paul@36 | 120 | "on_image" : '/wiki/modern/img/star_on.png', |
paul@36 | 121 | "off_image" : '/wiki/modern/img/star_off.png' |
paul@36 | 122 | } |
paul@36 | 123 | choices = range(1, 6) |
paul@36 | 124 | |
paul@36 | 125 | output.append(fmt.rawHTML('<form method="get" name="%(poll)s" action="%(url)s#%(poll)s">' % values)) |
paul@36 | 126 | output.append(fmt.rawHTML('<input type="hidden" name="poll" value="%(poll)s">' % values)) |
paul@37 | 127 | |
paul@36 | 128 | for choice in choices: |
paul@36 | 129 | values["choice"] = choice |
paul@37 | 130 | if votes.has_key(username) and choice <= votes[username]: |
paul@37 | 131 | values["default_image"] = values["on_image"] |
paul@37 | 132 | else: |
paul@37 | 133 | values["default_image"] = values["off_image"] |
paul@36 | 134 | output.append( |
paul@36 | 135 | fmt.rawHTML(''' |
paul@37 | 136 | <input type="image" name="vote" value="%(choice)s" src="%(default_image)s" |
paul@37 | 137 | onmouseover="this.src='%(on_image)s'" |
paul@37 | 138 | onmouseout="this.src='%(default_image)s'"> |
paul@36 | 139 | ''' % values)) |
paul@37 | 140 | |
paul@36 | 141 | output.append(fmt.rawHTML('</form>')) |
paul@36 | 142 | |
paul@36 | 143 | return ''.join(output) |
paul@36 | 144 | |
paul@36 | 145 | # vim: tabstop=4 expandtab shiftwidth=4 |