/**
  * Run the widget. Renders the shipping estimator lines on the page.
  */
 public function run()
 {
     // Required assets.
     $assets = Yii::app()->getAssetManager()->publish(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'assets', false, -1, true);
     Yii::app()->clientScript->registerScriptFile($assets . '/js/WsShippingEstimator.js');
     $pathToZippo = Yii::getPathOfAlias('ext') . DIRECTORY_SEPARATOR . 'wsadvcheckout' . DIRECTORY_SEPARATOR . 'assets';
     $assets = Yii::app()->getAssetManager()->publish($pathToZippo, false, -1, true);
     Yii::app()->clientScript->registerScriptFile($assets . '/zippo.js');
     $checkoutForm = MultiCheckoutForm::loadFromSessionOrNew();
     // We may wish to update the shipping options right away if we know the
     // cart has changed.
     $updateOnLoad = false;
     if ($this->updateShippingOptions) {
         // This check for shippingCountry being null is a workaround to fix
         // WS-3180. When shippingCountry is null, we need to update the
         // shipping estimates *now* because they will not be updated by the
         // JavaScript (since the JavaScript in WsShippingEstimator requires
         // country to be set). The reason we need to do this is because
         // shippingCountry may be null when in-store pickup has been
         // chosen.
         // TODO: Fix this in WsShippingEstimator and remove this workaround.
         if (empty($checkoutForm->shippingCountry) || empty($checkoutForm->shippingPostal)) {
             Shipping::updateCartScenariosInSession();
         } else {
             $updateOnLoad = true;
         }
     }
     // Use the shipping scenarios and shipping address in the session.
     $arrCartScenario = Shipping::loadCartScenariosFromSession();
     $wsShippingEstimatorOptions = self::getShippingEstimatorOptions($arrCartScenario, $checkoutForm->shippingProvider, $checkoutForm->shippingPriority, $checkoutForm->shippingCity, $checkoutForm->shippingStateCode, $checkoutForm->shippingCountryCode, $updateOnLoad);
     $selectedCartScenario = Shipping::getSelectedCartScenarioFromSession();
     if ($selectedCartScenario !== null) {
         $formattedShippingPrice = $selectedCartScenario['formattedShippingPrice'];
         $formattedCartTax = $selectedCartScenario['formattedCartTax'];
     } else {
         $formattedShippingPrice = null;
         $formattedCartTax = null;
     }
     $this->render('_shippingestimator', array('countries' => CHtml::listData(Country::getShippingCountries(), 'code', 'country'), 'formattedShippingPrice' => $formattedShippingPrice, 'formattedCartTax' => $formattedCartTax, 'shippingCountryCode' => $wsShippingEstimatorOptions['shippingCountryCode'], 'shippingCountryName' => $wsShippingEstimatorOptions['shippingCountryName'], 'shippingPostal' => $checkoutForm->shippingPostal, 'wsShippingEstimatorOptions' => CJSON::encode($wsShippingEstimatorOptions), 'cssClass' => self::CSS_CLASS));
 }
 /**
  * Display the logged in user's list of addresses
  * and handle them choosing one
  *
  * @return void
  */
 public function actionShippingAddress()
 {
     $this->publishJS('shipping');
     $this->publishJS('zippo');
     $this->layout = '/layouts/checkout';
     $error = null;
     $this->checkoutForm = MultiCheckoutForm::loadFromSessionOrNew();
     $arrObjAddresses = CustomerAddress::getActiveAddresses();
     // if the logged in customer has no addresses saved on file
     // take them to the page where they can enter an address
     if (count($arrObjAddresses) < 1) {
         $this->redirect($this->createAbsoluteUrl('/checkout/shipping'));
     }
     $arrFirst = array();
     $objCart = Yii::app()->shoppingcart;
     // if the logged in user has a default shipping address
     // make it appear first
     foreach ($arrObjAddresses as $key => $address) {
         if ($address->id == $objCart->customer->default_shipping_id) {
             $arrFirst['first'] = $address;
             // assign an index to avoid accidental overwrite
             unset($arrObjAddresses[$key]);
         }
     }
     $this->checkoutForm->objAddresses = array_values($arrFirst + $arrObjAddresses);
     $this->checkoutForm->saveFormToSession();
     // populate our form with some default values in case the user
     // was logged in already and bypassed checkout login
     if (isset($this->checkoutForm->contactEmail) === false) {
         $this->checkoutForm->contactEmail = $objCart->customer->email;
     }
     if (isset($this->checkoutForm->contactEmail_repeat) === false) {
         $this->checkoutForm->contactEmail_repeat = $objCart->customer->email;
     }
     if (isset($_POST['MultiCheckoutForm'])) {
         $this->checkoutForm->attributes = $_POST['MultiCheckoutForm'];
     }
     $hasErrors = false;
     $inStorePickupSelected = isset($_POST['storePickupCheckBox']) && $_POST['storePickupCheckBox'] == 1;
     // If in-store pickup was previously selected but has been deselected, make sure it's no longer used.
     if ($inStorePickupSelected === false && $this->checkoutForm->isStorePickupSelected()) {
         // TODO: Factor out this and the similar check in actionShipping.
         $this->checkoutForm->shippingProvider = null;
         $this->checkoutForm->shippingPriority = null;
         $this->checkoutForm->pickupFirstName = null;
         $this->checkoutForm->pickupLastName = null;
     }
     $addressId = Yii::app()->getRequest()->getPost('Address_id');
     $wishlistId = Yii::app()->getRequest()->getPost('wishlistId');
     // Store pickup.
     if ($inStorePickupSelected === true) {
         // store pickup is chosen
         $this->checkoutForm->fillFieldsForStorePickup();
         $this->checkoutForm->setScenario('StorePickup');
         $redirectUrl = $this->createUrl('/checkout/final');
         if ($this->checkoutForm->validate() === false) {
             $hasErrors = true;
         }
     } elseif ($addressId || $wishlistId) {
         $customerId = null;
         if ($wishlistId) {
             $wishlist = Wishlist::model()->findByPk($wishlistId);
             $addressId = $wishlist->ship_option;
             $customerId = $wishlist->customer_id;
         }
         // An existing shipping address is chosen.
         $result = $this->checkoutForm->fetchCustomerShippingAddress($addressId, $customerId);
         if ($result === false) {
             $this->redirect($this->createAbsoluteUrl("/checkout/shippingaddress"));
         }
         $this->checkoutForm->setScenario('Shipping');
         $redirectUrl = $this->createUrl('/checkout/shippingoptions');
         if ($this->checkoutForm->validate() == false) {
             $hasErrors = true;
         }
     } else {
         $wishlist = null;
         $wishlistAddress = null;
         // If any of the cart items are on a wishlist, then we show the
         // wishlist address to the user.
         foreach ($objCart->cartItems as $item) {
             if ($item->wishlist_item !== null) {
                 $wishlist = $item->wishlistItem()->registry();
                 $wishlistAddressId = $wishlist->ship_option;
                 $wishlistAddress = CustomerAddress::model()->findByPk($wishlistAddressId);
                 break;
                 // Multiple wishlist addresses are not yet supported.
             }
         }
         // Nothing was posted, just render the shipping address page.
         $this->render('shippingaddress', array('model' => $this->checkoutForm, 'error' => $this->formatErrors(), 'wishlist' => $wishlist, 'wishlistAddress' => $wishlistAddress));
         return;
     }
     // Update address ID if there are no errors.
     if ($hasErrors === false) {
         $this->checkoutForm->updateAddressId();
         // An error occurred in updateAddressId.
         if (count($this->checkoutForm->getErrors())) {
             $hasErrors = true;
         }
     }
     // A validation error occurred.
     if ($hasErrors === true) {
         $this->render('shippingaddress', array('model' => $this->checkoutForm, 'error' => $this->formatErrors()));
         return;
     }
     // Update the shipping scenarios based on the new address.
     $this->checkoutForm->saveFormToSession();
     Shipping::updateCartScenariosInSession();
     // If in-store pickup was selected we need to update the cart now
     // before moving to checkout/final. Otherwise, the address will be
     // validated at the next step and the taxes updated.
     if ($inStorePickupSelected === true) {
         // Update the shopping cart taxes.
         Yii::app()->shoppingcart->setTaxCodeByCheckoutForm($this->checkoutForm);
         // Update shipping. If in-store pickup was chosen then we need to
         // ensure the cart shipping values are updated.
         // Update shipping. If in-store pickup was chosen then we need to
         // ensure the cart shipping values are updated.
         $objShipping = CartShipping::getOrCreateCartShipping();
         if ($objShipping->hasErrors() === false) {
             $objShipping->updateShipping();
             $this->checkoutForm->addErrors($objShipping->getErrors());
         } else {
             $this->checkoutForm->addErrors($objShipping->getErrors());
         }
     }
     // Save the passed scenario and redirect to the next stage.
     $this->checkoutForm->passedScenario = $this->checkoutForm->getScenario();
     $this->redirect($redirectUrl);
 }
 /**
  * Ajax receiver function to remove the promocode on the modals and new
  * checkout page.
  */
 public function actionRemovePromoCodeModal()
 {
     Yii::app()->shoppingcart->removePromoCode();
     // The option is provided to update the cart scenarios stored in the
     // session. This is a performance optimization that allows the
     // front-end to request updated cart totals separately using the
     // shipping estimator.
     if (Yii::app()->getRequest()->getPost('updateCartTotals') === 'true') {
         Shipping::updateCartScenariosInSession();
     }
     // If the cart scenarios are updated, we can return a version of
     // the shoppingcart with the newly updated totals.
     $formattedShoppingCart = static::formatCartScenarioWithCartItems(Shipping::getSelectedCartScenarioFromSessionOrShoppingCart());
     $this->renderJSON(array('removeResult' => array('action' => 'success'), 'shoppingCart' => $formattedShoppingCart));
 }