|
eZ Publish
[4.0]
|
00001 <?php 00002 // 00003 // $Id$ 00004 // 00005 // Definition of eZSOAPResponse class 00006 // 00007 // Bård Farstad <bf@ez.no> 00008 // Created on: <19-Feb-2002 16:51:10 bf> 00009 // 00010 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ## 00011 // SOFTWARE NAME: eZ Publish 00012 // SOFTWARE RELEASE: 4.0.x 00013 // COPYRIGHT NOTICE: Copyright (C) 1999-2008 eZ Systems AS 00014 // SOFTWARE LICENSE: GNU General Public License v2.0 00015 // NOTICE: > 00016 // This program is free software; you can redistribute it and/or 00017 // modify it under the terms of version 2.0 of the GNU General 00018 // Public License as published by the Free Software Foundation. 00019 // 00020 // This program is distributed in the hope that it will be useful, 00021 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 // GNU General Public License for more details. 00024 // 00025 // You should have received a copy of version 2.0 of the GNU General 00026 // Public License along with this program; if not, write to the Free 00027 // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00028 // MA 02110-1301, USA. 00029 // 00030 // 00031 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ## 00032 // 00033 00034 /*! 00035 \class eZSOAPResponse ezsoapresponse.php 00036 \ingroup eZSOAP 00037 \brief eZSOAPResponse handles SOAP response packages 00038 00039 */ 00040 00041 require_once( "lib/ezutils/classes/ezdebug.php" ); 00042 //include_once( 'lib/ezsoap/classes/ezsoapcodec.php' ); 00043 //include_once( "lib/ezsoap/classes/ezsoapenvelope.php" ); 00044 00045 class eZSOAPResponse extends eZSOAPEnvelope 00046 { 00047 /*! 00048 Constructs a new SOAP response 00049 */ 00050 function eZSOAPResponse( $name="", $namespace="" ) 00051 { 00052 $this->Name = $name; 00053 $this->Namespace = $namespace; 00054 00055 // call the parents constructor 00056 $this->eZSOAPEnvelope(); 00057 } 00058 00059 /*! 00060 Decodes the SOAP response stream 00061 */ 00062 function decodeStream( $request, $stream ) 00063 { 00064 $dom = new DOMDocument( "1.0" ); 00065 00066 $dom->loadXML( $this->stripHTTPHeader( $stream ) ); 00067 $this->DOMDocument = $dom; 00068 00069 if ( !empty( $dom ) ) 00070 { 00071 // check for fault 00072 $response = $dom->getElementsByTagNameNS( eZSOAPEnvelope::ENV, 'Fault' ); 00073 00074 if ( $response->length == 1 ) 00075 { 00076 $this->IsFault = 1; 00077 foreach( $dom->getElementsByTagName( "faultstring" ) as $faultNode ) 00078 { 00079 $this->FaultString = $faultNode->textContent; 00080 break; 00081 } 00082 00083 foreach( $dom->getElementsByTagName( "faultcode" ) as $faultNode ) 00084 { 00085 $this->FaultCode = $faultNode->textContent; 00086 break; 00087 } 00088 return; 00089 } 00090 00091 // get the response 00092 $response = $dom->getElementsByTagNameNS( $request->namespace(), $request->name() . "Response" ); 00093 00094 /* Some protocols do not use namespaces, and do not work with an empty namespace. 00095 So, if we get no response, try again without namespace. 00096 */ 00097 if ( $response->length == 0 ) 00098 { 00099 $response = $dom->getElementsByTagName( $request->name() . "Response" ); 00100 } 00101 00102 $response = $response->item(0); 00103 00104 if ( !empty( $response ) ) 00105 { 00106 /* Cut from the SOAP spec: 00107 The method response is viewed as a single struct containing an accessor 00108 for the return value and each [out] or [in/out] parameter. 00109 The first accessor is the return value followed by the parameters 00110 in the same order as in the method signature. 00111 00112 Each parameter accessor has a name corresponding to the name 00113 of the parameter and type corresponding to the type of the parameter. 00114 The name of the return value accessor is not significant. 00115 Likewise, the name of the struct is not significant. 00116 However, a convention is to name it after the method name 00117 with the string "Response" appended. 00118 */ 00119 00120 $responseAccessors = $response->getElementsByTagName( 'return' ); 00121 if ( $responseAccessors->length > 0 ) 00122 { 00123 $returnObject = $responseAccessors->item( 0 ); 00124 $this->Value = $this->decodeDataTypes( $returnObject ); 00125 } 00126 } 00127 else 00128 { 00129 eZDebug::writeError( "Got error from server" ); 00130 } 00131 } 00132 else 00133 { 00134 eZDebug::writeError( "Could not process XML in response" ); 00135 } 00136 } 00137 00138 /*! 00139 \static 00140 Decodes a DOM node and returns the PHP datatype instance of it. 00141 */ 00142 static function decodeDataTypes( $node, $type = "" ) 00143 { 00144 $returnValue = false; 00145 00146 $attributeValue = ''; 00147 $attribute = $node->getAttributeNodeNS( eZSOAPEnvelope::SCHEMA_INSTANCE, 'type' ); 00148 if ( !$attribute ) 00149 { 00150 $attribute = $node->getAttributeNodeNS( 'http://www.w3.org/1999/XMLSchema-instance', 'type' ); 00151 } 00152 $attributeValue = $attribute->value; 00153 00154 $dataType = $type; 00155 $attrParts = explode( ":", $attributeValue ); 00156 if ( $attrParts[1] ) 00157 { 00158 $dataType = $attrParts[1]; 00159 } 00160 00161 /* 00162 $typeNamespacePrefix = $this->DOMDocument->namespaceByAlias( $attrParts[0] ); 00163 00164 check that this is a namespace type definition 00165 if ( ( $typeNamespacePrefix == eZSOAPEnvelope::SCHEMA_DATA ) || 00166 ( $typeNamespacePrefix == eZSOAPEnvelope::ENC ) 00167 ) 00168 TODO: add encoding checks with schema validation. 00169 */ 00170 00171 switch ( $dataType ) 00172 { 00173 case "string" : 00174 case "int" : 00175 case "float" : 00176 case 'double' : 00177 { 00178 $returnValue = $node->textContent; 00179 } break; 00180 00181 case "boolean" : 00182 { 00183 if ( $node->textContent == "true" ) 00184 $returnValue = true; 00185 else 00186 $returnValue = false; 00187 } break; 00188 00189 case "base64" : 00190 { 00191 $returnValue = base64_decode( $node->textContent ); 00192 } break; 00193 00194 case "Array" : 00195 { 00196 // Get array type 00197 $arrayType = $node->getAttributeNodeNS( eZSOAPEnvelope::ENC, 'arrayType' )->value; 00198 $arrayTypeParts = explode( ":", $arrayType ); 00199 00200 preg_match( "#(.*)\[(.*)\]#", $arrayTypeParts[1], $matches ); 00201 00202 $type = $matches[1]; 00203 $count = $matches[2]; 00204 00205 $returnValue = array(); 00206 foreach( $node->childNodes as $child ) 00207 { 00208 if ( $child instanceof DOMElement ) 00209 { 00210 $returnValue[] = eZSOAPResponse::decodeDataTypes( $child, $type ); 00211 } 00212 } 00213 }break; 00214 00215 case "SOAPStruct" : 00216 { 00217 $returnValue = array(); 00218 00219 foreach( $node->childNodes as $child ) 00220 { 00221 if ( $child instanceof DOMElement ) 00222 { 00223 $returnValue[$child->tagName] = eZSOAPResponse::decodeDataTypes( $child ); 00224 } 00225 } 00226 }break; 00227 00228 default: 00229 { 00230 foreach ( $node->childNodes as $childNode ) 00231 { 00232 if ( $childNode instanceof DOMElement ) 00233 { 00234 // check data type for child 00235 $attr = $childNode->getAttributeNodeNS( eZSOAPEnvelope::SCHEMA_INSTANCE, 'type' )->value; 00236 00237 $dataType = false; 00238 $attrParts = explode( ":", $attr ); 00239 $dataType = $attrParts[1]; 00240 00241 $returnValue[$childNode->tagName] = eZSOAPResponse::decodeDataTypes( $childNode ); 00242 } 00243 } 00244 00245 } break; 00246 } 00247 00248 return $returnValue; 00249 } 00250 00251 /*! 00252 Returns the XML payload for the response. 00253 */ 00254 function payload( ) 00255 { 00256 $doc = new DOMDocument( '1.0', 'utf-8' ); 00257 $doc->name = "eZSOAP message"; 00258 00259 $root = $doc->createElementNS( eZSOAPEnvelope::ENV, eZSOAPEnvelope::ENV_PREFIX . ':Envelope' ); 00260 00261 $root->setAttribute( 'xmlns:' . eZSOAPEnvelope::XSI_PREFIX, eZSOAPEnvelope::SCHEMA_INSTANCE ); 00262 $root->setAttribute( 'xmlns:' . eZSOAPEnvelope::XSD_PREFIX, eZSOAPEnvelope::SCHEMA_DATA ); 00263 $root->setAttribute( 'xmlns:' . eZSOAPEnvelope::ENC_PREFIX, eZSOAPEnvelope::ENC ); 00264 00265 // add the body 00266 $body = $doc->createElement( eZSOAPEnvelope::ENV_PREFIX . ':Body' ); 00267 $root->appendChild( $body ); 00268 00269 // Check if it's a fault 00270 if ( $this->Value instanceof eZSOAPFault ) 00271 { 00272 $fault = $doc->createElement( eZSOAPEnvelope::ENV_PREFIX . ':Fault' ); 00273 00274 $faultCodeNode = $doc->createElement( "faultcode", $this->Value->faultCode() ); 00275 $fault->appendChild( $faultCodeNode ); 00276 00277 $faultStringNode = $doc->createElement( "faultstring", $this->Value->faultString() ); 00278 $fault->appendChild( $faultStringNode ); 00279 00280 $body->appendChild( $fault ); 00281 } 00282 else 00283 { 00284 // add the request 00285 $responseName = $this->Name . "Response"; 00286 if ( $this->Namespace == '' ) 00287 $response = $doc->createElement( "resp:".$responseName ); 00288 else 00289 $response = $doc->createElementNS( $this->Namespace, "resp:".$responseName ); 00290 00291 $return = $doc->createElement( "return" ); 00292 00293 $value = eZSOAPCodec::encodeValue( $doc, "return", $this->Value ); 00294 00295 $body->appendChild( $response ); 00296 00297 $response->appendChild( $value ); 00298 } 00299 00300 $doc->appendChild( $root ); 00301 00302 return $doc->saveXML(); 00303 } 00304 00305 /*! 00306 \static 00307 \private 00308 Strips the header information from the HTTP raw response. 00309 */ 00310 function stripHTTPHeader( $data ) 00311 { 00312 $missingxml = false; 00313 $start = strpos( $data, "<?xml" ); 00314 if ( $start == 0 ) 00315 { 00316 eZDebug::writeWarning( "missing <?xml ...> in HTTP response, attempting workaround", 00317 "eZSoapResponse::stripHTTPHeader" ); 00318 $start = strpos( $data, "<E:Envelope" ); 00319 $missingxml = true; 00320 } 00321 $data = substr( $data, $start, strlen( $data ) - $start ); 00322 00323 if ( $missingxml == true ) 00324 { 00325 $data = '<?xml version="1.0"?>' . $data; 00326 } 00327 00328 return $data; 00329 } 00330 00331 /*! 00332 Returns the response value. 00333 */ 00334 function value() 00335 { 00336 return $this->Value; 00337 } 00338 00339 /*! 00340 Sets the value of the response. 00341 */ 00342 function setValue( $value ) 00343 { 00344 $this->Value = $value; 00345 } 00346 00347 /*! 00348 Returns true if the response was a fault 00349 */ 00350 function isFault() 00351 { 00352 return $this->IsFault; 00353 } 00354 00355 /*! 00356 Returns the fault code 00357 */ 00358 function faultCode() 00359 { 00360 return $this->FaultCode; 00361 } 00362 00363 /*! 00364 Returns the fault string 00365 */ 00366 function faultString() 00367 { 00368 return $this->FaultString; 00369 } 00370 00371 /// Contains the response value 00372 public $Value = false; 00373 /// Contains the response type 00374 public $Type = false; 00375 /// Contains fault string 00376 public $FaultString = false; 00377 /// Contains the fault code 00378 public $FaultCode = false; 00379 /// Contains true if the response was an fault 00380 public $IsFault = false; 00381 /// Contains the name of the response, i.e. function call name 00382 public $Name; 00383 /// Contains the target namespace for the response 00384 public $Namespace; 00385 00386 /// Contains the DOM document for the current SOAP response 00387 public $DOMDocument = false; 00388 } 00389 00390 ?>