Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/pod.git
<?php
require_once 'Currency.php';
require_once 'ExchangeRate.php';
require_once 'Money.php';

class Order {
  private $summary = [];
  private $errorMessage = '';
  private $renderMethod;

  /** Set to true if processing the order suceeded. */
  private $success = false;

  public function process( array $response, int $statusCode ) {
    if( $statusCode === 201 ) {
      $this->processResponse( $response );
    } else {
      $this->processError( $response, $statusCode );
    }
  }

  protected function processResponse( array $response ): void {
    $errorDetail = '';
    $lineItem = $response['line_item_costs'][0] ?? null;

    if( !isset( $lineItem['total_cost_excl_tax'] ) ||
        !isset( $response['total_cost_incl_tax'] ) ||
        !isset( $response['shipping_address'] ) ) {
      $errorDetail = 'Invalid order data received from server.';
    } else {
      $bookPrice = (float)( $lineItem['total_cost_excl_tax'] );

      if( $bookPrice <= 0 ) {
        $errorDetail = 'Invalid book price received.';
      }
    }

    if( empty( $errorDetail ) ) {
      $this->summary = $response;
      $this->renderMethod = 'renderSummary';
      $this->success = true;
    } else {
      $this->processError( ['detail' => $errorDetail], 500 );
    }
  }

  protected function processError( array $response, int $statusCode ): void {
    $this->errorMessage = $response[ 'shipping_address' ][ 'detail' ]
      [ 'errors' ][ 0 ][ 'message' ]
      ?? $response[ 'detail' ]
      ?? "An unexpected error occurred (HTTP $statusCode).";
    $this->renderMethod = 'renderError';
  }

  public function render(): void {
    $this->{$this->renderMethod}();
  }

  public function success(): bool {
    return $this->success;
  }

  private function renderSummary() {
    $EXCLUDING = "total_cost_excl_tax";
    $config = new Configuration();
    $forex = $config->createExchangeRate( Currency::CAD );

    $address = $this->summary[ 'shipping_address' ];
    $target = Currency::fromCountry( $address['country'] ?? 'CA' );

    $price = new Money( $this->summary['line_item_costs'][0][$EXCLUDING] );
    $shipping = new Money( $this->summary['shipping_cost'][$EXCLUDING] );
    $fulfillment = new Money( $this->summary['fulfillment_cost'][$EXCLUDING] );
    $taxes = new Money( $this->summary['total_tax'] );
    $total = new Money( $this->summary['total_cost_incl_tax'] );

    $price = $forex->convert( $price, $target );
    $shipping = $forex->convert( $shipping, $target );
    $fulfillment = $forex->convert( $fulfillment, $target );
    $taxes = $forex->convert( $taxes, $target );
    $total = $forex->convert( $total, $target );
    ?>
    <section>
      <p class="address">
        <strong><?= $this->escape( $address[ 'name' ] ) ?></strong><br>
        <?= $this->escape( $address[ 'street1' ] ) ?><br>
        <?php if( !empty( $address[ 'street2' ] ) ) { ?>
          <?= $this->escape( $address[ 'street2' ] ) ?><br>
        <?php } ?>
        <?= $this->escape( $address[ 'city' ] ) ?>
        <?= $this->escape( $address[ 'state' ] ) ?>
        <?= $this->escape( $address[ 'postcode' ] ) ?><br>
        <?= $this->escape( $address[ 'country_code' ] ) ?>
      </p>
      <table>
        <tr>
          <td>Book price</td>
          <td><?= $price->render(); ?></td>
        </tr>
        <tr>
          <td>Shipping</td>
          <td><?= $shipping->render(); ?></td>
        </tr>
        <tr>
          <td>Fulfillment</td>
          <td><?= $fulfillment->render(); ?></td>
        </tr>
        <tr>
          <td>Taxes</td>
          <td><?= $taxes->render(); ?></td>
        </tr>
        <tr>
          <td><strong>Amount due</strong></td>
          <td><strong><?= $total->render(); ?></strong></td>
        </tr>
      </table>
      <form action="payment.php" method="post">
        <button type="submit">Proceed to payment</button>
      </form>
    </section>
    <?php
  }

  private function renderError(): void {
    ?>
    <h2>Shipping calculation error</h2>
    <p><?= $this->escape( $this->errorMessage ) ?></p>
    <form action='.'>
      <button type='submit' onclick='history.back(); return false;'>
        Try again
      </button>
    </form>
    <?php
  }

  private function escape( $value ): string {
    return htmlspecialchars( $value ?? '', ENT_QUOTES, 'UTF-8' );
  }
}