whoami7 - Manager
:
/
home
/
kckglobal
/
www
/
portal
/
vendor
/
quickbooks
/
v3-php-sdk
/
src
/
DataService
/
Upload File:
files >> //home/kckglobal/www/portal/vendor/quickbooks/v3-php-sdk/src/DataService/Batch.php
<?php /******************************************************************************* * Copyright (c) 2017 Intuit * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ namespace QuickBooksOnline\API\DataService; use QuickBooksOnline\API\Core\Http\Serialization\XmlObjectSerializer; use QuickBooksOnline\API\Exception\IdsExceptionManager; use QuickBooksOnline\API\Exception\IdsException; use QuickBooksOnline\API\Exception\IdsError; use QuickBooksOnline\API\Exception\ValidationException; use QuickBooksOnline\API\Exception\ServiceException; use QuickBooksOnline\API\Exception\SecurityException; use QuickBooksOnline\API\Core\CoreHelper; use QuickBooksOnline\API\Core\ServiceContext; use QuickBooksOnline\API\Core\HttpClients\FaultHandler; use QuickBooksOnline\API\Core\HttpClients\RestHandler; use QuickBooksOnline\API\Data\IPPBatchItemRequest; use QuickBooksOnline\API\Data\IPPIntuitBatchRequest; use QuickBooksOnline\API\Core\CoreConstants; use QuickBooksOnline\API\Core\HttpClients\SyncRestHandler as RestServiceSyncRestHandler; use QuickBooksOnline\API\Diagnostics\TraceLevel; use QuickBooksOnline\API\Core\HttpClients\RequestParameters; use QuickBooksOnline\API\Utility\UtilityConstants; use \QuickBooksOnline\API\Core\Http\Serialization\IEntitySerializer; /** * This class contains code for Batch Processing. */ class Batch { /** * batch requests * @var array batchRequests */ private $batchRequests; /** * batch responses * @deprecated * @var array batchResponses */ private $batchResponses; /** * Intuit batch item responses list. * @var array batchResponses */ public $intuitBatchItemResponses; /** * service context object. * @var ServiceContext serviceContext */ private $serviceContext; /** * rest handler object. * @var RestHandler restHandler */ private $restHandler; /** * serializer to be used. * @var IEntitySerializer responseSerializer */ private $responseSerializer; /** * If not false, the request from last dataService did not return 2xx * @var FaultHandler */ private $lastError = false; /** * Throw Exception on Error or not. Default is false. * @var boolean */ private $isThrowExceptionOnError = false; /** * Enable debug mode to get more information inside the exception like intuit-tid * @var boolean */ private $debugMode = false; /** * Get the error from last request * @return FaultHandler */ public function getLastError() { return $this->lastError; } /** * Set the debug mode * @param $mode */ public function setDebug($mode) { $this->debugMode = $mode; } /** * Initializes a new instance of the Batch class. * @param $serviceContext The service context. * @param $restHandler The rest handler. */ public function __construct($serviceContext, $restHandler, $isThrowExceptionOnError) { $this->serviceContext = $serviceContext; $this->restHandler = $restHandler; $this->isThrowExceptionOnError = $isThrowExceptionOnError; $this->responseSerializer = CoreHelper::GetSerializer($this->serviceContext, false); $this->batchRequests = array(); $this->batchResponses = array(); $this->intuitBatchItemResponses = array(); } /** * Gets the count. * @return int count */ public function Count() { return count($this->batchRequests); } /** * Gets list of entites in case ResponseType is Report. */ public function ReadOnlyCollection() { return $this->intuitBatchItemResponses; } /** * Gets the IntuitBatchResponse with the specified id. * @param string $id unique batchitem id */ public function IntuitBatchResponse($id) { if(array_key_exists($id, $this->intuitBatchItemResponses)){ return $this->intuitBatchItemResponses[$id]; }else{ return null; } } /** * Adds the specified query. * @param string $query IDS query. * @param string $id unique batchitem id. */ public function AddQuery($query, $id) { if (!$query) { $exception = new IdsException('StringParameterNullOrEmpty: query'); IdsExceptionManager::HandleException($exception); } if (!$id) { $exception = new IdsException('StringParameterNullOrEmpty: id'); IdsExceptionManager::HandleException($exception); } if (count($this->batchRequests)>25) { $exception = new IdsException('BatchItemsExceededException'); IdsExceptionManager::HandleException($exception); } $batchItem = new IPPBatchItemRequest(); $batchItem->Query = $query; $batchItem->bId = $id; $batchItem->operationSpecified = true; //$batchItem->ItemElementName = ItemChoiceType6::Query; $this->batchRequests[] = $batchItem; } /** * Adds the specified query. * @param IEntity entity entitiy for the batch operation. * @param string id Unique batchitem id * @param OperationEnum operation operation to be performed for the entity. * @param string optionsdata to send with this specific batch item (example - allowduplicatedocnumber for invoices) */ public function AddEntity($entity, $id, $operation, $optionsData = null) { if (!$entity) { $exception = new IdsException('StringParameterNullOrEmpty: entity'); IdsExceptionManager::HandleException($exception); } if (!$id) { $exception = new IdsException('StringParameterNullOrEmpty: id'); IdsExceptionManager::HandleException($exception); } if (!$operation) { $exception = new IdsException('StringParameterNullOrEmpty: operation'); IdsExceptionManager::HandleException($exception); } foreach ($this->batchRequests as $oneBatchRequest) { if ($oneBatchRequest->bId == $id) { $exception = new IdsException('BatchIdAlreadyUsed'); IdsExceptionManager::HandleException($exception); } } $batchItem = new IPPBatchItemRequest(); $batchItem->IntuitObject = $entity; $batchItem->bId = $id; $batchItem->operation = $operation; $batchItem->operationSpecified = true; if ($optionsData !== null) { $batchItem->optionsData = $optionsData; } $this->batchRequests[] = $batchItem; } /** * Removes batchitem with the specified batchitem id. * @param string id unique batchitem id */ public function Remove($id) { if (!$id) { $exception = new IdsException('BatchItemIdNotFound: id'); IdsExceptionManager::HandleException($exception); } $revisedBatchRequests = array(); foreach ($this->batchRequests as $oneBatchRequest) { if ($oneBatchRequest->bId == $id) { // Exclude } else { $revisedBatchRequests[] = $oneBatchRequest; } } $this->batchRequests = $revisedBatchRequests; } /** * Remove all the batchitem requests. */ public function RemoveAll() { $this->batchRequests = array(); } /** * This method executes the batch request. */ public function Execute() { $requestID = rand() . rand(); $this->sendRequest($requestID); } /** * Use this function to do Batch Request instead of Execute() */ public function ExecuteWithRequestID($requestID) { if(isset($requestID) && !empty($requestID)){ $this->sendRequest($requestID); }else{ throw new \Exception("ExecuteWithRequestID called with Empty or Null request ID"); } } private function sendRequest($requestID) { $this->serviceContext->IppConfiguration->Logger->CustomLogger->Log(TraceLevel::Info, "Started Executing Method Execute for Batch"); // Create Intuit Batch Request $intuitBatchRequest = new IPPIntuitBatchRequest(); $intuitBatchRequest->BatchItemRequest = $this->batchRequests; $uri = "company/{1}/batch?requestid=" . $requestID; $uri = str_replace('{1}', $this->serviceContext->realmId, $uri); // Creates request parameters $requestParameters = new RequestParameters($uri, 'POST', CoreConstants::CONTENTTYPE_APPLICATIONXML, null); $restRequestHandler = $this->getRestHandler(); try { // Get literal XML representation of IntuitBatchRequest into a DOMDocument $httpsPostBodyPreProcessed = XmlObjectSerializer::getPostXmlFromArbitraryEntity($intuitBatchRequest, $urlResource); $doc = new \DOMDocument(); $domObj = $doc->loadXML($httpsPostBodyPreProcessed); $xpath = new \DOMXPath($doc); // Replace generically-named IntuitObject nodes with tags that describe contained objects $objectIndex = 0; while (1) { $matchingElementArray = $xpath->query("//IntuitObject"); if (is_null($matchingElementArray)) { break; } if ($objectIndex>=count($intuitBatchRequest->BatchItemRequest)) { break; } foreach ($matchingElementArray as $oneNode) { // Found a DOMNode currently named "IntuitObject". Need to rename to // entity that describes it's contents, like "ns0:Customer" (determine correct // name by inspecting IntuitObject's class). if ($intuitBatchRequest->BatchItemRequest[$objectIndex]->IntuitObject) { // Determine entity name to use $entityClassName = get_class($intuitBatchRequest->BatchItemRequest[$objectIndex]->IntuitObject); $entityTransferName = XmlObjectSerializer::cleanPhpClassNameToIntuitEntityName($entityClassName); $entityTransferName = 'ns0:'.$entityTransferName; // Replace old-named DOMNode with new-named DOMNode $newNode = $oneNode->ownerDocument->createElement($entityTransferName); if ($oneNode->attributes->length) { foreach ($oneNode->attributes as $attribute) { $newNode->setAttribute($attribute->nodeName, $attribute->nodeValue); } } while ($oneNode->firstChild) { $newNode->appendChild($oneNode->firstChild); } $oneNode->parentNode->replaceChild($newNode, $oneNode); } break; } $objectIndex++; } $httpsPostBody = $doc->saveXML(); list($responseCode, $responseBody) = $restRequestHandler->sendRequest($requestParameters, $httpsPostBody, null, $this->isThrowExceptionOnError); $faultHandler = $restRequestHandler->getFaultHandler(); if ($faultHandler) { $this->lastError = $faultHandler; return null; }else{ $this->lastError = false; } } catch (\Exception $e) { IdsExceptionManager::HandleException($e); } try { // No JSON support here yet // de serialize object $responseXmlObj = simplexml_load_string($responseBody); foreach ($responseXmlObj as $oneXmlObj) { // process batch item $intuitBatchItemResponse = $this->ProcessBatchItemResponse($oneXmlObj); $this->intuitBatchItemResponses[$intuitBatchItemResponse->batchItemId] = $intuitBatchItemResponse; } } catch (\Exception $e) { $this->serviceContext->IppConfiguration->Logger->CustomLogger->Log(TraceLevel::Error, "Encountered an error parsing the batch response." . $e->getMessage()); $this->serviceContext->IppConfiguration->Logger->CustomLogger->Log(TraceLevel::Error, "Stack Trace: " . $e->getTraceAsString()); return null; } $this->serviceContext->IppConfiguration->Logger->CustomLogger->Log(TraceLevel::Info, "Finished Execute method for batch."); } /** * Returns handler to communicate with service * @return RestHandler */ protected function getRestHandler() { return $this->restHandler; } private function verifyFault($fault) { if ($fault == null) { return null; } if (empty($fault)) { return null; } if (!$fault instanceof \SimpleXMLElement) { return null; } if (!$fault->attributes() instanceof \SimpleXMLElement) { return null; } if (!isset($fault->attributes()->type)) { return null; } return true; } private function collectErrors($fault) { $errors = array(); if (isset($fault->Error) && ($fault->Error instanceof \SimpleXMLElement) && $fault->Error->count()) { foreach ($fault->Error as $item) { if (!isset($item->Message)) { continue; } if (!$item->Message instanceof \SimpleXMLElement) { continue; } $error = new \stdClass(); $detail = (string)$item->Detail; if($detail) { $error->message = (string)$item->Message . ' - ' . $detail; } else { $error->message = (string)$item->Message; } $error->code = null; if ($item->attributes() instanceof \SimpleXMLElement && isset($item->attributes()->code)) { $error->code = (string)$item->attributes()->code; } $errors[] =$error; } } return $errors; } /** * Helper function for store the error message and code from Fault returned from QuickBooks Online */ private function arrayToMessageAndCode(array $array) { if (empty($array)) { return array(null,null); } if (1 == count($array)) { $item = array_pop($array); return array($item->message,$item->code); } $message = ""; $code = ""; foreach ($array as $item) { $message .= "Exception: ".$item->message . "\n"; if (empty($code) && !empty($item->code)) { $code = $item->code; } } return array($message,$code); } /** * Prepare IdsException out of Fault object. * @param Fault fault Fault object. * @return IdsException IdsException object. */ public function IterateFaultAndPrepareException($fault) { if (!$this->verifyFault($fault)) { return null; } // Collect information from XML entity $type = (string)$fault->attributes()->type; list($message, $code) = $this->arrayToMessageAndCode($this->collectErrors($fault)); if (is_null($message)) { return new IdsException("Fault Exception of type: " . $type . " has been generated."); } $idsException = null; // Fault types can be of Validation, Service, Authentication and Authorization. Run them through the switch case. switch ($type) { // If Validation errors iterate the Errors and add them to the list of exceptions. case "Validation": case "ValidationFault": // Throw specific exception like ValidationException. $idsException = new ValidationException($message, $code); break; // If Validation errors iterate the Errors and add them to the list of exceptions. case "Service": case "ServiceFault": // Throw specific exception like ServiceException. $idsException = new ServiceException($message, $code); break; // If Validation errors iterate the Errors and add them to the list of exceptions. case "Authentication": case "AuthenticationFault": case "Authorization": case "AuthorizationFault": $idsException = new SecurityException($message, $code); break; // Use this as default if there was some other type of Fault default: $idsException = new IdsException($message, $code); } // Return idsException which will be of type Validation, Service or Security. return $idsException; } /** * process batch item response * @param BatchItemResponse oneXmlObj The batchitem response. * @return IntuitBatchResponse IntuitBatchResponse object. */ private function ProcessBatchItemResponse($oneXmlObj) { $result = new IntuitBatchResponse(); if (null==$oneXmlObj) { return $result; } if(isset($oneXmlObj["bId"])){ $bid = (String)$oneXmlObj["bId"]; $result->batchItemId = $bid; }else{ throw new \Exception("No bid Found on the Batch Response."); } $firstChild = null; foreach ($oneXmlObj->children() as $oneChild) { $firstChild = $oneChild; break; } if (!$firstChild) { return $result; } $firstChildName = (string)$firstChild->getName(); switch ($firstChildName) { //For batch query result case "QueryResponse": $result->responseType = UtilityConstants::Query; $queryResult = array(); foreach ($oneXmlObj->QueryResponse->children() as $oneResponse) { $oneEntity = $this->responseSerializer->Deserialize('<RestResponse>'.$oneResponse->asXML().'</RestResponse>'); $queryResult = array_merge($queryResult, $oneEntity); } $result->setEntities($queryResult); $result->successFlagOn(); break; //For batch failure result case "Fault": $result->responseType = UtilityConstants::Exception; $idsException = $this->IterateFaultAndPrepareException($firstChild); if($this->debugMode) { $interface = $this->restHandler->getHttpClientInterface(); $responseInterface = $interface->getLastResponse(); $debugInfo = [ 'intuit_tid' => $responseInterface->getIntuitTid(), 'body' => $responseInterface->getBody(), 'headers' => $responseInterface->getHeaders(), ]; $idsException->setDebug($debugInfo); } $result->exception = $idsException; break; //For batch Entity Result default: $result->responseType = UtilityConstants::Entity; $oneEntityArray = $this->responseSerializer->Deserialize('<RestResponse>'.$firstChild->asXML().'</RestResponse>'); $oneEntity = $oneEntityArray[0]; $result->entity = $oneEntity; $result->successFlagOn(); break; } return $result; } }
Copyright ©2021 || Defacer Indonesia