<?php

class SopaClientOxa
{

    var $host = '127.0.0.1';

    var $xml_encoding = 'UTF-8';

    var $saop_deb = '<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns5406="http://tempuri.org"><SOAP-ENV:Body>';

    var $saop_fin = '</SOAP-ENV:Body></SOAP-ENV:Envelope>';

    var $diag = false;

    private $useNameSpace = true;

    private $modeASynchrone = false;

    public function setUseNameSpace($value)
    {
        $this->useNameSpace = $value;
    }

    public function &isUseNameSpace()
    {
        return $this->useNameSpace;
    }

    public function setModeASynchrone($value)
    {
        $this->modeASynchrone = $value;
    }

    public function &isModeASynchrone()
    {
        return $this->modeASynchrone;
    }

    function __construct($wsdl)
    {
        if (is_null($wsdl))
            $wsdl = 'null.wsdl'; // Obligation sinon le parsing ne va pas se faire
        
        if ($wsdl != '') {
            $wsdlparts = parse_url($wsdl);
            
            if (! array_key_exists('port', $wsdlparts))
                if (! array_key_exists('scheme', $wsdlparts))
                    $wsdlparts['port'] = 80;
                else
                    switch ($wsdlparts['scheme']) {
                        case 'http':
                            $wsdlparts['port'] = 80;
                            break;
                        case 'https':
                            $wsdlparts['port'] = 443;
                            break;
                    }
            
            $this->host = (array_key_exists('host', $wsdlparts) ? $wsdlparts['host'] : $this->host);
            $this->port = $wsdlparts['port'];
            $this->path = (array_key_exists('path', $wsdlparts)) ? $wsdlparts['path'] : '';
            
            // Construction du systeme de query
            
            if (array_key_exists('query', $wsdlparts))
                foreach (explode('&', $wsdlparts['query']) as $data) {
                    $element = explode('=', $data);
                    $this->query[$element[0]] = $element[1];
                }
        }
    }

    function &parseResponse(& $flux_xml)
    {
        return SopaClientOxa::xmlstr_to_array($flux_xml);
    }

    function &call($method, & $xml_string, $retourIsArray = true, $returnOriginXML = false)
    {
        // Translation du mot relatif à la method par le mot relatif au noeud primaire
        // enveloppe soap + tag de la methode + message xml
        $return = null;
        $wsdlparts = parse_url($_SESSION['wsdlurl']);
        
        $Ria = new SendHttpRIA('Oxaproc', 'APPEL_PHP_CENTRAL');
        $Ria->setHost($wsdlparts['host']);
        $Ria->setIspi($wsdlparts['path']);
        $Ria->setProtocol($wsdlparts['scheme']);
        $Ria->setPort($this->port);
        $Ria->setDiag($this->diag);

        if ($Ria->send($method, $xml_string, null, $this->isModeASynchrone())) {
            $this->responseData = $Ria->getXmlFromRia()->SaveXml();
            
            if($returnOriginXML)
            {
                return $this->responseData;
            }
            
            return SopaClientOxa::xmlstr_to_array($this->responseData, true, $retourIsArray);
        }
        
        return $return;
    }

    public static function &xmlstr_to_array(& $xmlstr, $useNameSpace = true, $retourIsArray = true)
    {
        $doc = new DOMDocument();
        $doc->loadXML($xmlstr);
        
        if ($retourIsArray)
            return SopaClientOxa::domnode_to_array($doc->documentElement, $useNameSpace);
        
        if ($ret = SopaClientOxa::domnode_to_arrayStruct($doc->documentElement, $useNameSpace)) {
            foreach ($ret as $index => & $cle)
                return $ret[$index];
        } else
            return $ret;
    }

    public static function &domnode_to_arrayStruct($node, $useNameSpace)
    {
        $output = null;
        
        /**
         * NE JAMAIS PRENDRE le textContent sur l'element XML_ELEMENT_NODE car sinon il concatene tous les textContent des noeuds fils
         */
        switch ($node->nodeType) {
            case XML_TEXT_NODE: // Uniquement un renvoi de texte
                if (trim($node->textContent) != '')
                    $output = trim($node->textContent);
                break;
            case XML_ELEMENT_NODE:
                // Affectation des attributes à la donnée
                if ($node->attributes->length != 0)
                    foreach ($node->attributes as $attrName => $attrNode)
                        $output[$node->nodeName]['!' . $attrName] = (string) $attrNode->value;
                
                $tabExist = array();
                
                for ($i = 0, $m = $node->childNodes->length; $i < $m; $i ++) {
                    $child = $node->childNodes->item($i);
                    
                    $ret = SopaClientOxa::domnode_to_arrayStruct($child, $useNameSpace);
                    if (! is_null($ret)) {
                        if (is_array($ret)) {
                            foreach ($ret as $index => & $suite) {
                                if (array_key_exists($index, $tabExist)) {
                                    if ($tabExist[$index] == 1) {
                                        $t = $output[$node->nodeName][$index];
                                        unset($output[$node->nodeName][$index]);
                                        
                                        $output[$node->nodeName][$index][] = $t;
                                        $tabExist[$index] = 2;
                                    }
                                    $output[$node->nodeName][$index][] = $suite;
                                } else {
                                    $output[$node->nodeName][$index] = $suite;
                                    $tabExist[$index] = 1;
                                }
                            }
                        } else
                            $output[$node->nodeName]['#text'] = $ret; // Pourquoi #text, c'est les memes valeur utilisé dans les RFC standard
                    }
                }
                break;
        }
        
        return $output;
    }

    public static function &domnode_to_array($node, $useNameSpace)
    {
        $output = array();
        switch ($node->nodeType) {
            case XML_CDATA_SECTION_NODE:
            case XML_TEXT_NODE:
                $output = trim($node->textContent);
                break;
            case XML_ELEMENT_NODE:
                for ($i = 0, $m = $node->childNodes->length; $i < $m; $i ++) {
                    $child = $node->childNodes->item($i);
                    $v = SopaClientOxa::domnode_to_array($child, $useNameSpace);
                    if (isset($child->tagName)) {
                        if ($useNameSpace || strpos($useNameSpace, ':') === false)
                            $t = $child->tagName;
                        else
                            $t = substr($child->tagName, strpos($child->tagName, ':') + 1);
                        
                        if (! isset($output[$t])) {
                            $output[$t] = array();
                        }
                        
                        $output[$t][] = $v;
                        
                        if ($child->attributes->length != 0)
                            foreach ($child->attributes as $attrName => $attrNode)
                                $output['!' . $attrName] = (string) $attrNode->value;
                    } elseif ($v || $v === '0') // https://github.com/gaarf/XML-string-to-PHP-array/blob/master/xmlstr_to_array.php
                        $output = (string) $v;
                }
                if (is_array($output)) {
                    foreach ($output as $t => $v)
                        if (is_array($v) && count($v) == 1 && $t != '@attributes') {
                            
                            if ($useNameSpace || strpos($t, ':') === false) {
                                // On ne touche à rien
                            } else
                                $t = substr($t, strpos($t, ':') + 1);
                            
                            if ((is_array($v[0]) && count($v[0]) == 0) || $v[0] == '')
                            {
                                $output[$t] = '';
                            }else
                                $output[$t] = $v[0];
                        }
                    
                    if ($node->attributes->length)
                        foreach ($node->attributes as $attrName => $attrNode)
                            $output['!' . $attrName] = (string) $attrNode->value;
                }
                break;
        }
        return $output;
    }
}