diff --git a/wortschlucker/src/forms.py b/wortschlucker/src/forms.py
index 2f0b6c6..45b6563 100644
--- a/wortschlucker/src/forms.py
+++ b/wortschlucker/src/forms.py
@@ -17,6 +17,10 @@ class SubmitForm(formencode.Schema):
submitter = formencode.validators.UnicodeString(strip=True, not_empty=True)
content = formencode.validators.UnicodeString(strip=True, not_empty=True)
+class VoteSubmissionOrderForm(formencode.Schema):
+ submitter = formencode.validators.UnicodeString(strip=True, not_empty=True)
+ vote_order = formencode.validators.UnicodeString(strip=True)
+
class ProfileForm(formencode.Schema):
email = formencode.validators.Email(resolve_domain=True, strip=True, not_empty=True)
diff --git a/wortschlucker/src/wortschlucker.py b/wortschlucker/src/wortschlucker.py
index 40c9c05..8b62e5a 100755
--- a/wortschlucker/src/wortschlucker.py
+++ b/wortschlucker/src/wortschlucker.py
@@ -104,6 +104,12 @@ class ContentSubmission(sqlobject.SQLObject):
return hashlib.md5(str(self.id)).hexdigest()
+class VoteOrder(sqlobject.SQLObject):
+ submitter = sqlobject.UnicodeCol()
+ content_submission_id = sqlobject.ForeignKey("ContentSubmission")
+ priority = sqlobject.IntCol()
+
+
class Profile(sqlobject.SQLObject):
email = sqlobject.UnicodeCol(unique=True)
hash_key = sqlobject.StringCol(unique=True)
@@ -198,6 +204,14 @@ class Poll(sqlobject.SQLObject):
if (key == 'public') and (value > 0):
self.announce_via_twitter()
+ def get_ordered_submissions(self, submitter):
+ votes = []
+ for submission in ContentSubmission.selectBy(poll_id=self.id):
+ votes.extend(list(VoteOrder.selectBy(content_submission_id=submission,
+ submitter=submitter)))
+ votes.sort(key=lambda item: item.priority)
+ return [order.content_submission_id for order in votes]
+
def announce_via_twitter(self):
complete_url = self.get_url(absolute=True)
try:
@@ -215,6 +229,14 @@ class Poll(sqlobject.SQLObject):
return
publish_twitter_alert(title, twitter_key, twitter_secret, twitter_access_key, twitter_access_secret)
+ def get_num_of_votes(self):
+ submitters = []
+ for submission in ContentSubmission.selectBy(poll_id=self.id):
+ for vote in VoteOrder.selectBy(content_submission_id=submission):
+ if not vote.submitter in submitters:
+ submitters.append(vote.submitter)
+ return len(submitters)
+
def get_num_of_submitters(self):
all_submitters = [submission.submitter for submission in ContentSubmission.selectBy(poll_id=self.id)]
unique_submitters = []
@@ -245,8 +267,7 @@ class Poll(sqlobject.SQLObject):
return get_url_string("%s%s/submit" % (BASE_DICT["base_url"], self.hash_key), absolute)
def get_vote_url(self, absolute=False):
- #TODO vote: Diese Funktion ist noch falsch, aber erstmal als Platzhalter noetig
- return ""
+ return get_url_string("%s%s/vote" % (BASE_DICT["base_url"], self.hash_key), absolute)
def get_admin_url(self, absolute=False, suffix=""):
return get_url_string("%s%s%s" % (BASE_DICT["base_url"], self.admin_hash_key, suffix), absolute)
@@ -266,6 +287,9 @@ class Poll(sqlobject.SQLObject):
def is_vote_enabled(self):
return self.get_settings()["vote_enabled"]
+ def is_vote_finished(self, submitter):
+ return len(self.get_ordered_submissions(submitter)) > 0
+
def get_submissions_visibility(self):
settings = self.get_settings()
return bool(settings["show_all_submissions"] or (settings["expose_date"] and \
@@ -553,15 +577,24 @@ def publish_twitter_alert(text, key, secret,access_key,access_secret):
except urllib2.URLError, e:
print e.reason
-def check_spam_submitter_name(name):
+def is_spam_submitter_name(name, errors_dict):
lower_text = re.sub("[^a-z]", "", name)
upper_text = re.sub("[^A-Z]", "", name)
- return (len(lower_text) + len(upper_text) == len(name)) and \
+ if (len(lower_text) + len(upper_text) == len(name)) and \
(len(lower_text) > 3) and (len(upper_text) > 3) and \
- (len(name) >= 8) and (not name.startswith(upper_text))
+ (len(name) >= 8) and (not name.startswith(upper_text)):
+ errors_dict["submitter"] = "Spam-Verdacht: bitte den Namen korrigieren"
+ return False
+ else:
+ return True
-def check_spam_content(text):
- return bool(re.search(r"()", text.lower()))
+def is_spam_content(text, errors_dict):
+ if re.search(r"()", text.lower()):
+ errors_dict["content"] = \
+ "Spam-Verdacht: Inhalt darf keine HTML-Tags enthalten"
+ return True
+ else:
+ return False
@bobo.query('/profile/logout')
def user_logout(bobo_request):
@@ -738,20 +771,61 @@ def new_poll(bobo_request, submit=None, cancel=None, author=None, title=None,
new_poll.change_setting(key, value)
return bobo.redirect(new_poll.get_admin_url())
+@bobo.query('/:hash_key/vote')
+def vote_submission_order(bobo_request, hash_key=None, submitter=None,
+ vote_order=None):
+ value_dict = get_default_values(bobo_request)
+ value_dict["errors"] = {}
+ data = {}
+ if submitter and is_spam_submitter_name(submitter, value_dict["errors"]):
+ data["submitter"] = submitter.strip()
+ if vote_order:
+ data["vote_order"] = vote_order
+ else:
+ data["vote_order"] = ""
+ poll_id = get_poll_id(hash_key)
+ if not poll_id is None:
+ poll = Poll.get(poll_id)
+ value_dict["poll"] = poll
+ try:
+ data = forms.VoteSubmissionOrderForm.to_python(data)
+ except formencode.Invalid, errors_packed:
+ # merge errors with previous ones - but never overwrite existing ones
+ errors = errors_packed.unpack_errors()
+ errors.update(value_dict["errors"])
+ value_dict["errors"] = errors
+ if value_dict["errors"] or poll.is_closed() or \
+ not poll.is_vote_enabled():
+ # ignore silently
+ pass
+ elif poll.is_vote_finished(submitter):
+ # there is already a vote stored for that submitter name
+ value_dict["errors"]["submit"] = \
+ "Fehler: deine Wahl wurde bereits gespeichert."
+ else:
+ # store this order of items
+ digest_dict = {}
+ for submission in ContentSubmission.selectBy(poll_id=poll.id):
+ digest_dict[submission.get_obfuscated_digest()] = submission
+ vote_order = vote_order.split()
+ for index, digest in enumerate(vote_order):
+ if digest in digest_dict:
+ VoteOrder(submitter=submitter, priority=index,
+ content_submission_id=digest_dict[digest])
+ #value_dict["errors"]["submit"] = str(poll.get_ordered_submissions(submitter))
+ value_dict["submitter"] = submitter
+ return render("poll_details.html", input_data=data, **value_dict)
+ else:
+ return bobo.redirect(BASE_DICT["base_url"])
+
@bobo.query('/:hash_key/submit')
def submit_content(bobo_request, hash_key=None, submitter=None, content=None):
value_dict = get_default_values(bobo_request)
value_dict["errors"] = {}
data = {}
- if content and check_spam_content(content):
- value_dict["errors"]["content"] = \
- "Spam-Verdacht: Inhalt darf keine HTML-Tags enthalten"
- else:
+ if content and is_spam_content(content, value_dict["errors"]):
data["content"] = content
- if submitter and check_spam_submitter_name(submitter):
- value_dict["errors"]["submitter"] = \
- "Spam-Verdacht: bitte den Namen korrigieren"
- else:
+ if submitter and is_spam_submitter_name(submitter, value_dict["errors"]):
data["submitter"] = submitter
poll_id = get_poll_id(hash_key)
if not poll_id is None:
@@ -774,7 +848,8 @@ def submit_content(bobo_request, hash_key=None, submitter=None, content=None):
# remove "content" for the next input
del data["content"]
return render("poll_details.html", input_data=data, **value_dict)
- return bobo.redirect(BASE_DICT["base_url"])
+ else:
+ return bobo.redirect(BASE_DICT["base_url"])
@bobo.query('/:admin_hash_key/delete')
def delete_poll(bobo_request, admin_hash_key=None):
@@ -1149,7 +1224,7 @@ def static_files(p1=None, p2=None, p3=None):
return get_static_file(pathname)
-for table in (Poll, ContentSubmission, PollSetting, PollRelation, Profile, ProfilePolls):
+for table in (Poll, ContentSubmission, VoteOrder, PollSetting, PollRelation, Profile, ProfilePolls):
#table.dropTable()
if not table.tableExists():
table.createTable()