Page Template: user_info

Basic user information page template

<html>
<body>
<div 
  
tal:omit-tag=""
  
tal:define="
    userName request/userName|nothing;
    userObj python: here.portal_membership.getMemberById(userName);
    getPortrait nocall: here/portal_membership/getPersonalPortrait;
    getFolder nocall: here/portal_membership/getHomeFolder
    "
>
     
<p tal:condition="not: userName">
        No username selected.
     
</p>
     
<p tal:condition="not: userObj">
       That username does not exist.
     
</p>
            
     
<table tal:condition="userObj">
       
<tr>
         
<td>
          
<img src=""
            
tal:replace="structure python: getPortrait(userName)" />
          
</td>
          
<td> 
            
<ul>
            
<li>
              
<i>Username:</i>
              
<span tal:replace="userName" />
            
</li>
            
<li>
              
<i>Full name:</i>
              
<span tal:replace="userObj/fullname" />
            
</li>
            
<li
              
tal:define="home python: getFolder(userName)" 
              
tal:condition="home">
              
<i>Home folder:</i>
              
<a href=""
                 
tal:attributes="href home/absolute_url"
                 
tal:content="home/absolute_url">Folder</a>
            
</li>
            
<li>
              
<i>Email:</i>
              
<a href="" 
                  
tal:define="email userObj/email"
                  
tal:attributes="href string:mailto:$email"
                  
tal:content="email">Email</a>
            
</li>
            
<li>
              
<i>Last login time:</i>
              
<span tal:replace="userObj/last_login_time" />
            
</li>
        
</ul>
       
</td>
     
</tr>
   
</table>
</div>
</body>
</html>

Page Template: test_context

An example Page Template showing the contexts

<html>
  
<head />
  
<body>
    
<h1>Debug information</h1>
  
<h2>CONTEXTS</h2>
  
<ul>
    
<tal:block 
        
tal:repeat="item CONTEXTS">
    
<li 
        
tal:condition="python: item != 'request'"
        
tal:define="context CONTEXTS;">
            
<b tal:content="item" />
            
<span tal:replace="python: context[item]" />
    
</li>
    
</tal:block>
  
</ul>
  
<h2>REQUEST</h2>
  
<p tal:replace="structure request" />
  
</body>
</html>

Page Template: user_info

A more advanced version of the user information Page Template

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US"
      
lang="en-US"
      
i18n:domain="plone"
      
metal:use-macro="here/main_template/macros/master">

<body>
<div metal:fill-slot="main">
  
<tal:block
    
tal:define="
     getPortrait nocall: here/portal_membership/getPersonalPortrait;
     getFolder nocall: here/portal_membership/getHomeFolder
     "
>
    
<table>
     
<tal:block 
      
tal:repeat="userObj here/portal_membership/listMembers">
       
<metal:block 
         
metal:use-macro="here/user_section/macros/userSection" />
     
</tal:block>
    
</table>
 
</tal:block>        
</div>
</body>
</html>

Page Template: user_section

The macro for displaying each user's information.

<div metal:define-macro="userSection"
 
tal:define="userName userObj/getUserName">
 
<tr>
   
<td>
     
<img src=""
       
tal:replace="structure python: getPortrait(userName)" />
   
</td>
   
<td tal:define="prop nocall: userObj/getProperty"> 
     
<ul>
       
<li>
         
<i>Username:</i>
         
<span tal:replace="userName" />
       
</li>
       
<li>
         
<i>Full name:</i>
         
<span tal:replace="python: prop('fullname')" />
       
</li>
       
<li
         
tal:define="home python: getFolder(userName)" 
         
tal:condition="home">
         
<a href=""
         
tal:attributes="href home/absolute_url">Home Folder</a>
       
</li>
       
<li>
         
<i>Email:</i>
         
<a href="" 
           
tal:define="email python: prop('email')"
           
tal:attributes="href string:mailto:$email"
           
tal:content="email">Email</a>
       
</li>
       
<li>
         
<i>Last login time:</i>
          
<span tal:replace="python: prop('last_login_time')" />
       
</li>
     
</ul>
   
</td>
 
</tr>
</div>

Python: zpt.py

A script to syntax check Page Templates, without having to load it into Plone.

#!/usr/bin/python
from Products.PageTemplates.PageTemplate import PageTemplate
import sys

def test(file):
    
raw_data = open(file, 'r').read()
    
pt = PageTemplate()
    
pt.write(raw_data)
    
if pt._v_errors:
        
print "*** Error in:", file
        
for error in pt._v_errors[1:]:
            
print error
                
if __name__=='__main__':
    
if len(sys.argv) < 2:
        
print "python check.py file [files...]"
        
sys.exit(1)
    
else:
        
for arg in sys.argv[1:]:
            
test(arg)

Page Template: google_ad_portlet

A portlet for showing Google ads.

<div metal:define-macro="portlet">
    
<div class="portlet">
<script type="text/javascript"><!--
google_ad_client = "yourUniqueValue";
google_ad_width = 120;
google_ad_height = 600;
google_ad_format = "120x600_as";
//--></script>
<script type="text/javascript"
  
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
   
</div>
</div>

Script Python: recentlyChanged

A script that examines all objects passed to the script and then find out what is new.

##title=recentlyChanged
##parameters=objects
from DateTime import DateTime

now = DateTime()
difference = 5 # as in 5 days
result = []

for object in objects:
  
diff = now - object.bobobase_modification_time()
  
if diff < difference:
    
dct = {"object":object,"diff":int(diff)}
    
result.append(dct)

return result

External Method: readFile

An External Method that reads a file from the file server

def readFile(self):
   
fh = open(r'c:\Program Files\Plone\Data\Extensions\README.txt', 'rb')
   
data = fh.read()
   
return data

Validator Script: validEmail

A script to validate email

email = context.REQUEST.get('email_address', None)

if not email:
    
state.setError('email_address', 'An email address is required', new_status='failure')

if state.getErrors():
    
state.set(portal_status_message='Please correct the errors shown.')
    
return state

Controller Python Script: sendEmail

A send email script

mhost = context.MailHost
emailAddress = context.REQUEST.get('email_address')
administratorEmailAddress = context.email_from_address
comments = context.REQUEST.get('comments')

# the message format, %s will be filled in from data
message = """
From: %s
To: %s
Subject: Website Feedback

%s

URL: %s
"""


# format the message
message = message % (
    
emailAddress, 
    
administratorEmailAddress,
    
comments,
    
context.absolute_url())

mhost.send(message)

screenMsg = "Comments sent, thank you."
state.setKwargs( {'portal_status_message':screenMsg} )
return state

Page Template: feedbackForm

A form for providing feedback to users.

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US"
lang="en-US" i18n:domain="plone"
metal:use-macro="here/main_template/macros/master">
  
<body>
    
<div metal:fill-slot="main"
    
tal:define="errors options/state/getErrors;">
      
<p>Please send us any feedback you might have about the
      site.
</p>
      
<form method="post" tal:attributes="action template/id;">
        
<fieldset>
          
<legend class="legend"
          
i18n:translate="legend_feedback_form">Website
          Feedback
</legend>
          
<div class="field"
          
tal:define="error_email_address errors/email_address|nothing;"
               
tal:attributes="class python:test(error_email_address, 'field error', 'field')">

            
<label i18n:translate="label_email_address">Your email
            address
</label>
            
<span class="fieldRequired" title="Required"
            
i18n:attributes="title"
            
i18n:translate="label_required">(Required)</span>
            
<div class="formHelp"
            
i18n:translate="label_email_address_help">Enter your
            email address.
</div>
            
<div tal:condition="error_email_address">
              
<tal:block i18n:translate=""
              
content="error_email_address">Error</tal:block>
            
</div>
            
<input type="text" name="email_address"
            
tal:attributes="tabindex tabindex/next; value request/email_address|nothing" />
          
</div>
          
<div class="field">
            
<label i18n:translate="label_feedback_comments">
            Comments
</label>
            
<div class="formHelp" id="label_feedback_comments_help"
            
i18n:translate="label_feedback_comments_help">Enter the
            comments you have about the site.
</div>
            
<textarea name="comments" rows="10"
            
tal:content="request/comments|nothing"
            
tal:attributes="tabindex tabindex/next;" />
          
</div>
          
<div class="formControls">
            
<input class="context" type="submit" tabindex=""
            
name="form.button.Submit" value="Submit"
            
i18n:attributes="value"
            
tal:attributes="tabindex tabindex/next;" />
          
</div>
        
</fieldset>
        
<input type="hidden" name="form.submitted" value="1" />
      
</form>
    
</div>
  
</body>
</html>

CSS: ploneCustom.css

NASA Maestro CSS

body {
    background
: #343434;
}

#visual-portal-wrapper {
    width
: 680px;
    margin
: 1em auto 0 auto;
}

#portal-top {
    background
: url("/header.jpg") transparent no-repeat;
    padding
: 162px 0 0 0;
    position
: relative;
}

#portal-logo {
    background
: transparent;
    background-image
: none;
    margin
: 0;
    position
: absolute;
    top
: 130px;
    left
: 5px;
    z-index
: 20;
}

#portal-logo a {
    padding-top
: 25px;
    height 
/**/: 25px;
    width
: 375px;
}

#portal-globalnav {
   background
: url("/listspacer.gif") transparent;
    padding
: 0;
    height
: 21px;
    border
: 0;
    margin
: 0 0 1px 6px;
    clear
: both;
}

#portal-globalnav li {
    display
: block;
    float
: left;
    height
: 21px;
    background
: url("/liststart.gif") transparent no-repeat;
    padding
: 0 0 0 33px;
    margin
: 0 0.5em 0 0;
}

#portal-globalnav li a {
    display
: block;
    float
: left;
    height
: 21px;
    background
: url("/listitem.gif") transparent right top;
    padding
: 0 33px 0 0;
    border
: 0;
    line-height
: 2em;
    color
: black;
    font-size
: 90%;
    margin
: 0;
}

#portal-globalnav li a:hover,
#portal-globalnav li.selected a {
    background-color
: transparent;
    border
: 0;
    color
: #444;
}

#portal-personaltools {
    clear
: both;
    margin-left
: 6px;
    border-top-color
: #776a44;
    border-top-style
: solid;
    border-top-width
: 1px;
}

#portal-breadcrumbs {
    clear
: both;
}

#portal-breadcrumbs,
#portal-columns,
.documentContent {
    background
: white;
    margin-left
: 6px;
}

.documentContent {
   margin
: 0;
   font-size
: 100%;
}

.screenshotThumb {
  float
:right;
}

#portal-footer {
    margin
: -1px 0 0 6px;
    padding
: 0.8em 0;
    border
: 1px solid #ddd;
    border-style
: solid none none none;
    background
: white;
    color
: #666;
    font-size
: 90%;
}

#portal-footer a {
    color
: #333;
    text-decoration
: underline;
}

dt {
    color
: #ECA200;
}

.documentDescription {
    font-size
: 110%;
}

#portal-breadcrumbs img {
    display
: none;
}

li.reqlist {
    margin-top
: 0;
    margin-bottom
: 0;
}

Script (Python): mail.py

Mail a message to all reviewers in a site

##parameters=state_change
# the objects we need
object = state_change.object
mship = context.portal_membership
mhost = context.MailHost

# the message format, %s will be filled in from data
message = """
From: noreply@yourwebsite.com
To: %s
Subject: New item submitted for approval - %s

%s

URL: %s
"""

for user in mship.listMembers():
    
if "Reviewer" in mship.getMemberById(user.id).getRoles():      
        
if user.email:
            
msg = message % (
                 
user.email,
                 
object.TitleOrId(), 
                 
object.Description(),
                 
object.absolute_url()
                 
)
            
mhost.send(msg)

External Method: importUsers

This script runs through a CSV file and adds in users based on that information.

# An external method to import user
import csv

# the full path to your csv file
fileName = "/var/zope.zeo/Extensions/test.csv"

def importUsers(self):
    
reader = csv.reader(open(fileName, "r"))
    
pr = self.portal_registration 
    
pg = self.portal_groups
    
out = []
    
    
# if your csv file contains a header line that
    
# explains the contents of each column
    
ignoreLine = 1
    
for row in reader:
        
if ignoreLine:
            
ignoreLine = 0
            
continue
        
        
# check we have exactly 4 items 
        
assert len(row) == 4
        
id, name, email, groups = row
        
groups = groups.split(',')

        
# make a password
        
password = pr.generatePassword()
        
try: 
            
# add in member
            
pr.addMember(id = id,
                
password = password,
                
roles = ["Member",],
                
properties = {
                    
'fullname': name,
                    
'username': id,
                    
'email': email,
                    
}
                
)
            
# groups are separated by commas
            
for groupId in groups:
                
group = pg.getGroupById(groupId)
                
group.addMember(id)
            
            
out.append("Added user %s" % id)
                
        
except ValueError, msg:
            
# if we skipped this user for a reason, tell the person
            
out.append("Skipped %s, reason: %s" % (id, msg))
    
    
# return something 
    
return "\n".join(out)

External Method: fixUsers

A script that runs through all the users and sets the editor property to Epoz.

def fixUsers(self):
    
pm = self.portal_membership
    
members = pm.listMemberIds() 

    
out = []
    
for member in members: 
        
# now get the actual member
        
m = pm.getMemberById(member)
        
# get the editor property for that member 
        
p = m.getProperty('wysiwyg_editor', None) 

        
out.append("%s %s" % (p, member))
        
if p is not None and p != 'Epoz': 
            
m.setMemberProperties({'wysiwyg_editor': 'Epoz',}) 
            
out.append("Changed property for %s" % member)
    
return "\n".join(out)

Script (Python): getGroups

A script to get all the ousers in the group for an object

##parameters=object=None
# object is the object to find all the members of the same group for
users = []
# get the creator
userName = object.Creator()
user = context.portal_membership.getMemberById(userName)
pg = context.portal_groups

# loop through the groups the user is in
for group in user.getGroups():
  
group = pg.getGroupById(group)
  
   
# loop through the users in each of those groups
  
for user in group.getGroupUsers():
    
if user not in users and user != userName:
      
users.append(user)
    
return users

Script (Python): scriptObjectCreation

A script to generate content types programmatically.

##title=Create 
##parameters=
# create with a random id
newId = context.generateUniqueId('Folder')

# create a object of type Folder
context.invokeFactory(id=newId, type_name='Folder')
newFolder = getattr(context, newId)

# create a new Document type
newFolder.invokeFactory(id='index.html', type_name='Document')

# get the new page
newPage = getattr(newFolder, 'index.html')
newPage.edit('html', '<p>This is the default page.</p>')

# return something back to the calling script
return "Done"

Script (Python): getCatalogResults

A script to search the catalog

##title=Get Catalog Results
##parameters=
return context.portal_catalog.searchResults(REQUEST=context.REQUEST)

Page Template: testResults

A page to show the results

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US"
      
lang="en-US"
      
metal:use-macro="here/main_template/macros/master"
      
i18n:domain="plone">
<body>
<div metal:fill-slot="main">
<ul tal:define="results here/getCatalogResults">
    
<li tal:repeat="result results">
        
<a href="" 
           
tal:attributes="href result/getURL" 
           
tal:content="result/Title" />
        
<span tal:replace="result/Description" />
    
</li>
</ul>
</div>
</body>
</html>

Page Template: testForm

A form to search the internet

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US"
      
lang="en-US"
      
metal:use-macro="here/main_template/macros/master"
      
i18n:domain="plone">
<body>
<div metal:fill-slot="main">
    
<p>Select a content type to search for</p>
    
<form method="post" action="testResults">
        
<select name="Type">
            
<option tal:repeat="value python:here.portal_catalog.uniqueValuesFor('Type')" tal:content="value" />
        
</select>
        
<br />
        
<input type="submit" class="context">
    
</form>
</div>
</body>
</html>

Python: header.py

A script that reads the headers of a web page, useful for testing caching.

#!/usr/bin/python
import sys

from httplib import HTTP
from urlparse import urlparse

def getHeaders(url, method):
    
p = list(urlparse(url))
    
if not p[0]:
        
url = 'http://' + url
        
p = list(urlparse(url))
        
    
h = HTTP(p[1])

    
h.putrequest(method, p[2])
    
h.putheader('Accept-Encoding', 'gzip, deflate')
    
h.endheaders()
    
    
reply = h.getreply()
    
print "Status:", reply[0]
    
print "Status message:", reply[1]
    
hdrs = reply[2].headers
    
hdrs.sort()
    
for header in hdrs:
        
print header[:-1]

def usage():
    
print """Usage: headers.py URL [method]

URL - the URL to get headers for, http:// default
method - GET default
"""

    
sys.exit()

if __name__=='__main__':
    
if len(sys.argv) < 2: usage()
    
method = 'GET'
    
if len(sys.argv) > 2:
        
method = sys.argv[2]
    
getHeaders(sys.argv[1], method)