def _items(self, **query): adapter = IAdapter(self.context) sort_limit = adapter.get_feed_number(self.interface) if sort_limit: query['sort_limit'] = sort_limit if isinstance(self, BaseNewsEventFeedViewlet): query['sort_limit'] += adapter.get_feed_number(ITopPageMainFeed) base = IBaseAdapter(self.context) res = [] for item in base.get_content_listing(**query): obj = item.getObject() if not isinstance(self, BaseNewsEventFeedViewlet) or ( ISiteRoot.providedBy(self.context) and not ITopPageFeed.providedBy(obj)) or ( not ISiteRoot.providedBy(self.context) and INavigationRoot.providedBy(self.context) and not IMicroSiteFeed.providedBy(obj)): parent = aq_parent(aq_inner(obj)) res.append({ 'title': item.Title(), 'url': item.getURL(), 'parent_title': parent.Title(), 'parent_url': parent.absolute_url(), 'date': self._date(item), 'image': self._image(item), 'description': self._description(item), }) if sort_limit: return res[:sort_limit] return res
def acquired_rules(self): # Short circuit if this is the root of the portal if ISiteRoot.providedBy(self.context): return [] in_use = set([r['id'] for r in self.assigned_rules()]) storage = getUtility(IRuleStorage) events = self._events() assignments = [] context = aq_parent(aq_inner(self.context)) while context is not None: assignable = IRuleAssignmentManager(context, None) if assignable is not None: for key, assignment in assignable.items(): if key not in in_use and assignment.bubbles: rule = storage.get(key, None) if rule is not None: assignments.append(dict(id=key, title=rule.title, description=rule.description, trigger=events.get(rule.event, "Unknown"), url=context.absolute_url() + '/@@manage-content-rules', enabled=(assignment.enabled and rule.enabled), )) if ISiteRoot.providedBy(context): context = None else: context = aq_parent(context) return assignments
def execute(context, event): """Execute all rules relative to the context, and bubble as appropriate. """ # Do nothing if there is no rule storage or it is not active storage = queryUtility(IRuleStorage) if storage is None or not storage.active: return init() rule_filter = _status.rule_filter # Stop if someone else is already executing. This could happen if, # for example, a rule triggered here caused another event to be fired. # We continue if we are in the context of a 'cascading' rule. if rule_filter.in_progress and not rule_filter.cascade: return # Tell other event handlers to be equally kind rule_filter.in_progress = True # Prepare to break hard if a rule demanded execution be stopped try: # Try to execute rules in the context. It may not work if the context # is not a rule executor, but we may still want to bubble events executor = IRuleExecutor(context, None) if executor is not None: executor(event, bubbled=False, rule_filter=rule_filter) # Do not bubble beyond the site root if not ISiteRoot.providedBy(context): parent = aq_parent(aq_inner(context)) while parent is not None: executor = IRuleExecutor(parent, None) if executor is not None: executor(event, bubbled=True, rule_filter=rule_filter) if ISiteRoot.providedBy(parent): parent = None else: parent = aq_parent(aq_inner(parent)) except StopRule: pass # We are done - other events that occur after this one will be allowed to # execute rules again rule_filter.in_progress = False
def isSiteRoot(self, ob): """ Returns a boolean value indicating if the object is an ISiteRoot or the default page of an ISiteRoot. """ siteroot = ISiteRoot.providedBy(ob) if siteroot: return True parent = aq_parent(ob) if ISiteRoot.providedBy(parent): if getattr(ob, "isPrincipiaFolderish", False) and ob.isPrincipiaFolderish: # We are looking at a folder in the root return False # We are at a non-folderish item in the root return True return False
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 ValueError, 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) )
def getInitialTree(self): '''Returns the initial tree for the dynatree.''' context = self.getFolderishParent(self.context) child_tree = None child_uid = None while True: is_root = ISiteRoot.providedBy(context) if is_root: uid = None else: uid = IUUID(context) tree = self.get_tree(uid) if child_tree is not None: self._insert_child_tree(tree, child_tree, child_uid) if is_root: break context = aq_parent(context) child_tree = tree child_uid = uid root_node = self.getRootNode() root_node['children'] = tree return simplejson.dumps(root_node)
def containing_subdossier(obj): """Returns the title of the subdossier the object is contained in, unless it's contained directly in the root of a dossier, in which case an empty string is returned. """ context = aq_inner(obj) # Only compute for types that actually can be contained in a dossier if not context.portal_type in ['opengever.document.document', 'opengever.task.task', 'ftw.mail.mail']: return '' parent = context parent_dossier = None parent_dossier_found = False while not parent_dossier_found: parent = aq_parent(parent) if ISiteRoot.providedBy(parent): # Shouldn't happen, just to be safe break if IDossierMarker.providedBy(parent): parent_dossier_found = True parent_dossier = parent if IDossierMarker.providedBy(aq_parent(parent_dossier)): # parent dossier is a subdossier return parent_dossier.Title() return ''
def _get_translations_by_dialog(self, supported_langs): """ """ context = aq_inner(self.context) default_view_for = getMultiAdapter((context, self.request), name='plone_context_state').canonical_object() _checkPermission = getSecurityManager().checkPermission translations = {} if ISiteRoot.providedBy(context): # We have a site root, which works as a fallback for code in supported_langs: has_view_permission = bool(_checkPermission('View', context)) translations[code] = (context, True, has_view_permission) elif INavigationRoot.providedBy(default_view_for): for code, content in ITranslationManager(default_view_for).get_translations().items(): code = str(code) has_view_permission = bool(_checkPermission('View', content)) translations[code] = (content, True, has_view_permission) else: for code, content in ITranslationManager(context).get_translations().items(): code = str(code) has_view_permission = bool(_checkPermission('View', content)) translations[code] = (content, True, has_view_permission) return translations
def __call__(self): cfg = authomatic_cfg() if cfg is None: return "Authomatic is not configured" if not ( ISiteRoot.providedBy(self.context) or INavigationRoot.providedBy(self.context) ): # callback url is expected on either navigationroot or site root # so bevor going on redirect root = api.portal.get_navigation_root(self.context) self.request.response.redirect( "{0}/authomatic-handler/{1}".format( root.absolute_url(), getattr(self, 'provider', '') ) ) return "redirecting" if not hasattr(self, 'provider'): return self.template() if self.provider not in cfg: return "Provider not supported" if not self.is_anon: if self.provider in self._provider_names: raise ValueError( 'Provider {0} is already connected to current ' 'user.'.format(self.provider) ) # TODO: some sort of CSRF check might be needed, so that # not an account got connected by CSRF. Research needed. pass auth = Authomatic( cfg, secret=authomatic_settings().secret.encode('utf8') ) result = auth.login( ZopeRequestAdapter(self), self.provider ) if not result: logger.info('return from view') # let authomatic do its work return if result.error: return result.error.message display = cfg[self.provider].get('display', {}) provider_name = display.get('title', self.provider) if not self.is_anon: # now we delegate to PAS plugin to add the identity self._add_identity(result, provider_name) self.request.response.redirect( "{0}".format(self.context.absolute_url()) ) else: # now we delegate to PAS plugin in order to login self._remember_identity(result, provider_name) self.request.response.redirect( "{0}/login_success".format(self.context.absolute_url()) ) return "redirecting"
def getPortal(self): ob = aq_inner(self.object) while ob is not None: if ISiteRoot.providedBy(ob): return ob ob = aq_parent(ob) return None
def _get_acquisiton_value(self): context = self.context if isinstance(context, MetadataBase) or context is None: # we do not test the factory, it is not acquisition wrapped and # we cant get the request... return None request = self.context.REQUEST # XXX CHANGED FROM PATH_TRANSLATED TO PATH_INFO # because the test don't work if '++add++' in request.get('PATH_INFO', ''): # object is not yet existing, context is container obj = context else: # object is existing, container is parent of context obj = context.aq_inner.aq_parent while not ISiteRoot.providedBy(obj): try: return self.field.get(obj) except AttributeError: try: interface_ = self.field.interface except AttributeError: pass else: try: adpt = interface_(obj) except TypeError: # could not adapt pass else: return self.field.get(adpt) obj = obj.aq_inner.aq_parent return self.field.default
def default_value_generator(data): obj = data.context # try to get it from context or a parent while not ISiteRoot.providedBy(obj): try: interface_ = data.field.interface except AttributeError: pass else: try: adpt = interface_(obj) except TypeError: # could not adapt pass else: value = data.field.get(adpt) if value is not None: return value obj = aq_parent(aq_inner(obj)) # otherwise use default value if field._acquisition_default: return field._acquisition_default else: # use first value try: return tuple(data.widget.terms)[0].value except AttributeError: return None
def heading_link_target(self): """ Get the href target where clicking the portlet header will take you. If this is a customized portlet with a custom root item set, we probably want to take the user to the custom root item instead of the sitemap of the navigation root. Plone does not have subsection sitemaps so there is no point of displaying /sitemap links for anything besides nav root. """ if not self.data.root: # No particular root item assigned -> should get link to the # navigation root sitemap of the current context acquisition chain portal_state = getMultiAdapter((self.context, self.request), name="plone_portal_state") return portal_state.navigation_root_url() + "/sitemap" nav_root = self.getNavRoot() # Root content item gone away or similar issue if not nav_root: return None if INavigationRoot.providedBy(nav_root) or ISiteRoot.providedBy(nav_root): # For top level folders go to the sitemap return nav_root.absolute_url() + "/sitemap" else: # Go to the item /view we have chosen as root item return nav_root.absolute_url()
def get_plone_root(ctx): obj = aq_inner(ctx) while obj is not None: if ISiteRoot.providedBy(obj): break obj = aq_parent(obj) return obj
def containing_subdossier(obj): """Returns the title of the subdossier the object is contained in, unless it's contained directly in the root of a dossier, in which case an empty string is returned. """ if obj.portal_type not in TYPES_WITH_CONTAINING_SUBDOSSIER_INDEX: return '' context = aq_inner(obj) parent = context parent_dossier = None parent_dossier_found = False while not parent_dossier_found: parent = aq_parent(parent) if ISiteRoot.providedBy(parent): # Shouldn't happen, just to be safe break if IDossierMarker.providedBy(parent): parent_dossier_found = True parent_dossier = parent if IDossierMarker.providedBy(aq_parent(parent_dossier)): # parent dossier is a subdossier return parent_dossier.Title() return ''
def _acquire_value(self, context): if isinstance(context, MetadataBase) or context is None: # we do not test the factory, it is not acquisition wrapped and # we cant get the request... return None request = context.REQUEST if IDuringContentCreation.providedBy(request): # object does not yet exist, context is container (add) container = context elif ISiteRoot.providedBy(context): # The context is the siteroot when using the /@types endpoint # from the plone rest-api. # See https://github.com/4teamwork/opengever.core/issues/5283 container = context else: # object already exists, container is parent of context (edit) container = context.aq_inner.aq_parent acquired_value = acquire_field_value(self.field, container) # Use acquired value if one was found if acquired_value is not NO_VALUE_FOUND: return acquired_value # Otherwise fall back to static field default # # NOTE: We deliberately avoid accessing field.default, because doing # so would invoke a defaultFactory if present return self.field.__dict__.get('default', None)
def details(self, context=None): # fetch details about dataset, if attributes are unpopulated # get data from associated collection if context is None: context = self.context coll = context while not (ISiteRoot.providedBy(coll) or ICollection.providedBy(coll)): coll = coll.__parent__ # we have either hit siteroot or found a collection ret = { 'title': context.title, 'description': context.description or coll.description, 'attribution': context.attribution or getattr(coll, 'attribution'), 'rights': context.rights or coll.rights, 'external_description': context.external_description or getattr(coll, 'external_description'), } md = IBCCVLMetadata(context) if 'layers' in md: layers = [] for layer in sorted(md.get('layers', ())): try: layers.append(self.layer_vocab.getTerm(layer)) except: layers.append(SimpleTerm(layer, layer, layer)) if layers: ret['layers'] = layers return ret
def can_translate(context, language): """ Check if required parent translations are in place so that we can translate this item :return: True if the item can be translated """ parent = aq_parent(context) if ISiteRoot.providedBy(parent): return True # Parent is a language base folder at plone site root if INavigationRoot.providedBy(parent): return True if ITranslatable.providedBy(parent): translatable = ITranslatable(parent) else: from logging import getLogger log = getLogger("silvuple.views.can_translate") log.info("Parent is not translatable: %s" % parent.absolute_url()) return False translation = translatable.getTranslation(language) return translation is not None
def organise(self): """Helper method to generate the menu items for organising content (copy/paste/etc.). If no organising actions are available None is returned. """ context = aq_inner(self.context) context_url = context.absolute_url() is_root = ISiteRoot.providedBy(context) pa = getToolByName(context, "portal_actions") actions = pa.listActions(object=context, categories=("folder_buttons",), ignore_categories=None) ec = pa._getExprContext(context) actions = [ActionInfo(action, ec) for action in actions] menu = {"title": _("menu_organise", default=u"Organise")} children = menu["children"] = [] for a in actions: if a["visible"] and a["allowed"] and a["available"] and not is_root: if a["id"] == "copy" and context.cb_isCopyable(): children.append({"title": _("menu_copy", default=u"Copy"), "url": "%s/@@copy" % context_url}) elif a["id"] == "cut" and context.cb_isMoveable(): children.append({"title": _("menu_cut", default=u"Cut"), "url": "%s/@@cut" % context_url}) elif a["id"] == "paste" and ICopyContainer.providedBy(context): children.append({"title": _("menu_paste", default=u"Paste"), "url": "%s/@@paste" % context_url}) elif a["id"] == "delete": children.append({"title": _("menu_delete", default=u"Delete"), "url": "%s/@@delete" % context_url}) if children: return menu
def disallow_anonymous_views_on_site_root(event): """Do not allow access for anonymous to views on the portal root except those explicitly allowed here. We do it this way because we cannot revoke the view permissions for anonymous on the portal root. The same applies for tabbed_view attributes of a tabbed_view that is displayed for the portal root. """ if getSecurityManager().getUser() != nobody: return # Find the first physical / persistent object in the PARENTS # by filtering all non-persist parents (views, widgets, ...). context = filter(IItem.providedBy, event.request['PARENTS'])[0] if not ISiteRoot.providedBy(context): return endpoint_name = event.request['PUBLISHED'].__name__ if endpoint_name in ALLOWED_ENDPOINTS: return views = filter(IBrowserView.providedBy, event.request['PARENTS']) if len(views) > 0 and views[0].__name__ in ALLOWED_ENDPOINTS: return raise Unauthorized
def update(self): super(View, self).update() messages = IStatusMessage(self.request) context = aq_inner(self.context) self.context = context self.state = getMultiAdapter( (context, self.request), name=u'plone_context_state') self.wf_state = self.state.workflow_state() self.utility = context.utility # Handle vote form = self.request.form self.errors = [] self.messages = [] #if the poll is open and anonymous should vote but the parent folder #is private.. inform the user. # When the poll's container is the site's root, we do not need to # check the permissions. container = aq_parent(aq_inner(self.context)) if 'open' == self.wf_state and not ISiteRoot.providedBy(container): roles = [ r['name'] for r in self.context.rolesOfPermission('collective.polls: Vote') if r['selected']] if 'Anonymous' not in roles and self.context.allow_anonymous: messages.addStatusMessage(_( u"Anonymous user won't be able to vote, you forgot to " u"publish the parent folder, you must sent back the poll " u"to private state, publish the parent folder and open " u"the poll again"), type="info") INVALID_OPTION = _(u'Invalid option') if 'poll.submit' in form: options = form.get('options', '') if isinstance(options, list): self.errors.append(INVALID_OPTION) elif isinstance(options, str): if not options.isdigit(): self.errors.append(INVALID_OPTION) else: options = int(options) if not self.errors: # Let's vote try: self.context.setVote(options, self.request) self.messages.append(_(u'Thanks for your vote')) # We do this to avoid redirecting anonymous user as # we just sent them the cookie self._has_voted = True except Unauthorized: self.errors.append(_(u'You are not authorized to vote')) # Update status messages for error in self.errors: messages.addStatusMessage(error, type="warn") for msg in self.messages: messages.addStatusMessage(msg, type="info")
def reload_template(root): counter = 0 for obj in root.objectValues(): if ISiteRoot.providedBy(obj): tool = getToolByName(obj, 'portal_skins', None) if tool is not None: counter = reload_skins(tool) return counter
def payment_properties(self): context = aq_inner(self.context) if ISiteRoot.providedBy(context): properties = getToolByName(context, 'portal_properties') prop = getattr(properties, 'collective_pfg_payment_properties') if IPloneFormGenForm.providedBy(context): prop = IAnnotations(context)['collective.pfg.payment'] return IProperties(prop)
def get_uid(obj): """ get the UID of the brain/object """ if ICatalogBrain.providedBy(obj): return obj.UID if ISiteRoot.providedBy(obj): return "siteroot" return obj.UID()
def _translations(self, missing): # Figure out the "closest" translation in the parent chain of the # context. We stop at both an INavigationRoot or an ISiteRoot to look # for translations. # Exceptions: 1) If the object does not implement ITranslatable (= not # LP-aware) or # 2) if the object is set to be neutral # then return this object and don't look for a translation. context = aq_inner(self.context) translations = {} chain = aq_chain(context) first_pass = True _checkPermission = getSecurityManager().checkPermission for item in chain: if ISiteRoot.providedBy(item) \ or not ITranslatable.providedBy(item) \ or not item.Language(): # We have a site root, which works as a fallback has_view_permission = bool(_checkPermission('View', item)) for c in missing: translations[c] = (item, first_pass, has_view_permission) break translatable = ITranslatable(item, None) if translatable is None: continue item_trans = item.getTranslations(review_state=False) for code, trans in item_trans.items(): code = str(code) if code not in translations: # make a link to a translation only if the user # has view permission has_view_permission = bool(_checkPermission('View', trans)) if (not INavigationRoot.providedBy(item) and not has_view_permission): continue # If we don't yet have a translation for this language # add it and mark it as found translations[code] = (trans, first_pass, has_view_permission) missing = missing - set((code, )) if len(missing) <= 0: # We have translations for all break if INavigationRoot.providedBy(item): # Don't break out of the navigation root jail has_view_permission = bool(_checkPermission('View', item)) for c in missing: translations[c] = (item, False, has_view_permission) break first_pass = False # return a dict of language code to tuple. the first tuple element is # the translated object, the second argument indicates wether the # translation is a direct translation of the context or something from # higher up the translation chain return translations
def get_parent_book(self): context = self.context while context and not ISiteRoot.providedBy(context): if IBook.providedBy(context): return context context = aq_parent(aq_inner(context)) return None
def is_portal(brain_or_object): """Checks if the passed in object is the portal root object :param brain_or_object: A single catalog brain or content object :type brain_or_object: ATContentType/DexterityContentType/CatalogBrain :returns: True if the object is the portal root object :rtype: bool """ return ISiteRoot.providedBy(brain_or_object)
def searchContent(context): # getSide() returns INavigationRoot Object siteroot = getSite() # if INavigationRoot != ISideRoot if not ISiteRoot.providedBy(context): for item in getSite().aq_chain: if ISiteRoot.providedBy(item): siteroot = item path = '/'.join(siteroot.getPhysicalPath()) # all Languages query = {"path": {'query': path}, "Language": 'all' } return ObjPathSourceBinder(navigation_tree_query=query)(context)
def current_section(self, context=None): """Return the current section, used to determine headers etc.""" if not context: context = aq_inner(self.context) if ISection.providedBy(context): return context if ISiteRoot.providedBy(context): return None return self.current_section(context=context.__parent__)
def _translations(self, missing): # Figure out the "closest" translation in the parent chain of the # context. We stop at both an INavigationRoot or an ISiteRoot to look # for translations. We do want to find something that is definitely # in the language the user asked for. context = aq_inner(self.context) translations = {} chain = aq_chain(context) first_pass = True _checkPermission = getSecurityManager().checkPermission for item in chain: if ISiteRoot.providedBy(item): # We have a site root, which works as a fallback has_view_permission = bool(_checkPermission('View', item)) for c in missing: translations[c] = (item, first_pass, has_view_permission) break elif IFactoryTempFolder.providedBy(item) or \ IFactoryTool.providedBy(item): # TempFolder or portal_factory, can't have a translation continue canonical = ITranslationManager(item, None) item_trans = canonical.get_translations() for code, trans in item_trans.items(): code = str(code) if code not in translations: # make a link to a translation only if the user # has view permission has_view_permission = bool(_checkPermission('View', trans)) if (not INavigationRoot.providedBy(item) and not has_view_permission): continue # If we don't yet have a translation for this language # add it and mark it as found translations[code] = (trans, first_pass, has_view_permission) missing = missing - set((code, )) if len(missing) <= 0: # We have translations for all break if INavigationRoot.providedBy(item): # Don't break out of the navigation root jail has_view_permission = bool(_checkPermission('View', item)) for c in missing: translations[c] = (item, False, has_view_permission) break first_pass = False # return a dict of language code to tuple. the first tuple element is # the translated object, the second argument indicates wether the # translation is a direct translation of the context or something from # higher up the translation chain return translations
def has_private_parents(obj): if (api.content.get_state(obj) != 'published'): return True # needs to be True for private self as well as parents parent = aq_parent(obj) while not ISiteRoot.providedBy(parent): try: parent_brain = get_brain(parent.UID()) try: if parent_brain.has_private_parents: return True except AttributeError: if api.content.get_state(parent) != 'published': return True except Exception: pass # to be extra secure, could return True here. Better to be fault tolerant for now. parent = aq_parent(parent) return False
def organise(self): """Helper method to generate the menu items for organising content (copy/paste/etc.). If no organising actions are available None is returned. """ context = aq_inner(self.context) context_url = context.absolute_url() is_root = ISiteRoot.providedBy(context) pa = getToolByName(context, 'portal_actions') actions = pa.listActions(object=context, categories=('folder_buttons', ), ignore_categories=None) ec = pa._getExprContext(context) actions = [ActionInfo(action, ec) for action in actions] menu = {"title": _("menu_organise", default="Organise")} children = menu["children"] = [] for a in actions: if a['visible'] and a['allowed'] \ and a['available'] and not is_root: if a['id'] == 'copy' and context.cb_isCopyable(): children.append({ "title": _("menu_copy", default="Copy"), "url": "%s/@@copy" % context_url }) elif a['id'] == 'cut' and context.cb_isMoveable(): children.append({ "title": _("menu_cut", default="Cut"), "url": "%s/@@cut" % context_url }) elif a['id'] == 'paste' and ICopyContainer.providedBy(context): children.append({ "title": _("menu_paste", default="Paste"), "url": "%s/@@paste" % context_url }) elif a['id'] == 'delete': children.append({ "title": _("menu_delete", default="Delete"), "url": "%s/@@delete" % context_url }) if children: return menu
def getPortal(self): ob = aq_inner(self.object) while ob is not None: if ISiteRoot.providedBy(ob): return ob if getattr(ob, '_isPortalRoot', None) is not None: # BBB warn( "The '_isPortalRoot' marker attribute for site " "roots is deprecated and will be removed in " "CMF 2.3; please mark the root object with " "'ISiteRoot' instead.", DeprecationWarning, stacklevel=2) return ob ob = aq_parent(ob) return None
def import_(self, import_context, subdir): """ See IFilesystemImporter. """ context = self.context if not ISiteRoot.providedBy(context): subdir = '%s/%s' % (subdir, context.getId()) preserve = import_context.readDataFile('.preserve', subdir) prior = context.contentIds() if not preserve: preserve = [] else: preserve = _globtest(preserve, prior) for id in prior: if id not in preserve: context._delObject(id) objects = import_context.readDataFile('.objects', subdir) if objects is None: return dialect = 'excel' stream = StringIO(objects) rowiter = reader(stream, dialect) existing = context.objectIds() for object_id, portal_type in rowiter: if object_id not in existing: object = self._makeInstance(object_id, portal_type, subdir, import_context) if object is None: message = "Couldn't make instance: %s/%s" % (subdir, object_id) import_context.note('SFWA', message) continue wrapped = context._getOb(object_id) IFilesystemImporter(wrapped).import_(import_context, subdir)
def fix_permissions(poll, event): ''' This subscriber will fix permission on poll object if allow_anonymous is enabled ''' if event.action in [ 'open', ]: parent = aq_parent(poll) parent_view_roles = parent.rolesOfPermission('View') parent_view_roles = [ r['name'] for r in parent_view_roles if r['selected'] ] # Poll has been opened allow_anonymous = poll.allow_anonymous parent_is_root = ISiteRoot.providedBy(parent) parent_allow_anon = 'Anonymous' in parent_view_roles if (parent_allow_anon or parent_is_root) and allow_anonymous: poll.manage_permission(PERMISSION_VOTE, ALL_ROLES, acquire=0)
def __call__(self): value = self._getFormValue() if value is None or value == self.context.missing_value: value = '' # Evil acquisition majik to find the site root. This is made tricky # by the fact that the widget doesn't have a direct path to its # context (you can go self.context.context, but this may be an # adapter on the context, not the context itself.). We can find # the root using getUtility(ISiteRoot), but this isn't wrapped # in the request container. We can use getSite(), but there may be # other sites in-between, not at least the KSS site-in-a-view. Sigh. site = getSite() while site is not None and not ISiteRoot.providedBy(site): site = aq_parent(site) return self.template(form_context=site, value=value)
def __call__(self): cfg = authomatic_cfg() if cfg is None: return "Authomatic is not configured" if not (ISiteRoot.providedBy(self.context) or INavigationRoot.providedBy(self.context)): # callback url is expected on either navigationroot or site root # so bevor going on redirect root = api.portal.get_navigation_root(self.context) self.request.response.redirect("{}/authomatic-handler/{}".format( root.absolute_url(), getattr(self, "provider", ""))) return "redirecting" if not getattr(self, "provider", None): return self.template() if self.provider not in cfg: return "Provider not supported" if not self.is_anon: if self.provider in self._provider_names: logger.warn( "Provider %s is already connected to current " "user.", self.provider) return self._redirect() # TODO: some sort of CSRF check might be needed, so that # not an account got connected by CSRF. Research needed. pass secret = authomatic_settings().secret auth = Authomatic(cfg, secret=secret) result = auth.login(ZopeRequestAdapter(self), self.provider) if not result: logger.info("return from view") # let authomatic do its work return if result.error: return result.error.message display = cfg[self.provider].get("display", {}) provider_name = display.get("title", self.provider) if not self.is_anon: # now we delegate to PAS plugin to add the identity self._add_identity(result, provider_name) else: # now we delegate to PAS plugin in order to login self._remember_identity(result, provider_name) return self._redirect()
def export(self, export_context, subdir): """ See IFilesystemExporter. """ # Enumerate exportable children exportable = self.context.contentItems() exportable = [x + (IFilesystemExporter(x, None), ) for x in exportable] exportable = [x for x in exportable if x[1] is not None] stream = StringIO() csv_writer = writer(stream) for object_id, object, ignored in exportable: csv_writer.writerow((object_id, object.getPortalTypeName())) if not ISiteRoot.providedBy(self.context): subdir = '%s/%s' % (subdir, self.context.getId()) export_context.writeDataFile( '.objects', text=stream.getvalue(), content_type='text/comma-separated-values', subdir=subdir, ) parser = ConfigParser() parser.set('DEFAULT', 'Title', self.context.Title()) parser.set('DEFAULT', 'Description', self.context.Description()) stream = StringIO() parser.write(stream) export_context.writeDataFile( '.properties', text=stream.getvalue(), content_type='text/plain', subdir=subdir, ) for id, object in self.context.objectItems(): adapter = IFilesystemExporter(object, None) if adapter is not None: adapter.export(export_context, subdir)
def acquire_field_value(field, container): """Acquire a value for a particular field from an object's container or its closest ancestor. This works similar to Zope's Acquisition, but also supports fields in behaviors with AnnotationStorage. The strategy for acquiring a field value can be described as follows: - Find the closest ancestor that: - Supports the field in question (intermediate ancestors that don't support the field are skipped) - Has a value for the field that validates - If no such ancestor can be found, return the NO_VALUE_FOUND sentinel """ if isinstance(container, MetadataBase) or container is None: # These are odd cases where we get passed a weird context and can't # (or don't want to) acquire an actual value. return NO_VALUE_FOUND obj = container while not ISiteRoot.providedBy(obj): try: interface_ = field.interface except AttributeError: pass else: try: adpt = interface_(obj) except TypeError: # could not adapt pass else: # XXX: Potential for infinite recursion here (Issue #2033) value = field.get(adpt) try: field.validate(value) return value except ValidationError: pass obj = obj.aq_inner.aq_parent return NO_VALUE_FOUND
def write_export(obj, data): objpath = '/'.join(obj.getPhysicalPath()) if IFolder.providedBy(obj): objpath = os.path.join(objpath, '__folder__') else: fobj = aq_parent(obj) while not ISiteRoot.providedBy(fobj): if not os.path.exists( os.path.join('/'.join(fobj.getPhysicalPath()), '__folder__')): # noqa for eobj, edata in export_obj(fobj): write_export(eobj, edata) fobj = aq_parent(fobj) path = create_path(objpath) try: fi = open(path, 'w') fi.write(dumps(data)) fi.close() except UnicodeDecodeError: print('Error exporting {}'.format(objpath))
def current_style(self, site_default_style): """Returns current stylesheet selection or site default.""" context = self.context while True: if ISiteRoot.providedBy(context): return site_default_style annotations = IAnnotations(context) curr_style = annotations.get(STYLESHEET_SELECTED_KEY) if curr_style: return curr_style if curr_style == '': return site_default_style context = aq_parent(context)
def check_traversal_to_acquired_content(context, request, name, result): if is_suspect_acquisition(context, request, name, result): logmsg = ( "when traversing '%s', (%s) is acquired from (%s)" % (request.get('ACTUAL_URL'), '/'.join(result.getPhysicalPath()), '/'.join(context.getPhysicalPath()))) referer = request.get('HTTP_REFERER', "none") if referer: logmsg += ", referred from %s" % referer logger.info(logmsg) if request['REQUEST_METHOD'] != 'GET': logger.info("no redirect because METHOD is '%s'", request.get('REQUEST_METHOD')) return if ISiteRoot.providedBy(result): request.set('IS_SITE_ACQUIRED', True) canonical_url = get_canonical_url(request, result.absolute_url()) # store CANONICAL_URL in order to be able to redirect later in traversal request.set('CANONICAL_URL', canonical_url)
def __call__(self): """ """ parents_type_list = [] for item in self.context.aq_chain: if item == self.context: # skip current context continue if ISiteRoot.providedBy(item): break parents_type_list.append(item.portal_type) try: parent_uid = self.context.aq_parent.UID() except AttributeError: parent_uid = "" return { "parents_type_list": parents_type_list, "parent_uid": parent_uid, }
def get_options(self): site_url = success_url = self.context.absolute_url() if ISiteRoot.providedBy(self.context): success_url += '/@@dashboard' if 'came_from' in self.request.form: came_from = self.request.form['came_from'] try: url_tool = api.portal.get_tool('portal_url') except api.exc.CannotGetPortalError: url_tool = None if (came_from.startswith(site_url) and (not url_tool or url_tool.isURLInPortal(came_from))): success_url = came_from data = { 'supportedAuthSchemes': self.get_supported_auth_schemes(), 'twoFactorEnabled': self.two_factor_enabled, 'apiEndpoint': '{}/@@secure-login'.format(site_url), 'successUrl': success_url, 'additionalProviders': [] } try: data['authenticator'] = createToken() except ConnectionStateError: # zope root related issue here... pass username = None pwreset = self.request.form.get('pwreset') == 'true' if pwreset: try: user = api.user.get(self.request.form.get('userid')) username = user.getUserName() data.update({ 'passwordReset': pwreset, 'username': username, 'code': self.request.form.get('code'), 'userid': self.request.form.get('userid') }) except Exception: pass return data
def save(self): adapted = ILayoutAware(self.context) data = self.request.form.get('data') if not data: return data = json.loads(data) adapted.pageSiteLayout = data['page_layout'] adapted.sectionSiteLayout = data['section_layout'] parent = aq_parent(self.context) if ISiteRoot.providedBy(parent): # check if default page... if getDefaultPage(parent) == self.context.id: # also set site wide global layout setting... registry = getUtility(IRegistry) field = registry_field.TextLine(title=u'Default layout', required=False) new_record = Record(field) registry.records['castle.cms.default_layout'] = new_record registry['castle.cms.default_layout'] = data['section_layout'] return {'success': True}
def _checkId(self, id, allow_dup=0): PortalFolderBase.inheritedAttribute('_checkId')(self, id, allow_dup) if allow_dup: return # FIXME: needed to allow index_html for join code if id == 'index_html': return # Another exception: Must allow "syndication_information" to enable # Syndication... if id == 'syndication_information': return # IDs starting with '@@' are reserved for views. if id[:2] == '@@': raise BadRequest('The id "%s" is invalid because it begins with ' '"@@".' % id) # This code prevents people other than the portal manager from # overriding skinned names and tools. if not getSecurityManager().checkPermission(ManagePortal, self): ob = aq_inner(self) while ob is not None: if ISiteRoot.providedBy(ob): break ob = aq_parent(ob) if ob is not None: # If the portal root has a non-contentish object by this name, # don't allow an override. if (hasattr(ob, id) and id not in ob.contentIds() and # Allow root doted prefixed object name overrides not id.startswith('.')): raise BadRequest('The id "%s" is reserved.' % id) # Don't allow ids used by Method Aliases. ti = self.getTypeInfo() if ti and ti.queryMethodID(id, context=self): raise BadRequest('The id "%s" is reserved.' % id)
def get_results(self, portal_type): """Returns results depending on request and the following logic Case 1: a folder with a Scheda set as default view -> return scheda contents filtered by content_types Case 2: the context is a Scheda -> return the contents of Moduli or Riferimenti according to the requeste portal type Case 3: as a fallback return an empty list """ if ISiteRoot.providedBy(self.context): return [] if self.has_default_view(self.context): return self.find_nephews( portal_type, self.get_default_view_object(self.context)) if self.is_scheda(self.context): return self.find_nephews(portal_type) return []
def update(self): super(View, self).update() context = aq_inner(self.context) self.context = context self.state = getMultiAdapter((context, self.request), name=u'plone_context_state') self.wf_state = self.state.workflow_state() # Handle vote form = self.request.form self.errors = [] self.messages = [] # if the poll is open and anonymous should vote but the parent folder # is private.. inform the user. # When the poll's container is the site's root, we do not need to # check the permissions. container = aq_parent(aq_inner(self.context)) if 'open' == self.wf_state and not ISiteRoot.providedBy(container): roles = [ r['name'] for r in self.context.rolesOfPermission( 'collective.polls: Vote') if r['selected'] ] if 'Anonymous' not in roles and self.context.allow_anonymous: msg = _( u"Anonymous user won't be able to vote, you forgot to " u'publish the parent folder, you must sent back the poll ' u'to private state, publish the parent folder and open ' u'the poll again') api.portal.show_message(msg, self.request, type='warn') if 'poll.submit' in form: self._updateForm(form) # Update status messages for error in self.errors: api.portal.show_message(error, self.request, type='warn') for msg in self.messages: api.portal.show_message(msg, self.request, type='info')
def breadcrumbs(self): """ Breadcrumbs """ if ISiteRoot.providedBy(self.context): return () context = aq_inner(self.context) request = self.request container = utils.parent(context) try: name, item_url = get_view_url(context) except AttributeError: print context raise if container is None: return ({ 'absolute_url': item_url, 'Title': utils.pretty_title_or_id(context, context), }, ) view = getMultiAdapter((container, request), name='breadcrumbs_view') base = tuple(view.breadcrumbs()) # Some things want to be hidden from the breadcrumbs if IHideFromBreadcrumbs.providedBy(context): return base if base: item_url = '%s/%s' % (base[-1]['absolute_url'], name) # don't show default pages in breadcrumbs if not utils.isDefaultPage(context, request): base += ({ 'absolute_url': item_url, 'Title': utils.pretty_title_or_id(context, context), }, ) return base
def get_basic_tags(self): try: context = self.context if ISiteRoot.providedBy(context): try: context = context[get_default_page(context)] except AttributeError: pass tags = { 'modificationDate': _date(context, 'modified'), 'publicationDate': _date(context, 'effective'), 'expirationDate': _date(context, 'expires'), 'generator': CASTLE_VERSION_STRING, "distribution": "Global", } ldata = ILocation(context, None) if ldata is not None: if ldata.locations: location = ldata.locations if type(location) in (list, tuple, set): location = location[0] tags['location'] = location search = ISearch(context, None) if search is not None: robot_configuration = self._get_robot_config(search) config = robot_configuration[:] if 'index' not in config: config.append('noindex') if 'follow' not in config: config.append('nofollow') tags['robots'] = ','.join(config) return ''.join([ u'<meta name="{}" content="{}">'.format(name, value) for name, value in tags.items() ]) except Exception: return u''
def breadcrumbs(self): context = aq_inner(self.context) view_utils = Utils(self.context, self.request) crumbs = [] while context is not None: if ISiteRoot.providedBy(context): break try: if utils.isDefaultPage(context, self.request): context = utils.parent(context) continue except AttributeError: break # Some things want to be hidden from the breadcrumbs if IHideFromBreadcrumbs.providedBy(context): context = utils.parent(context) continue item_url = view_utils.get_object_url(context) try: state = api.content.get_state(obj=context) except WorkflowException: state = None label = getattr(context, 'navigation_label', None) if not label: label = utils.pretty_title_or_id(context, context) crumbs.append({ 'absolute_url': item_url, 'Title': label, 'state': state }) context = utils.parent(context) return list(reversed(crumbs))
def validate(self, value): super(IntGreaterEqualThanParentValidator, self).validate(value) # should not be negative if int(value) < 0: raise schema.interfaces.TooSmall() # get parent value #XXX CHANGED FROM PATH_TRANSLATED TO PATH_INFO because the test # don't work if '++add++' in self.request.get('PATH_INFO', object()): obj = self.context else: obj = self.context.aq_inner.aq_parent parent_value = -1 while parent_value < 0 and not ISiteRoot.providedBy(obj): cf_obj = queryAdapter(obj, ILifeCycle) if cf_obj: try: parent_value = int(self.field.get(cf_obj)) except AttributeError: pass except TypeError: parent_value = 0 try: obj = obj.aq_inner.aq_parent except AttributeError: return # should not be smaller than parent if parent_value > -1 and int(value) < parent_value: raise schema.interfaces.TooBig()
def can_translate(context, language): """ Check if required parent translations are in place so that we can translate this item :return: True if the item can be translated """ assert context is not None parent = aq_parent(context) if ISiteRoot.providedBy(parent): return True # Parent is a language base folder at plone site root if INavigationRoot.providedBy(parent): return True if ITranslatable.providedBy(parent): translatable = ITranslatable(parent) else: from logging import getLogger log = getLogger('silvuple.views.can_translate') if parent: log.info('Parent is not translatable: %s' % parent.absolute_url()) else: log.error( 'Cannot translate language: %s, no parent for %s' % (language, context.absolute_url())) return False translation = translatable.getTranslation(language) return translation is not None
def add_leadimage_from_file(container, file_name, folder_name='data', image_field='image'): """Add leadimage from a file from a folder""" if not container: container = api.portal.get() data_path = os.path.join(os.path.dirname(__file__), folder_name) file_path = os.path.join(data_path, file_name) if not getattr(aq_base(container), file_name, False): namedblobimage = NamedBlobImage(data=open(file_path, 'r').read(), filename=unicode(file_name)) image_container = container if not INavigationRoot.providedBy(container) and \ not ISiteRoot.providedBy(container): image_container = container.aq_parent image = api.content.create(type='Image', title=file_name, image=namedblobimage, container=image_container) image.setTitle(file_name) image.reindexObject() setattr(container, image_field, namedblobimage)
def log_deleted(context, event): if ISiteRoot.providedBy(event.object): return ModificationLogger().deleted(context)
def buildAjaxViewName(self): "根据当前上下文,构建ajax view 名称" context = aq_inner(self.context) if ISiteRoot.providedBy(context): return "oajaxsearch" else: return "xiangtanshisearch"
def sliderobject(self): for item in self.context.aq_chain: if ISliderPage.providedBy(item): return item if ISiteRoot.providedBy(item): return None
def getConfiguration(self, context=None, field=None, request=None): """Return configuration as a dictionary :param field: Dexterity or Archetypes Field instance :param context: The TinyMCE editor content items :return: JSON string of the TinyMCE configuration for this field """ results = {} # Get widget attributes widget = getattr(field, 'widget', None) filter_buttons = getattr(widget, 'filter_buttons', None) allow_buttons = getattr(widget, 'allow_buttons', None) redefine_parastyles = getattr(widget, 'redefine_parastyles', None) parastyles = getattr(widget, 'parastyles', None) rooted = getattr(widget, 'rooted', False) toolbar_width = getattr(widget, 'toolbar_width', self.toolbar_width) # Get safe html transform safe_html = getattr(getToolByName(self, 'portal_transforms'), 'safe_html') # Get kupu library tool filter # Settings are stored on safe_html transform in Plone 4 and # on kupu tool in Plone 3. kupu_library_tool = getToolByName(self, 'kupu_library_tool', None) # Remove to be stripped attributes try: style_whitelist = safe_html.get_parameter_value('style_whitelist') except (KeyError, AttributeError): if kupu_library_tool is not None: style_whitelist = kupu_library_tool.getStyleWhitelist() else: style_whitelist = [] results['valid_inline_styles'] = ','.join( style_whitelist) # tinymce format # Replacing some hardcoded translations labels = {} labels['label_browseimage'] = translate(_('Image Browser'), context=request) labels['label_browselink'] = translate(_('Link Browser'), context=request) labels['label_addnewimage'] = translate(_('Add new Image'), context=request) labels['label_addnewfile'] = translate(_('Add new File'), context=request) labels['label_styles'] = translate(_('(remove style)'), context=request) labels['label_paragraph'] = translate(_('Normal paragraph'), context=request) labels['label_plain_cell'] = translate(_('Plain cell'), context=request) labels['label_style_ldots'] = translate(_('Style...'), context=request) labels['label_text'] = translate(_('Text'), context=request) labels['label_tables'] = translate(_('Tables'), context=request) labels['label_selection'] = translate(_('Selection'), context=request) labels['label_lists'] = translate(_('Lists'), context=request) labels['label_print'] = translate(_('Print'), context=request) labels['label_no_items'] = translate(_('No items in this folder'), context=request) labels['label_no_anchors'] = translate(_('No anchors in this page'), context=request) labels['label_browser'] = translate(_('Browser'), context=request) labels['label_shortcuts'] = translate(_('Shortcuts'), context=request) labels['label_search_results'] = translate(_('Search results:'), context=request) labels['label_internal_path'] = translate(PMF("you_are_here", default="You are here:"), context=request) results['labels'] = labels # Add styles to results results['styles'] = [] table_styles = [] if not redefine_parastyles: if isinstance(self.tablestyles, StringTypes): for tablestyle in self.tablestyles.split('\n'): if not tablestyle: # empty line continue tablestylefields = tablestyle.split('|') tablestyletitle = tablestylefields[0] tablestyleid = tablestylefields[1] if tablestyleid == 'plain': # Do not duplicate the default style hardcoded in the # table.htm.pt continue if request is not None: tablestyletitle = translate(_(tablestylefields[0]), context=request) results['styles'].append(tablestyletitle + '|table|' + tablestyleid) table_styles.append(tablestyletitle + '=' + tablestyleid) if isinstance(self.styles, StringTypes): styles = [] for style in self.styles.split('\n'): if not style: # empty line continue stylefields = style.split('|') styletitle = stylefields[0] if request is not None: styletitle = translate(_(stylefields[0]), context=request) merge = styletitle + '|' + '|'.join(stylefields[1:]) styles.append(merge) results['styles'].extend(styles) results['table_styles'] = ';'.join(table_styles) # tinymce config if parastyles is not None: results['styles'].extend(parastyles) styles = results.pop('styles') # Get buttons from control panel results['buttons'] = self.getEnabledButtons(context=context) # Filter buttons if allow_buttons is not None: allow_buttons = self.translateButtonsFromKupu( context=context, buttons=allow_buttons) results['buttons'] = filter(lambda x: x in results['buttons'], allow_buttons) if filter_buttons is not None: filter_buttons = self.translateButtonsFromKupu( context=context, buttons=filter_buttons) results['buttons'] = filter(lambda x: x not in filter_buttons, results['buttons']) # Get valid html elements valid_elements = self.getValidElements() results['valid_elements'] = ','.join([ "%s[%s]" % (key, '|'.join(value)) for key, value in valid_elements.iteritems() ]) # self.customplugins can be None on old migrated sites results['customplugins'] = (self.customplugins or "").splitlines() # Set toolbar_location if self.toolbar_external: results['theme_advanced_toolbar_location'] = 'external' else: results['theme_advanced_toolbar_location'] = 'top' if self.autoresize: results['theme_advanced_path_location'] = 'none' results['theme_advanced_resizing_use_cookie'] = False results['theme_advanced_resizing'] = False results['autoresize'] = True else: results['theme_advanced_path_location'] = 'bottom' results['theme_advanced_resizing_use_cookie'] = True results['theme_advanced_resizing'] = self.resizing results['autoresize'] = False if '%' in self.editor_width: results['theme_advanced_resize_horizontal'] = False else: results['theme_advanced_resize_horizontal'] = True try: results['theme_advanced_source_editor_width'] = int( self.editor_width) except (TypeError, ValueError): results['theme_advanced_source_editor_width'] = 600 try: results['theme_advanced_source_editor_height'] = int( self.editor_height) except (TypeError, ValueError): results['theme_advanced_source_editor_height'] = 400 try: results['toolbar_width'] = int(toolbar_width) except (TypeError, ValueError): results['toolbar_width'] = 440 portal_state = context.restrictedTraverse('@@plone_portal_state') # is_rtl handles every possible setting as far as RTL/LTR is concerned # pass that to tinmyce results['directionality'] = portal_state.is_rtl() and 'rtl' or 'ltr' portal = portal_state.portal() portal_url = portal_state.portal_url() results['portal_url'] = portal_url results['navigation_root_url'] = portal_state.navigation_root_url() if self.content_css and self.content_css.strip() != "": results['content_css'] = self.content_css else: results['content_css'] = '/'.join( [results['portal_url'], self.getId(), "@@tinymce-getstyle"]) results['link_using_uids'] = self.link_using_uids results['contextmenu'] = self.contextmenu results['entity_encoding'] = self.entity_encoding results['script_url'] = portal_url + '/tiny_mce_gzip.js' results['allow_captioned_images'] = bool(self.allow_captioned_images) results['rooted'] = bool(self.rooted or rooted) props = getToolByName(portal, 'portal_properties') plone_livesearch = props.site_properties.getProperty( 'enable_livesearch', False) livesearch = props.site_properties.getProperty( 'enable_tinymce_livesearch', plone_livesearch) results['livesearch'] = bool(livesearch) AVAILABLE_LANGUAGES = set( 'sq ar hy az eu be bn nb bs br bg ca ch zh hr cs da dv nl en et fi fr gl ' 'ka de el gu he hi hu is id ia it ja ko lv lt lb mk ms ml mn se no nn fa ' 'pl pt ps ro ru sc sr ii si sk sl es sv ta tt te th tr zh-cn zh-tw uk ur cy vi zu' .split()) if 'LANGUAGE' in context.REQUEST: if context.REQUEST.LANGUAGE in AVAILABLE_LANGUAGES: results['language'] = context.REQUEST.LANGUAGE elif context.REQUEST.LANGUAGE[:2] in AVAILABLE_LANGUAGES: results['language'] = context.REQUEST.LANGUAGE[:2] else: results['language'] = "en" else: results['language'] = "en" try: results['document_url'] = context.absolute_url() obj = context while obj is not None: if IFolderish.providedBy(obj): if obj.portal_type != 'TempFolder': # do not use portal_factory generated # temporary object for base url. results['document_base_url'] = obj.absolute_url() + "/" break # We should never reach this. if ISiteRoot.providedBy(obj): results['document_base_url'] = portal_url + "/" results['document_url'] = portal_url break obj = aq_parent(aq_inner(obj)) except AttributeError: results['document_base_url'] = portal_url + "/" results['document_url'] = portal_url # Get Library options results[ 'gecko_spellcheck'] = self.libraries_spellchecker_choice == 'browser' # Content Browser shortcuts_dict = dict(getUtilitiesFor(ITinyMCEShortcut)) results['link_shortcuts_html'] = [] results['image_shortcuts_html'] = [] results['num_of_thumb_columns'] = self.num_of_thumb_columns results['thumbnail_size'] = self.thumbnail_size results['anchor_selector'] = self.anchor_selector for name in self.link_shortcuts: results['link_shortcuts_html'].extend( shortcuts_dict.get(name).render(context)) for name in self.image_shortcuts: results['image_shortcuts_html'].extend( shortcuts_dict.get(name).render(context)) # init vars specific for "After the Deadline" spellchecker mtool = getToolByName(portal, 'portal_membership') member = mtool.getAuthenticatedMember() results['atd_rpc_id'] = 'Products.TinyMCE-' + ( member.getId() or '') # None when Anonymous User results['atd_rpc_url'] = "%s/@@" % portal_url results['atd_show_types'] = self.libraries_atd_show_types.strip( ).replace('\n', ',') results[ 'atd_ignore_strings'] = self.libraries_atd_ignore_strings.strip( ).replace('\n', ',') # generic configuration results['mode'] = "exact" results['theme'] = "advanced" results['skin'] = "plone" results['inlinepopups_skin'] = "plonepopup" results['body_class'] = "documentContent" plone_view = context.restrictedTraverse('@@plone') template = None if IBrowserDefault.providedBy(context): template = context.unrestrictedTraverse(context.getLayout()) results['body_class'] += ' ' + plone_view.bodyClass(template, template) results['body_id'] = "content" results['table_firstline_th'] = True results['fix_list_elements'] = False # allow embed tag if user removes it from # list of nasty tags - see #10681 results['media_strict'] = False results['theme_advanced_path'] = False results['theme_advanced_toolbar_align'] = "left" results['plugins'] = self.getPlugins() results['theme_advanced_styles'] = self.getStyles(styles, labels) results['theme_advanced_buttons1'], results['theme_advanced_buttons2'], \ results['theme_advanced_buttons3'], results['theme_advanced_buttons4'] = self.getToolbars(results) if self.formats and self.formats.strip(): results['formats'] = json.loads(self.formats) return results
def import_ala_data(self): if self.request.get('REQUEST_METHOD', 'GET').upper() != 'POST': self.record_error('Request must be POST', 400) raise BadRequest('Request must be POST') context = None # get import context if ISiteRoot.providedBy(self.context): # we have been called at site root... let's traverse to default # import location context = self.context.restrictedTraverse("/".join( (defaults.DATASETS_FOLDER_ID, defaults.DATASETS_SPECIES_FOLDER_ID, 'ala'))) else: # custom context.... let's use in context = self.context # do user check first member = ploneapi.user.get_current() if member.getId(): user = { 'id': member.getUserName(), 'email': member.getProperty('email'), 'fullname': member.getProperty('fullname') } else: # We need at least a valid user raise Unauthorized("Invalid user") # check permission if not checkPermission('org.bccvl.AddDataset', context): raise Unauthorized("User not allowed in this context") params = self.request.form.get('data') if not params: raise BadRequest("At least on of traits or environ has to be set") if params is None: self.record_error('Bad Request', 400, 'Missing parameter data', {'parameter': 'data'}) if not params: self.record_error('Bad Request', 400, 'Empty parameter data', {'parameter': 'data'}) # TODO: should validate objects inside as well? (or use json schema # validation?) # all good so far # pull dataset from aekos # TODO: get better name here title = params[0].get('name', 'ALA import') # determine dataset type # 1. test if it is a multi species import species = set() for query in params: biocache_url = '{}/occurrences/search'.format(query['url']) query = { 'q': query['query'], 'pageSize': 0, 'limit': 2, 'facets': 'species_guid', 'fq': 'species_guid:*' # skip results without species guid } res = requests.get(biocache_url, params=query) res = res.json() # FIXME: do we need to treat sandbox downloads differently? if res.get('facetResults'): # do we have some results at all? for guid in res['facetResults'][0]['fieldResult']: species.add(guid['label']) if len(species) > 1: portal_type = 'org.bccvl.content.multispeciesdataset' else: portal_type = 'org.bccvl.content.dataset' swiftsettings = getUtility(IRegistry).forInterface(ISwiftSettings) if swiftsettings.storage_url: portal_type = 'org.bccvl.content.remotedataset' # create content ds = createContent(portal_type, title=title) ds.dataSource = 'ala' ds.description = u' '.join([title, u' imported from ALA']) ds.import_params = params ds = addContentToContainer(context, ds) md = IBCCVLMetadata(ds) if IMultiSpeciesDataset.providedBy(ds): md['genre'] = 'DataGenreSpeciesCollection' md['categories'] = ['multispecies'] else: # species dataset md['genre'] = 'DataGenreSpeciesOccurrence' md['categories'] = ['occurrence'] # TODO: populate this correctly as well md['species'] = [{'scientificName': 'qid', 'taxonID': 'qid'}] # FIXME: IStatusMessage should not be in API call from Products.statusmessages.interfaces import IStatusMessage IStatusMessage(self.request).add('New Dataset created', type='info') # start import job jt = IExperimentJobTracker(ds) status, message = jt.start_job() # reindex ojebct to make sure everything is up to date ds.reindexObject() # FIXME: IStatutsMessage should not be in API call IStatusMessage(self.request).add(message, type=status) # FIXME: API should not return a redirect # 201: new resource created ... location may point to resource from Products.CMFCore.utils import getToolByName portal = getToolByName(self.context, 'portal_url').getPortalObject() nexturl = portal[defaults.DATASETS_FOLDER_ID].absolute_url() self.request.response.setStatus(201) self.request.response.setHeader('Location', nexturl) # FIXME: should return a nice json representation of success or error return { 'status': status, 'message': message, 'jobid': IJobTracker(ds).get_job().id }
def import_trait_data(self): if self.request.get('REQUEST_METHOD', 'GET').upper() != 'POST': self.record_error('Request must be POST', 400) raise BadRequest('Request must be POST') source = self.request.form.get('source', None) species = self.request.form.get('species', None) traits = self.request.form.get('traits', None) environ = self.request.form.get('environ', None) dataurl = self.request.form.get('url', None) context = None if not source or source not in ('aekos', 'zoatrack'): raise BadRequest("source parameter must be 'aekos' or 'zoatrack'") # get import context if ISiteRoot.providedBy(self.context): # we have been called at site root... let's traverse to default # import location context = self.context.restrictedTraverse("/".join( (defaults.DATASETS_FOLDER_ID, defaults.DATASETS_SPECIES_FOLDER_ID, str(source)))) else: # custom context.... let's use in context = self.context # do user check first member = ploneapi.user.get_current() if member.getId(): user = { 'id': member.getUserName(), 'email': member.getProperty('email'), 'fullname': member.getProperty('fullname') } else: # We need at least a valid user raise Unauthorized("Invalid user") # check permission if not checkPermission('org.bccvl.AddDataset', context): raise Unauthorized("User not allowed in this context") # check parameters if not species or not isinstance(species, (basestring, list)): raise BadRequest("Missing or invalid species parameter") elif isinstance(species, basestring): species = [species] # for zoatrack, url needs to be set if source == 'zoatrack' and not dataurl: raise BadRequest("url has to be set") # for aekos, at least a trait or environment variable must be specified. if source == 'aekos' and not traits and not environ: raise BadRequest( "At least a trait or environent variable has to be set") if not traits: traits = [] elif isinstance(traits, basestring): traits = [traits] if not environ: environ = [] elif isinstance(environ, basestring): environ = [environ] # all good so far # pull dataset from aekos title = ' '.join(species) # determine dataset type portal_type = 'org.bccvl.content.dataset' swiftsettings = getUtility(IRegistry).forInterface(ISwiftSettings) if swiftsettings.storage_url: portal_type = 'org.bccvl.content.remotedataset' # create content ds = createContent(portal_type, title=title) ds.dataSource = source ds.description = u' '.join([ title, ','.join(traits), ','.join(environ), u' imported from {}'.format(source.upper()) ]) ds = addContentToContainer(context, ds) md = IBCCVLMetadata(ds) md['genre'] = 'DataGenreTraits' md['categories'] = ['traits'] md['species'] = [{ 'scientificName': spec, 'taxonID': spec } for spec in species] md['traits'] = traits md['environ'] = environ md['dataurl'] = dataurl # FIXME: IStatusMessage should not be in API call from Products.statusmessages.interfaces import IStatusMessage IStatusMessage(self.request).add('New Dataset created', type='info') # start import job jt = IExperimentJobTracker(ds) status, message = jt.start_job() # reindex ojebct to make sure everything is up to date ds.reindexObject() # FIXME: IStatutsMessage should not be in API call IStatusMessage(self.request).add(message, type=status) # FIXME: API should not return a redirect # 201: new resource created ... location may point to resource from Products.CMFCore.utils import getToolByName portal = getToolByName(self.context, 'portal_url').getPortalObject() nexturl = portal[defaults.DATASETS_FOLDER_ID].absolute_url() self.request.response.setStatus(201) self.request.response.setHeader('Location', nexturl) # FIXME: should return a nice json representation of success or error return { 'status': status, 'message': message, 'jobid': IJobTracker(ds).get_job().id }