/**
  * FORM ACTION /payment
  * Take the given order, take payment and process it.
  * 
  * @param $data
  * @param $form
  * @param SS_HTTPRequest $request
  * @return Various
  */
 public function payment($data, $form = null, SS_HTTPRequest $request)
 {
     /**
      * If a TempBasketID exists, process new payment.
      */
     if (Store_BasketController::get_temp_basket_id()) {
         /* Temporary Basket Identifier */
         $TempBasketID = Store_BasketController::get_temp_basket_id();
         /* Order Object */
         $Order = Order::get_one("Order", "(TempBasketID='{$TempBasketID}')");
         /* Order ID */
         $order_id = new SQLQuery("id");
         $order_id = $order_id->setFrom("`order`")->addWhere("(TempBasketID='{$TempBasketID}')")->execute()->value();
         /**
          * STEP ONE - Alter the Order record.
          *
          * 1 - Alter the Order status to 1 ("Pending/Awaiting Payment") so store admins can now it.
          * 2 - Assign CustomerID to this Order so that it is now linked to the customers account.
          * 3 - As the order is now linked to a customer, remove all of the TempBasketID references.
          * 4 - Add any CustomerComments (if entered)
          */
         DB::Query("\n\t\t\tUPDATE `order`\n\t\t\tSET `Status`='1',\n\t\t\t`CustomerID`='" . Customer::currentUserID() . "',\n\t\t\t`TempBasketID`=NULL,\n\t\t\tCustomerComments='" . $data["CustomerComments"] . "'\n\t\t\tWHERE `ID`='" . $order_id . "'");
         /**
          * STEP TWO - Remove TempBasketID references from Order_Items records.
          */
         DB::Query("UPDATE `order_items` SET `TempBasketID`=NULL WHERE `OrderID`='" . $order_id . "'");
         /**
          * STEP THREE - Destroy TempBasketID Cookies so this customer can shop again later.
          */
         Store_BasketController::destroy_temp_basket_id();
         /**
          * STEP FOUR - Handle Stock (if Stock Management Enabled)
          *
          * 1 - Check desired products are still in stock.
          * 2 - Deduct requested stock from inventory to prevent double-allocation.
          */
         if (StoreSettings::get_settings()->Stock_StockManagement) {
             //Prepare the query to retreive the products in this order
             $product = new SQLQuery();
             $product->setFrom("Order_Items")->addWhere("(`OrderID`=" . $order_id . ")");
             //Execute the query
             $result = $product->execute();
             //Loop through each product in the order and check stock still exists in the inventory.
             foreach ($result as $row) {
                 //Products ID
                 $product_id = $row["OriginalProductID"];
                 //If not in stock, break loop by failing.
                 if (DataObject::get_by_id("Product", $product_id)->StockLevel < $row["Quantity"]) {
                     return $this->redirect($this->link() . "/place/order-stock");
                 }
                 //Otherwise, deduct requested stock from inventory.
                 DB::Query("UPDATE `product` SET `StockLevel`=StockLevel - " . $row["Quantity"] . " WHERE `ID`='" . $product_id . "'");
             }
         }
         /** 
          * STEP FIVE
          * Hand control over to the requested payment gateway class to continue with remainder of the order.
          * 
          * 1 - Get the ClassName of the selected payment gateway and create a new Object.
          * 2 - Call upon the method newPayment() within the gateway's class.
          */
         $ClassName = $data["PaymentMethod"] ? $data["PaymentMethod"] : null;
         return !is_null($ClassName) ? $ClassName::create()->newPayment($order_id) : null;
     } else {
         switch ($this->request->param("ID")) {
             /** 
              * A user has been returned after payment from their selected
              * payment gateway. Pass control to the object of the
              * Gateway class they used in order to fetch instructions.
              */
             case "success":
                 /**
                  * STEP ONE
                  * Does a Class exist for the requested Gateway?
                  * If not, throw HTTP 403 - Forbidden.
                  */
                 $request = $this->request;
                 if (class_exists($request->getVar("gateway"))) {
                     /**
                      * STEP TWO
                      * Is this gateway even enabled? 
                      * If not, throw HTTP 403 - Forbidden.
                      */
                     $Gateway = $request->getVar("gateway");
                     if (DataObject::get_one($Gateway)->Enabled) {
                         /**
                          * STEP THREE
                          * Initiate the Gateway class and pass the 
                          * control to its newPaymentSuccess() method.
                          */
                         return $Gateway::create()->newPaymentSuccess($request);
                     } else {
                         return $this->httpError(403);
                     }
                 } else {
                     return $this->httpError(403);
                 }
                 break;
                 /**
                  * A user has cancelled making a payment for a given order.
                  */
             /**
              * A user has cancelled making a payment for a given order.
              */
             case "cancelled":
                 return $this->customise(array("Title" => "An unexpected error occurred."))->renderWith(array("Store_Order_Error_PaymentCancelled", "Page"));
                 break;
                 /**
                  * A payment gateway has sent a response for a payment. We need to process that.
                  */
             /**
              * A payment gateway has sent a response for a payment. We need to process that.
              */
             case "response":
                 /**
                  * STEP ONE
                  * Does a Class exist for the requested Gateway?
                  * If not, throw HTTP 403 - Forbidden.
                  */
                 $request = $this->request;
                 if (class_exists($request->getVar("gateway"))) {
                     /**
                      * STEP TWO
                      * Is this gateway even enabled? 
                      * If not, throw HTTP 403 - Forbidden.
                      */
                     $Gateway = $request->getVar("gateway");
                     if (DataObject::get_one($Gateway)->Enabled) {
                         /**
                          * STEP THREE
                          * Initiate the Gateway class and pass the 
                          * control to its handleGatewayResponse() method.
                          */
                         return $Gateway::create()->handleGatewayResponse($request);
                     } else {
                         return $this->httpError(403);
                     }
                 } else {
                     return $this->httpError(403);
                 }
                 break;
                 /**
                  * Default is duplicate basket error.
                  */
             /**
              * Default is duplicate basket error.
              */
             default:
                 return $this->customise(array("Title" => "An unexpected error occurred."))->renderWith(array("Store_Order_Error_Duplicate", "Page"));
                 break;
         }
     }
 }