Untitled

mail@pastecode.io avatar
unknown
php
a year ago
15 kB
3
Indexable
Never
<?php

/*************** 
    
    Assignment 2
    Name: Ian Chatelain	
    Date: Sept. 15, 2023
    Description: Input Validation

****************/

/**
 * Class that validates the given HTML field.
 */
class ValidateField {
    protected $sanitizedData;
    protected bool $isValid = false;
    protected string $fieldName;
    protected bool $required;

    public function __construct(string $fieldName){
        $this->fieldName = $fieldName;
    }

    public function getValue(){
        return $this->sanitizedData;
    }

    public function getFieldName(){
        return $this->fieldName;
    }
    
    public function getIsValid(){
        return $this->isValid;
    }
}

/**
 * Class that validates the given HTML field.
 */
class ValidateQuantityField extends ValidateField {
    public function __construct($fieldName){
        parent::__construct($fieldName);
        $this->required = false;
        $this->sanitizedData = filter_var($_POST[$this->fieldName], FILTER_SANITIZE_NUMBER_INT);
        $this->setIsValid();
    }

    /**
     * Returns true if the given field is empty or numeric.
     */
    private function setIsValid(){
        if(trim($_POST[$this->fieldName]) === ""){
            $this->isValid = true;
        }
        if(is_numeric($this->sanitizedData)){
            $this->isValid = true;
        }
    }
}

/**
 * Class that validates the given HTML field.
 */
class ValidateEmptyField extends ValidateField {
    public function __construct($fieldName){
        parent::__construct($fieldName);
        $this->required = true;
        $this->sanitizedData = filter_input(INPUT_POST, $this->fieldName, FILTER_SANITIZE_STRING);
        $this->setIsValid();
    }

    /**
     * Returns true if the given field is empty.
     */
    private function setIsValid(){
        if(trim($_POST[$this->fieldName]) !== ""){
            $this->isValid = true;
        }
    }
}

/**
 * Class that validates the given HTML field.
 */
class ValidateProvinceField extends ValidateField {

    // Valid province codes
    private array $provinceCodes = [
        'AB', // Alberta
        'BC', // British Columbia
        'MB', // Manitoba
        'NB', // New Brunswick
        'NL', // Newfoundland and Labrador
        'NS', // Nova Scotia
        'ON', // Ontario
        'PE', // Prince Edward Island
        'QC', // Quebec
        'SK', // Saskatchewan
        'NT', // Northwest Territories
        'NU', // Nunavut
        'YT'  // Yukon
    ];

    public function __construct($fieldName){
        parent::__construct($fieldName);
        $this->sanitizedData = filter_input(INPUT_POST, $this->fieldName, FILTER_SANITIZE_STRING);
        $this->setIsValid();
    }

    /**
     * Returns true if the given field a valid province code.
     */
    private function setIsValid(){
        if(in_array($_POST[$this->fieldName], $this->provinceCodes)){
            $this->isValid = true;
        }
    }
}

/**
 * Class that validates the given HTML field.
 */
class ValidatePostalField extends ValidateField {
    public function __construct($fieldName){
        parent::__construct($fieldName);
        $this->required = true;
        $this->sanitizedData = filter_input(INPUT_POST, $this->fieldName, FILTER_SANITIZE_STRING);
        $this->setIsValid();
    }

    /**
     * Returns true if the given field is a valid Canadian postal code.
     */
    private function setIsValid(){
        if(filter_var($this->sanitizedData, FILTER_VALIDATE_REGEXP, array(
            "options" => array("regexp"=>"/^[A-Za-z]\d[A-Za-z][ -]?\d[A-Za-z]\d$/")))){
                $this->isValid = true;
            }
    }
}

/**
 * Class that validates the given HTML field.
 */
class ValidateEmailField extends ValidateField {
    public function __construct($fieldName){
        parent::__construct($fieldName);
        $this->required = true;
        $this->sanitizedData = filter_input(INPUT_POST, $this->fieldName, FILTER_SANITIZE_STRING);
        $this->setIsValid();
    }

    /**
     * Returns true if the given field is a valid email.
     */
    private function setIsValid(){
        if(filter_var($this->sanitizedData, FILTER_VALIDATE_EMAIL)){
            $this->isValid = true;
        }
    }
}

/**
 * Class that validates the given HTML field.
 */
class ValidateCardTypeField extends ValidateField {
    public function __construct($fieldName){
        parent::__construct($fieldName);
        $this->required = true;
        $this->sanitizedData = filter_input(INPUT_POST, $this->fieldName, FILTER_SANITIZE_STRING);
        $this->setIsValid();
    }

    /**
     * Returns true if a card type has been chosen.
     */
    private function setIsValid(){
        if($this->sanitizedData && $this->sanitizedData == 'on'){
            $this->isValid = true;
        }
    }
}

/**
 * Class that validates the given HTML field.
 */
class ValidateMonthField extends ValidateField {
    public function __construct($fieldName){
        parent::__construct($fieldName);
        $this->required = true;
        $this->sanitizedData = filter_var($_POST[$this->fieldName], FILTER_SANITIZE_NUMBER_INT);
        $this->setIsValid();
    }

    /**
     * Returns true if a valid month has been chosen.
     */
    private function setIsValid(){
        if(filter_var($this->sanitizedData, FILTER_VALIDATE_INT, array("options" => array("min_range" => 1, "max_range" => 12)))){
            $this->isValid = true;
        }
    }
}

/**
 * Class that validates the given HTML field.
 */
class ValidateYearField extends ValidateField {
    public function __construct($fieldName){
        parent::__construct($fieldName);
        $this->required = true;
        $this->sanitizedData = filter_var($_POST[$this->fieldName], FILTER_SANITIZE_STRING);
        $this->setIsValid();
    }

    /**
     * Returns true if the card expiry year chosen is a valid year.
     */
    private function setIsValid(){
        if($this->sanitizedData >= date("Y") && $this->sanitizedData < (date("Y") + 5)){
            $this->isValid = true;
        }
    }
}

/**
 * Class that validates the given HTML field.
 */
class ValidateCardNumberField extends ValidateField {
    public function __construct($fieldName){
        parent::__construct($fieldName);
        $this->required = true;
        $this->sanitizedData = filter_var($_POST[$this->fieldName], FILTER_SANITIZE_NUMBER_INT);
        $this->setIsValid();
    }

    /**
     * Returns true if the given field is a 10 digit number.
     */
    private function setIsValid(){
        if(filter_var($this->sanitizedData, FILTER_VALIDATE_INT) && 
          (strlen((string)$this->sanitizedData) == 10) && 
           is_numeric($this->sanitizedData)){
           $this->isValid = true;
        }
    }
}

/**
 * Class that handles product information assignment.
 */
class orderedProductInfo{
    private $quantity;
    private $description;
    private $price;
    private $total;
    private $fieldName;

    // Item information
    private array $itemInfo = [
        'qty1' => [
            'quantity' => 0,
            'total' => 0,
            'description' => 'Mac Book',
            'price' => 1899.99
        ],
        'qty2' => [
            'quantity' => 0,
            'total' => 0,
            'description' => 'Razer Mouse',
            'price' => 79.99
        ],
        'qty3' => [
            'quantity' => 0,
            'total' => 0,
            'description' => '2TB WD HDD',
            'price' => 179.99
        ],
        'qty4' => [
            'quantity' => 0,
            'total' => 0,
            'description' => 'Google Nexus 7',
            'price' => 249.99
        ],
        'qty5' => [
            'quantity' => 0,
            'total' => 0,
            'description' => 'DD-45 Drums',
            'price' => 119.99
        ]
    ];

    public function __construct($fieldName, $quantity){
        $this->fieldName = $fieldName;
        $this->quantity = $quantity;
        $this->setItemInfo();
    }

    public function getQuantity(){
        return $this->quantity;
    }

    public function getDescription(){
        return $this->description;
    }

    public function getTotal(){
        return $this->total;
    }

    public function getName(){
        return $this->fieldName;
    }
        
    /**
     * Sets objects the product information according to the given field. 
     */
    private function setItemInfo(){
        switch($this->fieldName){
            case 'qty1':
                $this->orderedProductInfoAssignment('qty1');
                break;
            case 'qty2':
                $this->orderedProductInfoAssignment('qty2');
                break;
            case 'qty3':
                $this->orderedProductInfoAssignment('qty3');
                break;
            case 'qty4':
                $this->orderedProductInfoAssignment('qty4');
                break;
            case 'qty5':
                $this->orderedProductInfoAssignment('qty5');
                break;
        }
    }

    /**
     * Assigns the given field to the respective values from the itemInfo array.
     * 
     * @param $fieldName The name of the given field.
     */
    private function orderedProductInfoAssignment($fieldName){
        $this->description = $this->itemInfo[$fieldName]['description'];
        $this->price = $this->itemInfo[$fieldName]['price'];
        $this->total = (float)$this->quantity * (float)$this->price;
    }
}

$errors = [];

$fieldObjects = [
    // Product quantities
    'qty1' => new ValidateQuantityField('qty1'),
    'qty2' => new ValidateQuantityField('qty2'),
    'qty3' => new ValidateQuantityField('qty3'),
    'qty4' => new ValidateQuantityField('qty4'),
    'qty5' => new ValidateQuantityField('qty5'),

    // Shipping information
    'fullname' => new ValidateEmptyField('fullname'),
    'address' => new ValidateEmptyField('address'),
    'city' => new ValidateEmptyField('city'),
    'province' => new ValidateProvinceField('province'),
    'postal' => new ValidatePostalField('postal'),
    'email' => new ValidateEmailField('email'),

    // // Payment information
    'cardtype' => new ValidateCardTypeField('cardtype'),
    'cardname' => new ValidateEmptyField('cardname'),
    'month' => new ValidateMonthField('month'),
    'year' => new ValidateYearField('year'),
    'cardnumber' => new ValidateCardNumberField('cardnumber')
];


$orderedProductInfo = [];
$total = 0;

// Copies all product fields that have positive quantities to a new array,
// and calculates the price totals.
foreach($fieldObjects as $fieldName => $fieldObject){
    if(strpos($fieldName, 'qty') === 0 && ($fieldObject->getValue() > 0)){
        $orderedProductInfo[$fieldName] = new orderedProductInfo($fieldName, $fieldObject->getValue());
        $total += $orderedProductInfo[$fieldName]->getTotal();
    }
}

/**
 * Copies any fields that have failed validation to the error array for display.
 */
function validateFields(){
    global $fieldObjects;
    global $errors;
    foreach($fieldObjects as $field => $object){
        if(!$object->getIsValid()){
            $errors[$field] = $object;
        }
    }
}

?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="thankyou.css">
    <title>Thanks for your order!</title>
</head>
<body>
    <?php validateFields() ?>
    <?php if(empty($errors)): ?>
    <div>
        <h1>Thanks for your order <?= $_POST['fullname'] ?></h1>
        <h4>Here's a summary of your order:</h3>
    </div>
    <table>
        <tbody>
            <tr>
                <td colspan="4">
                    <h3>Address Information</h3>
                </td>
            </tr>
            <tr>
                <td class="alignright">
                    <span class="bold">Address:</span>
                </td>
                <td><?= $fieldObjects['address']->getValue() ?></td>
                <td class="alignright">
                    <span class="bold">City:</span>
                </td>
                <td><?= $fieldObjects['city']->getValue() ?></td>
            </tr>
            <tr>
                <td class="alignright">
                    <span class="bold">Province:</span>
                </td>
                <td><?= $fieldObjects['province']->getValue() ?></td>
                <td class="alignright">
                    <span class="bold">Postal Code:</span>
                </td>
                <td><?= $fieldObjects['postal']->getValue() ?></td>
            </tr>
            <tr>
                <td colspan="2" class="alignright">
                    <span class="bold">Email:</span>
                </td>
                <td colspan="2"><?= $fieldObjects['email']->getValue() ?></td>
            </tr>
        </tbody>
    </table>

    <table>
        <tbody>
            <tr>
                <td colspan="3">
                    <h3>Order Information</h3>
                </td>
            </tr>
            <tr>
                <td><span class="bold">Quantity</span></td>
                <td><span class="bold">Description</span></td>
                <td><span class="bold">Cost</span></td>
            </tr>
            <?php foreach($orderedProductInfo as $item => $property): ?>
                <tr>
                    <td><?= $property->getQuantity() ?></td>
                    <td><?= $property->getDescription() ?></td>
                    <td class="alignright"><?= $property->getTotal() ?></td>
                </tr>
                <?php endforeach ?>
            <tr>
                <td colspan="2" class="alignright"><span class="bold">Totals</span></td>
                <td class="alignright">
                    <span class="bold"><?= "$" . number_format($total, 2, '.', ',') ?></span>
                </td>
            </tr>
        </tbody>
    </table>
        <?php if($total > 20000): ?>
            <div>
                <iframe width="650" height="360" src="https://www.youtube.com/embed/dQw4w9WgXcQ" frameborder="0" allowfullscreen></iframe>
            </div>
        <?php endif ?>
    <?php else: ?>
    <table>
        <tbody>
            <tr>
                <td>
                    <h1>The following fields were invalid:</h1>
                </td>
            </tr>
            <tr>
                <td>
                    <?php foreach($errors as $fieldName => $fieldObject): ?>
                        <ul>
                            <li>
                                <?= $fieldObject->getFieldName() ?>
                            </li>
                        </ul>
                    <?php endforeach ?>
                </td>
            </tr>
        </tbody>
    </table>
    <?php endif ?>
</body>
</html>