Why I am finished with Plone

I have a client that I set up on Plone about 9 months ago. It was a substantial amount of work moving them over to Plone, what with having to make a skin and copy all of the pages into Plone pages. It was all towards making my life easier in the long run, because, in theory, the users would be able to add their own news items and events.

For the first few months this was “sort of” working, but somewhere along the line I started having problems with Zope hanging, and hogging the processor and memory. Now it is at the point where this is happening hourly.

I have played with caching, session timeouts, and packing the ZODB, and anything else I can think of, but the site still seems to hang. The error logs are not helpful as they don’t give any indication that I can see as to what is causing the hanging.

So I decide to try to upgrade to the latest version (Plone 3 – I’m running 2.1). So I install a newer version of Python (2.4.4), and a new version of Zope (2.10), and finally I try to import and migrate one of my sites into the new instance. 2 hours of torture later I find that Plone 3 changed the way it handles its workflows and it is completely incompatible with the way that they were handled in Plone 2.5 and lower – so none of my add-on products will work (including the Forum, Ploneboard).

Well, so much for Plone 3. I guess I won’t EVER be upgrading to that one.

So what about Plone 2.5. Okay.. same deal. Installed different version of Zope (2.9.7) as recommended, then tried to import and migrate the site… But again – since Plone 2.5 changes the way it handles user accounts in an incompatible way, I need to uninstall the CAS module that I use for authentication…. Not today..

So I decide that maybe i just need to install the same version.. So I reinstall Zope 2.8.7, and Plone 2.1.4 and move the ZODB over to this new instance… It appears to be working ok for the first few minutes… however.. an hour later, it too is locking up.

So maybe it’s Python. I install Python 2.3.5 again in its own folder, then install Zope 2.8.7 on top of it, then I try to run my site on this instance…. Oh… but some of the extensions that I had compiled into my other Python 3.5 still need to be compiled in… so I compile/install PIL – seems to work ok — but then it comes to MySQL-Python so that I can access a MySQL database from Plone. This I spent 8 hours on, as there were missing libraries and header files.

Finally when I get it installed, this instance just locks up before I can even do anything…

Perhaps I’m not “smart” enough to run Plone.

I have been fed up with Plone before but keep on persisting because of all of the great features it appears to have. However, the single most important feature for me is that the site stays running. I’m at the end of my rope and really don’t know what to do at this point other than restart the server every hour until I manage to port the site back to PHP – a technology that just works!

Google top paying search word hoax

Ran across this article talking about some of the recent sites that claimed to know the top paying search words on Google. In this article, the author claims that these figures are a hoax – which makes sense because there are some pretty ridiculously high payouts listed for legal search terms. My guess is that the person who originally released this list made some good money off the page because lots of people are looking for this information…. and if the information that people want isn’t available, why not fabricate it, right?

PHP: call_user_func no good if you need to pass by reference

In PHP the call_user_func function is used to call a function whose name you won’t know until runtime.   In Dataface I need to do this sort of thing quite a bit because the developers are allowed to implement methods in their delegate classes that follow naming conventions. For example, they might define a method called firstname__permissions() that returns the permissions for the firstname field.   Since Dataface is written to be generic, I can’t very well hard code a call to the firstname__permissions() method inside the Dataface core.

This is where I turned to call_user_func so that I can do something like this:

// Suppose the field name we want to check was passed to us in the $fieldname variable.
$delegate =& $this->getDelegate(); // gets the delegate class
$permissions =& call_user_func( array(&$delegate, $fieldname."__permissions"), $this);

call_user_func will accept a function call as either a string function name (e.g. ‘trim’) or as a 2-element array, where the first element is an object, and the second element is a string which is the name of the method to call on that object. So call_user_func(array(&$delegate, $fieldname."__permissions")) is actually calling something like $delegate->firstname__permissions() (if the value of $fieldname was ‘firstname’).

Problem: Objects in PHP 4 are passed by value.

Now suppose our firstname__permissions() is defined like:
function firstname__permissions(&$record){ ... }. Note that the ‘&’ prepended to the $record parameter means that we want to pass the object by reference. This is necessary in PHP since objects are passed by value by default. There are many reasons why we don’t want to pass objects by value. For starters, if we make changes to the object inside our function those changes will be lost because they would have been applied to a copy of the object and not the object itself.

More problems: call_user_func passes everything by value

So you think you’ve solved your problem by defining firstname__permissions(&$record) to take the $record parameter by reference. WRONG! If we call it like:
call_user_func(array(&$delegage, 'firstname__permissions'), $record) the $record parameter will still be passed by value because call_user_func passes everything by value.

Solution: Don’t use call_user_func

One nice feature of PHP that most responsible PHP developers avoid like the plague is variable variables and variable functions. However this is one case where these come in handy. For instance, suppose we have the case above where we are calling call_user_func(array(&$delegate, $fieldname.'__permissions'), $record);. Call it this way will result in $record being passed by value.

However, we can use a variable method name as follows:

$methodname = $fieldname.'__permissions';
$out = $delegate->$methodname($record);

This solution will call our variable function AND pass $record by reference so everyone is happy.

But be responsible. Don’t over-use variable method calls.