Source code for cubicweb_web.views.idownloadable

# copyright 2003-2024 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact https://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
#
# CubicWeb is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 2.1 of the License, or (at your option)
# any later version.
#
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with CubicWeb.  If not, see <https://www.gnu.org/licenses/>.
"""
Specific views for entities adapting to IDownloadable
=====================================================
"""

from logilab.mtconverter import BINARY_ENCODINGS, xml_escape

from cubicweb import _
from cubicweb import tags
from cubicweb.mttransforms import ENGINE
from cubicweb.predicates import (
    one_line_rset,
    adaptable,
    has_mimetype,
)
from cubicweb_web.view import EntityView
from cubicweb_web import component, httpcache
from cubicweb_web.views import primary, baseviews


[docs]class DownloadBox(component.EntityCtxComponent): """add download box""" __regid__ = "download_box" # no download box for images __select__ = ( component.EntityCtxComponent.__select__ & adaptable("IDownloadable") & ~has_mimetype("image/") ) order = 10 title = _("download") def init_rendering(self): self.items = [self.entity] def render_body(self, w): for item in self.items: idownloadable = item.cw_adapt_to("IDownloadable") w( '<a href="%s"><img src="%s" alt="%s"/> %s</a>', idownloadable.download_url(), self._cw.uiprops["DOWNLOAD_ICON"], self._cw._("download icon"), idownloadable.download_file_name(), )
[docs]class DownloadView(EntityView): """download view this view is replacing the deprecated 'download' controller and allow downloading of entities providing the necessary interface """ __regid__ = "download" __select__ = one_line_rset() & adaptable("IDownloadable") templatable = False content_type = "application/octet-stream" binary = True http_cache_manager = httpcache.EntityHTTPCacheManager add_to_breadcrumbs = False def set_request_content_type(self): """overriden to set the correct filetype and filename""" entity = self.cw_rset.complete_entity(self.cw_row or 0, self.cw_col or 0) adapter = entity.cw_adapt_to("IDownloadable") encoding = adapter.download_encoding() if encoding in BINARY_ENCODINGS: contenttype = "application/%s" % encoding encoding = None else: contenttype = adapter.download_content_type() self._cw.set_content_type( contenttype or self.content_type, filename=adapter.download_file_name(), encoding=encoding, disposition="attachment", ) def call(self): entity = self.cw_rset.complete_entity(self.cw_row or 0, self.cw_col or 0) adapter = entity.cw_adapt_to("IDownloadable") self.w(adapter.download_data()) def last_modified(self): return self.cw_rset.get_entity( self.cw_row or 0, self.cw_col or 0 ).modification_date
[docs]class DownloadLinkView(EntityView): """view displaying a link to download the file""" __regid__ = "downloadlink" __select__ = adaptable("IDownloadable") title = None # should not be listed in possible views def cell_call(self, row, col, title=None, **kwargs): entity = self.cw_rset.get_entity(row, col) url = entity.cw_adapt_to("IDownloadable").download_url() self.w('<a href="%s">%s</a>', url, title or entity.dc_title())
[docs]class IDownloadablePrimaryView(primary.PrimaryView): __select__ = adaptable("IDownloadable") def render_entity_attributes(self, entity): self.w('<div class="content">') adapter = entity.cw_adapt_to("IDownloadable") contenttype = adapter.download_content_type() if contenttype.startswith("image/"): self._cw.add_js("cubicweb.image.js") self.wview( "image", entity.cw_rset, row=entity.cw_row, col=entity.cw_col, link=True, klass="contentimage", ) super(IDownloadablePrimaryView, self).render_entity_attributes(entity) elif contenttype.endswith("html"): self.wview( "downloadlink", entity.cw_rset, title=self._cw._("download"), row=entity.cw_row, ) self.wview( "ehtml", entity.cw_rset, row=entity.cw_row, col=entity.cw_col, height="600px", width="100%", ) else: super(IDownloadablePrimaryView, self).render_entity_attributes(entity) self.wview( "downloadlink", entity.cw_rset, title=self._cw._("download"), row=entity.cw_row, ) self.render_data(entity, contenttype, "text/html") self.w("</div>") def render_data(self, entity, sourcemt, targetmt): adapter = entity.cw_adapt_to("IDownloadable") if ENGINE.find_path(sourcemt, targetmt): try: self.w( entity._cw_mtc_transform( adapter.download_data(), sourcemt, targetmt, adapter.download_encoding(), ) ) except Exception as ex: self.exception("while rendering data for %s", entity) msg = self._cw._( "can't display data, unexpected error: %s" ) % xml_escape(str(ex)) self.w('<div class="error">%s</div>', msg) return True return False
[docs]class IDownloadableOneLineView(baseviews.OneLineView): __select__ = adaptable("IDownloadable") def cell_call(self, row, col, title=None, **kwargs): """the oneline view is a link to download the file""" entity = self.cw_rset.get_entity(row, col) url = entity.absolute_url() adapter = entity.cw_adapt_to("IDownloadable") name = title or entity.dc_title() durl = adapter.download_url() self.w( '<a href="%s">%s</a> [<a href="%s">%s</a>]', url, name, durl, self._cw._("download"), )
class AbstractEmbeddedView(EntityView): __abstract__ = True _embedding_tag = None def call(self, **kwargs): rset = self.cw_rset for i in range(len(rset)): self.w('<div class="efile">') self.wview(self.__regid__, rset, row=i, col=0, **kwargs) self.w("</div>") def cell_call(self, row, col, link=False, **kwargs): entity = self.cw_rset.get_entity(row, col) adapter = entity.cw_adapt_to("IDownloadable") tag = self._embedding_tag( src=adapter.download_url(), # pylint: disable=E1102 alt=(self._cw._("download %s") % adapter.download_file_name()), **kwargs, ) if link: self.w('<a href="%s">%s</a>', adapter.download_url(), tag, escape=False) else: self.w(tag)
[docs]class ImageView(AbstractEmbeddedView): """image embedded view""" __regid__ = "image" __select__ = has_mimetype("image/") title = _("image") _embedding_tag = tags.img
[docs]class EHTMLView(AbstractEmbeddedView): """html embedded view""" __regid__ = "ehtml" __select__ = has_mimetype("text/html") title = _("embedded html") _embedding_tag = tags.iframe