diff -r a64f48dd5fe4 -r 9ab2b4c74baf entities/adapters.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/entities/adapters.py Thu May 20 20:47:55 2010 +0200 @@ -0,0 +1,166 @@ +# copyright 2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved. +# contact http://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 . +"""some basic entity adapter implementations, for interfaces used in the +framework itself. +""" + +__docformat__ = "restructuredtext en" + +from cubicweb.view import EntityAdapter, implements_adapter_compat +from cubicweb.selectors import implements, relation_possible +from cubicweb.interfaces import IDownloadable + + +class IEmailableAdapter(EntityAdapter): + __regid__ = 'IEmailable' + __select__ = relation_possible('primary_email') | relation_possible('use_email') + + def get_email(self): + if getattr(self.entity, 'primary_email', None): + return self.entity.primary_email[0].address + if getattr(self.entity, 'use_email', None): + return self.entity.use_email[0].address + return None + + def allowed_massmail_keys(self): + """returns a set of allowed email substitution keys + + The default is to return the entity's attribute list but you might + override this method to allow extra keys. For instance, a Person + class might want to return a `companyname` key. + """ + return set(rschema.type + for rschema, attrtype in self.entity.e_schema.attribute_definitions() + if attrtype.type not in ('Password', 'Bytes')) + + def as_email_context(self): + """returns the dictionary as used by the sendmail controller to + build email bodies. + + NOTE: the dictionary keys should match the list returned by the + `allowed_massmail_keys` method. + """ + return dict( (attr, getattr(self.entity, attr)) + for attr in self.allowed_massmail_keys() ) + + +class INotifiableAdapter(EntityAdapter): + __regid__ = 'INotifiable' + __select__ = implements('Any') + + @implements_adapter_compat('INotifiableAdapter') + def notification_references(self, view): + """used to control References field of email send on notification + for this entity. `view` is the notification view. + + Should return a list of eids which can be used to generate message + identifiers of previously sent email(s) + """ + itree = self.entity.cw_adapt_to('ITree') + if itree is not None: + return itree.path()[:-1] + return () + + +class IFTIndexableAdapter(EntityAdapter): + __regid__ = 'IFTIndexable' + __select__ = implements('Any') + + def fti_containers(self, _done=None): + if _done is None: + _done = set() + entity = self.entity + _done.add(entity.eid) + containers = tuple(entity.e_schema.fulltext_containers()) + if containers: + for rschema, target in containers: + if target == 'object': + targets = getattr(entity, rschema.type) + else: + targets = getattr(entity, 'reverse_%s' % rschema) + for entity in targets: + if entity.eid in _done: + continue + for container in entity.cw_adapt_to('IFTIndexable').fti_containers(_done): + yield container + yielded = True + else: + yield entity + + def get_words(self): + """used by the full text indexer to get words to index + + this method should only be used on the repository side since it depends + on the logilab.database package + + :rtype: list + :return: the list of indexable word of this entity + """ + from logilab.database.fti import tokenize + # take care to cases where we're modyfying the schema + entity = self.entity + pending = self._cw.transaction_data.setdefault('pendingrdefs', set()) + words = [] + for rschema in entity.e_schema.indexable_attributes(): + if (entity.e_schema, rschema) in pending: + continue + try: + value = entity.printable_value(rschema, format='text/plain') + except TransformError: + continue + except: + self.exception("can't add value of %s to text index for entity %s", + rschema, entity.eid) + continue + if value: + words += tokenize(value) + for rschema, role in entity.e_schema.fulltext_relations(): + if role == 'subject': + for entity in getattr(entity, rschema.type): + words += entity.cw_adapt_to('IFTIndexable').get_words() + else: # if role == 'object': + for entity in getattr(entity, 'reverse_%s' % rschema.type): + words += entity.cw_adapt_to('IFTIndexable').get_words() + return words + + +class IDownloadableAdapter(EntityAdapter): + """interface for downloadable entities""" + __regid__ = 'IDownloadable' + __select__ = implements(IDownloadable) # XXX for bw compat, else should be abstract + + @implements_adapter_compat('IDownloadable') + def download_url(self): # XXX not really part of this interface + """return an url to download entity's content""" + raise NotImplementedError + @implements_adapter_compat('IDownloadable') + def download_content_type(self): + """return MIME type of the downloadable content""" + raise NotImplementedError + @implements_adapter_compat('IDownloadable') + def download_encoding(self): + """return encoding of the downloadable content""" + raise NotImplementedError + @implements_adapter_compat('IDownloadable') + def download_file_name(self): + """return file name of the downloadable content""" + raise NotImplementedError + @implements_adapter_compat('IDownloadable') + def download_data(self): + """return actual data of the downloadable content""" + raise NotImplementedError