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