eZ Publish Developer / Specialist / Blog / Do you need Action?

blog

A blog about developing websites with the eZ Publish Content Management System. It contains material such as news, how-to articles, tutorials, template and PHP code, and specific solutions.

Stay up-to-date and subscribe to the blog's RSS feed.

maingfx

Do you need Action?

I was looking for solution how to place comments form below weblog entry in eZ publish so I decide to create custom action. I will try to explain how to define custom Action in eZ publish which create new comment object.

In example extension (ezcomment) with new action which create new comment directory structure looks like:

extension/ezcomments
 |
 | - actions
 |        | - content_actionhandler.php
 | - settings
 |        | - content.ini.append.php

You will have to override content.ini in your extension and add
extension/mynewextension/settings/content.ini.append.php

[ActionSettings]
ExtensionDirectories[]=mynewextension

For ezcomments extension this will be extension/ezcomments/settings/content.ini.append.php with code:

 
<?php /*
 
[ActionSettings]
ExtensionDirectories[]=ezcomments
 
*/ ?>

Body of new custom action must be placed in:
extension/mynewextension/actions/content_actionhandler.php

This is general structure of new Action:

 
<?php
function mynewextension_ContentActionHandler( &$module, &$http, &$objectID ) 
{ 
   if( $http->hasPostVariable("CustomAction") ) 
   { 
       //your custom action goes here 
   } 
} 
?>

Function name have to start with extension name, other ways it will not work

In ezcomments example code will look more complex, since it will create new comment object.

code from extension/ezcomments/actions/content_actionhandler.php

 
<?php
include_once( 'lib/ezutils/classes/ezoperationhandler.php' );
 
function eZComments_ContentActionHandler( &$module, &$http, &$objectID )
{
	if( $http->hasPostVariable( 'AddComment' ) )
	{
                        // fetch object and read node ID
		$object =& eZContentObject::fetch( $objectID );
		$nodeID = $object->attribute( 'main_node_id' );
		
                        // read user variable
		$subject = $http->postVariable( 'Subject' );
		$author = $http->postVariable( 'Author' );
		$message = $http->postVariable( 'Message' );
		
                        // prepare new object data
		$parentNodeID = $nodeID;
		$userID = 10;
		$class = eZContentClass::fetchByIdentifier( 'comment' );
		$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 attributes with user data
		for( $i = 0; $i < $loopLenght; $i++ )
		{
			switch( $contentObjectAttributes[$i]->attribute( 'contentclass_attribute_identifier' ) )
			{
				case 'subject':
					$contentObjectAttributes[$i]->setAttribute( 'data_text', $subject );
					$contentObjectAttributes[$i]->store();
					break;
				case 'author':
					$contentObjectAttributes[$i]->setAttribute( 'data_text', $author );
					$contentObjectAttributes[$i]->store();
					break;
				case 'message':
					$contentObjectAttributes[$i]->setAttribute( 'data_text', $message );
					$contentObjectAttributes[$i]->store();
					break;
			}
		}
 
		$contentObject->setAttribute( 'status', EZ_VERSION_STATUS_DRAFT );
		$contentObject->store();
 
  		// publish new comment
		$operationResult = eZOperationHandler::execute( 'content', 'publish', array( 'object_id' => $contentObjectID, 'version' => 1 ) );
 
                        // redirect to weblog full view		
		$module->redirectTo( '/content/view/full/' . $nodeID );
	}
}
?>

The simplest form for new custom action will look like:

<form method="post" action={"content/action"|ezurl}>
   <input type="submit" name="CustomAction" value="Custom action" /> 
   <input name="ContentObjectID" type="hidden" value="102" /> 
</form> 

ContentObjectID have to be included in POST.

In ezcomments extension example from will include Subject, Author and Message input fields. Code blow can be placed in weblog_full.tpl. User will see form which can use for posting new comment:

<form method="post" action={"content/action"|ezurl}> 
	Subject: <input type="text" name="Subject" value="" /><br />
	Author: <input type="text" name="Author" value="" /><br />
	Message: <textarea name="Message"></textarea><br />
            <input type="submit" name="AddComment" value="Submit" /> 
            <input name="ContentObjectID" type="hidden" value="{$node.object.id}" /> 
</form> 

That's all. We have new action that create new comment under weblog object. Code from content_actionhandler.php (ezcomments) need of course some additional checking for incoming data, validation, etc. but shows how custom action works in the eZ publish.

Comments

Capture form field values and inject to template

Hi,
Good article.
I want to create an action that capture the fields value in the form, then assign these value to the template variable/parameters of a template which the action redirects to.

So, I can show some content based on the user input in the form.

How to do that?

eZ 4.0 compatibility ?

Hi Lukasz
and thank you for this useful post.

Is this code still OK for the 4.0 version of eZ publish?
If not, what should I change?

As mentioned in this post (http://ez.no/developer/forum/developer/postvariable_names_in_ezhttptool_with_ez_4_0) I can't have postVariables retrieved in a webservice extensions that seems to work for static values.

Thanks in advance for your tips.

Mickael

Small enhancement

Hi Łukasz

A little enhancement to your example code: if you return true from the action handler function, the content/action view will exit from the loop over all action handlers. It's just a little bit faster in case you have other action handler extension.

Not found?

I've checked my code half a dozen times, and can't find anything wrong. But, for whatever reason, my action extionsion is not recognized. The only debug info I get returned is
"Error: kernel/content/action.php, Unknown content object action"

What am I doing wrong?

new in ez publish

where can i found weblog_full.tpl or where can i create it ?

File Upload? Urgent +

Hi,
Using this mechanism how can I retrieve a file which is part of object attribute? Then I want to e-mail that file as an attachment. Is it possible? If so plz, guide me
Looking for early response.

re: ContentObjectID

Yes, thank you very much!
It's very clear to me now.

Keep up the good work!

re: ContentObjectID

ContentObjectID is the parent object id under which new object will be created. So in case where parent object is Weblog entry we will use it ID and comment will be created under weblog entry. Hope it is understand now?

Use the force of the community, Luke ;)

Hi,

I suggest you to use the wonderfull powercontent extension from Kristof, you don't have to code anything and get the same result (unless I misunderstood something).

X+

ContentObjectID

Hi,

Thanks for publishing a solution on how to create custom form actions!

I have only one question: "How will the ContentObjectID be assigned through HTTP-POST if you haven't even created an object yet?"

Thanks in advance.

Richard Tuin

re:Interesting

Hi Bruce,

Thanks for comment. Code was tested with 3.6/3.7 should work with older versions as well. Possibility to have custom actions was added since rev. 1226 so in earlier eZ publish version. Very useful functionality ;)

Interesting

Hi

Appreciation?

My Amazon.com Wish List