Index: /qPloneGoogleSitemaps/tags/0.6+/Extensions/Install.py
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/Extensions/Install.py (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/Extensions/Install.py (revision 525)
@@ -0,0 +1,97 @@
+import string
+from cStringIO import StringIO
+from Products.CMFCore.utils import getToolByName
+from Products.CMFCore.DirectoryView import addDirectoryViews
+from Products.qPloneGoogleSitemaps import qPGS_globals
+
+try:
+ from Products.CMFCore.permissions import ManagePortal
+except ImportError:
+ from Products.CMFCore.CMFCorePermissions import ManagePortal
+
+from OFS.ObjectManager import BadRequestException
+
+configlets = ({'id':'qPloneGoogleSitemaps',
+ 'name':'Google Sitemaps',
+ 'action':'string:${portal_url}/prefs_gsm_overview',
+ 'condition':'',
+ 'category':'Products',
+ 'visible':1,
+ 'appId':'qPloneGoogleSitemaps',
+ 'permission':ManagePortal,
+ 'imageUrl':'qplonegooglesitemaps.gif'},)
+
+def setupSkin(self, out, skinFolder):
+ skinstool=getToolByName(self, 'portal_skins')
+
+ addDirectoryViews(skinstool, 'skins', qPGS_globals)
+
+ for skin in skinstool.getSkinSelections():
+ path = skinstool.getSkinPath(skin)
+ path = map( string.strip, string.split( path,',' ) )
+
+ if not skinFolder in path:
+ try:
+ path.insert( path.index( 'custom')+1, skinFolder )
+ except ValueError:
+ path.append(skinFolder)
+ path = string.join( path, ', ' )
+ skinstool.addSkinSelection( skin, path )
+ out.write(' %s layer sucessfully installed into skin %s.\n' % (skinFolder, skin))
+ else:
+ out.write(' %s layer was already installed into skin %s.\n' % (skinFolder, skin))
+
+def install(self):
+ """ Install qPloneGoogleSitemaps """
+ out = StringIO()
+ if not hasattr(self.portal_properties, 'googlesitemap_properties'):
+ self.portal_properties.addPropertySheet('googlesitemap_properties', 'Google SiteMap properties')
+
+ props = self.portal_properties.googlesitemap_properties
+ portalTypes = ('Plone Folder', 'ATFolder')
+ new_portalTypes = ['Document', ]
+ sitemap_properties = (
+ ('portalTypes', 'lines', new_portalTypes),
+ ('states', 'lines', ['published', ]),
+ ('blackout_list', 'lines',[]),
+ ('reg_exp', 'lines',[]),
+ ('urls', 'lines',[]),
+ ('verification_filename','string','')
+ )
+
+ types = self.portal_types.listContentTypes( by_metatype=1 )
+ for prop_id, prop_type, prop_value in sitemap_properties:
+ if not hasattr(props, prop_id):
+ props._setProperty(prop_id, prop_value, prop_type)
+
+ configTool = getToolByName(self, 'portal_controlpanel', None)
+ if configTool:
+ for conf in configlets:
+ configTool.registerConfiglet(**conf)
+ out.write('Added configlet %s\n' % conf['id'])
+
+ out.write('Call setupSkin... \n')
+ setupSkin(self, out, 'qPloneGoogleSitemaps')
+
+ return out.getvalue()
+
+def uninstall(self):
+ """ Uninstall qPloneGoogleSitemaps """
+ out = StringIO()
+
+ props = getToolByName(self,'portal_properties')
+ try:
+ props.manage_delObjects(['googlesitemap_properties',])
+ except BadRequestException: pass
+
+ configTool = getToolByName(self, 'portal_controlpanel', None)
+ if configTool:
+ for conf in configlets:
+ try:
+ configTool.unregisterConfiglet(conf['id'])
+ except BadRequestException,KeyError:
+ portal_icons = getToolByName(self,'portal_actionicons')
+ portal_icons.manage_removeActionIcon(conf['category'],conf['id'])
+ out.write('Removed configlet %s\n' % conf['id'])
+
+ return out.getvalue()
Index: /qPloneGoogleSitemaps/tags/0.6+/Extensions/__init__.py
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/Extensions/__init__.py (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/Extensions/__init__.py (revision 525)
@@ -0,0 +1,1 @@
+# this file intentionally left blank
Index: /qPloneGoogleSitemaps/tags/0.6+/Extensions/ping_googlesitemap.py
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/Extensions/ping_googlesitemap.py (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/Extensions/ping_googlesitemap.py (revision 525)
@@ -0,0 +1,7 @@
+from Products.qPloneGoogleSitemaps.utils import ping_google
+from Products.CMFCore.utils import getToolByName
+def ping_googlesitemap(state_change):
+ """ping sitemap to Google when document has published"""
+ plone_home = getToolByName(state_change.object, 'portal_url').getPortalObject().absolute_url()
+ ping_google(plone_home)
+ return 0
Index: /qPloneGoogleSitemaps/tags/0.6+/HISTORY.txt
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/HISTORY.txt (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/HISTORY.txt (revision 525)
@@ -0,0 +1,47 @@
+0.6 Plone-3.0 compatibility
+
+ * Added plone-3 compatibility.
+
+0.5 Added tests
+
+ * Fix up bug in sed command s
+
+0.4.10 Configlet split into tabs
+
+ * Added workflow transitions configuration
+
+0.4.9 Introduced different sort options
+
+ * Added blackout list
+
+ * Added opportunity to use sed command s
+
+0.4 Introduced sitemap ping to Google
+
+ * Added Google ping
+
+ * Added configuration page
+
+ * Added filter by content-types and states
+
+0.3 Introduced product configlet
+
+ * Added product configlet
+
+ * Added product usage docs on configlet
+
+0.2 Introduced XML format
+
+ * Moved to XML sitemaps format
+
+ * Added lastmod element to inform Google of object change date
+
+ * sitemap is comressed via HTTP gzip compression
+
+0.1 Initial version, proof of concept (i.e, Google working ;)
+
+ * plain text sitemaps format
+
+ * simple installer, no configuration
+
+ * no UI, just the working code ;)
Index: /qPloneGoogleSitemaps/tags/0.6+/README.txt
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/README.txt (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/README.txt (revision 525)
@@ -0,0 +1,32 @@
+Quintagroup Plone Google Sitemaps
+
+ The product allows Plone websites to get better visibility for
+ Google search engine by providing it with complete listing of
+ URLs to website content. See
+ "Google Sitemaps":https://www.google.com/webmasters/sitemaps
+ website for more information.
+
+ "Product Homepage":http://quintagroup.com/services/plone-development/products/google-sitemaps |
+ "Download":http://sourceforge.net/projects/quintagroup
+
+
+ (c) "Quintagroup":http://quintagroup.com/ , 2005.
+
+ support@quintagroup.com * quintessence of modern business
+
+Usage
+
+ 1. Install with Quick Installer.
+
+ 2. Go to https://www.google.com/webmasters/sitemaps and
+ add http://your.site/google-sitemaps.
+
+ 3. Should be working without any intervention.
+
+Authors
+
+ * Myroslav Opyr
+
+ * Nazar Ilchuk
+
+ * Mykola Kharechko
Index: /qPloneGoogleSitemaps/tags/0.6+/TODO.txt
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/TODO.txt (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/TODO.txt (revision 525)
@@ -0,0 +1,9 @@
+The items that are planned to implement within short timeframe
+
+* Provide changefreq and priority elements in url
+
+* pre-Compress the sitemaps
+
+* Make it possible to break sitemap into parts (with the use of siteindex)
+
+* implement several siteindex split policies: location, modification date, etc.
Index: /qPloneGoogleSitemaps/tags/0.6+/__init__.py
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/__init__.py (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/__init__.py (revision 525)
@@ -0,0 +1,10 @@
+import Globals
+
+from Products.CMFCore.DirectoryView import registerDirectory
+from AccessControl import allow_module
+
+registerDirectory('skins', globals())
+qPGS_globals = globals()
+
+allow_module('Products.qPloneGoogleSitemaps.utils.py')
+allow_module('Products.qPloneGoogleSitemaps.config.py')
Index: /qPloneGoogleSitemaps/tags/0.6+/config.py
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/config.py (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/config.py (revision 525)
@@ -0,0 +1,1 @@
+ping_googlesitemap = 'ping_googlesitemap'
Index: /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/google-sitemaps.pt
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/google-sitemaps.pt (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/google-sitemaps.pt (revision 525)
@@ -0,0 +1,21 @@
+
+
+
+ http://www.yoursite.com/
+ 2005-01-01
+
+
+ http://www.yoursite.com/
+
+
Index: /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_create_verify_file.cpy
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_create_verify_file.cpy (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_create_verify_file.cpy (revision 525)
@@ -0,0 +1,23 @@
+## Script (Python) "create_verify_file"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind subpath=traverse_subpath
+##parameters=verify_filename
+##title=Create file for verification
+##
+
+from Products.CMFCore.utils import getToolByName
+from Products.qPloneGoogleSitemaps.utils import BadRequestException
+portal = getToolByName(context, 'portal_url').getPortalObject()
+try:
+ portal.manage_addFile(verify_filename,title='Verification File')
+ portal[verify_filename].manage_addProperty('CreatedBy','qPloneGoogleSitemaps','string')
+except BadRequestException:
+ pass
+props = getToolByName(context,'portal_properties').googlesitemap_properties
+props.manage_changeProperties(verification_filename = verify_filename)
+
+
+return state.set(portal_status_message = 'Plone Google Sitemap updated.')
Index: /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_create_verify_file.cpy.metadata
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_create_verify_file.cpy.metadata (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_create_verify_file.cpy.metadata (revision 525)
@@ -0,0 +1,14 @@
+#
+# $$
+#
+[default]
+title=Create verify file
+
+[security]
+View=0:Authenticated
+
+[validators]
+
+[actions]
+action.success=traverse_to:string:prefs_gsm_verification
+action.failure=traverse_to:string:prefs_gsm_verification
Index: /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_delete_verify_file.cpy
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_delete_verify_file.cpy (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_delete_verify_file.cpy (revision 525)
@@ -0,0 +1,23 @@
+## Script (Python) "create_verify_file"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind subpath=traverse_subpath
+##parameters=
+##title=Create file for verification
+##
+
+from Products.CMFCore.utils import getToolByName
+props = getToolByName(context,'portal_properties').googlesitemap_properties
+
+portal = getToolByName(context,'portal_url').getPortalObject()
+try:
+ if portal[props.verification_filename].CreatedBy == 'qPloneGoogleSitemaps':
+ portal.manage_delObjects(props.verification_filename)
+except:
+ pass
+
+props.manage_changeProperties(verification_filename = '')
+
+return state.set(portal_status_message = 'Plone Google Sitemap updated.')
Index: /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_delete_verify_file.cpy.metadata
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_delete_verify_file.cpy.metadata (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_delete_verify_file.cpy.metadata (revision 525)
@@ -0,0 +1,14 @@
+#
+# $$
+#
+[default]
+title=Delete verify file
+
+[security]
+View=0:Authenticated
+
+[validators]
+
+[actions]
+action.success=traverse_to:string:prefs_gsm_verification
+action.failure=traverse_to:string:prefs_gsm_verification
Index: /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_edit_pinging.cpy
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_edit_pinging.cpy (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_edit_pinging.cpy (revision 525)
@@ -0,0 +1,20 @@
+## Script (Python) "gsm_edit_pinging"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind subpath=traverse_subpath
+##parameters=transitions=[]
+##title=Configure Plone Google Sitemap
+##
+
+from Products.qPloneGoogleSitemaps.utils import setWorkflowTransitions
+from Products.CMFCore.utils import getToolByName
+
+if not transitions:
+ w_tool = getToolByName(context, "portal_workflow")
+ transitions = [w + "#" for w in w_tool.listWorkflows()]
+
+setWorkflowTransitions(context, transitions)
+
+return state.set(portal_status_message = "Plone Google Sitemap updated.")
Index: /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_edit_pinging.cpy.metadata
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_edit_pinging.cpy.metadata (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_edit_pinging.cpy.metadata (revision 525)
@@ -0,0 +1,14 @@
+#
+# $$
+#
+[default]
+title= Save Propertiest
+
+[security]
+View=0:Authenticated
+
+[validators]
+
+[actions]
+action.success=traverse_to:string:prefs_gsm_pinging
+action.failure=traverse_to:string:prefs_gsm_pinging
Index: /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_edit_settings.cpy
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_edit_settings.cpy (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_edit_settings.cpy (revision 525)
@@ -0,0 +1,20 @@
+## Script (Python) "gsm_edit_settings"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind subpath=traverse_subpath
+##parameters=states, portalTypes, blackout_list, reg_exp, urls
+##title=Configure Plone Google Sitemap
+##
+
+from Products.CMFCore.utils import getToolByName
+from Products.qPloneGoogleSitemaps.utils import setWorkflowTransitions
+import Products.qPloneGoogleSitemaps.config as config
+
+props = getToolByName(context,'portal_properties').googlesitemap_properties
+props.manage_changeProperties( states=states, portalTypes=portalTypes,
+ blackout_list=blackout_list, reg_exp = reg_exp,
+ urls = urls)
+
+return state.set(portal_status_message = 'Plone Google Sitemap updated.')
Index: /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_edit_settings.cpy.metadata
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_edit_settings.cpy.metadata (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/gsm_edit_settings.cpy.metadata (revision 525)
@@ -0,0 +1,14 @@
+#
+# $$
+#
+[default]
+title= Save Propertiest
+
+[security]
+View=0:Authenticated
+
+[validators]
+
+[actions]
+action.success=traverse_to:string:prefs_gsm_settings
+action.failure=traverse_to:string:prefs_gsm_settings
Index: /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/ping_googlesitemaps.cpy
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/ping_googlesitemaps.cpy (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/ping_googlesitemaps.cpy (revision 525)
@@ -0,0 +1,23 @@
+## Script (Python) "ping_googlesitemaps.cpy"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind subpath=traverse_subpath
+##parameters=
+##title=Ping information to Google
+##
+
+from Products.CMFCore.utils import getToolByName
+from Products.qPloneGoogleSitemaps.utils import ping_google
+
+url = getToolByName(context, 'portal_url')()
+
+portal_msg = "Google pinged. It will review your sitemap as soon as it will be able to."
+
+try:
+ ping_google(url)
+except:
+ portal_msg = "Cannot contact Google. Try again in a while."
+
+return state.set(portal_status_message = portal_msg)
Index: /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/ping_googlesitemaps.cpy.metadata
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/ping_googlesitemaps.cpy.metadata (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/ping_googlesitemaps.cpy.metadata (revision 525)
@@ -0,0 +1,13 @@
+#
+# $$
+#
+[default]
+title=Google Sitemap Ping
+
+[security]
+View=0:Authenticated
+
+[validators]
+
+[actions]
+action.success=traverse_to:string:prefs_gsm_pinging
Index: /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/prefs_gsm_overview.cpt
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/prefs_gsm_overview.cpt (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/prefs_gsm_overview.cpt (revision 525)
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+ -
+ Overview
+
+
+ -
+ Verification
+
+
+ -
+
+ Settings
+
+
+ -
+ Pinging
+
+
+
+
+
+
+
+
+
Plone Google Sitemaps
+
+ Up to Plone Setup
+
+
+
+ Plone Google Sitemaps allows search engine to have better visibility of your
+ example.com
+ Plone website.
+
+
+
Post-install instructions
+
+
Congratulations, you've installed Plone Google Sitemaps product from
+ Quintagroup.
+
+
+
+ - First step
+ - Your site is Google Sitemaps enabled already. Check
+ sitemap XML
+ to see generated sitemap document of your website. It should contain URLs of
+ all published objects. If you see something that should not be indexed by
+ Google, retract objects or exclude sections with robots.txt (that GoogleBot
+ obey).
+
+ - Second step
+ - Make Google know of your sitemap:
+
+ - go to Google
+ Sitemaps Central (logging in / signing up as necessary)
+ - add your sitemap URL:
+
http://example.com/google-sitemaps
+
+ It takes a while for your sitemap to be processed by Google.
+ Usually within 24 hours it processes hte sitemap so do not expect your
+ submission to be processed instantly.
+
+
+ Helpful resources
+
+ - google-sitemaps discussion group
-
+
- As Google Sitemaps is emerging technology, we are all learning from it.
+ Google set up discussion group to find your ideas about it. You can find
+ help from other webmasters as they usually found answers to questions that
+ you have. If not you are free to ask, to praise and to ramble ;)
+ - Plone Google Sitemaps
+ product page
+ - Stay tuned. We are preparing new and fresh releases. Product page will
+ help you to keep informed about them.
+
+
+
+
+
+
Index: /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/prefs_gsm_pinging.cpt
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/prefs_gsm_pinging.cpt (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/prefs_gsm_pinging.cpt (revision 525)
@@ -0,0 +1,115 @@
+
+
+
+
+
Index: /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/prefs_gsm_pinging.cpt.metadata
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/prefs_gsm_pinging.cpt.metadata (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/prefs_gsm_pinging.cpt.metadata (revision 525)
@@ -0,0 +1,15 @@
+#
+# $$
+#
+[default]
+title=Plone Google Sitemap Configuration
+
+[security]
+View=0:Authenticated
+
+[validators]
+
+[actions]
+action.success..Ping=traverse_to:string:ping_googlesitemaps
+action.success..Save=traverse_to:string:gsm_edit_pinging
+action.failure=traverse_to:string:prefs_gsm_pinging
Index: /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/prefs_gsm_settings.cpt
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/prefs_gsm_settings.cpt (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/prefs_gsm_settings.cpt (revision 525)
@@ -0,0 +1,176 @@
+
+
+
+
+
Index: /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/prefs_gsm_settings.cpt.metadata
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/prefs_gsm_settings.cpt.metadata (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/prefs_gsm_settings.cpt.metadata (revision 525)
@@ -0,0 +1,15 @@
+#
+# $$
+#
+[default]
+title=Plone Google Sitemap Configuration
+
+[security]
+View=0:Authenticated
+
+[validators]
+
+[actions]
+action.success..Save=traverse_to:string:gsm_edit_settings
+action.success=traverse_to:string:gsm_edit_settings
+action.failure=traverse_to:string:prefs_gsm_settings
Index: /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/prefs_gsm_verification.cpt
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/prefs_gsm_verification.cpt (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/prefs_gsm_verification.cpt (revision 525)
@@ -0,0 +1,90 @@
+
+
+
+
+
Index: /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/prefs_gsm_verification.cpt.metadata
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/prefs_gsm_verification.cpt.metadata (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/prefs_gsm_verification.cpt.metadata (revision 525)
@@ -0,0 +1,15 @@
+#
+# $$
+#
+[default]
+title=verification
+
+[security]
+View=0:Authenticated
+
+[validators]
+
+[actions]
+action.success..CreateFile=traverse_to:string:gsm_create_verify_file
+action.success..DeleteFile=traverse_to:string:gsm_delete_verify_file
+action.failure=traverse_to:string:prefs_gsm_verification
Index: /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/searchForGoogleSitemapObjects.py
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/searchForGoogleSitemapObjects.py (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/skins/qPloneGoogleSitemaps/searchForGoogleSitemapObjects.py (revision 525)
@@ -0,0 +1,30 @@
+## Script (Python) "searchForGoogleSitemapObjects"
+##bind container=
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind subpath=traverse_subpath
+##parameters=path=None
+##
+from Products.CMFCore.utils import getToolByName
+from Products.qPloneGoogleSitemaps.utils import applyOperations
+from string import find
+
+if not path:
+ path = '/'.join(context.getPhysicalPath())
+
+catalog = getToolByName(context, 'portal_catalog')
+try:
+ props = getToolByName(context, 'portal_properties').googlesitemap_properties
+ objects = catalog(path = path,
+ portal_type = props.portalTypes,
+ review_state = props.states,)
+except AttributeError:
+ # We are run without being properly installed, do default processing
+ return applyOperations(catalog(path = path,
+ review_state = ['published'],),
+ [])
+
+blackout_list = props.blackout_list
+return applyOperations([ob for ob in objects if (ob.getId not in blackout_list)],
+ props.getProperty('reg_exp'))
Index: /qPloneGoogleSitemaps/tags/0.6+/tests/XMLParser.py
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/tests/XMLParser.py (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/tests/XMLParser.py (revision 525)
@@ -0,0 +1,23 @@
+from xml.parsers.expat import ParserCreate
+import re
+
+def parse(data):
+ def start_el(name, attrs):
+ ParsedXML['start'][name] = attrs
+
+ def char_handler(data):
+ patt = re.compile('\S+', re.UNICODE)
+ if patt.search(data):
+ ParsedXML['data'].append(data)
+
+ ParsedXML = {'start':{}, 'end':[], 'data':[]}
+ parser = ParserCreate()
+ parser.StartElementHandler = start_el
+ parser.CharacterDataHandler = char_handler
+ parser.Parse(data)
+ return ParsedXML
+
+def hasURL(xml, url):
+ parsed_sitemap = parse(xml)
+ data = parsed_sitemap['data']
+ return url in data
Index: /qPloneGoogleSitemaps/tags/0.6+/tests/framework.py
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/tests/framework.py (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/tests/framework.py (revision 525)
@@ -0,0 +1,107 @@
+##############################################################################
+#
+# ZopeTestCase
+#
+# COPY THIS FILE TO YOUR 'tests' DIRECTORY.
+#
+# This version of framework.py will use the SOFTWARE_HOME
+# environment variable to locate Zope and the Testing package.
+#
+# If the tests are run in an INSTANCE_HOME installation of Zope,
+# Products.__path__ and sys.path with be adjusted to include the
+# instance's Products and lib/python directories respectively.
+#
+# If you explicitly set INSTANCE_HOME prior to running the tests,
+# auto-detection is disabled and the specified path will be used
+# instead.
+#
+# If the 'tests' directory contains a custom_zodb.py file, INSTANCE_HOME
+# will be adjusted to use it.
+#
+# If you set the ZEO_INSTANCE_HOME environment variable a ZEO setup
+# is assumed, and you can attach to a running ZEO server (via the
+# instance's custom_zodb.py).
+#
+##############################################################################
+#
+# The following code should be at the top of every test module:
+#
+# import os, sys
+# if __name__ == '__main__':
+# execfile(os.path.join(sys.path[0], 'framework.py'))
+#
+# ...and the following at the bottom:
+#
+# if __name__ == '__main__':
+# framework()
+#
+##############################################################################
+
+__version__ = '0.2.3'
+
+# Save start state
+#
+__SOFTWARE_HOME = os.environ.get('SOFTWARE_HOME', '')
+__INSTANCE_HOME = os.environ.get('INSTANCE_HOME', '')
+
+if __SOFTWARE_HOME.endswith(os.sep):
+ __SOFTWARE_HOME = os.path.dirname(__SOFTWARE_HOME)
+
+if __INSTANCE_HOME.endswith(os.sep):
+ __INSTANCE_HOME = os.path.dirname(__INSTANCE_HOME)
+
+# Find and import the Testing package
+#
+if not sys.modules.has_key('Testing'):
+ p0 = sys.path[0]
+ if p0 and __name__ == '__main__':
+ os.chdir(p0)
+ p0 = ''
+ s = __SOFTWARE_HOME
+ p = d = s and s or os.getcwd()
+ while d:
+ if os.path.isdir(os.path.join(p, 'Testing')):
+ zope_home = os.path.dirname(os.path.dirname(p))
+ sys.path[:1] = [p0, p, zope_home]
+ break
+ p, d = s and ('','') or os.path.split(p)
+ else:
+ print 'Unable to locate Testing package.',
+ print 'You might need to set SOFTWARE_HOME.'
+ sys.exit(1)
+
+import Testing, unittest
+execfile(os.path.join(os.path.dirname(Testing.__file__), 'common.py'))
+
+# Include ZopeTestCase support
+#
+if 1: # Create a new scope
+
+ p = os.path.join(os.path.dirname(Testing.__file__), 'ZopeTestCase')
+
+ if not os.path.isdir(p):
+ print 'Unable to locate ZopeTestCase package.',
+ print 'You might need to install ZopeTestCase.'
+ sys.exit(1)
+
+ ztc_common = 'ztc_common.py'
+ ztc_common_global = os.path.join(p, ztc_common)
+
+ f = 0
+ if os.path.exists(ztc_common_global):
+ execfile(ztc_common_global)
+ f = 1
+ if os.path.exists(ztc_common):
+ execfile(ztc_common)
+ f = 1
+
+ if not f:
+ print 'Unable to locate %s.' % ztc_common
+ sys.exit(1)
+
+# Debug
+#
+print 'SOFTWARE_HOME: %s' % os.environ.get('SOFTWARE_HOME', 'Not set')
+print 'INSTANCE_HOME: %s' % os.environ.get('INSTANCE_HOME', 'Not set')
+sys.stdout.flush()
+
Index: /qPloneGoogleSitemaps/tags/0.6+/tests/runalltests.py
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/tests/runalltests.py (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/tests/runalltests.py (revision 525)
@@ -0,0 +1,29 @@
+#
+# Runs all tests in the current directory
+#
+# Execute like:
+# python runalltests.py
+#
+# Alternatively use the testrunner:
+# python /path/to/Zope/utilities/testrunner.py -qa
+#
+
+import os, sys
+if __name__ == '__main__':
+ execfile(os.path.join(sys.path[0], 'framework.py'))
+
+import unittest
+TestRunner = unittest.TextTestRunner
+suite = unittest.TestSuite()
+
+tests = os.listdir(os.curdir)
+tests = [n[:-3] for n in tests if n.startswith('test') and n.endswith('.py')]
+
+for test in tests:
+ m = __import__(test)
+ if hasattr(m, 'test_suite'):
+ suite.addTest(m.test_suite())
+
+if __name__ == '__main__':
+ TestRunner().run(suite)
+
Index: /qPloneGoogleSitemaps/tags/0.6+/tests/testqPloneGoogleSitemaps.py
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/tests/testqPloneGoogleSitemaps.py (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/tests/testqPloneGoogleSitemaps.py (revision 525)
@@ -0,0 +1,154 @@
+#
+# Tests for qPloneGoogleSitemaps
+#
+import os, sys
+if __name__ == '__main__':
+ execfile(os.path.join(sys.path[0], 'framework.py'))
+
+from Products.PloneTestCase import PloneTestCase
+from XMLParser import parse, hasURL
+
+PRODUCT = 'qPloneGoogleSitemaps'
+PRODUCTS = (PRODUCT,)
+PloneTestCase.installProduct(PRODUCT)
+PloneTestCase.setupPloneSite(products = PRODUCTS)
+
+class TestqPloneGoogleSitemaps(PloneTestCase.FunctionalTestCase):
+
+ def afterSetUp(self):
+ self.loginAsPortalOwner()
+
+ self.membership = self.portal.portal_membership
+ self.workflow = self.portal.portal_workflow
+ self.auth = 'admin:admin'
+ self.sitemapUrl = '/'+self.portal.absolute_url(1) + '/google-sitemaps'
+ self.membership.addMember('admin', 'admin', ('Manager',), [])
+
+ # Add testing document to portal
+ my_doc = self.portal.invokeFactory('Document', id='my_doc')
+ self.my_doc = self.portal['my_doc']
+ self.my_doc.edit(text_format='plain', text='hello world')
+
+ def testInstallation(self):
+ installed = self.portal.portal_quickinstaller.isProductInstalled(PRODUCT)
+ self.assert_(installed, 'Product not installed')
+
+ def testSitemap(self):
+ sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
+ parsed_sitemap = parse(sitemap)
+ start = parsed_sitemap['start']
+ data = parsed_sitemap['data']
+ self.assertEqual(len(start.keys()), 1)
+ self.assert_('urlset' in start.keys())
+
+ self.workflow.doActionFor(self.my_doc, 'publish')
+
+ sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
+ parsed_sitemap = parse(sitemap)
+ start = parsed_sitemap['start']
+ data = parsed_sitemap['data']
+ self.assertEqual(len(start.keys()), 4)
+ self.assert_('urlset' in start.keys())
+ self.assert_('url' in start.keys())
+ self.assert_('loc' in start.keys())
+ self.assert_('lastmod' in start.keys())
+
+ self.assert_(data[0] == self.my_doc.absolute_url(0), 'Incorect url')
+
+ def testVerificationFile(self):
+ self.portal.gsm_create_verify_file('verif_file')
+
+ vf_created = hasattr(self.portal, 'verif_file')
+ self.assert_(vf_created, 'Verification file not created')
+
+ self.portal.gsm_delete_verify_file()
+ vf_created = hasattr(self.portal, 'verif_file')
+ self.assert_(not vf_created, 'Verification file not removed')
+
+class TestSettings(PloneTestCase.FunctionalTestCase):
+
+ def afterSetUp(self):
+ self.loginAsPortalOwner()
+
+ self.membership = self.portal.portal_membership
+ self.workflow = self.portal.portal_workflow
+ self.gsm_props = self.portal.portal_properties['googlesitemap_properties']
+ self.auth = 'admin:admin'
+ self.sitemapUrl = '/'+self.portal.absolute_url(1) + '/google-sitemaps'
+
+ self.membership.addMember('admin', 'admin', ('Manager',), [])
+
+ # Add testing document to portal
+ my_doc = self.portal.invokeFactory('Document', id='my_doc')
+ self.my_doc = self.portal['my_doc']
+ self.my_doc.edit(text_format='plain', text='hello world')
+ self.my_doc_url = self.my_doc.absolute_url()
+
+ def testMetaTypeToDig(self):
+ self.workflow.doActionFor(self.my_doc, 'publish')
+ sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
+ self.assert_(hasURL(sitemap, self.my_doc_url))
+
+ self.gsm_props.manage_changeProperties(portalTypes = [])
+
+ sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
+ self.assert_(not hasURL(sitemap, self.my_doc_url))
+
+ self.gsm_props.manage_changeProperties(portalTypes = ['Document'])
+
+ sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
+ self.assert_(hasURL(sitemap, self.my_doc_url))
+
+ def testStates(self):
+ self.workflow.doActionFor(self.my_doc, 'publish')
+ self.gsm_props.manage_changeProperties(states = ['visible'])
+
+ sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
+ self.assert_(not hasURL(sitemap, self.my_doc_url))
+
+ self.gsm_props.manage_changeProperties(states = ['published'])
+
+ sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
+ self.assert_(hasURL(sitemap, self.my_doc_url))
+
+ def test_blackout_entries(self):
+ self.workflow.doActionFor(self.my_doc, 'publish')
+ self.gsm_props.manage_changeProperties(blackout_list = (self.my_doc.getId(),))
+ sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
+ self.assert_(not hasURL(sitemap, self.my_doc_url))
+
+ self.gsm_props.manage_changeProperties(blackout_list = [])
+ sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
+ self.assert_(hasURL(sitemap, self.my_doc_url))
+
+ def test_regexp(self):
+ self.workflow.doActionFor(self.my_doc, 'publish')
+ sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
+ self.assert_(not hasURL(sitemap, self.portal.absolute_url()))
+
+ regexp = "s/\/%s//"%self.my_doc.getId()
+ self.gsm_props.manage_changeProperties(reg_exp = [regexp])
+
+ sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
+ self.assert_(hasURL(sitemap, self.portal.absolute_url()))
+
+ def test_add_urls(self):
+ self.gsm_props.manage_changeProperties(urls = ['http://w1', 'w2', '/w3'])
+ w1_url = 'http://w1'
+ w2_url = self.portal.absolute_url() + '/w2'
+ w3_url = self.portal.getPhysicalRoot().absolute_url() + '/w3'
+ sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
+
+ self.assert_(hasURL(sitemap, w1_url))
+ self.assert_(hasURL(sitemap, w2_url))
+ self.assert_(hasURL(sitemap, w3_url))
+
+def test_suite():
+ from unittest import TestSuite, makeSuite
+ suite = TestSuite()
+ suite.addTest(makeSuite(TestqPloneGoogleSitemaps))
+ suite.addTest(makeSuite(TestSettings))
+ return suite
+
+if __name__ == '__main__':
+ framework()
Index: /qPloneGoogleSitemaps/tags/0.6+/utils.py
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/utils.py (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/utils.py (revision 525)
@@ -0,0 +1,108 @@
+from urllib2 import urlopen
+from urllib import quote as urlquote
+from Products.CMFCore.utils import getToolByName
+import re
+import Products.qPloneGoogleSitemaps.config as config
+from OFS.ObjectManager import BadRequestException
+def ping_google(url):
+ """Ping sitemap to Google"""
+ sitemap_url = urlquote(url + "/google-sitemaps")
+ g = urlopen('http://www.google.com/webmasters/sitemaps/ping?sitemap='+sitemap_url)
+ result = g.read()
+ g.close()
+ return 0
+
+def searchAndReplace(string, what, with):
+ """Emulate sed command s/"""
+ res = re.sub(what,with,string)
+ return res
+
+OPERATORS = {'s': searchAndReplace,}
+
+def applyOperations(objects, operations):
+ """Parse Operations """
+ parse = re.compile(r"(.?[^\\])/(.*[^\\]|)/(.*[^\\]|)/")
+ operations=[parse.match(op).groups() for op in operations]
+ result={}
+ for ob in objects:
+ url = ob.getURL()
+ for operator, what, with in operations:
+ url = OPERATORS[operator](url, what, with.replace("\\", ""))
+ #TODO: Remove or replace following condition
+ #it is senseless in the case we need intelligent
+ #result set. Better condition would be to place
+ #freshest brain into result
+ if url in result.keys():
+ continue
+ #TODO: replace brain with only data necessary to
+ #generate sitemap
+ result[url]=ob
+ return result
+
+def additionalURLs(self):
+ """Add URLs to sitemap that arn't objects"""
+ res = []
+ plone_home = getToolByName(self, 'portal_url').getPortalObject().absolute_url()
+ root = self.getPhysicalRoot().absolute_url()
+
+ props = getToolByName(self,'portal_properties')
+ try:
+ URLs = props.googlesitemap_properties.urls
+ except AttributeError:
+ URLs = []
+
+ add_zope = re.compile('^/')
+ add_plone= re.compile('^[^http://|https://|\\\]')
+ for url in URLs:
+ if add_zope.match(url):
+ res.append(root+url)
+ elif add_plone.match(url):
+ res.append(plone_home+'/'+url)
+ else:
+ res.append(url)
+ return res
+
+"""workflows & co"""
+def getWorkflowTransitions(self,workflow_id):
+ pw = getToolByName(self,'portal_workflow')
+ wf = pw.getWorkflowById(workflow_id)
+ if not wf:
+ return None
+ return wf.transitions.values()
+
+def setWorkflowTransitions(self,transitions):
+ """set workflow transitions properties"""
+ portal_workflow = getToolByName(self, 'portal_workflow')
+ transmap = {}
+ for key in transitions:
+ if key.find('#')>0:
+ ids = key.split('#')
+ wfid = ids[0]
+ if not wfid in transmap.keys():
+ transmap[wfid]=[]
+ transmap[wfid].append(ids[1])
+ for wfid in transmap.keys():
+ workflow = portal_workflow.getWorkflowById(wfid)
+ if config.ping_googlesitemap not in workflow.scripts.objectIds():
+ workflow.scripts.manage_addProduct['ExternalMethod'].manage_addExternalMethod(
+ config.ping_googlesitemap,
+ 'Ping sitemap',
+ 'qPloneGoogleSitemaps.ping_googlesitemap',
+ config.ping_googlesitemap)
+ transitions_set = transmap[wfid]
+ for transition in workflow.transitions.values():
+ trid = transition.id
+ tras = transition.after_script_name
+ if (tras == '') and (trid in transitions_set):
+ #set
+ after_script = config.ping_googlesitemap
+ elif (tras == config.ping_googlesitemap) and not (trid in transitions_set):
+ #reset
+ after_script = ''
+ else:
+ #avoid properties set
+ continue
+ transition.setProperties(title=transition.title,
+ new_state_id=transition.new_state_id,
+ after_script_name=after_script,
+ actbox_name=transition.actbox_name)
Index: /qPloneGoogleSitemaps/tags/0.6+/version.txt
===================================================================
--- /qPloneGoogleSitemaps/tags/0.6+/version.txt (revision 525)
+++ /qPloneGoogleSitemaps/tags/0.6+/version.txt (revision 525)
@@ -0,0 +1,1 @@
+0.6+