def setLastLog(self,log): """Save an edit log message, if provided.""" if log and string.strip(log): log = string.strip(log) get_transaction().note('"%s"' % self.toencoded(log)) self.last_log = log else: self.last_log = ''
def revertEditsEverywhereBy(self, username, REQUEST=None, batch=0): """ Revert all the most recent edits by username throughout the wiki. """ batch = int(batch) n = 0 for p in self.pageObjects(): if p.last_editor == username: n += 1 try: p.revertEditsBy(username,REQUEST=REQUEST) except (IndexError, AttributeError): # IndexError - we don't have a version that old # AttributeError - new object, no history yet, # due to creation of page in unit tests # - doesn't really happen in real use I guess BLATHER('failed to revert edits by %s at %s: %s' \ % (username,p.id(),formattedTraceback())) if batch and n % batch == 0: BLATHER('committing after %d reverts' % n) get_transaction().commit()
def expungeEditsEverywhereBy(self, username, REQUEST=None, batch=0): # -> none # depends on: all pages, revisions ; modifies: all pages, revisions """Expunge all the most recent edits by username throughout the wiki. This is a powerful spam repair tool for managers. It removes all recent consecutive edits by username from each page in the wiki. The corresponding revisions will disappear from the page history. See #1157. Should this use the catalog ? Currently uses a more expensive and failsafe brute force ZODB search. """ batch = int(batch) for n,p in izip(count(1), [p for p in self.pageObjects() if p.last_editor==username]): try: p.expungeEditsBy(username,REQUEST=REQUEST) except IndexError: BLATHER('failed to expunge edits by %s at %s: %s' \ % (username,p.id(),formattedTraceback())) if batch and (n % batch)==0: BLATHER('committing after %d expunges' % n) get_transaction().commit()
def upgradeAll(self, render=1, batch=0, REQUEST=None): # -> none # depends on: wiki # modifies: wiki (folder, pages, dtml methods, catalog, outline, revisions..) """ Update, upgrade, pre-render and re-index all pages and data structures. Normally individual pages are upgraded and pre-rendered on demand, when viewed. An administrator may want to do this for all pages ahead of time, particularly after a zwiki upgrade, to ensure all pages have the latest properties and have been rendered by the latest code, minimizing delay and possible problems later on. Also installs a wiki catalog if not present, re-indexes each page, validates page parents, and rebuilds the wiki outline cache. Also installs the index_html and standard_error_message dtml methods. XXX split ? You can set render=0 to skip the page pre-rendering part, completing much faster on large wikis. The optional batch argument forces a commit every N pages. This may be useful to get a complete run in large/busy wikis, which can be difficult due to conflict errors or memory usage. Requires 'Manage properties' permission on the folder. """ if not self.checkPermission(Permissions.manage_properties, self.folder()): raise Unauthorized, ( _('You are not authorized to upgrade all pages.') + \ _('(folder -> Manage properties)')) batch = int(batch) if render: BLATHER('upgrading/reindexing/pre-rendering all pages:') else: BLATHER('upgrading/reindexing all pages:') starttime = clock() n, total = 0, self.pageCount() self.setupCatalog(reindex=0) self.rebuildWikiOutline() for p in self.pageObjects(): # poor caching (not a problem here) n += 1 try: p.upgrade(REQUEST) p.upgradeId(REQUEST) p.fixEncoding() if render: p.preRender(clear_cache=1) msg = 'upgraded and pre-rendered page' else: msg = 'upgraded page' # make sure every page is cataloged - slow but thorough p.index_object(log=0) BLATHER('%s %d/%d %s' % (msg, n, total, p.id())) except: BLATHER('failed to upgrade page %d/%d %s: %s' \ % (n,total,p.id(),formattedTraceback())) if batch and n % batch == 0: BLATHER('committing') get_transaction().commit() self.setupDtmlMethods() endtime = clock() BLATHER('upgrade complete, %d pages processed in %fs, %.1f pages/s' \ %(n, endtime-starttime, n/(endtime-starttime)))
def upgradeAll(self,render=1,batch=0,REQUEST=None): """ Update, upgrade, pre-render and re-index all pages and data structures. Normally individual pages are upgraded and pre-rendered on demand, when viewed. An administrator may want to do this for all pages ahead of time, particularly after a zwiki upgrade, to ensure all pages have the latest properties and have been rendered by the latest code, minimizing delay and possible problems later on. Also installs a wiki catalog if not present, re-indexes each page, validates page parents, and rebuilds the wiki outline cache. Also installs the index_html and standard_error_message dtml methods. XXX split ? You can set render=0 to skip the page pre-rendering part, completing much faster on large wikis. The optional batch argument forces a commit every N pages. This may be useful to get a complete run in large/busy wikis, which can be difficult due to conflict errors or memory usage. Requires 'Manage properties' permission on the folder. """ if not self.checkPermission(Permissions.manage_properties, self.folder()): raise 'Unauthorized', ( _('You are not authorized to upgrade all pages.') + \ _('(folder -> Manage properties)')) batch = int(batch) if render: BLATHER('upgrading/reindexing/pre-rendering all pages:') else: BLATHER('upgrading/reindexing all pages:') starttime = clock() n, total = 0, self.pageCount() self.setupCatalog(reindex=0) for p in self.pageObjects(): # poor caching (not a problem here) n += 1 try: p.upgrade(REQUEST) p.upgradeId(REQUEST) p.fixPageEncoding() if render: p.preRender(clear_cache=1) msg = 'upgraded and pre-rendered page' else: msg = 'upgraded page' # make sure every page is cataloged - slow but thorough p.index_object(log=0) BLATHER('%s %d/%d %s'%(msg,n,total,p.id())) except: BLATHER('failed to upgrade page %d/%d %s: %s' \ % (n,total,p.id(),formattedTraceback())) if batch and n % batch == 0: BLATHER('committing') get_transaction().commit() self.updateWikiOutline() self.setupDtmlMethods() endtime = clock() BLATHER('upgrade complete, %d pages processed in %fs, %f pages/s' \ %(n, endtime-starttime, n/(endtime-starttime)))
def create(self,page=None,text='',type=None,title='',REQUEST=None,log='', sendmail=1, parents=None, subtopics=None, pagename=None): # -> string; ... """Create a new wiki page, and optionally do extra stuff. Normally called via edit(). The page name arguments are confusing. Here's the situation as I understand it: XXX cleanup - page: the "original" name of the page we are to create. - pagename: an alternate spelling of the above, to ease page management form implementation. Pass one or the other. - title: optional "new" name to rename to after creation. This allows us to handle the zwiki and CMF/plone edit forms smoothly, supporting rename during creation. Page names are assumed to come url-quoted. For the new page id, we use a url-safe canonical id derived from the name. (This name and id are assumed to be available, or Zwiki would not be calling create.) Other arguments: - text: initial content for the new page - type: id of the page type to use (rst, html...) - REQUEST: standard zope argument, pass this to preserve any user authentication. Also, may include file upload data in which case the file is uploaded to the wiki. - log: optional note for edit history and mail-out subject - sendmail: sends mail-out to wiki subscribers, unless disabled - parents: the names of the new page's parent(s), if any - subtopics: if non-None, sets the subtopics display property Other features: - checks the edit_needs_username property as well as permissions - redirects to the new page, or to the denied view - returns the new page's name, or None - if old revisions with this name exist, takes the next revision number """ if not self.checkPermission(Permissions.Add, self.folder()): raise Unauthorized, ( _('You are not authorized to add pages in this wiki.')) if not self.checkSufficientId(REQUEST): if REQUEST: REQUEST.RESPONSE.redirect(self.pageUrl()+'/denied') return None # here goes.. sequence is important name = self.tounicode(self.urlunquote(page or pagename or REQUEST.form.get('title'))) title = title and self.tounicode(self.urlunquote(title)) text = text and self.tounicode(text) log = log and self.tounicode(log) id = self.canonicalIdFrom(name) if not name: return self.genericerror(shorttitle=_('No Page Name'), messagetitle=_('Please enter a Page Name'), messages=[_('You did not enter a name for your new page. Please go Back and enter a name in the form.'), _('Your browser should still have your edits.')]) p = self.__class__(__name__=id) p.title = name # because manage_afterAdd adds this to the wiki outline p = self.folder()[self.folder()._setObject(id,p)] # place in folder p.checkForSpam(text) # now we're acquiring wiki options, check for spam p.ensureMyRevisionNumberIsLatest() p.setCreator(REQUEST) p.setLastEditor(REQUEST) p.setLastLog(log) p._setOwnership(REQUEST) # now really update the wiki outline # XXX should reuse reparent code to do parents validation etc. p.parents = (parents==None) and [self.pageName()] or parents self.wikiOutline().add(p.pageName(), p.parents) p.setPageType(type or self.defaultPageType()) p.setText(text,REQUEST) p.handleFileUpload(REQUEST) p.handleSubtopicsProperty(subtopics,REQUEST) if p.autoSubscriptionEnabled(): p.subscribeThisUser(REQUEST) # allow users to alter the page name in the creation form. We do # a full rename after all the above to make sure everything gets # handled properly, such as updating backlinks. We must first # commit though, to get p.cb_isMoveable(). if title and title != p.pageName(): get_transaction().note('rename during creation') get_transaction().commit() p.handleRename(title,0,1,REQUEST,log) else: # reindex now all attributes are set. handleRename does it too. p.index_object() if sendmail: p.sendMailToSubscribers( p.read(), REQUEST=REQUEST, subjectSuffix='', subject=log, message_id=self.messageIdFromTime(p.creationTime())) if REQUEST: try: u = (REQUEST.get('redirectURL',None) or REQUEST['URL2']+'/'+ self.urlquote(p.id())) REQUEST.RESPONSE.redirect(u) except KeyError: pass return name