add question
[edumed.git] / catalogue / publish.py
index f79a809..293b89e 100755 (executable)
@@ -1,12 +1,59 @@
 # -*- coding: utf-8
 # -*- coding: utf-8
-from django.core.files.base import ContentFile
 from django.core.files import File
 from django.core.files import File
+from django.core.urlresolvers import reverse
 from librarian import DocProvider, IOFile
 from librarian.pyhtml import EduModuleFormat
 from librarian import DocProvider, IOFile
 from librarian.pyhtml import EduModuleFormat
+from librarian.pypdf import EduModulePDFFormat
+from librarian.pdf_from_html import EduModulePdfFromHtmlFormat
 from .models import Lesson, Attachment
 from .models import Lesson, Attachment
+from fnpdjango.utils.text.slughifi import slughifi
+
+
+# TODO: Using sorl.thumbnail for now,
+# but this should be done in Librarian,
+# directly using convert or PIL as a fallback.
+def get_image(src_img_path, width=None, default_width=1600, formats=('PNG', 'JPEG', 'GIF')):
+    """ Returns an object with `url` and `storage` attributes,
+        or None if using the original image is OK.
+    """
+
+    from PIL import Image
+    from sorl.thumbnail import get_thumbnail
+
+    # Does it need converting?
+    # Yes, if width is given explicitly.
+    convert = width is not None
+    if not convert:
+        # Looks like it doesn't need converting.
+        # But let's try opening it and checking its type.
+        try:
+            simg = Image.open(src_img_path)
+        except IOError:
+            # It doesn't look like image,
+            # but maybe it's convertable to one.
+            convert = True
+        else:
+            if simg.format not in formats:
+                # It's an image, but it's in some weird format.
+                convert = True
+                width = simg.size[0]
+
+    if convert:
+        if width is None:
+            width = default_width
+        try:
+            return get_thumbnail(src_img_path, '%sx%s' % (width, 10*width))
+        except:
+            # hard to predict what solr raises on invalid image
+            return None
+    else:
+        return None
 
 
 class HtmlFormat(EduModuleFormat):
 
 
 class HtmlFormat(EduModuleFormat):
+    IMAGE_FORMATS = ('PNG', 'JPEG', 'GIF')
+    DEFAULT_IMAGE_WIDTH = 1600
+
     def find_attachment(self, slug, fmt):
         lesson_slug = self.wldoc.book_info.url.slug
         try:
     def find_attachment(self, slug, fmt):
         lesson_slug = self.wldoc.book_info.url.slug
         try:
@@ -33,32 +80,92 @@ class HtmlFormat(EduModuleFormat):
         return self.find_attachment(slug, fmt).file.url
 
     def url_for_image(self, slug, fmt, width=None):
         return self.find_attachment(slug, fmt).file.url
 
     def url_for_image(self, slug, fmt, width=None):
-        if width is None:
-            return self.url_for_material(slug, fmt)
+        try:
+            src_img = self.find_attachment(slug, fmt).file
+        except self.MaterialNotFound:
+            return ''
+        img = get_image(src_img.path, width, self.DEFAULT_IMAGE_WIDTH, self.IMAGE_FORMATS)
+        return (img or src_img).url
 
 
+    def text_to_anchor(self, text):
+        return slughifi(text)
+
+    def get_forma_url(self, forma):
+        return '%s#%s' % (
+            reverse('catalogue_lesson', args=['metody']),
+            self.text_to_anchor(forma)
+        )
+
+    def get_help_url(self, naglowek):
+        return '%s%s#%s' % (
+            '//edukacjamedialna.edu.pl',
+            reverse('info', args=['jak-korzystac/']),
+            self.naglowek_to_anchor(naglowek)
+        )
+
+
+class PdfFormat(EduModulePDFFormat):
+    IMAGE_FORMATS = ('PNG', 'JPEG', 'GIF')
+    DEFAULT_IMAGE_WIDTH = 1600
+
+    def get_image(self, name):
+        src_img = super(PdfFormat, self).get_image(name)
+        img = get_image(
+            src_img.get_filename(),
+            default_width=self.DEFAULT_IMAGE_WIDTH,
+            formats=self.IMAGE_FORMATS)
+        if img:
+            return IOFile.from_filename(img.storage.path(img))
+        else:
+            return src_img
+
+
+class PdfFromHtmlFormat(EduModulePdfFromHtmlFormat):
+    IMAGE_FORMATS = ('PNG', 'JPEG', 'GIF')
+    DEFAULT_IMAGE_WIDTH = 1600
+
+    def find_attachment(self, slug, fmt):
         lesson_slug = self.wldoc.book_info.url.slug
         lesson_slug = self.wldoc.book_info.url.slug
-        th_slug = "thumb/%s__th%d" % (slug, width)
         try:
             # If already saved, use it.
             att = Attachment.objects.get(lesson__slug=lesson_slug,
         try:
             # If already saved, use it.
             att = Attachment.objects.get(lesson__slug=lesson_slug,
-                                         slug=th_slug, ext=fmt)
+                                         slug=slug, ext=fmt)
         except Attachment.DoesNotExist, e:
         except Attachment.DoesNotExist, e:
-            from PIL import Image
-            from StringIO import StringIO
-            # Find full image, create thumbnail, save.
-            src_att = self.find_attachment(slug, fmt)
-            simg = Image.open(src_att.file.path)
-            size = (width, simg.size[1]*width/simg.size[0])
-            simg = simg.resize(size, Image.ANTIALIAS)
-
-            tempfile = StringIO()
-            img_format = "JPEG" if fmt.upper() == "JPG" else fmt
-            simg.save(tempfile, format=img_format)
-            att_name = "%s.%s" % (th_slug, fmt)
-            lesson = Lesson.objects.get(slug=lesson_slug)
-            att = lesson.attachment_set.create(slug=th_slug, ext=fmt)
-            att.file.save(att_name, ContentFile(tempfile.getvalue()))
-        return att.file.url
+            # If attached to source IOFile, save now.
+            att_name = "%s.%s" % (slug, fmt)
+            try:
+                att_file = self.wldoc.source.attachments[att_name]
+            except KeyError:
+                print u"ATTACHMENT MISSING:", att_name
+                raise self.MaterialNotFound()
+            else:
+                lesson = Lesson.objects.get(slug=lesson_slug)
+                att = lesson.attachment_set.create(slug=slug, ext=fmt)
+                att.file.save(att_name, File(att_file.get_file()))
+                return att
+        else:
+            return att
+
+    def url_for_material(self, slug, fmt):
+        return self.find_attachment(slug, fmt).file.url
+
+    def image(self, slug, fmt, width=None):
+        try:
+            src_img = self.find_attachment(slug, fmt).file
+        except self.MaterialNotFound:
+            return None
+        img = get_image(src_img.path, width, self.DEFAULT_IMAGE_WIDTH, self.IMAGE_FORMATS)
+        return img or src_img
+
+    def url_for_image(self, slug, fmt, image=None, **kwargs):
+        img = image or self.image(slug, fmt, **kwargs)
+        if img:
+            return img.url
+        else:
+            return ''
+
+    def text_to_anchor(self, text):
+        return slughifi(text)
 
 
 class OrmDocProvider(DocProvider):
 
 
 class OrmDocProvider(DocProvider):