Simplify/Robustify the thumbnail URL usage in templates
[mediagoblin.git] / mediagoblin / db / mixin.py
index b0fecad3f31a41009df13f50778e19e1d6059932..22375b7f07ee43f9388624567fbdca7e2e454fbf 100644 (file)
@@ -1,5 +1,5 @@
 # GNU MediaGoblin -- federated, autonomous media hosting
-# Copyright (C) 2011,2012 MediaGoblin contributors.  See AUTHORS.
+# Copyright (C) 2011, 2012 MediaGoblin contributors.  See AUTHORS.
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Affero General Public License as published by
@@ -27,8 +27,13 @@ These functions now live here and get "mixed in" into the
 real objects.
 """
 
+import importlib
+
+from mediagoblin import mg_globals
 from mediagoblin.auth import lib as auth_lib
 from mediagoblin.tools import common, licenses
+from mediagoblin.tools.text import cleaned_markdown_conversion
+from mediagoblin.tools.url import slugify
 
 
 class UserMixin(object):
@@ -39,8 +44,36 @@ class UserMixin(object):
         return auth_lib.bcrypt_check_password(
             password, self.pw_hash)
 
+    @property
+    def bio_html(self):
+        return cleaned_markdown_conversion(self.bio)
+
 
 class MediaEntryMixin(object):
+    def generate_slug(self):
+        # import this here due to a cyclic import issue
+        # (db.models -> db.mixin -> db.util -> db.models)
+        from mediagoblin.db.util import check_media_slug_used
+
+        self.slug = slugify(self.title)
+
+        duplicate = check_media_slug_used(mg_globals.database,
+            self.uploader, self.slug, self.id)
+
+        if duplicate:
+            if self.id is not None:
+                self.slug = u"%s-%s" % (self.id, self.slug)
+            else:
+                self.slug = None
+
+    @property
+    def description_html(self):
+        """
+        Rendered version of the description, run through
+        Markdown and cleaned with our cleaning tool.
+        """
+        return cleaned_markdown_conversion(self.description)
+
     def get_display_media(self, media_map,
                           fetch_order=common.DISPLAY_IMAGE_FETCHING_ORDER):
         """
@@ -63,6 +96,10 @@ class MediaEntryMixin(object):
     def main_mediafile(self):
         pass
 
+    @property
+    def slug_or_id(self):
+        return (self.slug or self._id)
+
     def url_for_self(self, urlgen, **extra_args):
         """
         Generate an appropriate url for ourselves
@@ -71,26 +108,111 @@ class MediaEntryMixin(object):
         """
         uploader = self.get_uploader
 
-        if self.get('slug'):
-            return urlgen(
-                'mediagoblin.user_pages.media_home',
-                user=uploader.username,
-                media=self.slug,
-                **extra_args)
+        return urlgen(
+            'mediagoblin.user_pages.media_home',
+            user=uploader.username,
+            media=self.slug_or_id,
+            **extra_args)
+
+    @property
+    def thumb_url(self):
+        """Return the thumbnail URL (for usage in templates)
+        Will return either the real thumbnail or a default fallback icon."""
+        # TODO: implement generic fallback in case MEDIA_MANAGER does
+        # not specify one?
+        if u'thumb' in self.media_files:
+            thumb_url = mg_globals.app.public_store.file_url(
+                            self.media_files[u'thumb'])
         else:
-            return urlgen(
-                'mediagoblin.user_pages.media_home',
-                user=uploader.username,
-                media=unicode(self._id),
-                **extra_args)
+            # no thumbnail in media available. Get the media's
+            # MEDIA_MANAGER for the fallback icon and return static URL
+            manager = importlib.import_module(self.media_type)
+            thumb_url = manager.MEDIA_MANAGER[u'default_thumb']
+            thumb_url = mg_globals.app.staticdirector(thumb_url) # use static
+        return thumb_url
 
     def get_fail_exception(self):
         """
         Get the exception that's appropriate for this error
         """
-        if self['fail_error']:
-            return common.import_component(self['fail_error'])
+        if self.fail_error:
+            return common.import_component(self.fail_error)
 
     def get_license_data(self):
         """Return license dict for requested license"""
-        return licenses.SUPPORTED_LICENSES[self.license]
+        return licenses.SUPPORTED_LICENSES[self.license or ""]
+
+    def exif_display_iter(self):
+        from mediagoblin.tools.exif import USEFUL_TAGS
+
+        if not self.media_data:
+            return
+        exif_all = self.media_data.get("exif_all")
+
+        for key in USEFUL_TAGS:
+            if key in exif_all:
+                yield key, exif_all[key]
+
+
+class MediaCommentMixin(object):
+    @property
+    def content_html(self):
+        """
+        the actual html-rendered version of the comment displayed.
+        Run through Markdown and the HTML cleaner.
+        """
+        return cleaned_markdown_conversion(self.content)
+
+
+class CollectionMixin(object):
+    def generate_slug(self):
+        # import this here due to a cyclic import issue
+        # (db.models -> db.mixin -> db.util -> db.models)
+        from mediagoblin.db.util import check_collection_slug_used
+
+        self.slug = slugify(self.title)
+
+        duplicate = check_collection_slug_used(mg_globals.database,
+            self.creator, self.slug, self.id)
+
+        if duplicate:
+            if self.id is not None:
+                self.slug = u"%s-%s" % (self.id, self.slug)
+            else:
+                self.slug = None
+
+    @property
+    def description_html(self):
+        """
+        Rendered version of the description, run through
+        Markdown and cleaned with our cleaning tool.
+        """
+        return cleaned_markdown_conversion(self.description)
+
+    @property
+    def slug_or_id(self):
+        return (self.slug or self._id)
+
+    def url_for_self(self, urlgen, **extra_args):
+        """
+        Generate an appropriate url for ourselves
+
+        Use a slug if we have one, else use our '_id'.
+        """
+        creator = self.get_creator
+
+        return urlgen(
+            'mediagoblin.user_pages.user_collection',
+            user=creator.username,
+            collection=self.slug_or_id,
+            **extra_args)
+
+
+class CollectionItemMixin(object):
+    @property
+    def note_html(self):
+        """
+        the actual html-rendered version of the note displayed.
+        Run through Markdown and the HTML cleaner.
+        """
+        return cleaned_markdown_conversion(self.note)