Search for usernames literally, not with func.lower().
[zzz-floof.git] / floof / controllers / tag.py
1 import logging
2 import re
3
4 from pylons import request, response, session, tmpl_context as c, url
5 from pylons.controllers.util import abort, redirect
6
7 import elixir
8 from floof.model import Art, ArtUser, ArtUserType, Tag, TagText, User
9 from floof.lib.base import BaseController, render
10 from floof.lib.dbhelpers import find_or_create
11 from floof.lib import helpers as h
12
13 log = logging.getLogger(__name__)
14
15 class TagController(BaseController):
16
17 # TODO: login required
18 def delete(self, art_id, id):
19 tag = h.get_object_or_404(Tag, id=id)
20 elixir.session.delete(tag)
21 elixir.session.commit()
22 redirect(url('show_art', id=art_id))
23
24 # TODO: login required
25 def create(self, art_id):
26 c.art = h.get_object_or_404(Art, id=art_id)
27
28 tag_string = request.params.get('tags', '')
29
30 # Add or remove tags
31 bad_tags = []
32 for tag_text in tag_string.split():
33 original_tag_text = tag_text
34 tag_text = tag_text.lower()
35
36 # Adding or removing a tag?
37 if tag_text[0] == '-':
38 add = False
39 tag_text = tag_text[1:]
40 else:
41 # Allow "+foo" to mean "add foo"
42 if tag_text[0] == '+':
43 tag_text = tag_text[1:]
44 add = True
45
46 # Check for special namespaces
47 prefix = None
48 if ':' in tag_text:
49 prefix, tag_text = tag_text.split(':', 1)
50 if prefix not in ['by', 'for', 'of']:
51 # This is bogus. Skip it.
52 bad_tags.append(original_tag_text)
53 continue
54
55 if prefix == 'by':
56 # XXX this needs supporting. silently ignore for now
57 continue
58
59 # Must be 3-50 alphanumeric characters
60 if not re.match('^[a-z0-9]{3,50}$', tag_text):
61 bad_tags.append(original_tag_text)
62 continue
63
64 # Do work!
65 if prefix:
66 target_user = User.get_by(name=tag_text)
67
68 # Special tag; at the moment, just a relationship
69 if prefix == 'by':
70 rel = ArtUserType.BY
71 elif prefix == 'for':
72 rel = ArtUserType.FOR
73 elif prefix == 'of':
74 rel = ArtUserType.OF
75
76 user_assoc_data = dict(art=c.art, user=target_user, type=rel)
77 if add:
78 find_or_create(ArtUser, **user_assoc_data)
79
80 else:
81 # XXX this will die for nonassociations
82 user_assoc = ArtUser.get_by(art=c.art, **user_assoc_data)
83 user_assoc.delete()
84
85 else:
86 # Regular tag
87 if add:
88 tag = find_or_create(TagText, text=tag_text)
89 find_or_create(Tag, art=c.art, tagger=c.user, tagtext=tag)
90
91 else:
92 tag = TagText.get_by(text=tag_text)
93 if tag:
94 # XXX this will die
95 tag_assoc = Tag.get_by(art=c.art, tagger=c.user, tagtext=tag)
96 tag_assoc.delete()
97
98 elixir.session.commit()
99 redirect(url('show_art', id=c.art.id))