<?php
require_once 'Currency.php';
require_once 'ExchangeRate.php';
require_once 'Money.php';
class Order {
private $summary = [];
private $errorMessage = '';
private $renderMethod;
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' );
}
}