def handleBeforeProfileImportEvent(event): profile_id = event.profile_id if profile_id is None or not event.full_import: return if profile_id.startswith("profile-"): profile_id = profile_id[8:] context = event.tool # We need a request to scribble some data in request = getattr(context, "REQUEST", None) if request is None: return if FILTER_PROFILES: ignore_profiles = getattr(request, '_cachedIgnoredProfiles', ()) if not ignore_profiles: ignore_profiles = [] utils = getAllUtilitiesRegisteredFor(INonInstallable) for util in utils: ignore_profiles.extend(util.getNonInstallableProfiles()) request._cachedIgnoredProfiles = tuple(ignore_profiles) if profile_id in ignore_profiles: return qi = getToolByName(context, "portal_quickinstaller", None) if qi is None: return product = findProductForProfile(context, profile_id, qi) if product is None: return snapshot = qi.snapshotPortal(aq_parent(context)) storage = IAnnotatable(request, None) if storage is None: return installing = storage.get("Products.CMFQuickInstaller.Installing", []) if product in installing: return if storage.has_key("Products.CMFQuickInstallerTool.Events"): data = storage["Products.CMFQuickInstallerTool.Events"] else: data = storage["Products.CMFQuickInstallerTool.Events"] = {} data[event.profile_id] = dict(product=product, snapshot=snapshot)
def ensure_child_ordering_object_ids_are_native_strings(container): """Make sure the ordering stored on parent contains only native_string object ids. This function can be used to fix ordering object ids stored on a parent object in a `DefaultOrdering` ordering adapter. When changing object ordering via PATCH request we used to incorrectly store ids of reordered resouces as unicode instead of a bytestring (on python 2). This lead to mixed types being stored in the ordering annotations and subsequently mixed types being returned when calling `objectIds` of a container. The problem only exists with python 2 so we do nothing when we are called on python 3 by mistake. """ if six.PY3: return if not IAnnotatable.providedBy(container): return annotations = IAnnotations(container) if ORDER_KEY not in annotations: return fixed_ordering = PersistentList( safe_utf8(item_id) for item_id in annotations[ORDER_KEY]) annotations[ORDER_KEY] = fixed_ordering
def __setattr__(self, attr, value): """ """ if not IAnnotatable.providedBy(self.context): alsoProvides(self.context, IAnnotatable) d = IAnnotations(self.context).get(ANNOTATION_KEY, {}) d[attr] = value IAnnotations(self.context)[ANNOTATION_KEY] = d
def upgrade_attribute_storage(context): portal = getSite() catalog = getToolByName(portal, 'portal_catalog') query = {} query[ 'object_provides'] = 'collective.geolocationbehavior.geolocation.IGeolocatableMarker' # noqa results = catalog(**query) log.info('There are {0} in total, stating migration...'.format( len(results))) for result in results: try: obj = result.getObject() except: log.warning('Not possible to fetch object from catalog result for ' 'item: {0}.'.format(result.getPath())) continue if not IAnnotatable.providedBy(obj): log.warning( 'The object at {0} does provide annotation capabilities, ' 'skipping.'.format(obj.absolute_url())) continue annotations = IAnnotations(obj) oldvalue = annotations.get(GEO_ANNOTATION_KEY, None) geolocation = getattr(oldvalue, 'geolocation', None) if geolocation and not IGeolocatable(obj).geolocation: # Only write the old value if there is no new value yet IGeolocatable(obj).geolocation = geolocation notify(ObjectModifiedEvent(obj)) log.info('Set geolocation lat: {0}, lng: {1} for {2}'.format( geolocation.latitude, geolocation.longitude, obj.absolute_url())) if oldvalue: del annotations[GEO_ANNOTATION_KEY] obj.reindexObject( ) # reindex - old IGeolocatableMarker doesn't exist anymore # noqa
def notify_content_object_deleted(obj, event): """Remove all comments of a content object when the content object has been deleted. """ if IAnnotatable.providedBy(obj): conversation = IConversation(obj) while conversation: del conversation[conversation.keys()[0]]
def supports_snapshots(obj): """Checks if the object supports snapshots Only objects which can hold an annotation storage can be auditable :param obj: Content object :returns: True/False """ return IAnnotatable.providedBy(obj)
def __getattr__(self, key): """ """ context = self.__dict__['context'] if not IAnnotatable.providedBy(context): alsoProvides(context, IAnnotatable) annos = IAnnotations(context).get(ANNOTATION_KEY, {}) if annos.has_key(key): return annos[key] raise AttributeError
def outdate_item(ob, *arg, **kw): err = list() value = kw.get("outdated_status", None) value = not not value if IAnnotatable.providedBy(ob): IAnnotations(ob)[ANNOTATION_KEY] = value else: err.append("Object %s does not support annotations" % ob.absolute_url()) return err
def getExisting(self): portal_catalog = getToolByName(self.context, 'portal_catalog') if not IAnnotatable.providedBy(self.context): return '' ann = IAnnotations(self.context) existing_uid = ann.get(config.EXISTING_SWITCHED_CONTENT_UID, '') existing_url = '' if existing_uid: res = portal_catalog(UID=existing_uid) existing = len(res) and res[0].getObject() existing_url = existing and existing.absolute_url() return existing_url
def get(self, name): # first check overrides if exists and is True overrides = getattr(self, '%s_override' % name, True) if not overrides: return None context = aq_inner(self.context) if not IAnnotatable.providedBy(self.context): return None annotations = IAnnotations(context) if annotations.has_key(PERSEO): return annotations[PERSEO].get(name, None) return None
def get(self, name): # first check overrides if exists and is True overrides = getattr(self, "%s_override" % name, True) if not overrides: return None context = aq_inner(self.context) if not IAnnotatable.providedBy(self.context): return None annotations = IAnnotations(context) if PERSEO in annotations: # print "return %s --> %s" % (name, annotations[PERSEO].get(name, None)) return annotations[PERSEO].get(name, None) return None
def handleProfileImportedEvent(event): if event.profile_id is None or not event.full_import: return context = event.tool # We need a request to scribble some data in request = getattr(context, "REQUEST", None) if request is None: return storage = IAnnotatable(request, None) if storage is None: return data = storage.get("Products.CMFQuickInstallerTool.Events", []) if event.profile_id not in data: return info = data[event.profile_id] qi = getToolByName(context, "portal_quickinstaller", None) if qi is None: return after = qi.snapshotPortal(aq_parent(context)) settings = qi.deriveSettingsFromSnapshots(info["snapshot"], after) version = qi.getProductVersion(info["product"]) qi.notifyInstalled( info["product"], locked=False, logmsg="Installed via setup tool", settings=settings, installedversion=version, status='installed', error=False, )
def handleBeforeProfileImportEvent(event): profile_id = event.profile_id if profile_id is None or not event.full_import: return if profile_id.startswith("profile-"): profile_id = profile_id[8:] context = event.tool # We need a request to scribble some data in request = getattr(context, "REQUEST", None) if request is None: return qi = getToolByName(context, "portal_quickinstaller", None) if qi is None: return product = findProductForProfile(context, profile_id, qi) if product is None: return snapshot = qi.snapshotPortal(aq_parent(context)) storage = IAnnotatable(request, None) if storage is None: return installing = storage.get("Products.CMFQuickInstaller.Installing", []) if product in installing: return if "Products.CMFQuickInstallerTool.Events" in storage: data = storage["Products.CMFQuickInstallerTool.Events"] else: data = storage["Products.CMFQuickInstallerTool.Events"] = {} data[event.profile_id] = dict(product=product, snapshot=snapshot)
def _global_unprotect(self): # portal_memberdata._members cache will be written sometimes. if IPloneSiteRoot.providedBy(getSite()): unprotected_write(getToolByName(getSite(), 'portal_memberdata')._members) context = self.getContext() # always allow writes to context's annotations. if IAnnotatable.providedBy(context): annotations = IAnnotations(context) unprotected_write(annotations) if CONTEXT_ASSIGNMENT_KEY in annotations: # also allow writes to context portlet assignments unprotected_write(annotations[CONTEXT_ASSIGNMENT_KEY])
def _global_unprotect(self): # portal_memberdata._members cache will be written sometimes. if IPloneSiteRoot.providedBy(getSite()): unprotected_write( getToolByName(getSite(), 'portal_memberdata')._members) context = self.getContext() # always allow writes to context's annotations. if IAnnotatable.providedBy(context): annotations = IAnnotations(context) unprotected_write(annotations) if CONTEXT_ASSIGNMENT_KEY in annotations: # also allow writes to context portlet assignments unprotected_write(annotations[CONTEXT_ASSIGNMENT_KEY])
def upgrade_attribute_storage(context): portal = getSite() catalog = getToolByName(portal, 'portal_catalog') query = {} query['object_provides'] = IDXEvent.__identifier__ results = catalog(**query) log.info('There are {0} in total, stating migration...'.format( len(results))) for result in results: try: event = result.getObject() except: log.warning( 'Not possible to fetch event object from catalog result for ' 'item: {0}.'.format(result.getPath())) continue if not IAnnotatable.providedBy(event): log.warning( 'The event at {0} does provide annotation capabilities, ' 'skipping.'.format(event.absolute_url())) continue annotations = IAnnotations(event) did_work = False for behavior in BEHAVIOR_LIST: for name in behavior.names(): fullname = '{0}.{1}'.format(behavior.__identifier__, name) oldvalue = annotations.get(fullname, None) # Only write the old value if there is no new value yet if oldvalue and not getattr(event, name, None): setattr(event, name, oldvalue) did_work = True # The old IEventSummary behavior is gone, just look for the old name # inside the annotation storage oldvalue = annotations.get( 'plone.app.event.dx.behaviors.IEventSummary.text', None) if oldvalue and not getattr(event, 'text', None): setattr(event, 'text', oldvalue) did_work = True if did_work: notify(ObjectModifiedEvent(event)) log.debug('Handled event at {0}'.format(event.absolute_url()))
def upgrade_attribute_storage(context): portal = getSite() catalog = getToolByName(portal, 'portal_catalog') query = {} query['object_provides'] = 'collective.geolocationbehavior.geolocation.IGeolocatableMarker' # noqa results = catalog(**query) log.info('There are {0} in total, stating migration...'.format( len(results))) for result in results: try: obj = result.getObject() except: log.warning( 'Not possible to fetch object from catalog result for ' 'item: {0}.'.format(result.getPath())) continue if not IAnnotatable.providedBy(obj): log.warning( 'The object at {0} does provide annotation capabilities, ' 'skipping.'.format(obj.absolute_url())) continue annotations = IAnnotations(obj) oldvalue = annotations.get(GEO_ANNOTATION_KEY, None) geolocation = getattr(oldvalue, 'geolocation', None) if geolocation and not IGeolocatable(obj).geolocation: # Only write the old value if there is no new value yet IGeolocatable(obj).geolocation = geolocation notify(ObjectModifiedEvent(obj)) log.info('Set geolocation lat: {0}, lng: {1} for {2}'.format( geolocation.latitude, geolocation.longitude, obj.absolute_url()) ) if oldvalue: del annotations[GEO_ANNOTATION_KEY] obj.reindexObject() # reindex - old IGeolocatableMarker doesn't exist anymore # noqa
def installProduct( self, product_name, locked=False, hidden=False, swallowExceptions=None, reinstall=False, forceProfile=False, omitSnapshots=True, profile=None, blacklistedSteps=None ): """Install a product by name """ __traceback_info__ = (product_name, ) if profile is not None: forceProfile = True if self.isProductInstalled(product_name): prod = self._getOb(product_name) msg = ('This product is already installed, ' 'please uninstall before reinstalling it.') prod.log(msg) return msg portal = aq_parent(aq_inner(self)) before = self.snapshotPortal(portal) if hasattr(self, "REQUEST"): reqstorage = IAnnotatable(self.REQUEST, None) if reqstorage is not None: installing = reqstorage.get( "Products.CMFQUickInstaller.Installing", set() ) installing.add(product_name) else: reqstorage = None # XXX We can not use getToolByName since that returns a utility # without a RequestContainer. This breaks import steps that need # to run tools which request self.REQUEST. portal_setup = aq_get(portal, 'portal_setup', None, 1) status = None res = '' # Create a snapshot before installation before_id = portal_setup._mangleTimestampName( 'qi-before-%s' % product_name ) if not omitSnapshots: portal_setup.createSnapshot(before_id) install = False if not forceProfile: try: # Install via external method install = self.getInstallMethod(product_name).__of__(portal) except AttributeError: # No classic install method found pass if install and not forceProfile: try: res = install(portal, reinstall=reinstall) except TypeError: res = install(portal) status = 'installed' else: profiles = self.getInstallProfiles(product_name) if profiles: if profile is None: profile = profiles[0] if len(profiles) > 1: logger.info( 'Multiple extension profiles found for product ' '%s. Used profile: %s' % (product_name, profile) ) portal_setup.runAllImportStepsFromProfile( 'profile-%s' % profile, blacklisted_steps=blacklistedSteps, ) status = 'installed' else: # No install method and no profile, log / abort? pass if reqstorage is not None: installing.remove(product_name) # Create a snapshot after installation after_id = portal_setup._mangleTimestampName( 'qi-after-%s' % product_name ) if not omitSnapshots: portal_setup.createSnapshot(after_id) if profile: # If installation was done via a profile, the settings were already # snapshotted in the IProfileImportedEvent handler, and we should # use those because the ones derived here include settings from # dependency profiles. settings = {} else: after = self.snapshotPortal(portal) settings = self.deriveSettingsFromSnapshots(before, after) rr_css = getToolByName(self, 'portal_css', None) if rr_css is not None: if ( 'resources_css' in settings and len(settings['resources_css']) > 0 ): rr_css.cookResources() msg = str(res) version = self.getProductVersion(product_name) # add the product self.notifyInstalled( product_name, settings=settings, installedversion=version, logmsg=res, status=status, error=False, locked=locked, hidden=hidden, afterid=after_id, beforeid=before_id ) prod = getattr(self, product_name) afterInstall = prod.getAfterInstallMethod() if afterInstall is not None: afterInstall = afterInstall.__of__(portal) afterRes = afterInstall(portal, reinstall=reinstall, product=prod) if afterRes: res = res + '\n' + str(afterRes) return res
def get_actions_for(request): if IAnnotatable.providedBy(request): annotations = IAnnotations(request) else: annotations = {} return annotations.setdefault("collective.gsa64.actions", {})
def test_object_annotatable(self): self.assertTrue(IAnnotatable.providedBy(self.s1))
def set_settings(request, registry): settings = registry.forInterface(IConnectionSettings) if IAnnotatable.providedBy(request): IAnnotations(request).setdefault("collective.gsa64.settings", settings)
def retrieve(self): ST = [] pc = self.portal_catalog link_checker = self.portal_linkchecker async = getUtility(IAsyncService) sm = getSecurityManager() # INitialize the helperattribute to store paths to retrieve objpaths = getattr(link_checker, 'objpaths', None) cleanup = self.REQUEST.get('cleanup', False) if objpaths is None or cleanup=='1': link_checker.objpaths = [] objpaths = [] # Check wheter we start fresh or need to resume resume = self.REQUEST.get('resume') debug = self.REQUEST.get('debug') LOG("LCRetrieveByPath", INFO, "Resuming retrieval with %s paths" % len(objpaths)) if len(objpaths)==0 and not resume: path = self.REQUEST.get('path', '/'.join(self.getPhysicalPath())) alllangs = self.portal_languages.getSupportedLanguages() langs = self.REQUEST.get('langs', alllangs) print "path: %s" %path if "%s" in path: paths = [path%lang for lang in langs] else: paths = [path] LOG("LCRetrieveByPath", INFO, "Starting retrieval") for path in paths: LOG("LCRetrieveByPath", INFO, "> Path %s"%path) results = pc(Language='all', path=path) objpaths = [x.getPath() for x in results] link_checker.objpaths += objpaths LOG("LCRetrieveByPath", INFO, "> %s results found"%len(results)) # DONE Retrieving objpaths, start checkretrieval cnt = 0 objpaths = [x for x in link_checker.objpaths] total = len(objpaths) for path in objpaths: if debug: print path try: ob = self.unrestrictedTraverse(path) except: continue if not ob: continue if not sm.checkPermission(ModifyPortalContent, ob): continue if (not IReferenceable.providedBy(ob)): continue outdated = IAnnotatable.providedBy(ob) and \ IAnnotations(ob).get(ANNOTATION_KEY, False) or False if outdated: LOG("CMFLinkChecker", INFO, "unregistering %s, object is outdated" % path) links = link_checker.database.getLinksForObject(ob) link_ids = [x.getId() for x in links] job = async.queueJob(unregister_async, link_checker, link_ids) job.addCallbacks(failure=job_failure_callback) continue if not is_publically_visible(ob): LOG('CMFLinkChecker', INFO, "Skipping %s, obj is not public" % path) continue job = async.queueJob(retrieve_async, ob, path, online=True) job.addCallbacks(failure=job_failure_callback) LOG("LCRetrieveByPath", INFO, "> Retrieved %s"%path) ST.append("retrieved %s" % path) link_checker.objpaths.remove(path) link_checker._p_changed = 1 cnt += 1 if cnt%10==0: transaction.commit() LOG("LCRetrieveByPath", INFO, "Committing %s of %s" %(cnt, total)) LOG("LCRetrieveByPath", INFO, "Fertig") return "\n".join(ST)
def checkPerseoTabAvailable(self): """ Checks visibility of SEO tab for context """ return not IPloneSiteRoot.providedBy(self.context) and IAnnotatable.providedBy(self.context)
def isAnnotatable(self): """Does the object observed expect to be annotated? """ return IAnnotatable.providedBy(self.obj)
def is_outdated(obj): if IAnnotatable.providedBy(obj): return IAnnotations(obj).get('slc.outdated', False)
def __set__(self, obj, val): if obj is None: raise AttributeError("Can't set attribute") if IAnnotatable.providedBy(obj.context): IAnnotations(obj.context)[ANNOTATION_KEY] = val
def installProduct(self, product_name, locked=False, hidden=False, swallowExceptions=None, reinstall=False, forceProfile=False, omitSnapshots=True, profile=None, blacklistedSteps=None): """Install a product by name """ __traceback_info__ = (product_name, ) if profile is not None: forceProfile = True if self.isProductInstalled(product_name): prod = self._getOb(product_name) msg = ('This product is already installed, ' 'please uninstall before reinstalling it.') prod.log(msg) return msg portal = aq_parent(aq_inner(self)) before = self.snapshotPortal(portal) if hasattr(self, "REQUEST"): reqstorage = IAnnotatable(self.REQUEST, None) if reqstorage is not None: installing = reqstorage.get( "Products.CMFQUickInstaller.Installing", set()) installing.add(product_name) else: reqstorage = None # XXX We can not use getToolByName since that returns a utility # without a RequestContainer. This breaks import steps that need # to run tools which request self.REQUEST. portal_setup = aq_get(portal, 'portal_setup', None, 1) status = None res = '' # Create a snapshot before installation before_id = portal_setup._mangleTimestampName('qi-before-%s' % product_name) if not omitSnapshots: portal_setup.createSnapshot(before_id) install = False if not forceProfile: try: # Install via external method install = self.getInstallMethod(product_name).__of__(portal) except AttributeError: # No classic install method found pass if install and not forceProfile: try: res = install(portal, reinstall=reinstall) except TypeError: res = install(portal) status = 'installed' else: profiles = self.getInstallProfiles(product_name) if profiles: if profile is None: profile = profiles[0] if len(profiles) > 1: logger.info( 'Multiple extension profiles found for product ' '%s. Used profile: %s' % (product_name, profile)) portal_setup.runAllImportStepsFromProfile( 'profile-%s' % profile, blacklisted_steps=blacklistedSteps, ) status = 'installed' else: # No install method and no profile, log / abort? pass if reqstorage is not None: installing.remove(product_name) # Create a snapshot after installation after_id = portal_setup._mangleTimestampName('qi-after-%s' % product_name) if not omitSnapshots: portal_setup.createSnapshot(after_id) if profile: # If installation was done via a profile, the settings were already # snapshotted in the IProfileImportedEvent handler, and we should # use those because the ones derived here include settings from # dependency profiles. settings = {} else: after = self.snapshotPortal(portal) settings = self.deriveSettingsFromSnapshots(before, after) rr_css = getToolByName(self, 'portal_css', None) if rr_css is not None: if ('resources_css' in settings and len(settings['resources_css']) > 0): rr_css.cookResources() msg = str(res) version = self.getProductVersion(product_name) # add the product self.notifyInstalled(product_name, settings=settings, installedversion=version, logmsg=res, status=status, error=False, locked=locked, hidden=hidden, afterid=after_id, beforeid=before_id) prod = getattr(self, product_name) afterInstall = prod.getAfterInstallMethod() if afterInstall is not None: afterInstall = afterInstall.__of__(portal) afterRes = afterInstall(portal, reinstall=reinstall, product=prod) if afterRes: res = res + '\n' + str(afterRes) return res
def __get__(self, obj, objtype=None): if obj is None: return self if IAnnotatable.providedBy(obj.context): return IAnnotations(obj.context).get(ANNOTATION_KEY, False) return False
def LCRetrieveByDate(self, skiplist=[]): """Retrieves the links from all objects in the site by Date.""" sincedate = DateTime()-6*30 since = self.REQUEST.get('since') if since is not None: since = DateTime(since) sincedate = since or sincedate offline = self.REQUEST.get('offline', '') pwt = self.portal_workflow lc = self.portal_linkchecker async = getUtility(IAsyncService) sm = getSecurityManager() try: server = lc.database._getWebServiceConnection() except: server = None if server is None and offline!='1': raise RuntimeError, "The site could not be crawled because no " \ "connection to the lms could be established." # # Not actually necessary on every crawl, but it doesn't seem to work # # in the installer, so this seems the next logical place to do it. # self.portal_catalog.reindexIndex('portal_linkchecker_uid', self.REQUEST) if 1: # gather all objects that are of a type we can check for links objects = self.portal_catalog(Language='all', modified={'query':sincedate,'range':'min'}) os_ = len(objects) zLOG.LOG('CMFLinkChecker', zLOG.INFO, "%d objects will be crawled" % os_) i = 0 for res in objects: i += 1 zLOG.LOG("CMFLinkChecker", zLOG.BLATHER, "Site Crawl Status", "%s of %s (%s)" % (i, os_, res.getPath())) ob = res.getObject() if ob is None: # Maybe the catalog isn't up to date continue outdated = IAnnotatable.providedBy(ob) and \ IAnnotations(ob).get(ANNOTATION_KEY, False) or False if outdated: zLOG.LOG("CMFLinkChecker", zLOG.INFO, "unregistering %s, object is outdated" % res.getPath()) links = lc.database.getLinksForObject(ob) link_ids = [x.getId() for x in links] job = async.queueJob(unregister_async, lc, link_ids) callback = job.addCallbacks(failure=job_failure_callback) continue try: state = pwt.getInfoFor(ob, 'review_state') except: state = "undefined" if state not in ALLOWED_STATES: zLOG.LOG("CMFLinkChecker", zLOG.BLATHER, "unregistering, object is not public: %s" % state) links = lc.database.getLinksForObject(ob) link_ids = [x.getId() for x in links] job = async.queueJob(unregister_async, lc, link_ids) callback = job.addCallbacks(failure=job_failure_callback) continue if not sm.checkPermission(ModifyPortalContent, ob): continue if (not IReferenceable.providedBy(ob)): continue job = async.queueJob(retrieve_async, ob, res.getPath(), online=True) callback = job.addCallbacks(failure=job_failure_callback) if not i % 500 : transaction.savepoint() zLOG.LOG('CMFLinkChecker', zLOG.INFO, "Crawling site - commited after %d objects" %(i)) return "finished"