/**
  * Member login hook
  */
 function memberLoggedIn()
 {
     if (self::$associate_to_current_order && ShoppingCart::order_started() && ($order = ShoppingCart::current_order())) {
         $order->MemberID = $this->owner->ID;
         $order->write();
     }
 }
 /**
  * Tries to create an order item with a non-existent version.
  */
 function testProductVersionDoesNotExist()
 {
     $currentorder = ShoppingCart::current_order();
     $brokenitem = new Product_OrderItem(array("ProductID" => $productSocks->ID, "ProductVersion" => 99999));
     $this->assertEquals($brokenitem->UnitPrice(), null);
     //TODO: what should happen here???
 }
 function testCalculations()
 {
     $mp3player = $this->objFromFixture('Product', 'mp3player');
     $this->get(ShoppingCart::add_item_link($mp3player->ID));
     $cart = ShoppingCart::current_order();
     $this->assertEquals($cart->Total(), 215);
 }
 function addmembertocartform_add($data, $form)
 {
     $member = Member::currentUser();
     if ($member && $member->IsShopAdmin()) {
         $order = ShoppingCart::current_order();
         $member = Member::get()->byID(intval($data["MemberID"]));
         if ($member) {
             if ($member->ID != $order->MemberID) {
                 $order->MemberID = $member->ID;
                 $order->BillingAddressID = 0;
                 $order->ShippingAddressID = 0;
                 $order->write();
                 $response = $member->getTitle() . " " . _t("AddToCartPage.ADDED", "customer has been added to order.");
                 $status = "good";
             } else {
                 $response = _t("AddToCartPage.NOCHANGE", "The order has not been changed.");
                 $status = "good";
             }
         } else {
             $response = _t("AddToCartPage.CUSTOMERNOTADDED", "Customer could not be added.");
             $status = "bad";
         }
         if (Director::is_ajax()) {
             return $response;
         } else {
             $form->setMessage($response, $status);
             $this->redirectBack();
         }
     }
 }
 /**
  * @TODO Where is this method used?
  * @return Order
  */
 function Order()
 {
     if ($this->ID) {
         return DataObject::get_by_id('Order', $this->OrderID);
     } else {
         return ShoppingCart::current_order();
     }
 }
예제 #6
0
 function Order()
 {
     if ($orderID = Director::urlParam('Action')) {
         return DataObject::get_by_id('Order', $orderID);
     } else {
         return ShoppingCart::current_order();
     }
 }
 /**
  * returns the order to use.... You can provide one
  * which basically just checks that it is a real order
  * @param Order | Int
  * @return Order
  */
 protected function orderToUse($order = null)
 {
     if ($order && $order instanceof $order) {
         return $order;
     }
     if (intval($order)) {
         return Order::get()->byID(intval($order));
     } else {
         return ShoppingCart::current_order();
     }
     user_error("Can't find an order to use");
 }
 function Item()
 {
     $currentOrder = ShoppingCart::current_order();
     if ($items = $currentOrder->Items()) {
         foreach ($items as $item) {
             if ($item instanceof ProductVariation_OrderItem && ($itemProductVariation = $item->ProductVariation())) {
                 if ($itemProductVariation->ID == $this->ID && $itemProductVariation->Version == $this->Version) {
                     return $item;
                 }
             }
         }
     } else {
         return null;
     }
 }
 /**
  *
  * extension check
  * return NULL if there is no problem and return true if there is a problem.
  */
 function OrderFormBeforeFinalCalculation($data, $form, $request)
 {
     if ($data["PaymentMethod"] != "BuckarooPayment") {
         return null;
     }
     $order = ShoppingCart::current_order();
     //this is the standard way for getting a specific Order Modifier, allowing
     //you to work on multiple modifiers of the same kind .
     if (!isset($data['BuckarooMethod']) || !$data["BuckarooMethod"]) {
         return "ERROR";
     }
     $modifiers = $order->Modifiers('BuckarooPaymentModifier');
     if ($modifiers) {
         foreach ($modifiers as $modifier) {
             $modifier->updateName(Convert::raw2sql($data['BuckarooMethod'], $write = true));
         }
     } else {
         return "ERROR";
     }
     return null;
 }
 public function submit(array $data, Form $form, $message = "order updated", $status = "good")
 {
     $order = ShoppingCart::current_order();
     if ($order) {
         $modifier = $order->Modifiers('DonationModifier');
         if ($modifier) {
             $modifier = $modifier->First();
             $modifier->updateAddDonation($data['DonationID']);
             $msg = $data['DonationID'] ? _t("AnyPriceRoundUpDonationModifier.UPDATED", "Round up donation added - THANK YOU.") : _t("AnyPriceRoundUpDonationModifier.UPDATED", "Round up donation removed.");
             if (isset($data['OtherValue'])) {
                 $modifier->updateOtherValue(floatval($data['OtherValue']));
                 if (floatval($data['OtherValue']) > 0) {
                     $msg .= _t("AnyPriceRoundUpDonationModifier.UPDATED", "Added donation - THANK YOU.");
                 }
             } else {
                 $modifier->updateOtherValue(0);
             }
             $modifier->write();
             return ShoppingCart::singleton()->setMessageAndReturn($msg, "good");
         }
     }
     return ShoppingCart::singleton()->setMessageAndReturn(_t("AnyPriceRoundUpDonationModifier.NOTUPDATED", "Could not update the round up donation status.", "bad"));
 }
예제 #11
0
 /**
  * Ensures member unique id stays unique and other basic stuff...
  * @param array $data = Form Data
  * @return Boolean
  */
 function php($data)
 {
     $valid = parent::php($data);
     $checkoutPage = DataObject::get_one("CheckoutPage");
     if ($checkoutPage->TermsAndConditionsMessage) {
         if (isset($data["ReadTermsAndConditions"])) {
             if (!$data["ReadTermsAndConditions"]) {
                 $this->validationError("ReadTermsAndConditions", $checkoutPage->TermsAndConditionsMessage, "required");
                 $valid = false;
             }
         }
     }
     $order = ShoppingCart::current_order();
     if (!$order) {
         $this->validationError("Order", _t("OrderForm.ORDERNOTFOUND", "There was an error in processing your order, please try again or contact the administrator."), "required");
         $valid = false;
     }
     $billingAddress = DataObject::get_by_id("BillingAddress", intval($order->BillingAddressID) - 0);
     if (!$billingAddress) {
         $this->validationError("BillingAddress", _t("OrderForm.MUSTHAVEBILLINGADDRESS", "All orders must have a billing address."), "required");
         $valid = false;
     }
     return $valid;
 }
예제 #12
0
 /**
  * Standard SS method - can the current member view this order?
  *
  *@return Boolean
  **/
 public function canView($member = null)
 {
     if (!$this->exists()) {
         return true;
     }
     $member = $this->getMemberForCanFunctions($member);
     //check if this has been "altered" in a DataObjectDecorator
     $extended = $this->extendedCan('canView', $member->ID);
     //if this method has been extended in a data object decorator then use this
     if ($extended !== null) {
         return $extended;
     }
     //is the member is a shop admin they can always view it
     if (EcommerceRole::current_member_is_shop_admin($member)) {
         return true;
     }
     //if the current member OWNS the order, (s)he can always view it.
     if ($member->exists() && $this->MemberID == $member->ID) {
         return true;
     }
     //it is the current order
     $currentOrder = ShoppingCart::current_order();
     if ($currentOrder && $currentOrder->ID == $this->ID) {
         //we do some additional CHECKS for session hackings!
         if ($member->exists()) {
             //must be the same member!
             if ($this->MemberID == $member->ID) {
                 return true;
             } elseif ($this->MemberID) {
                 return false;
             } else {
                 //we do NOT add the member here, because this is done in shopping cart
                 //$this->MemberID = $member->ID;
                 //$this->write();
                 return true;
             }
         } else {
             //order belongs to someone, but current user is NOT logged in...
             if ($this->MemberID) {
                 return false;
             } else {
                 return true;
             }
         }
     }
     //if the session ID matches, we can always view it.
     //SECURITYL RISK: if you know someone else his/her session
     //OR you can view the sessions on the server
     //OR you can guess the session
     //THEN you can view the order.
     //by viewing the order you can also access some of the member details.
     //NB: this MUST be the last resort! If all other methods fail.
     //That is, if we are working with the current order then it is a good idea
     //to deny non-matching members.
     if ($this->SessionID && $this->SessionID == session_id()) {
         return true;
     }
     return false;
 }
 /**
  * This function works out the most likely region for the current order
  * @return Int
  **/
 public static function get_region()
 {
     $regionID = 0;
     if ($order = ShoppingCart::current_order()) {
         if ($region = $order->Region()) {
             $regionID = $region->ID;
         }
     }
     //3. check GEOIP information
     if (!$regionID) {
         $regionArray = self::list_of_allowed_entries_for_dropdown();
         if (is_array($regionArray) && count($regionArray)) {
             foreach ($regionArray as $regionID => $regionName) {
                 //we stop at the first one... as we have no idea which one is the best.
                 break;
             }
         }
     }
     return $regionID;
 }
 /**
  * Returns the shopping cart.
  * @todo Does HTTP::set_cache_age() still need to be set here?
  * 
  * @return Order
  */
 function Cart()
 {
     HTTP::set_cache_age(0);
     return ShoppingCart::current_order();
 }
 /**
  * create a member and add it to the order
  * then redirect back...
  *
  * @param Array $data
  * @param Form $form
  */
 function creatememberandaddtoorder($data, $form)
 {
     $member = new Member();
     $order = ShoppingCart::current_order();
     if ($order && $order->exists()) {
         $form->saveInto($member);
         $password = ShopAccountForm_PasswordValidator::clean_password($data);
         if ($password) {
             $member->changePassword($password);
             if ($member->validate()->valid()) {
                 $member->write();
                 if ($member->exists()) {
                     if (!$order->MemberID) {
                         $order->MemberID = $member->ID;
                         $order->write();
                     }
                     $member->login();
                     $this->sessionMessage(_t("ShopAccountForm.SAVEDDETAILS", "Your details has been saved."), "good");
                 } else {
                     $this->sessionMessage(_t("ShopAccountForm.COULD_NOT_CREATE_RECORD", "Could not save create a record for your details."), "bad");
                 }
             } else {
                 $this->sessionMessage(_t("ShopAccountForm.COULD_NOT_VALIDATE_MEMBER", "Could not save your details."), "bad");
             }
         }
     } else {
         $this->sessionMessage(_t("ShopAccountForm.COULDNOTFINDORDER", "Could not find order."), "bad");
     }
     $this->controller->redirectBack();
 }
 public function init()
 {
     parent::init();
     $this->currentOrder = ShoppingCart::current_order();
     $this->initVirtualMethods();
 }
 public function submit($data, $form)
 {
     if (isset($data['OrderFor'])) {
         $order = ShoppingCart::current_order();
         if ($order) {
             if ($modifiers = $order->Modifiers("OrderMarker")) {
                 foreach ($modifiers as $modifier) {
                     $modifier->updateOrderFor(Convert::raw2sql($data["OrderFor"]));
                     $modifier->write();
                 }
                 return ShoppingCart::singleton()->setMessageAndReturn(_t("EcommerceCorporateAccount.UPDATED", "Order saved as '" . Convert::raw2xml($data["OrderFor"])) . "'.", "good");
             }
         }
     }
     return ShoppingCart::singleton()->setMessageAndReturn(_t("EcommerceCorporateAccount.UPDATED", "Order marker could not be saved"), "bad");
 }
 /**
  * Builds json object to be returned via ajax.
  * @param Array $message (Type, Message)
  * @param Array $additionalData
  * @param String $status
  * @return HEADER + JSON
  **/
 public function ReturnCartData(array $messages = array(), array $additionalData = null, $status = "success")
 {
     //add header
     if ($this->includeHeaders) {
         $this->addHeader('Content-Type', 'application/json');
     }
     SSViewer::set_source_file_comments(false);
     //merge messages
     $messagesImploded = '';
     if (is_array($messages) && count($messages)) {
         foreach ($messages as $messageArray) {
             $messagesImploded .= '<span class="' . $messageArray["Type"] . '">' . $messageArray["Message"] . '</span>';
         }
     }
     //bad status
     if ($status != "success") {
         $this->setStatusCode(400, $messagesImploded);
     }
     //init Order - IMPORTANT
     $currentOrder = ShoppingCart::current_order();
     //THIS LINE TAKES UP MOST OF THE TIME OF THE RESPONSE!!!
     $currentOrder->calculateOrderAttributes($force = false);
     $ajaxObject = $currentOrder->AJAXDefinitions();
     // populate Javascript
     $js = array();
     //must be first
     if (isset($_REQUEST["loadingindex"])) {
         $js[] = array("t" => "loadingindex", "v" => $_REQUEST["loadingindex"]);
     }
     //order items
     $inCartArray = array();
     $items = $currentOrder->Items();
     if ($items->count()) {
         foreach ($items as $item) {
             $js = $item->updateForAjax($js);
             $buyable = $item->Buyable(true);
             if ($buyable) {
                 //products in cart
                 $inCartArray[] = $buyable->AJAXDefinitions()->UniqueIdentifier();
                 //HACK TO INCLUDE PRODUCT IN PRODUCT VARIATION
                 if (is_a($buyable, "ProductVariation")) {
                     $inCartArray[] = $buyable->Product()->AJAXDefinitions()->UniqueIdentifier();
                 }
             }
         }
     }
     //in cart items
     $js[] = array("t" => "replaceclass", "s" => $inCartArray, "p" => $currentOrder->AJAXDefinitions()->ProductListItemClassName(), "v" => $currentOrder->AJAXDefinitions()->ProductListItemInCartClassName(), "without" => $currentOrder->AJAXDefinitions()->ProductListItemNotInCartClassName());
     //order modifiers
     $modifiers = $currentOrder->Modifiers();
     if ($modifiers->count()) {
         foreach ($modifiers as $modifier) {
             $js = $modifier->updateForAjax($js);
         }
     }
     //order
     $js = $currentOrder->updateForAjax($js);
     //messages
     if (is_array($messages)) {
         $js[] = array("t" => "id", "s" => $ajaxObject->TableMessageID(), "p" => "innerHTML", "v" => $messagesImploded, "isOrderMessage" => true);
         $js[] = array("t" => "id", "s" => $ajaxObject->TableMessageID(), "p" => "hide", "v" => 0);
     } else {
         $js[] = array("t" => "id", "s" => $ajaxObject->TableMessageID(), "p" => "hide", "v" => 1);
     }
     //TO DO: set it up in such a way that it specifically requests one of these
     $templates = EcommerceConfig::get("CartResponse", "cart_responses_required");
     foreach ($templates as $idMethod => $template) {
         $selector = $ajaxObject->{$idMethod}();
         $classOrID = "id";
         if (strpos($selector, "ID") === null || strpos($selector, "ClassName") !== null) {
             $selector = "class";
         }
         $js[] = array("t" => $classOrID, "s" => $ajaxObject->{$idMethod}(), "p" => "innerHTML", "v" => " " . $currentOrder->renderWith($template));
     }
     //now can check if it needs to be reloaded
     if (self::$force_reload) {
         $js = array("reload" => 1);
     } else {
         $js[] = array("reload" => 0);
     }
     //merge and return
     if (is_array($additionalData) && count($additionalData)) {
         $js = array_merge($js, $additionalData);
     }
     //TODO: remove doubles?
     //turn HTMLText (et al.) objects into text
     foreach ($js as $key => $node) {
         if (isset($node["v"])) {
             if ($node["v"] instanceof DBField) {
                 $js[$key]["v"] = $node["v"]->forTemplate();
             }
         }
     }
     $json = json_encode($js);
     $json = str_replace('\\t', " ", $json);
     $json = str_replace('\\r', " ", $json);
     $json = str_replace('\\n', " ", $json);
     $json = preg_replace('/\\s\\s+/', ' ', $json);
     if (Director::isDev()) {
         $json = str_replace("{", "\r\n{", $json);
     }
     return $json;
 }
예제 #19
0
 /**
  * Builds json object to be returned via ajax.
  *
  *@return JSON
  **/
 public function ReturnCartData($messages = array(), $data = null, $status = "success")
 {
     //add header
     $this->addHeader('Content-Type', 'application/json');
     SSViewer::set_source_file_comments(false);
     if ($status != "success") {
         $messagesImploded = '';
         foreach ($messages as $messageArray) {
             $messagesImploded .= '<span class="' . $messageArray["Type"] . '">' . $messageArray["Message"] . '</span>';
         }
         $this->setStatusCode(400, $messagesImploded);
     }
     //init Order - IMPORTANT
     $currentOrder = ShoppingCart::current_order();
     $currentOrder->calculateOrderAttributes(true);
     //now we have done the calculations you may find that we need to reload...
     $ajaxObject = $currentOrder->AJAXDefinitions();
     // populate Javascript
     $js = array();
     //order items
     $inCartArray = array();
     if ($items = $currentOrder->Items()) {
         foreach ($items as $item) {
             $item->updateForAjax($js);
             $buyable = $item->Buyable(true);
             if ($buyable) {
                 //products in cart
                 $inCartArray[] = $buyable->AJAXDefinitions()->UniqueIdentifier();
                 //HACK TO INCLUDE PRODUCT IN PRODUCT VARIATION
                 if ($buyable instanceof ProductVariation) {
                     $inCartArray[] = $buyable->Product()->AJAXDefinitions()->UniqueIdentifier();
                 }
             }
         }
     }
     //in cart items
     $js[] = array("t" => "replaceclass", "s" => $inCartArray, "p" => ".productActions.inCart", "v" => "inCart", "without" => "notInCart");
     if (isset($_REQUEST["loadingindex"])) {
         $js[] = array("t" => "loadingindex", "v" => $_REQUEST["loadingindex"]);
     }
     //order modifiers
     if ($modifiers = $currentOrder->Modifiers()) {
         foreach ($modifiers as $modifier) {
             $modifier->updateForAjax($js);
         }
     }
     //order
     $currentOrder->updateForAjax($js);
     //messages
     if (is_array($messages)) {
         $messagesImploded = '';
         foreach ($messages as $messageArray) {
             $messagesImploded .= '<span class="' . $messageArray["Type"] . '">' . $messageArray["Message"] . '</span>';
         }
         $js[] = array("t" => "id", "s" => $ajaxObject->TableMessageID(), "p" => "innerHTML", "v" => $messagesImploded, "isOrderMessage" => true);
         $js[] = array("t" => "id", "s" => $ajaxObject->TableMessageID(), "p" => "hide", "v" => 0);
     } else {
         $js[] = array("t" => "id", "s" => $ajaxObject->TableMessageID(), "p" => "hide", "v" => 1);
     }
     //TO DO: set it up in such a way that ir specifically requests one of these
     //tiny cart
     $js[] = array("t" => "class", "s" => $ajaxObject->TinyCartClassName(), "p" => "innerHTML", "v" => $currentOrder->renderWith("CartTinyInner"));
     //add basic cart
     $js[] = array("t" => "id", "s" => $ajaxObject->SmallCartID(), "p" => "innerHTML", "v" => $currentOrder->renderWith("CartShortInner"));
     //side bar cart
     $js[] = array("t" => "id", "s" => $ajaxObject->SideBarCartID(), "p" => "innerHTML", "v" => $currentOrder->renderWith("Sidebar_Cart_Inner"));
     //now can check if it needs to be reloaded
     if (self::$force_reload) {
         $js = array("reload" => 1);
     } else {
         $js[] = array("reload" => 0);
     }
     //merge and return
     if (is_array($data)) {
         $js = array_merge($js, $data);
     }
     //TODO: remove doubles!
     $json = Convert::array2json($js);
     $json = str_replace('\\t', " ", $json);
     $json = str_replace('\\r', " ", $json);
     $json = str_replace('\\n', " ", $json);
     $json = preg_replace('/\\s\\s+/', ' ', $json);
     $json = str_replace("{", "\r\n{", $json);
     return $json;
 }
 static function apply_min_max()
 {
     if (self::$min_field || self::$max_field || self::$default_min_quantity || self::$default_max_quantity) {
         $msgArray = array();
         $minFieldName = self::$min_field;
         $maxFieldName = self::$max_field;
         $currentOrder = ShoppingCart::current_order();
         if ($currentOrder->IsSubmitted()) {
             //too late!
             return;
         }
         $items = $currentOrder->Items();
         $i = 0;
         if ($items) {
             foreach ($items as $item) {
                 $buyable = $item->Buyable();
                 if ($buyable) {
                     $quantity = $item->Quantity;
                     $absoluteMin = self::$default_min_quantity;
                     $absoluteMax = self::$default_max_quantity;
                     $parent = $buyable->Parent();
                     if ($minFieldName) {
                         if (isset($buyable->{$minFieldName}) && $buyable->{$minFieldName} > 0) {
                             $absoluteMin = $buyable->{$minFieldName};
                         } elseif (!isset($buyable->{$minFieldName})) {
                             if ($parent && isset($parent->{$minFieldName}) && $parent->{$minFieldName} > 0) {
                                 $absoluteMin = $parent->{$minFieldName};
                             }
                         }
                     }
                     if ($maxFieldName) {
                         if (isset($buyable->{$maxFieldName}) && $buyable->{$maxFieldName} > 0) {
                             $absoluteMax = $buyable->{$maxFieldName};
                         } elseif (!isset($buyable->{$maxFieldName})) {
                             if ($parent && isset($parent->{$maxFieldName}) && $parent->{$maxFieldName} > 0) {
                                 $absoluteMax = $parent->{$maxFieldName};
                             }
                         }
                     }
                     if ($buyable->UnlimitedStock) {
                         //nothing more to do
                     } elseif (self::$use_stock_quantities) {
                         $maxStockQuantity = $buyable->getActualQuantity();
                         if ($absoluteMax > $maxStockQuantity) {
                             $absoluteMax = $maxStockQuantity;
                         }
                         if ($absoluteMin > $maxStockQuantity) {
                             $absoluteMax = 0;
                             $maxStockQuantity = 0;
                         }
                     }
                     $absoluteMin = intval($absoluteMin) - 0;
                     $absoluteMax = intval($absoluteMax) - 0;
                     $newValue = $quantity;
                     if ($quantity < $absoluteMin && $absoluteMin > 0) {
                         debug::log("adjusting for MIN: {$quantity} < {$absoluteMin}");
                         $newValue = $absoluteMin;
                     }
                     if ($quantity > $absoluteMax && $absoluteMax > 0) {
                         debug::log("adjusting for MAX: {$quantity} > {$absoluteMax}");
                         $newValue = $absoluteMax;
                     }
                     if ($quantity != $newValue) {
                         $item->Quantity = $newValue;
                         ShoppingCart::singleton()->setQuantity($buyable, $newValue);
                         $msgArray[$i] = $buyable->Title . " changed from " . $quantity . " to " . $newValue;
                         $i++;
                         $quantity = $newValue;
                         self::$ids_of_items_adjusted[$item->ID] = $item->ID;
                     }
                     if (Director::is_ajax()) {
                         //do nothing
                     } else {
                         //IS THIS WORKING?
                         $fieldName = $item->AJAXDefinitions()->QuantityFieldName();
                         $js = 'MinMaxModifier.add_item("input[name=\'' . $fieldName . '\']", ' . intval($absoluteMin) . ', ' . intval($absoluteMax) . ', "' . addslashes(self::$sorry_message) . '");';
                         Requirements::javascript("ecommerce_stockcontrol/javascript/MinMaxModifier.js");
                         Requirements::customScript($js, $fieldName);
                     }
                 }
             }
         }
     }
     if (count($msgArray)) {
         if (self::$adjustment_message) {
             $msg = self::$adjustment_message . "\n" . implode("\n", $msgArray);
             if ($msg && !Director::is_ajax()) {
                 Requirements::customScript('alert("' . Convert::raw2js($msg) . '");', "MinMaxModifierAlert");
             }
             //$this->Adjustments = $msg;
         }
     }
 }
예제 #21
0
 function __construct($controller, $name)
 {
     Requirements::themedCSS('OrderForm');
     // 1) Member and shipping fields
     $member = Member::currentUser() ? Member::currentUser() : singleton('Member');
     $memberFields = new CompositeField($member->getEcommerceFields());
     $requiredFields = $member->getEcommerceRequiredFields();
     if (ShoppingCart::uses_different_shipping_address()) {
         $countryField = new DropdownField('ShippingCountry', 'Country', Geoip::getCountryDropDown(), EcommerceRole::findCountry());
         $shippingFields = new CompositeField(new HeaderField('Send goods to different address', 3), new LiteralField('ShippingNote', '<p class="warningMessage"><em>Your goods will be sent to the address below.</em></p>'), new LiteralField('Help', '<p>You can use this for gift giving. No billing information will be disclosed to this address.</p>'), new TextField('ShippingName', 'Name'), new TextField('ShippingAddress', 'Address'), new TextField('ShippingAddress2', ''), new TextField('ShippingCity', 'City'), $countryField, new HiddenField('UseShippingAddress', '', true), new FormAction_WithoutLabel('useMemberShippingAddress', 'Use Billing Address for Shipping'));
         $requiredFields[] = 'ShippingName';
         $requiredFields[] = 'ShippingAddress';
         $requiredFields[] = 'ShippingCity';
         $requiredFields[] = 'ShippingCountry';
     } else {
         $countryField = $memberFields->fieldByName('Country');
         $shippingFields = new FormAction_WithoutLabel('useDifferentShippingAddress', 'Use Different Shipping Address');
     }
     $countryField->addExtraClass('ajaxCountryField');
     $setCountryLinkID = $countryField->id() . '_SetCountryLink';
     $setContryLink = ShoppingCart_Controller::set_country_link();
     $memberFields->push(new HiddenField($setCountryLinkID, '', $setContryLink));
     $leftFields = new CompositeField($memberFields, $shippingFields);
     $leftFields->setID('LeftOrder');
     $rightFields = new CompositeField();
     $rightFields->setID('RightOrder');
     if (!$member->ID || $member->Password == '') {
         $rightFields->push(new HeaderField('Membership Details', 3));
         $rightFields->push(new LiteralField('MemberInfo', "<p class=\"message good\">If you are already a member, please <a href=\"Security/login?BackURL=" . CheckoutPage::find_link(true) . "/\">log in</a>.</p>"));
         $rightFields->push(new LiteralField('AccountInfo', "<p>Please choose a password, so you can login and check your order history in the future.</p><br/>"));
         $rightFields->push(new FieldGroup(new ConfirmedPasswordField('Password', 'Password')));
         $requiredFields[] = 'Password[_Password]';
         $requiredFields[] = 'Password[_ConfirmPassword]';
     }
     // 2) Payment fields
     $currentOrder = ShoppingCart::current_order();
     $total = '$' . number_format($currentOrder->Total(), 2);
     $paymentFields = Payment::combined_form_fields("{$total} " . $currentOrder->Currency(), $currentOrder->Total());
     foreach ($paymentFields as $field) {
         $rightFields->push($field);
     }
     if ($paymentRequiredFields = Payment::combined_form_requirements()) {
         $requiredFields = array_merge($requiredFields, $paymentRequiredFields);
     }
     // 3) Put all the fields in one FieldSet
     $fields = new FieldSet($leftFields, $rightFields);
     // 4) Terms and conditions field
     // If a terms and conditions page exists, we need to create a field to confirm the user has read it
     if ($controller->TermsPageID && ($termsPage = DataObject::get_by_id('Page', $controller->TermsPageID))) {
         $bottomFields = new CompositeField(new CheckboxField('ReadTermsAndConditions', "I agree to the terms and conditions stated on the <a href=\"{$termsPage->URLSegment}\" title=\"Read the shop terms and conditions for this site\">terms and conditions</a> page"));
         $bottomFields->setID('BottomOrder');
         $fields->push($bottomFields);
         $requiredFields[] = 'ReadTermsAndConditions';
     }
     // 5) Actions and required fields creation
     $actions = new FieldSet(new FormAction('processOrder', 'Place order and make payment'));
     $requiredFields = new CustomRequiredFields($requiredFields);
     // 6) Form construction
     parent::__construct($controller, $name, $fields, $actions, $requiredFields);
     // 7) Member details loading
     if ($member->ID) {
         $this->loadDataFrom($member);
     }
     // 8) Country field value update
     $currentOrder = ShoppingCart::current_order();
     $currentOrderCountry = $currentOrder->findShippingCountry(true);
     $countryField->setValue($currentOrderCountry);
 }
 /**
  * work out the options for the user
  **/
 protected function workOutMessagesAndActions()
 {
     if (!$this->workedOutMessagesAndActions) {
         $this->actionLinks = new ArrayList(array());
         //what order are we viewing?
         $viewingRealCurrentOrder = $this->CurrentOrderIsInCart();
         $currentUserID = Member::currentUserID();
         //Continue Shopping
         if (isset($this->ContinueShoppingLabel) && $this->ContinueShoppingLabel) {
             if ($viewingRealCurrentOrder) {
                 if ($this->isCartPage()) {
                     $continueLink = $this->ContinueShoppingLink();
                     if ($continueLink) {
                         $this->actionLinks->push(new ArrayData(array("Title" => $this->ContinueShoppingLabel, "Link" => $continueLink)));
                     }
                 }
             }
         }
         //Proceed To CheckoutLabel
         if (isset($this->ProceedToCheckoutLabel) && $this->ProceedToCheckoutLabel) {
             if ($viewingRealCurrentOrder) {
                 if ($this->isCartPage()) {
                     $checkoutPageLink = CheckoutPage::find_link();
                     if ($checkoutPageLink && $this->currentOrder && $this->currentOrder->getTotalItems()) {
                         $this->actionLinks->push(new ArrayData(array("Title" => $this->ProceedToCheckoutLabel, "Link" => $checkoutPageLink)));
                     }
                 }
             }
         }
         //view account details
         if (isset($this->ShowAccountLabel) && $this->ShowAccountLabel) {
             if ($this->isOrderConfirmationPage() || $this->isCartPage()) {
                 if (AccountPage::find_link()) {
                     if ($currentUserID) {
                         $this->actionLinks->push(new ArrayData(array("Title" => $this->ShowAccountLabel, "Link" => AccountPage::find_link())));
                     }
                 }
             }
         }
         //go to current order
         if (isset($this->CurrentOrderLinkLabel) && $this->CurrentOrderLinkLabel) {
             if ($this->isCartPage()) {
                 if (!$viewingRealCurrentOrder) {
                     $this->actionLinks->push(new ArrayData(array("Title" => $this->CurrentOrderLinkLabel, "Link" => ShoppingCart::current_order()->Link())));
                 }
             }
         }
         //Save order - we assume only current ones can be saved.
         if (isset($this->SaveOrderLinkLabel) && $this->SaveOrderLinkLabel) {
             if ($viewingRealCurrentOrder) {
                 if ($currentUserID && $this->currentOrder->MemberID == $currentUserID) {
                     if ($this->isCartPage()) {
                         if ($this->currentOrder && $this->currentOrder->getTotalItems() && !$this->currentOrder->IsSubmitted()) {
                             $this->actionLinks->push(new ArrayData(array("Title" => $this->SaveOrderLinkLabel, "Link" => $this->Link("saveorder") . "/" . $this->currentOrder->ID . "/")));
                         }
                     }
                 }
             }
         }
         //load order
         if (isset($this->LoadOrderLinkLabel) && $this->LoadOrderLinkLabel) {
             if ($this->isCartPage() && $this->currentOrder) {
                 if (!$viewingRealCurrentOrder) {
                     $this->actionLinks->push(new ArrayData(array("Title" => $this->LoadOrderLinkLabel, "Link" => $this->Link("loadorder") . "/" . $this->currentOrder->ID . "/")));
                 }
             }
         }
         //delete order
         if (isset($this->DeleteOrderLinkLabel) && $this->DeleteOrderLinkLabel) {
             if ($this->isCartPage() && $this->currentOrder) {
                 if (!$viewingRealCurrentOrder) {
                     $this->actionLinks->push(new ArrayData(array("Title" => $this->DeleteOrderLinkLabel, "Link" => $this->Link("deleteorder") . "/" . $this->currentOrder->ID . "/")));
                 }
             }
         }
         //Start new order
         //Strictly speaking this is only part of the
         //OrderConfirmationPage but we put it here for simplicity's sake
         if (isset($this->StartNewOrderLinkLabel) && $this->StartNewOrderLinkLabel) {
             if ($this->isOrderConfirmationPage()) {
                 $this->actionLinks->push(new ArrayData(array("Title" => $this->StartNewOrderLinkLabel, "Link" => CartPage::new_order_link($this->currentOrder->ID))));
             }
         }
         //copy order
         //Strictly speaking this is only part of the
         //OrderConfirmationPage but we put it here for simplicity's sake
         if (isset($this->CopyOrderLinkLabel) && $this->CopyOrderLinkLabel) {
             if ($this->isOrderConfirmationPage() && $this->currentOrder->ID) {
                 $this->actionLinks->push(new ArrayData(array("Title" => $this->CopyOrderLinkLabel, "Link" => OrderConfirmationPage::copy_order_link($this->currentOrder->ID))));
             }
         }
         //actions from modifiers
         if ($this->isOrderConfirmationPage() && $this->currentOrder->ID) {
             $modifiers = $this->currentOrder->Modifiers();
             if ($modifiers->count()) {
                 foreach ($modifiers as $modifier) {
                     $array = $modifier->PostSubmitAction();
                     if (is_array($array) && count($array)) {
                         $this->actionLinks->push(new ArrayData($array));
                     }
                 }
             }
         }
         //log out
         //Strictly speaking this is only part of the
         //OrderConfirmationPage but we put it here for simplicity's sake
         if (Member::currentUser()) {
             if ($this->isOrderConfirmationPage()) {
                 $this->actionLinks->push(new ArrayData(array("Title" => _t("CartPage.LOGOUT", "log out"), "Link" => "/Security/logout/")));
             }
         }
         //no items
         if ($this->currentOrder) {
             if (!$this->currentOrder->getTotalItems()) {
                 $this->message = $this->NoItemsInOrderMessage;
             }
         } else {
             $this->message = $this->NonExistingOrderMessage;
         }
         $this->workedOutMessagesAndActions = true;
         //does nothing at present....
     }
 }
 /**
  * This function works out the most likely country for the current order.
  *
  * @param Boolean $recalculate
  *
  * @return String - Country Code - e.g. NZ
  **/
 public static function get_country($recalculate = false)
 {
     if (self::$get_country_cache === null || $recalculate) {
         $countryCode = '';
         //1. fixed country is first
         $countryCode = self::get_fixed_country_code();
         if (!$countryCode) {
             //2. check shipping address
             if ($o = ShoppingCart::current_order()) {
                 $countryCode = $o->Country();
             }
             //3. check GEOIP information
             if (!$countryCode) {
                 $countryCode = self::get_country_from_ip();
                 //4 check default country set in GEO IP....
                 if (!$countryCode) {
                     $countryCode = EcommerceConfig::get('EcommerceCountry', 'default_country_code');
                     //5. take the FIRST country from the get_allowed_country_codes
                     if (!$countryCode) {
                         $countryArray = self::list_of_allowed_entries_for_dropdown();
                         if (is_array($countryArray) && count($countryArray)) {
                             foreach ($countryArray as $countryCode => $countryName) {
                                 //we stop at the first one... as we have no idea which one is the best.
                                 break;
                             }
                         }
                     }
                 }
             }
         }
         self::$get_country_cache = $countryCode;
     }
     return self::$get_country_cache;
 }
 /**
  * adds Javascript to the page to make it work when products are cached.
  */
 public function CachingRelatedJavascript()
 {
     if ($this->ProductGroupListAreAjaxified()) {
         Requirements::customScript("\n\t\t\t\t\tEcomCart.set_ajaxifyProductList(true);\n\t\t\t\t\tEcomCart.set_ajaxifiedListHolderSelector('#" . $this->AjaxDefinitions()->ProductListHolderID() . "');\n\t\t\t\t\tEcomCart.set_ajaxifiedListAdjusterSelectors('." . $this->AjaxDefinitions()->ProductListAjaxifiedLinkClassName() . "');\n\t\t\t\t\tEcomCart.set_hiddenPageTitleID('#" . $this->AjaxDefinitions()->HiddenPageTitleID() . "');\n\t\t\t\t", "cachingRelatedJavascript_AJAXlist");
     } else {
         Requirements::customScript("EcomCart.set_ajaxifyProductList(false);", "cachingRelatedJavascript_AJAXlist");
     }
     $currentOrder = ShoppingCart::current_order();
     if ($currentOrder->TotalItems(true)) {
         $responseClass = EcommerceConfig::get("ShoppingCart", "response_class");
         $obj = new $responseClass();
         $obj->setIncludeHeaders(false);
         $json = $obj->ReturnCartData();
         Requirements::customScript("\n\t\t\t\t\tEcomCart.set_initialData(" . $json . ");\n\t\t\t\t", "cachingRelatedJavascript_JSON");
     }
 }
 /**
  *
  * @param Controller
  * @param String
  */
 function __construct(Controller $controller, $name)
 {
     //set basics
     $requiredFields = array();
     //requirements
     Requirements::javascript('ecommerce/javascript/EcomOrderFormAddress.js');
     // LEAVE HERE - NOT EASY TO INCLUDE VIA TEMPLATE
     if (EcommerceConfig::get("OrderAddress", "use_separate_shipping_address")) {
         Requirements::javascript('ecommerce/javascript/EcomOrderFormShipping.js');
         // LEAVE HERE - NOT EASY TO INCLUDE VIA TEMPLATE
     }
     //  ________________ 1) Order + Member + Address fields
     //find member
     $this->order = ShoppingCart::current_order();
     $this->orderMember = $this->order->CreateOrReturnExistingMember(false);
     $this->loggedInMember = Member::currentUser();
     //strange security situation...
     if ($this->orderMember->exists() && $this->loggedInMember) {
         if ($this->orderMember->ID != $this->loggedInMember->ID) {
             if (!$this->loggedInMember->IsShopAdmin()) {
                 $this->loggedInMember->logOut();
             }
         }
     }
     $addressFieldsBilling = new FieldList();
     //member fields
     if ($this->orderMember) {
         $memberFields = $this->orderMember->getEcommerceFields();
         $requiredFields = array_merge($requiredFields, $this->orderMember->getEcommerceRequiredFields());
         $addressFieldsBilling->merge($memberFields);
     }
     //billing address field
     $billingAddress = $this->order->CreateOrReturnExistingAddress("BillingAddress");
     $billingAddressFields = $billingAddress->getFields($this->orderMember);
     $requiredFields = array_merge($requiredFields, $billingAddress->getRequiredFields());
     $addressFieldsBilling->merge($billingAddressFields);
     //shipping address field
     $addressFieldsShipping = null;
     if (EcommerceConfig::get("OrderAddress", "use_separate_shipping_address")) {
         $addressFieldsShipping = new FieldList();
         //add the important CHECKBOX
         $useShippingAddressField = new FieldList(new CheckboxField("UseShippingAddress", _t("OrderForm.USESHIPPINGADDRESS", "Use an alternative shipping address")));
         $addressFieldsShipping->merge($useShippingAddressField);
         //now we can add the shipping fields
         $shippingAddress = $this->order->CreateOrReturnExistingAddress("ShippingAddress");
         $shippingAddressFields = $shippingAddress->getFields($this->orderMember);
         //we have left this out for now as it was giving a lot of grief...
         //$requiredFields = array_merge($requiredFields, $shippingAddress->getRequiredFields());
         //finalise left fields
         $addressFieldsShipping->merge($shippingAddressFields);
     }
     $leftFields = new CompositeField($addressFieldsBilling);
     $leftFields->addExtraClass('leftOrderBilling');
     $allLeftFields = new CompositeField($leftFields);
     $allLeftFields->addExtraClass('leftOrder');
     if ($addressFieldsShipping) {
         $leftFieldsShipping = new CompositeField($addressFieldsShipping);
         $leftFieldsShipping->addExtraClass('leftOrderShipping');
         $allLeftFields->push($leftFieldsShipping);
     }
     //  ________________  2) Log in / vs Create Account fields - RIGHT-HAND-SIDE fields
     $rightFields = new CompositeField();
     $rightFields->addExtraClass('rightOrder');
     //to do: simplify
     if (EcommerceConfig::get("EcommerceRole", "allow_customers_to_setup_accounts")) {
         if ($this->orderDoesNotHaveFullyOperationalMember()) {
             //general header
             if (!$this->loggedInMember) {
                 $rightFields->push(new LiteralField('MemberInfo', '<p class="message good">' . _t('OrderForm.MEMBERINFO', 'If you already have an account then please') . " <a href=\"Security/login/?BackURL=/" . urlencode(implode("/", $controller->getURLParams())) . "\">" . _t('OrderForm.LOGIN', 'log in') . '</a>.</p>'));
             }
         } else {
             if ($this->loggedInMember) {
                 $rightFields->push(new LiteralField('LoginNote', "<p class=\"message good\">" . _t("Account.LOGGEDIN", "You are logged in as ") . Convert::raw2xml($this->loggedInMember->FirstName) . ' ' . Convert::raw2xml($this->loggedInMember->Surname) . ' (' . Convert::raw2xml($this->loggedInMember->Email) . ').' . ' <a href="/Security/logout/">' . _t("Account.LOGOUTNOW", "Log out?") . '</a>' . '</p>'));
             }
         }
         if ($this->orderMember->exists()) {
             if ($this->loggedInMember) {
                 if ($this->loggedInMember->ID != $this->orderMember->ID) {
                     $rightFields->push(new LiteralField('OrderAddedTo', "<p class=\"message good\">" . _t("Account.ORDERADDEDTO", "Order will be added to ") . Convert::raw2xml($this->orderMember->FirstName) . ' ' . Convert::raw2xml($this->orderMember->Surname) . ' (' . Convert::raw2xml($this->orderMember->Email) . ').</p>'));
                 }
             }
         }
     }
     //  ________________  5) Put all the fields in one FieldList
     $fields = new FieldList($rightFields, $allLeftFields);
     //  ________________  6) Actions and required fields creation + Final Form construction
     $nextButton = new FormAction('saveAddress', _t('OrderForm.NEXT', 'Next'));
     $nextButton->addExtraClass("next");
     $actions = new FieldList($nextButton);
     $validator = OrderFormAddress_Validator::create($requiredFields);
     parent::__construct($controller, $name, $fields, $actions, $validator);
     $this->setAttribute("autocomplete", "off");
     //extensions need to be set after __construct
     //extension point
     $this->extend('updateFields', $fields);
     $this->setFields($fields);
     $this->extend('updateActions', $actions);
     $this->setActions($actions);
     $this->extend('updateValidator', $validator);
     $this->setValidator($validator);
     //this needs to come after the extension calls
     foreach ($validator->getRequired() as $requiredField) {
         $field = $fields->dataFieldByName($requiredField);
         if ($field) {
             $field->addExtraClass("required");
         }
     }
     //  ________________  7)  Load saved data
     //we do this first so that Billing and Shipping Address can override this...
     if ($this->orderMember) {
         $this->loadDataFrom($this->orderMember);
     }
     if ($this->order) {
         $this->loadDataFrom($this->order);
         if ($billingAddress) {
             $this->loadDataFrom($billingAddress);
         }
         if (EcommerceConfig::get("OrderAddress", "use_separate_shipping_address")) {
             if ($shippingAddress) {
                 $this->loadDataFrom($shippingAddress);
             }
         }
     }
     //allow updating via decoration
     $oldData = Session::get("FormInfo.{$this->FormName()}.data");
     if ($oldData && (is_array($oldData) || is_object($oldData))) {
         $this->loadDataFrom($oldData);
     }
     $this->extend('updateOrderFormAddress', $this);
 }
 protected function LiveCountry()
 {
     $order = ShoppingCart::current_order();
     return $order->findShippingCountry(true);
 }
 /**
  * TODO: change to submitted from CustomerCanEdit criteria
  */
 protected function workoutActualQuantity()
 {
     $actualQuantity = 0;
     if ($buyable = $this->getBuyable()) {
         //set name
         //add total order quantities
         $data = DB::query("\r\n\t\t\t\tSELECT\r\n\t\t\t\t\t\"OrderItem\".\"BuyableID\",\r\n\t\t\t\t\tSum(\"OrderItem\".\"Quantity\")+0 \"QuantitySum\",\r\n\t\t\t\t\t\"Order\".\"ID\" \"OrderID\",\r\n\t\t\t\t\t\"OrderAttribute\".\"ClassName\",\r\n\t\t\t\t\t\"OrderItem\".\"BuyableClassName\",\r\n\t\t\t\t\t\"OrderStep\".\"CustomerCanEdit\"\r\n\t\t\t\tFROM\r\n\t\t\t\t\t\"Order\"\r\n\t\t\t\t\tINNER JOIN \"OrderAttribute\" ON \"OrderAttribute\".\"OrderID\" = \"Order\".\"ID\"\r\n\t\t\t\t\tINNER JOIN \"OrderItem\" ON \"OrderAttribute\".\"ID\" = \"OrderItem\".\"ID\"\r\n\t\t\t\t\tINNER JOIN \"OrderStep\" ON \"OrderStep\".\"ID\" = \"Order\".\"StatusID\"\r\n\t\t\t\tGROUP BY\r\n\t\t\t\t\t\"Order\".\"ID\", \"BuyableID\"\r\n\t\t\t\tHAVING\r\n\t\t\t\t\t\"OrderItem\".\"BuyableID\" = " . (intval($this->BuyableID) - 0) . "\r\n\t\t\t\t\tAND\r\n\t\t\t\t\t\"OrderItem\".\"BuyableClassName\" = '" . $this->BuyableClassName . "'\r\n\t\t\t\t\tAND\r\n\t\t\t\t\t\"OrderStep\".\"CustomerCanEdit\" = 0\r\n\t\t\t\t\tAND\r\n\t\t\t\t\t\"Order\".\"ID\" <> " . ShoppingCart::current_order()->ID . "\r\n\t\t\t");
         if ($data) {
             foreach ($data as $row) {
                 if ($row["OrderID"] && $this->ID && $row["QuantitySum"]) {
                     $buyableStockOrderEntry = BuyableStockOrderEntry::get()->filter(array('OrderID' => $row["OrderID"], 'ParentID' => $this->ID))->First();
                     if ($buyableStockOrderEntry) {
                         //do nothing
                     } else {
                         $buyableStockOrderEntry = new BuyableStockOrderEntry();
                         $buyableStockOrderEntry->OrderID = $row["OrderID"];
                         $buyableStockOrderEntry->ParentID = $this->ID;
                         $buyableStockOrderEntry->IncludeInCurrentCalculation = 1;
                         $buyableStockOrderEntry->Quantity = 0;
                     }
                     if ($buyableStockOrderEntry->Quantity != $row["QuantitySum"]) {
                         $buyableStockOrderEntry->Quantity = $row["QuantitySum"];
                         $buyableStockOrderEntry->write();
                     }
                 }
             }
         }
         //find last adjustment
         $latestManualUpdate = BuyableStockManualUpdate::get()->filter(array('ParentID' => $this->ID))->sort(array('LastEdited' => 'DESC'))->First();
         //nullify order quantities that were entered before last adjustment
         if ($latestManualUpdate) {
             $latestManualUpdateQuantity = $latestManualUpdate->Quantity;
             DB::query("\r\n\t\t\t\t\tUPDATE \"BuyableStockOrderEntry\"\r\n\t\t\t\t\tSET \"IncludeInCurrentCalculation\" = 0\r\n\t\t\t\t\tWHERE\r\n\t\t\t\t\t\"LastEdited\" < '" . $latestManualUpdate->LastEdited . "'\r\n\t\t\t\t\t\tAND\r\n\t\t\t\t\t\t\"ParentID\" = " . $this->ID);
         } else {
             $latestManualUpdateQuantity = 0;
         }
         //work out additional purchases
         $orderQuantityToDeduct = BuyableStockOrderEntry::get()->filter(array('ParentID' => $this->ID, 'IncludeInCurrentCalculation' => 1))->sum('Quantity');
         if (!$orderQuantityToDeduct) {
             $orderQuantityToDeduct = 0;
         }
         //work out base total
         $actualQuantity = $latestManualUpdateQuantity - $orderQuantityToDeduct;
         if (isset($_GET["debug"])) {
             echo "<hr />";
             echo $this->Name;
             echo " | Manual SUM: " . $latestManualUpdateQuantity;
             echo " | Order SUM: " . $orderQuantityToDeduct;
             echo " | Total SUM: " . $this->BaseQuantity;
             echo "<hr />";
         }
     }
     return $actualQuantity;
 }
예제 #28
0
 /**
  * Return the global tax information of the site.
  * @todo review this, and decide if it is necessary.
  * @return TaxModifier
  */
 function TaxInfo()
 {
     $currentOrder = ShoppingCart::current_order();
     return $currentOrder->TaxInfo();
 }
 function submit(array $data, Form $form, $message = "Order updated", $status = "good")
 {
     if (isset($data['DiscountCouponCode'])) {
         $order = ShoppingCart::current_order();
         if ($order) {
             $modifiers = $order->Modifiers('DiscountCouponModifier');
             $modifier = $modifiers->First();
             if ($modifier) {
                 list($message, $type) = $modifier->updateCouponCodeEntered(Convert::raw2sql($data['DiscountCouponCode']));
                 $form->addErrorMessage("DiscountCouponCode", $message, $type);
                 return ShoppingCart::singleton()->setMessageAndReturn($message, $type);
             }
         }
     }
     return ShoppingCart::singleton()->setMessageAndReturn(_t("DiscountCouponModifier.NOTAPPLIED", "Coupon could not be found.", "bad"));
 }
 function submit($request)
 {
     $buyableArray = null;
     $this->rowNumbers = intval($_REQUEST["rowNumbers"]);
     $array = array();
     $nameArray = array();
     for ($i = 0; $i <= $this->rowNumbers; $i++) {
         if (isset($_REQUEST["buyable_{$i}"])) {
             $explodeArray = explode("_", $_REQUEST["buyable_{$i}"]);
             if (is_array($explodeArray) && count($explodeArray) == 2) {
                 list($className, $id) = $explodeArray;
                 if (class_exists($className)) {
                     $id = intval($id);
                     if ($buyable = DataObject::get_by_id($className, $id)) {
                         $qty = round($_REQUEST["qty_{$i}"], $buyable->QuantityDecimals());
                         if ($qty) {
                             $buyable->Qty = 0;
                             $name = strtoupper(Convert::raw2sql(Convert::raw2xml($_REQUEST["name_{$i}"])));
                             $buyableClassNameAndID = $className . "_" . $id;
                             $price = $buyable->getCalculatedPrice();
                             $total = $price * $qty;
                             $innerArray = array("Name" => $name, "Qty" => $qty, "BuyableClassNameAndID" => $buyableClassNameAndID, "ClassName" => $className, "ID" => $id, "Buyable" => $buyable, "Price" => $price, "Total" => $total, "MyTitle" => $buyable->Title);
                             $array[$i] = $innerArray;
                             $buyableArray[$buyableClassNameAndID][] = $innerArray;
                             $nameArray[$name][$buyableClassNameAndID][] = $innerArray;
                         }
                     }
                 }
             }
         }
     }
     Session::set("AddProductsToOrderRows", serialize($array));
     $array = null;
     $innerArray = null;
     $buyable = null;
     // per BUYABLE
     $buyableSummaryDos = null;
     $buyableGrandTotal = 0;
     if (is_array($buyableArray) && count($buyableArray)) {
         $buyableSummaryDos = new DataObjectSet();
         foreach ($buyableArray as $buyableClassNameAndID => $buyables) {
             $buyableQty = 0;
             $buyableTotal = 0;
             foreach ($buyables as $buyableEntry) {
                 $buyableQty += $buyableEntry["Qty"];
                 $buyableTotal += $buyableEntry["Total"];
             }
             $myTitle = $buyableEntry["MyTitle"];
             $price = $buyableEntry["Price"];
             $buyableDo = new DataObject();
             $buyableDo->MyTitle = $myTitle;
             $buyableDo->Buyable = $buyableEntry["Buyable"];
             $buyableDo->Qty = $buyableQty;
             $buyableDo->Price = $price;
             $buyableDo->PriceNice = DBField::create("Currency", $price, "PriceNice" . $buyableClassNameAndID)->Nice();
             $buyableDo->Total = $buyableTotal;
             $buyableDo->TotalNice = DBField::create("Currency", $buyableTotal, "TotalNice" . $buyableClassNameAndID)->Nice();
             $buyableSummaryDos->push($buyableDo);
             $buyableGrandTotal += $buyableTotal;
         }
     }
     $buyableGrandTotalNice = DBField::create("Currency", $buyableGrandTotal, "buyableGrandTotal")->Nice();
     // per NAME
     $nameSummaryDos = null;
     $nameGrandTotal = 0;
     if (count($nameArray)) {
         $nameSummaryDos = new DataObjectSet();
         $buyablesDos = array();
         foreach ($nameArray as $name => $nameEntry) {
             $nameDo = new DataObject();
             $nameDo->Name = $name;
             $nameTotal = 0;
             $nameQty = 0;
             if (count($nameEntry)) {
                 $buyableDo = array();
                 $nameDo->Buyables = new DataObjectSet();
                 foreach ($nameEntry as $buyableClassNameAndID => $buyables) {
                     if (count($buyables)) {
                         $buyableQty = 0;
                         $buyableTotal = 0;
                         foreach ($buyables as $buyableEntry) {
                             $buyableQty += $buyableEntry["Qty"];
                             $buyableTotal += $buyableEntry["Total"];
                             $nameQty += $buyableEntry["Qty"];
                             $nameTotal += $buyableEntry["Total"];
                         }
                         $myTitle = $buyableEntry["MyTitle"];
                         $price = $buyableEntry["Price"];
                         $buyableDo[$buyableClassNameAndID] = new DataObject();
                         $buyableDo[$buyableClassNameAndID]->MyTitle = $myTitle;
                         //$buyableDo->Buyable = $buyableEntry["Buyable"];
                         $buyableDo[$buyableClassNameAndID]->Qty = $buyableQty;
                         $buyableDo[$buyableClassNameAndID]->Price = $price;
                         $buyableDo[$buyableClassNameAndID]->PriceNice = DBField::create("Currency", $price, "PriceNice" . $buyableClassNameAndID)->Nice();
                         $buyableDo[$buyableClassNameAndID]->Total = $buyableTotal;
                         $buyableDo[$buyableClassNameAndID]->TotalNice = DBField::create("Currency", $buyableTotal, "TotalNice" . $buyableClassNameAndID)->Nice();
                         $nameDo->Buyables->push($buyableDo[$buyableClassNameAndID]);
                         $nameGrandTotal += $buyableTotal;
                     }
                 }
             }
             $nameDo->Qty = $nameQty;
             $nameDo->Total = $nameTotal;
             $nameDo->TotalNice = DBField::create("Currency", $nameTotal, "TotalNice" . $name)->Nice();
             $nameSummaryDos->push($nameDo);
         }
     }
     $nameGrandTotalNice = DBField::create("Currency", $nameGrandTotal, "nameGrandTotal")->Nice();
     $customiseArray = array("Message" => "", "BuyableSummary" => $buyableSummaryDos, "NameSummary" => $nameSummaryDos, "BuyableGrandTotalNice" => $buyableGrandTotalNice, "NameGrandTotalNice" => $nameGrandTotalNice);
     //submit?
     if (isset($_REQUEST["submit"]) && $_REQUEST["submit"] || isset($_REQUEST["quote"]) && $_REQUEST["quote"]) {
         if ($buyableSummaryDos) {
             $sc = ShoppingCart::singleton();
             foreach ($buyableSummaryDos as $buyableDo) {
                 $sc->addBuyable($buyableDo->Buyable, $buyableDo->Qty);
             }
             $checkoutPage = DataObject::get_one("CheckoutPage");
             $html = $this->customise($customiseArray)->renderWith("AddProductsToOrderResultsAjax");
             $logEntry = DataObject::get_one("AddUpProductsToOrderPageStatusLog", "OrderID = " . ShoppingCart::current_order()->ID);
             if (!$logEntry) {
                 $logEntry = new AddUpProductsToOrderPageStatusLog();
                 $logEntry->OrderID = $sc->currentOrder()->ID;
             }
             $logEntry->Title = $this->OrderLogEntryTitle ? $this->OrderLogEntryTitle : "Order Breakdown";
             $logEntry->Note = $html;
             $logEntry->write();
             Session::set("AddProductsToOrderRows", null);
             Session::save();
             Session::clear("AddProductsToOrderRows");
             Session::save();
             $customiseArray["Message"] = "Entries updated.";
         } else {
             $customiseArray["Message"] = "No products added.";
         }
     } else {
         if ($buyableSummaryDos) {
             $customiseArray["Message"] = "Entries updated.";
         } else {
             $customiseArray["Message"] = "No products added.";
         }
     }
     return $this->customise($customiseArray)->renderWith("AddProductsToOrderResultsAjax");
 }