gabrielbull/php-ups-api

View on GitHub
src/Rate.php

Summary

Maintainability
B
4 hrs
Test Coverage
<?php

namespace Ups;

use DOMDocument;
use DOMElement;
use Exception;
use SimpleXMLElement;
use Ups\Entity\RateRequest;
use Ups\Entity\RateResponse;
use Ups\Entity\Shipment;

/**
 * Rate API Wrapper.
 *
 * @author Michael Williams <michael.williams@limelyte.com>
 */
class Rate extends Ups
{
    const ENDPOINT = '/Rate';

    /**
     * @var RequestInterface
     */
    private $request;

    /**
     * @var ResponseInterface
     *                        todo: make private
     */
    public $response;

    /**
     * @var string
     */
    protected $requestOption;

    /**
     * @param $rateRequest
     *
     * @throws Exception
     *
     * @return RateResponse
     */
    public function shopRates($rateRequest)
    {
        if ($rateRequest instanceof Shipment) {
            $shipment = $rateRequest;
            $rateRequest = new RateRequest();
            $rateRequest->setShipment($shipment);
        }

        $this->requestOption = 'Shop';

        return $this->sendRequest($rateRequest);
    }

    /**
     * @param $rateRequest
     *
     * @throws Exception
     *
     * @return RateResponse
     */
    public function getRate($rateRequest)
    {
        if ($rateRequest instanceof Shipment) {
            $shipment = $rateRequest;
            $rateRequest = new RateRequest();
            $rateRequest->setShipment($shipment);
        }

        $this->requestOption = 'Rate';

        return $this->sendRequest($rateRequest);
    }

    /**
     * Creates and sends a request for the given shipment. This handles checking for
     * errors in the response back from UPS.
     *
     * @param RateRequest $rateRequest
     *
     * @throws Exception
     *
     * @return RateResponse
     */
    protected function sendRequest(RateRequest $rateRequest)
    {
        $request = $this->createRequest($rateRequest);

        $this->response = $this->getRequest()->request($this->createAccess(), $request, $this->compileEndpointUrl(self::ENDPOINT));
        $response = $this->response->getResponse();

        if (null === $response) {
            throw new Exception('Failure (0): Unknown error', 0);
        }

        if ($response->Response->ResponseStatusCode == 0) {
            throw new Exception(
                "Failure ({$response->Response->Error->ErrorSeverity}): {$response->Response->Error->ErrorDescription}",
                (int)$response->Response->Error->ErrorCode
            );
        } else {
            return $this->formatResponse($response);
        }
    }

    /**
     * Create the Rate request.
     *
     * @param RateRequest $rateRequest The request details. Refer to the UPS documentation for available structure
     *
     * @return string
     */
    private function createRequest(RateRequest $rateRequest)
    {
        $shipment = $rateRequest->getShipment();

        $document = $xml = new DOMDocument();
        $xml->formatOutput = true;

        /** @var DOMElement $trackRequest */
        $trackRequest = $xml->appendChild($xml->createElement('RatingServiceSelectionRequest'));
        $trackRequest->setAttribute('xml:lang', 'en-US');

        $request = $trackRequest->appendChild($xml->createElement('Request'));

        $node = $xml->importNode($this->createTransactionNode(), true);
        $request->appendChild($node);

        $request->appendChild($xml->createElement('RequestAction', 'Rate'));
        $request->appendChild($xml->createElement('RequestOption', $this->requestOption));

        $trackRequest->appendChild($rateRequest->getPickupType()->toNode($document));

        $customerClassification = $rateRequest->getCustomerClassification();
        if (isset($customerClassification)) {
            $trackRequest->appendChild($customerClassification->toNode($document));
        }

        $shipmentNode = $trackRequest->appendChild($xml->createElement('Shipment'));

        // Support specifying an individual service
        $service = $shipment->getService();
        if (isset($service)) {
            $shipmentNode->appendChild($service->toNode($document));
        }

        $shipper = $shipment->getShipper();
        if (isset($shipper)) {
            $shipmentNode->appendChild($shipper->toNode($document));
        }

        $shipFrom = $shipment->getShipFrom();
        if (isset($shipFrom)) {
            $shipmentNode->appendChild($shipFrom->toNode($document));
        }

        $shipTo = $shipment->getShipTo();
        if (isset($shipTo)) {
            $shipmentNode->appendChild($shipTo->toNode($document));
        }

        $alternateDeliveryAddress = $shipment->getAlternateDeliveryAddress();
        if (isset($alternateDeliveryAddress)) {
            $shipmentNode->appendChild($alternateDeliveryAddress->toNode($document));
        }

        $rateInformation = $shipment->getRateInformation();
        if ($rateInformation !== null) {
            $shipmentNode->appendChild($rateInformation->toNode($document));
        }

        $shipmentIndicationType = $shipment->getShipmentIndicationType();
        if (isset($shipmentIndicationType)) {
            $shipmentNode->appendChild($shipmentIndicationType->toNode($document));
        }

        foreach ($shipment->getPackages() as $package) {
            $shipmentNode->appendChild($package->toNode($document));
        }

        $shipmentServiceOptions = $shipment->getShipmentServiceOptions();
        if (isset($shipmentServiceOptions)) {
            $shipmentNode->appendChild($shipmentServiceOptions->toNode($xml));
        }

        $deliveryTimeInformation = $shipment->getDeliveryTimeInformation();
        if (isset($deliveryTimeInformation)) {
            $shipmentNode->appendChild($deliveryTimeInformation->toNode($xml));
        }

        $ShipmentTotalWeight = $shipment->getShipmentTotalWeight();
        if (isset($ShipmentTotalWeight)) {
            $shipmentNode->appendChild($ShipmentTotalWeight->toNode($xml));
        }

        $InvoiceLineTotal = $shipment->getInvoiceLineTotal();
        if (isset($InvoiceLineTotal)) {
            $shipmentNode->appendChild($InvoiceLineTotal->toNode($xml));
        }

        if ($shipment->getTaxInformationIndicator()) {
            $shipmentNode->appendChild($xml->createElement('TaxInformationIndicator'));
        }

        return $xml->saveXML();
    }

    /**
     * Format the response.
     *
     * @param SimpleXMLElement $response
     *
     * @return RateResponse
     */
    private function formatResponse(SimpleXMLElement $response)
    {
        // We don't need to return data regarding the response to the user
        unset($response->Response);

        $result = $this->convertXmlObject($response);

        return new RateResponse($result);
    }

    /**
     * @return RequestInterface
     */
    public function getRequest()
    {
        if (null === $this->request) {
            $this->request = new Request($this->logger);
        }

        return $this->request;
    }

    /**
     * @param RequestInterface $request
     *
     * @return $this
     */
    public function setRequest(RequestInterface $request)
    {
        $this->request = $request;

        return $this;
    }

    /**
     * @return ResponseInterface
     */
    public function getResponse()
    {
        return $this->response;
    }

    /**
     * @param ResponseInterface $response
     *
     * @return $this
     */
    public function setResponse(ResponseInterface $response)
    {
        $this->response = $response;

        return $this;
    }
}