class Tool(UniqueObject, SimpleItem):
    """
    Contentrules subscription tool
    """
    id = SUBSCRIPTION_TOOL
    meta_type = 'Contentrules Subscription Tool'
    plone_tool = 1

    def __init__(self):
        self.subscriptions = PersistentDict()

    def registerUser(self, rule_id, email):
        """
        Insert the given email address in the given rule_id
        """
        if not rule_id in self.subscriptions:
            self.subscriptions[rule_id] = [email]
        else:
            if email in self.subscriptions[rule_id]:
                factory = getUtility(IVocabularyFactory,
                                     "contentrules.subscription.vocabularies.SubscriptionRulesVocabulary")
                vocabulary = factory(self)
                rule_term = vocabulary.getTerm(rule_id)
                msg = _('already_subscribed_error',
                        default='The given email is already present for "${title}"',
                        mapping=dict(title=rule_term.title))
                return False, msg
            else:
                self.subscriptions[rule_id].append(email)
        return True, ""

    def getSubscriptions(self):
        """
        Return the list of subscriptions
        """
        return self.subscriptions

    def getActionUIDS(self):
        """
        return a list of email addresses for the given rule_id
        """
        return self.subscriptions.keys()

    def getRegisteredList(self, rule_id):
        """
        return a list of email addresses for the given rule_id
        """
        return self.subscriptions.get(rule_id, [])
Ejemplo n.º 2
0
class UserAnnotation(object):
    """Stores annotations."""

    def __init__(self, principalId, store=None):
        self.principalId = principalId
        # _v_store is used to remember a mapping object that we should
        # be saved in if we ever change
        self._v_store = store
        self._data = PersistentDict() if store is None else store.get(principalId, PersistentDict())

    def __bool__(self):
        return bool(self._data)

    __nonzero__ = __bool__

    def __getitem__(self, key):
        return self._data[key]

    def get(self, key, default=None):
        return self._data.get(key, default)

    def keys(self):
        return self._data.keys()

    def __iter__(self):
        return iter(self._data)

    def __len__(self):
        return len(self._data)

    def __setitem__(self, key, value):
        if getattr(self, '_v_store', None) is not None:
            # _v_store is used to remember a mapping object that we should
            # be saved in if we ever change
            self._v_store[self.principalId] = self._data
            del self._v_store

        self._data[key] = value

    def __delitem__(self, key):
        del self._data[key]

    def __contains__(self, key):
        return key in self._data

    def items(self):
        return self._data.items()
Ejemplo n.º 3
0
class UserAnnotation(object):
    """Stores annotations."""
    def __init__(self, principalId, store=None):
        self.principalId = principalId
        # _v_store is used to remember a mapping object that we should
        # be saved in if we ever change
        self._v_store = store
        self._data = PersistentDict() if store is None else store.get(
            principalId, PersistentDict())

    def __bool__(self):
        return bool(self._data)

    __nonzero__ = __bool__

    def __getitem__(self, key):
        return self._data[key]

    def get(self, key, default=None):
        return self._data.get(key, default)

    def keys(self):
        return self._data.keys()

    def __iter__(self):
        return iter(self._data)

    def __len__(self):
        return len(self._data)

    def __setitem__(self, key, value):
        if getattr(self, '_v_store', None) is not None:
            # _v_store is used to remember a mapping object that we should
            # be saved in if we ever change
            self._v_store[self.principalId] = self._data
            del self._v_store

        self._data[key] = value

    def __delitem__(self, key):
        del self._data[key]

    def __contains__(self, key):
        return key in self._data

    def items(self):
        return self._data.items()
Ejemplo n.º 4
0
class MarscatsSettingsStorage(Persistent):

    implements(IMarscatsSettingsStorage)

    def __init__(self):
        self._fields = PersistentDict()

    def setStartupDir(self, fieldname, startup_dir, portal_type=None):
        field = self._fields.setdefault(fieldname, PersistentDict())
        if portal_type is not None:
            portal_types = field.setdefault('portal_types', PersistentDict())
            portal_types[portal_type] = startup_dir
        else:
            self._fields[fieldname]['startup_directory'] = startup_dir

    def getStartupDir(self, fieldname, portal_type=None,
                            fallback=True, ispath=False):
        sd = ''
        if fallback:
            sd = CAT_CONTAINER
        if fieldname in self._fields.keys():
            field = self._fields.get(fieldname)
            sd = field.get('startup_directory', sd)
            if portal_type is not None:
                pts = field.get('portal_types')
                if pts is not None:
                    sd = pts.get(portal_type, sd)
        if ispath:
            if not sd.startswith(CAT_CONTAINER):
                sd = CAT_CONTAINER + '/' + sd
#            sd = '/' + sd
        return sd

    def getFieldNames(self):
        return list(self._fields)

    def getTypesForField(self, fieldname):
        if fieldname in self._fields:
            field = self._fields[fieldname]
            if 'portal_types' in field and len(field['portal_types']):
                return list(field['portal_types'])
        return list()
Ejemplo n.º 5
0
class MockContainer(PortalContent):
    """ """
    implements(IUIDKeyedContainer, IAttributeUUID)

    def __init__(self, id, items=None):
        super(MockContainer, self).__init__()
        self.id = id
        self._items = PersistentDict(items)

    def get(self, uid, default=None):
        v = self._items.get(str(uid), None)
        if v and getattr(v, '_v_parent', None) is None:
            v._v_parent = self  # container marks obtained item with context
        return v

    # just here for test use:
    def register(self, uid, item):
        self._items[uid] = item

    def unregister(self, uid):
        del (self._items[uid])

    def __contains__(self, uid):
        return uid in self._items

    # here for indexing purposes, even though these indexes may
    # be handled differently in real life (e.g. indexer adapter):

    def UID(self):
        return IUUID(self)

    def contains(self):
        return self._items.keys()  # UUIDs of contained items

    def items(self):
        return self._items.items()
Ejemplo n.º 6
0
class MockContainer(PortalContent):
    """ """
    implements(IUIDKeyedContainer, IAttributeUUID)

    def __init__(self, id, items=None):
        super(MockContainer, self).__init__()
        self.id = id
        self._items = PersistentDict(items)

    def get(self, uid, default=None):
        v = self._items.get(str(uid), None)
        if v and getattr(v, '_v_parent', None) is None:
            v._v_parent = self  # container marks obtained item with context
        return v

    # just here for test use:
    def register(self, uid, item):
        self._items[uid] = item

    def unregister(self, uid):
        del(self._items[uid])

    def __contains__(self, uid):
        return uid in self._items

    # here for indexing purposes, even though these indexes may
    # be handled differently in real life (e.g. indexer adapter):

    def UID(self):
        return IUUID(self)

    def contains(self):
        return self._items.keys()  # UUIDs of contained items

    def items(self):
        return self._items.items()
Ejemplo n.º 7
0
class BaseContainer(PersistentMapping):
    """ Provides a basis for `container` objects
        >>> container = BaseContainer()
        >>> container[u'foo'] = u'bar'
        >>> container[u'foo']
        u'bar'
        >>> container.items()
        [(u'foo', u'bar')]
        >>> container.keys()
        [u'foo']
        >>> container.values()
        [u'bar']
        
    """
    def __init__(self):
        self.data = PersistentDict()
    
    def __getitem__(self, key):
        return self.data.__getitem__(key)
    
    def __setitem__(self, key, value):
        """ Acts as a proxy to the self.data PersistentDict. As it is a
            persistent object, it will also try and assign the __parent__
            attrubute to any object stored through this interface.
            
            >>> container = BaseContainer()
            >>> container.__setitem__('foo', 'bar')
            >>> 'foo' in container.data
            True
            >>> container['foo'].__parent__ # doctest: +ELLIPSIS
            Traceback (most recent call last):
            ...
            AttributeError: 'str' object has no attribute '__parent__'
            >>> class Child(object):
            ...     __parent__ = None
            ...
            >>> container.__setitem__('baz', Child())
            >>> 'baz' in container.data
            True
            >>> container['baz'].__parent__ == container
            True
        """
        ret = self.data.__setitem__(key, value)
        try: self.data[key].__parent__ = self
        except: pass
        return ret
    
    def items(self):
        return self.data.items()
    
    def keys(self):
        return self.data.keys()
    
    def values(self):
        return self.data.values()
    
    def update(self, _data={}, **kwargs):
        """ BaseContainers can be updated much the same as any Python dictionary.
            
            By passing another mapping object:
            
            >>> container = BaseContainer()
            >>> container.update({'foo':'bar'})
            
            By passing a list of iterables with length 2:
            
            >>> container = BaseContainer()
            >>> container.update([('foo', 'bar'),])
            
            By passing a set of keyword arguments:
            
            >>> container = BaseContainer()
            >>> container.update(foo='bar')
            
        """
        if kwargs:
            for k,v in kwargs.items():
                self.__setitem__(k,v)
            return
        elif isinstance(_data, dict):
            for k,v in _data.items():
                self.__setitem__(k,v)
        elif isinstance(_data, dict):
            for k,v in _data:
                self.__setitem__(k,v)
Ejemplo n.º 8
0
class Taxonomy(SimpleItem):
    implements(ITaxonomy)

    def __init__(self, name, title, default_language):
        super(Taxonomy, self).__init__(self)
        self.data = PersistentDict()
        self.name = name
        self.title = title
        self.default_language = default_language

    def __call__(self, context):

        if not self.data:
            return Vocabulary(self.name, {}, {})

        request = getattr(context, "REQUEST", None)

        current_language = self.getCurrentLanguage(request)
        data = self.data[current_language]
        inverted_data = self.inverted_data[current_language]

        return Vocabulary(self.name, data, inverted_data)

    @property
    @ram.cache(lambda method, self: (self.name, self.data._p_mtime))
    def inverted_data(self):
        inv_data = {}
        for (language, elements) in self.data.items():
            inv_data[language] = {}
            for (path, identifier) in elements.items():
                inv_data[language][identifier] = path
        return inv_data

    def getShortName(self):
        return self.name.split('.')[-1]

    def getGeneratedName(self):
        return 'collective.taxonomy.generated.' + self.getShortName()

    def getVocabularyName(self):
        return 'collective.taxonomy.' + self.getShortName()

    def getCurrentLanguage(self, request):
        try:
            portal_state = getMultiAdapter(
                (self, request), name=u'plone_portal_state'
            )

            language = portal_state.language().split('-', 1)[0]
        except ComponentLookupError:
            language = ''  # Force to return default language.

        if language in self.data:
            return language
        elif self.default_language in self.data:
            return self.default_language
        else:
            # our best guess!
            return self.data.keys()[0]

    def registerBehavior(self, **kwargs):
        context = getSite()
        sm = context.getSiteManager()
        new_args = copy(kwargs)

        new_args['name'] = self.name
        new_args['title'] = self.title
        new_args['description'] = kwargs.get('field_description', u'')
        new_args['field_description'] = new_args['description']

        behavior = TaxonomyBehavior(**new_args)
        sm.registerUtility(behavior, IBehavior,
                           name=self.getGeneratedName())

        behavior.addIndex()
        behavior.activateSearchable()

    def cleanupFTI(self):
        """Cleanup the FTIs"""
        generated_name = self.getGeneratedName()
        context = getSite()
        sm = context.getSiteManager()
        for (name, fti) in sm.getUtilitiesFor(IDexterityFTI):
            if generated_name in fti.behaviors:
                fti.behaviors = [behavior for behavior in
                                 fti.behaviors
                                 if behavior != generated_name]
            modified(fti, DexterityFTIModificationDescription("behaviors", ''))

    def updateBehavior(self, **kwargs):
        sm = getSite().getSiteManager()

        behavior_name = self.getGeneratedName()
        short_name = self.getShortName()

        utility = sm.queryUtility(IBehavior, name=behavior_name)
        if utility:
            utility.deactivateSearchable()
            utility.activateSearchable()
            utility.title = kwargs['field_title']

        delattr(generated, short_name)

        for (name, fti) in sm.getUtilitiesFor(IDexterityFTI):
            if behavior_name in fti.behaviors:
                modified(fti, DexterityFTIModificationDescription("behaviors", ''))

    def unregisterBehavior(self):
        context = getSite()
        sm = context.getSiteManager()
        behavior_name = self.getGeneratedName()
        utility = sm.queryUtility(IBehavior, name=behavior_name)

        if utility is None:
            return

        self.cleanupFTI()

        utility.removeIndex()
        utility.deactivateSearchable()
        utility.unregisterInterface()

        sm.unregisterUtility(utility, IBehavior, name=behavior_name)

    def clean(self):
        self.data.clear()

    def add(self, language, identifier, path):
        if not language in self.data:
            self.data[language] = OOBTree()

        self.data[language][path] = identifier

    def translate(self, msgid, mapping=None, context=None,
                  target_language=None, default=None):

        if target_language is None or \
                target_language not in self.inverted_data:
            target_language = str(self.getCurrentLanguage(
                getattr(context, 'REQUEST')
            ))

        if msgid not in self.inverted_data[target_language]:
            return ''

        path = self.inverted_data[target_language][msgid]
        pretty_path = path[1:].replace(PATH_SEPARATOR, u' » ')

        return pretty_path
class RegistrationApproval(PloneBaseTool, UniqueObject, SimpleItem):
    implements(IRegistrationApproval)

    id = 'wcc_membership_registration_approval'
    meta_type = 'WCC Registration Approval Tool'
    toolicon = 'skins/plone_images/site_icon.png'
    security = ClassSecurityInfo()

    def __init__(self):
        self._data = PersistentDict()
    
    def is_memberid_allowed(self, key):
        return not (key in self._data.keys())

    def values(self):
        for x in self._data.values():
            if not x.has_key('username'):
                x['username'] = x['email']
        return sorted(self._data.values(), key=(lambda x: x['username']))

    def add(self, key, data):
        if key in self._data.keys():
            raise ConflictError(u'User already exist in pending')
        data['username'] = key
        self._data[key] = data
        notify(UserRegisteredEvent(data))

    def get(self, key):
        return self._data[key]

    def approve(self, key):
        if key not in self._data.keys():
            raise KeyError(key)

        portal = getSite()
        registration = getToolByName(self, 'portal_registration')
        portal_props = getToolByName(self, 'portal_properties')
        mt = getToolByName(self, 'portal_membership')
        props = portal_props.site_properties
        use_email_as_login = props.getProperty('use_email_as_login')

        data = self._data[key]

        if use_email_as_login:
            data['username'] = data['email']

        user_id = data['username']
        password = registration.generatePassword()
        request = getRequest()
        try:
            registration.addMember(user_id, password, REQUEST=request)
        except (AttributeError, ValueError), err:
            logging.exception(err)
            IStatusMessage(request).addStatusMessage(err, type="error")
            return

        # set additional properties using the user schema adapter
        schema = getUtility(IUserDataSchemaProvider).getSchema()

        adapter = getAdapter(portal, schema)
        adapter.context = mt.getMemberById(user_id)

        for name in getFieldNamesInOrder(schema):
            if name in data:
                setattr(adapter, name, data[name])

        notify(UserApprovedEvent(data)) 
        del self._data[key]
Ejemplo n.º 10
0
class Taxonomy(SimpleItem):
    order = None
    count = None
    version = None

    def __init__(self, name, title, default_language):
        self.data = PersistentDict()
        self.order = PersistentDict()
        self.count = PersistentDict()
        self.version = PersistentDict()

        self.name = name
        self.title = title
        self.default_language = default_language

    @property
    def sm(self):
        return api.portal.get().getSiteManager()

    def __call__(self, context):
        if not self.data:
            return Vocabulary(self.name, {}, {}, {}, 2)

        request = getattr(context, "REQUEST", None)
        language = self.getCurrentLanguage(request)
        return self.makeVocabulary(language)

    @property
    @ram.cache(lambda method, self: (self.name, self.data._p_mtime))
    def inverted_data(self):
        inv_data = {}
        for (language, elements) in self.data.items():
            inv_data[language] = {}
            for (path, identifier) in elements.items():
                inv_data[language][identifier] = path
        return inv_data

    def getShortName(self):
        return self.name.split('.')[-1]

    def getGeneratedName(self):
        return 'collective.taxonomy.generated.' + self.getShortName()

    def getVocabularyName(self):
        return 'collective.taxonomy.' + self.getShortName()

    def makeVocabulary(self, language):
        self._fixup()
        data = self.data.get(language, {})
        order = self.order.get(language)
        version = self.version.get(language, 1)
        inverted_data = self.inverted_data.get(language, {})
        return Vocabulary(self.name, data, inverted_data, order, version)

    def getCurrentLanguage(self, request):
        language = get_lang_code()
        if language in self.data:
            return language
        elif self.default_language in self.data:
            return self.default_language
        else:
            # our best guess!
            return self.data.keys()[0]

    def getLanguages(self):
        return tuple(self.data)

    def iterLanguage(self, language=None):
        if language is None:
            language = self.default_language

        vocabulary = self.makeVocabulary(language)

        for path, identifier in vocabulary.iterEntries():
            parent_path = path.rsplit(PATH_SEPARATOR, 1)[0]
            if parent_path:
                parent = vocabulary.getTermByValue(parent_path)
            else:
                parent = None
            yield path, identifier, parent

    def registerBehavior(self, **kwargs):
        new_args = copy(kwargs)

        new_args['name'] = self.getGeneratedName()
        new_args['title'] = self.title
        new_args['description'] = kwargs.get('field_description', u'')
        new_args['field_description'] = new_args['description']

        behavior = TaxonomyBehavior(**new_args)
        self.sm.registerUtility(behavior, IBehavior,
                                name=self.getGeneratedName())

        behavior.addIndex()
        behavior.activateSearchable()

    def cleanupFTI(self):
        """Cleanup the FTIs"""
        generated_name = self.getGeneratedName()
        for (name, fti) in self.sm.getUtilitiesFor(IDexterityFTI):
            if generated_name in fti.behaviors:
                fti.behaviors = [behavior for behavior in
                                 fti.behaviors
                                 if behavior != generated_name]
            modified(fti, DexterityFTIModificationDescription("behaviors", ''))

    def updateBehavior(self, **kwargs):
        behavior_name = self.getGeneratedName()
        short_name = self.getShortName()

        utility = self.sm.queryUtility(IBehavior, name=behavior_name)
        if utility:
            utility.deactivateSearchable()
            utility.activateSearchable()
            if 'field_title' in kwargs:
                utility.title = kwargs.pop('field_title')

            for k, v in kwargs.items():
                setattr(utility, k, v)

        delattr(generated, short_name)

        for (name, fti) in self.sm.getUtilitiesFor(IDexterityFTI):
            if behavior_name in fti.behaviors:
                modified(fti, DexterityFTIModificationDescription("behaviors", ''))

    def unregisterBehavior(self):
        behavior_name = self.getGeneratedName()
        utility = self.sm.queryUtility(IBehavior, name=behavior_name)

        if utility is None:
            return

        self.cleanupFTI()

        utility.removeIndex()
        utility.deactivateSearchable()
        utility.unregisterInterface()

        self.sm.unregisterUtility(utility, IBehavior, name=behavior_name)

    def clean(self):
        self.data.clear()

    def add(self, language, value, key):
        self._fixup()
        tree = self.data.get(language)
        if tree is None:
            tree = self.data[language] = OOBTree()
        else:
            # Make sure we update the modification time.
            self.data[language] = tree

        update = key in tree
        tree[key] = value

        order = self.order.get(language)
        if order is None:
            order = self.order[language] = IOBTree()
            count = self.count[language] = 0
        else:
            if update:
                pop_value(tree, key)

            count = self.count[language] + 1

        self.count[language] = count
        order[count] = key

    def update(self, language, items, clear=False):
        self._fixup()

        tree = self.data.setdefault(language, OOBTree())
        if clear:
            tree.clear()

        # A new tree always uses the newest version.
        if not tree:
            version = self.version[language] = 2
        else:
            version = self.version.get(language, 1)

        order = self.order.setdefault(language, IOBTree())
        count = self.count.get(language, 0)

        if clear:
            order.clear()
            count = 0

        # Always migrate to newest version.
        if version == 1:
            def fix(path):
                return path.replace(LEGACY_PATH_SEPARATOR, PATH_SEPARATOR)

            for i in list(order):
                path = order[i]
                order[i] = fix(path)

            for path in list(tree):
                value = tree.pop(path)
                tree[fix(path)] = value

            version = self.version[language] = 2
            logger.info(
                "Taxonomy '%s' upgraded to version %d for language '%s'." % (
                    self.name, version, language
                )
            )

        # Make sure we update the modification time.
        self.data[language] = tree

        # The following structure is used to expunge updated entries.
        inv = {}
        if not clear:
            for i, key in order.items():
                inv[key] = i

        seen = set()
        for key, value in items:
            if key in seen:
                logger.warning("Duplicate key entry: %r" % (key, ))
                continue

            seen.add(key)
            update = key in tree
            tree[key] = value
            order[count] = key
            count += 1

            # If we're updating, then we have to pop out the old ordering
            # information in order to maintain relative ordering of new items.
            if update:
                i = inv.get(key)
                if i is not None:
                    del order[i]

        self.count[language] = count

    def translate(self, msgid, mapping=None, context=None,
                  target_language=None, default=None, msgid_plural=None,
                  default_plural=None, number=None):

        if target_language is None or \
                target_language not in self.inverted_data:
            target_language = str(api.portal.get_current_language())

        if msgid not in self.inverted_data[target_language]:
            return ''

        if self.version is not None and self.version.get(target_language) != 2:
            path_sep = LEGACY_PATH_SEPARATOR
        else:
            path_sep = PATH_SEPARATOR

        path = self.inverted_data[target_language][msgid]
        pretty_path = path[1:].replace(path_sep, PRETTY_PATH_SEPARATOR)

        if mapping is not None and mapping.get(NODE):
            pretty_path = pretty_path.rsplit(PRETTY_PATH_SEPARATOR, 1)[-1]

        return pretty_path

    def _fixup(self):
        # due to compatibility reasons this method fixes data structure
        # for old Taxonomy instances.
        # XXX: remove this in version 2.0 to prevent write on read
        if self.order is None:
            safeWrite(self, getRequest())
            self.order = PersistentDict()
            self.count = PersistentDict()

        if self.version is None:
            safeWrite(self, getRequest())
            self.version = PersistentDict()
Ejemplo n.º 11
0
class UserIdentities(Persistent):
    def __init__(self, userid):
        self.userid = userid
        self._identities = PersistentDict()
        self._sheet = None
        self._secret = str(uuid.uuid4())

    @property
    def secret(self):
        return self._secret

    def check_password(self, password):
        return password == self._secret

    def handle_result(self, result):
        """add a authomatic result to this user
        """
        self._sheet = None  # invalidate property sheet
        self._identities[result.provider.name] = UserIdentity(result)

    def identity(self, provider):
        """users identity at a distinct provider
        """
        return self._identities.get(provider, None)

    def providers(self):
        """List linked providers
        """
        return self._identities.keys()

    def unlink(self, provider):
        return self._identities.pop(provider)

    def update_userdata(self, result):
        self._sheet = None  # invalidate property sheet
        identity = self._identities[result.provider.name]
        identity.update(result.user.to_dict())

    @property
    def propertysheet(self):
        if self._sheet is not None:
            return self._sheet
        # build sheet from identities
        pdata = dict(id=self.userid)
        cfgs_providers = authomatic_cfg()
        for provider_name in cfgs_providers:
            identity = self.identity(provider_name)
            if identity is None:
                continue
            logger.debug(identity)
            cfg = cfgs_providers[provider_name]
            for akey, pkey in cfg.get('propertymap', {}).items():
                # Always search first on the user attributes, then on the raw
                # data this guaratees we do not break existing configurations
                ainfo = identity.get(akey, identity['data'].get(akey, None))
                if ainfo is None:
                    continue
                if isinstance(pkey, dict):
                    for k, v in pkey.items():
                        pdata[k] = ainfo.get(v)
                else:
                    pdata[pkey] = ainfo
        self._sheet = UserPropertySheet(**pdata)
        return self._sheet
Ejemplo n.º 12
0
class PlominoDocument(CatalogAware, CMFBTreeFolder, Contained):
    """ These represent the contents in a Plomino database.

    A document contains *items* that may or may not correspond to fields on
    one or more forms.
    """

    security = ClassSecurityInfo()
    implements(interfaces.IPlominoDocument, IAttributeAnnotatable)

    portal_type = "PlominoDocument"
    meta_type = "PlominoDocument"

    security.declarePublic('__init__')

    def __init__(self, id):
        """ Initialization
        """
        CMFBTreeFolder.__init__(self, id)
        self.id = id
        self.items = PersistentDict()
        self.plomino_modification_time = DateTime().toZone('UTC')

    security.declarePublic('checkBeforeOpenDocument')

    def checkBeforeOpenDocument(self):
        """ Check read permission and open view.

        .. NOTE:: if ``READ_PERMISSION`` is set on the ``view`` action
            itself, it causes an error ('maximum recursion depth exceeded')
            if user hasn't permission.
        """
        if self.isReader():
            return self.OpenDocument()
        else:
            raise Unauthorized, "You cannot read this content"

    def doc_path(self):
        return self.getPhysicalPath()

    def doc_url(self):
        """ return valid and nice url:
        - hide plomino_documents
        - use physicalPathToURL if REQUEST available
        """
        path = self.doc_path()
        short_path = [p for p in path if p != "plomino_documents"]
        if hasattr(self, "REQUEST"):
            return self.REQUEST.physicalPathToURL(short_path)
        else:
            return "/".join(short_path)

    security.declarePublic('setItem')

    def setItem(self, name, value):
        """
        """
        items = self.items
        if type(value) == type(''):
            db = self.getParentDatabase()
            translation_service = getToolByName(db, 'translation_service')
            value = translation_service.asunicodetype(value)
        items[name] = value
        self.items = items
        self.plomino_modification_time = DateTime().toZone('UTC')

    security.declarePublic('getItem')

    def getItem(self, name, default=''):
        """
        """
        if (self.items.has_key(name)):
            return deepcopy(self.items[name])
        else:
            return default

    security.declarePublic('hasItem')

    def hasItem(self, name):
        """
        """
        return self.items.has_key(name)

    security.declarePublic('removeItem')

    def removeItem(self, name):
        """
        """
        if (self.items.has_key(name)):
            items = self.items
            del items[name]
            self.items = items

    security.declarePublic('getItems')

    def getItems(self):
        """
        """
        return self.items.keys()

    security.declarePublic('getItemClassname')

    def getItemClassname(self, name):
        """
        """
        return self.getItem(name).__class__.__name__

    security.declarePublic('getLastModified')

    def getLastModified(self, asString=False):
        """
        """
        if not hasattr(self, 'plomino_modification_time'):
            self.plomino_modification_time = self.bobobase_modification_time(
            ).toZone('UTC')
        if asString:
            return str(self.plomino_modification_time)
        else:
            return self.plomino_modification_time

    security.declarePublic('getRenderedItem')

    def getRenderedItem(self,
                        itemname,
                        form=None,
                        formid=None,
                        convertattachments=False):
        """ Return the item rendered according to the corresponding field.

        The used form can be, in order of precedence:
        - passed as the `form` parameter,
        - specified with the `formid` parameter and looked up,
        - looked up from the document.

        If no form or field is found, return the empty string.

        If `convertattachments` is True, then we assume that field
        attachments are text and append them to the rendered value.
        """
        db = self.getParentDatabase()
        result = ''
        if not form:
            if formid:
                form = db.getForm(formid)
            else:
                form = self.getForm()
        if form:
            field = form.getFormField(itemname)
            if field:
                result = field.getFieldRender(form, self, False)
                if (field.getFieldType() == 'ATTACHMENT'
                        and convertattachments):
                    result += ' ' + db.getIndex().convertFileToText(
                        self, itemname).decode('utf-8')
                    result = result.encode('utf-8')

        return result

    security.declarePublic('tojson')

    def tojson(self, REQUEST=None, item=None, formid=None, rendered=False):
        """return item value as JSON
        (return all items if item=None)
        """
        if not self.isReader():
            raise Unauthorized, "You cannot read this content"

        datatables_format = False
        if REQUEST:
            REQUEST.RESPONSE.setHeader('content-type',
                                       'application/json; charset=utf-8')
            item = REQUEST.get('item', item)
            formid = REQUEST.get('formid', formid)
            rendered_str = REQUEST.get('rendered', None)
            if rendered_str:
                rendered = True
            datatables_format_str = REQUEST.get('datatables', None)
            if datatables_format_str:
                datatables_format = True
        if not item:
            return json.dumps(self.items.data)

        if not formid:
            form = self.getForm()
        else:
            form = self.getParentDatabase().getForm(formid)
        if form:
            field = form.getFormField(item)
            if field:
                if field.getFieldType() == 'DATAGRID':
                    adapt = field.getSettings()
                    fieldvalue = adapt.getFieldValue(form, self, False, False,
                                                     REQUEST)
                    fieldvalue = adapt.rows(fieldvalue, rendered=rendered)
                    if datatables_format:
                        fieldvalue = {
                            'iTotalRecords': len(fieldvalue),
                            'aaData': fieldvalue
                        }
                else:
                    if rendered:
                        fieldvalue = self.getRenderedItem(item, form)
                    else:
                        adapt = field.getSettings()
                        fieldvalue = adapt.getFieldValue(
                            form, self, False, False, REQUEST)
            else:
                fieldvalue = self.getItem(item)
        else:
            fieldvalue = self.getItem(item)

        return json.dumps(fieldvalue)

    security.declarePublic('computeItem')

    def computeItem(self,
                    itemname,
                    form=None,
                    formid=None,
                    store=True,
                    report=True):
        """ return the item value according the formula of the field defined in
        the given form (use default doc form if None)
        and store the value in the doc (if store=True)
        """
        result = None
        db = self.getParentDatabase()
        if not form:
            if not formid:
                form = self.getForm()
            else:
                form = db.getForm(formid)
        if form:
            result = form.computeFieldValue(itemname, self, report=report)
            if store:
                self.setItem(itemname, result)
        return result

    security.declarePublic('getPlominoReaders')

    def getPlominoReaders(self):
        """
        """
        if self.hasItem('Plomino_Readers'):
            return asList(self.Plomino_Readers)
        else:
            return ['*']

    security.declarePublic('isReader')

    def isReader(self):
        """
        """
        return self.getParentDatabase().isCurrentUserReader(self)

    security.declarePublic('isAuthor')

    def isAuthor(self):
        """
        """
        return self.getParentDatabase().isCurrentUserAuthor(self)

    security.declareProtected(REMOVE_PERMISSION, 'delete')

    def delete(self, REQUEST=None):
        """delete the current doc
        """
        db = self.getParentDatabase()
        db.deleteDocument(self)
        if not REQUEST is None:
            return_url = REQUEST.get('returnurl')
            REQUEST.RESPONSE.redirect(return_url)

    security.declareProtected(EDIT_PERMISSION, 'validation_errors')

    def validation_errors(self, REQUEST):
        """check submitted values
        """
        db = self.getParentDatabase()
        form = db.getForm(REQUEST.get('Form'))

        errors = form.validateInputs(REQUEST, doc=self)
        if len(errors) > 0:
            return self.errors_json(errors=json.dumps({
                'success': False,
                'errors': errors
            }))
        else:
            return self.errors_json(errors=json.dumps({'success': True}))

    security.declareProtected(EDIT_PERMISSION, 'saveDocument')

    def saveDocument(self, REQUEST, creation=False):
        """save a document using the form submitted content
        """
        db = self.getParentDatabase()
        form = db.getForm(REQUEST.get('Form'))

        errors = form.validateInputs(REQUEST, doc=self)
        if len(errors) > 0:
            return form.notifyErrors(errors)

        self.setItem('Form', form.getFormName())

        # process editable fields (we read the submitted value in the request)
        form.readInputs(self, REQUEST, process_attachments=True)

        # refresh computed values, run onSave, reindex
        self.save(form, creation)

        redirect = REQUEST.get('plominoredirecturl')
        if not redirect:
            redirect = self.getItem("plominoredirecturl")
        if not redirect:
            redirect = self.absolute_url()
        REQUEST.RESPONSE.redirect(redirect)

    security.declareProtected(EDIT_PERMISSION, 'refresh')

    def refresh(self, form=None):
        """ re-compute fields and re-index document
        (onSave event is not called, and authors are not updated
        """
        self.save(form,
                  creation=False,
                  refresh_index=True,
                  asAuthor=False,
                  onSaveEvent=False)

    security.declareProtected(EDIT_PERMISSION, 'save')

    def save(self,
             form=None,
             creation=False,
             refresh_index=True,
             asAuthor=True,
             onSaveEvent=True):
        """refresh values according form, and reindex the document
        """
        # we process computed fields (refresh the value)
        if form is None:
            form = self.getForm()
        else:
            self.setItem('Form', form.getFormName())

        db = self.getParentDatabase()
        if form:
            for f in form.getFormFields(includesubforms=True,
                                        doc=self,
                                        applyhidewhen=False):
                mode = f.getFieldMode()
                fieldname = f.id
                if mode in ["COMPUTED", "COMPUTEDONSAVE"
                            ] or (mode == "CREATION" and creation):
                    result = form.computeFieldValue(fieldname, self)
                    self.setItem(fieldname, result)
                else:
                    # computed for display field are not stored
                    pass

            # compute the document title
            title_formula = form.getDocumentTitle()
            if title_formula:
                # Use the formula if we have one
                try:
                    title = self.runFormulaScript("form_" + form.id + "_title",
                                                  self, form.DocumentTitle)
                    if title != self.Title():
                        self.setTitle(title)
                except PlominoScriptException, e:
                    e.reportError('Title formula failed')
            elif creation:
                # If we have no formula and we're creating, use Form's title
                title = form.Title()
                if title != self.Title():
                    # We may be calling save with 'creation=True' on
                    # existing documents, in which case we may already have
                    # a title.
                    self.setTitle(title)

            # update the document id
            if creation and form.getDocumentId():
                new_id = self.generateNewId()
                if new_id:
                    transaction.savepoint(optimistic=True)
                    db.documents.manage_renameObject(self.id, new_id)

        # update the Plomino_Authors field with the current user name
        if asAuthor:
            authors = self.getItem('Plomino_Authors')
            name = db.getCurrentUser().getUserName()
            if authors == '':
                authors = []
                authors.append(name)
            elif name in authors:
                pass
            else:
                authors.append(name)
            self.setItem('Plomino_Authors', authors)

        # execute the onSaveDocument code of the form
        if form and onSaveEvent:
            try:
                result = self.runFormulaScript("form_" + form.id + "_onsave",
                                               self, form.onSaveDocument)
                if result and hasattr(self, 'REQUEST'):
                    self.REQUEST.set('plominoredirecturl', result)
            except PlominoScriptException, e:
                if hasattr(self, 'REQUEST'):
                    e.reportError(
                        'Document has been saved but onSave event failed.')
                    doc_path = self.REQUEST.physicalPathToURL(self.doc_path())
                    self.REQUEST.RESPONSE.redirect(doc_path)
Ejemplo n.º 13
0
class PlominoDocument(CatalogAware, CMFBTreeFolder, Contained):
    """ These represent the contents in a Plomino database.

    A document contains *items*.
    An item may or may not correspond to fields on one or more forms.
    They may be manipulated by Formulas.
    """

    security = ClassSecurityInfo()
    implements(IPlominoDocument, IAttributeAnnotatable)

    portal_type = "PlominoDocument"
    meta_type = "PlominoDocument"

    security.declarePublic('__init__')

    def __init__(self, id):
        """ Initialization
        """
        CMFBTreeFolder.__init__(self, id)
        self.id = id
        self.items = PersistentDict()
        self.plomino_modification_time = DateTime().toZone(TIMEZONE)

    def absolute_url(self):
        db_url = self.getParentDatabase().absolute_url()
        return "%s/document/%s" % (db_url, self.id)

    def doc_path(self):
        db_path = self.getParentDatabase().getPhysicalPath()
        return list(db_path) + ["document", self.id]

    def doc_url(self):
        """ Return valid and nice url
        """
        path = self.doc_path()
        if hasattr(self, "REQUEST"):
            return self.REQUEST.physicalPathToURL(path)
        else:
            return "/".join(path)

    security.declarePublic('setItem')

    def setItem(self, name, value):
        """ Set item on document, converting str to unicode.
        """
        items = self.items
        if isinstance(value, str):
            db = self.getParentDatabase()
            translation_service = getToolByName(db, 'translation_service')
            value = translation_service.asunicodetype(value)
        items[name] = value
        self.items = items
        self.plomino_modification_time = DateTime().toZone(TIMEZONE)

    security.declarePublic('getItem')

    def getItem(self, name, default=''):
        """ Get item from document.
        """
        if name in self.items:
            return deepcopy(self.items[name])
        else:
            return default

    security.declarePublic('hasItem')

    def hasItem(self, name):
        """ Check if doc has item 'name'.
        """
        return name in self.items

    security.declarePublic('removeItem')

    def removeItem(self, name):
        """ Delete item 'name', if it exists.
        """
        if name in self.items:
            items = self.items
            del items[name]
            self.items = items

    security.declarePublic('getItems')

    def getItems(self):
        """ Return all item names.
        """
        return self.items.keys()

    security.declarePublic('getItemClassname')

    def getItemClassname(self, name):
        """ Return class name of the item.
        """
        return self.getItem(name).__class__.__name__

    security.declarePublic('getLastModified')

    def getLastModified(self, asString=False):
        """ Return last modified date, setting it if absent.
        """
        if not hasattr(self, 'plomino_modification_time'):
            self.plomino_modification_time =\
                self.bobobase_modification_time().toZone(TIMEZONE)
        if asString:
            return DateToString(
                self.plomino_modification_time,
                db=self.getParentDatabase())
        else:
            return self.plomino_modification_time

    security.declarePublic('getRenderedItem')

    def getRenderedItem(self, itemname, form=None, formid=None,
            convertattachments=False):
        """ Return the item rendered according to the corresponding field.

        The form used can be, in order of precedence:
        - passed as the `form` parameter,
        - specified with the `formid` parameter and looked up,
        - looked up from the document.

        If no form or field is found, return the empty string.

        If `convertattachments` is True, then we assume that field
        attachments are text and append them to the rendered value.
        """
        db = self.getParentDatabase()
        result = ''
        if not form:
            if formid:
                form = db.getForm(formid)
            else:
                form = self.getForm()
        if form:
            field = form.getFormField(itemname)
            if field:
                result = field.getFieldRender(form, self, False)
                if (field.field_type == 'ATTACHMENT' and
                        convertattachments):
                    result += ' ' + db.getIndex().convertFileToText(
                        self,
                        itemname).decode('utf-8')
                    result = result.encode('utf-8')

        return result

    security.declarePublic('tojson')

    def tojson(
        self,
        REQUEST=None,
        item=None,
        formid=None,
        rendered=False,
        lastmodified=None
    ):
        """ Return item value as JSON.

        Return all items if `item=None`.
        Values on the REQUEST overrides parameters.

        If the requested item corresponds to a field on the found form,
        the field value is returned. If not, it falls back to a plain item
        lookup on the document.

        `formid="None"` specifies plain item lookup.
        """
        # TODO: Don't always return the entire dataset: allow batching.

        if not self.isReader():
            raise Unauthorized("You cannot read this content")

        datatables_format = False
        if REQUEST:
            REQUEST.RESPONSE.setHeader(
                'content-type', 'application/json; charset=utf-8')
            item = REQUEST.get('item', item)
            formid = REQUEST.get('formid', formid)
            lastmodified = REQUEST.get('lastmodified', lastmodified)
            rendered_str = REQUEST.get('rendered', None)
            if rendered_str:
                rendered = True
            datatables_format_str = REQUEST.get('datatables', None)
            if datatables_format_str:
                datatables_format = True
        if item:
            if formid == "None":
                form = None
            elif formid:
                form = self.getParentDatabase().getForm(formid)
            else:
                form = self.getForm()
            if form:
                field = form.getFormField(item)
                if field:
                    if field.field_type == 'DATAGRID':
                        adapt = field.getSettings()
                        fieldvalue = adapt.getFieldValue(
                            form, doc=self, request=REQUEST)
                        fieldvalue = adapt.rows(
                            fieldvalue, rendered=rendered)
                    else:
                        if rendered:
                            fieldvalue = self.getRenderedItem(item, form)
                        else:
                            adapt = field.getSettings()
                            fieldvalue = adapt.getFieldValue(
                                form, doc=self, request=REQUEST)
                else:
                    fieldvalue = self.getItem(item)
            else:
                fieldvalue = self.getItem(item)
            data = fieldvalue
        else:
            data = self.items.data

        if datatables_format:
            data = {'iTotalRecords': len(data),
                    'iTotalDisplayRecords': len(data),
                    'aaData': data}
        if lastmodified:
            data = {'lastmodified': self.getLastModified(), 'data': data}
        return json.dumps(data)

    security.declarePublic('computeItem')

    def computeItem(self, itemname, form=None, formid=None, store=True,
            report=True):
        """ Return the value of named item according to the formula
        - of the field defined in the given form (default),
        - or the named `formid`,
        - or use the default doc form if no form found.
        Store the value in the doc (if `store=True`).
        (Pass `report` to `PlominoForm.computeFieldValue`.)
        """
        result = None
        if not form:
            if not formid:
                form = self.getForm()
            else:
                db = self.getParentDatabase()
                form = db.getForm(formid)
        if form:
            result = form.computeFieldValue(itemname, self, report=report)
            if store:
                # So this is a way to store the value of a DISPLAY field ..
                self.setItem(itemname, result)
        return result

    security.declarePublic('getPlominoReaders')

    def getPlominoReaders(self):
        """ Return list of readers; if none set, everyone can read.
        """
        if self.hasItem('Plomino_Readers'):
            return asList(self.getItem('Plomino_Readers'))
        else:
            return ['*']

    security.declarePublic('isReader')

    def isReader(self):
        """
        """
        return self.getParentDatabase().isCurrentUserReader(self)

    security.declarePublic('isAuthor')

    def isAuthor(self):
        """
        """
        return self.getParentDatabase().isCurrentUserAuthor(self)

    security.declareProtected(REMOVE_PERMISSION, 'delete')

    def delete(self, REQUEST=None):
        """ Delete the current doc; redirect to `returnurl` if available.
        """
        db = self.getParentDatabase()
        db.deleteDocument(self)
        if REQUEST:
            return_url = REQUEST.get('returnurl')
            if not return_url:
                return_url = db.absolute_url()
            REQUEST.RESPONSE.redirect(return_url)

    security.declareProtected(EDIT_PERMISSION, 'validation_errors')

    def validation_errors(self, REQUEST):
        """ Check submitted values.
        """
        db = self.getParentDatabase()
        form = db.getForm(REQUEST.get('Form'))
        errors = form.validateInputs(REQUEST, doc=self)
        if errors:
            return self.errors_json(
                errors=json.dumps({'success': False, 'errors': errors}))
        else:
            return self.errors_json(
                errors=json.dumps({'success': True}))

    security.declareProtected(EDIT_PERMISSION, 'saveDocument')

    def saveDocument(self, REQUEST, creation=False):
        """ Save a document using the form submitted content
        """
        db = self.getParentDatabase()
        form = db.getForm(REQUEST.get('Form'))

        errors = form.validateInputs(REQUEST, doc=self)

        # execute the beforeSave code of the form
        error = None
        try:
            error = self.runFormulaScript(
                SCRIPT_ID_DELIMITER.join(['form', form.id, 'beforesave']),
                self,
                form.beforeSaveDocument)
        except PlominoScriptException, e:
            e.reportError('Form submitted, but beforeSave formula failed')

        if error:
            errors.append(error)

        # if errors, stop here, and notify errors to user
        if errors:
            return form.notifyErrors(errors)

        self.setItem('Form', form.id)

        # process editable fields (we read the submitted value in the request)
        form.readInputs(self, REQUEST, process_attachments=True)

        # refresh computed values, run onSave, reindex
        self.save(form, creation)

        redirect = REQUEST.get('plominoredirecturl')
        if not redirect:
            redirect = self.getItem("plominoredirecturl")
        if type(redirect) is dict:
            # if dict, we assume it contains "callback" as an URL that will be
            # called asynchronously, "redirect" as the redirect url (optional,
            # default=doc url), and "method" (optional, default=GET)
            redirect = "./async_callback?" + urlencode(redirect)
        if not redirect:
            redirect = self.absolute_url()
        REQUEST.RESPONSE.redirect(addTokenToUrl(redirect))
Ejemplo n.º 14
0
class Taxonomy(SimpleItem):
    def __init__(self, name, title, default_language):
        self.data = PersistentDict()
        self.name = name
        self.title = title
        self.default_language = default_language

    @property
    def sm(self):
        return api.portal.get().getSiteManager()

    def __call__(self, context):

        if not self.data:
            return Vocabulary(self.name, {}, {})

        request = getattr(context, "REQUEST", None)

        current_language = self.getCurrentLanguage(request)
        data = self.data[current_language]
        inverted_data = self.inverted_data[current_language]

        return Vocabulary(self.name, data, inverted_data)

    @property
    @ram.cache(lambda method, self: (self.name, self.data._p_mtime))
    def inverted_data(self):
        inv_data = {}
        for (language, elements) in self.data.items():
            inv_data[language] = {}
            for (path, identifier) in elements.items():
                inv_data[language][identifier] = path
        return inv_data

    def getShortName(self):
        return self.name.split('.')[-1]

    def getGeneratedName(self):
        return 'collective.taxonomy.generated.' + self.getShortName()

    def getVocabularyName(self):
        return 'collective.taxonomy.' + self.getShortName()

    def getCurrentLanguage(self, request):
        language = get_lang_code()
        if language in self.data:
            return language
        elif self.default_language in self.data:
            return self.default_language
        else:
            # our best guess!
            return self.data.keys()[0]

    def registerBehavior(self, **kwargs):
        new_args = copy(kwargs)

        new_args['name'] = self.getGeneratedName()
        new_args['title'] = self.title
        new_args['description'] = kwargs.get('field_description', u'')
        new_args['field_description'] = new_args['description']

        behavior = TaxonomyBehavior(**new_args)
        self.sm.registerUtility(behavior,
                                IBehavior,
                                name=self.getGeneratedName())

        behavior.addIndex()
        behavior.activateSearchable()

    def cleanupFTI(self):
        """Cleanup the FTIs"""
        generated_name = self.getGeneratedName()
        for (name, fti) in self.sm.getUtilitiesFor(IDexterityFTI):
            if generated_name in fti.behaviors:
                fti.behaviors = [
                    behavior for behavior in fti.behaviors
                    if behavior != generated_name
                ]
            modified(fti, DexterityFTIModificationDescription("behaviors", ''))

    def updateBehavior(self, **kwargs):
        behavior_name = self.getGeneratedName()
        short_name = self.getShortName()

        utility = self.sm.queryUtility(IBehavior, name=behavior_name)
        if utility:
            utility.deactivateSearchable()
            utility.activateSearchable()
            if 'field_title' in kwargs:
                utility.title = kwargs.pop('field_title')

            for k, v in kwargs.iteritems():
                setattr(utility, k, v)

        delattr(generated, short_name)

        for (name, fti) in self.sm.getUtilitiesFor(IDexterityFTI):
            if behavior_name in fti.behaviors:
                modified(fti,
                         DexterityFTIModificationDescription("behaviors", ''))

    def unregisterBehavior(self):
        behavior_name = self.getGeneratedName()
        utility = self.sm.queryUtility(IBehavior, name=behavior_name)

        if utility is None:
            return

        self.cleanupFTI()

        utility.removeIndex()
        utility.deactivateSearchable()
        utility.unregisterInterface()

        self.sm.unregisterUtility(utility, IBehavior, name=behavior_name)

    def clean(self):
        self.data.clear()

    def add(self, language, identifier, path):
        if language not in self.data:
            self.data[language] = OOBTree()

        self.data[language][path] = identifier

    def translate(self,
                  msgid,
                  mapping=None,
                  context=None,
                  target_language=None,
                  default=None):

        if target_language is None or \
                target_language not in self.inverted_data:
            target_language = str(
                self.getCurrentLanguage(getattr(context, 'REQUEST')))

        if msgid not in self.inverted_data[target_language]:
            return ''

        path = self.inverted_data[target_language][msgid]
        pretty_path = path[1:].replace(PATH_SEPARATOR, u' » ')

        return pretty_path
Ejemplo n.º 15
0
class Taxonomy(SimpleItem):
    order = None
    count = None
    version = None

    def __init__(self, name, title, default_language):
        self.data = PersistentDict()
        self.order = PersistentDict()
        self.count = PersistentDict()
        self.version = PersistentDict()

        self.name = name
        self.title = title
        self.default_language = default_language

    @property
    def sm(self):
        return api.portal.get().getSiteManager()

    def __call__(self, context):
        if not self.data:
            return Vocabulary(self.name, {}, {}, {}, 2)

        request = getattr(context, "REQUEST", None)
        language = self.getCurrentLanguage(request)
        return self.makeVocabulary(language)

    @property
    @ram.cache(lambda method, self: (self.name, self.data._p_mtime))
    def inverted_data(self):
        inv_data = {}
        for (language, elements) in self.data.items():
            inv_data[language] = {}
            for (path, identifier) in elements.items():
                inv_data[language][identifier] = path
        return inv_data

    def getShortName(self):
        return self.name.split('.')[-1]

    def getGeneratedName(self):
        return 'collective.taxonomy.generated.' + self.getShortName()

    def getVocabularyName(self):
        return 'collective.taxonomy.' + self.getShortName()

    def makeVocabulary(self, language):
        self._fixup()
        data = self.data.get(language, {})
        order = self.order.get(language)
        version = self.version.get(language, 1)
        inverted_data = self.inverted_data.get(language, {})
        return Vocabulary(self.name, data, inverted_data, order, version)

    def getCurrentLanguage(self, request):
        language = get_lang_code()
        if language in self.data:
            return language
        elif self.default_language in self.data:
            return self.default_language
        else:
            # our best guess!
            return self.data.keys()[0]

    def getLanguages(self):
        return tuple(self.data)

    def iterLanguage(self, language=None):
        if language is None:
            language = self.default_language

        vocabulary = self.makeVocabulary(language)

        for path, identifier in vocabulary.iterEntries():
            parent_path = path.rsplit(PATH_SEPARATOR, 1)[0]
            if parent_path:
                parent = vocabulary.getTermByValue(parent_path)
            else:
                parent = None
            yield path, identifier, parent

    def registerBehavior(self, **kwargs):
        new_args = copy(kwargs)

        new_args['name'] = self.getGeneratedName()
        new_args['title'] = self.title
        new_args['description'] = kwargs.get('field_description', u'')
        new_args['field_description'] = new_args['description']

        behavior = TaxonomyBehavior(**new_args)
        self.sm.registerUtility(behavior, IBehavior,
                                name=self.getGeneratedName())

        behavior.addIndex()
        behavior.activateSearchable()

    def cleanupFTI(self):
        """Cleanup the FTIs"""
        generated_name = self.getGeneratedName()
        for (name, fti) in self.sm.getUtilitiesFor(IDexterityFTI):
            if generated_name in fti.behaviors:
                fti.behaviors = [behavior for behavior in
                                 fti.behaviors
                                 if behavior != generated_name]
            modified(fti, DexterityFTIModificationDescription("behaviors", ''))

    def updateBehavior(self, **kwargs):
        behavior_name = self.getGeneratedName()
        short_name = self.getShortName()

        utility = self.sm.queryUtility(IBehavior, name=behavior_name)
        if utility:
            utility.deactivateSearchable()
            utility.activateSearchable()
            if 'field_title' in kwargs:
                utility.title = kwargs.pop('field_title')

            for k, v in kwargs.items():
                setattr(utility, k, v)

        delattr(generated, short_name)

        for (name, fti) in self.sm.getUtilitiesFor(IDexterityFTI):
            if behavior_name in fti.behaviors:
                modified(fti, DexterityFTIModificationDescription("behaviors", ''))

    def unregisterBehavior(self):
        behavior_name = self.getGeneratedName()
        utility = self.sm.queryUtility(IBehavior, name=behavior_name)

        if utility is None:
            return

        self.cleanupFTI()

        utility.removeIndex()
        utility.deactivateSearchable()
        utility.unregisterInterface()

        self.sm.unregisterUtility(utility, IBehavior, name=behavior_name)

    def clean(self):
        self.data.clear()

    def add(self, language, value, key):
        self._fixup()
        tree = self.data.get(language)
        if tree is None:
            tree = self.data[language] = OOBTree()
        else:
            # Make sure we update the modification time.
            self.data[language] = tree

        update = key in tree
        tree[key] = value

        order = self.order.get(language)
        if order is None:
            order = self.order[language] = IOBTree()
            count = self.count[language] = 0
        else:
            if update:
                pop_value(tree, key)

            count = self.count[language] + 1

        self.count[language] = count
        order[count] = key

    def update(self, language, items, clear=False):
        self._fixup()

        tree = self.data.setdefault(language, OOBTree())
        if clear:
            tree.clear()

        # A new tree always uses the newest version.
        if not tree:
            version = self.version[language] = 2
        else:
            version = self.version.get(language, 1)

        order = self.order.setdefault(language, IOBTree())
        count = self.count.get(language, 0)

        if clear:
            order.clear()
            count = 0

        # Always migrate to newest version.
        if version == 1:
            def fix(path):
                return path.replace(LEGACY_PATH_SEPARATOR, PATH_SEPARATOR)

            for i in list(order):
                path = order[i]
                order[i] = fix(path)

            for path in list(tree):
                value = tree.pop(path)
                tree[fix(path)] = value

            version = self.version[language] = 2
            logger.info(
                "Taxonomy '%s' upgraded to version %d for language '%s'." % (
                    self.name, version, language
                )
            )

        # Make sure we update the modification time.
        self.data[language] = tree

        # The following structure is used to expunge updated entries.
        inv = {}
        if not clear:
            for i, key in order.items():
                inv[key] = i

        seen = set()
        for key, value in items:
            if key in seen:
                logger.warning("Duplicate key entry: %r" % (key, ))

            seen.add(key)
            update = key in tree
            tree[key] = value
            order[count] = key
            count += 1

            # If we're updating, then we have to pop out the old ordering
            # information in order to maintain relative ordering of new items.
            if update:
                i = inv.get(key)
                if i is not None:
                    del order[i]

        self.count[language] = count

    def translate(self, msgid, mapping=None, context=None,
                  target_language=None, default=None, msgid_plural=None,
                  default_plural=None, number=None):

        if target_language is None or \
                target_language not in self.inverted_data:
            target_language = str(self.getCurrentLanguage(
                getattr(context, 'REQUEST')
            ))

        if msgid not in self.inverted_data[target_language]:
            return ''

        if self.version is not None and self.version.get(target_language) != 2:
            path_sep = LEGACY_PATH_SEPARATOR
        else:
            path_sep = PATH_SEPARATOR

        path = self.inverted_data[target_language][msgid]
        pretty_path = path[1:].replace(path_sep, PRETTY_PATH_SEPARATOR)

        if mapping is not None and mapping.get(NODE):
            pretty_path = pretty_path.rsplit(PRETTY_PATH_SEPARATOR, 1)[-1]

        return pretty_path

    def _fixup(self):
        # due to compatibility reasons this method fixes data structure
        # for old Taxonomy instances.
        # XXX: remove this in version 2.0 to prevent write on read
        if self.order is None:
            safeWrite(self, getRequest())
            self.order = PersistentDict()
            self.count = PersistentDict()

        if self.version is None:
            safeWrite(self, getRequest())
            self.version = PersistentDict()
Ejemplo n.º 16
0
class HebergementFolder(ATFolder):
    """
    """
    security = ClassSecurityInfo()
    __implements__ = (getattr(ATFolder, '__implements__', ()))

    # This name appears in the 'add' box
    archetype_name = 'HebergementFolder'

    meta_type = 'HebergementFolder'
    portal_type = 'HebergementFolder'
    allowed_content_types = []
    filter_content_types = 0
    global_allow = 1
    #content_icon = 'HebergementFolder.gif'
    immediate_view = 'view'
    default_view = 'view'
    suppl_views = ()
    typeDescription = "HebergementFolder"
    typeDescMsgId = 'description_edit_hebergementfolder'

    _at_rename_after_creation = True

    schema = HebergementFolder_schema

    ##code-section class-header #fill in your manual code here
    implements(IHebergementFolder, IMappableContent)
    ##/code-section class-header

    # Methods

    # Manually created methods

    security.declarePrivate('_createUniqueId')
    def _createUniqueId(self, dupId, idList):
        cpt = 1
        while 1:
            new_id = "%s-%s" % (dupId, cpt)
            cpt += 1
            if new_id not in idList:
                id = new_id
                break
        return id

    security.declareProtected("Modify portal content", 'updateHebergement')
    def updateHebergement(self):
        portal = getToolByName(self, 'portal_url').getPortalObject()
        ptool = portal.plone_utils
        wrapper = getSAWrapper('gites_wallons')
        Hebergement = wrapper.getMapper('hebergement')
        session = wrapper.session
        hebergements = session.query(Hebergement).all()
        self.known_gites_id = PersistentDict()
        for hebergement in hebergements:
            nom = hebergement.heb_nom
            id = hebergement.heb_id
            if not id:
                id = ptool.normalizeString(nom)
                if id in self.known_gites_id.keys():
                    id = self._createUniqueId(id, self.known_gites_id.keys())
                hebergement.heb_id = id
                session.add(hebergement)
            self.known_gites_id[id] = hebergement.heb_pk

    security.declareProtected("Modify portal content", 'updateType')
    def updateType(self):
        portal = getToolByName(self, 'portal_url').getPortalObject()
        ptool = portal.plone_utils
        wrapper = getSAWrapper('gites_wallons')
        TypesHeb = wrapper.getMapper('type_heb')
        session = wrapper.session
        typesHebs = session.query(TypesHeb).all()
        self.known_types_id = PersistentDict()
        for typeHeb in typesHebs:
            nom = typeHeb.type_heb_nom
            pk = typeHeb.type_heb_pk
            id = typeHeb.type_heb_id
            if not id:
                id = ptool.normalizeString(nom)
                if id in self.known_types_id.keys():
                    id = self._createUniqueId(id, self.known_types_id.keys())
                typeHeb.type_heb_id = id
                session.add(typeHeb)
            self.known_types_id[id] = pk

            nom = typeHeb.type_heb_nom_nl
            id = typeHeb.type_heb_id_nl
            if not id:
                id = ptool.normalizeString(nom)
                if id in self.known_types_id.keys():
                    id = self._createUniqueId(id, self.known_types_id.keys())
                typeHeb.type_heb_id_nl = id
                session.add(typeHeb)
            self.known_types_id[id] = pk

            nom = typeHeb.type_heb_nom_uk
            id = typeHeb.type_heb_id_uk
            if not id:
                id = ptool.normalizeString(nom)
                if id in self.known_types_id.keys():
                    id = self._createUniqueId(id, self.known_types_id.keys())
                typeHeb.type_heb_id_uk = id
                session.add(typeHeb)
            self.known_types_id[id] = pk

            id = typeHeb.type_heb_id_de
            nom = typeHeb.type_heb_nom_de
            if not id:
                id = ptool.normalizeString(nom)
                if id in self.known_types_id.keys():
                    id = self._createUniqueId(id, self.known_types_id.keys())
                typeHeb.type_heb_id_de = id
                session.add(typeHeb)
            self.known_types_id[id] = pk

            nom = typeHeb.type_heb_nom_it
            id = typeHeb.type_heb_id_it
            if not id:
                id = ptool.normalizeString(nom)
                if id in self.known_types_id.keys():
                    id = self._createUniqueId(id, self.known_types_id.keys())
                typeHeb.type_heb_id_it = id
                session.add(typeHeb)
            self.known_types_id[id] = pk

    security.declareProtected("Modify portal content", 'updateCommune')
    def updateCommune(self):
        portal = getToolByName(self, 'portal_url').getPortalObject()
        ptool = portal.plone_utils
        wrapper = getSAWrapper('gites_wallons')
        Commune = wrapper.getMapper('commune')
        session = wrapper.session
        communes = session.query(Commune).all()
        self.known_communes_id = PersistentDict()
        for commune in communes:
            nom = commune.com_nom
            id = commune.com_id
            if not id:
                id = ptool.normalizeString(nom)
                commune.com_id = id
                session.add(commune)
            self.known_communes_id[id] = commune.com_pk

    security.declareProtected("Modify portal content", 'updateHebergement')
    def update(self, REQUEST=None):
        """
        """
        alsoProvides(REQUEST, IDisableCSRFProtection)
        self.updateHebergement()
        self.updateCommune()
        self.updateType()
        memcache = memcachedClient()
        memcache.invalidateAll()

    def view(self, REQUEST):
        """
        default give back a search form
        """
        url = "%s/search_hosting.html" % self.absolute_url()
        return REQUEST.RESPONSE.redirect(url)
Ejemplo n.º 17
0
class Page(Persistent):
    __name__ = None
    __parent__ = None
    __children__ = []
    
    title = u''
    
    layout_template = u''
    
    _default_behaviour = config['DEFAULT_PAGE_BEHAVIOUR']
    
    def __init__(self, title):
        self.title = title
        self.__name__ = normalise_title(title)
        self._properties = PersistentDict({})
        self._extra_behaviour = PersistentList([])
        
        self._update_properties()
    
    ### Behaviour ###
    
    @property
    def behaviour(self):
        """ Collates the default and user-added behaviour into a list
            
                >>> page = Page('test')
                >>> page.behaviour == list(page._default_behaviour) + list(page._extra_behaviour)
                True
        """
        return list(self._default_behaviour) + list(self._extra_behaviour)
    
    def add_behaviour(self, key, data=None, prefix=''):
        """ Adds additional behaviour as defined by a Schema object.
            
            We can't extend the page with behaviour that isn't provided for in the registry:
            
                >>> page = Page('test')
                >>> page.add_behaviour('test')
                Traceback (most recent call last):
                ...
                InvalidSchema: There is no Schema registered to provide `test`
            
            We must add the schema to the registry first:
            
                >>> from jingle.schemas import registry, Schema
                >>> from formencode.validators import UnicodeString
                >>> class TestSchema(Schema):
                ...     behaviour = 'test'
                ...     title = UnicodeString(default=u'',
                ...                           not_empty=True)
                >>> page.add_behaviour('test')
                ['page', 'test']
            
            We can also pass some initial data in rather than having to make another call to update():
            
                >>> page2 = Page('test2')
                >>> page2.update('test', {'title':u'Page 2'}) # doctest: +ELLIPSIS
                {...}
                >>> 'test.title' in page2.properties
                False
                >>> page2.add_behaviour('test', {'title':u'Page 2'}) # doctest: +ELLIPSIS
                {...}
                >>> 'test.title' in page2.properties and page2.properties['test.title'] == u'Page 2'
                True
            
            
        """
        if key not in schemas.registry:
            raise schemas.InvalidSchema('There is no Schema registered to provide `%s`' % key)
        elif key not in self.behaviour:
            self._extra_behaviour.append(key)
            self._update_properties()
            if data is not None:
                return self.update(key, data, prefix)
        return self.behaviour
    
    def remove_behaviour(self, key, remove_properties=False):
        """ Removes additional behaviour.
            
            We can't remove behaviour that isn't there:
            
                >>> page = Page('test')
                >>> page.behaviour == page.remove_behaviour('test')
                True
            
            We also cannot delete default behaviour:
            
                >>> page.remove_behaviour('page')
                Traceback (most recent call last):
                ...
                Exception: Cannot remove default behaviour
            
            We can delete extra behaviour however:
            
                >>> from jingle.schemas import registry, Schema
                >>> from formencode.validators import UnicodeString
                >>> class TestSchema(Schema):
                ...     behaviour = 'test'
                ...     title = UnicodeString(default=u'',
                ...                           not_empty=True)
                >>> page.add_behaviour('test')
                ['page', 'test']
                >>> page.remove_behaviour('test')
                ['page']
            
            This will leave the schema values behind in the properties store
            in an attempt to userproof data deletion.
            
                >>> 'test.title' in page.properties
                True
            
            We can delete these values though:
            
                >>> page.remove_behaviour('test', remove_properties=True)
                ['page']
                >>> 'test.title' in page.properties
                False
            
        """
        if key in self._extra_behaviour:
            self._extra_behaviour.remove(key)
        elif key in self._default_behaviour:
            raise Exception('Cannot remove default behaviour')
        if remove_properties: # delete keys and values from the property store
            for k in self._properties.keys():
                if k.startswith('%s.' % key):
                    del self._properties[k]
            
        return self.behaviour
    
    ### Properties ###
    
    def _update_properties(self):
        for behaviour in self.behaviour:
            schema = schemas.registry.lookup(behaviour)
            for field, ob in schema.fields.items():
                key = '%s.%s' % (behaviour, field)
                if key not in self._properties.keys():
                    self._properties[key] = ob.default
    
    @property
    def properties(self):
        # really should move this to update events on self.extra_behaviour
        self._update_properties()
        return dict(self._properties)
    
    def update(self, key, data, prefix=''):
        if key not in self.behaviour:
            return dict(self._properties)
        schema = schemas.registry.lookup(key)
        formatted = schema.to_python(data, prefix=prefix)
        for k,v in formatted.items():
            self._properties['%s.%s' % (key, k)] = v
        return dict(self._properties)
    
    
    ### Navigation / Hierarchy ###
    
    def add_child(self, child):
        """ This method will process setting / syncing the __parent__ and children attributes
            
            Adding a child page should add a reference to the children attribute:
            
                >>> parent = Page('Parent')
                >>> child = Page('Child')
                >>> parent.add_child(child)
                [u'child']
                >>> child.__parent__ == parent.__name__
                True
            
            However, children must be Pages too:
            
                >>> parent.add_child(object())
                Traceback (most recent call last):
                ...
                TypeError: Children must be inherited from the Page class, not <type 'object'>
                
        """
        if not isinstance(child, Page):
            raise TypeError('Children must be inherited from the Page class, not %s' % str(type(child)))
        self.__children__.append(child.__name__)
        child.__parent__ = self.__name__
        return self.__children__
Ejemplo n.º 18
0
class PlominoDocument(CatalogAware, CMFBTreeFolder, Contained):
    """ These represent the contents in a Plomino database.

    A document contains *items*.
    An item may or may not correspond to fields on one or more forms.
    They may be manipulated by Formulas.
    """

    security = ClassSecurityInfo()
    implements(interfaces.IPlominoDocument, IAttributeAnnotatable)

    portal_type = "PlominoDocument"
    meta_type = "PlominoDocument"

    security.declarePublic('__init__')

    def __init__(self, id):
        """ Initialization
        """
        CMFBTreeFolder.__init__(self, id)
        self.id = id
        self.items = PersistentDict()
        self.plomino_modification_time = DateTime().toZone(TIMEZONE)

    security.declarePublic('checkBeforeOpenDocument')

    def checkBeforeOpenDocument(self):
        """ Check read permission and open view.

        .. NOTE:: if ``READ_PERMISSION`` is set on the ``view`` action
            itself, it causes an error ('maximum recursion depth exceeded')
            if user hasn't permission.
        """
        if self.isReader():
            return self.OpenDocument()
        else:
            raise Unauthorized, "You cannot read this content"

    def doc_path(self):
        return self.getPhysicalPath()

    def doc_url(self):
        """ Return valid and nice url:
        - hide plomino_documents
        - use physicalPathToURL if REQUEST available
        """
        path = self.doc_path()
        short_path = [p for p in path if p != "plomino_documents"]
        if hasattr(self, "REQUEST"):
            return self.REQUEST.physicalPathToURL(short_path)
        else:
            return "/".join(short_path)

    security.declarePublic('setItem')

    def setItem(self, name, value):
        """ Set item on document, converting str to unicode.
        """
        items = self.items
        if isinstance(value, str):
            db = self.getParentDatabase()
            translation_service = getToolByName(db, 'translation_service')
            value = translation_service.asunicodetype(value)
        items[name] = value
        self.items = items
        self.plomino_modification_time = DateTime().toZone(TIMEZONE)

    security.declarePublic('getItem')

    def getItem(self, name, default=''):
        """ Get item from document.
        """
        if self.items.has_key(name):
            return deepcopy(self.items[name])
        else:
            return default

    security.declarePublic('hasItem')

    def hasItem(self, name):
        """ Check if doc has item 'name'.
        """
        return self.items.has_key(name)

    security.declarePublic('removeItem')

    def removeItem(self, name):
        """ Delete item 'name', if it exists.
        """
        if self.items.has_key(name):
            items = self.items
            del items[name]
            self.items = items

    security.declarePublic('getItems')

    def getItems(self):
        """ Return all item names.
        """
        return self.items.keys()

    security.declarePublic('getItemClassname')

    def getItemClassname(self, name):
        """ Return class name of the item.
        """
        return self.getItem(name).__class__.__name__

    security.declarePublic('getLastModified')

    def getLastModified(self, asString=False):
        """ Return last modified date, setting it if absent.
        """
        if not hasattr(self, 'plomino_modification_time'):
            self.plomino_modification_time = self.bobobase_modification_time(
            ).toZone(TIMEZONE)
        if asString:
            return DateToString(self.plomino_modification_time,
                                db=self.getParentDatabase())
        else:
            return self.plomino_modification_time

    security.declarePublic('getRenderedItem')

    def getRenderedItem(self,
                        itemname,
                        form=None,
                        formid=None,
                        convertattachments=False):
        """ Return the item rendered according to the corresponding field.

        The form used can be, in order of precedence:
        - passed as the `form` parameter,
        - specified with the `formid` parameter and looked up,
        - looked up from the document.

        If no form or field is found, return the empty string.

        If `convertattachments` is True, then we assume that field
        attachments are text and append them to the rendered value.
        """
        db = self.getParentDatabase()
        result = ''
        if not form:
            if formid:
                form = db.getForm(formid)
            else:
                form = self.getForm()
        if form:
            field = form.getFormField(itemname)
            if field:
                result = field.getFieldRender(form, self, False)
                if (field.getFieldType() == 'ATTACHMENT'
                        and convertattachments):
                    result += ' ' + db.getIndex().convertFileToText(
                        self, itemname).decode('utf-8')
                    result = result.encode('utf-8')

        return result

    security.declarePublic('tojson')

    def tojson(self,
               REQUEST=None,
               item=None,
               formid=None,
               rendered=False,
               lastmodified=None):
        """ Return item value as JSON.

        Return all items if `item=None`.
        Values on the REQUEST overrides parameters.

        If the requested item corresponds to a field on the found form,
        the field value is returned. If not, it falls back to a plain item
        lookup on the document.

        `formid="None"` specifies plain item lookup.
        """
        # TODO: Don't always return the entire dataset: allow batching.

        if not self.isReader():
            raise Unauthorized, "You cannot read this content"

        datatables_format = False
        if REQUEST:
            REQUEST.RESPONSE.setHeader('content-type',
                                       'application/json; charset=utf-8')
            item = REQUEST.get('item', item)
            formid = REQUEST.get('formid', formid)
            lastmodified = REQUEST.get('lastmodified', lastmodified)
            rendered_str = REQUEST.get('rendered', None)
            if rendered_str:
                rendered = True
            datatables_format_str = REQUEST.get('datatables', None)
            if datatables_format_str:
                datatables_format = True
        if item:
            if formid == "None":
                form = None
            elif formid:
                form = self.getParentDatabase().getForm(formid)
            else:
                form = self.getForm()
            if form:
                field = form.getFormField(item)
                if field:
                    if field.getFieldType() == 'DATAGRID':
                        adapt = field.getSettings()
                        fieldvalue = adapt.getFieldValue(form,
                                                         doc=self,
                                                         request=REQUEST)
                        fieldvalue = adapt.rows(fieldvalue, rendered=rendered)
                    else:
                        if rendered:
                            fieldvalue = self.getRenderedItem(item, form)
                        else:
                            adapt = field.getSettings()
                            fieldvalue = adapt.getFieldValue(form,
                                                             doc=self,
                                                             request=REQUEST)
                else:
                    _logger.info("Failed to find %s on %s, "
                                 "fallback to getItem." % (item, form.id))
                    fieldvalue = self.getItem(item)
            else:
                fieldvalue = self.getItem(item)
            data = fieldvalue
        else:
            data = self.items.data

        if datatables_format:
            data = {
                'iTotalRecords': len(data),
                'iTotalDisplayRecords': len(data),
                'aaData': data
            }
        if lastmodified:
            data = {'lastmodified': self.getLastModified(), 'data': data}
        return json.dumps(data)

    security.declarePublic('computeItem')

    def computeItem(self,
                    itemname,
                    form=None,
                    formid=None,
                    store=True,
                    report=True):
        """ Return the value of named item according to the formula
        - of the field defined in the given form (default),
        - or the named `formid`,
        - or use the default doc form if no form found.
        Store the value in the doc (if `store=True`).
        (Pass `report` to `PlominoForm.computeFieldValue`.)
        """
        result = None
        if not form:
            if not formid:
                form = self.getForm()
            else:
                db = self.getParentDatabase()
                form = db.getForm(formid)
        if form:
            result = form.computeFieldValue(itemname, self, report=report)
            if store:
                # So this is a way to store the value of a DISPLAY field ..
                self.setItem(itemname, result)
        return result

    security.declarePublic('getPlominoReaders')

    def getPlominoReaders(self):
        """ Return list of readers; if none set, everyone can read.
        """
        if self.hasItem('Plomino_Readers'):
            return asList(self.getItem('Plomino_Readers'))
        else:
            return ['*']

    security.declarePublic('isReader')

    def isReader(self):
        """
        """
        return self.getParentDatabase().isCurrentUserReader(self)

    security.declarePublic('isAuthor')

    def isAuthor(self):
        """
        """
        return self.getParentDatabase().isCurrentUserAuthor(self)

    security.declareProtected(REMOVE_PERMISSION, 'delete')

    def delete(self, REQUEST=None):
        """ Delete the current doc; redirect to `returnurl` if available.
        """
        db = self.getParentDatabase()
        db.deleteDocument(self)
        if REQUEST:
            return_url = REQUEST.get('returnurl')
            if not return_url:
                return_url = db.absolute_url()
            REQUEST.RESPONSE.redirect(return_url)

    security.declareProtected(EDIT_PERMISSION, 'validation_errors')

    def validation_errors(self, REQUEST):
        """ Check submitted values.
        """
        db = self.getParentDatabase()
        form = db.getForm(REQUEST.get('Form'))
        errors = form.validateInputs(REQUEST, doc=self)
        if errors:
            return self.errors_json(errors=json.dumps({
                'success': False,
                'errors': errors
            }))
        else:
            return self.errors_json(errors=json.dumps({'success': True}))

    security.declareProtected(EDIT_PERMISSION, 'saveDocument')

    def saveDocument(self, REQUEST, creation=False):
        """ Save a document using the form submitted content
        """
        db = self.getParentDatabase()
        form = db.getForm(REQUEST.get('Form'))

        errors = form.validateInputs(REQUEST, doc=self)

        # execute the beforeSave code of the form
        error = None
        try:
            error = self.runFormulaScript(
                SCRIPT_ID_DELIMITER.join(['form', form.id, 'beforesave']),
                self, form.getBeforeSaveDocument)
        except PlominoScriptException, e:
            e.reportError('Form submitted, but beforeSave formula failed')

        if error:
            errors.append(error)

        # if errors, stop here, and notify errors to user
        if errors:
            return form.notifyErrors(errors)

        self.setItem('Form', form.getFormName())

        # process editable fields (we read the submitted value in the request)
        form.readInputs(self, REQUEST, process_attachments=True)

        # refresh computed values, run onSave, reindex
        self.save(form, creation)

        redirect = REQUEST.get('plominoredirecturl')
        if not redirect:
            redirect = self.getItem("plominoredirecturl")
        if type(redirect) is dict:
            # if dict, we assume it contains "callback" as an URL that will be
            # called asynchronously, "redirect" as the redirect url (optional,
            # default=doc url), and "method" (optional, default=GET)
            redirect = "./async_callback?" + urlencode(redirect)
        if not redirect:
            redirect = self.absolute_url()
        REQUEST.RESPONSE.redirect(redirect)
Ejemplo n.º 19
0
class RoleProtectedObject(Persistent, Contained):
    """Base class for object protected by roles"""

    inherit_parent_security = FieldProperty(
        IRoleProtectedObject['inherit_parent_security'])
    everyone_denied = FieldProperty(IRoleProtectedObject['everyone_denied'])
    everyone_granted = FieldProperty(IRoleProtectedObject['everyone_granted'])
    authenticated_denied = FieldProperty(
        IRoleProtectedObject['authenticated_denied'])
    authenticated_granted = FieldProperty(
        IRoleProtectedObject['authenticated_granted'])
    inherit_parent_roles = FieldProperty(
        IRoleProtectedObject['inherit_parent_roles'])

    def __init__(self):
        self._principals_by_role = PersistentDict()
        self._roles_by_principal = PersistentDict()

    def get_everyone_denied(self):
        """Get permissions denied to everyone"""
        permissions = self.everyone_denied or set()
        if self.inherit_parent_security:
            for parent in lineage(self):
                if parent in (self, self.__parent__):
                    continue
                protection = IProtectedObject(parent, None)
                if protection is not None:
                    permissions = permissions | (protection.everyone_denied
                                                 or set())
        return permissions

    def get_everyone_granted(self):
        """Get permissions granted to everyone"""
        permissions = self.everyone_granted or set()
        if self.inherit_parent_security:
            for parent in lineage(self):
                if parent in (self, self.__parent__):
                    continue
                protection = IProtectedObject(parent, None)
                if protection is not None:
                    permissions = permissions | (protection.everyone_granted
                                                 or set())
        return permissions

    def get_authenticated_denied(self):
        """Get permissions denied to authenticated users"""
        permissions = self.authenticated_denied or set()
        if self.inherit_parent_security:
            for parent in lineage(self):
                if parent in (self, self.__parent__):
                    continue
                protection = IProtectedObject(parent, None)
                if protection is not None:
                    permissions = permissions | (
                        protection.authenticated_denied or set())
        return permissions

    def get_authenticated_granted(self):
        """Get permissions granted to authenticated users"""
        permissions = self.authenticated_granted or set()
        if self.inherit_parent_security:
            for parent in lineage(self):
                if parent in (self, self.__parent__):
                    continue
                protection = IProtectedObject(parent, None)
                if protection is not None:
                    permissions = permissions | (
                        protection.authenticated_granted or set())
        return permissions

    def grant_role(self, role_id, principal_ids):
        """Grant role to selected principals"""
        registry = get_pyramid_registry()
        if IRole.providedBy(role_id):
            role_id = role_id.id
        if isinstance(principal_ids, str):
            principal_ids = {principal_ids}
        role_principals = self._principals_by_role.get(role_id) or set()
        for principal_id in principal_ids:
            if IPrincipalInfo.providedBy(principal_id):
                principal_id = principal_id.id
            if principal_id not in role_principals:
                principal_roles = self._roles_by_principal.get(
                    principal_id) or set()
                role_principals.add(principal_id)
                principal_roles.add(role_id)
                self._roles_by_principal[principal_id] = principal_roles
                self._principals_by_role[role_id] = role_principals
                registry.notify(GrantedRoleEvent(self, role_id, principal_id))

    def revoke_role(self, role_id, principal_ids):
        """Revoke role to selected principals"""
        registry = get_pyramid_registry()
        if IRole.providedBy(role_id):
            role_id = role_id.id
        if isinstance(principal_ids, str):
            principal_ids = {principal_ids}
        role_principals = self._principals_by_role.get(role_id) or set()
        for principal_id in principal_ids.copy():
            if IPrincipalInfo.providedBy(principal_id):
                principal_id = principal_id.id
            if principal_id in role_principals:
                principal_roles = self._roles_by_principal.get(
                    principal_id) or set()
                if principal_id in role_principals:
                    role_principals.remove(principal_id)
                if role_id in principal_roles:
                    principal_roles.remove(role_id)
                if principal_roles:
                    self._roles_by_principal[principal_id] = principal_roles
                elif principal_id in self._roles_by_principal:
                    del self._roles_by_principal[principal_id]
                if role_principals:
                    self._principals_by_role[role_id] = role_principals
                elif role_id in self._principals_by_role:
                    del self._principals_by_role[role_id]
                registry.notify(RevokedRoleEvent(self, role_id, principal_id))

    def get_principals(self, role_id):
        """Get principals which have selected role granted"""
        if IRole.providedBy(role_id):
            role_id = role_id.id
        return self._principals_by_role.get(role_id) or set()

    def get_roles(self, principal_id):
        """Get roles for given principal"""
        if IPrincipalInfo.providedBy(principal_id):
            principal_id = principal_id.id
        return self._roles_by_principal.get(principal_id) or set()

    def get_permissions(self, principal_id):
        """Get permissions for given principal"""
        registry = get_pyramid_registry()
        result = set()
        for role_id in self.get_roles(principal_id):
            role = registry.queryUtility(IRole, role_id)
            result |= role.permissions or set()
        return result

    def get_granted_roles(self):
        """Get granted roles on current context or parents"""
        roles = set(self._principals_by_role.keys())
        if self.inherit_parent_roles:
            for parent in lineage(self):
                if parent in (self, self.__parent__):
                    continue
                protection = IProtectedObject(parent, None)
                if protection is not None:
                    roles = roles | protection.get_granted_roles()
        return roles

    @request_property(key=None)
    def __acl__(self):
        """Get ACL for current context

        The result is stored into current request annotations, so it's not supposed to change
        during request lifetime.
        """
        # always grant all permissions to system manager
        # and 'public' permission to everyone
        result = [(Allow, ADMIN_USER_ID, ALL_PERMISSIONS),
                  (Allow, Everyone, {PUBLIC_PERMISSION})]
        # grant access to all roles permissions
        for role_id in self.get_granted_roles():
            role = query_utility(IRole, role_id)
            if role is not None:
                result.append(
                    (Allow, ROLE_ID.format(role_id), role.permissions))
        # add denied permissions to everyone and authenticated
        permissions = self.get_everyone_denied()
        if permissions:
            result.append((Deny, Everyone, permissions))
        permissions = self.get_authenticated_denied()
        if permissions:
            result.append((Deny, Authenticated, permissions))
        # add allowed permissions to everyone and authenticated
        permissions = self.get_authenticated_granted()
        if permissions:
            result.append((Allow, Authenticated, permissions))
        permissions = self.get_everyone_granted()
        if permissions:
            result.append((Allow, Everyone, permissions))
        # deny all parent permissions if inheritance is disabled
        if not self.inherit_parent_security:
            result.append(DENY_ALL)
        LOGGER.debug('ACL({0!r}) = {1}'.format(self.__parent__, str(result)))
        return result
Ejemplo n.º 20
0
class VideoContainer(PersistentMapping):
    """ A simple container for Video objects
        
        >>> from mint.repoze.interfaces import IVideoContainer
        >>> from mint.repoze.models import VideoContainer, Video
        >>> ob = VideoContainer()
        >>> IVideoContainer.providedBy(ob)
        True
        >>> len(ob)
        0
        >>> ob[u'vid1'] = Video('vid1', 'Video 1', 'description', [])
        >>> len(ob)
        1
        >>> ob.keys()
        [u'vid1']
        
    """
    __acl__ = [
            (Allow, Everyone, 'view'),
            (Allow, 'admin', 'add'),
            (Allow, 'admin', 'edit'),
            ]
    
    implements(IVideoContainer,ILocation)
    
    encode_dir = 'var/videos/'
    
    def __init__(self, *args, **kwargs):
        self.data = PersistentDict()
        for data in args:
            self.add_video(*data)
        for v in kwargs.values():
            pass
    
    def __getitem__(self, key):
        return self.data.__getitem__(key)
    
    def __setitem__(self, key, value):
        return self.data.__setitem__(key, value)
    
    def items(self):
        return self.data.items()
    
    def keys(self):
        return self.data.keys()
    
    def values(self):
        return self.data.values()
    
    def __repr__(self):
        return u'<VideoContainer object>'
    
    def add_video(self, name, description, tags, encodes={}):
        uid = name.lower().replace(' ', '_')
        counter = 1
        while uid in self:
            uid = '%s_%03d' % (uid, counter)
            counter += 1
        self.data[uid] = Video(uid, name, description, tags, encodes, self.encode_dir)
        import transaction
        transaction.commit()
    
    def get_videos_by_tag(self, tag):
        """ Returns a list of video objects with the given tag
            >>> from mint.repoze.test.data import video_container
            >>> video_container.get_videos_by_tag('feature') # doctest: +ELLIPSIS
            [<Video name=...]
        """
        return [video for video in self.data.values() if tag in video.tags]
class RegistrationApproval(PloneBaseTool, UniqueObject, SimpleItem):
    implements(IRegistrationApproval)

    id = 'wcc_minisites_registration_approval'
    meta_type = 'WCC Minisite Approval Tool'
    toolicon = 'skins/plone_images/site_icon.png'
    security = ClassSecurityInfo()

    def __init__(self):
        self._data = PersistentDict()

    def is_memberid_allowed(self, key):
        return not (key in self._data.keys())

    def values(self):
        for x in self._data.values():
            if not x.has_key('username'):
                x['username'] = x['email']
        return sorted(self._data.values(), key=(lambda x: x['username']))

    def add(self, key, data):
        if key in self._data.keys():
            raise ConflictError(u'User already exist in pending')
        data['username'] = key
        self._data[key] = data
        notify(UserRegisteredEvent(data))

    def get(self, key):
        return self._data[key]

    def approve(self, key):
        if key not in self._data.keys():
            raise KeyError(key)

        portal = getSite()
        registration = getToolByName(self, 'portal_registration')
        portal_props = getToolByName(self, 'portal_properties')
        mt = getToolByName(self, 'portal_membership')
        props = portal_props.site_properties
        use_email_as_login = props.getProperty('use_email_as_login')

        data = self._data[key]

        if use_email_as_login:
            data['username'] = data['email']

        user_id = data['username']
        password = registration.generatePassword()
        request = getRequest()
        try:
            registration.addMember(user_id, password, REQUEST=request)
        except (AttributeError, ValueError), err:
            logging.exception(err)
            IStatusMessage(request).addStatusMessage(err, type="error")
            return

        # set additional properties using the user schema adapter
        schema = getUtility(IUserDataSchemaProvider).getSchema()

        adapter = getAdapter(portal, schema)
        adapter.context = mt.getMemberById(user_id)

        for name in getFieldNamesInOrder(schema):
            if name in data:
                setattr(adapter, name, data[name])

        notify(UserApprovedEvent(data))
        del self._data[key]
Ejemplo n.º 22
0
class Taxonomy(SimpleItem):
    implements(ITaxonomy)

    def __init__(self, name, title, default_language):
        super(Taxonomy, self).__init__(self)
        self.data = PersistentDict()
        self.name = name
        self.title = title
        self.default_language = default_language

    def __call__(self, context):
        request = getattr(context, "REQUEST", None)

        current_language = self.getCurrentLanguage(request)
        data = self.data[current_language]
        inverted_data = self.inverted_data[current_language]

        return Vocabulary(self.name, data, inverted_data)

    @property
    @ram.cache(lambda method, self: (self.name, self.data._p_mtime))
    def inverted_data(self):
        inv_data = {}
        for (language, elements) in self.data.items():
            inv_data[language] = {}
            for (path, identifier) in elements.items():
                inv_data[language][identifier] = path
        return inv_data

    def getShortName(self):
        return self.name.split('.')[-1]

    def getGeneratedName(self):
        return 'collective.taxonomy.generated.' + self.getShortName()

    def getVocabularyName(self):
        return 'collective.taxonomy.' + self.getShortName()

    def getCurrentLanguage(self, request):
        try:
            portal_state = getMultiAdapter((self, request),
                                           name=u'plone_portal_state')

            language = portal_state.language().split('-', 1)[0]
        except ComponentLookupError:
            language = ''  # Force to return default language.

        if language in self.data:
            return language
        elif self.default_language in self.data:
            return self.default_language
        else:
            # our best guess!
            return self.data.keys()[0]

    def registerBehavior(self, **kwargs):
        context = getSite()
        sm = context.getSiteManager()
        new_args = copy(kwargs)

        new_args['name'] = self.name
        new_args['title'] = self.title
        new_args['description'] = kwargs['field_description']

        behavior = TaxonomyBehavior(**new_args)
        sm.registerUtility(behavior, IBehavior, name=self.getGeneratedName())

        behavior.addIndex()
        behavior.activateSearchable()

    def cleanupFTI(self):
        """Cleanup the FTIs"""
        generated_name = self.getGeneratedName()
        context = getSite()
        sm = context.getSiteManager()
        for (name, fti) in sm.getUtilitiesFor(IDexterityFTI):
            if generated_name in fti.behaviors:
                fti.behaviors = [
                    behavior for behavior in fti.behaviors
                    if behavior != generated_name
                ]
            modified(fti, DexterityFTIModificationDescription("behaviors", ''))

    def updateBehavior(self, **kwargs):
        sm = getSite().getSiteManager()

        behavior_name = self.getGeneratedName()
        short_name = self.getShortName()

        utility = sm.queryUtility(IBehavior, name=behavior_name)
        if utility:
            utility.deactivateSearchable()
            utility.activateSearchable()

        delattr(generated, short_name)

        for (name, fti) in sm.getUtilitiesFor(IDexterityFTI):
            if behavior_name in fti.behaviors:
                modified(fti,
                         DexterityFTIModificationDescription("behaviors", ''))

    def unregisterBehavior(self):
        context = getSite()
        sm = context.getSiteManager()
        behavior_name = self.getGeneratedName()
        utility = sm.queryUtility(IBehavior, name=behavior_name)

        if utility is None:
            return

        self.cleanupFTI()

        utility.removeIndex()
        utility.deactivateSearchable()
        utility.unregisterInterface()

        sm.unregisterUtility(utility, IBehavior, name=behavior_name)

    def clean(self):
        self.data.clear()

    def add(self, language, identifier, path):
        if not language in self.data:
            self.data[language] = OOBTree()

        self.data[language][path] = identifier

    def translate(self,
                  msgid,
                  mapping=None,
                  context=None,
                  target_language=None,
                  default=None):

        if target_language is None or \
                target_language not in self.inverted_data:
            target_language = str(
                self.getCurrentLanguage(getattr(context, 'REQUEST')))

        if msgid not in self.inverted_data[target_language]:
            return ''

        path = self.inverted_data[target_language][msgid]
        #we may have non-ascii now
        if not isinstance(path, unicode):
            path = path.decode('utf-8')
        pretty_path = path[1:].replace('/', u' » ')

        return pretty_path