<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>jjmojojjmojo: In Effect</title>
	<atom:link href="http://lionfacelemonface.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://lionfacelemonface.wordpress.com</link>
	<description>Programming... for life</description>
	<lastBuildDate>Tue, 13 Oct 2009 17:35:06 +0000</lastBuildDate>
	<generator>http://wordpress.com/</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain='lionfacelemonface.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://www.gravatar.com/blavatar/b4b47436b8cdb2c341f45d0a94acc689?s=96&#038;d=http://s.wordpress.com/i/buttonw-com.png</url>
		<title>jjmojojjmojo: In Effect</title>
		<link>http://lionfacelemonface.wordpress.com</link>
	</image>
			<item>
		<title>extending a buildout: taking out unwanted parts</title>
		<link>http://lionfacelemonface.wordpress.com/2009/10/13/buildout-remove-parts/</link>
		<comments>http://lionfacelemonface.wordpress.com/2009/10/13/buildout-remove-parts/#comments</comments>
		<pubDate>Tue, 13 Oct 2009 17:35:06 +0000</pubDate>
		<dc:creator>jjmojojjmojo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://lionfacelemonface.wordpress.com/?p=280</guid>
		<description><![CDATA[I&#8217;m working on a suite of buildout configuration files to use for different circumstances. Having a special buildout for development in a zeo cluster, and another for a single monolithic zope instance (plus useful debug tools already installed) was easy to do and is working well.
I then get to the notion of staging vs production. [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lionfacelemonface.wordpress.com&blog=2073436&post=280&subd=lionfacelemonface&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I&#8217;m working on a suite of buildout configuration files to use for different circumstances. Having a special buildout for development in a zeo cluster, and another for a single monolithic zope instance (plus useful debug tools already installed) was easy to do and is working well.</p>
<p>I then get to the notion of staging vs production. We stage our plone sites on a separate server, often using the staging instance for content development, debugging, etc. The IP addresses everything is listening on, the ports, etc, may need to vary between staging and production, but everything else has to be identical. </p>
<p>The idea of just running bin/buildout -c staging.cfg on the staging server seemed very elegant.</p>
<p>The production buildout.cfg does a lot. I&#8217;ve got homemade recipes that set up process control, multiple facets of apache (load balancer, ssl), etc. My first idea was to just duplicate the production buildout.cfg, and then modify it as needed, but I figured that would be hard to maintain. There had to be a better way.</p>
<p>So I read through the <a href="http://pypi.python.org/pypi/zc.buildout/">zc.buildout</a> docs, and the <a href="http://pypi.python.org/pypi/zc.buildout/#adding-and-removing-options">Adding And Removing Options</a> section caught my eye.</p>
<p>So say my production buildout.cfg file looks like this:</p>
<pre>
[buildout]
parts = apache
            ssl
            client1
            client2
            zeoserver
... 

[client1]
recipe = plone.recipe.zope2instance
zope2-location = ${zope2:location}
user = me:pass
http-address = 8080

[apache]
recipe = my.apache.recipe
listen = 243.25.21.2:80

[ssl]
recipe = my.ssl.recipe
cert_file = /blah/blah
key = /secure/server.key
httpd_part = apache

... etc, you get the idea
</pre>
<p>And my staging.cfg file looks like this:</p>
<pre>
[buildout]
extends = buildout.cfg

[client1]
http-address = 9090

[apache]
listen = 127.0.0.1:5500
</pre>
<p>So I&#8217;m able to selectively override options in arbitrary parts. This is great. I like the idea of making the config that represents reduced functionality subtract functionality out of the other. Worries of having to maintain two files, or worse, have a dissimilar staging environment are mitigated. </p>
<p>But there&#8217;s a problem. Let&#8217;s say that on staging, I don&#8217;t care about SSL. I need to disable this part somehow, and from what I can tell, at least from the docs (code spelunking pending) there&#8217;s no way to do this.</p>
<p>I tried using the -= syntax that&#8217;s useful for lists of option values:</p>
<pre>
[buildout]
extends = buildout.cfg
parts -= ssl

[client1]
http-address = 9090

[apache]
listen = 127.0.0.1:5500
</pre>
<p>If this had worked, it would have been EPIC. But alas, it did not (should it have worked?). </p>
<p>So I poked around some more and checked with some folks on IRC with no luck. </p>
<p>I sort of solved the problem, by just repeating all the parts and then commenting out the ones I didn&#8217;t want:</p>
<pre>
[buildout]
extends = buildout.cfg
parts = apache
#          ssl
            client1
            client2
            zeoserver

[client1]
http-address = 9090

[apache]
listen = 127.0.0.1:5500
</pre>
<p>This works, but I don&#8217;t like it :P </p>
<p>I wonder if this is intentional, a bug, or just an oversight in zc.buildout. I&#8217;ll dig further when I&#8217;ve got time.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/lionfacelemonface.wordpress.com/280/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/lionfacelemonface.wordpress.com/280/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/lionfacelemonface.wordpress.com/280/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/lionfacelemonface.wordpress.com/280/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/lionfacelemonface.wordpress.com/280/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/lionfacelemonface.wordpress.com/280/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/lionfacelemonface.wordpress.com/280/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/lionfacelemonface.wordpress.com/280/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/lionfacelemonface.wordpress.com/280/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/lionfacelemonface.wordpress.com/280/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lionfacelemonface.wordpress.com&blog=2073436&post=280&subd=lionfacelemonface&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://lionfacelemonface.wordpress.com/2009/10/13/buildout-remove-parts/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5683b763dd1f27ec0c045b66cba43ab0?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jjmojojjmojo</media:title>
		</media:content>
	</item>
		<item>
		<title>Request For Comments: My Plone/Apache Stack</title>
		<link>http://lionfacelemonface.wordpress.com/2009/10/01/rcf-ploneapache-stack/</link>
		<comments>http://lionfacelemonface.wordpress.com/2009/10/01/rcf-ploneapache-stack/#comments</comments>
		<pubDate>Thu, 01 Oct 2009 18:44:12 +0000</pubDate>
		<dc:creator>jjmojojjmojo</dc:creator>
				<category><![CDATA[plone]]></category>

		<guid isPermaLink="false">http://lionfacelemonface.wordpress.com/?p=251</guid>
		<description><![CDATA[I was recently took up the task of engineering my own plone infrastructure. I want to share what I did, and get any feedback I can about the scalability and usefulness of what I&#8217;ve done.
Requirements

SSL – It must be secure while logged-in users are on the site*.

It must NOT be secure for public pages (unless [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lionfacelemonface.wordpress.com&blog=2073436&post=251&subd=lionfacelemonface&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I was recently took up the task of engineering my own plone infrastructure. I want to share what I did, and get any feedback I can about the scalability and usefulness of what I&#8217;ve done.</p>
<h2>Requirements</h2>
<ul>
<li>SSL – It must be secure while logged-in users are on the site*.
<ul>
<li>It must NOT be secure for public pages (unless the user is logged in)</li>
<li>It must force SSL for login pages.</li>
</ul>
</li>
<li>Hide /Plone – the infrastructure must present the user with URLs that don&#8217;t contain the plone instance id.</li>
<li>Admin access – the infrastructure must provide SSL-encrypted access to the root ZMI.</li>
</ul>
<p>* I understand that in recent versions of plone, this isn&#8217;t important to protect the user&#8217;s session cookies, however, I&#8217;m concerned about SSL encryption after login due to the content that will be stored on the site.</p>
<h2>Approach</h2>
<p>I&#8217;m very familiar with the Apache httpd server, so I wanted to leverage that experience as much as possible. I&#8217;m using the <a href="http://httpd.apache.org/docs/2.2/">Apache 2.2.9</a> package that comes with Debian Lenny.</p>
<p>I used <a href="http://plone.org/products/plone/releases/3.3.1">Plone 3.3.1</a> as I was developing this infrastructure, but I don&#8217;t think there&#8217;s anything about it that wouldn&#8217;t work with any version of Plone (as long as it&#8217;s got a virtual host monster).</p>
<p>We&#8217;ve settled on using one IP address (an alias) per Plone stack to keep the sites autonomous. This makes deployment and host registration easier.</p>
<p>I used IP-based Virtual Hosting and <a href="http://httpd.apache.org/docs/2.2/mod/mod_proxy.html">mod_proxy</a> in conjunction with <a href="http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html">mod_proxy_balancer</a>.</p>
<p>I&#8217;m logging to the local disk, and will be setting up a log rotation scheme separately.</p>
<p>Here&#8217;s what it looks like:</p>
<div id="attachment_252" class="wp-caption aligncenter" style="width: 310px"><a href="http://lionfacelemonface.files.wordpress.com/2009/10/plone_infrastructure_current.png"><img src="http://lionfacelemonface.files.wordpress.com/2009/10/plone_infrastructure_current.png?w=300&#038;h=231" alt="Production Plone Infrastructure (Existing Setup)" title="plone_infrastructure_current" width="300" height="231" class="size-medium wp-image-252" /></a><p class="wp-caption-text">Production Plone Infrastructure (Existing Setup)</p></div>
<p>So I&#8217;ve got 3 Zope instances, acting as Zeo clients, on ports 1040, 1041, and 1042. I&#8217;ve heard more is just wasteful and fewer tends to not be enough.</p>
<p>I then have three virtual hosts. One is the load balancer, and back-ends to the Zope instances. It&#8217;s listening on port 8080 (the traditional proxy port, it really could be anything).</p>
<p>The other two virtual hosts are for &quot;public&quot; traffic (port 80), and SSL (port 443). They both back-end via a <a href="http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypass">ProxyPass</a> directive to the balancer virtual host. What&#8217;s different is what they tell the Virtual Host Monster to rewrite the URLs to and the RewriteRules that nudge the browser to use the right virtual host when doing certain actions, like logging in and logging out. Of course, the SSL virtual host is set up to do SSL using my SSL certificate (self-signed for now).</p>
<h2>Configuration</h2>
<p>I&#8217;ve got the config files sort of spread out because I&#8217;m using some buildout recipes I wrote to configure all this stuff,  but here&#8217;s what it looks like all mashed into one file, pretending that you&#8217;re not using my recipes:</p>
<pre>
# httpd.conf for Apache2 - inspired by:  http://www.links.org/?p=264

ServerRoot  /etc/apache2

ServerName  localhost

Listen 127.0.0.1:8080
Listen 127.0.0.1:443
Listen 127.0.0.1:80

PidFile  /var/run/apache2.pid
LockFile /var/lock/apache2/accept.lock

LoadModule alias_module            /usr/lib/apache2/modules/mod_alias.so
LoadModule auth_basic_module       /usr/lib/apache2/modules/mod_auth_basic.so
LoadModule authn_file_module       /usr/lib/apache2/modules/mod_authn_file.so
LoadModule auth_digest_module      /usr/lib/apache2/modules/mod_auth_digest.so
LoadModule authz_user_module       /usr/lib/apache2/modules/mod_authz_user.so
LoadModule authz_host_module       /usr/lib/apache2/modules/mod_authz_host.so
LoadModule authz_groupfile_module  /usr/lib/apache2/modules/mod_authz_groupfile.so
LoadModule dir_module              /usr/lib/apache2/modules/mod_dir.so
LoadModule include_module          /usr/lib/apache2/modules/mod_include.so
LoadModule mime_module             /usr/lib/apache2/modules/mod_mime.so
LoadModule ssl_module              /usr/lib/apache2/modules/mod_ssl.so
LoadModule cgi_module              /usr/lib/apache2/modules/mod_cgi.so
LoadModule rewrite_module          /usr/lib/apache2/modules/mod_rewrite.so
LoadModule headers_module          /usr/lib/apache2/modules/mod_headers.so
LoadModule proxy_module            /usr/lib/apache2/modules/mod_proxy.so
LoadModule proxy_http_module       /usr/lib/apache2/modules/mod_proxy_http.so
LoadModule proxy_balancer_module   /usr/lib/apache2/modules/mod_proxy_balancer.so
#[BUILT-IN] LoadModule log_config_module  modules/mod_log_config.so
#[BUILT-IN] LoadModule logio_module       modules/mod_logio.so

# worker MPM - tuned
# StartServers: initial number of server processes to start
# MaxClients: maximum number of simultaneous client connections
# MinSpareThreads: minimum number of worker threads which are kept spare
# MaxSpareThreads: maximum number of worker threads which are kept spare
# ThreadsPerChild: constant number of worker threads in each server process
# MaxRequestsPerChild: maximum number of requests a server process serves
StartServers           1
MaxClients            16
MinSpareThreads        2
MaxSpareThreads        8
ThreadsPerChild        8
MaxRequestsPerChild    0

User www-data
Group www-data
ServerAdmin me@somehost.com

DirectoryIndex index.html

# The following lines prevent .htaccess and .htpasswd files from being
# viewed by Web clients.
&lt;FilesMatch &quot;^\.ht&quot;&gt;
    Order allow,deny
    Deny from all
    Satisfy All
&lt;/FilesMatch&gt;

DefaultType text/plain

&lt;IfModule mime_module&gt;
    TypesConfig /etc/mime.types
&lt;/IfModule&gt;

# &quot;combinedio&quot; includes actual counts of actual bytes received (%I)
# and sent (%O) - requires the 'mod_logio' module

LogFormat &quot;%h %l %u %t \&quot;%r\&quot; %&gt;s %b \&quot;%{Referer}i\&quot; \&quot;%{User-Agent}i\&quot; %I %O&quot; combinedio
LogFormat &quot;%h %l %u %t \&quot;%r\&quot; %&gt;s %b \&quot;%{Referer}i\&quot; \&quot;%{User-Agent}i\&quot;&quot; combined

ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combinedio

### Zeo Cluster Virtual Host ###################################################
&lt;VirtualHost 127.0.0.1:8080&gt;
    ProxyPreserveHost On

    Header add Set-Cookie &quot;balancer_zopes=route.%{BALANCER_WORKER_ROUTE}e; path=/;&quot;

    ProxyPass / balancer://zeocluster/
    &lt;Proxy balancer://zeocluster&gt;
        BalancerMember http://127.0.0.1:1040 route=client1
        BalancerMember http://127.0.0.1:1041 route=client2
        BalancerMember http://127.0.0.1:1042 route=client3
    &lt;/Proxy&gt;
&lt;/VirtualHost&gt;

### SSL Virtual Host ###########################################################

# example from http://httpd.apache.org/docs/2.2/mod/mod_ssl.html#sslsessioncache
# I think this should be conservative
SSLSessionCache shm:/usr/local/apache/logs/ssl_gcache_data(512000)

&lt;VirtualHost 127.0.0.1:443&gt;
    ServerName localhost

    SSLEngine on

    # this didn't work...
    # SSLCACertificatePath ...

    SSLCertificateKeyFile /home/jj/localhost.key

    # SSLCertificateChainFile /home/jj/localhost.ca-bundle

    SSLCertificateFile /home/jj/localhost.crt

    # ProxyPassInterpolateEnv On
    RedirectMatch /.*logged_out$ http://localhost:80/

    ProxyPass /admin http://localhost:8080/VirtualHostBase/https/localhost:443/VirtualHostRoot/_vh_admin
    ProxyPass / http://localhost:8080/VirtualHostBase/https/localhost:443/plone/VirtualHostRoot/

&lt;/VirtualHost&gt;

### Non-SSL Virtual Host #######################################################

&lt;VirtualHost 127.0.0.1:80&gt;
    ServerName localhost

    ProxyPass / http://localhost:8080/VirtualHostBase/http/localhost:80/plone/VirtualHostRoot/
    RewriteEngine On
    RewriteCond %{HTTP_COOKIE} &quot;__ac=&quot;
    RewriteRule ^(.*) https://%{SERVER_NAME}:443$1 [L]
    RewriteRule (.*)/login_form https://%{SERVER_NAME}:443$1/login_form [R]
&lt;/VirtualHost&gt;
</pre>
<p>I was able to start apache using this file on a fresh Debian Lenny VM (bear in mind you have to <a href="http://www.akadia.com/services/ssh_test_certificate.html">create a self-signed certificate and a private key</a> first)</p>
<p>The command looks like this:</p>
<pre>
   $ sudo /usr/sbin/apache2 -f /path/to/above/httpd.conf &amp;
</pre>
<p>This has to be done as root (using sudo here) since port 80 and 443 are &quot;priveledged&quot; ports.</p>
<p><em>I, of course, have a process management daemon (<a href="http://smarden.sunsite.dk/runit/">runit</a>) that handles this for me (and buildout recipes to configure it), which I will blog about at some point</em></p>
<p><em>I initially had this set up for testing with SSH tunneling (ssh -L) for the ports, and it worked well. This did however affect the setup, primarily I had to change the VHM paths so the URLs would be re-written to the local side of the tunnels, so if I connected like this:</em></p>
<pre>
    $ ssh -L1400:localhost:80 -L1443:localhost:443 jj@vmhost
</pre>
<p><em>The ProxyPass directive for the SSL VH looks like this:</em></p>
<pre>
    ProxyPass /admin http://localhost:8080/VirtualHostBase/https/localhost:1443/VirtualHostRoot/_vh_admin
    ProxyPass / http://localhost:8080/VirtualHostBase/https/localhost:1443/plone/VirtualHostRoot/
</pre>
<p><em>And the ProxyPass directive for the other host: </em></p>
<pre>
    ProxyPass / http://localhost:8080/VirtualHostBase/http/localhost:1400/plone/VirtualHostRoot/
</pre>
<p><em>This way the urls are pointed back through the SSL tunnel.</em></p>
<h2>Discussion</h2>
<p>The general Apache configuration is an amalgam of the /etc/apache2.conf file that came with Debian and some website I found about optimization.</p>
<h3>Cluster</h3>
<p>The Zeo Cluster virtual host uses <a href="http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html">mod_proxy_balancer</a> to round-robin the Zope clients.</p>
<p>To get &quot;sticky&quot; sessions, I set a cookie using <a href="http://httpd.apache.org/docs/2.2/mod/mod_headers.html">mod_headers</a> that holds the &quot;route&quot; of the client. The routs are defined as additional information passed to the BalancerMember, and manifest in an evnironmen variable called &quot;BALANCER_WORKER_ROUTE&quot;.</p>
<p>This way once someone comes into the site, as long as the cookie persists, they will always be proxied to the same client. I opted to let the cookie expire when the user closes their browser since that&#8217;s how Plone is set up by default.</p>
<h3>SSL</h3>
<p>The SSL virtual host is a very straight forward <a href="http://httpd.apache.org/docs/2.2/mod/mod_ssl.html">SSL</a> setup. Since I used a self-signed certificate, I didn&#8217;t need a &quot;ca-bundle&quot; file.</p>
<p>The interesting bit is when I use <a href="http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypass">ProxyPass</a> to route all traffic to the load balancer. Here I utilize the <a href="http://www.zope.org/Documentation/Books/ZopeBook/2_6Edition/VirtualHosting.stx">Virtual Host Monster</a> (standard issue in Zope/Plone these days) to ensure urls are properly re-written to use HTTPS. And while I&#8217;m at it, I also &quot;hide&quot; the plone root (called /plone in my case) so that it looks like https://www.myhost.com/ is the root of the plone site, instead of https://www.myhost.com/plone. Nice.</p>
<p>There&#8217;s another ProxyPass directive that proxies any access to /admin to the load balancer, but also uses some VHM magic to give the user access to the root of Zope, and the core ZMI. This allows access since we&#8217;re proxying / to /plone As a bonus, since this directive only exists in the SSL virtual host, this also &quot;forces&quot; the user to use SSL to do root ZMI stuff, which helps protect the admin password (and gives the administrator warm fuzzies).</p>
<p>I also add a <a href="http://httpd.apache.org/docs/2.2/mod/mod_alias.html#redirectmatch">RedirectMatch</a> directive to push the user over to the non-ssl virtual host when they log out. No sense in keeping them on SSL when there&#8217;s no need.</p>
<h3>Non-SSL HTTP</h3>
<p>Finally, the &quot;public&quot; virtual host. It consists of a ProxyPass directive similar to the one used in the SSL virtual host, except in this case, we&#8217;re rewriting to port 80, standard http. The VHM bits are the same.</p>
<p>The last few directives are rewrite rules to get the user to use SSL if they are logged in, and redirect the user to the SSL virtual host when they click the &quot;log in&quot; link. I&#8217;m sure there&#8217;s more to do to sew this up (like alter the template for the login portlet), but this covers most of the bases.</p>
<h2>The Future</h2>
<div id="attachment_253" class="wp-caption aligncenter" style="width: 310px"><a href="http://lionfacelemonface.files.wordpress.com/2009/10/plone_infrastructure_future.png"><img src="http://lionfacelemonface.files.wordpress.com/2009/10/plone_infrastructure_future.png?w=300&#038;h=231" alt="Production Plone Infrastructure (Future Plans)" title="plone_infrastructure_future" width="300" height="231" class="size-medium wp-image-253" /></a><p class="wp-caption-text">Production Plone Infrastructure (Future Plans)</p></div>
<h3>Logging</h3>
<p>I&#8217;d like to set up separate logging for each virtual host, possibly to syslogd (or some other collective logging solution).</p>
<h3>Virtual Crash Cart Access</h3>
<p>I may add a fourth Zope client. This fourth client wouldn&#8217;t be in the load balancer group and is solely responsible for handling ZMI requests. This was something Joel Burton mentioned at the Advanced Bootcamp, and I&#8217;ve always been keen on it. All the Zope clients can be busy and/or locked up, apache can be hosed, and I can still get to an unhosed client&#8217;s ZMI to try to shut things down or manually fix whatever caused the problem.</p>
<h3>Caching</h3>
<p>I haven&#8217;t included caching in this setup for two reasons:</p>
<ol>
<li>I don&#8217;t like to preemptively optimize, and</li>
<li>Cache-fu does an extraordinarily good job just being there. :)</li>
</ol>
<p>This infrastructure makes it easy to drop in a caching mechanism between the public virtual host and the load balancer virtual host if I need it.</p>
<p>I&#8217;m keen on <a href="http://httpd.apache.org/docs/2.2/mod/mod_cache.html">mod_cache</a>, since it can be loaded easily and keeps with my &quot;do as much as we can in apache&quot; mantra. However, my unscientific tests have shown little benefit from it&#8217;s use. Of course, that was before I came up with this scheme, and I was trying to keep everything in one apache host (which I&#8217;ve dubbed the &quot;one host to unite them, one host to rule them&quot; folly). Stay tuned for more on that.</p>
<p>Even if mod_cache doesn&#8217;t work out, there are still lots of other options, from <a href="http://varnish.projects.linpro.no/">Varnish</a> to <a href="http://www.squid-cache.org/">Squid</a> to <a href="http://www.ietf.org/rfc/rfc1149.txt">PigeonNet</a>.</p>
<h2>Summary</h2>
<p>So here&#8217;s my attempt to do Plone Up Right<sup>TM</sup>, and distill all of the many tutorials that are out there into what I think is one pretty good approach. Please, leave comments and let me know if I&#8217;m out of my mind, or setting myself up for some pain later. All criticism is welcome. If I&#8217;m doing it right, that might be good to hear too :)</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/lionfacelemonface.wordpress.com/251/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/lionfacelemonface.wordpress.com/251/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/lionfacelemonface.wordpress.com/251/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/lionfacelemonface.wordpress.com/251/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/lionfacelemonface.wordpress.com/251/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/lionfacelemonface.wordpress.com/251/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/lionfacelemonface.wordpress.com/251/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/lionfacelemonface.wordpress.com/251/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/lionfacelemonface.wordpress.com/251/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/lionfacelemonface.wordpress.com/251/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lionfacelemonface.wordpress.com&blog=2073436&post=251&subd=lionfacelemonface&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://lionfacelemonface.wordpress.com/2009/10/01/rcf-ploneapache-stack/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5683b763dd1f27ec0c045b66cba43ab0?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jjmojojjmojo</media:title>
		</media:content>

		<media:content url="http://lionfacelemonface.files.wordpress.com/2009/10/plone_infrastructure_current.png?w=300" medium="image">
			<media:title type="html">plone_infrastructure_current</media:title>
		</media:content>

		<media:content url="http://lionfacelemonface.files.wordpress.com/2009/10/plone_infrastructure_future.png?w=300" medium="image">
			<media:title type="html">plone_infrastructure_future</media:title>
		</media:content>
	</item>
		<item>
		<title>Plone User Management: LDAP vs RDBMS vs ?????</title>
		<link>http://lionfacelemonface.wordpress.com/2009/08/06/ldap-vs-rdbms/</link>
		<comments>http://lionfacelemonface.wordpress.com/2009/08/06/ldap-vs-rdbms/#comments</comments>
		<pubDate>Thu, 06 Aug 2009 14:48:39 +0000</pubDate>
		<dc:creator>jjmojojjmojo</dc:creator>
				<category><![CDATA[ldap]]></category>
		<category><![CDATA[plone]]></category>

		<guid isPermaLink="false">http://lionfacelemonface.wordpress.com/?p=230</guid>
		<description><![CDATA[I&#8217;ve been faced with a user requirement I&#8217;ve never had to deal with before, and I&#8217;m on the fence as to what would be the best solution. I&#8217;m looking for war stories, implementation strategies, other ideas, anything that might help me make this decision.
Here are my basic requirements:

Multiple users will log into the following services [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lionfacelemonface.wordpress.com&blog=2073436&post=230&subd=lionfacelemonface&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I&#8217;ve been faced with a user requirement I&#8217;ve never had to deal with before, and I&#8217;m on the fence as to what would be the best solution. I&#8217;m looking for war stories, implementation strategies, other ideas, anything that might help me make this decision.</p>
<p>Here are my basic requirements:</p>
<ul>
<li>Multiple users will log into the following services with the same username/password:
<ul>
<li>Multiple Plone Sites</li>
<li>Samba</li>
</ul>
</li>
<li>Most will be affiliated with the university I work for, but some will be outside collaborators.</li>
<li>We also need to store extra metadata about users:
<ul>
<li>Contact info</li>
<li>Application-specific info</li>
</ul>
</li>
</ul>
<p>Softer requirements:</p>
<ul>
<li>Group/Role Management</li>
<li>
       Softer metadata requirements:</p>
<ul>
<li>Store service info (which plone sites are they on, what Samba file shares do they have access to, etc)
         </li>
<li>Plone site-specific info</li>
</ul>
</li>
</ul>
<p>Our campus uses Active Directory. I&#8217;m able to authenticate against it in Plone and Samba. I have no direct access, however, to the AD or would ever be able to routinely modify it. </p>
<p>This situation is further complicated by the addition of users who are not affiliated with our university. For Plone this isn&#8217;t too big of a deal, but I have yet to figure out how to get Samba to authenticate against multiple sources (e.g. user not in AD? auth against local user). </p>
<p>So I&#8217;ve come up with some proposed scenarios, and have drawn up some diagrams to help convey the ideas.</p>
<h3>Scenario 1</h3>
<p><a href="http://lionfacelemonface.files.wordpress.com/2009/08/ldap-with-central-admin.png"><img src="http://lionfacelemonface.files.wordpress.com/2009/08/ldap-with-central-admin.png?w=300&#038;h=231" alt="LDAP with central admin" title="LDAP with central admin" width="300" height="231" class="aligncenter size-medium wp-image-244" /></a></p>
<p>Here LDAP is used as the central storage for users, groups, roles, etc, and LDAP handles both authentication and authorization. The information is managed via an external management interface. There are many LDAP management tools out there, so this wouldn&#8217;t require any development to that end. </p>
<p>There&#8217;s an alternate way to handle authentication here using Kerberos directly in Plone instead of letting LDAP do it. I added this after talking to a colleague of mine who&#8217;s ultimately in the same boat, and had a lot of trouble getting OpenLDAP to auth over Kerberos.</p>
<h3>Scinerio 2</h3>
<p><a href="http://lionfacelemonface.files.wordpress.com/2009/08/ldap-with-plone-user-management.png"><img src="http://lionfacelemonface.files.wordpress.com/2009/08/ldap-with-plone-user-management.png?w=300&#038;h=231" alt="LDAP with Plone User Management" title="LDAP with Plone User Management" width="300" height="231" class="aligncenter size-medium wp-image-245" /></a></p>
<p>Here the situation is almost the same, except all of the user and group management is handled in Plone. This centralizes the user management to one common web-fronted UI (including Samba). I&#8217;m a little apprehensive of this situation. I don&#8217;t know if I like filesystem access decisions being made by Plone, and I also am not sure how well Plone works with LDAP in a read-write relationship.</p>
<h3>Scinerio 3</h3>
<p><a href="http://lionfacelemonface.files.wordpress.com/2009/08/rdbms-user-manager-push-to-plone.png"><img src="http://lionfacelemonface.files.wordpress.com/2009/08/rdbms-user-manager-push-to-plone.png?w=300&#038;h=231" alt="RDBMS User Manager - Push to Plone" title="RDBMS User Manager - Push to Plone" width="300" height="231" class="aligncenter size-medium wp-image-246" /></a></p>
<p>This option involves building a user management system, and storing all of our user info in a relational database. The user management system pushes out user and group info to the Plone sites via XML-RPC (or some sort of RESTful addon), and separately alters the local userbase and samba config files on the Samba server. </p>
<p>In this scenario, Plone does authentication via a PAS plugin that talks to the AD, and falls back to the RDBMS. Samba authenticates against PAM, which tries AD and falls back to the local system.</p>
<p><em>One caveat here, I haven&#8217;t researched PAM yet to be sure it can handle this.</em></p>
<p>So, I&#8217;m at an impasse. I don&#8217;t know what to do. Avoiding development effort would be nice, but I&#8217;m not afraid of building a solution if I need to. I&#8217;m apprehensive about cramming application-specific data into LDAP, but such things have been done before.</p>
<p>I don&#8217;t know what to do. Any input would be greatly appreciated. :)</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/lionfacelemonface.wordpress.com/230/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/lionfacelemonface.wordpress.com/230/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/lionfacelemonface.wordpress.com/230/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/lionfacelemonface.wordpress.com/230/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/lionfacelemonface.wordpress.com/230/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/lionfacelemonface.wordpress.com/230/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/lionfacelemonface.wordpress.com/230/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/lionfacelemonface.wordpress.com/230/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/lionfacelemonface.wordpress.com/230/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/lionfacelemonface.wordpress.com/230/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lionfacelemonface.wordpress.com&blog=2073436&post=230&subd=lionfacelemonface&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://lionfacelemonface.wordpress.com/2009/08/06/ldap-vs-rdbms/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5683b763dd1f27ec0c045b66cba43ab0?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jjmojojjmojo</media:title>
		</media:content>

		<media:content url="http://lionfacelemonface.files.wordpress.com/2009/08/ldap-with-central-admin.png?w=300" medium="image">
			<media:title type="html">LDAP with central admin</media:title>
		</media:content>

		<media:content url="http://lionfacelemonface.files.wordpress.com/2009/08/ldap-with-plone-user-management.png?w=300" medium="image">
			<media:title type="html">LDAP with Plone User Management</media:title>
		</media:content>

		<media:content url="http://lionfacelemonface.files.wordpress.com/2009/08/rdbms-user-manager-push-to-plone.png?w=300" medium="image">
			<media:title type="html">RDBMS User Manager - Push to Plone</media:title>
		</media:content>
	</item>
		<item>
		<title>jjmojojjmojo &#8211; LIVE! (Plone Symposium Talk Video Availble)</title>
		<link>http://lionfacelemonface.wordpress.com/2009/07/31/jjmojojjmojo-live/</link>
		<comments>http://lionfacelemonface.wordpress.com/2009/07/31/jjmojojjmojo-live/#comments</comments>
		<pubDate>Fri, 31 Jul 2009 14:33:28 +0000</pubDate>
		<dc:creator>jjmojojjmojo</dc:creator>
				<category><![CDATA[plone]]></category>

		<guid isPermaLink="false">http://lionfacelemonface.wordpress.com/?p=238</guid>
		<description><![CDATA[I gave a talk on the &#8220;Great Saga of Content Type Creation in Plone&#8221; (read: AGX sucks but you should still do UML) at the Plone Symposium East 2009 at Penn State a month or two ago. 
The video is available online. Give it a look.
I was scheduled against Nate Aune&#8217;s talk on Deliverance, a [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lionfacelemonface.wordpress.com&blog=2073436&post=238&subd=lionfacelemonface&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I gave a talk on the &#8220;Great Saga of Content Type Creation in Plone&#8221; (read: AGX sucks but you should still do UML) at the Plone Symposium East 2009 at Penn State a month or two ago. </p>
<p>The video is available online. <a href="https://streaming.psu.edu/media/?movieId=8545">Give it a look.</a></p>
<p>I was scheduled against <a href="http://plone.org/events/regional/plone-symposium-east-2009/nate-aune-deliverance">Nate Aune&#8217;s talk on Deliverance</a>, a very hot topic, so I didn&#8217;t get as many people as I&#8217;d hoped, but the audience was great and the whole thing was a lot of fun.  I turned some people onto other ways of making content, and got a ton of really positive and constructive feedback.</p>
<p>This was my first &#8220;major&#8221; presentation, so it was a big learning experience for me, as such, comments and suggestions are highly encouraged. </p>
<p>I&#8217;ll even put up with mild flaming ;) </p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/lionfacelemonface.wordpress.com/238/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/lionfacelemonface.wordpress.com/238/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/lionfacelemonface.wordpress.com/238/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/lionfacelemonface.wordpress.com/238/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/lionfacelemonface.wordpress.com/238/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/lionfacelemonface.wordpress.com/238/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/lionfacelemonface.wordpress.com/238/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/lionfacelemonface.wordpress.com/238/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/lionfacelemonface.wordpress.com/238/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/lionfacelemonface.wordpress.com/238/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lionfacelemonface.wordpress.com&blog=2073436&post=238&subd=lionfacelemonface&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://lionfacelemonface.wordpress.com/2009/07/31/jjmojojjmojo-live/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5683b763dd1f27ec0c045b66cba43ab0?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jjmojojjmojo</media:title>
		</media:content>
	</item>
		<item>
		<title>ZopeSkel: Time For a Rebirth?</title>
		<link>http://lionfacelemonface.wordpress.com/2009/04/21/zopeskel-time-for-a-rebirth/</link>
		<comments>http://lionfacelemonface.wordpress.com/2009/04/21/zopeskel-time-for-a-rebirth/#comments</comments>
		<pubDate>Tue, 21 Apr 2009 15:11:09 +0000</pubDate>
		<dc:creator>jjmojojjmojo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://lionfacelemonface.wordpress.com/?p=218</guid>
		<description><![CDATA[If you&#8217;re skimming this, I&#8217;d like to direct your attention to the poll below
I&#8217;ve been using ZopeSkel and advocating it&#8217;s use for over a year now. I&#8217;ve participated in a major sprint on it, I&#8217;ve taught it to friends and colleagues, and I&#8217;ve come to a conclusion:
ZopeSkel SUCKS.
OK, so it doesn&#8217;t really suck. IMHO, it [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lionfacelemonface.wordpress.com&blog=2073436&post=218&subd=lionfacelemonface&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><em><strong>If you&#8217;re skimming this, I&#8217;d like to direct your attention to the <a href="#zopeskelsprintpoll">poll</a> below</strong></em></p>
<p>I&#8217;ve been using ZopeSkel and advocating it&#8217;s use for over a year now. I&#8217;ve participated in a major sprint on it, I&#8217;ve taught it to friends and colleagues, and I&#8217;ve come to a conclusion:</p>
<p>ZopeSkel SUCKS.</p>
<p>OK, so it doesn&#8217;t <em>really</em> suck. IMHO, it sucks a lot less than ArchGenXML. It&#8217;s still an essential part of my development tool kit, and I can&#8217;t see doing Plone development without it.</p>
<p>I&#8217;m giving a talk about ZopeSkel at the <a href="http://plone.org/events/regional/plone-symposium-east-2009/plone-symposium-east-schedule">Plone Symposium East</a> next month. I&#8217;m going to be advocating ZopeSkel over AGX for content type creation. It will surely be epic. </p>
<p>Back to the suckage: ZopeSkel is not without its flaws. It&#8217;s inherent architecture isn&#8217;t quite <em>right</em>. ZopeSkel took a somewhat specific tool (<a href="http://pythonpaste.org/script/">PasteScript</a>) and abused it to do something outside the realm of the tools purpose. This is bad!</p>
<p>I hit upon some of the shortcomings of ZopeSkel in the <A href="http://lionfacelemonface.wordpress.com/2008/12/09/plone-conference-2008-zopeskel-sprint-reportout/">Sprint Reportout</a> I posted last year. Over the past few months I&#8217;ve been pondering those shortcomings and think it&#8217;s time for a major change.</p>
<p>So here are the major issues:</p>
<ul>
<li>ZopeSkel is out of PasteScript&#8217;s scope</li>
<li>ZopeSkel is impossible to test accurately</li>
<li>ZopeSkel interactive sessions are not easily reproducable</li>
<li>ZopeSkel can&#8217;t respond to user input</li>
<li>ZopeSkel&#8217;s documentation varies from overly adequate to non-existent</li>
<li>ZopeSkel&#8217;s development is severely fragmented.</li>
<li>People complain about ZopeSkel not having a graphical user interface</li>
</ul>
<p>That said, ZopeSkel is still extremely useful and intuitive, it just needs some work by a few dedicated individuals. Ultimately, I&#8217;d like to see the product position itself as the defacto code generation tool in the Plone universe.</p>
<p>So here&#8217;s what I think needs to be done:</p>
<p>We need to re-write zopeskel from the ground up. I like the use of cheetah templates and context-aware commands. I&#8217;d like to see a robust framework for collecting information from the developer, saving it into an INI file (or something else, maybe YAML) and providing a framework where the user interface is decoupled from the data collection and template execution. </p>
<p>There&#8217;s even an opportunity here for an integration point with AGX. </p>
<p>It&#8217;s ambitious, yes, but I think it&#8217;s well within the realm of possibility.</p>
<p>Now we get to the reason why I&#8217;m posting this: I&#8217;m seriously contemplating sprinting on this at Penn State next month. </p>
<p>Due to funding problems I&#8217;m paying my own way to the symposium. I don&#8217;t want to plan a sprint and stay 2 extra nights if nobody is going to sprint with me. I&#8217;m also open to the idea of taking on a sponsor if someone wants to put up some money to see this work progress. </p>
<p>I need to know what <strong>you</strong> think. Please leave a comment, or use the poll below.<br />
<a name="zopeskelsprintpoll"></a><br />
<a name="pd_a_1556747"></a><div class="PDS_Poll" id="PDI_container1556747" style="display:inline-block;"></div><script type="text/javascript" language="javascript" charset="utf-8" src="http://static.polldaddy.com/p/1556747.js"></script>
		<noscript>
		<a href="http://answers.polldaddy.com/poll/1556747/">View This Poll</a><br/><span style="font-size:10px;"><a href="http://www.polldaddy.com">polls</a></span>
		</noscript></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/lionfacelemonface.wordpress.com/218/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/lionfacelemonface.wordpress.com/218/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/lionfacelemonface.wordpress.com/218/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/lionfacelemonface.wordpress.com/218/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/lionfacelemonface.wordpress.com/218/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/lionfacelemonface.wordpress.com/218/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/lionfacelemonface.wordpress.com/218/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/lionfacelemonface.wordpress.com/218/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/lionfacelemonface.wordpress.com/218/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/lionfacelemonface.wordpress.com/218/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lionfacelemonface.wordpress.com&blog=2073436&post=218&subd=lionfacelemonface&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://lionfacelemonface.wordpress.com/2009/04/21/zopeskel-time-for-a-rebirth/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5683b763dd1f27ec0c045b66cba43ab0?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jjmojojjmojo</media:title>
		</media:content>
	</item>
		<item>
		<title>I Used Macros In My Browser Views And Saved A Bunch of Money on My Car Insurance!</title>
		<link>http://lionfacelemonface.wordpress.com/2009/03/02/i-used-macros-in-my-browser-views-and-saved-a-bunch-of-money-on-my-car-insurance/</link>
		<comments>http://lionfacelemonface.wordpress.com/2009/03/02/i-used-macros-in-my-browser-views-and-saved-a-bunch-of-money-on-my-car-insurance/#comments</comments>
		<pubDate>Mon, 02 Mar 2009 20:46:12 +0000</pubDate>
		<dc:creator>jjmojojjmojo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[macro]]></category>
		<category><![CDATA[page templates]]></category>
		<category><![CDATA[plone]]></category>
		<category><![CDATA[tal]]></category>
		<category><![CDATA[zope]]></category>
		<category><![CDATA[zpt]]></category>

		<guid isPermaLink="false">http://lionfacelemonface.wordpress.com/?p=214</guid>
		<description><![CDATA[I had a template with a handful of tables that basically just displayed the same tabular data, just different data sets depending on the table. In case your curious, my data is segregated by workflow state. 
I&#8217;ve had this problem before but in the past I had a skin layer registered too (thanks to ArchGenXML). [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lionfacelemonface.wordpress.com&blog=2073436&post=214&subd=lionfacelemonface&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I had a template with a handful of tables that basically just displayed the same tabular data, just different data sets depending on the table. In case your curious, my data is segregated by workflow state. </p>
<p>I&#8217;ve had this problem before but in the past I had a skin layer registered too (thanks to <a href="http://plone.org/products/archgenxml">ArchGenXML</a>). </p>
<p>Defining macros is pretty easy, the <a href="http://www.zope.org/Documentation/Books/ZopeBook/2_6Edition/AppendixC.stx">Zope Book</a> does a good job of explaining how to define them. It&#8217;s actually easier than it looks. If you don&#8217;t have a need for slots, it basically just comes down to slapping a <code>metal:define-macro</code> attribute into any arbitrary block of code.</p>
<p>Here&#8217;s a quick example:</p>
<pre>
&lt;html&gt;
&lt;body&gt;
    &lt;p metal:define-macro=&quot;title&quot;&gt;
        &lt;span tal:replace=&quot;view/context/Title&quot; /&gt;
    &lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>I&#8217;ve left out most of the usual ZPT window-dressings (like a i18n domain declaration), but I&#8217;ll assume you already know how to do that :). </p>
<p>This is also of course, a pretty stupid example. But it does illustrate an important concept in METAL: when your macro is being expanded, it&#8217;s as if you wrote the code right where the <code>metal:use-macro</code> attribute is used. So any variables that are available to the template that&#8217;s calling the macro are available here.</p>
<p>You have to be careful of this though, because it does limit how much your macro can be re-used. </p>
<p>In the past, because of the skin layer, I was able to drop a ZPT file into my skins directory, and call them like this (assume I put the last macro into a file called &#8220;macros.pt&#8221; in the skins directory along side this template):</p>
<pre>
&lt;html&gt;
&lt;body&gt;
    &lt;p metal:use-macro=&quot;here/macros/macros/title&quot; /&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>I saw a lot of examples where the name of the file itself was used (e.g. <code>here/macros.pt/macros/title</code>), but I don&#8217;t recall doing it that way.</p>
<p>As far as I can tell, this doesn&#8217;t work with templates on the filesystem that aren&#8217;t registered in a skin layer. So when you aren&#8217;t using a skins folder, because you&#8217;ve had the forethought to put that sort of stuff in a policy or theme product, this sort of macro expansion doesn&#8217;t seem to work.</p>
<p>I found a solution to this by accident. I don&#8217;t have my Zope 3 book (the essential <em><a href="http://www.worldcookery.com/">Web Component Development with Zope 3</a></em>) with me today, and was poking around Google aimlessly to solve this problem. I stumbled upon a <a href="http://dc.ubuntu-us.org/bazaar/zope3class/html/lesson07/index.html">page from a hereto unidentified Zope 3 course</a> that showed me what I needed to do. </p>
<p>Zope 3 registers page templates, much like Zope 2/Plone does with the skins concept. But in Zope 3 you do it with ZCML as opposed to the CMF/GenericSetup glue that you need to register a Plone skin layer. </p>
<p>So in a handy <code>configure.zcml</code>  (I put mine in the <code>browser</code> directory of my product), you first need to register the template containing your macros as a browser page:</p>
<pre>
&lt;configure
    xmlns=&quot;http://namespaces.zope.org/zope&quot;
    xmlns:browser=&quot;http://namespaces.zope.org/browser&quot;&gt;
...
    &lt;browser:page
      for=&quot;*&quot;
      name=&quot;my.product.macros&quot;
      template=&quot;macros.pt&quot;
      permission=&quot;zope.Public&quot;
    /&gt;

&lt;/configure&gt;
</pre>
<p>Note that I since my macro file (<code>macros.pt</code>) is in the same directory as my <code>configure.zcml</code>, I didn&#8217;t have to specify any sort of relative path information in the <code>template</code> attribute.</p>
<p>Since the macro template is being registered like any other browser view, you can specify a particular interface that is only allowed to use it, using the <code>for</code> attribute. Likewise, you can set a specific permission that will restrict access to the macros using the <code>permission</code> attribute. I haven&#8217;t tested either attribute with a browser page that&#8217;s being used for macros, so I don&#8217;t know what the expected behavior is.</p>
<p>OK, so with the ZCML tag above added to <code>configure.zcml</code> and a quick restart of the server (I had trouble with <a href="http://pypi.python.org/pypi/plone.reload">plone.reload</a> in this case, FYI), any macros in <code>macros.pt</code> are available, to any view on any content type that feels inclined to use them.</p>
<p>To access the macros within a browser view/page (or viewlet, etc), the syntax is similar to what it was in the &#8220;skins layer&#8221; scenario mentioned earlier, but it&#8217;s very Zope 3:</p>
<pre>
&lt;html&gt;
&lt;body&gt;
    &lt;p metal:use-macro=&quot;view/context/@@my.product.macros/title&quot; /&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>You access the macro by getting the browser page defined in the ZCML above applied to the current context. That&#8217;s it.</p>
<p>So to summarize: you can use a browser page like a sort of template/code snippet resource. And as a bonus, said resource can contain METAL macros. METAL macros are a nice way to clean up your code, enforce DRY, and reduce bugs.</p>
<p><em>Side Note:</em><br />
I&#8217;ve also come to realize that the same <code>@@viewname</code> syntax works to apply a view to an object inside of a page template. This is a natural predecessor to the macro stuff I was just talking about, but I didn&#8217;t realize it was possible until now. Whoo-hoo!</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/lionfacelemonface.wordpress.com/214/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/lionfacelemonface.wordpress.com/214/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/lionfacelemonface.wordpress.com/214/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/lionfacelemonface.wordpress.com/214/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/lionfacelemonface.wordpress.com/214/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/lionfacelemonface.wordpress.com/214/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/lionfacelemonface.wordpress.com/214/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/lionfacelemonface.wordpress.com/214/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/lionfacelemonface.wordpress.com/214/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/lionfacelemonface.wordpress.com/214/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lionfacelemonface.wordpress.com&blog=2073436&post=214&subd=lionfacelemonface&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://lionfacelemonface.wordpress.com/2009/03/02/i-used-macros-in-my-browser-views-and-saved-a-bunch-of-money-on-my-car-insurance/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5683b763dd1f27ec0c045b66cba43ab0?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jjmojojjmojo</media:title>
		</media:content>
	</item>
		<item>
		<title>Adventures In Theming &#8211; Followup</title>
		<link>http://lionfacelemonface.wordpress.com/2009/02/04/adventures-in-theming-followup/</link>
		<comments>http://lionfacelemonface.wordpress.com/2009/02/04/adventures-in-theming-followup/#comments</comments>
		<pubDate>Thu, 05 Feb 2009 02:59:02 +0000</pubDate>
		<dc:creator>jjmojojjmojo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://lionfacelemonface.wordpress.com/?p=198</guid>
		<description><![CDATA[I wrote the Adventures In Theming series about a month ago as I was working my way through developing my first theme product for Plone 3. Initally it was a very long single blog post, but I figured it would be more useful to people if I split it up and released it over the [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lionfacelemonface.wordpress.com&blog=2073436&post=198&subd=lionfacelemonface&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I wrote the <a href="http://lionfacelemonface.wordpress.com/tutorials/adventures-in-theming-the-complete-saga/">Adventures In Theming</a> series about a month ago as I was working my way through developing my first theme product for Plone 3. Initally it was a very long single blog post, but I figured it would be more useful to people if I split it up and released it over the course of a couple of weeks.</p>
<p>WordPress <a href="http://dev.plone.org/plone.org/ticket/1120">didn&#8217;t seem to like that after the first few posts</a>, at least in the atom feed, so I think I lost a lot of Planet Plone views. Sorry if anybody was following along. :) It looks like google is helping people find the posts, so it&#8217;s not soo bad, and anyway, I doubt anybody was waiting with bated breath for the each installment :P. It&#8217;s pretty hard to read if you just happen upon the individual articles, which sucks.</p>
<p>I&#8217;ve just put all of the posts into <a href="http://lionfacelemonface.wordpress.com/tutorials/adventures-in-theming-the-complete-saga/">one page</a> as promised. If you&#8217;ve done themeing, or want to do theming, please take a gander. As with anything I write, I&#8217;m always open to suggestions, corrections, etc. I got some editing help from Rob Lineberger before I broke my original post up into a series, which I think helped the series a lot (so buy him a beer and tell him to get a blog already if you see him&#8230; or ever meet him). I haven&#8217;t audited the code in a while, that&#8217;s on my todo list, but I can always use help with that. Getting to the point: be a good <em>blogospherizan</em> and give me some feedback :)</p>
<p>So anyway, enough epilouge-ing, there&#8217;s some new developments that need to be at least documented (does anyone actually read this far down into a blog post?) to help wayword googlers and stranded plonistas learn from my mistakes.</p>
<p>Recall my original implementation idea from <a href="http://lionfacelemonface.wordpress.com/2009/01/26/adventures-in-theming-the-beginning/">my first post</a>: </p>
<blockquote><p>
I thought that because viewlets were registered providers, I could easily get the stock plone viewlets I wanted to re-organize to show up in my new viewlet by simply using the provider prefix in TALES expressions in my page template.
</p></blockquote>
<p>It just didn&#8217;t work. I was met with weird errors, and spent a lot of time trying to work around them (I just <em>couldn&#8217;t</em> blame Plone, it had to me my fault)</p>
<p>I didn&#8217;t do much digging until after my theme was complete. I traced the problem down to the stock viewlets, but didn&#8217;t realize that the problem was actually <em>with</em> the stock viewlets. </p>
<p>I ranted a bit about the situation during a psuedo-pair programming session I was having with my coworker, Mark Biggers (who also doesn&#8217;t have a blog yet). I was putting the finishing touches on my theme product at the time, and showing Mark what I did.</p>
<p>I was a little peeved that something that <em>should</em> work, going by every book and piece of documentation I had, not to mention logic, just <em>didn&#8217;t</em> work. I also felt stupid because I didn&#8217;t take the time to really understand what was wrong. Instead I wasted <em>days</em> trying to work around it, and spent even more time implementing my own viewlet manager. </p>
<p>Mark agreed that the situation seemed really odd, and suggested I take a look for some known Plone bugs to see if anyone noticed the problem before. In my haste and fustration, I never thought to look into the <a href="http://dev.plone.org/plone">plone trac</a> to see if somebody had submitted a bug ticket with the same problem I had. Taking Mark&#8217;s advice, I gave it a shot, and within seconds, in the first search I did, I found a <a href="http://dev.plone.org/plone/ticket/7868">bug ticket</a> that was <em>precisely</em> the problem I was having. And the person who posted the bug was dilligent (and estute!) enough to figure out how to fix the bug and submit a patch. Score!</p>
<p>But the celebration was short lived. Upon further inspection, I realized the ticket was marked <em>fixed</em>. But wait, the bug also says &#8220;milestone changed from 3.x to 4.0&#8243;. This was just confusing, so I did some digging.</p>
<p>I was able to verify that the bug was truely fixed (<a href="http://dev.plone.org/plone/changeset/21497">6 months prior</a>), and that it truely <a href="http://dev.plone.org/plone/browser/plone.app.layout/tags/1.1.7/plone/app/layout/viewlets/common.py#L23">wasn&#8217;t in the latest release</a> of plone.app.layout. That made no sense to me, especially given that the change was <em><strong>5 characters</strong></em>.
</p>
<p>I figured this warrented a post to the plone core mailing list, just to see what the reasoning was. <a href="http://plone.org/support/forums#nabble-f293351">I didn&#8217;t really get the response I wanted</a>.</p>
<p><em>Note to self:</em> I need to follow up on this. If there is anything I can do to help out, I really need to put some effort into finding out how. I&#8217;m not sure how releases work in Plone, so I didn&#8217;t want to volunteer, but in retrospect I should have said &#8220;So how do <em>I</em> do that&#8221; instead of &#8220;can that someone be me&#8221; :P</p>
<p>In case it&#8217;s not obvious, this small change would have prevented the need for me to create my own viewlet manager. It&#8217;s probably best, in the long run, that I went ahead and built my own viewlet manager. I&#8217;ve learned a lot, I&#8217;ve got a more stable and flexible means of customizing Plone, and I was able to document it pretty thouroughly, which (hopefully) will help somebody (most likely myself) someday.</p>
<p>In spite of that most <em>Excellent Adventure</em> (surely not a <em>Bogus Journey</em>), <strong>bugs suck</strong>. When you find out that days and days of fustration could have been avoided by such a minor change, it really makes you want to do whatever you can to avoid (and fix!) bugs in general.</p>
<h2>Future Plans</h2>
<p>So since I wrote my initial post my theme has been deployed in a live site and it&#8217;s gone over well. It&#8217;s holding up to multi-browser scrutiny in a very hostile environment (research lab at a university :)).</p>
<p>One thing I failed to document before, however, is that this first deployment is also the first time I extended my theme. This worked surprisingly well. The only customization I&#8217;ve had to do so far is change the logo, but between skin-layer changes and zcml overrides I don&#8217;t think making major changes to the way it looks without changing the layout should be pretty easy, and I think more drastic re-arrangement wouldn&#8217;t be much harder.</p>
<p>So I plan to document that in a blog post in the near future.</p>
<p>I also want to see how well my theme plays with <a href="http://pypi.python.org/pypi/Products.CSSManager">CSSManager</a>, and see how I can integrate with it, or add my own tool that&#8217;s specific to my applicaitons and base theme.</p>
<p>One thing I didn&#8217;t do much of that I&#8217;ll need to expand on is writing my own viewlets. The theme I created will be used in conjunction with a suite of applications I&#8217;m co-developing. You may have noticed I left a large empty space in my theme on the upper left-hand side. I plan to put a context-aware viewlet there with application-specific information and links to help and common resources. It should be pretty cool, I&#8217;ll document it here on my blog when I get to writing it.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/lionfacelemonface.wordpress.com/198/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/lionfacelemonface.wordpress.com/198/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/lionfacelemonface.wordpress.com/198/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/lionfacelemonface.wordpress.com/198/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/lionfacelemonface.wordpress.com/198/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/lionfacelemonface.wordpress.com/198/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/lionfacelemonface.wordpress.com/198/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/lionfacelemonface.wordpress.com/198/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/lionfacelemonface.wordpress.com/198/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/lionfacelemonface.wordpress.com/198/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lionfacelemonface.wordpress.com&blog=2073436&post=198&subd=lionfacelemonface&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://lionfacelemonface.wordpress.com/2009/02/04/adventures-in-theming-followup/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5683b763dd1f27ec0c045b66cba43ab0?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jjmojojjmojo</media:title>
		</media:content>
	</item>
		<item>
		<title>Adventures In Theming: The Final Chapter</title>
		<link>http://lionfacelemonface.wordpress.com/2009/02/03/adventures-in-theming-the-final-chapter/</link>
		<comments>http://lionfacelemonface.wordpress.com/2009/02/03/adventures-in-theming-the-final-chapter/#comments</comments>
		<pubDate>Tue, 03 Feb 2009 06:00:12 +0000</pubDate>
		<dc:creator>jjmojojjmojo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[plone theme tutorial design css]]></category>

		<guid isPermaLink="false">http://lionfacelemonface.wordpress.com/?p=127</guid>
		<description><![CDATA[This is the seventh post in a short series about the ideas, trials and tribulations of my first theme product. I’ll be posting the whole story in one place when the series is complete.
I&#8217;m Not Done Yet
Now that the theme is finished, there are a few more steps before I can consider it truly complete.


Does [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lionfacelemonface.wordpress.com&blog=2073436&post=127&subd=lionfacelemonface&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><em>This is the seventh post in a short series about the ideas, trials and tribulations of my first theme product. I’ll be posting the <a href="http://lionfacelemonface.wordpress.com/tutorials/adventures-in-theming-the-complete-saga/">whole story</a> in one place when the series is complete.</em></p>
<h3>I&#8217;m Not Done Yet</h3>
<p>Now that the theme is finished, there are a few more steps before I can consider it truly complete.</p>
<ol>
<li>
<p><strong>Does it work in IE?</strong> <em>Or FireFox, or Safari, or Konqurer or Your Cellphone or a screen reader&#8230;</em>. It&#8217;s important to test your theme across a few browsers. Chances are if you follow the Plone Way<sup>TM</sup>, you won&#8217;t have too much trouble, but it&#8217;s always a good idea. This goes beyond the usual web designer&#8217;s perogative. You&#8217;ve opted to use a CMS that prides itself in graceful fallbacks, cross-browser compatibility and accessability. Make sure you&#8217;re not stomping all over those ends just so you can have a &quot;rad&quot; theme.</p>
</li>
<li>
<p><strong>Is anything missing?</strong> Much like how I missed the footer in my theme, there are other bits and pieces of Plone that your theme may not have taken into account. A good example of this is the calendar portlet. There are some very specific CSS rules that you may have to override to get your theme to take affect.</p>
<p>It&#8217;s a good idea to add all the stock portlets, and install any third-party products you plan to use with your site into your theme product&#8217;s development buildout. Poke around the site, and make sure you didn&#8217;t miss anything. It may be the product or portlet developer&#8217;s fault, but it&#8217;s up to you as the theme creator to cover all the bases.</p>
</li>
<li>
<p><strong>Can you change themes?</strong> There is a theme control panel configlet (<a href="http://localhost:8080/plone/@@skins-controlpanel">http://localhost:8080/plone/@@skins-controlpanel</a>) that has a dropdown list allowing you to select the current theme. You should be able to select the &quot;Default Plone&quot; theme without any lingering effects.</p>
<p><em>You will however, notice some immediate effects :). Reload the page, restart the server and poke around again like you did earlier just to be sure.</em></p>
<p>If you find reminates, they can probably be attributed to forgetting to associate a stylesheet or viewlet customization specifically with your theme.</p>
</li>
<li>
<p><strong>Does it uninstall?</strong> If you do more than add theme-specific viewlets, make sure that nothing breaks when you uninstall your theme. This is especially important if you ever want to distribute your theme to other people, but even if it&#8217;s for internal use only, it will make you happier in the long run.
    </p>
</li>
</ol>
<p>Walking through these steps myself, here&#8217;s what I discovered.</p>
<h4>It looks funny in IE</h4>
<p>A preliminary glance in IE 6 (installed on my Ubuntu Hardy system via <a href="http://www.tatanka.com.br/ies4linux/page/Main_Page">IEs4Linux</a>) showed some messy bits under my theme relating to portlets, but the same issues come up with the default Plone theme, so I&#8217;m counting this one passable.</p>
<p>I&#8217;m in the process of getting a new windows VM up and running so I can test &quot;real&quot; IE6 and IE7 (and probably IE8-beta just for kicks)</p>
<p><em>I need to dig a bit and see if IE6 compatibility is a priority for Plone, and see if there are any bugs relating to this issue (I&#8217;m sure there are, but I should verify)</em></p>
<h4>Odd Portal Rows</h4>
<p>I hadn&#8217;t noticed it before, but there are special odd/even classes for portlet content like there are for listing tables (e.g. folder contents). I added a bunch of portlets to my layout, and added some events and recent changes. I tried to cover as many bases as I could for the sake of throughness.</p>
<p>After adding all the content, I noticed that the portal footers and headers looked nice, but the content seemed a bit messy, as each item in the events and recent changes portlets would run together. I investigated a bit and found that there was <code>class=&quot;portletItem even&quot;</code> and <code>class=&quot;portletItem odd&quot;</code> attributes specified in the portlet content. </p>
<p>To account for this, I added the following to my CSS</p>
<p><strong>src/my.theme/my/theme/browser/stylesheets/main.css</strong></p>
<pre>
...
.portletItem.even {
    background-color: #ecf0f5;
}
...
</pre>
<h4>Uninstallability</h4>
<p>In testing the theme, I found out that the theme itself isn&#8217;t &quot;deleted&quot; when the product is uninstalled, inspite of the fact that all of it&#8217;s required resources and viewlets are no longer available.</p>
<p>And worse, the theme is still set as the default theme. This leaves the site in a more-or-less broken state to the end user, who may not realize they need to change the default theme to a theme that&#8217;s actually available still. And the theme stays in the dropdown list.</p>
<p>To fix this requires setting up an uninstall profile. This is documented on <a href="http://plone.org/documentation/tutorial/genericsetup/creating-an-uninstall-profile">plone.org</a>, but I&#8217;ll show you what I did in my case.</p>
<p>First, I created a new directory called <code>uninstall</code> in my <code>profiles</code> directory.</p>
<pre>
$ cd ~/my.theme/src/my/theme/profiles
$ mkdir uninstall
</pre>
<p>Then I added the XML files that made up the profile. It&#8217;s basically what I did in the <code>default</code> profile, but with <code>remove=&quot;True&quot;</code> added to the bits I wanted to remove, and the default theme changed back to a sane default.</p>
<p><strong>src/my.theme/my/theme/profiles/uninstall/skins.xml</strong></p>
<pre>
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;object name=&quot;portal_skins&quot;
   default_skin=&quot;Plone Default&quot;&gt;

 &lt;object name=&quot;my_theme_custom_images&quot; remove=&quot;True&quot;/&gt;
 &lt;object name=&quot;my_theme_custom_templates&quot; remove=&quot;True&quot;/&gt;
 &lt;object name=&quot;my_theme_styles&quot; remove=&quot;True&quot;/&gt;

 &lt;skin-path name=&quot;My Theme&quot; based-on=&quot;Plone Default&quot; remove=&quot;True&quot;&gt;
  &lt;layer name=&quot;my_theme_custom_images&quot;
     insert-after=&quot;custom&quot; remove=&quot;True&quot;/&gt;
  &lt;layer name=&quot;my_theme_custom_templates&quot;
     insert-after=&quot;my_theme_custom_images&quot; remove=&quot;True&quot;/&gt;
  &lt;layer name=&quot;my_theme_styles&quot;
     insert-after=&quot;my_theme_custom_templates&quot; remove=&quot;True&quot;/&gt;
 &lt;/skin-path&gt;

&lt;/object&gt;
</pre>
<p>You need just enough information to let GenericSetup find the configuration bits that need to be removed, so you may notice that I removed some of the extra attributes from this <code>skins.xml</code>.</p>
<p>Then, I had to wire up the profile. This is a multi-part process, that starts with registering the profile with ZCML</p>
<p><strong>src/my.theme/my/theme/profiles.zcml</strong></p>
<pre>
...
  &lt;genericsetup:registerProfile
      name=&quot;uninstall&quot;
      title=&quot;My Theme - Uninstall&quot;
      directory=&quot;profiles/uninstall&quot;
      description='&quot;My Theme&quot; Plone theme. - UNINSTALL'
      provides=&quot;Products.GenericSetup.interfaces.EXTENSION&quot;
      /&gt;
...
</pre>
<p>This is esentially the same as the other <code>&lt;genericsetup:registerProfile&gt;</code> tag that ZopeSkel already put into <code>profiles.zcml</code> for you, modified slightly to reflect the location and name of the new profile.</p>
<p>Now I&#8217;ve got a brand new GenericSetup profile, but no way to invoke it using the add/remove products interface that my users will be acustomed to. This means I&#8217;ll have to apply the uninstall profile with python code.</p>
<p>This is accomplished by bringing back an old-school, but still effective, method of controlling what happens when Plone installs or uninstalls a product: <code>Extensions/install.py</code></p>
<p>The <code>Extensions</code> directory is not created for us by ZopeSkel, so we need to create it ourselves.</p>
<pre>
$ cd ~/my.theme/src/my/theme/
$ mkdir Extensions
</pre>
<p>Then we need to create the <code>install.py</code> file. This file can contain 3 functions: <code>install()</code>, <code>uninstall()</code>, and <code>upgrade()</code>. Each function will only be called if it&#8217;s present, and can basically do whatever you want. This is a very straight-forward way to add in some &quot;magic&quot; activity upon install, do some migration upon upgrade, or as in our case, tidy up when the product is being removed. It&#8217;s definately the go-to proceedure when GenericSetup doesn&#8217;t do what you want, or time prevents you from implementing a GenericSetup-based solution effectively.</p>
<p><strong>src/my.theme/my/theme/Extensions/install.py</strong></p>
<pre>
from Products.CMFCore.utils import getToolByName

def uninstall(portal):
    setup_tool = getToolByName(portal, 'portal_setup')
    setup_tool.setImportContext('profile-my.theme:uninstall')
    setup_tool.runAllImportSteps()
    return &quot;Ran all uninstall steps.&quot;
</pre>
<p>You can find out more about the <code>setup_tool</code>&#8217;s API by inspecting it with <a href="http://pypi.python.org/pypi/Products.DocFinderTab/1.0.2">DocFinderTab</a> or looking at the source code (in <code>parts/plone/CMFQuickInstallerTool</code>)</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/lionfacelemonface.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/lionfacelemonface.wordpress.com/127/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/lionfacelemonface.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/lionfacelemonface.wordpress.com/127/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/lionfacelemonface.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/lionfacelemonface.wordpress.com/127/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/lionfacelemonface.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/lionfacelemonface.wordpress.com/127/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/lionfacelemonface.wordpress.com/127/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/lionfacelemonface.wordpress.com/127/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lionfacelemonface.wordpress.com&blog=2073436&post=127&subd=lionfacelemonface&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://lionfacelemonface.wordpress.com/2009/02/03/adventures-in-theming-the-final-chapter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5683b763dd1f27ec0c045b66cba43ab0?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jjmojojjmojo</media:title>
		</media:content>
	</item>
		<item>
		<title>Adventures In Theming: Overriding A Stock Viewlet</title>
		<link>http://lionfacelemonface.wordpress.com/2009/02/02/adventures-in-theming-overriding-a-stock-viewlet/</link>
		<comments>http://lionfacelemonface.wordpress.com/2009/02/02/adventures-in-theming-overriding-a-stock-viewlet/#comments</comments>
		<pubDate>Mon, 02 Feb 2009 06:00:25 +0000</pubDate>
		<dc:creator>jjmojojjmojo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[plone theme tutorial design css]]></category>

		<guid isPermaLink="false">http://lionfacelemonface.wordpress.com/?p=126</guid>
		<description><![CDATA[This is the sixth post in a short series about the ideas, trials and tribulations of my first theme product. I’ll be posting the whole story in one place when the series is complete.
I Forgot  The Footer! (Overriding Stock Viewlets)
I&#8217;ve managed to get all of the styling nailed down. Here&#8217;s what it looks like [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lionfacelemonface.wordpress.com&blog=2073436&post=126&subd=lionfacelemonface&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><em>This is the sixth post in a short series about the ideas, trials and tribulations of my first theme product. I’ll be posting the <a href="http://lionfacelemonface.wordpress.com/tutorials/adventures-in-theming-the-complete-saga/">whole story</a> in one place when the series is complete.</em></p>
<h3>I Forgot  The Footer! (Overriding Stock Viewlets)</h3>
<p>I&#8217;ve managed to get all of the styling nailed down. Here&#8217;s what it looks like now:   </p>
<div id="attachment_109" class="wp-caption aligncenter" style="width: 310px"><a href="http://lionfacelemonface.files.wordpress.com/2009/01/theming-second-pass-css.png"><img src="http://lionfacelemonface.files.wordpress.com/2009/01/theming-second-pass-css.png?w=300&#038;h=248" alt="Looking Good.... But wait!" title="Looking Good.... But wait!" width="300" height="248" class="size-medium wp-image-109" /></a><p class="wp-caption-text">Looking Good.... But wait!</p></div>
<p>So here&#8217;s what&#8217;s different: The extra viewlets are gone. I&#8217;ve added in all of the background images. I&#8217;ve styled the portlets. It&#8217;s become obvious that I&#8217;m  going to have to do some more specific customization of the calendar portlet, but that&#8217;s not a big deal right now.</p>
<p>You may have been wondering what I did with the search viewlet that&#8217;s normally up in the right hand corner. In this screenshot, you can see I opted to use the search portlet instead&#8230; and yeah, that was my plan all along. :)</p>
<p>In addition, I&#8217;ve added my own copy of the modern plone logo, with a transparent background. I accomplished this by putting a file called &quot;logo.jpg&quot; into <code>/src/my.theme/my/theme/skins/my_theme_custom_images</code>.</p>
<p>Here&#8217;s the CSS as it stands now:</p>
<p><strong>src/my.theme/my/theme/browser/stylesheets/main.css</strong></p>
<pre>
/* Stylesheet for the 'My Theme' Plone theme */

body {
    background-color: #cfd8e5;
}

#siice_header #main {
    height: 90px;
}

#my_header #left_side {
    float: left;
    clear: left;
    height: 90px;
    width: 50%;
    background-image: url("++resource++my.theme.images/left_background.png");
    background-repeat: no-repeat;
}

#my_header #right_side {
    float: right;
    clear: right;
    height: 90px;
    width: 50%;
    background-repeat: no-repeat;
    background-position: right;
    background-image: url("++resource++my.theme.images/right_background.png");
}

#my_header #personal_bar_sections {
    clear: both;
}

#my_header #personal_bar {
    float: right;
    clear: right;
}

#my_header #sections {
    float: left;
    clear: left;
}

#my_header #crumbtrail {
    clear: both;
}

#my_header #personal_bar_sections {
    background-image: url("++resource++my.theme.images/tabs_background.png");
    height: 20px;
    background-repeat: repeat-x;
    background-color: #b7c4c8;
    border-bottom: 1px solid #93a7ac;
    background-position: top;
}
/************* Override Plone Styles **********/

/* Logo */
#portal-logo {
    float: right;
    padding-right: 5px;
}

/* Site Actions */
#portal-siteactions {
    float: left;
}

#portal-siteactions li a, #portal-siteactions li a:hover, #portal-siteactions li a:active, #portal-siteactions li a:visited {
    border: 0px;
    color: #5f8dd3;
    background-color: transparent;
}

/* Top Sections */
#portal-globalnav {
    padding: 0px;
    font-size: 110%;
}

#portal-globalnav li.selected a {
    color: #000000;
    background-color: transparent;
    border: none;
}

#portal-globalnav li.plain a {
    color: #000000;
    background-color: transparent;
}

/* get rid of the left border for the first tab, the index page */
#portaltab-index_html {
    border: 0px !important;
}

#portal-globalnav li {
    border: 0px;
    border-left: 1px solid #000000;
}
#portal-globalnav li a {
    border: 0px;
    color: #000000;
    background-color: transparent;
    margin: 0px;
}

/* Personal Bar */
#portal-personaltools {
    padding: 0px;
    padding-right: 1em;
    background-color: transparent;
    border: 0px;
}

/* Bread Crumbs Nav */
#portal-breadcrumbs {
    background-color: #b7c4c8;
    border-bottom: none;
}

#portal-breadcrumbs a {
    color: #4b93ff;
}

/* "Green" action tabs */
.contentViews li a {
    background-color: #e3f4d7;
}

/* Portlets */
.portletHeader, .portletFooter, .portletItem, .portlet {
    border: 0px !important;
}

.portletHeader {
    text-transform: none;
    font-size: 110%;
}

.portletHeader, .portletFooter {
    background-color: #b5c3d7 !important;
}

.portletItem {
    background-color: #dfe5ee;
}

.portletHeader a, .portletFooter a, .portletItem a {
    border: 0px;
}

/* Page Body */
.documentContent {
    border: 1px #447821 solid;
}
</pre>
<p>Considering the amount of CSS that Plone uses, this isn&#8217;t that much to override. I&#8217;m sure if I was delving deepter into the content area it might be a little more cumbersome, but it looks like the core theme is pretty well built for utilizing CSS to it&#8217;s fulllest.</p>
<p>A nice bonus of this layout: it works with large fonts. I haven&#8217;t tested it in Internet Explorer or Safari yet, but I can hit ctrl-+ over and over with no ill effects. w00t!</p>
<p>You&#8217;ll notice, of course, that I&#8217;ve missed the portal footer, the bit just above the colophon at the bottom of the page. I styled it in my mockup but have neglected to give it any attention in my theme product. Now is the time.</p>
<p>I don&#8217;t like the idea of just slapping a background on the div around the footer via CSS. I like my styles to be flexible, and if the font size got beyond a certain point, the text would exceed the height of the background. That&#8217;s just messy. There&#8217;s also the chance that I may need to put some static content inside of the portal footer that I don&#8217;t want overriden by any user-configurable options. Examples include a special copywright notice or link to a help center.</p>
<p>Normally, this isn&#8217;t a big deal. In my application, however, I may have people with the Manager role running around on the sites that use this theme that aren&#8217;t under my jurisdiction.</p>
<p>What this all means is that I need a new viewlet to replace the portal footer viewlet. Luckily, executing such a task is easier than explaining why I need to do it :).</p>
<p>Anyway, overriding a viewlet can be accomplished entirely in ZCML if you want. The same goes for viewlet managers, in theory at least. But, if you need it, you have the option to produce a class that can give you more flexibility.</p>
<p>The <a href="http://plone.org/documentation/manual/theme-reference/elements/viewlet/override/overview">Theme Reference</a> has a good overview of what you need to do. Here&#8217;s what my <code>&lt;browser:viewlet&gt;</code> tag looks like:</p>
<p><strong>src/my.theme/my/theme/browser/configure.zcml</strong></p>
<pre>
...
  &lt;browser:viewlet
        name=&quot;plone.footer&quot;
        for=&quot;*&quot;
        manager=&quot;plone.app.layout.viewlets.interfaces.IPortalFooter&quot;
        template=&quot;footer.pt&quot;
        permission=&quot;zope.Public&quot;
        layer=&quot;.interfaces.IThemeSpecific&quot;
        /&gt;
...
</pre>
<p>With this configuration, I just had to drop a <code>footer.pt</code> file into my <code>browser</code> directory and <em>bickety-bam</em>, my footer shows up!</p>
<p>Note that I made sure to specify a layer so my override will only be enabled when my theme is in effect.</p>
<p>I took a look at the footer template that comes with Plone to be sure nothing special was happening. No worries there, so in my <code>footer.pt</code>, I was free to code it how I wished. I did borrow the date/time stuff to display the copywright year, however. Clever!</p>
<p>For the sake of illustration, in my examples here I&#8217;ve pulled the full copywright from Plone&#8217;s storck footer template. Here&#8217;s what it looks like:</p>
<p><strong>src/my.theme/my/theme/browser/footer.pt</strong></p>
<pre>
&lt;div id=&quot;my_footer&quot;&gt;
    &lt;div id=&quot;my_copywright&quot;&gt;
        &lt;p&gt;
    &lt;span i18n:translate=&quot;description_copyright&quot; tal:omit-tag=&quot;&quot;&gt;
    The
    &lt;span i18n:name=&quot;plonecms&quot; tal:omit-tag=&quot;&quot;&gt;
        &lt;a href=&quot;http://plone.org&quot; i18n:translate=&quot;label_plone_cms&quot;&gt;Plone&lt;sup&gt;&amp;reg;&lt;/sup&gt; CMS &amp;mdash; Open Source Content Management System&lt;/a&gt;
    &lt;/span&gt;
    is
    &lt;acronym title=&quot;Copyright&quot; i18n:name=&quot;copyright&quot; i18n:attributes=&quot;title title_copyright;&quot;&gt;&amp;copy;&lt;/acronym&gt;
    2000-&lt;span i18n:name=&quot;current_year&quot;
               tal:omit-tag=&quot;&quot;
               tal:define=&quot;now modules/DateTime/DateTime&quot;
               tal:content=&quot;now/year&quot; /&gt;
    by the
    &lt;span i18n:name=&quot;plonefoundation&quot; tal:omit-tag=&quot;&quot;&gt;
        &lt;a href=&quot;http://plone.org/foundation&quot; i18n:translate=&quot;label_plone_foundation&quot;&gt;Plone Foundation&lt;/a&gt;&lt;/span&gt;
    et al.
    &lt;/span&gt;
&lt;/p&gt;

&lt;p&gt;
    &lt;span i18n:translate=&quot;description_trademark&quot; tal:omit-tag=&quot;&quot;&gt;
    Plone&lt;sup&gt;&amp;reg;&lt;/sup&gt; and the Plone logo are registered trademarks of the
        &lt;span i18n:name=&quot;plonefoundation&quot; tal:omit-tag=&quot;&quot;&gt;
            &lt;a href=&quot;http://plone.org/foundation&quot; i18n:translate=&quot;label_plone_foundation&quot;&gt;Plone Foundation&lt;/a&gt;&lt;/span&gt;.
    &lt;/span&gt;

    &lt;span i18n:translate=&quot;description_license&quot; tal:omit-tag=&quot;&quot;&gt;
    Distributed under the
        &lt;span i18n:name=&quot;license&quot; tal:omit-tag=&quot;&quot;&gt;
            &lt;a href=&quot;http://creativecommons.org/licenses/GPL/2.0/&quot; i18n:translate=&quot;label_gnu_gpl_licence&quot;&gt;GNU GPL license&lt;/a&gt;&lt;/span&gt;.
    &lt;/span&gt;
&lt;/p&gt;
    &lt;/div&gt;
    &lt;div id=&quot;my_footer_shadow&quot;&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
</pre>
<p>Here&#8217;s what I added to my existing CSS file to make the footer look like it does in my original design:</p>
<p><strong>src/my.theme/my/theme/browser/stylesheets/main.css</strong></p>
<pre>
...
#my_footer {
    border-top: 2px solid #a9dd89;
        background-color: #d2dce2;
    background-image: url("++resource++my.theme.images/footer_background.png");
    height: 32px;
    background-repeat: repeat-x;
    background-position: top;
    clear: both;
}

#my_footer #my_copywright {
    text-align: center;
}

#my_footer #my_footer_shadow {
    background-image: url("++resource++my.theme.images/footer_shadow.png");
    border-top: 2px #879ba3 solid;
    height: 10px;
    background-repeat: repeat-x;
    background-position: top;
    clear: both;
}
...
</pre>
<h4>A quick note about my background images</h4>
<p>Each of my gradient backgrounds are much larger than they need to be height-wise, and the color of the last row of pixels is the same as the background color of the element they&#8217;re in the background of. This helps to ensure that the text can stretch to a severe degree, either in amount or font-size, and the gradient still looks good.</p>
<p>With the new CSS added, here&#8217;s what it looks like: </p>
<div id="attachment_111" class="wp-caption aligncenter" style="width: 310px"><a href="http://lionfacelemonface.files.wordpress.com/2009/01/theming-final-look.png"><img src="http://lionfacelemonface.files.wordpress.com/2009/01/theming-final-look.png?w=300&#038;h=210" alt="Ah, that&#39;s much better" title="Ah, that&#39;s much better" width="300" height="210" class="size-medium wp-image-111" /></a><p class="wp-caption-text">Ah, that's much better</p></div>
<p>So almost everything is done! All that&#8217;s left is some cleanup and testing.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/lionfacelemonface.wordpress.com/126/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/lionfacelemonface.wordpress.com/126/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/lionfacelemonface.wordpress.com/126/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/lionfacelemonface.wordpress.com/126/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/lionfacelemonface.wordpress.com/126/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/lionfacelemonface.wordpress.com/126/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/lionfacelemonface.wordpress.com/126/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/lionfacelemonface.wordpress.com/126/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/lionfacelemonface.wordpress.com/126/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/lionfacelemonface.wordpress.com/126/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lionfacelemonface.wordpress.com&blog=2073436&post=126&subd=lionfacelemonface&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://lionfacelemonface.wordpress.com/2009/02/02/adventures-in-theming-overriding-a-stock-viewlet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5683b763dd1f27ec0c045b66cba43ab0?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jjmojojjmojo</media:title>
		</media:content>

		<media:content url="http://lionfacelemonface.files.wordpress.com/2009/01/theming-second-pass-css.png?w=300" medium="image">
			<media:title type="html">Looking Good.... But wait!</media:title>
		</media:content>

		<media:content url="http://lionfacelemonface.files.wordpress.com/2009/01/theming-final-look.png?w=300" medium="image">
			<media:title type="html">Ah, that&#39;s much better</media:title>
		</media:content>
	</item>
		<item>
		<title>Adventures in Theming: CSS and Hiding Viewlets</title>
		<link>http://lionfacelemonface.wordpress.com/2009/01/30/adventures-in-theming-css-and-hiding-viewlets/</link>
		<comments>http://lionfacelemonface.wordpress.com/2009/01/30/adventures-in-theming-css-and-hiding-viewlets/#comments</comments>
		<pubDate>Fri, 30 Jan 2009 06:00:24 +0000</pubDate>
		<dc:creator>jjmojojjmojo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[plone theme tutorial design css]]></category>

		<guid isPermaLink="false">http://lionfacelemonface.wordpress.com/?p=125</guid>
		<description><![CDATA[This is the fifth post in a short series about the ideas, trials and tribulations of my first theme product. I’ll be posting the whole story in one place when the series is complete.
A Touch Of Style
I&#8217;m going to continue using the Zope 3 resource approach with my style sheet. I don&#8217;t need DTML, I&#8217;m [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lionfacelemonface.wordpress.com&blog=2073436&post=125&subd=lionfacelemonface&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><em>This is the fifth post in a short series about the ideas, trials and tribulations of my first theme product. I’ll be posting the <a href="http://lionfacelemonface.wordpress.com/tutorials/adventures-in-theming-the-complete-saga/">whole story</a> in one place when the series is complete.</em></p>
<h4>A Touch Of Style</h4>
<p>I&#8217;m going to continue using the Zope 3 resource approach with my style sheet. I don&#8217;t need DTML, I&#8217;m not overriding any specific stock Plone CSS file, and I like keeping all of my browser-related stuff in the <code>browser</code> directory of my product.</p>
<p>Doing things this way requires an additional step. For Plone to incorporate the style sheet(s), they have to be registered with the <code>portal_css</code> tool. This is accomplished via <a href="http://plone.org/documentation/tutorial/genericsetup">GenericSetup</a>.</p>
<p>First, it&#8217;s a good idea to turn on &#8220;Debug/development mode&#8221; under <code>portal_css</code> in the ZMI of your plone instance (<a href="http://localhost:8080/plone/portal_css/manage_cssForm">http://localhost:8080/plone/portal_css/manage_cssForm</a>). This will ensure that your css will be refreshed in the browser as it&#8217;s updated on disk.</p>
<p>Then you need to create a css file, for example <code>main.css</code> in <code>browser/stylesheets</code></p>
<p>To get the CSS registered, you need to add a tag to <code>profiles/default/cssregistry.xml</code></p>
<p>What do you know! A quick glance at the <code>profiles/default</code> directory and we see that ZopeSkel has already done this for us. :). For the sake of illustration, here&#8217;s what that file looks like, after ZopeSkel has generated the skeleton:</p>
<p><strong>src/my.theme/my/theme/profiles/default/cssregistry.xml</strong></p>
<pre>
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;object name=&quot;portal_css&quot;&gt;
 &lt;stylesheet title=&quot;&quot;
    id=&quot;++resource++my.theme.stylesheets/main.css&quot;
    media=&quot;screen&quot; rel=&quot;stylesheet&quot; rendering=&quot;import&quot;
    cacheable=&quot;True&quot; compression=&quot;safe&quot; cookable=&quot;True&quot;
    enabled=&quot;1&quot; expression=&quot;&quot;/&gt;
&lt;/object&gt;
</pre>
<p>You can add additional style sheets in the same manner.</p>
<p>You can verify that the css is active by checking the <code>portal_css</code> tool (it will be second-to-last in the list), and making sure <a href="http://localhost:8080/plone/++resource++my.theme.stylesheets/main.css">http://localhost:8080/plone/++resource++my.theme.stylesheets/main.css</a> doesn&#8217;t throw any errors.</p>
<p>Now that the style sheet is registered, it needs to be populated with styles.</p>
<p><strong>src/my.theme/my/theme/browser/stylesheets/main.css</strong></p>
<pre>
/* Stylesheet for the 'MY Theme' Plone theme */

#my_header #main {
    height: 90px;
}

#my_header #left_side {
    float: left;
    clear: left;
}

#my_header #right_side {
    float: right;
    clear: right;
}

#my_header #personal_bar_sections {
    clear: both;
}

#my_header #personal_bar {
    float: right;
    clear: right;
}

#my_header #sections {
    float: left;
    clear: left;
}

#my_header #crumbtrail {
    clear: both;
}
</pre>
<p><P>I had to add another id to my template, and re-arrange things a bit to get it all to work. Here&#8217;s the modified template:</P></p>
<p><strong>src/my.theme/my/theme/browser/myheader.pt</strong></p>
<pre>
&lt;div id=&quot;my_header&quot;&gt;
    &lt;div id=&quot;main&quot;&gt;
        &lt;div id=&quot;right_side&quot;&gt;
            &lt;div tal:replace=&quot;structure view/plone.logo/render&quot; /&gt;
        &lt;/div&gt;
        &lt;div id=&quot;left_side&quot;&gt;
            &lt;div tal:replace=&quot;structure view/plone.site_actions/render&quot; /&gt;
        &lt;/div&gt;
    &lt;/div&gt;
    &lt;br /&gt;
    &lt;div id=&quot;personal_bar_sections&quot;&gt;
        &lt;div id=&quot;sections&quot;&gt;
            &lt;div tal:replace=&quot;structure view/plone.global_sections/render&quot; /&gt;
        &lt;/div&gt;
        &lt;div id=&quot;personal_bar&quot;&gt;
            &lt;div tal:replace=&quot;structure view/plone.personal_bar/render&quot; /&gt;
        &lt;/div&gt;
    &lt;/div&gt;
    &lt;br /&gt;
    &lt;div id=&quot;crumbtrail&quot;&gt;
        &lt;div tal:replace=&quot;structure view/plone.path_bar/render&quot; /&gt;
    &lt;/div&gt;
&lt;/div&gt;
</pre>
<p>To explain a bit, what I&#8217;ve done is used <code>&lt;div&gt;</code>&#8217;s to separate everything out, and then used <code>float</code> and <code>clear</code> to create the sort of layout I wanted. <code>float</code> moves the block-level elements to one side, and <code>clear</code> controls where <code>float</code>-ing elements are allowed to go. Here&#8217;s what it looks like at this point:</p>
<div id="attachment_106" class="wp-caption aligncenter" style="width: 310px"><a href="http://lionfacelemonface.files.wordpress.com/2009/01/theming-first-pass-css.png"><img src="http://lionfacelemonface.files.wordpress.com/2009/01/theming-first-pass-css.png?w=300&#038;h=123" alt="We&#39;re Almost There!" title="We&#39;re Almost There!" width="300" height="123" class="size-medium wp-image-106" /></a><p class="wp-caption-text">We're Almost There!</p></div>
<p>As you can see from the screen shot, I&#8217;ve achieved my primary goal of re-arranging the stock plone viewlets into the orientation that I specified in my initial design.</p>
<p>So now, I&#8217;ve just got to add in styles to handle the more looky-feely elements (background images, colors, fonts) and override bits of Plone style that either don&#8217;t look good in my theme or are counter to it (like the padding around the personal_bar)</p>
<h3>Ousting The Doppelgängers</h3>
<p>Now&#8217;s a good time to get rid of the superflous viewlets that I&#8217;ve re-implemented in my viewlet manager. This is accomplished through the <code>&lt;hidden&gt;</code> tag, in our GenericSetup profile&#8217;s <code>viewlets.xml</code> file.</p>
<p><strong>src/my.theme/my/theme/profiles/default/viewlets.xml</strong></p>
<pre>
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;object&gt;
    &lt;hidden manager=&quot;plone.portaltop&quot; skinname=&quot;My Theme&quot;&gt;
     &lt;viewlet name=&quot;plone.header&quot; /&gt;
     &lt;viewlet name=&quot;plone.personal_bar&quot; /&gt;
     &lt;viewlet name=&quot;plone.path_bar&quot; /&gt;
   &lt;/hidden&gt;
&lt;/object&gt;
</pre>
<p>The <code>&lt;hidden&gt;</code> tag takes two attributes, <code>manager</code> and <code>skinname</code>. <code>manager</code> is the name of the viewlet manager that you want to hide viewlets in. In this case, it&#8217;s <code>plone.portaltop</code>. You can figure out where the viewlets you want to hide are by using <a href="http://pypi.python.org/pypi/Products.Gloworm/1.0">GloWorm</a> or <a href="http://localhost:8080/plone/@@manage-viewlets">@@manage-viewlets</a>.</p>
<p>Inside of the <code>&lt;hidden&gt;</code> tag are <code>&lt;viewlet&gt;</code> tags, each specifying the name of a viewlet you&#8217;d like to hide.</p>
<p>You&#8217;ll need to re-install your theme product to see the change.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/lionfacelemonface.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/lionfacelemonface.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/lionfacelemonface.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/lionfacelemonface.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/lionfacelemonface.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/lionfacelemonface.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/lionfacelemonface.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/lionfacelemonface.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/lionfacelemonface.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/lionfacelemonface.wordpress.com/125/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=lionfacelemonface.wordpress.com&blog=2073436&post=125&subd=lionfacelemonface&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://lionfacelemonface.wordpress.com/2009/01/30/adventures-in-theming-css-and-hiding-viewlets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5683b763dd1f27ec0c045b66cba43ab0?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jjmojojjmojo</media:title>
		</media:content>

		<media:content url="http://lionfacelemonface.files.wordpress.com/2009/01/theming-first-pass-css.png?w=300" medium="image">
			<media:title type="html">We&#39;re Almost There!</media:title>
		</media:content>
	</item>
	</channel>
</rss>