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@43 | 14 | import MoinMoin.user |
paul@36 | 15 | import os |
paul@37 | 16 | try: |
paul@37 | 17 | import cPickle as pickle |
paul@37 | 18 | except ImportError: |
paul@37 | 19 | import pickle |
paul@36 | 20 | |
paul@37 | 21 | Dependencies = ["time"] |
paul@36 | 22 | |
paul@37 | 23 | def get_vote_directory(page, name): |
paul@36 | 24 | votes_dir = page.getPagePath("poll") |
paul@36 | 25 | if not os.path.exists(votes_dir): |
paul@36 | 26 | filesys.makeDirs(votes_dir) |
paul@37 | 27 | return votes_dir |
paul@37 | 28 | |
paul@37 | 29 | def get_vote_pathname(page, name): |
paul@37 | 30 | votes_dir = get_vote_directory(page, name) |
paul@36 | 31 | filename = wikiutil.quoteWikinameFS(name) |
paul@36 | 32 | return os.path.join(votes_dir, filename) |
paul@36 | 33 | |
paul@37 | 34 | def get_lock_directory(page, name): |
paul@37 | 35 | votes_dir = get_vote_directory(page, name) |
paul@37 | 36 | return os.path.join(votes_dir, "__lock__") |
paul@37 | 37 | |
paul@37 | 38 | def save_votes(page, poll_name, votes): |
paul@37 | 39 | vote_lock = lock.WriteLock(get_lock_directory(page, poll_name)) |
paul@37 | 40 | vote_lock.acquire() |
paul@36 | 41 | try: |
paul@37 | 42 | _save_votes(page, poll_name, votes) |
paul@37 | 43 | finally: |
paul@37 | 44 | vote_lock.release() |
paul@37 | 45 | |
paul@37 | 46 | def _save_votes(page, poll_name, votes): |
paul@37 | 47 | path = get_vote_pathname(page, poll_name) |
paul@37 | 48 | f = open(path, "wb") |
paul@37 | 49 | try: |
paul@37 | 50 | pickle.dump(votes, f) |
paul@36 | 51 | finally: |
paul@36 | 52 | f.close() |
paul@36 | 53 | |
paul@37 | 54 | def get_all_votes(page, poll_name): |
paul@37 | 55 | vote_lock = lock.ReadLock(get_lock_directory(page, poll_name)) |
paul@37 | 56 | vote_lock.acquire() |
paul@36 | 57 | try: |
paul@37 | 58 | return _get_all_votes(page, poll_name) |
paul@37 | 59 | finally: |
paul@37 | 60 | vote_lock.release() |
paul@37 | 61 | |
paul@37 | 62 | def _get_all_votes(page, poll_name): |
paul@37 | 63 | path = get_vote_pathname(page, poll_name) |
paul@37 | 64 | if not os.path.exists(path): |
paul@37 | 65 | return {} |
paul@37 | 66 | f = open(path, "rb") |
paul@37 | 67 | try: |
paul@37 | 68 | voting = pickle.load(f) |
paul@36 | 69 | return voting |
paul@36 | 70 | finally: |
paul@36 | 71 | f.close() |
paul@36 | 72 | |
paul@36 | 73 | def execute(macro, args): |
paul@36 | 74 | request = macro.request |
paul@36 | 75 | form = macro.form |
paul@36 | 76 | fmt = macro.formatter |
paul@36 | 77 | page = fmt.page |
paul@36 | 78 | |
paul@36 | 79 | output = [] |
paul@36 | 80 | |
paul@36 | 81 | # Obtain the poll name for presentation purposes. |
paul@36 | 82 | |
paul@36 | 83 | args = args.split(",") |
paul@36 | 84 | if args: |
paul@36 | 85 | poll_name = args[0] |
paul@36 | 86 | else: |
paul@36 | 87 | output.append(fmt.sysmsg(on=1)) |
paul@36 | 88 | output.append(fmt.text("Please specify a poll name!")) |
paul@36 | 89 | output.append(fmt.sysmsg(on=0)) |
paul@36 | 90 | return ''.join(output) |
paul@36 | 91 | |
paul@43 | 92 | # Check for extra arguments. |
paul@43 | 93 | # NOTE: This is only adequate protection if an ACL stops untrusted users |
paul@43 | 94 | # NOTE: from editing the page. This should actually query the ACL in order |
paul@43 | 95 | # NOTE: to prevent such exploits. |
paul@43 | 96 | |
paul@43 | 97 | public = "public" in args[1:] |
paul@36 | 98 | |
paul@36 | 99 | # Get the user, if known. |
paul@43 | 100 | # Show a message if the user is not logged in and the poll is not public. |
paul@36 | 101 | |
paul@43 | 102 | if not public and not request.user.valid: |
paul@36 | 103 | output.append(fmt.emphasis(on=1)) |
paul@36 | 104 | output.append(fmt.text("Please log in to vote!")) |
paul@36 | 105 | output.append(fmt.emphasis(on=0)) |
paul@36 | 106 | return ''.join(output) |
paul@36 | 107 | |
paul@43 | 108 | username = MoinMoin.user.getUserIdentification(request) |
paul@43 | 109 | #username = request.user.valid and request.user.name or request.user.host() |
paul@37 | 110 | votes = get_all_votes(page, poll_name) |
paul@36 | 111 | |
paul@36 | 112 | # Handle any vote. |
paul@36 | 113 | |
paul@36 | 114 | if form and form.has_key("vote") and form.has_key("poll"): |
paul@36 | 115 | poll = form["poll"][0] |
paul@36 | 116 | if poll == poll_name: |
paul@37 | 117 | votes[username] = int(form["vote"][0]) |
paul@37 | 118 | save_votes(page, poll_name, votes) |
paul@36 | 119 | output.append(fmt.emphasis(on=1)) |
paul@36 | 120 | output.append(fmt.text("Vote submitted!")) |
paul@36 | 121 | output.append(fmt.emphasis(on=0)) |
paul@36 | 122 | return ''.join(output) |
paul@36 | 123 | |
paul@36 | 124 | # Show the choices. |
paul@36 | 125 | |
paul@36 | 126 | values = { |
paul@36 | 127 | "poll" : poll_name, "url" : page.url(request), |
paul@36 | 128 | "on_image" : '/wiki/modern/img/star_on.png', |
paul@36 | 129 | "off_image" : '/wiki/modern/img/star_off.png' |
paul@36 | 130 | } |
paul@36 | 131 | choices = range(1, 6) |
paul@36 | 132 | |
paul@36 | 133 | output.append(fmt.rawHTML('<form method="get" name="%(poll)s" action="%(url)s#%(poll)s">' % values)) |
paul@36 | 134 | output.append(fmt.rawHTML('<input type="hidden" name="poll" value="%(poll)s">' % values)) |
paul@37 | 135 | |
paul@36 | 136 | for choice in choices: |
paul@36 | 137 | values["choice"] = choice |
paul@37 | 138 | if votes.has_key(username) and choice <= votes[username]: |
paul@37 | 139 | values["default_image"] = values["on_image"] |
paul@37 | 140 | else: |
paul@37 | 141 | values["default_image"] = values["off_image"] |
paul@36 | 142 | output.append( |
paul@36 | 143 | fmt.rawHTML(''' |
paul@37 | 144 | <input type="image" name="vote" value="%(choice)s" src="%(default_image)s" |
paul@37 | 145 | onmouseover="this.src='%(on_image)s'" |
paul@37 | 146 | onmouseout="this.src='%(default_image)s'"> |
paul@36 | 147 | ''' % values)) |
paul@37 | 148 | |
paul@36 | 149 | output.append(fmt.rawHTML('</form>')) |
paul@36 | 150 | |
paul@36 | 151 | return ''.join(output) |
paul@36 | 152 | |
paul@36 | 153 | # vim: tabstop=4 expandtab shiftwidth=4 |