/**
  * 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 a radio button list of shipping options
  * to the end user and process the chosen option
  *
  * @return void
  */
 public function actionShippingOptions()
 {
     $this->publishJS('shipping');
     $this->publishJS('zippo');
     $this->layout = '/layouts/checkout';
     $this->checkoutForm = MultiCheckoutForm::loadFromSessionOrNew();
     // Check whether the user has selected a shipping option.
     if (isset($_POST['MultiCheckoutForm'])) {
         $this->checkoutForm->attributes = $_POST['MultiCheckoutForm'];
         $this->checkoutForm->hasTaxModeChanged = false;
         $this->checkoutForm->setScenario('ShippingOptions');
         if ($this->checkoutForm->validate() === true) {
             $this->checkoutForm->saveFormToSession();
             // Update the cart shipping in the database.
             // 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());
             }
             $this->checkoutForm->passedScenario = $this->checkoutForm->getScenario();
             $this->redirect($this->createUrl('/checkout/final'));
         } else {
             Yii::log(sprintf('Validation of the checkout form failed: %s', print_r($this->checkoutForm->getErrors(), true)), 'error', 'application.' . __CLASS__ . '.' . __FUNCTION__);
         }
     }
     // In the case where the destination does not have a defined tax code,
     // return to the shipping page with an error message.
     if (Checkout::verifyUserShippingDestination($this->checkoutForm) === false) {
         Yii::log(sprintf('Shipping destination is invalid: country=%s state=%s postal=%s', $this->checkoutForm->shippingCountryCode, $this->checkoutForm->shippingStateCode, $this->checkoutForm->shippingPostal), 'error', 'application.' . __CLASS__ . "." . __FUNCTION__);
         $this->redirect(array('/checkout/shipping', 'error-destination' => true));
         return;
     }
     // Update the cart taxes prior to updating the cart scenarios.
     Yii::app()->shoppingcart->setTaxCodeByCheckoutForm($this->checkoutForm);
     $arrCartScenario = Shipping::loadCartScenariosFromSession();
     // In the case where no shipping options are available, return to the
     // shipping page with an error message.
     // TODO: This isn't quite right. If store pickup is the only option, we
     // also want to display this error because store pickup is not shown
     // shown on the shipping options screen. See WS-3267.
     if ($arrCartScenario === null || count($arrCartScenario) === 0) {
         Yii::log(sprintf('No shipping options available: country=%s state=%s postal=%s', $this->checkoutForm->shippingCountryCode, $this->checkoutForm->shippingStateCode, $this->checkoutForm->shippingPostal), 'info', 'application.' . __CLASS__ . "." . __FUNCTION__);
         $this->redirect(array('/checkout/shipping', 'error-destination' => true));
         return;
     }
     // Render the shipping options.
     // The options themselves are loaded from the session.
     // The implication here is that before redirecting to this page, ensure
     // that the shipping options stored in the session are up to date.
     $this->render('shippingoptions', array('model' => $this->checkoutForm, 'arrCartScenario' => $arrCartScenario, 'error' => $this->formatErrors()));
 }