def get_references(self): """ AT references """ try: from Products.Archetypes.interfaces import IReferenceable if not IReferenceable.providedBy(self.context): return except: return self['_atrefs'] = {} self['_atbrefs'] = {} relationships = self.context.getRelationships() for rel in relationships: self['_atrefs'][rel] = [] refs = self.context.getRefs(relationship=rel) for ref in refs: if ref is not None: self['_atrefs'][rel].append('/'.join(ref.getPhysicalPath())) brelationships = self.context.getBRelationships() for brel in brelationships: self['_atbrefs'][brel] = [] brefs = self.context.getBRefs(relationship=brel) for bref in brefs: if bref is not None: self['_atbrefs'][brel].append('/'.join(bref.getPhysicalPath()))
def checkout_allowed(self): """Check if a checkout is allowed. """ context = aq_inner(self.context) checkPermission = getSecurityManager().checkPermission if not interfaces.IIterateAware.providedBy(context): return False if not IReferenceable.providedBy(context): return False archiver = interfaces.IObjectArchiver(context) if not archiver.isVersionable(): return False # check if there is an existing checkout if len(context.getBRefs(WorkingCopyRelation.relationship)) > 0: return False # check if it is a checkout or contains a checkout if recursivelyCheckForWorkingCopies(context): return False # check if it is contained by a checkout if recursivelyCheckParentsForWorkingCopies(context): return False # check the permission if not checkPermission(permissions.CheckoutPermission, context): return False return True
def transmogrify(self, item): path = self.get_path(item) obj = self.get_object(item) uid = item.get(self.uidkey, "") if not uid: raise NothingToDoHere at_uid = ATIReferenceable.providedBy(obj) dx_uid = DXIReferenceable.providedBy(obj) old_uid = obj.UID() if old_uid != uid: # Code from plone.app.transmogrifier used for AT objects: if at_uid: if not old_uid: setattr(obj, AT_UUID_ATTR, uid) else: obj._setUID(uid) elif dx_uid: setattr(obj, DX_UID_ATTR, uid) else: #Don't ask, JUST DO IT! # If the attribute is not used as UID, it # is not used as anything else as well, # and at least the desired UID value stays recorded in the # object, allowing for a post-migration retrieval setattr(obj, DEFAULT_UID_ATTR, uid) return item
def get_references(self): """ AT references """ try: from Products.Archetypes.interfaces import IReferenceable if not IReferenceable.providedBy(self.context): return except: return self['_atrefs'] = {} self['_atbrefs'] = {} relationships = self.context.getRelationships() for rel in relationships: self['_atrefs'][rel] = [] refs = self.context.getRefs(relationship=rel) for ref in refs: if ref is not None: self['_atrefs'][rel].append('/'.join( ref.getPhysicalPath())) brelationships = self.context.getBRelationships() for brel in brelationships: self['_atbrefs'][brel] = [] brefs = self.context.getBRefs(relationship=brel) for bref in brefs: if bref is not None: self['_atbrefs'][brel].append('/'.join( bref.getPhysicalPath()))
def getObjectsFromLinks(base, links): """ determine actual objects refered to by given links """ objects = set() url = base.absolute_url() scheme, host, path, query, frag = urlsplit(url) for link in links: s, h, path, q, f = urlsplit(link) # relative or local url if (not s and not h) or (s == scheme and h == host): # Paths should always be strings if isinstance(path, unicode): path = path.encode('utf-8') obj, extra = findObject(base, path) if obj: if IOFSImage.providedBy(obj): # use atimage object for scaled images obj = aq_parent(obj) if not IReferenceable.providedBy(obj): try: obj = IReferenceable(obj) except: continue objects.add(obj) return objects
def _notifyOfCopyTo(self, container, op=0): """In the case of a move (op=1) we need to make sure references are mainained for all referencable objects within the one being moved. manage_renameObject calls _notifyOfCopyTo so that the object being renamed doesn't lose its references. But manage_renameObject calls _delObject which calls manage_beforeDelete on all the children of the object being renamed which deletes all references for children of the object being renamed. Here is a patch that does recursive calls for _notifyOfCopyTo to address that problem. """ # XXX this doesn't appear to be necessary anymore, if it is # it needs to be used in BaseBTreeFolder as well, it currently # is not. BaseObject._notifyOfCopyTo(self, container, op=op) # keep reference info internally when op == 1 (move) # because in those cases we need to keep refs if op == 1: self._v_cp_refs = 1 for child in self.contentValues(): if IReferenceable.providedBy(child): child._notifyOfCopyTo(self, op)
def update_links(event): obj = event.object if is_outdated(obj) or not is_publically_visible(obj): return temporary = hasattr(obj, 'meta_type') and \ obj.meta_type == TempFolder.meta_type if temporary: # Objects that are temporary (read: portal_factory) and do not have a # (stable) URL (yet) do not need to be crawled: relative links will be # off quickly and we can't really use the UID anyway. return try: link_checker = getToolByName(obj, 'portal_linkchecker').aq_inner except AttributeError: return if not link_checker.active: return retriever = IRetriever(obj, None) if retriever is not None: sm = getSecurityManager() if not sm.checkPermission(ModifyPortalContent, obj): return if (not IReferenceable.providedBy(obj)): return async = getUtility(IAsyncService) tpath = '/'.join(obj.getPhysicalPath()) job = async .queueJob(retrieve_async, obj, tpath, online=True) callback = job.addCallbacks(failure=job_failure_callback) callback # for pep
def __iter__(self): for item in self.previous: pathkey = self.pathkey(*item.keys())[0] uidkey = self.uidkey(*item.keys())[0] if not pathkey or not uidkey: # not enough info yield item continue path = item[pathkey] uid = item[uidkey] obj = traverse(self.context, str(path).lstrip('/'), None) if obj is None: # path doesn't exist yield item continue if IReferenceable.providedBy(obj): oldUID = obj.UID() if oldUID != uid: if not oldUID: setattr(obj, UUID_ATTR, uid) else: obj._setUID(uid) if IAttributeUUID.providedBy(obj): IMutableUUID(obj).set(uid) yield item
def update_links(event): obj = event.object if is_outdated(obj) or not is_publically_visible(obj): return temporary = hasattr(obj, 'meta_type') and \ obj.meta_type == TempFolder.meta_type if temporary: # Objects that are temporary (read: portal_factory) and do not have a # (stable) URL (yet) do not need to be crawled: relative links will be # off quickly and we can't really use the UID anyway. return try: link_checker = getToolByName(obj, 'portal_linkchecker').aq_inner except AttributeError: return if not link_checker.active: return retriever = IRetriever(obj, None) if retriever is not None: sm = getSecurityManager() if not sm.checkPermission(ModifyPortalContent, obj): return if (not IReferenceable.providedBy(obj)): return async = getUtility(IAsyncService) tpath = '/'.join(obj.getPhysicalPath()) job = async.queueJob(retrieve_async, obj, tpath, online=True) callback = job.addCallbacks(failure=job_failure_callback) callback # for pep
def _notifyOfCopyTo(self, container, op=0): """In the case of a move (op=1) we need to make sure references are mainained for all referencable objects within the one being moved. manage_renameObject calls _notifyOfCopyTo so that the object being renamed doesn't lose its references. But manage_renameObject calls _delObject which calls manage_beforeDelete on all the children of the object being renamed which deletes all references for children of the object being renamed. Here is a patch that does recursive calls for _notifyOfCopyTo to address that problem. """ # XXX this doesn't appear to be necessary anymore, if it is # it needs to be used in BaseBTreeFolder as well, it currently # is not. BaseObject._notifyOfCopyTo(self, container, op=op) # keep reference info internally when op == 1 (move) # because in those cases we need to keep refs if op==1: self._v_cp_refs = 1 for child in self.contentValues(): if IReferenceable.providedBy(child): child._notifyOfCopyTo(self, op)
def migrate_at_uuid(self): """Migrate AT universal uid """ if not IReferenceable.providedBy(self.old): return # old object doesn't support AT uuids uid = self.old.UID() self.old._uncatalogUID(self.parent) self.new._setUID(uid)
def beforeChange_at_uuid(self): """Load AT universal uid.""" self._checkLoadAttr('UID') if IReferenceable.providedBy(self.old): self.UID = self.old.UID() self.old._uncatalogUID(self.parent) else: self.UID = None
def getuid(self): if HAS_PLONE_UUID: uid = IUUID(self.context, None) if uid is not None: return uid if HAS_AT: if IReferenceable.providedBy(self.context): return self.context.UID() return None
def getSourceId(self, name, filename, instance, fresh=False): sid = '' if IReferenceable.providedBy(instance): sid = sid + instance.UID() sid = "%s_%s" % (sid, self.make_prefix()) sid = "%s_%s" % (sid, name) fname = self.getNormalizedName(filename) if fname: sid = '%s_%s' % (sid, fname) return sid
def prepareIterateObjectTabs(self, *args, **kwargs): tabs = self.prepareObjectTabs(*args, **kwargs) if IReferenceable.providedBy(self.context): iterate_control = plone.app.iterate.browser.control.Control(self.context, self.request) if tabs and iterate_control.checkout_allowed(): for tab in [e for e in tabs if e['id'] == 'edit']: tab['url'] = self.context.absolute_url() + '/@@content-checkout' return tabs
def test_upgrade(self): doc3 = self.portal['doc3'] doc1 = self.portal['doc1'] self.assertTrue(IReferenceable.providedBy(doc3)) doc3.setText('<a href="doc1">doc1</a>', mimetype='text/html') doc3.addReference(doc1, relationship=referencedRelationship) self.assertFalse(hasIncomingLinks(doc1)) self.assertFalse(hasIncomingLinks(doc3)) migrate_linkintegrity_relations(self.portal) self.assertTrue(hasIncomingLinks(doc1)) self.assertFalse(hasIncomingLinks(doc3))
def migrate_at_uuid(self): """Migrate AT universal uid """ if not IReferenceable.providedBy(self.old): return # old object doesn't support AT uuids uid = self.old.UID() self.old._uncatalogUID(self.parent) if queryAdapter(self.new, IMutableUUID): IMutableUUID(self.new).set(str(uid)) else: self.new._setUID(uid)
def migrate_at_uuid(self): """Migrate AT universal uid """ if not IReferenceable.providedBy(self.old): return # old object doesn't support AT uuids uid = self.old.UID() self.old._uncatalogUID(self.parent) if UUID_ATTR: # Prevent object deletion triggering UID related magic setattr(self.old, UUID_ATTR, None) if queryAdapter(self.new, IMutableUUID): IMutableUUID(self.new).set(str(uid)) else: self.new._setUID(uid)
def __call__(self, skipRedirect=False, **args): context = self.context request = context.REQUEST if IReferenceable.providedBy(context): plone_utils = getToolByName(context, 'plone_utils') uid = request.get('uid', '') remoteUrl = request.get('remoteUrl', '') if not remoteUrl: message = u'No URL was given, nothing has been added.' else: util = getUtility(ISearchUrlSettings) urlTuples = util.urls existing = list() existing_idx = list() pc = context.portal_catalog for item in urlTuples: if item.url == remoteUrl: res = pc(UID=item.provider) title = len(res) and res[0].Title or 'None' url = len(res) and res[0].getURL() or '' existing.append("existing:list=%s|%s" % (title, url)) existing_idx.append(urlTuples.index(item)) if len(existing): if not request.get('override', False): message = u"The URL is already registered" path = context.absolute_url() + "/%s?%s" % ( request.get('template_id', ''), '&'.join(existing) ) plone_utils.addPortalMessage(message) skipRedirect = True self.request.RESPONSE.redirect(path) return else: existing_idx.reverse() for idx in existing_idx: del urlTuples[idx] urlTuples.append(SearchUrlTuple(remoteUrl, uid)) util.urls = urlTuples message = (u'"%s" has been added to search urls' % unicode(context.title_or_id(), 'utf-8')) else: message = (u'"%s" could not be added to the search, because ist' 'is not referenceable' % unicode(context.title_or_id(), 'utf-8')) if not skipRedirect: path = context.absolute_url() plone_utils.addPortalMessage(message) self.request.RESPONSE.redirect(path)
def apply_referenceable_behavior(context): # See plone.app.referenceablebehavior.uidcatalog. uid_catalog = getToolByName(context, 'uid_catalog') portal_catalog = getToolByName(context, 'portal_catalog') brains = portal_catalog( meta_type=['Dexterity Item', 'Dexterity Container']) for brain in brains: obj = brain.getObject() if IReferenceable.providedBy(obj): path = '/'.join(obj.getPhysicalPath()) logger.info( """Applying referenceable behavior for object at path %s""", path) uid_catalog.catalog_object(obj, path)
def links(self): if not IReferenceable.providedBy(self.context): return [] value = [] tasks = self.context.getBRefs('task_issues') tasks = sorted(tasks, lambda a, b: cmp(a.ModificationDate(), b.ModificationDate())) for task in tasks: value.append( dict(iterationid=task.getPhysicalPath()[-3], title=abbreviate(task.Title() or task.getId(), width=25), url=task.absolute_url(), state=self.workflow.getInfoFor(task, 'review_state'))) return value
def links(self): if not IReferenceable.providedBy(self.context): return [] value = [] tasks = self.context.getBRefs('task_issues') tasks = sorted( tasks, lambda a, b: cmp(a.ModificationDate(), b.ModificationDate())) for task in tasks: value.append( dict(iterationid=task.getPhysicalPath()[-3], title=abbreviate(task.Title() or task.getId(), width=25), url=task.absolute_url(), state=self.workflow.getInfoFor(task, 'review_state'))) return value
def manageLink(self, obj, normalled): # need IObject iface for catalog brains if hasattr(obj, 'getObject'): # brain, other sort of pseudo object obj = obj.getObject() if not IReferenceable.providedBy(obj): # backlink not possible return mark(obj, IWickedTarget) self.refcat.addReference(obj, self.context, relationship=self.relation, referenceClass=self.refKlass) objuid = IUID(obj) path = '/'.join(obj.getPhysicalPath()) data = dict(path=path, icon=obj.getIcon(), uid=objuid) self.cm.set((intern(str(normalled)), objuid), [data])
def getObjectsFromLinks(base, links): """ determine actual objects refered to by given links """ objects = set() url = base.absolute_url() scheme, host, path, query, frag = urlsplit(url) for link in links: try: s, h, path, q, f = urlsplit(link) except ValueError: continue if (not s and not h) or (s == scheme and h == host): # relative or local url obj, extra = findObject(base, path) if obj: if IOFSImage.providedBy(obj): obj = aq_parent(obj) # use atimage object for scaled images if not IReferenceable.providedBy(obj): try: obj = IReferenceable(obj) except: continue objects.add(obj) return objects
def checkout_allowed(self): """Check if a checkout is allowed. """ context = aq_inner(self.context) if not interfaces.IIterateAware.providedBy(context): return False if not IReferenceable.providedBy(context): return False archiver = interfaces.IObjectArchiver(context) if not archiver.isVersionable(): return False # check if there is an existing checkout if len(context.getBRefs(WorkingCopyRelation.relationship)) > 0: return False # check if its is a checkout if len(context.getRefs(WorkingCopyRelation.relationship)) > 0: return False return True
def getRatingVariance(obj, portal, **kw): if not IReferenceable.providedBy(obj): return None rt = getToolByName(obj, 'portal_ratings') return rt.getRatingSumSquared(obj.UID())
def getWorkingCopy(self): if IReferenceable.providedBy(self.context): refs = self.context.getBRefs(WorkingCopyRelation.relationship) if refs: return refs[0]
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"
def getCyninRating(obj, portal, **kw): if not IReferenceable.providedBy(obj): return None rt = getToolByName(obj, 'portal_ratings') return rt.getCyninRating(obj.UID())
def get_original(self, context): if IReferenceable.providedBy(context): refs = context.getRefs(WorkingCopyRelation.relationship) if refs: return refs[0]
def getHitCount(obj, portal, **kw): if not IReferenceable.providedBy(obj): return None rt = getToolByName(obj, 'portal_ratings') return rt.getHitCount(obj.UID())
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)