def upgrade(tool): # Hack prevent out-of-date upgrading # Related: PR #1484 # https://github.com/bikalabs/Bika-LIMS/pull/1484 from bika.lims.upgrade import skip_pre315 if skip_pre315(aq_parent(aq_inner(tool))): return True portal = aq_parent(aq_inner(tool)) setup = portal.portal_setup workflow = getToolByName(portal, "portal_workflow") # /arimports folder permissions mp = portal.arimports.manage_permission mp(ManageARImport, ['Manager', ], 1) mp(permissions.ListFolderContents, ['Manager','Member',], 1) mp(permissions.AddPortalContent, ['Manager', ], 0) mp(permissions.DeleteObjects, ['Manager'], 0) mp(permissions.View, ['Manager','Member'], 0) portal.arimports.reindexObject() try: workflow.doActionFor(portal.arimports, "hide") except: pass portal.arimports.setLayout('@@arimports') return True
def doCreate(self, obj, id=None, **kw): """Create a real object from a temporary object.""" if self.isTemporary(obj=obj): if id is not None: id = id.strip() if not id: if hasattr(obj, 'getId') and callable(getattr(obj, 'getId')): id = obj.getId() else: id = getattr(obj, 'id', None) # get the ID of the TempFolder type_name = aq_parent(aq_inner(obj)).id folder = aq_parent(aq_parent(aq_parent(aq_inner(obj)))) folder.invokeFactory(id=id, type_name=type_name) obj = getattr(folder, id) # give ownership to currently authenticated member if not anonymous # TODO is this necessary? membership_tool = getToolByName(self, 'portal_membership') if not membership_tool.isAnonymousUser(): member = membership_tool.getAuthenticatedMember() obj.changeOwnership(member.getUser(), 1) if hasattr(aq_base(obj), 'manage_afterPortalFactoryCreate'): obj.manage_afterPortalFactoryCreate() return obj
def role_match(ob, permission, roles): pr = [] while True: p = getattr(ob, permission, _marker) if p is not _marker: if isinstance(p, list): pr.append(p) ob = aq_parent(ob) if ob is not None: continue break if isinstance(p, tuple): pr.append(p) break if p is None: pr.append(('Manager', 'Anonymous')) break ob = aq_parent(ob) if ob is not None: continue break for role in roles: if role not in pr: return False return True
def getPageSiteLayout(context): """Get the path to the site layout for a page. This is generally only appropriate for the view of this page. For a generic template or view, use getDefaultSiteLayout(context) instead. """ layoutAware = ILayoutAware(context, None) if layoutAware is not None: if getattr(layoutAware, 'pageSiteLayout', None): return layoutAware.pageSiteLayout # Note: the sectionSiteLayout on context is for pages *under* context, not # necessarily context itself parent = aq_parent(aq_inner(context)) while parent is not None: layout = ILayoutAware(parent, None) if layout is not None: if getattr(layout, 'sectionSiteLayout', None): return layout.sectionSiteLayout parent = aq_parent(aq_inner(parent)) fti = queryUtility(IDexterityFTI, name=context.portal_type) if fti is not None and IPageFTI.providedBy(fti): if fti.default_site_layout: return fti.default_site_layout registry = queryUtility(IRegistry) if registry is None: return None return registry.get(DEFAULT_SITE_LAYOUT_REGISTRY_KEY)
def getInfoData(self): """ Get the data needed to create an ActionInfo. """ category_path = [] lazy_keys = [] lazy_map = {} lazy_map['id'] = self.getId() parent = aq_parent(self) while parent is not None and parent.getId() != 'portal_actions': category_path.append( parent.getId() ) parent = aq_parent(parent) lazy_map['category'] = '/'.join(category_path[::-1]) for id, val in self.propertyItems(): if id.endswith('_expr'): id = id[:-5] if val: val = getattr(self, '%s_expr_object' % id) lazy_keys.append(id) elif id == 'available': val = True elif id == 'i18n_domain': continue elif self.i18n_domain and id in ('title', 'description'): val = Message(val, self.i18n_domain) lazy_map[id] = val return (lazy_map, lazy_keys)
def notify_content_object(obj, event): """Tell the content object when a comment is added """ content_obj = aq_parent(aq_parent(obj)) content_obj.reindexObject(idxs=('total_comments', 'last_comment_date', 'commentators'))
def parent_url(self): """ """ context = aq_inner(self.context) portal_membership = getToolByName(context, 'portal_membership') obj = context checkPermission = portal_membership.checkPermission # Abort if we are at the root of the portal if IPloneSiteRoot.providedBy(context): return None # Get the parent. If we can't get it (unauthorized), use the portal parent = aq_parent(obj) # # We may get an unauthorized exception if we're not allowed to access# # the parent. In this case, return None try: if getattr(parent, 'getId', None) is None or \ parent.getId() == 'talkback': # Skip any Z3 views that may be in the acq tree; # Skip past the talkback container if that's where we are parent = aq_parent(parent) if not checkPermission('List folder contents', parent): return None return parent.absolute_url() except Unauthorized: return None
def upgrade(tool): # Hack prevent out-of-date upgrading # Related: PR #1484 # https://github.com/bikalabs/Bika-LIMS/pull/1484 from bika.lims.upgrade import skip_pre315 if skip_pre315(aq_parent(aq_inner(tool))): return True portal = aq_parent(aq_inner(tool)) setup = portal.portal_setup setup.runImportStepFromProfile('profile-bika.lims:default', 'typeinfo') stub('bika.lims.content.pricelistlineitem', 'PricelistLineItem', BaseContent) for pl in portal['pricelists'].objectValues(): pl.pricelist_lineitems = [] for pli in pl.objectValues(): item = dict( title=pli.title, ItemDescription=pli.ItemDescription, Accredited=pli.Accredited, Subtotal="%d.%d" % (pli.Subtotal[0], pli.Subtotal[1]), VATAmount="%d.%d" % (pli.VATAmount[0], pli.VATAmount[1]), Total="%d.%d" % (pli.Total[0], pli.Total[1]), CategoryTitle=pli.CategoryTitle, ) pl.pricelist_lineitems.append(item) return True
def publishTraverse(self, request, name): request.survey = self.context utils.setLanguage(request, self.context, self.context.language) if name not in ["view", "index_html"] and \ not self.hasValidSession(request): request.response.redirect( aq_parent(aq_parent(self.context)).absolute_url(), lock=True) return self.context if name not in self.phases: return super(SurveyPublishTraverser, self)\ .publishTraverse(request, name) # Decorate the request with the right skin layer and add to the aq path directlyProvides(request, self.phases[name], *directlyProvidedBy(request)) self.context = PathGhost(name).__of__(self.context) session = SessionManager.session tree_id = find_sql_context(session.id, request['TraversalRequestNameStack']) if tree_id is not None: return build_tree_aq_chain(self.context, tree_id) # No SQL based traversal possible, return the existing context with the # new skin layer applied return self.context
def ticket_title_generator(obj): """Generate a title for the ticket, also using event information. """ event = obj ret = { 'title': obj.title, 'eventtitle': '', 'eventstart': '', 'eventend': '' } if ITicketOccurrence.providedBy(event): event = aq_parent(aq_parent(event)) # Traverse to the Occurrence object if IATEvent.providedBy(event): # get the request out of thin air to be able to publishTraverse to # the transient Occurrence object. traverser = OccTravAT(event, getRequest()) elif IDXEvent.providedBy(event): # TODO traverser = OccTravDX(event, getRequest()) else: raise NotImplementedError( u"There is no event occurrence traverser implementation for " u"this kind of object." ) try: event = traverser.publishTraverse(getRequest(), obj.id) except KeyError: # Maybe the ticket occurrence isn't valid anymore because the # event occurence doesn't exist anymore. # Just ignore that case. return ret elif ITicket.providedBy(event): event = aq_parent(event) if IEvent.providedBy(event) or IOccurrence.providedBy(event): acc = IEventAccessor(event) lstart = ulocalized_time( DT(acc.start), long_format=True, context=event ) lend = ulocalized_time( DT(acc.start), long_format=True, context=event ) # XXX: no unicode, store as utf-8 encoded string instead ret = dict( title=u'%s - %s (%s - %s)' % ( safe_unicode(acc.title), safe_unicode(obj.title), lstart, lend, ), eventtitle=acc.title, eventstart=acc.start, eventend=acc.end, ) return ret
def tinymce(self): """ data-pat-tinymce : JSON.stringify({ relatedItems: { vocabularyUrl: config.portal_url + '/@@getVocabulary?name=plone.app.vocabularies.Catalog' }, tiny: config, prependToUrl: 'resolveuid/', linkAttribute: 'UID', prependToScalePart: '/@@images/image/' }) """ generator = TinyMCESettingsGenerator(self.context, self.request) settings = generator.settings folder = aq_inner(self.context) # Test if we are currently creating an Archetype object if IFactoryTempFolder.providedBy(aq_parent(folder)): folder = aq_parent(aq_parent(aq_parent(folder))) if not IFolderish.providedBy(folder): folder = aq_parent(folder) if IPloneSiteRoot.providedBy(folder): initial = None else: initial = IUUID(folder, None) current_path = folder.absolute_url()[len(generator.portal_url):] image_types = settings.image_objects or [] folder_types = settings.contains_objects or [] configuration = { 'relatedItems': { 'vocabularyUrl': '%s/@@getVocabulary?name=plone.app.vocabularies.Catalog' % ( generator.portal_url), 'folderTypes': folder_types }, 'upload': { 'initialFolder': initial, 'currentPath': current_path, 'baseUrl': generator.portal_url, 'relativePath': '@@fileUpload', 'uploadMultiple': False, 'maxFiles': 1, 'showTitle': False }, 'base_url': self.context.absolute_url(), 'tiny': generator.get_tiny_config(), # This is for loading the languages on tinymce 'loadingBaseUrl': '%s/++plone++static/components/tinymce-builded/js/tinymce' % generator.portal_url, # noqa 'prependToUrl': '{0}/resolveuid/'.format(generator.portal_url), 'linkAttribute': 'UID', 'prependToScalePart': '/@@images/image/', 'imageTypes': image_types # 'anchorSelector': utility.anchor_selector, } return {'data-pat-tinymce': json.dumps(configuration)}
def _setUID(self, uid): old_uid = IUUID(self, None) if old_uid is None: # Nothing to be done. return # Update forward references fw_refs = self.getReferenceImpl() for ref in fw_refs: assert ref.sourceUID == old_uid ref.sourceUID = uid item = ref container = aq_parent(aq_inner(ref)) # We call manage_afterAdd to inform the # reference catalog about changes. ref.manage_afterAdd(item, container) # Update back references back_refs = self.getBackReferenceImpl() for ref in back_refs: assert ref.targetUID == old_uid ref.targetUID = uid item = ref container = aq_parent(aq_inner(ref)) # We call manage_afterAdd to inform the # reference catalog about changes. ref.manage_afterAdd(item, container) setattr(self, config.UUID_ATTR, uid) item = self container = aq_parent(aq_inner(item)) # We call manage_afterAdd to inform the # reference catalog about changes. self.manage_afterAdd(item, container)
def find_user(context, userid): """Walk up all of the possible acl_users to find the user with the given userid. """ track = set() acl_users = aq_inner(cmfutils.getToolByName(context, 'acl_users')) path = '/'.join(acl_users.getPhysicalPath()) logger.debug('Visited acl_users "%s"' % path) track.add(path) user = acl_users.getUserById(userid) while user is None and acl_users is not None: context = aq_parent(aq_parent(aq_inner(acl_users))) acl_users = aq_inner(cmfutils.getToolByName(context, 'acl_users')) if acl_users is not None: path = '/'.join(acl_users.getPhysicalPath()) logger.debug('Visited acl_users "%s"' % path) if path in track: logger.warn('Tried searching an already visited acl_users, ' '"%s". All visited are: %r' % (path, list(track))) break track.add(path) user = acl_users.getUserById(userid) if user is not None: user = user.__of__(acl_users) return user
def notify_moderator(obj, event): """Tell the moderator when a comment needs attention. This method sends an email to the moderator if comment moderation a new comment has been added that needs to be approved. The moderator_notification setting has to be enabled in the discussion control panel. Configure the moderator e-mail address in the discussion control panel. If no moderator is configured but moderator notifications are turned on, the site admin email (from the mail control panel) will be used. """ # Check if moderator notification is enabled registry = queryUtility(IRegistry) settings = registry.forInterface(IDiscussionSettings, check=False) if not settings.moderator_notification_enabled: return # Get informations that are necessary to send an email mail_host = getToolByName(obj, 'MailHost') portal_url = getToolByName(obj, 'portal_url') portal = portal_url.getPortalObject() sender = portal.getProperty('email_from_address') if settings.moderator_email: mto = settings.moderator_email else: mto = sender # Check if a sender address is available if not sender: return conversation = aq_parent(obj) content_object = aq_parent(conversation) # Compose email subject = translate(_(u"A comment has been posted."), context=obj.REQUEST) message = translate(Message(MAIL_NOTIFICATION_MESSAGE_MODERATOR, mapping={ 'title': safe_unicode(content_object.title), 'link': content_object.absolute_url() + '/view#' + obj.id, 'text': obj.text, 'link_approve': obj.absolute_url() + '/@@moderate-publish-comment', 'link_delete': obj.absolute_url() + '/@@moderate-delete-comment', }), context=obj.REQUEST) # Send email try: mail_host.send(message, mto, sender, subject, charset='utf-8') except SMTPException, e: logger.error('SMTP exception (%s) while trying to send an ' + 'email notification to the comment moderator ' + '(from %s to %s, message: %s)', e, sender, mto, message)
def update(self): super(View, self).update() context = aq_inner(self.context) parent = aq_parent(context) if parent.portal_type=='apyb.papers.track': track = parent program = aq_parent(track) else: program = parent self.context = context self._path = '/'.join(context.getPhysicalPath()) self.state = getMultiAdapter((context, self.request), name=u'plone_context_state') self.tools = getMultiAdapter((context, self.request), name=u'plone_tools') self.portal = getMultiAdapter((context, self.request), name=u'plone_portal_state') self.helper = getMultiAdapter((program, self.request), name=u'helper') self._ct = self.tools.catalog() self._mt = self.tools.membership() self._wt = self.tools.workflow() self.member = self.portal.member() voc_factory = queryUtility(IVocabularyFactory, 'apyb.papers.talk.rooms') self.rooms = voc_factory(self.context) self.roles_context = self.member.getRolesInContext(context) if not self.show_border: self.request['disable_border'] = True
def getLexicon(self): """Get the lexicon for this index """ if hasattr(aq_base(self), 'lexicon'): # Fix up old ZCTextIndexes by removing direct lexicon ref # and changing it to an ID lexicon = getattr(aq_parent(aq_inner(self)), self.lexicon.getId()) self.lexicon_id = lexicon.getId() del self.lexicon if getattr(aq_base(self), 'lexicon_path', None): # Fix up slightly less old ZCTextIndexes by removing # the physical path and changing it to an ID. # There's no need to use a physical path, which otherwise # makes it difficult to move or rename ZCatalogs. self.lexicon_id = self.lexicon_path[-1] del self.lexicon_path try: return self._v_lexicon except AttributeError: lexicon = getattr(aq_parent(aq_inner(self)), self.lexicon_id) if not (ILexicon.providedBy(lexicon) or z2ILexicon.isImplementedBy(lexicon)): raise TypeError('Object "%s" is not a ZCTextIndex Lexicon' % repr(lexicon)) self._v_lexicon = lexicon return lexicon
def nextURL(self): element = aq_inner(self.context) rule = aq_parent(element) context = aq_parent(rule) url = str(getMultiAdapter((context, self.request), name=u"absolute_url")) focus = self.context.id.strip('+') return '%s/++rule++%s/@@manage-elements#%s' % (url, rule.__name__, focus)
def getOAI(context, object=None): initializeTFC() request = getattr(context, 'REQUEST', None) if request: cache = request.get('_oai_cache', None) if cache is None: request['_oai_cache'] = cache = {} info = cache.get(id(object), None) else: info = None if info is None: if object is None or not hasattr(object, 'aq_base'): folder = None else: folder = object # Search up the containment hierarchy until we find an # object that claims it's a folder. while folder is not None: if getattr(aq_base(folder), 'isPrincipiaFolderish', 0): # found it. break else: # If the parent of the object at hand is a TempFolder # don't strip off its outer acquisition context (Plone) parent = aq_parent(aq_inner(folder)) if getattr(parent, '__class__', None) == TempFolderClass: folder = aq_parent(folder) else: folder = parent info = oai(context, folder, object) if request: cache[id(object)] = info return info
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 notifyCommentAdded(obj ,event): """Notify owner of added comment""" log = logging.getLogger('plumi.content.subscribers') urltool = getToolByName(obj, 'portal_url') portal = urltool.getPortalObject() video = aq_parent(aq_parent(obj)) videoUrl = video.absolute_url() creator= video.Creator() membr_tool = getToolByName(obj,'portal_membership') member=membr_tool.getMemberById(creator) mTo = member.getProperty('email',None) log.info('notifyCommentAdded') if mTo: try: mFrom = portal.getProperty('email_from_address') mSubj = _('Comment added on: ') + video.Title().decode('utf-8') mMsg = 'To: %s\n' % mTo mMsg += 'From: %s\n' % mFrom mMsg += 'Content-Type: text/plain; charset=utf-8\n\n' mMsg = _('Hi ') + member.getProperty('fullname', creator) mMsg += '\n\n' + _('A comment has been added on ') + videoUrl + '\n\n' async = getUtility(IAsyncService) job = async.queueJobWithDelay(None, temp_time, sendMail, obj, mMsg, mSubj) log.info('notifyCommentAdded , im %s . sending email to %s from %s ' % (obj, mTo, mFrom) ) except: log.error('Didnt actually send email to contribution owner! Something amiss with SecureMailHost.')
def getExprContext(context, object=None): initializeTFC() request = getattr(context, 'REQUEST', None) if request: cache = request.get('_plone_ec_cache', None) if cache is None: request['_plone_ec_cache'] = cache = {} ec = cache.get(id(object), None) else: ec = None if ec is None: utool = getToolByName(context, 'portal_url') portal = utool.getPortalObject() if object is None or not hasattr(object, 'aq_base'): folder = portal else: folder = object # Search up the containment hierarchy until we find an # object that claims it's a folder. while folder is not None: if getattr(aq_base(folder), 'isPrincipiaFolderish', 0): # found it. break else: # If the parent of the object at hand is a TempFolder # don't strip off its outer acquisition context (Plone) parent = aq_parent(aq_inner(folder)) if getattr(parent, '__class__', None) == TempFolderClass: folder = aq_parent(folder) else: folder = parent ec = createExprContext(folder, portal, object) if request: cache[id(object)] = ec return ec
def editProperties(self, props): # Change portal settings. aq_parent(aq_inner(self)).manage_changeProperties(props) if hasattr(self, 'propertysheets'): ps = self.propertysheets if hasattr(ps, 'props'): ps.props.manage_changeProperties(props)
def upgrade(tool): # Hack prevent out-of-date upgrading # Related: PR #1484 # https://github.com/bikalabs/Bika-LIMS/pull/1484 from bika.lims.upgrade import skip_pre315 if skip_pre315(aq_parent(aq_inner(tool))): return True portal = aq_parent(aq_inner(tool)) setup = portal.portal_setup mp = portal.bika_setup.manage_permission mp('Access contents information', ['Authenticated', 'Analyst'], 1) mp(permissions.View, ['Authenticated', 'Analyst'], 1) portal.bika_setup.reindexObject() for obj in portal.bika_setup.bika_analysisservices.objectValues(): mp = obj.manage_permission mp(permissions.View, ['Manager', 'LabManager', 'Analyst'], 0) mp('Access contents information', ['Manager', 'LabManager', 'Member', 'LabClerk', 'Analyst', 'Sampler', 'Preserver', 'Owner'], 0) obj.reindexObject() wf = getToolByName(portal, 'portal_workflow') # update affected tools setup.runImportStepFromProfile('profile-bika.lims:default', 'typeinfo') setup.runImportStepFromProfile('profile-bika.lims:default', 'workflow-csv') wf.updateRoleMappings() return True
def __init__(self, context, request): super(CompetitionDetail, self).__init__(context, request) if IBaseFolder.providedBy(context): self.parent = aq_parent(aq_inner(context)) else: self.parent = aq_parent(aq_parent(aq_inner(context))) self.parent = '/'.join(self.parent.getPhysicalPath())
def upgrade(tool): """ Sort by Type in instruments """ # Hack prevent out-of-date upgrading # Related: PR #1484 # https://github.com/bikalabs/Bika-LIMS/pull/1484 from bika.lims.upgrade import skip_pre315 if skip_pre315(aq_parent(aq_inner(tool))): return True portal = aq_parent(aq_inner(tool)) bsc = getToolByName(portal, 'bika_setup_catalog', None) if 'getInstrumentType' not in bsc.indexes(): bsc.addIndex('getInstrumentType', 'FieldIndex') bsc.addColumn('getInstrumentType') bsc.addIndex('getInstrumentTypeName','FieldIndex') bsc.addColumn('getInstrumentTypeName') #Del old "getType" Index, it's not used now. if 'getType' in bsc.indexes(): bsc.delIndex('getType') if 'getType' in bsc.indexes(): bsc.delColumn('getType') setup = portal.portal_setup logger.info("Reindex added indexes in bika_setup_catalog") bsc.manage_reindexIndex( ids=['getInstrumentType', 'getInstrumentTypeName', ]) return True
def upgrade(tool): # Hack prevent out-of-date upgrading # Related: PR #1484 # https://github.com/bikalabs/Bika-LIMS/pull/1484 from bika.lims.upgrade import skip_pre315 if skip_pre315(aq_parent(aq_inner(tool))): return True portal = aq_parent(aq_inner(tool)) setup = portal.portal_setup # update affected tools setup.runImportStepFromProfile('profile-bika.lims:default', 'workflow-csv') # /supplyorders folder permissions mp = portal.supplyorders.manage_permission mp(CancelAndReinstate, ['Manager', 'LabManager', 'LabClerk'], 0) mp(ManagePricelists, ['Manager', 'LabManager', 'Owner'], 1) mp(permissions.ListFolderContents, ['Member'], 1) mp(permissions.AddPortalContent, ['Manager', 'LabManager', 'Owner'], 0) mp(permissions.DeleteObjects, ['Manager', 'LabManager', 'Owner'], 0) mp(permissions.View, ['Manager', 'LabManager'], 0) portal.supplyorders.reindexObject() wf = getToolByName(portal, 'portal_workflow') wf.updateRoleMappings() return True
def articles(self): """Returns list of dictionary of articles :rtype: list """ res = [] context = aq_inner(self.context) if not getattr(context, 'related_articles', None): context = aq_parent(context) if not getattr(context, 'related_articles', None): context = aq_parent(context) if getattr(context, 'related_articles', None): shopping_site = IShoppingSite(self.context) path = shopping_site.shop_path() for uuid in context.related_articles: obj = shopping_site.get_object(IArticle, UID=uuid, path=path, review_state='published') if obj is not None: art = IArticleAdapter(obj) res.append({ 'gross': art.gross(), 'image_url': art.image_url(size='preview'), 'title': art.title(), 'url': obj.absolute_url(), }) return res[:4]
def parent_info(self): """query parent url for back to overview link""" portal_url = getToolByName(self.context, 'portal_url') plone_utils = getToolByName(self.context, 'plone_utils') portal_membership = getToolByName(self.context, 'portal_membership') obj = self.context checkPermission = portal_membership.checkPermission # There is no parent if we are at the root of the portal if IPloneSiteRoot.providedBy(self.context): return None # Get the parent: we may get an unauthorized exception if we are # not allowed to access the parent. In this case, use the portal parent = aq_parent(aq_inner(obj)) try: if getattr(parent, 'getId', None) is None or parent.getId() == 'talkback': # Skip past the discussion items, aka the talkback container parent = aq_parent(aq_inner(parent)) if not checkPermission('List folder contents', parent): return None return [dict(title=parent.Title, url=parent.absolute_url)] except Unauthorized: return None
def upgrade(tool): # Hack prevent out-of-date upgrading # Related: PR #1484 # https://github.com/bikalabs/Bika-LIMS/pull/1484 from bika.lims.upgrade import skip_pre315 if skip_pre315(aq_parent(aq_inner(tool))): return True portal = aq_parent(aq_inner(tool)) # Fix Analysis Services IMM incoherences for service in portal.bika_setup.bika_analysisservices.objectValues('AnalysisService'): if (service.getInstrumentEntryOfResults() == False): # Remove any assigned instrument service.setInstruments([]) service.setInstrument(None) if (service.getManualEntryOfResults() == False): # Remove any assigned manual method service.setMethods([]) service.set_Method(None) service.reindexObject() return True
def verifyAcquisitionContext(user, object, object_roles=None): """Mimics the relevant section of User.allowed(). Returns true if the object is in the context of the user's user folder. """ ufolder = aq_parent(user) ucontext = aq_parent(ufolder) if ucontext is not None: if object is None: # This is a strange rule, though # it doesn't cause any security holes. SDH return 1 if getattr(object, '__self__', None) is not None: # This is a method. Grab its self. object = object.__self__ if not aq_inContextOf(object, ucontext, 1): if 'Shared' in object_roles: # Old role setting. Waaa object_roles = user._shared_roles(object) if 'Anonymous' in object_roles: return 1 return None # Note that if the user were not wrapped, it would # not be possible to determine the user's context # and this method would return 1. # However, as long as user folders always return # wrapped user objects, this is safe. return 1
def getCustomizableObject(self): ob = aq_parent(aq_inner(self)) while getattr(ob, '_isDirectoryView', 0): ob = aq_parent(aq_inner(ob)) return ob
def label(self): if IDossierTemplateSchema.providedBy(aq_parent(aq_inner( self.context))): return _(u'Edit Subdossier') return super(DossierTemplateEditForm, self).label
def unrestrictedTraverse(self, path, default=_marker, restricted=False): """Lookup an object by path. path -- The path to the object. May be a sequence of strings or a slash separated string. If the path begins with an empty path element (i.e., an empty string or a slash) then the lookup is performed from the application root. Otherwise, the lookup is relative to self. Two dots (..) as a path element indicates an upward traversal to the acquisition parent. default -- If provided, this is the value returned if the path cannot be traversed for any reason (i.e., no object exists at that path or the object is inaccessible). restricted -- If false (default) then no security checking is performed. If true, then all of the objects along the path are validated with the security machinery. Usually invoked using restrictedTraverse(). """ if not path: return self if isinstance(path, str): # Only native strings are allowed path = path.split('/') else: path = list(path) REQUEST = {'TraversalRequestNameStack': path} path.reverse() path_pop = path.pop if len(path) > 1 and not path[0]: # Remove trailing slash path_pop(0) if restricted: validate = getSecurityManager().validate if not path[-1]: # If the path starts with an empty string, go to the root first. path_pop() obj = self.getPhysicalRoot() if restricted: validate(None, None, None, obj) # may raise Unauthorized else: obj = self # import time ordering problem if bbb.HAS_ZSERVER: from webdav.NullResource import NullResource else: NullResource = bbb.NullResource resource = _marker try: while path: name = path_pop() __traceback_info__ = path, name if name[0] == '_': # Never allowed in a URL. raise NotFound(name) if name == '..': next = aq_parent(obj) if next is not None: if restricted and not validate(obj, obj, name, next): raise Unauthorized(name) obj = next continue bobo_traverse = getattr(obj, '__bobo_traverse__', None) try: if (name and name[:1] in '@+' and name != '+' and nsParse(name)[1]): # Process URI segment parameters. ns, nm = nsParse(name) try: next = namespaceLookup(ns, nm, obj, aq_acquire(self, 'REQUEST')) if IAcquirer.providedBy(next): next = next.__of__(obj) if restricted and not validate( obj, obj, name, next): raise Unauthorized(name) except LocationError: raise AttributeError(name) else: next = UseTraversalDefault # indicator try: if bobo_traverse is not None: next = bobo_traverse(REQUEST, name) if restricted: if aq_base(next) is not next: # The object is wrapped, so the # acquisition context is the container. container = aq_parent(aq_inner(next)) elif getattr(next, '__self__', None) is not None: # Bound method, the bound instance # is the container container = next.__self__ elif getattr(aq_base(obj), name, _marker) is next: # Unwrapped direct attribute of the # object so object is the container container = obj else: # Can't determine container container = None # If next is a simple unwrapped property, # its parentage is indeterminate, but it # may have been acquired safely. In this # case validate will raise an error, and # we can explicitly check that our value # was acquired safely. try: ok = validate(obj, container, name, next) except Unauthorized: ok = False if not ok: if (container is not None or guarded_getattr( obj, name, _marker) is not next # NOQA: E501 ): raise Unauthorized(name) except UseTraversalDefault: # behave as if there had been no # '__bobo_traverse__' bobo_traverse = None if next is UseTraversalDefault: if getattr(aq_base(obj), name, _marker) is not _marker: if restricted: next = guarded_getattr(obj, name) else: next = getattr(obj, name) else: try: next = obj[name] # The item lookup may return a # NullResource, if this is the case we # save it and return it if all other # lookups fail. if (NullResource is not None and isinstance(next, NullResource)): resource = next raise KeyError(name) except (AttributeError, TypeError): # Raise NotFound for easier debugging # instead of AttributeError: __getitem__ # or TypeError: not subscriptable raise NotFound(name) if restricted and not validate( obj, obj, None, next): raise Unauthorized(name) except (AttributeError, NotFound, KeyError) as e: # Try to look for a view next = queryMultiAdapter( (obj, aq_acquire(self, 'REQUEST')), Interface, name) if next is not None: if IAcquirer.providedBy(next): next = next.__of__(obj) if restricted and not validate(obj, obj, name, next): raise Unauthorized(name) elif bobo_traverse is not None: # Attribute lookup should not be done after # __bobo_traverse__: raise e else: # No view, try acquired attributes try: if restricted: next = guarded_getattr(obj, name, _marker) else: next = getattr(obj, name, _marker) except AttributeError: raise e if next is _marker: # If we have a NullResource from earlier use it. next = resource if next is _marker: # Nothing found re-raise error raise e obj = next return obj except ConflictError: raise except Exception: if default is not _marker: return default else: raise
def _assignation_target(self): return aq_parent(aq_inner(self.context))
def _target_groupnames(self): context = aq_inner(self.context) observation = aq_parent(context) country = observation.country.lower() ldap_wrapper = getUtility(IGetLDAPWrapper)(context) return ['{}-{}'.format(ldap_wrapper(LDAP_MSEXPERT), country)]
def getMailHost(self): """Gets the MailHost.""" return getattr(aq_parent(self), 'MailHost')
def upgrade(tool): """ issue #623, #583, ... """ portal = aq_parent(aq_inner(tool)) setup = portal.portal_setup typestool = getToolByName(portal, 'portal_types') # update affected tools setup.runImportStepFromProfile('profile-bika.lims:default', 'typeinfo') setup.runImportStepFromProfile('profile-bika.lims:default', 'workflow') setup.runImportStepFromProfile('profile-bika.lims:default', 'factorytool') setup.runImportStepFromProfile('profile-bika.lims:default', 'jsregistry') setup.runImportStepFromProfile('profile-bika.lims:default', 'propertiestool') setup.runImportStepFromProfile('profile-bika.lims:default', 'plone.app.registry') # Changes to the catalogs # create lexicon wordSplitter = Empty() wordSplitter.group = 'Word Splitter' wordSplitter.name = 'Unicode Whitespace splitter' caseNormalizer = Empty() caseNormalizer.group = 'Case Normalizer' caseNormalizer.name = 'Unicode Case Normalizer' stopWords = Empty() stopWords.group = 'Stop Words' stopWords.name = 'Remove listed and single char words' zc_extras = Empty() zc_extras.index_type = 'Okapi BM25 Rank' zc_extras.lexicon_id = 'Lexicon' # then add indexes bc = getToolByName(portal, 'bika_catalog') bc.addIndex('getContactTitle', 'FieldIndex', zc_extras) bc.addIndex('getClientTitle', 'FieldIndex', zc_extras) bc.addIndex('getProfileTitle', 'FieldIndex', zc_extras) bc.addIndex('getAnalysisCategory', 'KeywordIndex') bc.addIndex('getAnalysisService', 'KeywordIndex') bc.addIndex('getAnalysts', 'KeywordIndex') bc.clearFindAndRebuild() # add new types not to list in nav # AnalysisRequestQuery and QueryFolder (listed in portal_tabs already) portal_properties = getToolByName(portal, 'portal_properties') ntp = getattr(portal_properties, 'navtree_properties') types = list(ntp.getProperty('metaTypesNotToList')) types.append("AnalysisRequestQuery") types.append("QueryFolder") ntp.manage_changeProperties(MetaTypesNotToQuery=types) # Add /queries folder typestool.constructContent(type_name="QueryFolder", container=portal, id='queries', title='Queries') obj = portal['queries'] obj.unmarkCreationFlag() obj.reindexObject() # /queries folder permissions mp = portal.queries.manage_permission mp(permissions.ListFolderContents, ['Manager', 'LabManager', 'LabClerk', 'Analyst'], 0) mp(permissions.AddPortalContent, ['Manager', 'LabManager', 'LabClerk', 'Analyst'], 0) mp(permissions.View, ['Manager', 'LabManager', 'LabClerk', 'Analyst'], 0) mp('Access contents information', ['Manager', 'LabManager', 'LabClerk', 'Analyst'], 0) mp(permissions.DeleteObjects, ['Manager'], 0) portal.queries.reindexObject() # idserver prefix for AnalysisRequestQuery prefixes = portal.bika_setup.getPrefixes() if [x for x in prefixes if x['portal_type'] == 'AnalysisRequestQuery']: prefixes.append({ 'portal_type': 'AnalysisRequestQuery', 'prefix': 'query-', 'padding': '4' }) portal.bika_setup.setPrefixes(prefixes) return True
def absolute_url(self): return '/'.join([aq_parent(self).absolute_url(), self.getId()])
def migrate_replies(context, in_reply_to, replies, depth=0, just_delete=0): # Recursive function to migrate all direct replies # of a comment. Returns True if there are no replies to # this comment left, and therefore the comment can be removed. if len(replies) == 0: return True for reply in replies: # log indent = " " for i in range(depth): indent += " " log("%smigrate_reply: '%s'." % (indent, reply.title)) should_migrate = True if filter_callback and not filter_callback(reply): should_migrate = False if just_delete: should_migrate = False new_in_reply_to = None if should_migrate: # create a reply object comment = CommentFactory() comment.title = reply.Title() comment.text = reply.cooked_text comment.mime_type = 'text/html' comment.creator = reply.Creator() email = reply.getProperty('email', None) if email: comment.author_email = email comment.creation_date = DT2dt(reply.creation_date) comment.modification_date = DT2dt(reply.modification_date) comment.reply_to = in_reply_to if in_reply_to == 0: # Direct reply to a content object new_in_reply_to = conversation.addComment(comment) else: # Reply to another comment comment_to_reply_to = conversation.get(in_reply_to) replies = IReplies(comment_to_reply_to) try: comment.text.encode("utf-8") new_in_reply_to = replies.addComment(comment) except UnicodeDecodeError, e: log("Fixing UnicodeDecodeError %s" % e) comment.text = comment.text.decode("utf-8") new_in_reply_to = replies.addComment(comment) total_comments_migrated[0] += 1 # migrate all talkbacks of the reply talkback = getattr( reply, 'talkback', None) no_replies_left = migrate_replies(context, new_in_reply_to, talkback.getReplies(), depth=depth+1, just_delete=not should_migrate) if no_replies_left: # remove reply and talkback talkback.deleteReply(reply.id) obj = aq_parent(talkback) obj.talkback = None log("%sremove %s" % (indent, reply.id)) total_comments_deleted[0] += 1
def allowedContentTypes(self, *args, **kwargs): """ We have to follow some rules: 1. If this RepositoryFolder contains another RF, we should not be able to add other types than RFs. 2. If we are reaching the maximum depth of repository folders (Configured in plone.registry), we should not be able to add any more RFs, but then we should be able to add the other configured types in any case. If the maximum_repository_depth is set to 0, we do not have a depth limit. """ # get the default types types = super( RepositoryFolder, self).allowedContentTypes(*args, **kwargs) # get fti of myself fti = self.portal_types.get(self.portal_type) # get maximum depth of repository folders registry = queryUtility(IRegistry) proxy = registry.forInterface(IRepositoryFolderRecords) # 0 -> no restriction maximum_depth = getattr(proxy, 'maximum_repository_depth', 0) current_depth = 0 # if we have a maximum depth, we need to know the current depth if maximum_depth > 0: obj = self while IRepositoryFolder.providedBy(obj): current_depth += 1 obj = aq_parent(aq_inner(obj)) if IPloneSiteRoot.providedBy(obj): break if maximum_depth <= current_depth: # depth exceeded # RepositoryFolder not allowed, but any other type types = filter(lambda a: a != fti, types) # check if self contains any similar objects contains_similar_objects = False for id, obj in self.contentItems(): if obj.portal_type == self.portal_type: contains_similar_objects = True break # filter content types, if required if contains_similar_objects: # only allow same types types = filter(lambda a: a == fti, types) # finally: remove not enabled resticted content types marker_behavior = 'opengever.dossier.behaviors.restricteddossier.' + \ 'IRestrictedDossier' allowed = self.addable_dossier_types \ and self.addable_dossier_types or [] def _filterer(fti): if fti.id in allowed: # fti is enabled in repository folder return True elif getattr(fti, 'behaviors', None) \ and marker_behavior in fti.behaviors: # fti has marker interface and is not enabled return False else: # normal type - we don't care return True types = filter(_filterer, types) return types
def getTool(self): return aq_parent(aq_inner(self))
def nextURL(self): return "{}#periods".format( aq_parent(aq_inner(self.context)).absolute_url())
def getTargetFolder(self): target_folder = getattr(self.calendar, 'target_folder', None) addContext = target_folder and self.portal.unrestrictedTraverse( '/' + self.portal.id + target_folder) or aq_parent( aq_inner(self.context)) return addContext.absolute_url()
for brain in new_brains: try: obj = brain.getObject() talkback = getattr( obj, 'talkback', None) except: log("There is no object for the brain at: %s" % brain.getPath()) talkback = None if talkback: replies = talkback.getReplies() if replies: conversation = IConversation(obj) log("\n") log("Migrate '%s' (%s)" % (obj.Title(), obj.absolute_url(relative=1))) migrate_replies(context, 0, replies) obj = aq_parent(talkback) obj.talkback = None if total_comments_deleted[0] != total_comments_migrated[0]: log("Something went wrong during migration. The number of \ migrated comments (%s) differs from the number of deleted \ comments (%s)." # pragma: no cover % (total_comments_migrated[0], total_comments_deleted[0])) if not test: # pragma: no cover transaction.abort() # pragma: no cover log("Abort transaction") # pragma: no cover log("\n") log("Comment migration finished.") log("\n")
def parent(obj): return aq_parent(aq_inner(obj))
def getTopicRelativeUrl(self): if CMFPloneUtils.isDefaultPage(self.context, self.request): return '/' + aq_parent(aq_inner( self.context)).absolute_url(relative=1) else: return '/' + self.context.absolute_url(relative=1)
def getWorkflow(self): return aq_parent(aq_inner(aq_parent(aq_inner(self))))
def getTargetFolder(self): return aq_parent(aq_inner(self.context)).absolute_url()
def get_repository_folder_title(self, language): main_dossier = self.get_containing_dossier().get_main_dossier() repository_folder = aq_parent(aq_inner(main_dossier)) return repository_folder.Title(language=language, prefix_with_reference_number=False)
def deleteSubnet(self, uid): toDel = self._dmd.restrictedTraverse(uid) aq_parent(toDel)._delObject(toDel.id) return True
def _getPAS(self): """ Canonical way to get at the PAS instance from a plugin """ return aq_parent(aq_inner(self))
def searchNearestTranslatedParent(self, content): parent = aq_parent(content) while parent.Language() != content.Language()\ and not IPloneSiteRoot.providedBy(parent): parent = aq_parent(parent) return parent
def getPortalObject(self): return aq_parent(aq_inner(self))
def __call__(self): if not self.available: return None return aq_parent(aq_inner(self.context))
def __call__(self): self.errors = [] self.protect() context = aq_inner(self.context) catalog = getToolByName(context, 'portal_catalog') mtool = getToolByName(context, 'portal_membership') missing = [] for key in self.request.form.keys(): if not key.startswith('UID_'): continue index = key.split('_')[-1] uid = self.request.form[key] brains = catalog(UID=uid, show_inactive=True) if len(brains) == 0: missing.append(uid) continue obj = brains[0].getObject() title = self.objectTitle(obj) if not mtool.checkPermission('Copy or Move', obj): self.errors( _(u'Permission denied to rename ${title}.', mapping={u'title': title})) continue sp = transaction.savepoint(optimistic=True) newid = self.request.form['newid_' + index] if six.PY2: newid = newid.encode('utf8') newtitle = self.request.form['newtitle_' + index] try: obid = obj.getId() title = obj.Title() change_title = newtitle and title != newtitle if change_title: getSecurityManager().validate(obj, obj, 'setTitle', obj.setTitle) obj.setTitle(newtitle) notify(ObjectModifiedEvent(obj)) if newid and obid != newid: parent = aq_parent(aq_inner(obj)) # Make sure newid is safe newid = INameChooser(parent).chooseName(newid, obj) # Update the default_page on the parent. context_state = getMultiAdapter((obj, self.request), name='plone_context_state') if context_state.is_default_page(): parent.setDefaultPage(newid) parent.manage_renameObjects((obid, ), (newid, )) elif change_title: # the rename will have already triggered a reindex obj.reindexObject() except ConflictError: raise except Exception as e: sp.rollback() if six.PY2: title = title.decode('utf8') logger.error(u'Error renaming "{title}": "{exception}"'.format( title=title, exception=e)) self.errors.append( _(u'Error renaming ${title}', mapping={'title': title})) return self.message(missing)
def getMenuItems(self, context, request): """Return menu item entries in a TAL-friendly form. """ try: lang_names = request.locale.displayNames.languages except AttributeError: lang_names = {} menu = [] url = context.absolute_url() lt = getToolByName(context, "portal_languages") site_url = getSite().absolute_url() showflags = lt.showFlags context_id = ITranslationManager(context).tg registry = getUtility(IRegistry) settings = registry.forInterface(IMultiLanguageExtraOptionsSchema, prefix="plone") edit_view = 'babel_edit' if settings.redirect_babel_view else 'edit' # In case is neutral language show set language menu only is_neutral_content = ( ILanguage(context).get_language() == LANGUAGE_INDEPENDENT or is_language_independent(context) ) shared_folder_url = site_url + '/folder_contents' pc = getToolByName(getSite(), 'portal_catalog') results = pc.unrestrictedSearchResults( portal_type='LIF', Language=ILanguage(context).get_language()) for brain in results: shared_folder_url = brain.getURL() + '/folder_contents' if not is_neutral_content and not INavigationRoot.providedBy(context): menu.append({ "title": _( u"title_babel_edit", default=u"Edit with babel view" ), "description": _( u"description_babel_edit", default=u"Edit with the babel_edit" ), "action": url + "/" + edit_view, "selected": False, "icon": None, "extra": { "id": "_edit_babel_edit", "separator": None, "class": "", }, "submenu": None, }) if ITranslatable.providedBy(context): contexts = [context, ] else: contexts = [] prt = aq_parent(context) if is_default_page(prt, context) and ITranslatable.providedBy(prt): contexts.append(prt) for idx, context in enumerate(contexts): url = context.absolute_url() ulangs = untranslated_languages(context) for lang in ulangs: lang_name = lang_names.get(lang.value, lang.title) lang_id = lang.value icon = showflags and lt.getFlagForLanguageCode(lang_id)\ or None item = { "description": _( u"description_translate_into", default=u"Translate into ${lang_name}", mapping={"lang_name": lang_name} ), "action": "%s/@@create_translation?language=%s" % ( url, lang_id), "selected": False, "icon": icon, "width": "14", "height": "11", "extra": {"id": "translate_into_%s" % lang_id, "separator": None, "class": "contentmenuflags"}, "submenu": None, } item['title'] = idx and _( u'create_translation_folder', default=u"Create ${lang_name} folder", mapping={"lang_name": lang_name} ) or _( u'create_translation', default=u"Create ${lang_name}", mapping={"lang_name": lang_name} ) menu.append(item) langs = translated_languages(context) urls = translated_urls(context) for lang in langs: if lang.value not in urls.by_token: # omit if translation is not permitted to access. continue lang_name = lang_names.get(lang.value, lang.title) lang_id = lang.value icon = showflags and lt.getFlagForLanguageCode(lang_id)\ or None item = { "description": _( u"description_babeledit_menu", default=u"Babel edit ${lang_name}", mapping={"lang_name": lang_name} ), "action": (urls.getTerm(lang_id).title + "/" + edit_view), "selected": False, "icon": icon, "width": "14", "height": "11", "extra": {"id": "babel_edit_%s" % lang_id, "separator": None, "class": "contentmenuflags"}, "submenu": None, } item['title'] = idx and _( u'edit_translation_folder', default=u"Edit ${lang_name} folder", mapping={"lang_name": lang_name} ) or _( u'edit_translation', default=u"Edit ${lang_name}", mapping={"lang_name": lang_name} ) menu.append(item) item = { "description": _( u"description_add_translations", default=u"Add existing content as translation"), "action": url + "/add_translations", "selected": False, "icon": None, "extra": { "id": "_add_translations", "separator": langs and "actionSeparator" or None, "class": "" }, "submenu": None, } item['title'] = idx and _( u"title_add_translations_folder", default=u"Add translations for folder..." ) or _( u"title_add_translations", default=u"Add translations..." ) menu.append(item) item = { "title": _( u"title_remove_translations", default=u"Remove translations..." ), "description": _( u"description_remove_translations", default=u"Delete translations or remove the relations" ), "action": url + "/remove_translations", "selected": False, "icon": None, "extra": { "id": "_remove_translations", "separator": langs and "actionSeparator" or None, "class": "" }, "submenu": None, } menu.append(item) elif is_neutral_content: menu.append({ "title": _( u"language_folder", default=u"Return to language folder" ), "description": _( u"description_language_folder", default=u"Go to the user's browser preferred language " u"related folder" ), "action": site_url + '/' + lt.getPreferredLanguage(), "selected": False, "icon": None, "extra": { "id": "_language_folder", "separator": None, "class": "" }, "submenu": None, }) if not is_neutral_content: menu.append({ "title": _( u"universal_link", default=u"Universal Link" ), "description": _( u"description_universal_link", default=u"Universal Language content link" ), "action": "%s/@@multilingual-universal-link/%s" % ( site_url, context_id), "selected": False, "icon": None, "extra": { "id": "_universal_link", "separator": None, "class": "" }, "submenu": None, }) menu.append({ "title": _( u"shared_folder", default=u"Go to Media folder" ), "description": _( u"description_shared_folder", default=u"Show the shared Language Independent Folder" ), "action": shared_folder_url, "selected": False, "icon": None, "extra": { "id": "_shared_folder", "separator": None, "class": ""}, "submenu": None, }) menu.append({ "title": _( u"title_set_language", default=u"Set content language" ), "description": _( u"description_set_language", default=u"Set or change the current content language" ), "action": url + "/update_language", "selected": False, "icon": None, "extra": { "id": "_set_language", "separator": None, "class": "" }, "submenu": None, }) return menu
def __init__(self, tool, profile_path, should_purge=False, encoding=None): self._site = aq_parent(aq_inner(tool)) self._profile_path = profile_path self._should_purge = bool(should_purge) self._encoding = encoding
def getPhysicalPath(self): p = aq_parent(aq_inner(self)) path = (self._id, ) if p is not None: path = p.getPhysicalPath() + path return path
def __init__(self, tool, snapshot_id): self._tool = tool = aq_inner(tool) self._site = aq_parent(tool) self._snapshot_id = snapshot_id
def getMembersFolder(self): """ Get the members folder object. """ parent = aq_parent(aq_inner(self)) members = getattr(parent, 'Members', None) return members