eZ publish 3.8: New Custom Edit Handler

One of many new features in eZ publish 3.8 is the ability to use a custom edit handler. A custom edit handler is an extension (a PHP class) that enables you to perform actions based on user choices during the object editing process. You can add some extra POST data processing, connect to an external database , update data and much more, depending on your needs.

I found the custom edit handler useful in the case where newly registered users should have their own content folders somewhere in the content structure. The process is very simple: when the publish action is invoked, the custom edit handler creates a new contentobject as an instance of the folder class under the root node (when the owner of this folder is a newly registered user). No custom workflow events are needed for this.

First we need to create a new extension. The handler must be placed in: <extensions>/<extension-name>/content/<extension-name>handler.php. In our example this will be: extension/customedit/content/customedithandler.php

The file must contain a class called <extension-name>Handler, which extends the eZContentObjectEditHandler class (kernel/classes/ezcontentobjectedithandler.php) with the function fetchInput. Here is complete example of an extension/customedit/content/customedithandler.php file

<?php
class CustomEditHandler extends eZContentObjectEditHandler
{
    function fetchInput( &$http, &$module, &$class, &$object, &$version, &$contentObjectAttributes, $editVersion, $editLanguage, $fromLanguage )
    {
 
    }
 
    function storeActionList()
    {
    }
 
    function publish( $contentObjectID, $contentObjectVersion )
    {
 
    }
}
?>

Next we need to tell eZ publish that our custom edit handler is available. Add:

[EditSettings]
ExtensionDirectories[]=customedit

into settings/override/content.ini.append.php. If the file does not exist, create it.

The class definition also implements the optional functions ?publish? and ?storeActionList?. The first does content object publish operations, and the second returns a list of HTTP post parameters that should trigger the store action.

In our example we will focus on the ?publish? function and implement the code that will create a folder when a new user is registered in the system.

Here is the complete class definition for the custom edit handler:

<?php
class CustomEditHandler extends eZContentObjectEditHandler
{
    function fetchInput( &$http, &$module, &$class, &$object, &$version, &$contentObjectAttributes, $editVersion, $editLanguage, $fromLanguage )
    {
        // Do some action here
    }
 
    function storeActionList()
    {
    }
 
    function publish( $contentObjectID, $contentObjectVersion )
    {
        // fetch object
        $object =& eZContentObject::fetch( $contentObjectID );
        // get content class object
        $contentClass =& $object->attribute('content_class');
 
        // check if currently published object is USER
        if ( $contentClass->attribute( 'id' ) == 4 )
        {
            include_once( 'lib/ezutils/classes/ezoperationhandler.php' );
 
            // prepare new object data
            $parentNodeID = 2;
            $userID = $object->attribute( 'id' );
            $class = eZContentClass::fetchByIdentifier( 'folder' );
            $parentContentObjectTreeNode = eZContentObjectTreeNode::fetch( $parentNodeID );
            $parentContentObject = $parentContentObjectTreeNode->attribute( 'object' );
            $sectionID = $parentContentObject->attribute( 'section_id' );
 
            $contentObject = $class->instantiate( $userID, $sectionID );
            $contentObjectID = $contentObject->attribute( 'id' );
 
            $nodeAssignment = eZNodeAssignment::create( array( 'contentobject_id' => $contentObject->attribute( 'id' ),
            'contentobject_version' => $contentObject->attribute( 'current_version' ),
            'parent_node' => $parentContentObjectTreeNode->attribute( 'node_id' ),
            'is_main' => 1 ) );
            $nodeAssignment->store();
 
            $contentObjectAttributes =& $contentObject->contentObjectAttributes();
 
            $loopLenght = count( $contentObjectAttributes );
 
            // Fill up content object name attribute with user object name
            for( $i = 0; $i < $loopLenght; $i++ )
            {
                switch( $contentObjectAttributes[$i]->attribute( 'contentclass_attribute_identifier' ) )
                {
                    case 'name':
                        $contentObjectAttributes[$i]->setAttribute( 'data_text', $object->attribute( 'name' ) );
                        $contentObjectAttributes[$i]->store();
                        break;
                }
            }
 
            $contentObject->setAttribute( 'status', EZ_VERSION_STATUS_DRAFT );
            $contentObject->store();
 
            // publish new object
            $operationResult = eZOperationHandler::execute( 'content', 'publish', array( 'object_id' => $contentObjectID, 'version' => 1 ) );
        }
 
    }
}
?>

Now for every newly registered user, the system will create a new folder (owned by the new user). This code must be extended, of course, for additional checking, but it gives a practical example of how to use eZ publish 3.8's new custom edit handler.

Comments

interresting!

Hi Łukasz,

your article here has helped me to understand the custom edit handler. Thanks.

I still have some questions: How do you deal with one or more users having the same names? How do you avoid users seeing content from other accounts? I thought about using the pseudo (unique) instead of the first + last name to build the new folder name, but unfortunately, the login is not known to the user class here... So the question is how to make this waterproof, I can't live with the fact that users could try other names to see other account's information...

Cheers,
</Pascal>

Can I make my remove handler?

Hello, Łukasz!

Is there any way to make a custom remove hadler?
Today I made a very useful hack, but I want to form it as an extension to post it on ez.no.

May be this can help me?
[ActionSettings]
ExtensionDirectories[]

The same for class attribute edit?

Hi this is interesting,

I am wondering if something similar exists / is possible, on a content class attribute edit level?

Thanks for your answer.

N.O

check folder

Hello,

peter grilli in your example, i think that must be:
if ($child->ContentObject->OwnerID==$userId)
{
$already_has_folder=true;
break;
}

Thx for this extension

Today i needed this :)

content.ini should be in extension, isn't it ?

That was a missing functionality before 3.8. That's great.

Though, I think the content.ini.append.php file should be under the extension directory, so that it's taken into account only when extension is activated.

Am I wrong ?

mod

hi,
you should to add something like this to the publish method:
$params= array( 'Depth'=> 1);
$childs = eZContentObjectTreeNode::subTree( $params ,$parentNodeID );
$already_has_blog=false;
foreach ($childs as $child)
{
if ($child->ContentObject->OwnerID==$userID)
$already_has_blog=true;
break;
}
if ($already_has_blog==false)
{
//folder creation code
}

it checks if user already has a folder

can anybody help

first of all, thanks for the nice contribution, I really nedded it badly
I am supposed to use this extension to add a personal folder to the user on registeration, but I need to know how to create an action button to copy a content object to this folder.
any help?

Quota

Just thinking of implementing Quota System on the folders owned by the Registered Users.

Any Suggestions Please?

re: Fetch Input

You can fetch input only when form was submit and POST data were sent to /content/edit module.

For example you can check current action like this:

function fetchInput( &$http, &$module, &$class, &$object, &$version, &$contentObjectAttributes, $editVersion, $editLanguage, $fromLanguage )
{

if( $module->isCurrentAction( 'Store' ) )
{
// do something here
}

if( $http->hasPostVariable( 'Name' ) )
{
// do something here
}

}

List of available actions you can check in kernel/content/module.php for view 'Edit'.

Fetch Input

What could I put under the function fetchInput? Can I extract Data entered in a Form just before the "Send to publish"? And if so, how would I do that?

Thanks Łukasz

This is what i need today :)

eZ publish™ copyright © 1999-2008 eZ systems as