from pylons import url
from floof.lib.base import BaseController, render
-from floof.lib.search import parse
+from floof.lib.tags import parse
log = logging.getLogger(__name__)
import elixir
from floof.model import Art, ArtUser, ArtUserType, Tag, TagText, User
+from floof.lib import helpers as h
from floof.lib.base import BaseController, render
+from floof.lib.tags import add_tags
from floof.lib.dbhelpers import find_or_create
-from floof.lib import helpers as h
log = logging.getLogger(__name__)
c.art = h.get_object_or_404(Art, id=art_id)
tag_string = request.params.get('tags', '')
+ add_tags(c.art, tag_string, c.user)
# Add or remove tags
- bad_tags = []
- for tag_text in tag_string.split():
- original_tag_text = tag_text
- tag_text = tag_text.lower()
-
- # Adding or removing a tag?
- if tag_text[0] == '-':
- add = False
- tag_text = tag_text[1:]
- else:
- # Allow "+foo" to mean "add foo"
- if tag_text[0] == '+':
- tag_text = tag_text[1:]
- add = True
-
- # Check for special namespaces
- prefix = None
- if ':' in tag_text:
- prefix, tag_text = tag_text.split(':', 1)
- if prefix not in ['by', 'for', 'of']:
- # This is bogus. Skip it.
- bad_tags.append(original_tag_text)
- continue
-
- if prefix == 'by':
- # XXX this needs supporting. silently ignore for now
- continue
-
- # Must be 3-50 alphanumeric characters
- if not re.match('^[a-z0-9]{3,50}$', tag_text):
- bad_tags.append(original_tag_text)
- continue
-
- # Do work!
- if prefix:
- target_user = User.get_by(name=tag_text)
-
- # Special tag; at the moment, just a relationship
- if prefix == 'by':
- rel = ArtUserType.BY
- elif prefix == 'for':
- rel = ArtUserType.FOR
- elif prefix == 'of':
- rel = ArtUserType.OF
-
- user_assoc_data = dict(art=c.art, user=target_user, type=rel)
- if add:
- find_or_create(ArtUser, **user_assoc_data)
-
- else:
- # XXX this will die for nonassociations
- user_assoc = ArtUser.get_by(art=c.art, **user_assoc_data)
- user_assoc.delete()
-
- else:
- # Regular tag
- if add:
- tag = find_or_create(TagText, text=tag_text)
- find_or_create(Tag, art=c.art, tagger=c.user, tagtext=tag)
-
- else:
- tag = TagText.get_by(text=tag_text)
- if tag:
- # XXX this will die
- tag_assoc = Tag.get_by(art=c.art, tagger=c.user, tagtext=tag)
- tag_assoc.delete()
-
- elixir.session.commit()
redirect(url('show_art', id=c.art.id))
+++ /dev/null
-from floof.model import Art, ArtUser, ArtUserType, Tag, TagText, User
-
-def parse(search_string):
- """Parses a search query, and returns a query object on Art.
-
- Queries can contain:
- - Regular tags: foo
- - User relations: by:kalu, of:eevee, for:ootachi
-
- Later:
- - Negative versions of anything above: -by:eevee, -dongs
- """
-
- # XXX doesn't do negative querying yet.
- # XXX could use some sane limits.
-
- # We'll be building this as we go.
- q = Art.query
-
- terms = search_string.split()
- for tag in terms:
- if ':' in tag:
- # This is a special tag; at the moment, by/for/of to indicate
- # related users
- prefix, tag = tag.split(':', 1)
-
- # XXX what to do if this fails? abort? return empty query?
- target_user = User.get_by(name=tag)
-
- if prefix == 'by':
- rel = ArtUserType.BY
- elif prefix == 'for':
- rel = ArtUserType.FOR
- elif prefix == 'of':
- rel = ArtUserType.OF
- else:
- # Bogus tag. Not sure what to do here, so for the moment,
- # ignore it
- continue
-
- # Inner join to the ArtUser table
- q = q.join(ArtUser, aliased=True) \
- .filter(ArtUser.user == target_user) \
- .filter(ArtUser.type == rel)
-
- else:
- # Regular ol' tag
- q = q.join(Tag, TagText, aliased=True) \
- .filter(TagText.text == tag)
-
- return q
--- /dev/null
+from floof.model import Art, ArtUser, ArtUserType, Tag, TagText, User
+
+def parse(search_string):
+ """Parses a search query, and returns a query object on Art.
+
+ Queries can contain:
+ - Regular tags: foo
+ - User relations: by:kalu, of:eevee, for:ootachi
+
+ Later:
+ - Negative versions of anything above: -by:eevee, -dongs
+ """
+
+ # XXX doesn't do negative querying yet.
+ # XXX could use some sane limits.
+
+ # We'll be building this as we go.
+ q = Art.query
+
+ terms = search_string.split()
+ for tag in terms:
+ if ':' in tag:
+ # This is a special tag; at the moment, by/for/of to indicate
+ # related users
+ prefix, tag = tag.split(':', 1)
+
+ # XXX what to do if this fails? abort? return empty query?
+ target_user = User.get_by(name=tag)
+
+ if prefix == 'by':
+ rel = ArtUserType.BY
+ elif prefix == 'for':
+ rel = ArtUserType.FOR
+ elif prefix == 'of':
+ rel = ArtUserType.OF
+ else:
+ # Bogus tag. Not sure what to do here, so for the moment,
+ # ignore it
+ continue
+
+ # Inner join to the ArtUser table
+ q = q.join(ArtUser, aliased=True) \
+ .filter(ArtUser.user == target_user) \
+ .filter(ArtUser.type == rel)
+
+ else:
+ # Regular ol' tag
+ q = q.join(Tag, TagText, aliased=True) \
+ .filter(TagText.text == tag)
+
+ return q
+
+def add_tags(art, tag_string, user):
+ """Takes a string that looks like a tag query, and effectively modifies the
+ art's tags to match it.
+ """
+
+ # XXX what to do with invalid tags? just return them and let caller fix?
+ bad_tags = []
+ for tag_text in tag_string.split():
+ original_tag_text = tag_text
+ tag_text = tag_text.lower()
+
+ # Adding or removing a tag?
+ if tag_text[0] == '-':
+ add = False
+ tag_text = tag_text[1:]
+ else:
+ # Allow "+foo" to mean "add foo"
+ if tag_text[0] == '+':
+ tag_text = tag_text[1:]
+ add = True
+
+ # Check for special namespaces
+ prefix = None
+ if ':' in tag_text:
+ prefix, tag_text = tag_text.split(':', 1)
+ if prefix not in ['by', 'for', 'of']:
+ # This is bogus. Skip it.
+ bad_tags.append(original_tag_text)
+ continue
+
+ if prefix == 'by':
+ # XXX this needs supporting. silently ignore for now
+ continue
+
+ # Must be 3-50 alphanumeric characters
+ if not re.match('^[a-z0-9]{3,50}$', tag_text):
+ bad_tags.append(original_tag_text)
+ continue
+
+ # Do work!
+ if prefix:
+ target_user = User.get_by(name=tag_text)
+
+ # Special tag; at the moment, just a relationship
+ if prefix == 'by':
+ rel = ArtUserType.BY
+ elif prefix == 'for':
+ rel = ArtUserType.FOR
+ elif prefix == 'of':
+ rel = ArtUserType.OF
+
+ user_assoc_data = dict(art=art, user=target_user, type=rel)
+ if add:
+ find_or_create(ArtUser, **user_assoc_data)
+
+ else:
+ # XXX this will die for nonassociations
+ user_assoc = ArtUser.get_by(art=art, **user_assoc_data)
+ user_assoc.delete()
+
+ else:
+ # Regular tag
+ if add:
+ tag = find_or_create(TagText, text=tag_text)
+ find_or_create(Tag, art=art, tagger=user, tagtext=tag)
+
+ else:
+ tag = TagText.get_by(text=tag_text)
+ if tag:
+ # XXX this will die
+ tag_assoc = Tag.get_by(art=art, tagger=user, tagtext=tag)
+ tag_assoc.delete()
+
+ elixir.session.commit()
<%! from floof.lib.search import parse %>
% for gallery in c.this_user.primary_page.galleries:
<h2>${gallery.string}</h2>
-${macros.thumbs(parse(gallery.search.string))}
+${macros.thumbs(parse(gallery.tags.string))}
% endfor