From klm at zope.com Fri Dec 14 15:44:38 2001 From: klm at zope.com (Ken Manheimer) Date: Sun Aug 10 17:02:05 2008 Subject: [zopeorg-checkins] CVS: Products/ZWiki - SubscriberList.py:1.7 Message-ID: <200112142044.fBEKic514131@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ZWiki In directory cvs.zope.org:/tmp/cvs-serv14123 Modified Files: SubscriberList.py Log Message: Use a separate catalog for indexing subscriber information. Using the main catalog is not quite proper, the subscriber info is more about the subscriber than the content. .subscribers_catalog: New string property which names the catalog. .reindex_subscribers(): Reindex against the subscribers catalog when subscriptions and unsubscriptions happen. === Products/ZWiki/SubscriberList.py 1.6 => 1.7 === -import ZWikiPage ########################################################################### # CLASS SubscriberList @@ -31,9 +30,14 @@ # _subscribers: {userid: [option, ...], ...} # Empty options list mean plain subscription. _subscribers = {} + subscribers_catalog = 'SubscribersIndex' # NB this will hide the folder's subscribers property + _properties=( + {'id':'subscribers_catalog', 'type': 'string', 'mode': 'w'}, + ) + def _resetSubscribers(self, container=0): """ Clear this page's subscriber list. @@ -142,13 +146,13 @@ subp = folder[i] subp.subscribe(container=0, _propagating=1, sticky=1) - self.reindex_me() + self.reindex_subscribers() # redirect browser if needed if REQUEST: REQUEST.RESPONSE.redirect(REQUEST['URL1'] + '/subscribeform') - def unsubscribe(self, userid=None, container=0, propagating=0, + def unsubscribe(self, userid=None, container=0, _propagating=0, REQUEST=None): """ Remove a userid from this page's mail subscriber list. @@ -165,18 +169,27 @@ obj._subscribers = obj._subscribers if not container and REQUEST.get('unsubscribe_offspring'): - if not propagating: + if not _propagating: folder = self.aq_parent for i in self.my_offspring(): subp = folder[i] subp.unsubscribe(REQUEST=REQUEST, container=0, - propagating=1) + _propagating=1) - self.reindex_me() + self.reindex_subscribers() # redirect browser if needed if REQUEST: REQUEST.RESPONSE.redirect(REQUEST['URL1'] + '/subscribeform') + + def reindex_subscribers(self): + """Apply the subscribers index if we can acquare a catalog for it.""" + if self.dont_catalog or not hasattr(self, 'REQUEST'): + pass + elif hasattr(self, self.subscribers_catalog): + catalog = getattr(self, self.subscribers_catalog) + catalog.uncatalog_object(self) + catalog.catalog_object(self) ###################################################################### # METHOD CATEGORY: containing folder subscription From klm at zope.com Fri Dec 14 15:48:03 2001 From: klm at zope.com (Ken Manheimer) Date: Sun Aug 10 17:02:05 2008 Subject: [zopeorg-checkins] CVS: Products/ZWiki - SubscriberList.py:1.8 Message-ID: <200112142048.fBEKm3n14481@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ZWiki In directory cvs.zope.org:/tmp/cvs-serv14417 Modified Files: SubscriberList.py Log Message: Provide for unidexing only (on manage_beforeDelete in ZWikiPage). === Products/ZWiki/SubscriberList.py 1.7 => 1.8 === REQUEST.RESPONSE.redirect(REQUEST['URL1'] + '/subscribeform') - def reindex_subscribers(self): + def reindex_subscribers(self, unindex_only=0): """Apply the subscribers index if we can acquare a catalog for it.""" if self.dont_catalog or not hasattr(self, 'REQUEST'): pass elif hasattr(self, self.subscribers_catalog): catalog = getattr(self, self.subscribers_catalog) catalog.uncatalog_object(self) - catalog.catalog_object(self) + if not unindex_only: + catalog.catalog_object(self) ###################################################################### # METHOD CATEGORY: containing folder subscription From klm at zope.com Fri Dec 14 15:58:40 2001 From: klm at zope.com (Ken Manheimer) Date: Sun Aug 10 17:02:05 2008 Subject: [zopeorg-checkins] CVS: Products/ZWiki - ZWikiPage.py:1.67 Message-ID: <200112142058.fBEKwek20233@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ZWiki In directory cvs.zope.org:/tmp/cvs-serv20225 Modified Files: ZWikiPage.py Log Message: Add update of subscribers index upon page "lifecycle events" (add, delete, clone). Include the SubscriberList properties among the published ones. === Products/ZWiki/ZWikiPage.py 1.66 => 1.67 === {'id':'last_editor', 'type': 'string', 'mode': 'w'}, {'id':'last_log', 'type': 'string', 'mode': 'w'}, - ) + ) + SubscriberList._properties # define permissions __ac_permissions__=( @@ -1631,6 +1631,7 @@ pass # In artificial situations, eg migr.py. elif hasattr(self, 'default_catalog') and self.default_catalog: self.index_object() + self.reindex_subscribers() def manage_beforeDelete(self, item, container): "Unindex content object before it is deleted." @@ -1641,6 +1642,7 @@ self.unindex_object() except: pass + self.reindex_subscribers(unindex_only=1) def manage_afterClone(self, item): "Used when copying and pasting" @@ -1648,6 +1650,7 @@ pass # In artificial situations, eg migr.py. elif hasattr(self, 'default_catalog') and self.default_catalog: self.index_object() + self.reindex_subscribers() def prep_citation(self, rfind=string.rfind, strip=string.strip): """Quote text for use in literal citations. @@ -3117,7 +3120,7 @@ - + Click here to search for all your page subscriptions. From klm at zope.com Sat Dec 15 19:20:42 2001 From: klm at zope.com (Ken Manheimer) Date: Sun Aug 10 17:02:05 2008 Subject: [zopeorg-checkins] CVS: Products/ZWiki/Extensions - convert.py:1.4 Message-ID: <200112160020.fBG0Kg027484@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ZWiki/Extensions In directory cvs.zope.org:/tmp/cvs-serv27476 Modified Files: convert.py Log Message: Guard against corrupt folders, so processing completes. add_subscribe_links(): Commit every 100 changed footers. (I don't think this is necessary, but accidentally ran the version with the real fix plus this in it, so i'm checking it in.) hierarchy_folders(): Catch exceptions and continue processing. === Products/ZWiki/Extensions/convert.py 1.3 => 1.4 === did = did + 1 footer.raw = new + if not did % 100: + get_transaction().commit() else: missed = missed + 1 return ("Did %s footers, missed %s, skipped %s already done." @@ -43,13 +45,22 @@ addline = (' / ' 'Subscriptions') -def hierarchy_folders(folder=None): +bads = [] +def hierarchy_folders(folder): """Return list all folders contained in the current one, inclusive.""" + global bads got = [] - if folder is None: - folder = self got.append(folder) - for subfolder in folder.objectValues(spec=FOLDER_TYPES): + folderpath = string.join(folder.getPhysicalPath(), '/') + for id in folder.objectIds(spec=FOLDER_TYPES): + subfolder = folder[id] got.append(subfolder) - got.extend(hierarchy_folders(subfolder)) + try: + got.extend(hierarchy_folders(subfolder)) + except: + import sys + bad = folderpath + '/' + id + bads.append(bad) + print ("Skipping failure #%s in folder '%s' (%s)" + % (len(bads), bad, sys.exc_info()[1])) return got From klm at zope.com Sat Dec 15 19:23:51 2001 From: klm at zope.com (Ken Manheimer) Date: Sun Aug 10 17:02:05 2008 Subject: [zopeorg-checkins] CVS: Products/ZWiki/Extensions - convert.py:1.5 Message-ID: <200112160023.fBG0Npp28541@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ZWiki/Extensions In directory cvs.zope.org:/tmp/cvs-serv28533 Modified Files: convert.py Log Message: Report the bad folders... === Products/ZWiki/Extensions/convert.py 1.4 => 1.5 === else: missed = missed + 1 - return ("Did %s footers, missed %s, skipped %s already done." - % (did, missed, already_done)) + return ("Did %s footers, skipped %s already changed, " + "missed %s, hit %s bad folders\n%s" + % (did, already_done, missed, len(bads), string.join(bads, "\n"))) histline = ' / History' addline = (' / ' From klm at zope.com Sat Dec 15 19:42:52 2001 From: klm at zope.com (Ken Manheimer) Date: Sun Aug 10 17:02:05 2008 Subject: [zopeorg-checkins] CVS: Products/ZWiki/Extensions - convert.py:1.6 Message-ID: <200112160042.fBG0gq532527@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ZWiki/Extensions In directory cvs.zope.org:/tmp/cvs-serv32519 Modified Files: convert.py Log Message: Dang - subscription mechanism is slightly whacky, going to remove the links until i fix it. For that purpose: remove_subscribe_links(): Remove the subscriptions link line. === Products/ZWiki/Extensions/convert.py 1.5 => 1.6 === % (did, already_done, missed, len(bads), string.join(bads, "\n"))) + +def remove_subscribe_links(self): + """Edit standard_wiki_footers to remove the "Subscribe" link. + + We look recursively through all folders below the one containing the + method.""" + did = missed = undone = 0 + for f in hierarchy_folders(folder=self): + if hasattr(f, 'standard_wiki_footer'): + footer = f.standard_wiki_footer + raw = footer.raw + if string.find(raw, addline + "\n") != -1: + new = string.replace(raw, addline + "\n", "") + if new != raw: + did = did + 1 + footer.raw = new + if not did % 100: + get_transaction().commit() + else: + missed = missed + 1 + else: + undone = undone + 1 + return ("Did %s footers, skipped %s not necessary, " + "missed %s, hit %s bad folders\n%s" + % (did, undone, missed, len(bads), string.join(bads, "\n"))) + histline = ' / History' addline = (' / ' 'Subscriptions') From klm at zope.com Mon Dec 17 19:29:13 2001 From: klm at zope.com (Ken Manheimer) Date: Sun Aug 10 17:02:05 2008 Subject: [zopeorg-checkins] CVS: Products/ZWiki - ZWikiPage.py:1.69 Message-ID: <200112180029.fBI0TDf27318@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ZWiki In directory cvs.zope.org:/tmp/cvs-serv27310 Modified Files: ZWikiPage.py Log Message: Changed what's used as the notification 'from' address: If the wiki has (directly or by inheritance) a non-empty 'email_from_address' attribute, use that, otherwise use the address of the person making the change. (Using 'email_from_address' because that's what the CMF uses for this purpose.) .notificationFromAddr(): implements new policy. .sendMailTo(): Apply new policy. Also, tweaked the message template, including moving the text to a global variable, refining the layout, and including some RFC 2369 maillist header fields. === Products/ZWiki/ZWikiPage.py 1.68 => 1.69 === #wikiname2 = r'[A-Z]'+IU+'[A-Z'+IU+']+[a-z'+IL+'][A-Za-z'+IA+']*' - +NOTIFICATION_TEMPLATE = \ +"""From: "Wikis on %(wiki_host)s" <%(from_email)s> +Sender: %(sender_email)s +To: Wiki notification recipients <> +Subject: Wiki updates - %(qualifier)s: %(id)s +X-Wiki-URL: %(url)s +List-Unsubscribe: %(subscribe_url)s +List-Subscribe: %(subscribe_url)s + +Wiki page %(qualifier)s (%(num_recips)s recipient%(recips_plural)s): + %(url)s + +%(delim)s +%(text)s +%(delim)s +To change your page subscription, visit: + %(subscribe_url)s +""" class ZWikiPage(DTMLDocument, CatalogAware, ZWikiDiffMixin, SubscriberList): """A ZWikiPage is a DTML Document which knows how to render itself in @@ -1082,7 +1099,7 @@ return t - def _process_comment(self, comment, text, ack_requested, REQUEST=None, + def _process_comment(self, comment, text, ack_requested=0, REQUEST=None, preexp=re.compile('
'), strip=string.strip):
         """Return formatted comment, escaping cited text.
 
@@ -1350,6 +1367,22 @@
 
     def editTimestamp(self): return str(self._p_mtime)
 
+    def notificationFromAddr(self):
+        """Return the 'from' address for a notification message.
+
+        If the wiki has (directly or by inheritance) a non-empty
+        'email_from_address' attribute, use that, otherwise use the address of
+        the person making the change."""
+        got = getattr(self, 'email_from_address', None)
+        if not got:
+            userobj = getSecurityManager().getUser()
+            userid = str(userobj)
+            if ((userobj is not None)
+                and (userid != str(self.acl_users._nobody))
+                and hasattr(userobj, 'email')):
+                got = userobj.email
+        return got
+
     def sendMailToSubscribers(self, text, REQUEST,
                               qualifier='edited'):
         """
@@ -1369,6 +1402,7 @@
 
         We return None if successful, or else a string describing the problem.
         """
+
         # ugLy temp hack
         # strip out message heading typically prepended on *Discussion pages
         mailouttext = re.sub(r'(?s)(
)?(.*?)
\n',r'',text) @@ -1387,47 +1421,37 @@ addrs_list.append(e) if not addrs_list: return "No update notice sent - no email addrs resolved" - addrs = string.join(addrs_list, ', ') + recipients = string.join(addrs_list, ', ') + num_recips = len(addrs_list) + recips_plural = ((num_recips != 1) and "s") or "" wiki_host = REQUEST.BASE0 if wiki_host[:7] == 'http://': wiki_host = wiki_host[7:] - sender_email = "webmaster@" + wiki_host + sender_email = "" + from_email = (self.notificationFromAddr() + or sender_email) + subscribe_url = self.absolute_url() + "/subscribeform" + userobj = getSecurityManager().getUser() userid = str(userobj) if (userobj is None) or (userid == str(self.acl_users._nobody)): userid = 'anonymous' - elif hasattr(userobj, 'email'): - sender_email = userobj.email - mhost=self.MailHost + try: - # send message - make this configurable - # the \ is required - mhost.send("""\ -From: "Wikis on %s for" <%s> -To: %s -Subject: Wiki updates - %s: %s - -Wiki page change notification - %s: - %s - -%s -%s -%s -To change your page subscription, visit: - %s/subscribeform -""" % (wiki_host, - sender_email, - addrs, - qualifier, - self.id(), - qualifier, - self.absolute_url(), - SECTION_DELIM, - mailouttext, - SECTION_DELIM, - self.absolute_url(), - )) + msg = NOTIFICATION_TEMPLATE % {'wiki_host': wiki_host, + 'from_email': from_email, + 'sender_email': sender_email, + 'qualifier': qualifier, + 'num_recips': len(addrs_list), + 'recips_plural': recips_plural, + 'id': self.id(), + 'url': self.absolute_url(), + 'subscribe_url': subscribe_url, + 'delim': SECTION_DELIM, + 'text': mailouttext, + } + self.MailHost.send(msg, mto=recipients) return None except: import sys From klm at zope.com Tue Dec 18 11:46:22 2001 From: klm at zope.com (Ken Manheimer) Date: Sun Aug 10 17:02:05 2008 Subject: [zopeorg-checkins] CVS: Products/ZWiki - ZWikiPage.py:1.70 Message-ID: <200112181646.fBIGkM924358@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ZWiki In directory cvs.zope.org:/tmp/cvs-serv24350 Modified Files: ZWikiPage.py Log Message: Now that the 'from' address will typically be a standard across a wiki, i've added the username that made the changes to the subject line and the body synopsis, and moved around some other info in the message. === Products/ZWiki/ZWikiPage.py 1.69 => 1.70 === NOTIFICATION_TEMPLATE = \ -"""From: "Wikis on %(wiki_host)s" <%(from_email)s> +"""From: "Wikis on %(wiki_host)s for %(who)s" <%(from_email)s> Sender: %(sender_email)s To: Wiki notification recipients <> -Subject: Wiki updates - %(qualifier)s: %(id)s +Subject: Wiki: %(who)s %(qualifier)s %(id)s X-Wiki-URL: %(url)s List-Unsubscribe: %(subscribe_url)s List-Subscribe: %(subscribe_url)s -Wiki page %(qualifier)s (%(num_recips)s recipient%(recips_plural)s): +Wiki page %(qualifier)s by %(who)s: %(url)s %(delim)s @@ -134,6 +134,7 @@ %(delim)s To change your page subscription, visit: %(subscribe_url)s +(You are %(recips_phrase)s.) """ class ZWikiPage(DTMLDocument, CatalogAware, ZWikiDiffMixin, SubscriberList): @@ -1423,7 +1424,11 @@ return "No update notice sent - no email addrs resolved" recipients = string.join(addrs_list, ', ') num_recips = len(addrs_list) - recips_plural = ((num_recips != 1) and "s") or "" + if num_recips == 1: + recips_phrase = "the only notification recipient" + else: + recips_phrase = "among %s notification recipients" % num_recips + wiki_host = REQUEST.BASE0 if wiki_host[:7] == 'http://': @@ -1437,19 +1442,22 @@ userid = str(userobj) if (userobj is None) or (userid == str(self.acl_users._nobody)): userid = 'anonymous' + who = '??' + else: + who = userid try: msg = NOTIFICATION_TEMPLATE % {'wiki_host': wiki_host, 'from_email': from_email, 'sender_email': sender_email, 'qualifier': qualifier, - 'num_recips': len(addrs_list), - 'recips_plural': recips_plural, + 'recips_phrase': recips_phrase, 'id': self.id(), 'url': self.absolute_url(), 'subscribe_url': subscribe_url, 'delim': SECTION_DELIM, 'text': mailouttext, + 'who': who, } self.MailHost.send(msg, mto=recipients) return None From klm at zope.com Wed Dec 19 18:06:21 2001 From: klm at zope.com (Ken Manheimer) Date: Sun Aug 10 17:02:05 2008 Subject: [zopeorg-checkins] CVS: Products/ZWiki - SubscriberList.py:1.9 Message-ID: <200112192306.fBJN6LT01757@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ZWiki In directory cvs.zope.org:/tmp/cvs-serv1749 Modified Files: SubscriberList.py Log Message: .reindex_subscribers(): First of all, uncatalog_object() takes a "uid", which is apparently the '/' delimited path to the object. Second, we don't need to uncatalog before recataloging, so we only uncatalog when that's all that's going to be done. === Products/ZWiki/SubscriberList.py 1.8 => 1.9 === +import string ########################################################################### # CLASS SubscriberList @@ -188,8 +189,10 @@ pass elif hasattr(self, self.subscribers_catalog): catalog = getattr(self, self.subscribers_catalog) - catalog.uncatalog_object(self) - if not unindex_only: + if unindex_only: + catalog.uncatalog_object(string.join(self.getPhysicalPath(), + '/')) + else: catalog.catalog_object(self) ######################################################################