/src/sixdg/Sixdg/DynamicsCRMConnector/Components/Soap/SoapRequester.php
https://bitbucket.org/6dg/dynamics-crm-php-connector · PHP · 271 lines · 143 code · 35 blank · 93 comment · 6 complexity · 415b21b702331fc071ad88c3709d4318 MD5 · raw file
- <?php
- namespace Sixdg\DynamicsCRMConnector\Components\Soap;
- use Sixdg\DynamicsCRMConnector\Responses\DynamicsCRMResponse;
- /**
- * Class SoapRequester
- *
- * @package Sixdg\DynamicsCRMConnector\Components\Soap
- */
- class SoapRequester
- {
- public static $soapEnvelope = 'http://www.w3.org/2003/05/soap-envelope';
- public static $soapFaults = [
- 'http://www.w3.org/2005/08/addressing/soap/fault',
- 'http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher/fault',
- 'http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/ExecuteOrganizationServiceFaultFault',
- 'http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/CreateOrganizationServiceFaultFault',
- 'http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/RetrieveOrganizationServiceFaultFault',
- 'http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/UpdateOrganizationServiceFaultFault',
- 'http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/DeleteOrganizationServiceFaultFault',
- 'http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/RetrieveMultipleOrganizationServiceFaultFault',
- ];
- protected $timeout = 10;
- protected $responder = null;
- /**
- * @param DynamicsCRMResponse $responder
- */
- public function setResponder(\DOMDocument $responder)
- {
- $this->responder = $responder;
- }
- /**
- * @param string $uri
- * @param string $request
- *
- * @return mixed
- * @throws \Exception
- */
- public function sendRequest($uri, $request)
- {
- $headers = $this->getHeaders($uri, $request);
- $ch = $this->getCurlHandle($uri, $headers, $request);
- $responseXml = curl_exec($ch);
- try {
- $this->hasError($ch, $responseXml);
- } catch (\Exception $ex) {
- throw $ex;
- }
- curl_close($ch);
- if ($this->responder) {
- $this->responder->loadXML($responseXml);
- return $this->responder;
- }
- return $responseXml;
- }
- /**
- * @param string $uri
- * @param string $request
- *
- * @return array
- */
- private function getHeaders($uri, $request)
- {
- $urlDetails = parse_url($uri);
- return [
- "POST " . $urlDetails['path'] . " HTTP/1.1",
- "Host: " . $urlDetails['host'],
- 'Connection: Keep-Alive',
- 'Content-type: application/soap+xml; charset=UTF-8',
- 'Content-length: ' . strlen($request)
- ];
- }
- /**
- * @param string $uri
- * @param array $headers
- * @param string $request
- *
- * @return resource
- */
- private function getCurlHandle($uri, $headers, $request)
- {
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, $uri);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLOPT_TIMEOUT, 60);
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
- curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
- curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
- curl_setopt($ch, CURLOPT_POST, true);
- curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
- curl_setopt($ch, CURLOPT_HEADER, false);
- curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->timeout);
- curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
- return $ch;
- }
- /**
- * @param resource $ch
- * @param string $responseXML
- *
- * @throws \Exception
- */
- private function hasError($ch, $responseXML)
- {
- $this->testCurlResponse($ch, $responseXML);
- if ($responseXML) {
- $responseDOM = new \DOMDocument();
- $responseDOM->loadXML($responseXML);
- $this->testIsValidSoapResponse($responseDOM, $responseXML);
- $this->testIsValidSoapHeader($responseDOM, $responseXML);
- $this->testActionIsNotError($responseDOM, $responseXML);
- return;
- }
- throw new \Exception('No response found');
- }
- /**
- * @param resource $ch
- * @param string $responseXML
- *
- * @throws \Exception
- */
- private function testCurlResponse($ch, $responseXML)
- {
- if ($responseXML === false) {
- throw new \Exception('cURL Error: ' . curl_error($ch));
- }
- }
- /**
- * @param \DOMDocument $responseDOM
- * @param string $responseXML
- *
- * @throws \Exception
- */
- private function testIsValidSoapResponse(\DOMDocument $responseDOM, $responseXML)
- {
- if ($responseDOM->getElementsByTagNameNS(SoapRequester::$soapEnvelope, 'Envelope')->length < 1) {
- throw new \Exception('Invalid SOAP Response: HTTP Response ' . $responseXML . PHP_EOL . $responseXML . PHP_EOL);
- }
- }
- /**
- * @param string $responseDOM
- *
- * @return mixed
- */
- private function getEnvelope($responseDOM)
- {
- return $responseDOM->getElementsByTagNameNS(SoapRequester::$soapEnvelope, 'Envelope')->item(0);
- }
- /**
- * @param \DOMElement $envelope
- *
- * @return mixed
- */
- private function getHeader($envelope)
- {
- return $envelope->getElementsByTagNameNS(SoapRequester::$soapEnvelope, 'Header')->item(0);
- }
- /**
- * @param \DOMElement $header
- *
- * @return mixed
- */
- private function getAction($header)
- {
- return $header->getElementsByTagNameNS('http://www.w3.org/2005/08/addressing', 'Action')->item(0);
- }
- /**
- * @param \DOMDocument $responseDOM
- * @param string $responseXML
- *
- * @throws \Exception
- */
- private function testIsValidSoapHeader(\DOMDocument $responseDOM, $responseXML)
- {
- $envelope = $this->getEnvelope($responseDOM);
- $header = $this->getHeader($envelope);
- if (!$header) {
- throw new \Exception('Invalid SOAP Response: No SOAP Header!' . PHP_EOL . $responseXML . PHP_EOL);
- }
- }
- /**
- * @param \DOMDocument $responseDOM
- *
- * @throws \Exception
- */
- private function testActionIsNotError(\DOMDocument $responseDOM)
- {
- $envelope = $this->getEnvelope($responseDOM);
- $header = $this->getHeader($envelope);
- $actionString = $this->getAction($header)->textContent;
- if (in_array($actionString, self::$soapFaults)) {
- throw $this->getSoapFault($responseDOM);
- }
- }
- /**
- * @param \DOMDocument $responseDOM
- *
- * @return \Exception
- */
- private function getSoapFault(\DOMDocument $responseDOM)
- {
- return new \SoapFault($this->getSoapFaultCode($responseDOM), $this->getSoapFaultMessage($responseDOM));
- }
- /**
- * @param \DomDocument $responseDOM
- *
- * @return string
- */
- private function getSoapFaultCode(\DomDocument $responseDOM)
- {
- /**
- * TODO Change to use xpath
- */
- $hierarchy = ['Envelope', 'Body', 'Fault', 'Code', 'Value'];
- $item = $responseDOM;
- foreach ($hierarchy as $currentLevel) {
- $item = $item->getElementsByTagNameNS('http://www.w3.org/2003/05/soap-envelope', $currentLevel)->item(0);
- }
- return $item->nodeValue;
- }
- /**
- * @param \DOMDocument $responseDOM
- *
- * @return string
- */
- private function getSoapFaultMessage(\DOMDocument $responseDOM)
- {
- /**
- * TODO Change to use xpath
- */
- $hierarchy = ['Envelope', 'Body', 'Fault', 'Reason', 'Text'];
- $item = $responseDOM;
- foreach ($hierarchy as $currentLevel) {
- $item = $item->getElementsByTagNameNS('http://www.w3.org/2003/05/soap-envelope', $currentLevel)->item(0);
- }
- return $item->nodeValue;
- }
- }