Ejemplo n.º 1
0
def filterTypes(self, out, types, package_name):
    filtered_types = []

    for rti in types:
        t = rti['klass']

        isBaseObject = 0
        if IBaseObject.implementedBy(t):
            isBaseObject = 1
        else:
            for k in t.__bases__:
                if IBaseObject.implementedBy(k):
                    isBaseObject = 1
                    break

        if isBaseObject:
            filtered_types.append(t)
        else:
            print >> out, ("%s doesnt implements IBaseObject. "
                           "Possible misconfiguration. "
                           "Check if your class has an "
                           "'implements(IBaseObject)' "
                           "(or IBaseContent, or IBaseFolder)" % repr(t))

    return filtered_types
Ejemplo n.º 2
0
Archivo: utils.py Proyecto: dtgit/dtedu
def filterTypes(self, out, types, package_name):
    typesTool = getToolByName(self, 'portal_types')

    filtered_types = []

    for rti in types:
        t = rti['klass']
        name = rti['name']
        meta_type = rti['meta_type']

        isBaseObject = 0
        if IBaseObject.isImplementedByInstancesOf(t):
            isBaseObject = 1
        else:
            for k in t.__bases__:
                if IBaseObject.isImplementedByInstancesOf(k):
                    isBaseObject = 1
                    break

        if isBaseObject:
            filtered_types.append(t)
        else:
            print >> out, ("%s doesnt implements IBaseObject. "
                           "Possible misconfiguration. "
                           "Check if your class has an "
                           "'__implements__ = IBaseObject' "
                           "(or IBaseContent, or IBaseFolder)" % repr(t))

    return filtered_types
Ejemplo n.º 3
0
def findBaseTypes(klass):
    bases = []
    if hasattr(klass, '__bases__'):
        for b in klass.__bases__:
            if IBaseObject.providedBy(b):
                bases.append(className(b))
    return bases
Ejemplo n.º 4
0
def findBaseTypes(klass):
    bases = []
    if hasattr(klass, '__bases__'):
        for b in klass.__bases__:
            if IBaseObject.providedBy(b):
                bases.append(className(b))
    return bases
Ejemplo n.º 5
0
 def __bobo_traverse__(self, REQUEST, name):
     try:
         return self.boboTraverse(self.obj, REQUEST, name)
     except AttributeError:
         if not IBaseObject.providedBy(self.obj):
             return self.boboTraverse(getSite(), REQUEST, name)
         raise
Ejemplo n.º 6
0
def findBaseTypes(klass):
    bases = []
    if hasattr(klass, '__bases__'):
        for b in klass.__bases__:
            if IBaseObject.isImplementedByInstancesOf(b):
                bases.append(className(b))
    return bases
Ejemplo n.º 7
0
def is_at_content(brain_or_object):
    """Checks if the passed in object is an Archetype Content Type

    :param brain_or_object: A single catalog brain or content object
    :type brain_or_object: ATContentType/DexterityContentType/CatalogBrain
    :returns: True if the object is an ATCT
    :rtype: bool
    """
    obj = get_object(brain_or_object)
    return IBaseObject.providedBy(obj)
Ejemplo n.º 8
0
def update_translated_ids(obj, event):
    if IBaseObject.providedBy(obj) and obj.isTemporary():
        return
    handler = IMultilanguageURLHandler(event.newParent, None)
    old_handler = IMultilanguageURLHandler(event.oldParent, None)
    if handler is not None and old_handler is not None:
        for lang, id in old_handler.get_translated_ids(event.oldName):
            handler.set_translated_id(event.newName, id, lang)
    if not event.newParent is event.oldParent and old_handler is not None:
        old_handler.remove_translated_ids(event.oldName, False)
Ejemplo n.º 9
0
 def _rawEnum(self, callback, *args, **kwargs):
     # Finds all object to check if they are 'referenceable'.
     catalog = getToolByName(self, 'portal_catalog')
     brains = catalog(dict(id=[]))
     for b in brains:
         o = b.getObject()
         if o is not None:
             if IBaseObject.providedBy(o):
                 callback(o, *args, **kwargs)
         else:
             log('no object for brain: %s:%s' % (b, b.getURL()))
Ejemplo n.º 10
0
 def _rawEnum(self, callback, *args, **kwargs):
     # Finds all object to check if they are 'referenceable'.
     catalog = getToolByName(self, 'portal_catalog')
     brains = catalog(dict(id=[]))
     for b in brains:
         o = b.getObject()
         if o is not None:
             if IBaseObject.providedBy(o):
                 callback(o, *args, **kwargs)
         else:
             log('no object for brain: %s:%s' % (b, b.getURL()))
 def getFields(self):
     """
     The context should provide IBaseObject
     The creation flag shoul be True
     The context portal_type should be in the list of types with captcha validation
     """
     first_cond = IBaseObject.providedBy(self.context)
     second_cond = self.context.checkCreationFlag()
     third_cond = self.context.portal_type in self.get_captcha_types()
     if first_cond and second_cond and third_cond:
         return self._fields
     return []
Ejemplo n.º 12
0
def create(container=None, type=None, id=None, title=None, strict=True, *args,
           **kwargs):
    """Create a new object.

    :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 strict: When True, the given id will be enforced. If the id is
        conflicting with another object in the target container, raise a
        KeyError. When False, ``create`` creates a new, non-conflicting id.
    :type param: boolean
    :returns: Content object
    :Example: :ref:`create_content_example`
    """
    if not container:
        raise ValueError('The ``container`` attribute is required.')

    if not type:
        raise ValueError('The ``type`` attribute is required.')

    if not id and not title:
        raise ValueError('You have to provide either the ``id`` or the '
                         '``title`` attribute')

    # Create a temporary id
    id = str(random.randint(0, 99999999))
    container.invokeFactory(type, id, title=title, **kwargs)
    content = container[id]

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

    # Create a new id from title
    chooser = INameChooser(container)
    new_id = chooser.chooseName(title, content)
    content.aq_parent.manage_renameObject(id, new_id)

    return content
Ejemplo n.º 13
0
 def update(self):
     self.available = False
     if not HAS_ARCHETYPES:
         return
     self.context = aq_inner(self.context)
     replaced_types = [
         'ATFolder', 'ATDocument', 'ATFile', 'ATImage', 'ATNewsItem',
         'ATLink', 'ATEvent', 'ATBlobImage', 'ATBlobFile', 'Collection'
     ]
     if self.context.meta_type not in replaced_types:
         return
     if not IBaseObject.providedBy(self.context):
         return
     context_fti = self.context.getTypeInfo()
     if IDexterityFTI.providedBy(context_fti):
         self.available = True
Ejemplo n.º 14
0
def unrestricted_create(container=None, portal_type=None,
                        id=None, title=None, transition=None, **kwargs):
    """Create content, bypassing security checks.

    XXX: this would be a bit cleaner if we used api.env.adopt_roles,
    but it doesn't seem to work properly..

    XXX 2: Verbose security needs to be turned on in buildout to make
    this method work. WTF! We need to fix this.

    :param container: container for the created object
    :param portal_type: type of the object to create
    :param id: id of the object to create
    :param title: title of the object to create
    :param transition: name of a workflow transition to perform after
        creation
    :param kwargs: additional parameters which are passed to the
        createContent function (e.g. title, description etc.)
    :returns: object that was created
    """
    portal_types = api.portal.get_tool("portal_types")
    type_info = portal_types.getTypeInfo(portal_type)
    content_id = id or str(random.randint(0, 99999999))
    obj = type_info._constructInstance(
        container, content_id, title=title, **kwargs)

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

    if not id:
        # Create a new id from title
        chooser = INameChooser(container)
        derived_id = id or title
        new_id = chooser.chooseName(derived_id, obj)
        transaction.savepoint(optimistic=True)
        with api.env.adopt_roles(['Manager', 'Member']):
            obj.aq_parent.manage_renameObject(content_id, new_id)

    # perform a workflow transition
    if transition:
        with api.env.adopt_roles(['Manager', 'Member']):
            api.content.transition(obj, transition=transition)

    return obj
Ejemplo n.º 15
0
def migrateUIDs(portal, out):
    count = 0
    uc = getToolByName(portal, UID_CATALOG)
    print >>out, 'Migrating uids\n'

    # temporary add a new index
    if olduididx not in uc.indexes():
        uc.addIndex(olduididx, 'FieldIndex', extra=None)
        if not olduididx in uc.schema():
            uc.addColumn(olduididx)

    # clear UID Catalog
    uc.manage_catalogClear()

    # rebuild UIDS on objects and in catalog
    allbrains = portal.portal_catalog()
    for brain in allbrains:
        # get a uid for each thingie
        obj = brain.getObject()
        if not IBaseObject.providedBy(obj):
            continue  # its no Archetype instance, so leave it

        objUID = getattr(aq_base(obj), '_uid', None)
        if objUID is not None:  # continue  # not an old style AT?
            # this one can be part of the catalog
            setattr(obj, olduididx, objUID)
            delattr(obj, '_uid')
            setattr(obj, UUID_ATTR, None)
        obj._register()  # creates a new UID
        obj._updateCatalog(portal)  # to be sure
        count += 1
        if not count % 10:
            print >>out, '.',
        # avoid eating up all RAM
        if not count % 250:
            print >>out, '*',
            transaction.savepoint(optimistic=True)
    print >>out, '\nDone\n'
    if USE_FULL_TRANSACTIONS:
        transaction.commit()
    else:
        transaction.savepoint(optimistic=True)

    print >>out, count, "UID's migrated."
Ejemplo n.º 16
0
def migrateUIDs(portal, out):
    count = 0
    uc = getToolByName(portal, UID_CATALOG)
    print >> out, 'Migrating uids\n'

    # temporary add a new index
    if olduididx not in uc.indexes():
        uc.addIndex(olduididx, 'FieldIndex', extra=None)
        if not olduididx in uc.schema():
            uc.addColumn(olduididx)

    # clear UID Catalog
    uc.manage_catalogClear()

    # rebuild UIDS on objects and in catalog
    allbrains = portal.portal_catalog()
    for brain in allbrains:
        # get a uid for each thingie
        obj = brain.getObject()
        if not IBaseObject.providedBy(obj):
            continue  # its no Archetype instance, so leave it

        objUID = getattr(aq_base(obj), '_uid', None)
        if objUID is not None:  # continue  # not an old style AT?
            # this one can be part of the catalog
            setattr(obj, olduididx, objUID)
            delattr(obj, '_uid')
            setattr(obj, UUID_ATTR, None)
        obj._register()  # creates a new UID
        obj._updateCatalog(portal)  # to be sure
        count += 1
        if not count % 10:
            print >> out, '.',
        # avoid eating up all RAM
        if not count % 250:
            print >> out, '*',
            transaction.savepoint(optimistic=True)
    print >> out, '\nDone\n'
    if USE_FULL_TRANSACTIONS:
        transaction.commit()
    else:
        transaction.savepoint(optimistic=True)

    print >> out, count, "UID's migrated."
Ejemplo n.º 17
0
def reindex_object(obj, recursive=0):
    """reindex the given object.

    If 'recursive' is true then also take reindex of all sub-objects.
    """
    if not IBaseObject.providedBy(obj):
        return

    try:
        catalog_object(obj)
        # Also reindex AT References
        if hasattr(obj, 'at_references'):
            refs = getattr(obj.at_references, 'objectValues', lambda: ())()
            for ref in refs:
                catalog_object(ref)
    except Exception, err:
        logger.warn("Couldn't reindex obj --> %s",
                    getattr(obj, 'absolute_url', lambda: 'None')())
        logger.exception(err)
 def update(self):
     self.available = False
     if not HAS_ARCHETYPES:
         return
     self.context = aq_inner(self.context)
     replaced_types = [
         "ATFolder",
         "ATDocument",
         "ATFile",
         "ATImage",
         "ATNewsItem",
         "ATLink",
         "ATEvent",
         "ATBlobImage",
         "ATBlobFile",
         "Collection",
     ]
     if self.context.meta_type not in replaced_types:
         return
     if not IBaseObject.providedBy(self.context):
         return
     context_fti = self.context.getTypeInfo()
     if IDexterityFTI.providedBy(context_fti):
         self.available = True
Ejemplo n.º 19
0
    def __call__(self):
        wrapped = IndexableObjectWrapper(self.context, self.catalog)
        text = getattr(wrapped, 'SearchableText')
        if safe_callable(text):
            text = text()

        # Archetypes object: remove id and title
        if IBaseObject.providedBy(self.context):
            for fieldname in ['id', 'title']:
                field = self.context.Schema().getField(fieldname)
                if field is None:
                    continue

                method = field.getIndexAccessor(self.context)
                value = method()
                text = text.replace(value, '', 1)
        # other content (e.g. dexterity): remove title
        elif IContentish.providedBy(self.context):
            text = text.replace(self.context.Title(), '', 1)

        # Strip html tags
        text = re.sub('<[^<]+?>', '', text)

        return text
Ejemplo n.º 20
0
def create(
    container=None,
    type=None,
    id=None,
    title=None,
    safe_id=False,
    **kwargs
):
    """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:
        if ISiteRoot.providedBy(container):
            allowed_types = container.allowedContentTypes()
            types = [allowed_type.id for allowed_type in allowed_types]
        else:
            try:
                types = container.getLocallyAllowedTypes()
            except AttributeError:
                raise InvalidParameterError(
                    "Cannot add a '%s' object to the container." % type
                )

        raise InvalidParameterError(
            "Cannot add a '{0}' object to the container.\n"
            "Allowed types are:\n"
            "{1}\n"
            "{2}".format(type, '\n'.join(sorted(types)), 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()

    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
Ejemplo n.º 21
0
    def get_translated_id(self, id, lang, event=True):
        """ Returns a translated ID of the object with the given ID and in the given language
        """
        id = safe_unicode(id)
        try:
            if not id in self.context:
                return id
        except:
            return id
        if not lang in self.storage:
            self.storage[lang] = OOBTree()
        if not id in self.storage[lang]:
            field = None
            try:
                obj = self.context[id]
                if IBaseObject.providedBy(obj) and (obj.isTemporary() or obj._isIDAutoGenerated(id)):
                    return id
                field = obj.Schema()['title']
                if not IMultilanguageField.providedBy(field):
                    return id

                field.setLanguage(lang)
                new_id = obj.generateNewId()
                field.resetLanguage()

                if new_id is None:
                    new_id = str('%s-%s' % (lang,id))
                if (not 'index' in self.storage or
                    not new_id in self.storage['index'] or
                    not self.storage['index'][new_id] == id) and not new_id == id:
                    invalid_id = False
                    check_id = getattr(obj, 'check_id', None)
                    if check_id is not None:
                        invalid_id = check_id(new_id, required=1)

                    # If check_id told us no, or if it was not found, make sure we have an
                    # id unique in the parent folder.
                    if invalid_id:
                        unique_id = obj._findUniqueId(new_id)
                        if unique_id is not None:
                            if check_id is None or check_id(new_id, required=1):
                                new_id = unique_id
                                invalid_id = False

                    if invalid_id:
                        new_id = id

                if self.get_actual_id(new_id) is not None:
                    new_id = '%s-%s' % (lang,new_id)
                new_id = safe_unicode(new_id)
                self.storage[lang][id] = new_id
                if not 'index' in self.storage:
                    self.storage['index'] = OOBTree()
                self.storage['index'][new_id] = id
                if event:
                    self.dispatchEvent(id)
            except ConflictError:
                if field is not None and IMultilanguageField.providedBy(field):
                    field.resetLanguage()
                raise
            except:
                if field is not None and IMultilanguageField.providedBy(field):
                    field.resetLanguage()
                return id
        return self.storage[lang][id]
Ejemplo n.º 22
0
def install_indexes(self, out, types):
    portal_catalog = catalog = getToolByName(self, 'portal_catalog')
    for cls in types:
        if 'indexes' not in cls.installMode:
            continue

        for field in cls.schema.fields():
            if not field.index:
                continue

            if isinstance(field.index, basestring):
                index = (field.index,)
            elif isinstance(field.index, (tuple, list)):
                index = field.index
            else:
                raise SyntaxError("Invalid Index Specification %r"
                                  % field.index)

            for alternative in index:
                installed = None
                index_spec = alternative.split(':', 1)
                use_column = 0
                if len(index_spec) == 2 and index_spec[1] in ('schema', 'brains'):
                    use_column = 1
                index_spec = index_spec[0]

                accessor = field.getIndexAccessorName()

                parts = index_spec.split('|')
                # we want to be able to specify which catalog we want to use
                # for each index. syntax is
                # index=('member_catalog/:schema',)
                # portal catalog is used by default if not specified
                if parts[0].find('/') > 0:
                    str_idx = parts[0].find('/')
                    catalog_name = parts[0][:str_idx]
                    parts[0] = parts[0][str_idx + 1:]
                    catalog = getToolByName(self, catalog_name)
                else:
                    catalog = portal_catalog

                #####################
                # add metadata column

                # lets see if the catalog is itself an Archetype:
                isArchetype = IBaseObject.providedBy(catalog)
                # archetypes based zcatalogs need to provide a different method
                # to list its schema-columns to not conflict with archetypes
                # schema
                hasNewWayMethod = hasattr(catalog, 'zcschema')
                hasOldWayMethod = not isArchetype and hasattr(
                    catalog, 'schema')
                notInNewWayResults = hasNewWayMethod and accessor not in catalog.zcschema()
                notInOldWayResults = hasOldWayMethod and accessor not in catalog.schema()
                if use_column and (notInNewWayResults or notInOldWayResults):
                    try:
                        catalog.addColumn(accessor)
                    except:
                        import traceback
                        traceback.print_exc(file=out)

                ###########
                # add index

                # if you want to add a schema field without an index
                # if not parts[0]:
                #    continue

                for itype in parts:
                    extras = itype.split(',')
                    if len(extras) > 1:
                        itype = extras[0]
                        props = Extra()
                        for extra in extras[1:]:
                            name, value = extra.split('=')
                            setattr(props, name.strip(), value.strip())
                    else:
                        props = None
                    try:
                        # Check for the index and add it if missing
                        catalog.addIndex(accessor, itype,
                                         extra=props)
                        catalog.manage_reindexIndex(ids=(accessor,))
                    except:
                        # FIXME: should only catch "Index Exists"
                        # damned string exception !
                        pass
                    else:
                        installed = 1
                        break

                if installed:
                    break
Ejemplo n.º 23
0
            except AttributeError:
                raise InvalidParameterError(
                    "Cannot add a '%s' object to the container." % type
                )

        raise InvalidParameterError(
            "Cannot add a '{0}' object to the container.\n"
            "Allowed types are:\n"
            "{1}\n"
            "{2}".format(type, '\n'.join(sorted(types)), 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()

    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.
Ejemplo n.º 24
0
def create(container=None,
           type=None,
           id=None,
           title=None,
           safe_id=False,
           **kwargs):
    """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:
        if ISiteRoot.providedBy(container):
            allowed_types = container.allowedContentTypes()
            types = [allowed_type.id for allowed_type in allowed_types]
        else:
            try:
                types = container.getLocallyAllowedTypes()
            except AttributeError:
                raise InvalidParameterError(
                    "Cannot add a '%s' object to the container." % type)

        raise InvalidParameterError(
            "Cannot add a '{0}' object to the container.\n"
            "Allowed types are:\n"
            "{1}\n"
            "{2}".format(type, '\n'.join(sorted(types)), 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()

    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
Ejemplo n.º 25
0
def create(container=None,
           type=None,
           id=None,
           title=None,
           strict=True,
           **kwargs):
    """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 strict: When True, the given id will be enforced. If the id is
        conflicting with another object in the target container, raise a
        KeyError. When False, ``create`` creates a new, non-conflicting id.
    :type strict: boolean
    :returns: Content object

    :Example: :ref:`content_create_example`
    """
    if not container:
        raise ValueError('The ``container`` attribute is required.')

    if not type:
        raise ValueError('The ``type`` attribute is required.')

    if not id and not title:
        raise ValueError('You have to provide either the ``id`` or the '
                         '``title`` attribute')

    # Create a temporary id if the id is not given
    content_id = strict and id or str(random.randint(0, 99999999))

    if title:
        kwargs['title'] = title

    container.invokeFactory(type, content_id, **kwargs)
    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()

    if not id or (not strict 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