Issues

ZF-5754: ArrayOfTypeComplex does not allow recursive types

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

Comments

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();
?>

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()

The following patch solves the issue:


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

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

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

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.

Fix in trunk and merged back into 1.7 release branch.

Throw an Exception on possible infinite recursion now.

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?

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/… (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?

closed the issue by fault, now resolved.

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?