Ignore:
Timestamp:
22 Nov 2014, 10:14:38 (10 years ago)
Author:
Henrik Bettermann
Message:

Add document file viewlets. Tests will follow.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.ikoba/trunk/src/waeup/ikoba/customers/documents.py

    r12018 r12035  
    1919Customer document components.
    2020"""
     21import os
    2122import grok
    2223from zope.component import queryUtility, getUtility
    2324from zope.component.interfaces import IFactory
    2425from zope.interface import implementedBy
     26
     27from waeup.ikoba.image import IkobaImageFile
     28from waeup.ikoba.imagestorage import DefaultFileStoreHandler
    2529from waeup.ikoba.interfaces import MessageFactory as _
     30from waeup.ikoba.interfaces import (
     31    IFileStoreNameChooser, IFileStoreHandler,
     32    IIkobaUtils, IExtFileStore)
    2633from waeup.ikoba.customers.interfaces import (
    2734    ICustomerDocumentsContainer, ICustomerNavigation, ICustomerDocument,
     
    3037from waeup.ikoba.documents.interfaces import IDocumentsUtils
    3138from waeup.ikoba.utils.helpers import attrs_to_fields
     39
     40from waeup.ikoba.customers.utils import path_from_custid
    3241
    3342class CustomerDocumentsContainer(DocumentsContainer):
     
    102111    def getInterfaces(self):
    103112        return implementedBy(CustomerDocument)
     113
     114#: The file id marker for customer files
     115CUSTOMERDOCUMENT_FILE_STORE_NAME = 'file-customerdocument'
     116
     117
     118class CustomerDocumentFileNameChooser(grok.Adapter):
     119    """A file id chooser for :class:`CustomerDocument` objects.
     120
     121    `context` is an :class:`CustomerDocument` instance.
     122
     123    The :class:`CustomerDocumentFileNameChooser` can build/check file ids for
     124    :class:`Customer` objects suitable for use with
     125    :class:`ExtFileStore` instances. The delivered file_id contains
     126    the file id marker for :class:`CustomerDocument` object and the customer id
     127    of the context customer.
     128
     129    This chooser is registered as an adapter providing
     130    :class:`waeup.ikoba.interfaces.IFileStoreNameChooser`.
     131
     132    File store name choosers like this one are only convenience
     133    components to ease the task of creating file ids for customer document
     134    objects. You are nevertheless encouraged to use them instead of
     135    manually setting up filenames for customer documents.
     136
     137    .. seealso:: :mod:`waeup.ikoba.imagestorage`
     138
     139    """
     140
     141    grok.context(ICustomerDocument)
     142    grok.implements(IFileStoreNameChooser)
     143
     144    def checkName(self, name=None, attr=None):
     145        """Check whether the given name is a valid file id for the context.
     146
     147        Returns ``True`` only if `name` equals the result of
     148        :meth:`chooseName`.
     149
     150        """
     151        return name == self.chooseName()
     152
     153    def chooseName(self, attr, name=None):
     154        """Get a valid file id for customer document context.
     155
     156        *Example:*
     157
     158        For a customer with customer id ``'A123456'``
     159        and document with id 'd123'
     160        with attr ``'nice_image.jpeg'`` stored in
     161        the customers container this chooser would create:
     162
     163          ``'__file-customerdocument__customers/A/A123456/nice_image_d123_A123456.jpeg'``
     164
     165        meaning that the nice image of this customer document would be
     166        stored in the site-wide file storage in path:
     167
     168          ``customers/A/A123456/nice_image_d123_A123456.jpeg``
     169
     170        """
     171        basename, ext = os.path.splitext(attr)
     172        cust_id = self.context.customer.customer_id
     173        doc_id = self.context.document_id
     174        marked_filename = '__%s__%s/%s_%s_%s%s' % (
     175            CUSTOMERDOCUMENT_FILE_STORE_NAME, path_from_custid(cust_id),
     176            basename, doc_id, cust_id, ext)
     177        return marked_filename
     178
     179
     180class CustomerDocumentFileStoreHandler(DefaultFileStoreHandler, grok.GlobalUtility):
     181    """Customer document specific file handling.
     182
     183    This handler knows in which path in a filestore to store customer document
     184    files and how to turn this kind of data into some (browsable)
     185    file object.
     186
     187    It is called from the global file storage, when it wants to
     188    get/store a file with a file id starting with
     189    ``__file-customerdocument__`` (the marker string for customer files).
     190
     191    Like each other file store handler it does not handle the files
     192    really (this is done by the global file store) but only computes
     193    paths and things like this.
     194    """
     195    grok.implements(IFileStoreHandler)
     196    grok.name(CUSTOMERDOCUMENT_FILE_STORE_NAME)
     197
     198    def pathFromFileID(self, store, root, file_id):
     199        """All customer document files are put in directory ``customers``.
     200        """
     201        marker, filename, basename, ext = store.extractMarker(file_id)
     202        sub_root = os.path.join(root, 'customers')
     203        return super(CustomerDocumentFileStoreHandler, self).pathFromFileID(
     204            store, sub_root, basename)
     205
     206    def createFile(self, store, root, filename, file_id, file):
     207        """Create a browsable file-like object.
     208        """
     209        # call super method to ensure that any old files with
     210        # different filename extension are deleted.
     211        file, path, file_obj = super(
     212            CustomerDocumentFileStoreHandler, self).createFile(
     213            store, root,  filename, file_id, file)
     214        return file, path, IkobaImageFile(
     215            file_obj.filename, file_obj.data)
     216
Note: See TracChangeset for help on using the changeset viewer.