inadmissible

Enhancedselection fix for PHP 4.4

December 23rd, 2005

Last week I’ve updated some eZ publish extensions to make them work with PHP 4.4. One of them was the enhancedselection datatype, an excellent contribution by Hans Melis.

With PHP 4.3 (eZ publish releases before 3.7), the datatype worked fine. But when using PHP 4.4 (eZ publish 3.7+), the attribute’s class level configuration wasn’t saved correctly.

The enhancedselection datatype uses the eZ publish xml library to store the selection’s possible options. That’s where it went wrong. The original code to store the options in an XML structure is:

$doc = new eZDOMDocument( "selection" );
$root =& $doc->createElementNode( "ezenhancedselection" );
$doc->setRoot( $root );

$options =& $doc->createElementNode( "options" );
$root->appendChild( $options );

foreach ( $currentOptions as $optionArray )
{
    $optionNode =& $doc->createElementNode( "option" );
    $optionNode->appendAttribute( $doc->createAttributeNode( "id", $optionArray['id'] ) );
    $optionNode->appendAttribute( $doc->createAttributeNode( 'name', $optionArray['name'] ) );
    $optionNode->appendAttribute( $doc->createAttributeNode( 'identifier', $optionArray['identifier'] ) );
    $optionNode->appendAttribute( $doc->createAttributeNode( 'priority', $optionArray['priority'] ) );
    $options->appendChild( $optionNode );
}

$xml =& $doc->toString();

Suppose you’ve added three options. This should result in the following XML string:

<?xml version="1.0" encoding="UTF-8"?>
<ezenhancedselection>
  <options>
    <option id="0"
            name="Value 1"
            identifier="Identifier 1"
            priority="1" />
    <option id="2"
            name="Value 2"
            identifier="Identifier 2"
            priority="2" />
    <option id="3"
            name="Value 3"
            identifier="Identifier 3"
            priority="3" />
  </options>
</ezenhancedselection>

But with PHP 4.4, you would get this XML string:

<?xml version="1.0" encoding="UTF-8"?>
<ezenhancedselection>
  <options>
    <option id="3"
            name="Value 3"
            identifier="Identifier 3"
            priority="3" />
    <option id="3"
            name="Value 3"
            identifier="Identifier 3"
            priority="3" />
    <option id="3"
            name="Value 3"
            identifier="Identifier 3"
            priority="3" />
  </options>
</ezenhancedselection>

All options have been replaced by te last one.

A first correction is to call the functions createElementNode and createAttributeNode as class methods, because the eZDOMDocument code includes Doxygen comments, marking these functions static.

The function createElementNode and toString are called by reference, but in eZ publish 3.7+ they don’t return by reference. So we’ll have to correct this too.

So far, the code will be:

$doc = new eZDOMDocument( "selection" );
$root = eZDOMDocument::createElementNode( "ezenhancedselection" );
$doc->setRoot( $root );

$options = eZDOMDocument::createElementNode( "options" );
$root->appendChild( $options );

foreach ( $currentOptions as $optionArray )
{
    $optionNode = eZDOMDocument::createElementNode( "option" );
    $optionNode->appendAttribute( eZDOMDocument::createAttributeNode( "id", $optionArray['id'] ) );
    $optionNode->appendAttribute( eZDOMDocument::createAttributeNode( 'name', $optionArray['name'] ) );
    $optionNode->appendAttribute( eZDOMDocument::createAttributeNode( 'identifier', $optionArray['identifier'] ) );
    $optionNode->appendAttribute( eZDOMDocument::createAttributeNode( 'priority', $optionArray['priority'] ) );
    $options->appendChild( $optionNode );
}

$xml = $doc->toString();

The call to $options->appendChild takes the $optionNode argument by reference. So the function’s argument will point to whatever value we assign to $optionNode. That’s why all options got replaced by the last one. At least in PHP 4.4. In PHP 4.3, there were some bugs related to references, and I suppose it’s because of these bugs that this code ever worked.

Finally, I’ve used an array to hold the different option elements in the loop:

$doc = new eZDOMDocument( "selection" );
$root = eZDOMDocument::createElementNode( "ezenhancedselection" );
$doc->setRoot( $root );

$options = eZDOMDocument::createElementNode( "options" );
$root->appendChild( $options );

$optionNodes = array();
foreach ( $currentOptions as $i => $optionArray )
{
    $optionNodes[$i] = eZDOMDocument::createElementNode( "option" );
    $optionNodes[$i]->appendAttribute( eZDOMDocument::createAttributeNode( "id", $optionArray['id'] ) );
    $optionNodes[$i]->appendAttribute( eZDOMDocument::createAttributeNode( 'name', $optionArray['name'] ) );
    $optionNodes[$i]->appendAttribute( eZDOMDocument::createAttributeNode( 'identifier', $optionArray['identifier'] ) );
    $optionNodes[$i]->appendAttribute( eZDOMDocument::createAttributeNode( 'priority', $optionArray['priority'] ) );
    $options->appendChild( $optionNodes[$i] );
}

$xml = $doc->toString();

This makes the datatype work with PHP 4.4, while remaining compatible with PHP 4.3.

Entry Filed under: PHP,eZ Publish

Leave a Comment

Required

Required, hidden

Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackback this post  |  Subscribe to the comments via RSS Feed


Calendar

December 2005
M T W T F S S
    Jan »
 1234
567891011
12131415161718
19202122232425
262728293031  

Most Recent Posts