Fixes #3405: no annotations in pictures.
[wolnelektury.git] / apps / catalogue / templatetags / catalogue_tags.py
index cf80beb..f9c69ea 100644 (file)
@@ -2,18 +2,21 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-import datetime
-import feedparser
+from random import randint
+from urlparse import urlparse
 
 
+from django.conf import settings
 from django import template
 from django.template import Node, Variable, Template, Context
 from django.core.urlresolvers import reverse
 from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
 from django import template
 from django.template import Node, Variable, Template, Context
 from django.core.urlresolvers import reverse
 from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
+from django.utils.cache import add_never_cache_headers
 from django.utils.translation import ugettext as _
 
 from django.utils.translation import ugettext as _
 
-from catalogue import forms
-from catalogue.utils import split_tags
-from catalogue.models import Book, Fragment, Tag
+from ssify import ssi_variable
+from catalogue.models import Book, BookMedia, Fragment, Tag, Source
+from catalogue.constants import LICENSES
+from picture.models import Picture
 
 register = template.Library()
 
 
 register = template.Library()
 
@@ -52,7 +55,6 @@ def html_title_from_tags(tags):
     template = Template("{{ category }}: <a href='{{ tag.get_absolute_url }}'>{{ tag.name }}</a>")
     return capfirst(",<br/>".join(
         template.render(Context({'tag': tag, 'category': _(tag.category)})) for tag in tags))
     template = Template("{{ category }}: <a href='{{ tag.get_absolute_url }}'>{{ tag.name }}</a>")
     return capfirst(",<br/>".join(
         template.render(Context({'tag': tag, 'category': _(tag.category)})) for tag in tags))
-    
 
 
 def simple_title(tags):
 
 
 def simple_title(tags):
@@ -147,6 +149,17 @@ def book_tree(book_list, books_by_parent):
     else:
         return ''
 
     else:
         return ''
 
+@register.simple_tag
+def audiobook_tree(book_list, books_by_parent):
+    text = "".join("<li><a class='open-player' href='%s'>%s</a>%s</li>" % (
+        reverse("book_player", args=[book.slug]), book.title, audiobook_tree(books_by_parent.get(book, ()), books_by_parent)
+        ) for book in book_list)
+
+    if text:
+        return "<ol>%s</ol>" % text
+    else:
+        return ''
+
 @register.simple_tag
 def book_tree_texml(book_list, books_by_parent, depth=1):
     return "".join("""
 @register.simple_tag
 def book_tree_texml(book_list, books_by_parent, depth=1):
     return "".join("""
@@ -157,13 +170,36 @@ def book_tree_texml(book_list, books_by_parent, depth=1):
             %(children)s
             """ % {
                 "depth": depth,
             %(children)s
             """ % {
                 "depth": depth,
-                "title": book.title, 
+                "title": book.title,
                 "audiences": ", ".join(book.audiences_pl()),
                 "audiobook": "audiobook" if book.has_media('mp3') else "",
                 "children": book_tree_texml(books_by_parent.get(book.id, ()), books_by_parent, depth + 1)
             } for book in book_list)
 
 
                 "audiences": ", ".join(book.audiences_pl()),
                 "audiobook": "audiobook" if book.has_media('mp3') else "",
                 "children": book_tree_texml(books_by_parent.get(book.id, ()), books_by_parent, depth + 1)
             } for book in book_list)
 
 
+@register.simple_tag
+def book_tree_csv(author, book_list, books_by_parent, depth=1, max_depth=3, delimeter="\t"):
+    def quote_if_necessary(s):
+        try:
+            s.index(delimeter)
+            s.replace('"', '\\"')
+            return '"%s"' % s
+        except ValueError:
+            return s
+
+    return "".join("""%(author)s%(d)s%(preindent)s%(title)s%(d)s%(postindent)s%(audiences)s%(d)s%(audiobook)s
+%(children)s""" % {
+                "d": delimeter,
+                "preindent": delimeter * (depth - 1),
+                "postindent": delimeter * (max_depth - depth),
+                "depth": depth,
+                "author": quote_if_necessary(author.name),
+                "title": quote_if_necessary(book.title),
+                "audiences": ", ".join(book.audiences_pl()),
+                "audiobook": "audiobook" if book.has_media('mp3') else "",
+                "children": book_tree_csv(author, books_by_parent.get(book.id, ()), books_by_parent, depth + 1)
+            } for book in book_list)
+
 @register.simple_tag
 def all_editors(extra_info):
     editors = []
 @register.simple_tag
 def all_editors(extra_info):
     editors = []
@@ -194,7 +230,6 @@ def authentication_form():
 @register.tag
 def catalogue_url(parser, token):
     bits = token.split_contents()
 @register.tag
 def catalogue_url(parser, token):
     bits = token.split_contents()
-    tag_name = bits[0]
 
     tags_to_add = []
     tags_to_remove = []
 
     tags_to_add = []
     tags_to_remove = []
@@ -243,135 +278,144 @@ class CatalogueURLNode(Node):
             return reverse('main_page')
 
 
             return reverse('main_page')
 
 
-@register.inclusion_tag('catalogue/latest_blog_posts.html')
-def latest_blog_posts(feed_url, posts_to_show=5):
-    try:
-        feed = feedparser.parse(str(feed_url))
-        posts = []
-        for i in range(posts_to_show):
-            pub_date = feed['entries'][i].updated_parsed
-            published = datetime.date(pub_date[0], pub_date[1], pub_date[2] )
-            posts.append({
-                'title': feed['entries'][i].title,
-                'summary': feed['entries'][i].summary,
-                'link': feed['entries'][i].link,
-                'date': published,
-                })
-        return {'posts': posts}
-    except:
-        return {'posts': []}
-
-
 @register.inclusion_tag('catalogue/tag_list.html')
 def tag_list(tags, choices=None):
     if choices is None:
         choices = []
 @register.inclusion_tag('catalogue/tag_list.html')
 def tag_list(tags, choices=None):
     if choices is None:
         choices = []
-    if len(tags) == 1:
+    if len(tags) == 1 and tags[0].category not in [t.category for t in choices]:
         one_tag = tags[0]
     return locals()
 
         one_tag = tags[0]
     return locals()
 
+
 @register.inclusion_tag('catalogue/inline_tag_list.html')
 def inline_tag_list(tags, choices=None):
 @register.inclusion_tag('catalogue/inline_tag_list.html')
 def inline_tag_list(tags, choices=None):
-    if choices is None:
-        choices = []
-    if len(tags) == 1:
-        one_tag = tags[0]
-    return locals()
+    return tag_list(tags, choices)
 
 
 
 
-@register.inclusion_tag('catalogue/book_info.html')
-def book_info(book):
+@register.inclusion_tag('catalogue/collection_list.html')
+def collection_list(collections):
     return locals()
 
 
     return locals()
 
 
-@register.inclusion_tag('catalogue/book_wide.html', takes_context=True)
-def book_wide(context, book):
-    theme_counter = book.theme_counter
-    book_themes = Tag.objects.filter(pk__in=theme_counter.keys())
-    for tag in book_themes:
-        tag.count = theme_counter[tag.pk]
-    extra_info = book.get_extra_info_value()
-    hide_about = extra_info.get('about', '').startswith('http://wiki.wolnepodreczniki.pl')
-
+@register.inclusion_tag('catalogue/book_info.html')
+def book_info(book):
     return {
     return {
+        'is_picture': isinstance(book, Picture),
         'book': book,
         'book': book,
-        'main_link': reverse('book_text', args=[book.slug]),
-        'related': book.related_info(),
-        'extra_info': book.get_extra_info_value(),
-        'hide_about': hide_about,
-        'themes': book_themes,
-        'custom_pdf_form': forms.CustomPDFForm(),
-        'request': context.get('request'),
     }
 
 
     }
 
 
-@register.inclusion_tag('catalogue/book_short.html', takes_context=True)
-def book_short(context, book):
-    return {
-        'book': book,
-        'main_link': book.get_absolute_url(),
-        'related': book.related_info(),
-        'request': context.get('request'),
-    }
+@register.inclusion_tag('catalogue/work-list.html', takes_context=True)
+def work_list(context, object_list):
+    request = context.get('request')
+    return locals()
 
 
 
 
-@register.inclusion_tag('catalogue/book_mini_box.html')
-def book_mini(book):
+@register.inclusion_tag('catalogue/related_books.html', takes_context=True)
+def related_books(context, book, limit=6, random=1, taken=0):
+    limit = limit - taken
+    related = Book.tagged.related_to(book,
+            Book.objects.exclude(common_slug=book.common_slug)
+            ).exclude(ancestor=book)[:limit-random]
+    random_excluded = [b.pk for b in related] + [book.pk]
     return {
     return {
-        'book': book,
-        'related': book.related_info(),
+        'request': context['request'],
+        'books': related,
+        'random': random,
+        'random_excluded': random_excluded,
     }
 
 
     }
 
 
-@register.inclusion_tag('catalogue/work-list.html', takes_context=True)
-def work_list(context, object_list):
-    request = context.get('request')
-    if object_list:
-        object_type = type(object_list[0]).__name__
-    return locals()
-
+@register.inclusion_tag('catalogue/menu.html')
+def catalogue_menu():
+    return {'categories': [
+                ('author', _('Authors'), 'autorzy'),
+                ('genre', _('Genres'), 'gatunki'),
+                ('kind', _('Kinds'), 'rodzaje'),
+                ('epoch', _('Epochs'), 'epoki'),
+                ('theme', _('Themes'), 'motywy'),
+        ]}
 
 
-@register.inclusion_tag('catalogue/fragment_promo.html')
-def fragment_promo(arg=None):
-    if arg is None:
-        fragments = Fragment.objects.all().order_by('?')
-        fragment = fragments[0] if fragments.exists() else None
-    elif isinstance(arg, Book):
-        fragment = arg.choose_fragment()
-    else:
-        fragments = Fragment.tagged.with_all(arg).order_by('?')
-        fragment = fragments[0] if fragments.exists() else None
 
 
+@register.simple_tag
+def download_audio(book, daisy=True):
+    links = []
+    if book.has_media('mp3'):
+        links.append("<a href='%s'>%s</a>" %
+            (reverse('download_zip_mp3', args=[book.slug]),
+                BookMedia.formats['mp3'].name))
+    if book.has_media('ogg'):
+        links.append("<a href='%s'>%s</a>" %
+            (reverse('download_zip_ogg', args=[book.slug]),
+                BookMedia.formats['ogg'].name))
+    if daisy and book.has_media('daisy'):
+        for dsy in book.get_media('daisy'):
+            links.append("<a href='%s'>%s</a>" %
+                (dsy.file.url, BookMedia.formats['daisy'].name))
+    return ", ".join(links)
+
+
+@register.inclusion_tag("catalogue/snippets/custom_pdf_link_li.html")
+def custom_pdf_link_li(book):
     return {
     return {
-        'fragment': fragment,
+        'book': book,
+        'NO_CUSTOM_PDF': settings.NO_CUSTOM_PDF,
     }
 
 
     }
 
 
-@register.inclusion_tag('catalogue/related_books.html')
-def related_books(book, limit=6):
-    related = list(Book.objects.filter(
-        common_slug=book.common_slug).exclude(pk=book.pk)[:limit])
-    limit -= len(related)
-    if limit:
-        related += Book.tagged.related_to(book,
-                Book.objects.exclude(common_slug=book.common_slug),
-                ignore_by_tag=book.book_tag())[:limit]
+@register.inclusion_tag("catalogue/snippets/license_icon.html")
+def license_icon(license_url):
+    """Creates a license icon, if the license_url is known."""
+    known = LICENSES.get(license_url)
+    if known is None:
+        return {}
     return {
     return {
-        'books': related,
+        "license_url": license_url,
+        "icon": "img/licenses/%s.png" % known['icon'],
+        "license_description": known['description'],
     }
 
 
     }
 
 
-@register.inclusion_tag('catalogue/menu.html')
-def catalogue_menu():
-    tags = Tag.objects.filter(
-            category__in=('author', 'epoch', 'genre', 'kind', 'theme')
-        ).exclude(book_count=0)
-    return split_tags(tags)
-    
+@register.filter
+def class_name(obj):
+    return obj.__class__.__name__
 
 
 @register.simple_tag
 
 
 @register.simple_tag
-def tag_url(category, slug):
-    return reverse('catalogue.views.tagged_object_list', args=[
-        '/'.join((Tag.categories_dict[category], slug))
-    ])
+def source_name(url):
+    url = url.lstrip()
+    netloc = urlparse(url).netloc
+    if not netloc:
+        netloc = urlparse('http://' + url).netloc
+    if not netloc:
+        return ''
+    source, created = Source.objects.get_or_create(netloc=netloc)
+    return source.name or netloc
+
+
+@ssi_variable(register, patch_response=[add_never_cache_headers])
+def catalogue_random_book(request, exclude_ids):
+    queryset = Book.objects.exclude(pk__in=exclude_ids)
+    count = queryset.count()
+    if count:
+        return queryset[randint(0, count - 1)].pk
+    else:
+        return None
+
+
+@ssi_variable(register, patch_response=[add_never_cache_headers])
+def choose_fragment(request, book_id=None, tag_ids=None, unless=False):
+    if unless:
+        return None
+
+    if book_id is not None:
+        fragment = Book.objects.get(pk=book_id).choose_fragment()
+    else:
+        if tag_ids is not None:
+            tags = Tag.objects.filter(pk__in=tag_ids)
+            fragments = Fragment.tagged.with_all(tags).order_by().only('id')
+        else:
+            fragments = Fragment.objects.all().order_by().only('id')
+        fragment_count = fragments.count()
+        fragment = fragments[randint(0, fragment_count - 1)] if fragment_count else None
+    return fragment.pk if fragment is not None else None