def add(self, fd):
     """Add field description to the container."""
     chooser = INameChooser(self.context)
     name = chooser.chooseName(fd.name, fd)
     self.context[name] = fd
     return fd
Exemple #2
0
def ical_import(container,
                ics_resource,
                event_type,
                sync_strategy=base.SYNC_KEEP_NEWER):
    cal = icalendar.Calendar.from_ical(ics_resource)
    events = cal.walk('VEVENT')

    cat = getToolByName(container, 'portal_catalog')
    container_path = '/'.join(container.getPhysicalPath())

    def _get_by_sync_uid(uid):
        return cat(sync_uid=uid, path={'query': container_path, 'depth': 1})

    def _get_prop(prop, item, default=None):
        ret = default
        if prop in item:
            ret = safe_unicode(item.decoded(prop))
        return ret

    def _from_list(ical, prop):
        """For EXDATE and RDATE recurrence component properties, the dates can
        be defined within one EXDATE/RDATE line or for each date an individual
        line.
        In the latter case, icalendar creates a list.
        This method handles this case.

        TODO: component property parameters like TZID are not used here.
        """
        val = ical[prop] if prop in ical else []
        if not isinstance(val, list):
            val = [val]

        # Zip multiple lines into one, since jquery.recurrenceinput.js does
        # not support multiple lines here
        # https://github.com/collective/jquery.recurrenceinput.js/issues/15
        ret = ''
        for item in val:
            ret = '%s,' % ret if ret else ret  # insert linebreak
            ret = '%s%s' % (ret, item.to_ical())
        return '%s:%s' % (prop, ret) if ret else None

    count = 0
    for item in events:
        start = _get_prop('DTSTART', item)
        end = _get_prop('DTEND', item)
        if not end:
            duration = _get_prop('DURATION', item)
            if duration:
                end = start + duration
            # else: whole day or open end

        whole_day = False
        open_end = False
        if is_date(start) and (is_date(end) or end is None):
            # All day / whole day events
            # End must be same type as start (RFC5545, 3.8.2.2)
            whole_day = True
            if end is None:
                end = start
            if start < end:
                # RFC5545 doesn't define clearly, if all day events should have
                # a end date one day after the start day at 0:00.
                # Internally, we handle all day events with start=0:00,
                # end=:23:59:59, so we substract one day here.
                end = end - datetime.timedelta(days=1)
            start = base.dt_start_of_day(date_to_datetime(start))
            end = base.dt_end_of_day(date_to_datetime(end))
        elif is_datetime(start) and end is None:
            # Open end event, see RFC 5545, 3.6.1
            open_end = True
            end = base.dt_end_of_day(date_to_datetime(start))
        assert (is_datetime(start))
        assert (is_datetime(end))

        # Set timezone, if not already set
        tz = base.default_timezone(container, as_tzinfo=True)
        if not getattr(start, 'tzinfo', False):
            start = tz.localize(start)
        if not getattr(end, 'tzinfo', False):
            end = tz.localize(end)

        title = _get_prop('SUMMARY', item)
        description = _get_prop('DESCRIPTION', item)
        location = _get_prop('LOCATION', item)

        url = _get_prop('URL', item)

        rrule = _get_prop('RRULE', item)
        rrule = 'RRULE:%s' % rrule.to_ical() if rrule else ''
        rdates = _from_list(item, 'RDATE')
        exdates = _from_list(item, 'EXDATE')
        rrule = '\n'.join([it for it in [rrule, rdates, exdates] if it])

        # TODO: attendee-lists are not decoded properly and contain only
        # vCalAddress values
        attendees = item.get('ATTENDEE', ())

        contact = _get_prop('CONTACT', item)
        categories = item.get('CATEGORIES', ())
        if getattr(categories, '__iter__', False):
            categories = tuple([safe_unicode(it) for it in categories])

        ext_modified = utc(_get_prop('LAST-MODIFIED', item))

        content = None
        new_content_id = None
        existing_event = None
        sync_uid = _get_prop('UID', item)
        if sync_uid and sync_strategy is not base.SYNC_NONE:
            existing_event = _get_by_sync_uid(sync_uid)
        if existing_event:
            if sync_strategy == base.SYNC_KEEP_MINE:
                # On conflict, keep mine
                continue

            exist_event = existing_event[0].getObject()
            acc = IEventAccessor(exist_event)

            if sync_strategy == base.SYNC_KEEP_NEWER and\
                    (not ext_modified or acc.last_modified > ext_modified):
                # Update only if modified date was passed in and it is not
                # older than the current modified date.  The client is not
                # expected to update the "last-modified" property, it is the
                # job of the server (calendar store) to keep it up to date.
                # This makes sure the client did the change on an up-to-date
                # version of the object.  See
                # http://tools.ietf.org/search/rfc5545#section-3.8.7.3
                continue

            # Else: update
            content = exist_event
        else:
            new_content_id = str(random.randint(0, 99999999))
            container.invokeFactory(event_type,
                                    id=new_content_id,
                                    title=title,
                                    description=description)
            content = container[new_content_id]

        assert (content)  # At this point, a content must be available.

        event = IEventAccessor(content)
        event.title = title
        event.description = description
        event.start = start
        event.end = end
        event.whole_day = whole_day
        event.open_end = open_end
        event.location = location
        event.event_url = url
        event.recurrence = rrule
        event.attendees = attendees
        event.contact_name = contact
        event.subjects = categories
        if sync_uid and sync_strategy is not base.SYNC_NONE:
            # Set the external sync_uid for sync strategies other than
            # SYNC_NONE.
            event.sync_uid = sync_uid
        notify(ObjectModifiedEvent(content))

        # Use commits instead of savepoints to avoid "FileStorageError:
        # description too long" on large imports.
        transaction.get().commit()  # Commit before rename

        if new_content_id and new_content_id in container:
            # Rename with new id from title, if processForm didn't do it.
            chooser = INameChooser(container)
            new_id = chooser.chooseName(title, content)
            content.aq_parent.manage_renameObject(new_content_id, new_id)

        # Do this at the end, otherwise it's overwritten
        if ext_modified:
            event.last_modified = ext_modified

        count += 1

    return {'count': count}
Exemple #3
0
 def add(self, term):
     """Add `term` to the container."""
     chooser = INameChooser(self.context)
     name = chooser.chooseName("", term)
     self.context[name] = term
     return term
    def upload(self, files, title='', description=''):

        if not self.doc.isDocument():
            return

        #import pdb;pdb.set_trace()

        overwrite = True

        current_files = self.doc.getItem(self.fieldName, {})
        if not current_files:
            current_files = dict()

        #Utile ma pericoloso: se cambio da multi a single elimino tutti i file.. da vedere
        # if not self.multi:
        #     for fileId in current_files.keys():
        #         self.doc.deletefile(fileId)

        if not isinstance(files, list):
            files = [files]

        namechooser = INameChooser(self.doc)
        info = {
            'name': 'File-Name.jpg',
            'title': '',
            'description': '',
            'size': 999999,
            'url': '@@getattachment?',
            'thumbnail_url': '//nohost.org',
            'delete_url': '//nohost.org',
            'delete_type': 'DELETE',
            'field_name': self.fieldName
        }

        results = []

        for item in files:
            if item.filename:

                #            if overwrite and filename in self.objectIds():
                #                self.doc.deletefile(filename)

                contenttype = item.headers.get('Content-Type')
                filename = safe_unicode(item.filename)
                data = item.read()
                id_name = ''
                title = title and title[0] or filename
                #non usata
                description = description and description[0] or ''

                # Get a unique id here
                id_name = namechooser.chooseName(title, self.doc)

                info["name"] = id_name
                info["title"] = title
                info["description"] = description
                info["thumbnail_url"] = self.getIcon(contenttype)
                info["content_type"] = contenttype

                try:
                    blob = BlobWrapper(contenttype)
                except:  # XXX Except what?
                    # BEFORE PLONE 4.0.1
                    blob = BlobWrapper()

                file_obj = blob.getBlob().open('w')
                file_obj.write(data)
                file_obj.close()
                blob.setFilename(id_name)
                blob.setContentType(contenttype)
                info['size'] = blob.get_size()
                self.doc._setObject(id_name, blob)
                results.append(info)

                if self.settings.widget == 'MULTI':
                    current_files[id_name] = contenttype
                    self.doc.setItem(self.fieldName, current_files)
                else:
                    self.doc.setItem(self.fieldName, {id_name: contenttype})

            if results:
                return results
            return False
Exemple #5
0
 def add(self, content):
     """Add the rule to the context
     """
     storage = getUtility(IRuleStorage)
     chooser = INameChooser(storage)
     storage[chooser.chooseName(None, content)] = content
Exemple #6
0
 def add(self, **data):
     officelocation = OfficeLocation(**data)
     name = INameChooser(self.context).chooseName(u'', officelocation)
     self.context[name] = officelocation
     self.redirect(self.url(self.context))
Exemple #7
0
 def add(self, level):
     container = self.getContent()
     name = INameChooser(container).chooseName('', level)
     container[name] = level
Exemple #8
0
    def _initAssignmentNode(self, node):
        """Create an assignment from a node
        """
        site = self.environ.getSite()

        # 1. Determine the assignment mapping and the name
        manager = node.getAttribute('manager')
        category = node.getAttribute('category')
        key = node.getAttribute('key')
        # convert unicode to str as unicode paths are not allowed in
        # restrictedTraverse called in assignment_mapping_from_key
        key = key.encode()

        purge = False
        if node.hasAttribute('purge'):
            purge = self._convertToBoolean(node.getAttribute('purge'))

        mapping = assignment_mapping_from_key(site,
                                              manager,
                                              category,
                                              key,
                                              create=True)

        # 2. Either find or create the assignment

        assignment = None
        name = node.getAttribute('name')
        if name:
            name = str(name)
            assignment = mapping.get(name, None)

        __traceback_info__ = "Assignment name: " + name

        if node.hasAttribute('remove'):
            if assignment is not None:
                del mapping[name]
            return

        if purge:
            for portlet in mapping.keys():
                del mapping[portlet]
            return

        type_ = str(node.getAttribute('type'))

        if assignment is None:
            portlet_factory = getUtility(IFactory, name=type_)
            assignment = portlet_factory()

            if not name:
                chooser = INameChooser(mapping)
                name = chooser.chooseName(None, assignment)

            mapping[name] = assignment

        # aq-wrap it so that complex fields will work
        assignment = assignment.__of__(site)

        # set visibility setting
        visible = node.getAttribute('visible')
        if visible:
            settings = IPortletAssignmentSettings(assignment)
            settings['visible'] = self._convertToBoolean(visible)

        # 3. Use an adapter to update the portlet settings

        portlet_interface = getUtility(IPortletTypeInterface, name=type_)
        assignment_handler = IPortletAssignmentExportImportHandler(assignment)
        assignment_handler.import_assignment(portlet_interface, node)

        # 4. Handle ordering

        insert_before = node.getAttribute('insert-before')
        if insert_before:
            position = None
            keys = list(mapping.keys())

            if insert_before == "*":
                position = 0
            elif insert_before in keys:
                position = keys.index(insert_before)

            if position is not None:
                keys.remove(name)
                keys.insert(position, name)
                mapping.updateOrder(keys)
    def __getattribute__(self, name):
        if name.startswith('_') or name.startswith(
                'portal_') or name.startswith(
                    '@@') or name == 'sql_id' or name in SpecificAttrs:
            return super(SQLDexterityItem, self).__getattribute__(name)
        connection = queryUtility(ISQLConnectionsUtility,
                                  name=self.portal_type,
                                  default=None)
        if connection == None and self.portal_type:
            fti = queryUtility(IDexterityFTI,
                               name=self.portal_type,
                               default=None)
            if not fti:
                return None
            updateConnectionsForFti(fti)
            connection = queryUtility(ISQLConnectionsUtility,
                                      name=self.portal_type,
                                      default=None)
        if name == 'view':
            #be sure session and sqlitem are up to date
            self._v_sql_item = None
            connection.session.close()
        if not connection:
            return super(SQLDexterityItem, self).__getattribute__(name)
        if name == 'UID' and self.sql_virtual:
            return self.portal_type + '-' + connection.sql_table + '-' + str(
                self.sql_id)
        if name == 'id' and 'id' not in connection.fieldnames.keys():
            if not self.sql_virtual:
                return super(SQLDexterityItem, self).__getattribute__(name)
            fti = ISQLTypeSettings(
                getUtility(IDexterityFTI, name=self.portal_type))
            nameFromTitle = INameFromTitle(self, None)
            if nameFromTitle is not None and nameFromTitle.title:
                sql_folder_id = getattr(fti, 'sql_folder_id',
                                        'data-' + self.portal_type)
                title = nameFromTitle.title
                folder = None
                if IRelationValue.providedBy(sql_folder_id):
                    folder = sql_folder_id.to_object
                elif sql_folder_id and sql_folder_id.startswith('/'):
                    portal = getToolByName(getSite(),
                                           'portal_url').getPortalObject()
                    folder = portal.restrictedTraverse(sql_folder_id)
                if folder:
                    name = INameChooser(folder).chooseName(title, self)
                    return name
#                return INameChooser(getSite()).chooseName(title, self)
#                return getUtility(IURLNormalizer).normalize(title)
                return self.sql_id
        if name in connection.fieldnames.keys():
            sql_column = connection.fieldnames[name]
            sql_item = self.getSQLItem()
            try:
                sql_id = getattr(sql_item, connection.sql_id_column, None)
            except orm_exc.DetachedInstanceError:
                self._v_sql_item = None
                sql_item = self.getSQLItem()
                sql_id = getattr(sql_item, connection.sql_id_column, None)
            fieldname = 'name'
            if sql_item and sql_column:
                while '.' in sql_column:
                    sql_key = sql_column.split('.')[0]
                    sql_item = getattr(sql_item, sql_key, None)
                    if isinstance(sql_item, list):
                        value = sql_item
                        fieldname = sql_column.split('.')[-1]
                        break
                    sql_column = '.'.join(sql_column.split('.')[1:])
                else:
                    if not isinstance(sql_item, list):
                        value = getattr(sql_item, sql_column, None)
                if not value and (isinstance(value, list)
                                  or hasattr(value, '_sa_instance_state')):
                    value = ''
                elif (isinstance(value, list)
                      or hasattr(value, '_sa_instance_state')):
                    sqlftis = [
                        a for a in getAllUtilitiesRegisteredFor(IDexterityFTI)
                        if
                        'collective.behavior.sql.behavior.behaviors.ISQLContent'
                        in a.behaviors and getattr(a, 'sql_table', None)
                    ]
                    if name == 'subject':
                        return tuple(
                            [getattr(a, fieldname, '') for a in value])
                    tableftis = []
                    for iface in iterSchemataForType(self.portal_type):
                        if name in iface.names():
                            field = iface[name]
                            if IRelationChoice.providedBy(
                                    field) or IRelationList.providedBy(field):
                                if IRelationChoice.providedBy(field):
                                    allowed_types = field.source.query.get(
                                        'portal_type', [])
                                else:
                                    allowed_types = field.value_type.source.query.get(
                                        'portal_type', [])
                                tableftis = []
                                for sqlfti in sqlftis:
                                    adapted = ISQLTypeSettings(sqlfti, None)
                                    if isinstance(value, list):
                                        classname = value[0].__class__.__name__
                                    else:
                                        classname = value.__class__.__name__
                                    if adapted and getattr(
                                            adapted, 'sql_table',
                                            None) == classname:
                                        if not allowed_types or sqlfti.id in allowed_types:
                                            tableftis.append(adapted)
                                catalog = getToolByName(
                                    getSite(), 'portal_catalog')
                                relations = []
                                for tablefti in tableftis:
                                    sql_id_column = getattr(
                                        tablefti, 'sql_id_column', 'id')
                                    valueids = []
                                    if isinstance(value, list):
                                        valueids = [
                                            getattr(a, sql_id_column, None)
                                            for a in value
                                            if getattr(a, sql_id_column, None)
                                        ]
                                    else:
                                        valueids = getattr(
                                            value, sql_id_column, None)
                                    valueids = [str(a) for a in valueids]
                                    brains = catalog.unrestrictedSearchResults(
                                        portal_type=tablefti.id,
                                        sql_id=valueids)
                                    for brain in brains:
                                        relations.append(
                                            SQLRelationValue(
                                                brain.portal_type, brain.UID,
                                                self))
                                if IRelationChoice.providedBy(
                                        field) and relations:
                                    return relations[0]
                                elif IRelationList.providedBy(
                                        field) and relations:
                                    return relations
                            elif ITuple.providedBy(field):
                                return tuple(
                                    [getattr(a, fieldname, '') for a in value])
                            elif IList.providedBy(field):
                                return [
                                    getattr(a, fieldname, '') for a in value
                                ]
                            elif value and isinstance(value, list):
                                value = getattr(value[0], fieldname, '')
                for iface in iterSchemataForType(self.portal_type):
                    if name == 'subject':
                        try:
                            return tuple([
                                a.decode('utf-8') for a in literal_eval(value)
                            ])
                        except:
                            return tuple([a.strip() for a in value.split(',')])
                    if name in iface.names():
                        field = iface[name]
                        if IRichText.providedBy(field):
                            if not value:
                                value = ''
                            if not '<p' in value or not '<br' in value:
                                value = '<p>' + '</p><p>'.join([
                                    a for a in value.split('\n') if a.strip()
                                ]) + '</p>'


#                            try:
#                                value = str(value)
#                            except:
#                                try:
#                                    value = value.decode('utf-8')
#                                except:
#                                    try:
#                                        value = value.encode('utf-8')
#                                    except:
#                                        pass
                            return RichTextValue(unidecode(value))
                        elif INamedBlobImage.providedBy(field):
                            return NamedBlobImage(
                                base64.b64decode(value),
                                filename=unicode(self.portal_type + self.id +
                                                 ".jpg"))
                        elif ITuple.providedBy(field):
                            if not value:
                                return tuple([])
                            try:
                                return tuple([
                                    a.decode('utf-8')
                                    for a in literal_eval(value)
                                ])
                            except:
                                return tuple(
                                    [a.strip() for a in value.split(',')])
                        elif IList.providedBy(field):
                            if not value:
                                return []
                            try:
                                return [
                                    a.decode('utf-8')
                                    for a in literal_eval(value)
                                ]
                            except:
                                return [a.strip() for a in value.split(',')]
                        elif IDatetime.providedBy(field) and hasattr(
                                value, 'day') and not hasattr(value, 'hour'):
                            value = datetime.datetime.combine(
                                value, datetime.datetime.min.time())
                if name in [
                        'expiration_date', 'effective_date', 'effective',
                        'expires'
                ] and hasattr(value, 'day') and not hasattr(value, 'hour'):
                    value = datetime.datetime.combine(
                        value, datetime.datetime.min.time())
                if isinstance(value, unicode) or name == 'id':
                    try:
                        value = str(value)
                    except:
                        pass
                return value
        return super(SQLDexterityItem, self).__getattribute__(name)
    def __getattribute__(self, name):
        if name.startswith('_') or name.startswith(
                'portal_') or name.startswith('@@'):
            return super(SQLDexterityItem, self).__getattribute__(name)
        if name == 'id' and not self.sql_virtual:
            return super(SQLDexterityItem, self).__getattribute__(name)
        connection = queryUtility(ISQLConnectionsUtility,
                                  name=self.portal_type,
                                  default=None)
        if connection == None and self.portal_type:
            fti = queryUtility(IDexterityFTI,
                               name=self.portal_type,
                               default=None)
            if not fti:
                return None
            updateConnectionsForFti(fti)
            connection = queryUtility(ISQLConnectionsUtility,
                                      name=self.portal_type,
                                      default=None)
        if not connection:
            return super(SQLDexterityItem, self).__getattribute__(name)
        if name == 'UID':
            return self.portal_type + '-' + connection.sql_table + '-' + str(
                self.sql_id)
        if name == 'id' and 'id' not in connection.fieldnames.keys():
            fti = ISQLTypeSettings(
                getUtility(IDexterityFTI, name=self.portal_type))
            nameFromTitle = INameFromTitle(self, None)
            if nameFromTitle is not None and nameFromTitle.title:
                sql_folder_id = getattr(fti, 'sql_folder_id',
                                        'data-' + self.portal_type)
                title = nameFromTitle.title
                if IRelationValue.providedBy(name):
                    folder = sql_folder_id.to_object
                    if folder:
                        return INameChooser(folder).chooseName(title, self)
                return INameChooser(getSite()).chooseName(title, self)
        if name in connection.fieldnames.keys():
            sql_column = connection.fieldnames[name]
            sql_item = self.getSQLItem()
            fieldname = 'name'
            if sql_item and sql_column:
                while '.' in sql_column:
                    sql_item = getattr(sql_item,
                                       sql_column.split('.')[0], None)
                    if sql_item and (
                        (isinstance(sql_item, list) and len(sql_item) > 1)
                            or hasattr(sql_item, '_sa_instance_state')):
                        value = sql_item
                        fieldname = sql_column.split('.')[-1]
                        break
                    sql_column = '.'.join(sql_column.split('.')[1:])
                else:
                    value = getattr(sql_item, sql_column, None)
                #this is a relation
                if value and (isinstance(value, list)
                              or hasattr(value, '_sa_instance_state')):
                    sqlftis = [
                        a for a in getAllUtilitiesRegisteredFor(IDexterityFTI)
                        if
                        'collective.behavior.sql.behavior.behaviors.ISQLContent'
                        in a.behaviors and getattr(a, 'sql_table', None)
                    ]
                    if name == 'subject':
                        return tuple(
                            [getattr(a, fieldname, '') for a in value])
                    tableftis = []
                    for iface in iterSchemataForType(self.portal_type):
                        if name in iface.names():
                            field = iface[name]
                            if IList.providedBy(field):
                                return [
                                    getattr(a, fieldname, '') for a in value
                                ]  # hope it has name!
                            elif ITuple.providedBy(field):
                                return tuple(
                                    [getattr(a, fieldname, '') for a in value])
                            if IRelationChoice.providedBy(
                                    field) or IRelationList.providedBy(field):
                                if IRelationChoice.providedBy(field):
                                    allowed_types = field.source.query.get(
                                        'portal_type', [])
                                else:
                                    allowed_types = field.value_type.source.query.get(
                                        'portal_type', [])
                                tableftis = []
                                for sqlfti in sqlftis:
                                    adapted = ISQLTypeSettings(sqlfti, None)
                                    if isinstance(value, list):
                                        classname = value[0].__class__.__name__
                                    else:
                                        classname = value.__class__.__name__
                                    if adapted and getattr(
                                            adapted, 'sql_table',
                                            None) == classname:
                                        if not allowed_types or sqlfti.id in allowed_types:
                                            tableftis.append(adapted)

                                catalog = getToolByName(
                                    getSite(), 'portal_catalog')
                                relations = []
                                for tablefti in tableftis:
                                    sql_id_column = getattr(
                                        tablefti, 'sql_id_column', 'id')
                                    valueids = []
                                    if isinstance(value, list):
                                        valueids = [
                                            getattr(a, sql_id_column, None)
                                            for a in value
                                            if getattr(a, sql_id_column, None)
                                        ]
                                    else:
                                        valueids = getattr(
                                            value, sql_id_column, None)
                                    brains = catalog.searchResults(
                                        portal_type=tablefti.id,
                                        sql_id=valueids)
                                    for brain in brains:
                                        relations.append(
                                            SQLRelationValue(
                                                brain.portal_type,
                                                brain.sql_id))
                                if IRelationChoice.providedBy(
                                        field) and relations:
                                    return relations[0]
                                elif IRelationList.providedBy(
                                        field) and relations:
                                    return relations
                for iface in iterSchemataForType(self.portal_type):
                    if name == 'subject':
                        try:
                            return tuple([
                                a.decode('utf-8') for a in literal_eval(value)
                            ])
                        except:
                            return tuple([a.strip() for a in value.split(',')])
                    if name in iface.names():
                        field = iface[name]
                        if IRichText.providedBy(field):
                            return RichTextValue(value)
                        if INamedBlobImage.providedBy(field):
                            return NamedBlobImage(
                                base64.b64decode(value),
                                filename=unicode(self.portal_type + self.id +
                                                 ".jpg"))
                        if IList.providedBy(field):
                            try:
                                return [
                                    a.decode('utf-8')
                                    for a in literal_eval(value)
                                ]
                            except:
                                return [a.strip() for a in value.split(',')]
                        if ITuple.providedBy(field):
                            try:
                                return tuple([
                                    a.decode('utf-8')
                                    for a in literal_eval(value)
                                ])
                            except:
                                return tuple(
                                    [a.strip() for a in value.split(',')])

                if isinstance(value, unicode) or name == 'id':
                    try:
                        return str(value)
                    except:
                        pass
                return value
        return super(SQLDexterityItem, self).__getattribute__(name)
    def test_downtimeTimezones(self, _getUtcnow):
        # Execute a browser test for downtime to ensure correct time formats and
        # timezone handling.

        # Hack to be able to mock utcnow as it can not be patched immediatelly as it is
        # member of the builtin type datetime. Additionally datetime is required by Plone
        # within the patching scope.
        _getUtcnow.return_value = datetime.datetime(2017, 4, 13, 15, 37, 0, 0,
                                                    pytz.utc)

        # Allow user create content.
        setRoles(self.portal, TEST_USER_ID, [
            'Manager',
        ])

        # Create the provider folder and two providers.
        self.portal.invokeFactory('Folder', 'Providers')
        self.portal.Providers.invokeFactory('Provider', 'provider')
        self.portal.Providers.invokeFactory('Provider',
                                            self.TEST_OTHER_PROVIDER)

        # Create primary providers downtime to be filled out via browser.
        self.portal.Providers.provider.invokeFactory('Downtime', 'downtime')

        # Setup default workflow.
        getToolByName(self.portal,
                      'portal_workflow').setDefaultChain('intranet_workflow')

        # Setup downtime portlet.
        column = getUtility(IPortletManager, 'plone.leftcolumn')
        manager = getMultiAdapter((self.portal, column),
                                  IPortletAssignmentMapping)
        assignment = Assignment()
        chooser = INameChooser(manager)
        setRoles(self.portal, TEST_USER_ID, [
            'Manager',
        ])
        manager[chooser.chooseName(None, assignment)] = assignment

        # Setup secondary provider and it's downtimes:
        # * otherDowntime: not to be shown by portlet in primary provider's content subtree
        # * pastDowntime: not to be shown by portlet at all
        otherProvider = self.portal.Providers[self.TEST_OTHER_PROVIDER]
        otherProvider.update(title=self.TEST_OTHER_PROVIDER)

        otherProvider.invokeFactory('Downtime', self.TEST_OTHER_DOWNTIME)
        otherDowntime = otherProvider[self.TEST_OTHER_DOWNTIME]
        otherDowntime.update(title=self.TEST_OTHER_DOWNTIME,
                             startDateTime=self.TEST_OTHER_DOWNTIME_START,
                             endDateTime=self.TEST_OTHER_DOWNTIME_END)

        otherProvider.invokeFactory('Downtime', self.TEST_PAST_DOWNTIME)
        pastDowntime = otherProvider[self.TEST_PAST_DOWNTIME]
        pastDowntime.update(title=self.TEST_PAST_DOWNTIME,
                            startDateTime=self.TEST_PAST_DOWNTIME_START,
                            endDateTime=self.TEST_PAST_DOWNTIME_END)

        plone.api.content.transition(obj=otherDowntime, transition='publish')
        plone.api.content.transition(obj=pastDowntime, transition='publish')

        transaction.commit()

        # Start actual interaction via browser

        from plone.testing.z2 import Browser
        browser = Browser(self.app)
        browser.handleErrors = False

        portal_url = self.portal.absolute_url()
        self.portal.error_log._ignored_exceptions = ()

        browser.open(portal_url + '/login_form')
        browser.getControl(name='__ac_name').value = TEST_USER_NAME
        browser.getControl(name='__ac_password').value = TEST_USER_PASSWORD
        browser.getControl(name='submit').click()

        self.assertIn('You are now logged in', browser.contents)
        browser.open(portal_url)

        # Create provider
        browser.follow('Providers')
        browser.follow('Add new')

        self.assertTrue('Add new item' in browser.contents)
        self.assertTrue('Compute or data service provider' in browser.contents)

        browser.getControl("Provider").click()
        browser.getControl(name='form.button.Add').click()

        browser.getControl(name="title").value = self.TEST_PROVIDER_NAME
        browser.getControl(
            name='provider_userid').value = self.TEST_PROVIDER_ID
        browser.getControl(name='address.city:record:ignore_empty'
                           ).value = self.TEST_PROVIDER_CITY
        browser.getControl(
            name='address.country:record:ignore_empty').displayValue = [
                self.TEST_PROVIDER_COUNTRY
            ]
        browser.getControl(name="form.button.save").click()

        # Create downtime
        browser.follow('Add new')
        self.assertTrue('Add new item' in browser.contents)
        browser.getControl(label='Downtime').click()
        browser.getControl(name='form.button.Add').click()

        self.assertTrue('Add Downtime' in browser.contents)
        browser.getControl(name='title').value = self.TEST_DOWNTIME_TITLE
        browser.getControl(
            name='description').value = self.TEST_DOWNTIME_DESCRIPTION
        self.fillInDateWidget(browser, 'startDateTime',
                              self.TEST_DOWNTIME_START)
        self.fillInDateWidget(browser, 'endDateTime', self.TEST_DOWNTIME_END)
        browser.getControl(name='form.button.save').click()

        # Publish
        browser.follow('Publish')
        browser.getControl(name='form.button.confirm').click()

        # Check detail view
        self.assertContainsDowntimeFull(browser)

        # Check overview
        browser.open(portal_url + '/downtime_overview')
        self.assertContainsDowntimeShort(browser)

        # Back to detail view and edit
        browser.follow('Das ganze Schei')
        browser.follow('Edit')

        # Check edit view for correct dates
        self.assertDateWidget(browser, 'startDateTime',
                              self.TEST_DOWNTIME_START)
        self.assertDateWidget(browser, 'endDateTime', self.TEST_DOWNTIME_END)

        # Check portlet on portal site
        browser.open(portal_url)
        self.assertTrue('All Downtimes...' in browser.contents)
        self.assertContainsDowntimeShort(browser)
        self.assertFalse(
            re.search('Upcoming Downtimes\\s+?\\(' + self.TEST_PROVIDER_NAME,
                      browser.contents))
        self.assertTrue(self.TEST_OTHER_DOWNTIME in browser.contents)
        self.assertFalse(self.TEST_PAST_DOWNTIME in browser.contents)

        # Check portlet on provider overview site
        browser.follow('Providers')
        self.assertContainsDowntimeShort(browser)
        self.assertFalse(
            re.search('Upcoming Downtimes\\s+?\\(' + self.TEST_PROVIDER_NAME,
                      browser.contents))
        self.assertTrue(self.TEST_OTHER_DOWNTIME in browser.contents)
        self.assertFalse(self.TEST_PAST_DOWNTIME in browser.contents)

        # Check portlet on provider detail site
        browser.follow(self.TEST_PROVIDER_NAME)
        self.assertContainsDowntimeShort(browser)
        self.assertTrue(
            re.search('Upcoming Downtimes\\s+?\\(' + self.TEST_PROVIDER_NAME,
                      browser.contents))
        self.assertFalse(self.TEST_OTHER_DOWNTIME in browser.contents)
        self.assertFalse(self.TEST_PAST_DOWNTIME in browser.contents)
Exemple #12
0
def ical_import(container, ics_resource, event_type):
    cal = icalendar.Calendar.from_ical(ics_resource)
    events = cal.walk('VEVENT')

    def _get_prop(prop, item):
        ret = None
        if prop in item:
            ret = safe_unicode(item.decoded(prop))
        return ret

    def _from_list(ical, prop):
        """For EXDATE and RDATE recurrence component properties, the dates can
        be defined within one EXDATE/RDATE line or for each date an individual
        line.
        In the latter case, icalendar creates a list.
        This method handles this case.

        TODO: component property parameters like TZID are not used here.
        """
        val = prop in ical and ical[prop] or []
        if not isinstance(val, list):
            val = [val]
        #ret = ''
        #for item in val:
        #    ret = ret and '%s\n' % ret or ret  # insert linebreak
        #    ret = '%s%s:%s' % (ret, prop, item.to_ical())
        #return ret

        # Zip multiple lines into one, since jquery.recurrenceinput.js does
        # not support multiple lines here
        # https://github.com/collective/jquery.recurrenceinput.js/issues/15
        ret = ''
        for item in val:
            ret = ret and '%s,' % ret or ret  # insert linebreak
            ret = '%s%s' % (ret, item.to_ical())
        return ret and '%s:%s' % (prop, ret) or None


    count = 0
    for item in events:
        start = _get_prop('DTSTART', item)
        end = _get_prop('DTEND', item)
        if not end:
            duration = _get_prop('DURATION', item)
            if duration:
                end = start + duration
            # else: whole day or open end

        timezone = getattr(getattr(start, 'tzinfo', None), 'zone', None) or\
                base.default_timezone(container)

        whole_day = False
        open_end = False
        if is_date(start) and (is_date(end) or end is None):
            # All day / whole day events
            # End must be same type as start (RFC5545, 3.8.2.2)
            whole_day = True
            if end is None: end = start
            if start < end:
                # RFC5545 doesn't define clearly, if all day events should have
                # a end date one day after the start day at 0:00.
                # Internally, we handle all day events with start=0:00,
                # end=:23:59:59, so we substract one day here.
                end = end - datetime.timedelta(days=1)
            start = base.dt_start_of_day(date_to_datetime(start))
            end = base.dt_end_of_day(date_to_datetime(end))
        elif is_datetime(start) and end is None:
            # Open end event, see RFC 5545, 3.6.1
            open_end = True
            end = base.dt_end_of_day(date_to_datetime(start))
        assert(is_datetime(start))
        assert(is_datetime(end))

        title = _get_prop('SUMMARY', item)
        description = _get_prop('DESCRIPTION', item)
        location = _get_prop('LOCATION', item)

        url = _get_prop('URL', item)

        rrule = _get_prop('RRULE', item)
        rrule = rrule and 'RRULE:%s' % rrule.to_ical() or ''
        rdates =  _from_list(item, 'RDATE')
        exdates =  _from_list(item, 'EXDATE')
        rrule = '\n'.join([it for it in [rrule, rdates, exdates] if it])

        # TODO: attendee-lists are not decoded properly and contain only
        # vCalAddress values
        attendees = _get_prop('ATTENDEE', item)

        contact = _get_prop('CONTACT', item)
        categories = _get_prop('CATEGORIES', item)
        if hasattr(categories, '__iter__'):
            categories = [safe_unicode(it) for it in categories]

        # for sync
        created = _get_prop('CREATED', item)
        modified = _get_prop('LAST-MODIFIED', item)

        # TODO: better use plone.api, from which some of the code here is
        # copied
        content_id = str(random.randint(0, 99999999))

        # TODO: if AT had the same attrs like IDXEventBase, we could set
        # everything within this invokeFactory call.
        container.invokeFactory(event_type,
                                id=content_id,
                                title=title,
                                description=description)
        content = container[content_id]

        event = IEventAccessor(content)
        event.start = start
        event.end = end
        event.timezone = timezone
        event.whole_day = whole_day
        event.open_end = open_end
        event.location = location
        event.event_url = url
        event.recurrence = rrule
        event.attendees = attendees
        event.contact_name = contact
        event.subjects = categories
        notify(ObjectModifiedEvent(content))

        # Archetypes specific code
        if getattr(content, 'processForm', False):
            # Will finish Archetypes content item creation process,
            # rename-after-creation and such
            content.processForm()

        if content_id in container:
            # Rename with new id from title, if processForm didn't do it.
            chooser = INameChooser(container)
            new_id = chooser.chooseName(title, content)
            transaction.savepoint(optimistic=True)  # Commit before renaming
            content.aq_parent.manage_renameObject(content_id, new_id)
        else:
            transaction.savepoint(optimistic=True)

        count += 1

    return {'count': count}
Exemple #13
0
 def get_new_id(self, obj):
     return INameChooser(self.context).chooseName(None, obj)
Exemple #14
0
    def create_object(self, folder, type_, info):
        filename = info['name']
        name = filename.decode("utf8")
        chooser = INameChooser(folder)
        chooser_name = name.lower().replace('aq_', '')
        newid = chooser.chooseName(chooser_name, folder.aq_parent)
        # strip metadata from file
        if (type_ in ('Image', 'File', 'Video') and
                exiftool is not None and 'tmp_file' in info):
            is_pdf = ('application/pdf' in guess_type(info['tmp_file']))
            if is_pdf and qpdf is not None:
                try:
                    # Will recursively remove the tags of the file using exiftool, linearize it.
                    # And do it again.
                    exiftool(info['tmp_file'])
                    qpdf(info['tmp_file'])
                    exiftool(info['tmp_file'])
                    qpdf(info['tmp_file'])
                except Exception:
                    logger.warn('Could not strip additional metadata with qpdf %s' % info['tmp_file'])
            else:
                try:
                    exiftool(info['tmp_file'])
                except Exception:
                    logger.warn('Could not strip metadata from file: %s' % info['tmp_file'])

        fi = open(info['tmp_file'], 'r')
        try:
            # Try to determine which kind of NamedBlob we need
            # This will suffice for standard p.a.contenttypes File/Image
            # and any other custom type that would have 'File' or 'Image' in
            # its type name
            filename = ploneutils.safe_unicode(filename)
            create_opts = dict(
                type=type_,
                id=newid,
                container=folder)
            if 'Image' in type_:
                image = NamedBlobImage(data=fi, filename=filename)
                try:
                    image.focal_point = [
                        float(self.request.form.get('focalX')),
                        float(self.request.form.get('focalY'))
                    ]
                except Exception:
                    pass
                create_opts['image'] = image
            else:
                create_opts['file'] = NamedBlobFile(data=fi, filename=filename)

            for field in get_upload_fields():
                if not field.get('name'):
                    continue
                name = field['name']
                if not self.request.form.get(name):
                    continue
                if name in ('tags', 'subject'):
                    # tags needs to be converted
                    create_opts['subject'] = self.request.form.get(name).split(';')
                else:
                    create_opts[name] = self.request.form.get(name, '')
            return api.content.create(**create_opts)
        finally:
            fi.close()
Exemple #15
0
def convert_legacy_portlets(context):
    """Convert legacy portlets (left_slots, right_slots) in the given
    context to new-style portlets.
    """

    portletsMapping = {
        'portlet_login': login.Assignment(),
        'portlet_news': news.Assignment(count=5),
        'portlet_navigation': navigation.Assignment(),
        'portlet_review': review.Assignment(),
        'portlet_recent': recent.Assignment(count=5),
        'portlet_related': DONT_MIGRATE,
        'portlet_languages': DONT_MIGRATE,
    }
    if HAS_EVENTS:
        portletsMapping.update({
            'portlet_calendar':
            portlet_calendar.Assignment(),
            'portlet_events':
            portlet_events.Assignment(count=5),
        })

    # Convert left_slots and right_slots to portlets

    left = getUtility(IPortletManager, name='plone.leftcolumn')
    right = getUtility(IPortletManager, name='plone.rightcolumn')

    leftAssignable = getMultiAdapter((context, left),
                                     IPortletAssignmentMapping).__of__(context)
    rightAssignable = getMultiAdapter(
        (context, right), IPortletAssignmentMapping).__of__(context)

    IPortletPermissionChecker(leftAssignable)()
    IPortletPermissionChecker(rightAssignable)()

    leftChooser = INameChooser(leftAssignable)
    rightChooser = INameChooser(rightAssignable)

    left_slots = getattr(aq_base(context), 'left_slots', [])
    right_slots = getattr(aq_base(context), 'right_slots', [])

    for item in left_slots:
        path = item.split('/')
        if len(path) == 4:
            newPortlet = portletsMapping.get(path[1], None)
            if newPortlet is None and path[0] in (
                    'context', 'here') and path[2] == 'macros':
                newPortlet = classic.Assignment(path[1], path[3])
            if newPortlet is not None and newPortlet is not DONT_MIGRATE:
                leftAssignable[leftChooser.chooseName(None,
                                                      newPortlet)] = newPortlet

    for item in right_slots:
        path = item.split('/')
        if len(path) == 4:
            newPortlet = portletsMapping.get(path[1], None)
            if newPortlet is None and path[0] in (
                    'context', 'here') and path[2] == 'macros':
                newPortlet = classic.Assignment(path[1], path[3])
            if newPortlet is not None and newPortlet is not DONT_MIGRATE:
                rightAssignable[rightChooser.chooseName(
                    None, newPortlet)] = newPortlet

    context.left_slots = []
    context.right_slots = []
 def addScoreSystem(self, target):
     chooser = INameChooser(self.context)
     name = chooser.chooseName('', target)
     self.context[name] = target
Exemple #17
0
 def add(self, schedule):
     chooser = INameChooser(self.context)
     name = chooser.chooseName('', schedule)
     self.context[name] = schedule
     self._object_added = schedule
Exemple #18
0
 def add(self, content):
     # I think this should be more deterministic
     name = INameChooser(self).chooseName(content.__name__ or '', content)
     self[name] = content
Exemple #19
0
def register_portlets(obj, item):
    """Register portlets fror one object
    Code adapted from plone.app.portlets.exportimport.portlets.PortletsXMLAdapter
    Work in progress...
    """
    site = api.portal.get()
    request = getRequest()
    results = 0
    for manager_name, portlets in item.get("portlets", {}).items():
        manager = getUtility(IPortletManager, manager_name)
        mapping = queryMultiAdapter((obj, manager), IPortletAssignmentMapping)
        namechooser = INameChooser(mapping)

        for portlet_data in portlets:
            # 1. Create the assignment
            assignment_data = portlet_data["assignment"]
            portlet_type = portlet_data["type"]
            portlet_factory = getUtility(IFactory, name=portlet_type)
            assignment = portlet_factory()

            name = namechooser.chooseName(None, assignment)
            mapping[name] = assignment
            logger.info("Added portlet {} to {}".format(
                name, obj.absolute_url()))

            # aq-wrap it so that complex fields will work
            assignment = assignment.__of__(site)

            # set visibility setting
            visible = portlet_data.get("visible")
            if visible:
                settings = IPortletAssignmentSettings(assignment)
                settings["visible"] = visible

            # 2. Apply portlet settings
            portlet_interface = getUtility(IPortletTypeInterface,
                                           name=portlet_type)
            for property_name, value in assignment_data.items():
                field = portlet_interface.get(property_name, None)
                if field is None:
                    continue
                field = field.bind(assignment)
                # deserialize data (e.g. for RichText)
                deserializer = queryMultiAdapter((field, obj, request),
                                                 IFieldDeserializer)
                if deserializer is not None:
                    try:
                        value = deserializer(value)
                    except Exception as e:
                        logger.info(
                            u"Could not import portlet data {} for field {} on {}: {}"
                            .format(value, field, obj.absolute_url(), str(e)))
                        continue
                field.set(assignment, value)

            results += 1

    for blacklist_status in item.get("blacklist_status", []):
        status = blacklist_status["status"]
        manager_name = blacklist_status["manager"]
        category = blacklist_status["category"]
        manager = getUtility(IPortletManager, manager_name)
        assignable = queryMultiAdapter((obj, manager),
                                       ILocalPortletAssignmentManager)
        if status.lower() == "block":
            assignable.setBlacklistStatus(category, True)
        elif status.lower() == "show":
            assignable.setBlacklistStatus(category, False)

    return results
Exemple #20
0
 def add(self, timetable):
     """Add the timetable to self.context."""
     nameChooser = INameChooser(self.context)
     key = nameChooser.chooseName('', timetable)
     self.context[key] = timetable
Exemple #21
0
    def __call__(self):
        self.errors = []
        self.protect()
        context = aq_inner(self.context)

        catalog = getToolByName(context, 'portal_catalog')
        mtool = getToolByName(context, 'portal_membership')

        missing = []
        for key in self.request.form.keys():
            if not key.startswith('UID_'):
                continue
            index = key.split('_')[-1]
            uid = self.request.form[key]
            brains = catalog(UID=uid, show_inactive=True)
            if len(brains) == 0:
                missing.append(uid)
                continue
            obj = brains[0].getObject()
            title = self.objectTitle(obj)
            if not mtool.checkPermission('Copy or Move', obj):
                self.errors.append(
                    _(u'Permission denied to rename ${title}.',
                      mapping={u'title': title}))
                continue

            sp = transaction.savepoint(optimistic=True)

            newid = self.request.form['newid_' + index]
            if six.PY2:
                newid = newid.encode('utf8')
            newtitle = self.request.form['newtitle_' + index]
            try:
                obid = obj.getId()
                title = obj.Title()
                change_title = newtitle and title != newtitle
                if change_title:
                    getSecurityManager().validate(obj, obj, 'setTitle',
                                                  obj.setTitle)
                    obj.setTitle(newtitle)
                    notify(ObjectModifiedEvent(obj))
                if newid and obid != newid:
                    parent = aq_parent(aq_inner(obj))
                    # Make sure newid is safe
                    newid = INameChooser(parent).chooseName(newid, obj)
                    # Update the default_page on the parent.
                    context_state = getMultiAdapter((obj, self.request),
                                                    name='plone_context_state')
                    if context_state.is_default_page():
                        parent.setDefaultPage(newid)
                    parent.manage_renameObjects((obid, ), (newid, ))
                elif change_title:
                    # the rename will have already triggered a reindex
                    obj.reindexObject()
            except ConflictError:
                raise
            except Exception as e:
                sp.rollback()
                if six.PY2:
                    title = title.decode('utf8')
                logger.error(u'Error renaming "{title}": "{exception}"'.format(
                    title=title, exception=e))
                self.errors.append(
                    _(u'Error renaming ${title}', mapping={'title': title}))

        return self.message(missing)
Exemple #22
0
    def __call__(self, name, content_type, data, title, request):
        # contextual import to prevent ImportError
        from plone.dexterity.utils import createContentInContainer

        ctr = getToolByName(self.context, 'content_type_registry')
        type_ = ctr.findTypeName(name.lower(), '', '') or 'File'

        name = name.decode('utf8')
        title = title.decode('utf8')

        chooser = INameChooser(self.context)

        # otherwise I get ZPublisher.Conflict ConflictErrors
        # when uploading multiple files
        upload_lock.acquire()

        def trim_title(title):
            pview = getMultiAdapter((self.context, request), name='plone')
            return pview.cropText(title, 40)

        if title:
            newid = chooser.chooseName(title, self.context.aq_parent)
        else:
            newid = chooser.chooseName(name, self.context.aq_parent)

        try:
            transaction.begin()
            # Try to determine which kind of NamedBlob we need
            # This will suffice for standard p.a.contenttypes File/Image
            # and any other custom type that would have 'File' or 'Image' in
            # its type name
            if 'File' in type_:
                file = NamedBlobFile(data=data.read(),
                                     filename=unicode(data.filename),
                                     contentType=content_type)
                obj = createContentInContainer(self.context,
                                               'AppFile',
                                               id=newid,
                                               title=trim_title(title),
                                               description=title,
                                               file=file,
                                               checkConstraints=False)
            elif 'Image' in type_:
                image = NamedBlobImage(data=data.read(),
                                       filename=unicode(data.filename),
                                       contentType=content_type)

                obj = createContentInContainer(self.context,
                                               'AppImage',
                                               id=newid,
                                               title=trim_title(title),
                                               description=title,
                                               image=image,
                                               checkConstraints=False)

            # obj.title = name
            obj.reindexObject()
            transaction.commit()

        finally:
            upload_lock.release()

        return obj
    def folderupload(self, files, title='', description=''):

        if not self.doc.isDocument():
            return

        self.doc.setfile(self.doc, files[0])

        docfolderId = self.doc.getId()
        dbfolderId = self.doc.getParentDatabase().id

        #TODO come configurare diverse cartelle per applicazione o plomino db (da fare sulle singole app)?
        target = self.context.portal_url.getPortalObject()[ATTACHMENT_FOLDER]

        with adopt_roles('Manager'):
            if not dbfolderId in target.keys():
                target.invokeFactory("Folder", id=dbfolderId, title=dbfolderId)
            target = target[dbfolderId]
            if not docfolderId in target.keys():
                target.invokeFactory("Folder",
                                     id=docfolderId,
                                     title=docfolderId)
            docFolder = target[docfolderId]
            for username, roles in self.doc.get_local_roles():
                docFolder.manage_setLocalRoles(username, roles)

        if not isinstance(files, list):
            files = [files]

        #se non  campo multiplo vuoto la cartella
        #TODO tenere allineati i files nella cartella con i nomi sul campo di plomino
        current_files = self.doc.getItem(self.element)
        cleaned_files = {}
        if self.multiple:
            for fName in current_files:
                if fName in docFolder.keys():
                    cleaned_files[fName] = current_files[fName]
            self.doc.setItem(self.element, cleaned_files)

        #se upload singolo cancello tutti i file presenti collegati al campo
        else:
            try:
                docFolder.manage_delObjects(current_files.keys())
            except Exception as error:
                pass
            self.doc.removeItem(self.element)

        namechooser = INameChooser(docFolder)
        loaded = []
        for item in files:
            if item.filename:
                content_type = item.headers.get('Content-Type')
                filename = safe_unicode(item.filename)
                data = item.read()
                id_name = ''
                title = title and title[0] or filename
                # Get a unique id here
                id_name = namechooser.chooseName(title, docFolder)

                # Portal types allowed : File and Image
                # Since Plone 4.x both types use Blob
                if content_type in IMAGE_MIMETYPES:
                    portal_type = 'Image'
                    wrapped_data = NamedBlobImage(data=data, filename=filename)
                else:
                    portal_type = 'File'
                    wrapped_data = NamedBlobFile(data=data, filename=filename)

                # Create content
                docFolder.invokeFactory(portal_type,
                                        id=id_name,
                                        title=title,
                                        description=description[0])

                newfile = docFolder[id_name]
                # Set data
                if portal_type == 'File':
                    if IATFile.providedBy(newfile):
                        newfile.setFile(data, filename=filename)
                    else:
                        newfile.file = wrapped_data
                elif portal_type == 'Image':
                    if IATImage.providedBy(newfile):
                        newfile.setImage(data, filename=filename)
                    else:
                        newfile.image = wrapped_data

                # Finalize content creation, reindex it
                newfile.reindexObject()
                notify(ObjectModifiedEvent(newfile))
                loaded.append(newfile)
            if loaded:
                return loaded
            return False
Exemple #24
0
 def addItem(self, item):
     chooser = INameChooser(self)
     item_id = getattr(item, 'ldap_name', None) or chooser.chooseName(
         None, item)
     self[item_id] = item
Exemple #25
0
 def add(self, content):
     name = INameChooser(self).chooseName(content.__name__ or '', content)
     self[name] = content
Exemple #26
0
def ical_import(container,
                ics_resource,
                event_type,
                sync_strategy=base.SYNC_KEEP_NEWER):
    cal = icalendar.Calendar.from_ical(ics_resource)
    events = cal.walk('VEVENT')

    cat = getToolByName(container, 'portal_catalog')
    container_path = '/'.join(container.getPhysicalPath())

    def _get_by_sync_uid(uid):
        return cat(sync_uid=uid, path={'query': container_path, 'depth': 1})

    def _get_prop(prop, item, default=None):
        ret = default
        if prop in item:
            ret = safe_unicode(item.decoded(prop))
        return ret

    def _from_list(ical, prop):
        """For EXDATE and RDATE recurrence component properties, the dates can
        be defined within one EXDATE/RDATE line or for each date an individual
        line.
        In the latter case, icalendar creates a list.
        This method handles this case.

        TODO: component property parameters like TZID are not used here.
        """
        val = prop in ical and ical[prop] or []
        if not isinstance(val, list):
            val = [val]
        #ret = ''
        #for item in val:
        #    ret = ret and '%s\n' % ret or ret  # insert linebreak
        #    ret = '%s%s:%s' % (ret, prop, item.to_ical())
        #return ret

        # Zip multiple lines into one, since jquery.recurrenceinput.js does
        # not support multiple lines here
        # https://github.com/collective/jquery.recurrenceinput.js/issues/15
        ret = ''
        for item in val:
            ret = ret and '%s,' % ret or ret  # insert linebreak
            ret = '%s%s' % (ret, item.to_ical())
        return ret and '%s:%s' % (prop, ret) or None

    count = 0
    for item in events:
        start = _get_prop('DTSTART', item)
        end = _get_prop('DTEND', item)
        if not end:
            duration = _get_prop('DURATION', item)
            if duration:
                end = start + duration
            # else: whole day or open end

        timezone = getattr(getattr(start, 'tzinfo', None), 'zone', None) or\
            base.default_timezone(container)

        whole_day = False
        open_end = False
        if is_date(start) and (is_date(end) or end is None):
            # All day / whole day events
            # End must be same type as start (RFC5545, 3.8.2.2)
            whole_day = True
            if end is None:
                end = start
            if start < end:
                # RFC5545 doesn't define clearly, if all day events should have
                # a end date one day after the start day at 0:00.
                # Internally, we handle all day events with start=0:00,
                # end=:23:59:59, so we substract one day here.
                end = end - datetime.timedelta(days=1)
            start = base.dt_start_of_day(date_to_datetime(start))
            end = base.dt_end_of_day(date_to_datetime(end))
        elif is_datetime(start) and end is None:
            # Open end event, see RFC 5545, 3.6.1
            open_end = True
            end = base.dt_end_of_day(date_to_datetime(start))
        assert (is_datetime(start))
        assert (is_datetime(end))

        title = _get_prop('SUMMARY', item)
        description = _get_prop('DESCRIPTION', item)
        location = _get_prop('LOCATION', item)

        url = _get_prop('URL', item)

        rrule = _get_prop('RRULE', item)
        rrule = rrule and 'RRULE:%s' % rrule.to_ical() or ''
        rdates = _from_list(item, 'RDATE')
        exdates = _from_list(item, 'EXDATE')
        rrule = '\n'.join([it for it in [rrule, rdates, exdates] if it])

        # TODO: attendee-lists are not decoded properly and contain only
        # vCalAddress values
        attendees = item.get('ATTENDEE', ())

        contact = _get_prop('CONTACT', item)
        categories = item.get('CATEGORIES', ())
        if hasattr(categories, '__iter__'):
            categories = [safe_unicode(it) for it in categories]

        ext_modified = utc(_get_prop('LAST-MODIFIED', item))

        # TODO: better use plone.api for content creation, from which some of
        # the code here is copied

        content = None
        new_content_id = None
        existing_event = None
        sync_uid = _get_prop('UID', item)
        if sync_strategy != base.SYNC_NONE and sync_uid:
            existing_event = _get_by_sync_uid(sync_uid)
        if existing_event:
            if sync_strategy == base.SYNC_KEEP_MINE:
                # On conflict, keep mine
                continue

            exist_event = existing_event[0].getObject()
            acc = IEventAccessor(exist_event)

            if sync_strategy == base.SYNC_KEEP_NEWER and\
                    (not ext_modified or acc.last_modified >= ext_modified):
                # Update only, if newer, if ext_modified exists
                continue

            # Else: update
            content = exist_event
        else:
            # TODO: if AT had the same attrs like IDXEventBase, we could set
            # everything within this invokeFactory call.
            new_content_id = str(random.randint(0, 99999999))
            container.invokeFactory(event_type,
                                    id=new_content_id,
                                    title=title,
                                    description=description)
            content = container[new_content_id]

        assert (content)  # At this point, a content must be available.

        event = IEventAccessor(content)
        event.title = title
        event.description = description
        event.start = start
        event.end = end
        event.timezone = timezone
        event.whole_day = whole_day
        event.open_end = open_end
        event.location = location
        event.event_url = url
        event.recurrence = rrule
        event.attendees = attendees
        event.contact_name = contact
        event.subjects = categories
        if sync_strategy != base.SYNC_NONE:
            # Don't import the sync_uid, if no sync strategy is chosen. Let the
            # sync_uid be autogenerated then.
            event.sync_uid = sync_uid
        notify(ObjectModifiedEvent(content))

        # Archetypes specific code
        if getattr(content, 'processForm', False):
            # Will finish Archetypes content item creation process,
            # rename-after-creation and such
            content.processForm()

        # Use commits instead of savepoints to avoid "FileStorageError:
        # description too long" on large imports.
        transaction.get().commit()  # Commit before rename

        if new_content_id and new_content_id in container:
            # Rename with new id from title, if processForm didn't do it.
            chooser = INameChooser(container)
            new_id = chooser.chooseName(title, content)
            content.aq_parent.manage_renameObject(new_content_id, new_id)

        # Do this at the end, otherwise it's overwritten
        if ext_modified:
            event.last_modified = ext_modified

        count += 1

    return {'count': count}
 def add(self, ob):
     self.context[INameChooser(self.context).chooseName()] = ob
Exemple #28
0
    def _initRules(self, node):
        """Import rules from the given node
        """

        site = self.environ.getSite()
        storage = queryUtility(IRuleStorage)
        if storage is None:
            return

        for child in node.childNodes:
            if child.nodeName == 'rule':

                rule = None
                name = child.getAttribute('name')
                if name:
                    rule = storage.get(name, None)

                if rule is None:
                    rule = Rule()

                    if not name:
                        chooser = INameChooser(storage)
                        name = chooser.chooseName(None, rule)

                    storage[name] = rule
                else:
                    # Clear out conditions and actions since we're expecting
                    # new ones
                    del rule.conditions[:]
                    del rule.actions[:]

                rule.title = child.getAttribute('title')
                rule.description = child.getAttribute('description')
                event_name = child.getAttribute('event')
                rule.event = _resolveDottedName(event_name)
                if not rule.event:
                    raise ImportError('Can not import {0}'.format(event_name))

                rule.enabled = as_bool(child.getAttribute('enabled'), True)
                rule.stop = as_bool(child.getAttribute('stop-after'))
                rule.cascading = as_bool(child.getAttribute('cascading'))
                # Aq-wrap to enable complex setters for elements below
                # to work

                rule = rule.__of__(site)

                for rule_config_node in child.childNodes:
                    if rule_config_node.nodeName == 'conditions':
                        for condition_node in rule_config_node.childNodes:
                            if not condition_node.nodeName == 'condition':
                                continue

                            type_ = condition_node.getAttribute('type')
                            element_type = getUtility(IRuleCondition,
                                                      name=type_)
                            if element_type.factory is None:
                                continue

                            condition = element_type.factory()

                            # Aq-wrap in case of complex setters
                            condition = condition.__of__(rule)

                            handler = IRuleElementExportImportHandler(
                                condition)
                            handler.import_element(condition_node)

                            rule.conditions.append(aq_base(condition))

                    elif rule_config_node.nodeName == 'actions':
                        for action_node in rule_config_node.childNodes:
                            if not action_node.nodeName == 'action':
                                continue

                            type_ = action_node.getAttribute('type')
                            element_type = getUtility(IRuleAction, name=type_)
                            if element_type.factory is None:
                                continue

                            action = element_type.factory()

                            # Aq-wrap in case of complex setters
                            action = action.__of__(rule)

                            handler = IRuleElementExportImportHandler(action)
                            handler.import_element(action_node)

                            rule.actions.append(aq_base(action))

            elif child.nodeName == 'assignment':
                location = child.getAttribute('location')
                if location.startswith('/'):
                    location = location[1:]

                try:
                    container = site.unrestrictedTraverse(str(location))
                except KeyError:
                    continue

                name = child.getAttribute('name')
                api.assign_rule(
                    container,
                    name,
                    enabled=as_bool(child.getAttribute('enabled')),
                    bubbles=as_bool(child.getAttribute('bubbles')),
                    insert_before=child.getAttribute('insert-before'),
                )
Exemple #29
0
def create(
        container=None,
        type=None,
        id=None,
        title=None,
        safe_id=False,
        **kwargs  # NOQA: C816
):
    """Create a new content item.

    :param container: [required] Container object in which to create the new
        object.
    :type container: Folderish content object
    :param type: [required] Type of the object.
    :type type: string
    :param id: Id of the object.  If the id conflicts with another object in
        the container, a suffix will be added to the new object's id. If no id
        is provided, automatically generate one from the title. If there is no
        id or title provided, raise a ValueError.
    :type id: string
    :param title: Title of the object. If no title is provided, use id as
        the title.
    :type title: string
    :param safe_id: When False, the given id will be enforced. If the id is
        conflicting with another object in the target container, raise an
        InvalidParameterError. When True, choose a new, non-conflicting id.
    :type safe_id: boolean
    :returns: Content object
    :raises:
        KeyError,
        :class:`~plone.api.exc.MissingParameterError`,
        :class:`~plone.api.exc.InvalidParameterError`
    :Example: :ref:`content_create_example`
    """
    # Create a temporary id if the id is not given
    content_id = not safe_id and id or str(random.randint(0, 99999999))

    if title:
        kwargs['title'] = title

    try:
        container.invokeFactory(type, content_id, **kwargs)
    except UnicodeDecodeError:
        # UnicodeDecodeError is a subclass of ValueError,
        # so will be swallowed below unless we re-raise it here
        raise
    except ValueError as e:
        types = [fti.getId() for fti in container.allowedContentTypes()]

        raise InvalidParameterError(
            "Cannot add a '{obj_type}' object to the container.\n"
            'Allowed types are:\n'
            '{allowed_types}\n'
            '{message}'.format(
                obj_type=type,
                allowed_types='\n'.join(sorted(types)),
                message=e.message,
            ), )

    content = container[content_id]

    # Archetypes specific code
    if IBaseObject.providedBy(content):
        # Will finish Archetypes content item creation process,
        # rename-after-creation and such
        content.processForm(values=kwargs)

    if not id or (safe_id and id):
        # Create a new id from title
        chooser = INameChooser(container)
        derived_id = id or title
        new_id = chooser.chooseName(derived_id, content)
        # kacee: we must do a partial commit, else the renaming fails because
        # the object isn't in the zodb.
        # Thus if it is not in zodb, there's nothing to move. We should
        # choose a correct id when
        # the object is created.
        # maurits: tests run fine without this though.
        transaction.savepoint(optimistic=True)
        content.aq_parent.manage_renameObject(content_id, new_id)

    return content
Exemple #30
0
 def add_test_data(self, *items):
     from collective.notices.interfaces import INoticeFactory
     for item in items:
         self.storage[INameChooser(self.storage).chooseName()] = \
             INoticeFactory(self.storage)(**item)