Zend Framework

ArrayOfTypeComplex does not allow recursive types

Details

  • Type: Bug Bug
  • Status: Resolved Resolved
  • Priority: Major Major
  • Resolution: Fixed
  • Affects Version/s: 1.7.4
  • Fix Version/s: 1.7.5
  • Component/s: Zend_Soap_Wsdl
  • Labels:
    None

Description

Since the fix of job #5604, it's not possible to have recursive types.

The following code fails in ZF 1.7.4 (Fatal error: Maximum function nesting level of '100' reached, aborting!)

<?php
    ini_set('include_path', dirname(__FILE__) . '/1.7.4');

    require_once('Zend/Soap/AutoDiscover.php');
    require_once('Zend/Soap/Wsdl/Strategy/ArrayOfTypeComplex.php');

    class WebservicesTestClass
    {
        /**
         * @var WebservicesTestClass[]
         */
        public $children = array();
    }

    class WebservicesTest
    {
        /**
         * @return WebservicesTestClass[]
         */
        public function test()
        {
            return array();
        }
    }

    $auto = new Zend_Soap_AutoDiscover('Zend_Soap_Wsdl_Strategy_ArrayOfTypeComplex');
    $auto->setClass('WebservicesTest');
    $auto->handle();
?>

Note however when working in <= 1.7.3pl1, the type is incorrectly returned in the WSDL as WebservicesTestClass[] rather than ArrayOfWebservicesTestClass

Issue Links

Activity

Hide
Quentin Zervaas added a comment -

Further testing indicates that if not specifying the types as arrays, it also fails in older versions

Sample code:


<?php
ini_set('include_path', dirname(_FILE_) . '/1.7.3');

require_once('Zend/Soap/AutoDiscover.php');
require_once('Zend/Soap/Wsdl/Strategy/ArrayOfTypeComplex.php');

class WebservicesTestClass

{ /** * @var WebservicesTestClass */ public $child; }

class WebservicesTest
{
/**

  • @return WebservicesTestClass
    */
    public function test() { return array(); }

    }

$auto = new Zend_Soap_AutoDiscover('Zend_Soap_Wsdl_Strategy_ArrayOfTypeComplex');
$auto->setClass('WebservicesTest');
$auto->handle();
?>

{/code}

The Zend_Soap_Wsdl_Strategy_DefaultComplexType->addComplexType() method needs to check what types are currently being added since it won't yet be available in $this->getContext()->getTypes()

Show
Quentin Zervaas added a comment - Further testing indicates that if not specifying the types as arrays, it also fails in older versions Sample code:

<?php ini_set('include_path', dirname(_FILE_) . '/1.7.3'); require_once('Zend/Soap/AutoDiscover.php'); require_once('Zend/Soap/Wsdl/Strategy/ArrayOfTypeComplex.php'); class WebservicesTestClass { /** * @var WebservicesTestClass */ public $child; } class WebservicesTest { /**
  • @return WebservicesTestClass */ public function test() { return array(); } }
$auto = new Zend_Soap_AutoDiscover('Zend_Soap_Wsdl_Strategy_ArrayOfTypeComplex'); $auto->setClass('WebservicesTest'); $auto->handle(); ?> {/code} The Zend_Soap_Wsdl_Strategy_DefaultComplexType->addComplexType() method needs to check what types are currently being added since it won't yet be available in $this->getContext()->getTypes()
Hide
Quentin Zervaas added a comment -

The following patch solves the issue:

{code title=Zend/Soap/Wsdl/Strategy/DefaultComplexType.php}

24a25,26
> protected static $_processing = array();
>
32a35,40
> if (in_array($type, self::$_processing)) { > return; > }
>
> self::$_processing[$type] = $type;
>
65a74
> unset(self::$_processing[$type]);


Show
Quentin Zervaas added a comment - The following patch solves the issue: {code title=Zend/Soap/Wsdl/Strategy/DefaultComplexType.php} 24a25,26 > protected static $_processing = array(); > 32a35,40 > if (in_array($type, self::$_processing)) { > return; > } > > self::$_processing[$type] = $type; > 65a74 > unset(self::$_processing[$type]);

Hide
Quentin Zervaas added a comment -

This file contains my changes to Zend/Soap/Wsdl/Strategy/DefaultComplexType.php

Show
Quentin Zervaas added a comment - This file contains my changes to Zend/Soap/Wsdl/Strategy/DefaultComplexType.php
Hide
Benjamin Eberlei added a comment -

confirmed! i'll look into it for the next mini release.

Show
Benjamin Eberlei added a comment - confirmed! i'll look into it for the next mini release.
Hide
Benjamin Eberlei added a comment -

your patch prevents recursion from happening, but it doesnt fix the bug. Your nested value is empty because you return nothing from the function.

Actually in the current implementation recursion objects is not even possible i think. I am changing this to throw an exception.

Show
Benjamin Eberlei added a comment - your patch prevents recursion from happening, but it doesnt fix the bug. Your nested value is empty because you return nothing from the function. Actually in the current implementation recursion objects is not even possible i think. I am changing this to throw an exception.
Hide
Benjamin Eberlei added a comment -

Fix in trunk and merged back into 1.7 release branch.

Throw an Exception on possible infinite recursion now.

Show
Benjamin Eberlei added a comment - Fix in trunk and merged back into 1.7 release branch. Throw an Exception on possible infinite recursion now.
Hide
Quentin Zervaas added a comment -

This doesn't really solve my issue... why should it not be possible to recurse into itself?

Can you not just change my implementation slightly to return "tns:$type" rather than just return?

Show
Quentin Zervaas added a comment - This doesn't really solve my issue... why should it not be possible to recurse into itself? Can you not just change my implementation slightly to return "tns:$type" rather than just return?
Hide
Benjamin Eberlei added a comment -

well if you require recursion, then you might need to stop somewhere. but wsdl types are rather strict, so how would you do that? The current ArrayOfTypeComplex does not support minOccurs which is the only way to handle this situation according to http://stackoverflow.com/questions/148988/recursion-in-xsd-schemas (i couldnt find it in the XSD doc, its dull to read).

I will have to look into it for the future, but i can't support this right now because if have to test it further.

So long the infinite recursion protection will be added.

Would that be ok?

The problem with returning tns:$type is, it might be the wrong name.

Back to your recursive example, how does it "stop" when you return "tns:$type" anyways? Doesnt SOAP then require an infinite stream of objects in your definition?

Show
Benjamin Eberlei added a comment - well if you require recursion, then you might need to stop somewhere. but wsdl types are rather strict, so how would you do that? The current ArrayOfTypeComplex does not support minOccurs which is the only way to handle this situation according to http://stackoverflow.com/questions/148988/recursion-in-xsd-schemas (i couldnt find it in the XSD doc, its dull to read). I will have to look into it for the future, but i can't support this right now because if have to test it further. So long the infinite recursion protection will be added. Would that be ok? The problem with returning tns:$type is, it might be the wrong name. Back to your recursive example, how does it "stop" when you return "tns:$type" anyways? Doesnt SOAP then require an infinite stream of objects in your definition?
Hide
Benjamin Eberlei added a comment -

closed the issue by fault, now resolved.

Show
Benjamin Eberlei added a comment - closed the issue by fault, now resolved.
Hide
Quentin Zervaas added a comment -

Fair enough. I thought you could effectively "end the recursion" by returning a null object.

Is it worth creating a new feature request in this tracker to support such functionality?

Show
Quentin Zervaas added a comment - Fair enough. I thought you could effectively "end the recursion" by returning a null object. Is it worth creating a new feature request in this tracker to support such functionality?

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated:
    Resolved: