예제 #1
0
 /**
  * Add and/or update VAT entries
  *
  * Takes the class and rate of the VAT to be added from the $_POST array
  * variable and passes them on to {@link addVat()}.
  * Takes the IDs, classes and rates of the records to be updated from the
  * $_POST array variable and passes them on to {@link updateVat()}.
  * @static
  */
 static function update_vat()
 {
     //DBG::log("update_vat: ".self::$success.", changed: ".self::$changed);
     if (!empty($_POST['vatratenew'])) {
         self::$changed = true;
         self::$success &= Vat::addVat(trim(strip_tags(contrexx_input2raw($_POST['vatclassnew']))), floatval($_POST['vatratenew']));
     }
     //DBG::log("Success: ".self::$success.", changed: ".self::$changed);
     if (!empty($_POST['vatclass'])) {
         $result = Vat::updateVat(contrexx_input2raw($_POST['vatclass']), $_POST['vatrate']);
         if (isset($result)) {
             self::$changed = true;
             self::$success &= $result;
         }
     }
     //DBG::log("end of update_vat: ".self::$success.", changed: ".self::$changed);
 }
예제 #2
0
 /**
  * Returns an array with all placeholders and their values to be
  * replaced in any shop mailtemplate for the given order ID.
  *
  * You only have to set the 'substitution' index value of your MailTemplate
  * array to the array returned.
  * Customer data is not included here.  See {@see Customer::getSubstitutionArray()}.
  * Note that this method is now mostly independent of the current session.
  * The language of the mail template is determined by the browser
  * language range stored with the order.
  * @access  private
  * @static
  * @param   integer $order_id     The order ID
  * @param   boolean $create_accounts  If true, creates User accounts
  *                                    and Coupon codes.  Defaults to true
  * @return  array                 The array with placeholders as keys
  *                                and values from the order on success,
  *                                false otherwise
  */
 static function getSubstitutionArray($order_id, $create_accounts = true)
 {
     global $_ARRAYLANG;
     /*
                 $_ARRAYLANG['TXT_SHOP_URI_FOR_DOWNLOAD'].":\r\n".
                 'http://'.$_SERVER['SERVER_NAME'].
                 "/index.php?section=download\r\n";
     */
     $objOrder = Order::getById($order_id);
     if (!$objOrder) {
         // Order not found
         return false;
     }
     $lang_id = $objOrder->lang_id();
     if (!intval($lang_id)) {
         $lang_id = \FWLanguage::getLangIdByIso639_1($lang_id);
     }
     $status = $objOrder->status();
     $customer_id = $objOrder->customer_id();
     $customer = Customer::getById($customer_id);
     $payment_id = $objOrder->payment_id();
     $shipment_id = $objOrder->shipment_id();
     $arrSubstitution = array('CUSTOMER_COUNTRY_ID' => $objOrder->billing_country_id(), 'LANG_ID' => $lang_id, 'NOW' => date(ASCMS_DATE_FORMAT_DATETIME), 'TODAY' => date(ASCMS_DATE_FORMAT_DATE), 'ORDER_ID' => $order_id, 'ORDER_ID_CUSTOM' => ShopLibrary::getCustomOrderId($order_id), 'ORDER_DATE' => date(ASCMS_DATE_FORMAT_DATE, strtotime($objOrder->date_time())), 'ORDER_TIME' => date(ASCMS_DATE_FORMAT_TIME, strtotime($objOrder->date_time())), 'ORDER_STATUS_ID' => $status, 'ORDER_STATUS' => $_ARRAYLANG['TXT_SHOP_ORDER_STATUS_' . $status], 'MODIFIED' => date(ASCMS_DATE_FORMAT_DATETIME, strtotime($objOrder->modified_on())), 'REMARKS' => $objOrder->note(), 'ORDER_SUM' => sprintf('% 9.2f', $objOrder->sum()), 'CURRENCY' => Currency::getCodeById($objOrder->currency_id()));
     $arrSubstitution += $customer->getSubstitutionArray();
     if ($shipment_id) {
         $arrSubstitution += array('SHIPMENT' => array(0 => array('SHIPMENT_NAME' => sprintf('%-40s', Shipment::getShipperName($shipment_id)), 'SHIPMENT_PRICE' => sprintf('% 9.2f', $objOrder->shipment_amount()))), 'SHIPPING_ADDRESS' => array(0 => array('SHIPPING_COMPANY' => $objOrder->company(), 'SHIPPING_TITLE' => $_ARRAYLANG['TXT_SHOP_' . strtoupper($objOrder->gender())], 'SHIPPING_FIRSTNAME' => $objOrder->firstname(), 'SHIPPING_LASTNAME' => $objOrder->lastname(), 'SHIPPING_ADDRESS' => $objOrder->address(), 'SHIPPING_ZIP' => $objOrder->zip(), 'SHIPPING_CITY' => $objOrder->city(), 'SHIPPING_COUNTRY_ID' => $objOrder->country_id(), 'SHIPPING_COUNTRY' => \Cx\Core\Country\Controller\Country::getNameById($objOrder->country_id()), 'SHIPPING_PHONE' => $objOrder->phone())));
     }
     if ($payment_id) {
         $arrSubstitution += array('PAYMENT' => array(0 => array('PAYMENT_NAME' => sprintf('%-40s', Payment::getNameById($payment_id)), 'PAYMENT_PRICE' => sprintf('% 9.2f', $objOrder->payment_amount()))));
     }
     $arrItems = $objOrder->getItems();
     if (!$arrItems) {
         \Message::warning($_ARRAYLANG['TXT_SHOP_ORDER_WARNING_NO_ITEM']);
     }
     // Deduct Coupon discounts, either from each Product price, or
     // from the items total.  Mind that the Coupon has already been
     // stored with the Order, but not redeemed yet.  This is done
     // in this method, but only if $create_accounts is true.
     $coupon_code = NULL;
     $coupon_amount = 0;
     $objCoupon = Coupon::getByOrderId($order_id);
     if ($objCoupon) {
         $coupon_code = $objCoupon->code();
     }
     $orderItemCount = 0;
     $total_item_price = 0;
     // Suppress Coupon messages (see Coupon::available())
     \Message::save();
     foreach ($arrItems as $item) {
         $product_id = $item['product_id'];
         $objProduct = Product::getById($product_id);
         if (!$objProduct) {
             //die("Product ID $product_id not found");
             continue;
         }
         //DBG::log("Orders::getSubstitutionArray(): Item: Product ID $product_id");
         $product_name = substr($item['name'], 0, 40);
         $item_price = $item['price'];
         $quantity = $item['quantity'];
         // TODO: Add individual VAT rates for Products
         //            $orderItemVatPercent = $objResultItem->fields['vat_percent'];
         // Decrease the Product stock count,
         // applies to "real", shipped goods only
         $objProduct->decreaseStock($quantity);
         $product_code = $objProduct->code();
         // Pick the order items attributes
         $str_options = '';
         // Any attributes?
         if ($item['attributes']) {
             $str_options = '  ';
             // '[';
             $attribute_name_previous = '';
             foreach ($item['attributes'] as $attribute_name => $arrAttribute) {
                 //DBG::log("Attribute /$attribute_name/ => ".var_export($arrAttribute, true));
                 // NOTE: The option price is optional and may be left out
                 foreach ($arrAttribute as $arrOption) {
                     $option_name = $arrOption['name'];
                     $option_price = $arrOption['price'];
                     $item_price += $option_price;
                     // Recognize the names of uploaded files,
                     // verify their presence and use the original name
                     $option_name_stripped = ShopLibrary::stripUniqidFromFilename($option_name);
                     $path = Order::UPLOAD_FOLDER . $option_name;
                     if ($option_name != $option_name_stripped && \File::exists($path)) {
                         $option_name = $option_name_stripped;
                     }
                     if ($attribute_name != $attribute_name_previous) {
                         if ($attribute_name_previous) {
                             $str_options .= '; ';
                         }
                         $str_options .= $attribute_name . ': ' . $option_name;
                         $attribute_name_previous = $attribute_name;
                     } else {
                         $str_options .= ', ' . $option_name;
                     }
                     // TODO: Add proper formatting with sprintf() and language entries
                     if ($option_price != 0) {
                         $str_options .= ' ' . Currency::formatPrice($option_price) . ' ' . Currency::getActiveCurrencyCode();
                     }
                 }
             }
             //                $str_options .= ']';
         }
         // Product details
         $arrProduct = array('PRODUCT_ID' => $product_id, 'PRODUCT_CODE' => $product_code, 'PRODUCT_QUANTITY' => $quantity, 'PRODUCT_TITLE' => $product_name, 'PRODUCT_OPTIONS' => $str_options, 'PRODUCT_ITEM_PRICE' => sprintf('% 9.2f', $item_price), 'PRODUCT_TOTAL_PRICE' => sprintf('% 9.2f', $item_price * $quantity));
         //DBG::log("Orders::getSubstitutionArray($order_id, $create_accounts): Adding article: ".var_export($arrProduct, true));
         $orderItemCount += $quantity;
         $total_item_price += $item_price * $quantity;
         if ($create_accounts) {
             // Add an account for every single instance of every Product
             for ($instance = 1; $instance <= $quantity; ++$instance) {
                 $validity = 0;
                 // Default to unlimited validity
                 // In case there are protected downloads in the cart,
                 // collect the group IDs
                 $arrUsergroupId = array();
                 if ($objProduct->distribution() == 'download') {
                     $usergroupIds = $objProduct->usergroup_ids();
                     if ($usergroupIds != '') {
                         $arrUsergroupId = explode(',', $usergroupIds);
                         $validity = $objProduct->weight();
                     }
                 }
                 // create an account that belongs to all collected
                 // user groups, if any.
                 if (count($arrUsergroupId) > 0) {
                     // The login names are created separately for
                     // each product instance
                     $username = self::usernamePrefix . "_{$order_id}_{$product_id}_{$instance}";
                     $userEmail = $username . '-' . $arrSubstitution['CUSTOMER_EMAIL'];
                     $userpass = \User::make_password();
                     $objUser = new \User();
                     $objUser->setUsername($username);
                     $objUser->setPassword($userpass);
                     $objUser->setEmail($userEmail);
                     $objUser->setAdminStatus(false);
                     $objUser->setActiveStatus(true);
                     $objUser->setGroups($arrUsergroupId);
                     $objUser->setValidityTimePeriod($validity);
                     $objUser->setFrontendLanguage(FRONTEND_LANG_ID);
                     $objUser->setBackendLanguage(FRONTEND_LANG_ID);
                     $objUser->setProfile(array('firstname' => array(0 => $arrSubstitution['CUSTOMER_FIRSTNAME']), 'lastname' => array(0 => $arrSubstitution['CUSTOMER_LASTNAME']), 'company' => array(0 => $arrSubstitution['CUSTOMER_COMPANY']), 'address' => array(0 => $arrSubstitution['CUSTOMER_ADDRESS']), 'zip' => array(0 => $arrSubstitution['CUSTOMER_ZIP']), 'city' => array(0 => $arrSubstitution['CUSTOMER_CITY']), 'country' => array(0 => $arrSubstitution['CUSTOMER_COUNTRY_ID']), 'phone_office' => array(0 => $arrSubstitution['CUSTOMER_PHONE']), 'phone_fax' => array(0 => $arrSubstitution['CUSTOMER_FAX'])));
                     if (!$objUser->store()) {
                         \Message::error(implode('<br />', $objUser->getErrorMsg()));
                         return false;
                     }
                     if (empty($arrProduct['USER_DATA'])) {
                         $arrProduct['USER_DATA'] = array();
                     }
                     $arrProduct['USER_DATA'][] = array('USER_NAME' => $username, 'USER_PASS' => $userpass);
                 }
                 //echo("Instance $instance");
                 if ($objProduct->distribution() == 'coupon') {
                     if (empty($arrProduct['COUPON_DATA'])) {
                         $arrProduct['COUPON_DATA'] = array();
                     }
                     //DBG::log("Orders::getSubstitutionArray(): Getting code");
                     $code = Coupon::getNewCode();
                     //DBG::log("Orders::getSubstitutionArray(): Got code: $code, calling Coupon::addCode($code, 0, 0, 0, $item_price)");
                     Coupon::storeCode($code, 0, 0, 0, $item_price, 0, 0, 10000000000.0, true);
                     $arrProduct['COUPON_DATA'][] = array('COUPON_CODE' => $code);
                 }
             }
             // Redeem the *product* Coupon, if possible for the Product
             if ($coupon_code) {
                 $objCoupon = Coupon::available($coupon_code, $item_price * $quantity, $customer_id, $product_id, $payment_id);
                 if ($objCoupon) {
                     $coupon_code = NULL;
                     $coupon_amount = $objCoupon->getDiscountAmount($item_price, $customer_id);
                     if ($create_accounts) {
                         $objCoupon->redeem($order_id, $customer_id, $item_price * $quantity);
                     }
                 }
                 //\DBG::log("Orders::getSubstitutionArray(): Got Product Coupon $coupon_code");
             }
         }
         if (empty($arrSubstitution['ORDER_ITEM'])) {
             $arrSubstitution['ORDER_ITEM'] = array();
         }
         $arrSubstitution['ORDER_ITEM'][] = $arrProduct;
     }
     $arrSubstitution['ORDER_ITEM_SUM'] = sprintf('% 9.2f', $total_item_price);
     $arrSubstitution['ORDER_ITEM_COUNT'] = sprintf('% 4u', $orderItemCount);
     // Redeem the *global* Coupon, if possible for the Order
     if ($coupon_code) {
         $objCoupon = Coupon::available($coupon_code, $total_item_price, $customer_id, null, $payment_id);
         if ($objCoupon) {
             $coupon_amount = $objCoupon->getDiscountAmount($total_item_price, $customer_id);
             if ($create_accounts) {
                 $objCoupon->redeem($order_id, $customer_id, $total_item_price);
             }
         }
     }
     \Message::restore();
     // Fill in the Coupon block with proper discount and amount
     if ($objCoupon) {
         $coupon_code = $objCoupon->code();
         //\DBG::log("Orders::getSubstitutionArray(): Coupon $coupon_code, amount $coupon_amount");
     }
     if ($coupon_amount) {
         //\DBG::log("Orders::getSubstitutionArray(): Got Order Coupon $coupon_code");
         $arrSubstitution['DISCOUNT_COUPON'][] = array('DISCOUNT_COUPON_CODE' => sprintf('%-40s', $coupon_code), 'DISCOUNT_COUPON_AMOUNT' => sprintf('% 9.2f', -$coupon_amount));
     } else {
         //\DBG::log("Orders::getSubstitutionArray(): No Coupon for Order ID $order_id");
     }
     Products::deactivate_soldout();
     if (Vat::isEnabled()) {
         //DBG::log("Orders::getSubstitutionArray(): VAT amount: ".$objOrder->vat_amount());
         $arrSubstitution['VAT'] = array(0 => array('VAT_TEXT' => sprintf('%-40s', Vat::isIncluded() ? $_ARRAYLANG['TXT_SHOP_VAT_PREFIX_INCL'] : $_ARRAYLANG['TXT_SHOP_VAT_PREFIX_EXCL']), 'VAT_PRICE' => $objOrder->vat_amount()));
     }
     return $arrSubstitution;
 }
예제 #3
0
 /**
  * Processes the Order
  *
  * Verifies all data, updates and stores it in the database, and
  * initializes payment
  * @return  boolean         True on successs, false otherwise
  */
 static function process()
 {
     global $objDatabase, $_ARRAYLANG;
     // FOR TESTING ONLY (repeatedly process/store the order, also disable self::destroyCart())
     //$_SESSION['shop']['order_id'] = NULL;
     // Verify that the order hasn't yet been saved
     // (and has thus not yet been confirmed)
     if (isset($_SESSION['shop']['order_id'])) {
         return \Message::error($_ARRAYLANG['TXT_ORDER_ALREADY_PLACED']);
     }
     // No more confirmation
     self::$objTemplate->hideBlock('shopConfirm');
     // Store the customer, register the order
     $customer_ip = $_SERVER['REMOTE_ADDR'];
     $customer_host = substr(@gethostbyaddr($_SERVER['REMOTE_ADDR']), 0, 100);
     $customer_browser = substr(getenv('HTTP_USER_AGENT'), 0, 100);
     $new_customer = false;
     //\DBG::log("Shop::process(): E-Mail: ".$_SESSION['shop']['email']);
     if (self::$objCustomer) {
         //\DBG::log("Shop::process(): Existing User username ".$_SESSION['shop']['username'].", email ".$_SESSION['shop']['email']);
     } else {
         // Registered Customers are required to be logged in!
         self::$objCustomer = Customer::getRegisteredByEmail($_SESSION['shop']['email']);
         if (self::$objCustomer) {
             \Message::error($_ARRAYLANG['TXT_SHOP_CUSTOMER_REGISTERED_EMAIL']);
             \Cx\Core\Csrf\Controller\Csrf::redirect(\Cx\Core\Routing\Url::fromModuleAndCmd('Shop', 'login') . '?redirect=' . base64_encode(\Cx\Core\Routing\Url::fromModuleAndCmd('Shop', 'confirm')));
         }
         // Unregistered Customers are stored as well, as their information is needed
         // nevertheless.  Their active status, however, is set to false.
         self::$objCustomer = Customer::getUnregisteredByEmail($_SESSION['shop']['email']);
         if (!self::$objCustomer) {
             self::$objCustomer = new Customer();
             // Currently, the e-mail address is set as the user name
             $_SESSION['shop']['username'] = $_SESSION['shop']['email'];
             //\DBG::log("Shop::process(): New User username ".$_SESSION['shop']['username'].", email ".$_SESSION['shop']['email']);
             self::$objCustomer->username($_SESSION['shop']['username']);
             self::$objCustomer->email($_SESSION['shop']['email']);
             // Note that the password is unset when the Customer chooses
             // to order without registration.  The generated one
             // defaults to length 8, fulfilling the requirements for
             // complex passwords.  And it's kept absolutely secret.
             $password = empty($_SESSION['shop']['password']) ? \User::make_password() : $_SESSION['shop']['password'];
             //\DBG::log("Password: $password (session: {$_SESSION['shop']['password']})");
             if (!self::$objCustomer->password($password)) {
                 \Message::error($_ARRAYLANG['TXT_INVALID_PASSWORD']);
                 \Cx\Core\Csrf\Controller\Csrf::redirect(\Cx\Core\Routing\Url::fromModuleAndCmd('Shop', 'account'));
             }
             self::$objCustomer->active(empty($_SESSION['shop']['dont_register']));
             $new_customer = true;
         }
     }
     // Update the Customer object from the session array
     // (whether new or not -- it may have been edited)
     self::$objCustomer->gender($_SESSION['shop']['gender']);
     self::$objCustomer->firstname($_SESSION['shop']['firstname']);
     self::$objCustomer->lastname($_SESSION['shop']['lastname']);
     self::$objCustomer->company($_SESSION['shop']['company']);
     self::$objCustomer->address($_SESSION['shop']['address']);
     self::$objCustomer->city($_SESSION['shop']['city']);
     self::$objCustomer->zip($_SESSION['shop']['zip']);
     self::$objCustomer->country_id($_SESSION['shop']['countryId']);
     self::$objCustomer->phone($_SESSION['shop']['phone']);
     self::$objCustomer->fax($_SESSION['shop']['fax']);
     $arrGroups = self::$objCustomer->getAssociatedGroupIds();
     $usergroup_id = \Cx\Core\Setting\Controller\Setting::getValue('usergroup_id_reseller', 'Shop');
     if (empty($usergroup_id)) {
         //\DBG::log("Shop::process(): ERROR: Missing reseller group");
         \Message::error($_ARRAYLANG['TXT_SHOP_ERROR_USERGROUP_INVALID']);
         \Cx\Core\Csrf\Controller\Csrf::redirect(\Cx\Core\Routing\Url::fromModuleAndCmd('Shop', ''));
     }
     if (!in_array($usergroup_id, $arrGroups)) {
         //\DBG::log("Shop::process(): Customer is not in Reseller group (ID $usergroup_id)");
         // Not a reseller.  See if she's a final customer
         $usergroup_id = \Cx\Core\Setting\Controller\Setting::getValue('usergroup_id_customer', 'Shop');
         if (empty($usergroup_id)) {
             //\DBG::log("Shop::process(): ERROR: Missing final customer group");
             \Message::error($_ARRAYLANG['TXT_SHOP_ERROR_USERGROUP_INVALID']);
             \Cx\Core\Csrf\Controller\Csrf::redirect(\Cx\Core\Routing\Url::fromModuleAndCmd('Shop', ''));
         }
         if (!in_array($usergroup_id, $arrGroups)) {
             //\DBG::log("Shop::process(): Customer is not in final customer group (ID $usergroup_id), either");
             // Neither one, add to the final customer group (default)
             $arrGroups[] = $usergroup_id;
             self::$objCustomer->setGroups($arrGroups);
             //\DBG::log("Shop::process(): Added Customer to final customer group (ID $usergroup_id): ".var_export(self::$objCustomer->getAssociatedGroupIds(), true));
         } else {
             //\DBG::log("Shop::process(): Customer is a final customer (ID $usergroup_id) already: ".var_export(self::$objCustomer->getAssociatedGroupIds(), true));
         }
     } else {
         //\DBG::log("Shop::process(): Customer is a Reseller (ID $usergroup_id) already: ".var_export(self::$objCustomer->getAssociatedGroupIds(), true));
     }
     // Insert or update the customer
     //\DBG::log("Shop::process(): Storing Customer: ".var_export(self::$objCustomer, true));
     if (!self::$objCustomer->store()) {
         return \Message::error($_ARRAYLANG['TXT_SHOP_CUSTOMER_ERROR_STORING']);
     }
     // Authenticate new Customer
     if ($new_customer) {
         // Fails for "unregistered" Customers!
         if (self::$objCustomer->auth($_SESSION['shop']['username'], $_SESSION['shop']['password'], false, true)) {
             if (!self::_authenticate()) {
                 return \Message::error($_ARRAYLANG['TXT_SHOP_CUSTOMER_ERROR_STORING']);
             }
         }
     }
     //die();
     // Clear the ship-to country if there is no shipping
     if (!Cart::needs_shipment()) {
         $_SESSION['shop']['countryId2'] = 0;
     }
     $shipper_id = empty($_SESSION['shop']['shipperId']) ? null : $_SESSION['shop']['shipperId'];
     $payment_id = empty($_SESSION['shop']['paymentId']) ? null : $_SESSION['shop']['paymentId'];
     $objOrder = new Order();
     $objOrder->customer_id(self::$objCustomer->id());
     $objOrder->billing_gender($_SESSION['shop']['gender']);
     $objOrder->billing_firstname($_SESSION['shop']['firstname']);
     $objOrder->billing_lastname($_SESSION['shop']['lastname']);
     $objOrder->billing_company($_SESSION['shop']['company']);
     $objOrder->billing_address($_SESSION['shop']['address']);
     $objOrder->billing_city($_SESSION['shop']['city']);
     $objOrder->billing_zip($_SESSION['shop']['zip']);
     $objOrder->billing_country_id($_SESSION['shop']['countryId']);
     $objOrder->billing_phone($_SESSION['shop']['phone']);
     $objOrder->billing_fax($_SESSION['shop']['fax']);
     $objOrder->billing_email($_SESSION['shop']['email']);
     $objOrder->currency_id($_SESSION['shop']['currencyId']);
     $objOrder->sum($_SESSION['shop']['grand_total_price']);
     $objOrder->date_time(date(ASCMS_DATE_FORMAT_INTERNATIONAL_DATETIME));
     $objOrder->status(0);
     $objOrder->company($_SESSION['shop']['company2']);
     $objOrder->gender($_SESSION['shop']['gender2']);
     $objOrder->firstname($_SESSION['shop']['firstname2']);
     $objOrder->lastname($_SESSION['shop']['lastname2']);
     $objOrder->address($_SESSION['shop']['address2']);
     $objOrder->city($_SESSION['shop']['city2']);
     $objOrder->zip($_SESSION['shop']['zip2']);
     $objOrder->country_id($_SESSION['shop']['countryId2']);
     $objOrder->phone($_SESSION['shop']['phone2']);
     $objOrder->vat_amount($_SESSION['shop']['vat_price']);
     $objOrder->shipment_amount($_SESSION['shop']['shipment_price']);
     $objOrder->shipment_id($shipper_id);
     $objOrder->payment_id($payment_id);
     $objOrder->payment_amount($_SESSION['shop']['payment_price']);
     $objOrder->ip($customer_ip);
     $objOrder->host($customer_host);
     $objOrder->lang_id(FRONTEND_LANG_ID);
     $objOrder->browser($customer_browser);
     $objOrder->note($_SESSION['shop']['note']);
     if (!$objOrder->insert()) {
         // $order_id is unset!
         return \Message::error($_ARRAYLANG['TXT_SHOP_ORDER_ERROR_STORING']);
     }
     $order_id = $objOrder->id();
     $_SESSION['shop']['order_id'] = $order_id;
     // The products will be tested one by one below.
     // If any single one of them requires delivery, this
     // flag will be set to true.
     // This is used to determine the order status at the
     // end of the shopping process.
     $_SESSION['shop']['isDelivery'] = false;
     // Try to redeem the Coupon, if any
     $coupon_code = isset($_SESSION['shop']['coupon_code']) ? $_SESSION['shop']['coupon_code'] : null;
     //\DBG::log("Cart::update(): Coupon Code: $coupon_code");
     $items_total = 0;
     // Suppress Coupon messages (see Coupon::available())
     \Message::save();
     foreach (Cart::get_products_array() as $arrProduct) {
         $objProduct = Product::getById($arrProduct['id']);
         if (!$objProduct) {
             unset($_SESSION['shop']['order_id']);
             return \Message::error($_ARRAYLANG['TXT_ERROR_LOOKING_UP_ORDER']);
         }
         $product_id = $arrProduct['id'];
         $name = $objProduct->name();
         $priceOptions = !empty($arrProduct['optionPrice']) ? $arrProduct['optionPrice'] : 0;
         $quantity = $arrProduct['quantity'];
         $price = $objProduct->get_custom_price(self::$objCustomer, $priceOptions, $quantity);
         $item_total = $price * $quantity;
         $items_total += $item_total;
         $productVatId = $objProduct->vat_id();
         $vat_rate = $productVatId && Vat::getRate($productVatId) ? Vat::getRate($productVatId) : '0.00';
         // Test the distribution method for delivery
         $productDistribution = $objProduct->distribution();
         if ($productDistribution == 'delivery') {
             $_SESSION['shop']['isDelivery'] = true;
         }
         $weight = $productDistribution == 'delivery' ? $objProduct->weight() : 0;
         // grams
         if ($weight == '') {
             $weight = 0;
         }
         // Add to order items table
         $result = $objOrder->insertItem($order_id, $product_id, $name, $price, $quantity, $vat_rate, $weight, $arrProduct['options']);
         if (!$result) {
             unset($_SESSION['shop']['order_id']);
             // TODO: Verify error message set by Order::insertItem()
             return false;
         }
         // Store the Product Coupon, if applicable.
         // Note that it is not redeemed yet (uses=0)!
         if ($coupon_code) {
             $objCoupon = Coupon::available($coupon_code, $item_total, self::$objCustomer->id(), $product_id, $payment_id);
             if ($objCoupon) {
                 //\DBG::log("Shop::process(): Got Coupon for Product ID $product_id: ".var_export($objCoupon, true));
                 if (!$objCoupon->redeem($order_id, self::$objCustomer->id(), $price * $quantity, 0)) {
                     // TODO: Do something if the Coupon does not work
                     \DBG::log("Shop::process(): ERROR: Failed to store Coupon for Product ID {$product_id}");
                 }
                 $coupon_code = null;
             }
         }
     }
     // foreach product in cart
     // Store the Global Coupon, if applicable.
     // Note that it is not redeemed yet (uses=0)!
     //\DBG::log("Shop::process(): Looking for global Coupon $coupon_code");
     if ($coupon_code) {
         $objCoupon = Coupon::available($coupon_code, $items_total, self::$objCustomer->id(), null, $payment_id);
         if ($objCoupon) {
             //\DBG::log("Shop::process(): Got global Coupon: ".var_export($objCoupon, true));
             if (!$objCoupon->redeem($order_id, self::$objCustomer->id(), $items_total, 0)) {
                 \DBG::log("Shop::process(): ERROR: Failed to store global Coupon");
             }
         }
     }
     \Message::restore();
     $processor_id = Payment::getProperty($_SESSION['shop']['paymentId'], 'processor_id');
     $processor_name = PaymentProcessing::getPaymentProcessorName($processor_id);
     // other payment methods
     PaymentProcessing::initProcessor($processor_id);
     // TODO: These arguments are no longer valid.  Set them up later?
     //            Currency::getActiveCurrencyCode(),
     //            FWLanguage::getLanguageParameter(FRONTEND_LANG_ID, 'lang'));
     // if the processor is Internal_LSV, and there is account information,
     // store the information.
     if ($processor_name == 'internal_lsv') {
         if (!self::lsv_complete()) {
             // Missing mandatory data; return to payment
             unset($_SESSION['shop']['order_id']);
             \Message::error($_ARRAYLANG['TXT_ERROR_ACCOUNT_INFORMATION_NOT_AVAILABLE']);
             \Cx\Core\Csrf\Controller\Csrf::redirect(\Cx\Core\Routing\Url::fromModuleAndCmd('Shop', 'payment'));
         }
         $query = "\n                INSERT INTO " . DBPREFIX . "module_shop" . MODULE_INDEX . "_lsv (\n                    order_id, holder, bank, blz\n                ) VALUES (\n                    {$order_id},\n                    '" . contrexx_raw2db($_SESSION['shop']['account_holder']) . "',\n                    '" . contrexx_raw2db($_SESSION['shop']['account_bank']) . "',\n                    '" . contrexx_raw2db($_SESSION['shop']['account_blz']) . "'\n                )";
         $objResult = $objDatabase->Execute($query);
         if (!$objResult) {
             // Return to payment
             unset($_SESSION['shop']['order_id']);
             \Message::error($_ARRAYLANG['TXT_ERROR_INSERTING_ACCOUNT_INFORMATION']);
             \Cx\Core\Csrf\Controller\Csrf::redirect(\Cx\Core\Routing\Url::fromModuleAndCmd('Shop', 'payment'));
         }
     }
     $_SESSION['shop']['order_id_checkin'] = $order_id;
     $strProcessorType = PaymentProcessing::getCurrentPaymentProcessorType();
     // Test whether the selected payment method can be
     // considered an instant or deferred one.
     // This is used to set the order status at the end
     // of the shopping process.
     // TODO: Invert this flag, as it may no longer be present after paying
     // online using one of the external payment methods!  Ensure that it is set
     // instead when paying "deferred".
     $_SESSION['shop']['isInstantPayment'] = false;
     if ($strProcessorType == 'external') {
         // For the sake of simplicity, all external payment
         // methods are considered to be 'instant'.
         // All currently implemented internal methods require
         // further action from the merchant, and thus are
         // considered to be 'deferred'.
         $_SESSION['shop']['isInstantPayment'] = true;
     }
     // Send the Customer login separately, as the password possibly
     // won't be available later
     if (!empty($_SESSION['shop']['password'])) {
         self::sendLogin(self::$objCustomer->email(), $_SESSION['shop']['password']);
     }
     // Show payment processing page.
     // Note that some internal payments are redirected away
     // from this page in checkOut():
     // 'internal', 'internal_lsv'
     self::$objTemplate->setVariable('SHOP_PAYMENT_PROCESSING', PaymentProcessing::checkOut());
     // Clear the order ID.
     // The order may be resubmitted and the payment retried.
     unset($_SESSION['shop']['order_id']);
     // Custom.
     // Enable if Discount class is customized and in use.
     //self::showCustomerDiscount(Cart::get_price());
     return true;
 }
예제 #4
0
 static function getJavascriptArray($groupCustomerId = 0, $isReseller = false)
 {
     global $objDatabase;
     // create javascript array containing all products;
     // used to update the display when changing the product ID.
     // we need the VAT rate in there as well in order to be able to correctly change the products,
     // and the flag indicating whether the VAT is included in the prices already.
     $strJsArrProduct = 'var vat_included = ' . intval(Vat::isIncluded()) . ";\nvar arrProducts = new Array();\n";
     $arrSql = \Text::getSqlSnippets('`product`.`id`', FRONTEND_LANG_ID, 'Shop', array('name' => Product::TEXT_NAME, 'code' => Product::TEXT_CODE));
     $query = "\n            SELECT `product`.`id`,\n                   `product`.`resellerprice`, `product`.`normalprice`,\n                   `product`.`discountprice`, `product`.`discount_active`,\n                   `product`.`weight`, `product`.`vat_id`,\n                   `product`.`distribution`,\n                   `product`.`group_id`, `product`.`article_id`, " . $arrSql['field'] . "\n              FROM `" . DBPREFIX . "module_shop" . MODULE_INDEX . "_products` AS `product`" . $arrSql['join'] . "\n             WHERE `product`.`active`=1";
     $objResult = $objDatabase->Execute($query);
     if (!$objResult) {
         return Product::errorHandler();
     }
     while (!$objResult->EOF) {
         $id = $objResult->fields['id'];
         $distribution = $objResult->fields['distribution'];
         $strCode = $objResult->fields['code'];
         if ($strCode === null) {
             $strCode = \Text::getById($id, 'Shop', Product::TEXT_CODE)->content();
         }
         $strName = $objResult->fields['name'];
         if ($strName === null) {
             $strName = \Text::getById($id, 'Shop', Product::TEXT_NAME)->content();
         }
         $price = $objResult->fields['normalprice'];
         if ($objResult->fields['discount_active']) {
             $price = $objResult->fields['discountprice'];
         } elseif ($isReseller) {
             $price = $objResult->fields['resellerprice'];
         }
         // Determine discounted price from customer and article group matrix
         $discountCustomerRate = Discount::getDiscountRateCustomer($groupCustomerId, $objResult->fields['article_id']);
         $price -= $price * $discountCustomerRate * 0.01;
         // Determine prices for various count discounts, if any
         $arrDiscountCountRate = Discount::getDiscountCountRateArray($objResult->fields['group_id']);
         //\DBG::log("Products::getJavascriptArray($groupCustomerId, $isReseller): Discount rate array: ".var_export($arrDiscountCountRate, true));
         // Order the counts in reverse, from highest to lowest
         $strJsArrPrice = '';
         if (is_array($arrDiscountCountRate)) {
             foreach ($arrDiscountCountRate as $count => $rate) {
                 // Deduct the customer type discount right away
                 //\DBG::log("Products::getJavascriptArray(): price $price, rate $rate");
                 $discountPrice = $price - $price * $rate * 0.01;
                 $strJsArrPrice .= ($strJsArrPrice ? ',' : '') . $count . ',' . Currency::getCurrencyPrice($discountPrice);
             }
         }
         $strJsArrPrice .= ($strJsArrPrice ? ',' : '') . '0,' . Currency::getCurrencyPrice($price);
         $strJsArrProduct .= 'arrProducts[' . $id . '] = {' . 'id:' . $id . ',' . 'code:"' . $strCode . '",' . 'title:"' . htmlspecialchars($strName, ENT_QUOTES, CONTREXX_CHARSET) . '",' . 'percent:' . Vat::getRate($objResult->fields['vat_id']) . ',' . 'weight:' . ($distribution == 'delivery' ? '"' . Weight::getWeightString($objResult->fields['weight']) . '"' : '0') . ',' . 'price:[' . $strJsArrPrice . "]};\n";
         $objResult->MoveNext();
     }
     return $strJsArrProduct;
 }
예제 #5
0
 /**
  * The Cart view
  *
  * Mind that the Cart needs to be {@see update()}d before calling this
  * method.
  * @global  array $_ARRAYLANG   Language array
  * @param   \Cx\Core\Html\Sigma $objTemplate  The optional Template
  */
 static function view($objTemplate = null)
 {
     global $_ARRAYLANG;
     if (!$objTemplate) {
         // TODO: Handle missing or empty Template, load one
         die("Cart::view(): ERROR: No template");
         //            return false;
     }
     $objTemplate->setGlobalVariable($_ARRAYLANG);
     $i = 0;
     if (count(self::$products)) {
         foreach (self::$products as $arrProduct) {
             $groupCountId = $arrProduct['group_id'];
             $groupArticleId = $arrProduct['article_id'];
             $groupCustomerId = 0;
             if (Shop::customer()) {
                 $groupCustomerId = Shop::customer()->group_id();
             }
             Shop::showDiscountInfo($groupCustomerId, $groupArticleId, $groupCountId, $arrProduct['quantity']);
             // product image
             $arrProductImg = Products::get_image_array_from_base64($arrProduct['product_images']);
             $shopImagesWebPath = \Cx\Core\Core\Controller\Cx::instanciate()->getWebsiteImagesWebPath() . '/Shop/';
             $thumbnailPath = $shopImagesWebPath . ShopLibrary::noPictureName;
             foreach ($arrProductImg as $productImg) {
                 if (!empty($productImg['img']) && $productImg['img'] != ShopLibrary::noPictureName) {
                     $thumbnailPath = $shopImagesWebPath . \ImageManager::getThumbnailFilename($productImg['img']);
                     break;
                 }
             }
             /* UNUSED (and possibly obsolete, too)
                             if (isset($arrProduct['discount_string'])) {
             //DBG::log("Shop::view_cart(): Product ID ".$arrProduct['id'].": ".$arrProduct['discount_string']);
                                 $objTemplate->setVariable(
                                     'SHOP_DISCOUNT_COUPON_STRING',
                                         $arrProduct['coupon_string']
                                 );
                             }*/
             // The fields that don't apply have been set to ''
             // (empty string) already -- see update().
             $objTemplate->setVariable(array('SHOP_PRODUCT_ROW' => 'row' . (++$i % 2 + 1), 'SHOP_PRODUCT_ID' => $arrProduct['id'], 'SHOP_PRODUCT_CODE' => $arrProduct['product_id'], 'SHOP_PRODUCT_THUMBNAIL' => $thumbnailPath, 'SHOP_PRODUCT_CART_ID' => $arrProduct['cart_id'], 'SHOP_PRODUCT_TITLE' => str_replace('"', '&quot;', contrexx_raw2xhtml($arrProduct['title'])), 'SHOP_PRODUCT_PRICE' => $arrProduct['price'], 'SHOP_PRODUCT_PRICE_UNIT' => Currency::getActiveCurrencySymbol(), 'SHOP_PRODUCT_QUANTITY' => $arrProduct['quantity'], 'SHOP_PRODUCT_ITEMPRICE' => $arrProduct['itemprice'], 'SHOP_PRODUCT_ITEMPRICE_UNIT' => Currency::getActiveCurrencySymbol(), 'SHOP_REMOVE_PRODUCT' => $_ARRAYLANG['TXT_SHOP_REMOVE_ITEM']));
             //DBG::log("Attributes String: {$arrProduct['options_long']}");
             if ($arrProduct['options_long']) {
                 $objTemplate->setVariable('SHOP_PRODUCT_OPTIONS', $arrProduct['options_long']);
             }
             if (\Cx\Core\Setting\Controller\Setting::getValue('weight_enable', 'Shop')) {
                 $objTemplate->setVariable(array('SHOP_PRODUCT_WEIGHT' => Weight::getWeightString($arrProduct['weight']), 'TXT_WEIGHT' => $_ARRAYLANG['TXT_TOTAL_WEIGHT']));
             }
             if (Vat::isEnabled()) {
                 $objTemplate->setVariable(array('SHOP_PRODUCT_TAX_RATE' => $arrProduct['vat_rate'] ? Vat::format($arrProduct['vat_rate']) : '', 'SHOP_PRODUCT_TAX_AMOUNT' => $arrProduct['vat_amount'] . '&nbsp;' . Currency::getActiveCurrencySymbol()));
             }
             if (intval($arrProduct['minimum_order_quantity']) > 0) {
                 $objTemplate->setVariable(array('SHOP_PRODUCT_MINIMUM_ORDER_QUANTITY' => $arrProduct['minimum_order_quantity']));
             } else {
                 if ($objTemplate->blockExists('orderQuantity')) {
                     $objTemplate->hideBlock('orderQuantity');
                 }
                 if ($objTemplate->blockExists('minimumOrderQuantity')) {
                     $objTemplate->hideBlock('minimumOrderQuantity');
                 }
             }
             $objTemplate->parse('shopCartRow');
         }
     } else {
         $objTemplate->hideBlock('shopCart');
         if ($objTemplate->blockExists('shopCartEmpty')) {
             $objTemplate->touchBlock('shopCartEmpty');
             $objTemplate->parse('shopCartEmpty');
         }
         if ($_SESSION['shop']['previous_product_ids']) {
             $ids = $_SESSION['shop']['previous_product_ids']->toArray();
             Shop::view_product_overview($ids);
         }
     }
     $objTemplate->setGlobalVariable(array('TXT_PRODUCT_ID' => $_ARRAYLANG['TXT_ID'], 'SHOP_PRODUCT_TOTALITEM' => self::get_item_count(), 'SHOP_PRODUCT_TOTALPRICE' => Currency::formatPrice(self::get_price()), 'SHOP_PRODUCT_TOTALPRICE_PLUS_VAT' => Currency::formatPrice(self::get_price() + (Vat::isEnabled() && !Vat::isIncluded() ? self::get_vat_amount() : 0)), 'SHOP_PRODUCT_TOTALPRICE_UNIT' => Currency::getActiveCurrencySymbol(), 'SHOP_TOTAL_WEIGHT' => Weight::getWeightString(self::get_weight()), 'SHOP_PRICE_UNIT' => Currency::getActiveCurrencySymbol()));
     // Show the Coupon code field only if there is at least one defined
     if (Coupon::count_available()) {
         //DBG::log("Coupons available");
         $objTemplate->setVariable(array('SHOP_DISCOUNT_COUPON_CODE' => isset($_SESSION['shop']['coupon_code']) ? $_SESSION['shop']['coupon_code'] : ''));
         if ($objTemplate->blockExists('shopCoupon')) {
             $objTemplate->parse('shopCoupon');
         }
         if (self::get_discount_amount()) {
             $total_discount_amount = self::get_discount_amount();
             //DBG::log("Shop::view_cart(): Total: Amount $total_discount_amount");
             $objTemplate->setVariable(array('SHOP_DISCOUNT_COUPON_TOTAL' => $_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_AMOUNT_TOTAL'], 'SHOP_DISCOUNT_COUPON_TOTAL_AMOUNT' => Currency::formatPrice(-$total_discount_amount)));
         }
     }
     if (Vat::isEnabled()) {
         $objTemplate->setVariable(array('TXT_TAX_PREFIX' => Vat::isIncluded() ? $_ARRAYLANG['TXT_SHOP_VAT_PREFIX_INCL'] : $_ARRAYLANG['TXT_SHOP_VAT_PREFIX_EXCL'], 'SHOP_TOTAL_TAX_AMOUNT' => self::get_vat_amount() . '&nbsp;' . Currency::getActiveCurrencySymbol()));
         if (Vat::isIncluded()) {
             $objTemplate->setVariable(array('SHOP_GRAND_TOTAL_EXCL_TAX' => Currency::formatPrice(self::get_price() - self::get_vat_amount()) . '&nbsp;' . Currency::getActiveCurrencySymbol()));
         }
     }
     if (self::needs_shipment()) {
         $objTemplate->setVariable(array('TXT_SHIP_COUNTRY' => $_ARRAYLANG['TXT_SHIP_COUNTRY'], 'SHOP_COUNTRIES_MENU' => \Cx\Core\Country\Controller\Country::getMenu('countryId2', $_SESSION['shop']['countryId2'], true, "document.forms['shopForm'].submit()"), 'SHOP_COUNTRIES_MENUOPTIONS' => \Cx\Core\Country\Controller\Country::getMenuoptions($_SESSION['shop']['countryId2'])));
     }
     if (\Cx\Core\Setting\Controller\Setting::getValue('orderitems_amount_min', 'Shop') > 0 && \Cx\Core\Setting\Controller\Setting::getValue('orderitems_amount_min', 'Shop') > self::get_price()) {
         $objTemplate->setVariable('MESSAGE_TEXT', sprintf($_ARRAYLANG['TXT_SHOP_ORDERITEMS_AMOUNT_MIN'], Currency::formatPrice(\Cx\Core\Setting\Controller\Setting::getValue('orderitems_amount_min', 'Shop')), Currency::getActiveCurrencySymbol()));
     } elseif (\Cx\Core\Setting\Controller\Setting::getValue('orderitems_amount_max', 'Shop') > 0 && \Cx\Core\Setting\Controller\Setting::getValue('orderitems_amount_max', 'Shop') < self::get_price()) {
         $objTemplate->setVariable('MESSAGE_TEXT', sprintf($_ARRAYLANG['TXT_SHOP_ORDERITEMS_AMOUNT_MAX'], Currency::formatPrice(\Cx\Core\Setting\Controller\Setting::getValue('orderitems_amount_max', 'Shop')), Currency::getActiveCurrencySymbol()));
     } else {
         $objTemplate->setVariable('TXT_NEXT', $_ARRAYLANG['TXT_NEXT']);
     }
 }
예제 #6
0
/**
 * Cloudrexx
 *
 * @link      http://www.cloudrexx.com
 * @copyright Cloudrexx AG 2007-2015
 *
 * According to our dual licensing model, this program can be used either
 * under the terms of the GNU Affero General Public License, version 3,
 * or under a proprietary license.
 *
 * The texts of the GNU Affero General Public License with an additional
 * permission and of our proprietary license can be found at and
 * in the LICENSE file you have received along with this program.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * "Cloudrexx" is a registered trademark of Cloudrexx AG.
 * The licensing of the program under the AGPLv3 does not imply a
 * trademark license. Therefore any rights, title and interest in
 * our trademarks remain entirely with us.
 */
function _shopUpdate()
{
    global $objDatabase, $_ARRAYLANG, $objUpdate;
    if (!defined('MODULE_INDEX')) {
        define('MODULE_INDEX', '');
    }
    try {
        $table_name = DBPREFIX . 'module_shop_config';
        // Mind that this table does no longer exist from version 3
        if (Cx\Lib\UpdateUtil::table_exist($table_name)) {
            // Shop settings
            // Shop thumbnail default settings: shop_thumbnail_max_width
            $query = "\n                SELECT 1 FROM `{$table_name}`\n                WHERE name='shop_thumbnail_max_width'";
            $objResult = $objDatabase->Execute($query);
            if ($objResult) {
                if ($objResult->RecordCount() == 0) {
                    $query = "\n                        INSERT INTO `{$table_name}` (\n                            name, value\n                        ) VALUES (\n                            'shop_thumbnail_max_width', '120'\n                        )";
                    $objResult = $objDatabase->Execute($query);
                    if ($objResult) {
                    } else {
                        return _databaseError($query, $objDatabase->ErrorMsg());
                    }
                }
            } else {
                return _databaseError($query, $objDatabase->ErrorMsg());
            }
            // Shop thumbnail default settings: shop_thumbnail_max_height
            $query = "\n                SELECT 1 FROM `{$table_name}`\n                WHERE name='shop_thumbnail_max_height'";
            $objResult = $objDatabase->Execute($query);
            if ($objResult) {
                if ($objResult->RecordCount() == 0) {
                    $query = "\n                        INSERT INTO `{$table_name}` (\n                            name, value\n                        ) VALUES (\n                            'shop_thumbnail_max_height', '90'\n                        )";
                    $objResult = $objDatabase->Execute($query);
                    if ($objResult) {
                    } else {
                        return _databaseError($query, $objDatabase->ErrorMsg());
                    }
                }
            } else {
                return _databaseError($query, $objDatabase->ErrorMsg());
            }
            // Shop thumbnail default settings: shop_thumbnail_quality
            $query = "\n                SELECT 1 FROM `{$table_name}`\n                WHERE name='shop_thumbnail_quality'";
            $objResult = $objDatabase->Execute($query);
            if ($objResult) {
                if ($objResult->RecordCount() == 0) {
                    $query = "\n                        INSERT INTO `{$table_name}` (\n                            name, value\n                        ) VALUES (\n                            'shop_thumbnail_quality', '80'\n                        )";
                    $objResult = $objDatabase->Execute($query);
                    if ($objResult) {
                    } else {
                        return _databaseError($query, $objDatabase->ErrorMsg());
                    }
                }
            } else {
                return _databaseError($query, $objDatabase->ErrorMsg());
            }
            // Add Yellowpay payment methods default settings:
            // Accepted payment methods
            $query = "\n                SELECT 1 FROM `{$table_name}`\n                WHERE name='yellowpay_accepted_payment_methods'";
            $objResult = $objDatabase->Execute($query);
            if ($objResult) {
                if ($objResult->RecordCount() == 0) {
                    $query = "\n                        INSERT INTO `{$table_name}` (\n                            `id`, `name`, `value`, `status`\n                        ) VALUES (\n                            NULL, 'yellowpay_accepted_payment_methods', '', '1'\n                        )";
                    $objResult = $objDatabase->Execute($query);
                    if ($objResult) {
                    } else {
                        return _databaseError($query, $objDatabase->ErrorMsg());
                    }
                }
            } else {
                return _databaseError($query, $objDatabase->ErrorMsg());
            }
            // Change old yellowpay_delivery_payment_type setting
            // to new yellowpay_authorization_type
            $query = "\n                SELECT 1 FROM `{$table_name}`\n                WHERE `name`='yellowpay_delivery_payment_type'";
            $objResult = $objDatabase->Execute($query);
            if ($objResult) {
                if ($objResult->RecordCount() == 1) {
                    $query = "\n                        UPDATE `{$table_name}`\n                           SET `name`='yellowpay_authorization_type'\n                         WHERE `name`='yellowpay_delivery_payment_type'";
                    $objResult = $objDatabase->Execute($query);
                    if ($objResult) {
                    } else {
                        return _databaseError($query, $objDatabase->ErrorMsg());
                    }
                }
            } else {
                return _databaseError($query, $objDatabase->ErrorMsg());
            }
            // Add yellowpay test server flag setting
            $query = "\n                SELECT 1 FROM `{$table_name}`\n                WHERE `name`='yellowpay_use_testserver'";
            $objResult = $objDatabase->Execute($query);
            if ($objResult) {
                if ($objResult->RecordCount() == 0) {
                    $query = "\n                        INSERT INTO `{$table_name}` (\n                            `id`, `name`, `value`, `status`\n                        ) VALUES (\n                            NULL, 'yellowpay_use_testserver', '1', '1'\n                        )";
                    $objResult = $objDatabase->Execute($query);
                    if ($objResult) {
                    } else {
                        return _databaseError($query, $objDatabase->ErrorMsg());
                    }
                }
            } else {
                return _databaseError($query, $objDatabase->ErrorMsg());
            }
            // Add weight enable flag setting
            $query = "\n                SELECT 1 FROM `{$table_name}`\n                WHERE `name`='shop_weight_enable'";
            $objResult = $objDatabase->Execute($query);
            if ($objResult) {
                if ($objResult->RecordCount() == 0) {
                    $query = "\n                        INSERT INTO `{$table_name}` (\n                            `id`, `name`, `value`, `status`\n                        ) VALUES (\n                            NULL, 'shop_weight_enable', '1', '1'\n                        )";
                    $objResult = $objDatabase->Execute($query);
                    if ($objResult) {
                    } else {
                        return _databaseError($query, $objDatabase->ErrorMsg());
                    }
                }
            } else {
                return _databaseError($query, $objDatabase->ErrorMsg());
            }
            // Add shop_show_products_default:
            // Which products are shown on the first shop page?
            $query = "\n                SELECT 1 FROM `{$table_name}`\n                WHERE `name`='shop_show_products_default'";
            $objResult = $objDatabase->Execute($query);
            if (!$objResult) {
                return _databaseError($query, $objDatabase->ErrorMsg());
            }
            if ($objResult->RecordCount() == 0) {
                $query = "\n                    INSERT INTO `{$table_name}` (\n                        `name`, `value`\n                    ) VALUES (\n                        'shop_show_products_default', '1'\n                    )";
                $objResult = $objDatabase->Execute($query);
                if (!$objResult) {
                    return _databaseError($query, $objDatabase->ErrorMsg());
                }
            }
            // Update VAT settings
            $query = "\n                SELECT `value` FROM `{$table_name}`\n                WHERE `name`='tax_enabled'";
            $objResult = $objDatabase->Execute($query);
            if (!$objResult) {
                return _databaseError($query, $objDatabase->ErrorMsg());
            }
            if ($objResult->RecordCount()) {
                $flagVatEnabled = $objResult->fields['value'];
                $arrVatEnabled = array('vat_enabled_foreign_customer', 'vat_enabled_foreign_reseller', 'vat_enabled_home_customer', 'vat_enabled_home_reseller');
                foreach ($arrVatEnabled as $strSetting) {
                    $query = "\n                        SELECT 1 FROM `{$table_name}`\n                        WHERE `name`='{$strSetting}'";
                    $objResult = $objDatabase->Execute($query);
                    if (!$objResult) {
                        return _databaseError($query, $objDatabase->ErrorMsg());
                    }
                    if ($objResult->RecordCount() == 0) {
                        $query = "\n                            INSERT INTO `{$table_name}` (\n                                `name`, `value`\n                            ) VALUES (\n                                '{$strSetting}', '{$flagVatEnabled}'\n                            )";
                        $objResult = $objDatabase->Execute($query);
                        if (!$objResult) {
                            return _databaseError($query, $objDatabase->ErrorMsg());
                        }
                    }
                }
            }
            $query = "\n                SELECT `value` FROM `{$table_name}`\n                WHERE `name`='tax_included'";
            $objResult = $objDatabase->Execute($query);
            if (!$objResult) {
                return _databaseError($query, $objDatabase->ErrorMsg());
            }
            if ($objResult->RecordCount()) {
                $flagVatIncluded = $objResult->fields['value'];
                $arrVatIncluded = array('vat_included_foreign_customer', 'vat_included_foreign_reseller', 'vat_included_home_customer', 'vat_included_home_reseller');
                foreach ($arrVatIncluded as $strSetting) {
                    $query = "\n                        SELECT 1 FROM `{$table_name}`\n                        WHERE `name`='{$strSetting}'";
                    $objResult = $objDatabase->Execute($query);
                    if (!$objResult) {
                        return _databaseError($query, $objDatabase->ErrorMsg());
                    }
                    if ($objResult->RecordCount() == 0) {
                        $query = "\n                            INSERT INTO `{$table_name}` (\n                                `name`, `value`\n                            ) VALUES (\n                                '{$strSetting}', '{$flagVatIncluded}'\n                            )";
                        $objResult = $objDatabase->Execute($query);
                        if (!$objResult) {
                            return _databaseError($query, $objDatabase->ErrorMsg());
                        }
                    }
                }
            }
            $query = "\n                DELETE FROM `{$table_name}`\n                WHERE `name`='tax_enabled' OR `name`='tax_included'";
            $objResult = $objDatabase->Execute($query);
            if (!$objResult) {
                return _databaseError($query, $objDatabase->ErrorMsg());
            }
        }
        // Update Attribute price to signed.
        // price_prefix is removed for version 3.  See Attribute::errorHandler()
        $table_name = DBPREFIX . 'module_shop_products_attributes_value';
        if (Cx\Lib\UpdateUtil::table_exist($table_name) && Cx\Lib\UpdateUtil::column_exist($table_name, 'price_prefix') && Cx\Lib\UpdateUtil::table_exist(DBPREFIX . 'module_shop_order_items_attributes') && Cx\Lib\UpdateUtil::column_exist(DBPREFIX . 'module_shop_order_items_attributes', 'price_prefix')) {
            $query = "\n                UPDATE `{$table_name}`\n                   SET `price`=-`price`,\n                       `price_prefix`='+'\n                WHERE `price`>0\n                  AND `price_prefix`='-'";
            $objResult = $objDatabase->Execute($query);
            if (!$objResult) {
                return _databaseError($query, $objDatabase->ErrorMsg());
            }
            $query = "\n                UPDATE `" . DBPREFIX . "module_shop_order_items_attributes`\n                   SET `product_option_values_price`=-`product_option_values_price`\n                WHERE `product_option_values_price`>0\n                  AND `price_prefix`='-'";
            $objResult = $objDatabase->Execute($query);
            if (!$objResult) {
                return _databaseError($query, $objDatabase->ErrorMsg());
            }
        }
        // Update tables' field types and indices
        $table_name = DBPREFIX . 'module_shop_article_group';
        if (Cx\Lib\UpdateUtil::table_exist($table_name) && Cx\Lib\UpdateUtil::column_exist($table_name, 'name')) {
            Cx\Lib\UpdateUtil::table($table_name, array('id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'primary' => true, 'auto_increment' => true), 'name' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => '', 'renamefrom' => 'name')));
        }
        $table_name = DBPREFIX . 'module_shop_customer_group';
        if (Cx\Lib\UpdateUtil::table_exist($table_name) && Cx\Lib\UpdateUtil::column_exist($table_name, 'name')) {
            Cx\Lib\UpdateUtil::table($table_name, array('id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'primary' => true, 'auto_increment' => true), 'name' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => '')));
        }
        $table_name = DBPREFIX . 'module_shop_discountgroup_count_name';
        if (Cx\Lib\UpdateUtil::table_exist($table_name) && Cx\Lib\UpdateUtil::column_exist($table_name, 'name')) {
            Cx\Lib\UpdateUtil::table($table_name, array('id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'primary' => true, 'auto_increment' => true), 'name' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => ''), 'unit' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => '')));
        }
        $table_name = DBPREFIX . 'module_shop_discountgroup_count_rate';
        if (Cx\Lib\UpdateUtil::table_exist($table_name)) {
            Cx\Lib\UpdateUtil::table($table_name, array('group_id' => array('type' => 'INT(10) UNSIGNED', 'notnull' => true, 'primary' => true, 'default' => 0), 'count' => array('type' => 'INT(10) UNSIGNED', 'notnull' => true, 'primary' => true, 'default' => '1'), 'rate' => array('type' => 'DECIMAL(5,2)', 'unsigned' => true, 'notnull' => true, 'default' => '0.0')));
        }
        $table_name = DBPREFIX . 'module_shop_rel_discount_group';
        if (Cx\Lib\UpdateUtil::table_exist($table_name)) {
            Cx\Lib\UpdateUtil::table($table_name, array('customer_group_id' => array('type' => 'INT(10) UNSIGNED', 'notnull' => true, 'primary' => true, 'default' => '0'), 'article_group_id' => array('type' => 'INT(10) UNSIGNED', 'notnull' => true, 'primary' => true, 'default' => '0'), 'rate' => array('type' => 'DECIMAL(9,2)', 'notnull' => true, 'default' => '0.0')));
        }
        $table_name = DBPREFIX . 'module_shop_lsv';
        if (Cx\Lib\UpdateUtil::table_exist($table_name)) {
            Cx\Lib\UpdateUtil::table($table_name, array('id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true, 'renamefrom' => 'order_id'), 'order_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'holder' => array('type' => 'TINYTEXT'), 'bank' => array('type' => 'TINYTEXT'), 'blz' => array('type' => 'TINYTEXT')), array('order_id' => array('fields' => array('order_id'), 'type' => 'UNIQUE')));
        }
        $table_name = DBPREFIX . 'module_shop_shipment_cost';
        if (Cx\Lib\UpdateUtil::table_exist($table_name) && Cx\Lib\UpdateUtil::column_exist($table_name, 'price_free')) {
            Cx\Lib\UpdateUtil::table($table_name, array('id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true), 'shipper_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'max_weight' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => false), 'cost' => array('type' => 'DECIMAL(10,2)', 'unsigned' => true, 'notnull' => false), 'price_free' => array('type' => 'DECIMAL(10,2)', 'unsigned' => true, 'notnull' => false)));
        }
        $table_name = DBPREFIX . 'module_shop_shipper';
        if (Cx\Lib\UpdateUtil::table_exist($table_name) && Cx\Lib\UpdateUtil::column_exist($table_name, 'name')) {
            Cx\Lib\UpdateUtil::table($table_name, array('id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true), 'name' => array('type' => 'TINYTEXT'), 'status' => array('type' => 'TINYINT(1)', 'unsigned' => true, 'notnull' => true, 'default' => '0')));
        }
        // Note that countries are migrated to the core_countries table
        // for version 3, and this table is then dropped.
        // See Country::errorHandler()
        $table_name = DBPREFIX . 'module_shop_countries';
        if (Cx\Lib\UpdateUtil::table_exist($table_name)) {
            Cx\Lib\UpdateUtil::table($table_name, array('countries_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'primary' => true, 'auto_increment' => true), 'countries_name' => array('type' => 'VARCHAR(64)', 'notnull' => true, 'default' => ''), 'countries_iso_code_2' => array('type' => 'CHAR(2)', 'notnull' => true, 'default' => ''), 'countries_iso_code_3' => array('type' => 'CHAR(3)', 'notnull' => true, 'default' => ''), 'activation_status' => array('type' => 'TINYINT(1)', 'unsigned' => true, 'notnull' => true, 'default' => '1')), array('countries_name' => array('fields' => array('countries_name'))));
        }
        // Add Category description to old table version with "catid"
        // primary key only!  Fulltext indices are added when migrating
        // to core_text anyway, so don't bother with text fields here.
        $table_name = DBPREFIX . 'module_shop_categories';
        if (Cx\Lib\UpdateUtil::table_exist($table_name) && Cx\Lib\UpdateUtil::column_exist($table_name, 'catid')) {
            Cx\Lib\UpdateUtil::table($table_name, array('catid' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'primary' => true, 'auto_increment' => true), 'parentid' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'catname' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => ''), 'catdesc' => array('type' => 'TEXT', 'notnull' => true, 'default' => ''), 'catsorting' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '100'), 'catstatus' => array('type' => 'TINYINT(1)', 'unsigned' => true, 'notnull' => true, 'default' => '1'), 'picture' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => ''), 'flags' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => '')), array('flags' => array('fields' => array('flags'), 'type' => 'FULLTEXT')));
        }
        // Settings table fields -- this is supposed to exist; see above
        /*        $table_name = DBPREFIX.'module_shop_config';
                if (Cx\Lib\UpdateUtil::table_exist($table_name)) {
                    Cx\Lib\UpdateUtil::table($table_name,
                        array(
                            'id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'primary' => true, 'auto_increment' => true),
                            'name' => array('type' => 'VARCHAR(64)', 'notnull' => true, 'default' => ''),
                            'value' => array('type' => 'VARCHAR(255)', 'notnull', 'default' => ''),
                            'status' => array('type' => 'TINYINT(1)', 'unsigned' => true, 'notnull' => true, 'default' => '1'),
                        )
                    );
                }*/
        $table_name = DBPREFIX . 'module_shop_currencies';
        if (Cx\Lib\UpdateUtil::table_exist($table_name) && Cx\Lib\UpdateUtil::column_exist($table_name, 'name')) {
            $query = "\n                UPDATE `{$table_name}`\n                SET sort_order = 0 WHERE sort_order IS NULL";
            Cx\Lib\UpdateUtil::sql($query);
            // Currencies table fields
            Cx\Lib\UpdateUtil::table($table_name, array('id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true), 'code' => array('type' => 'CHAR(3)', 'notnull' => true, 'default' => ''), 'symbol' => array('type' => 'VARCHAR(20)', 'notnull' => true, 'default' => ''), 'name' => array('type' => 'VARCHAR(50)', 'notnull' => true, 'default' => ''), 'rate' => array('type' => 'DECIMAL(10,4)', 'unsigned' => true, 'notnull' => true, 'default' => '1.0000'), 'sort_order' => array('type' => 'INT(5)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'status' => array('type' => 'TINYINT(1)', 'unsigned' => true, 'notnull' => true, 'default' => '1'), 'is_default' => array('type' => 'TINYINT(1)', 'unsigned' => true, 'notnull' => true, 'default' => '0')));
        }
        // Note that this table is migrated to access_users for version 3,
        // then dropped.
        $table_name = DBPREFIX . 'module_shop_customers';
        if (Cx\Lib\UpdateUtil::table_exist($table_name)) {
            Cx\Lib\UpdateUtil::table($table_name, array('customerid' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true), 'username' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => ''), 'password' => array('type' => 'VARCHAR(32)', 'notnull' => true, 'default' => ''), 'prefix' => array('type' => 'VARCHAR(50)', 'notnull' => true, 'default' => ''), 'company' => array('type' => 'VARCHAR(100)', 'notnull' => true, 'default' => ''), 'firstname' => array('type' => 'VARCHAR(50)', 'notnull' => true, 'default' => ''), 'lastname' => array('type' => 'VARCHAR(100)', 'notnull' => true, 'default' => ''), 'address' => array('type' => 'VARCHAR(40)', 'notnull' => true, 'default' => ''), 'city' => array('type' => 'VARCHAR(20)', 'notnull' => true, 'default' => ''), 'zip' => array('type' => 'VARCHAR(10)', 'notnull' => false), 'country_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => false), 'phone' => array('type' => 'VARCHAR(20)', 'notnull' => true, 'default' => ''), 'fax' => array('type' => 'VARCHAR(25)', 'notnull' => true, 'default' => ''), 'email' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => ''), 'ccnumber' => array('type' => 'VARCHAR(100)', 'notnull' => true, 'default' => ''), 'ccdate' => array('type' => 'VARCHAR(10)', 'notnull' => true, 'default' => ''), 'ccname' => array('type' => 'VARCHAR(100)', 'notnull' => true, 'default' => ''), 'cvc_code' => array('type' => 'VARCHAR(5)', 'notnull' => true, 'default' => ''), 'company_note' => array('type' => 'TEXT', 'notnull' => true), 'is_reseller' => array('type' => 'TINYINT(1)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'register_date' => array('type' => 'DATETIME', 'notnull' => true, 'default' => '0000-00-00 00:00:00'), 'customer_status' => array('type' => 'TINYINT(1)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'group_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => false)));
        }
        $table_name = DBPREFIX . 'module_shop_importimg';
        if (Cx\Lib\UpdateUtil::table_exist($table_name)) {
            Cx\Lib\UpdateUtil::table($table_name, array('img_id' => array('type' => 'INT(10) UNSIGNED', 'notnull' => true, 'primary' => true, 'auto_increment' => true), 'img_name' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => ''), 'img_cats' => array('type' => 'TEXT', 'notnull' => true, 'default' => ''), 'img_fields_file' => array('type' => 'TEXT', 'notnull' => true, 'default' => ''), 'img_fields_db' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => '')));
        }
        // Note that the following two tables are migrated to MailTemplate
        // for version 3, then dropped.
        $table_name = DBPREFIX . 'module_shop_mail';
        if (Cx\Lib\UpdateUtil::table_exist($table_name)) {
            Cx\Lib\UpdateUtil::table($table_name, array('id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true), 'tplname' => array('type' => 'VARCHAR(60)', 'notnull' => true, 'default' => ''), 'protected' => array('type' => 'TINYINT(1)', 'unsigned' => true, 'notnull' => true, 'default' => '0')));
        }
        $table_name = DBPREFIX . 'module_shop_mail_content';
        if (Cx\Lib\UpdateUtil::table_exist($table_name)) {
            Cx\Lib\UpdateUtil::table($table_name, array('id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true), 'tpl_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'lang_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'from_mail' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => ''), 'xsender' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => ''), 'subject' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => ''), 'message' => array('type' => 'TEXT', 'notnull' => true)));
        }
        // Note:  No changes necessary; the manufacturer table will be
        // completely modified in Manufacturer::errorHandler() below.
        /*        $table_name = DBPREFIX.'module_shop_manufacturer';
                if (   Cx\Lib\UpdateUtil::table_exist($table_name)
                    && Cx\Lib\UpdateUtil::column_exist($table_name, 'name')) {
                    Cx\Lib\UpdateUtil::table($table_name,
                        DBPREFIX.'',
                        array(
                            'id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true),
                            'name' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => ''),
                            'url' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => ''),
                        )
                    );
                }*/
        $table_name = DBPREFIX . 'module_shop_order_items';
        if (Cx\Lib\UpdateUtil::table_exist($table_name) && Cx\Lib\UpdateUtil::column_exist($table_name, 'order_items_id')) {
            Cx\Lib\UpdateUtil::table($table_name, array('order_items_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true), 'orderid' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'productid' => array('type' => 'VARCHAR(100)', 'notnull' => true, 'default' => ''), 'product_name' => array('type' => 'VARCHAR(100)', 'notnull' => true, 'default' => ''), 'price' => array('type' => 'DECIMAL(9,2)', 'notnull' => true, 'default' => '0.00'), 'quantity' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '1'), 'vat_percent' => array('type' => 'DECIMAL(5,2)', 'unsigned' => true, 'notnull' => false), 'weight' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => false)));
        }
        // Note: Removed field price_prefix for version 2.2; no changes since
        $table_name = DBPREFIX . 'module_shop_order_items_attributes';
        if (Cx\Lib\UpdateUtil::table_exist($table_name) && Cx\Lib\UpdateUtil::column_exist($table_name, 'price_prefix')) {
            Cx\Lib\UpdateUtil::table($table_name, array('orders_items_attributes_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true), 'order_items_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'order_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'product_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'product_option_name' => array('type' => 'VARCHAR(32)', 'notnull' => true, 'default' => ''), 'product_option_value' => array('type' => 'VARCHAR(32)', 'notnull' => true, 'default' => ''), 'product_option_values_price' => array('type' => 'DECIMAL(9,2)', 'notnull' => true, 'default' => '0.00')));
        }
        $table_name = DBPREFIX . 'module_shop_orders';
        if (Cx\Lib\UpdateUtil::table_exist($table_name) && Cx\Lib\UpdateUtil::column_exist($table_name, 'orderid')) {
            Cx\Lib\UpdateUtil::table($table_name, array('orderid' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true), 'customerid' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'selected_currency_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'order_sum' => array('type' => 'DECIMAL(9,2)', 'notnull' => true, 'default' => '0.00'), 'currency_order_sum' => array('type' => 'DECIMAL(9,2)', 'notnull' => true, 'default' => '0.00'), 'order_date' => array('type' => 'DATETIME', 'notnull' => true, 'default' => '0000-00-00 00:00:00'), 'order_status' => array('type' => 'TINYINT(1)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'ship_prefix' => array('type' => 'VARCHAR(50)', 'notnull' => true, 'default' => ''), 'ship_company' => array('type' => 'VARCHAR(100)', 'notnull' => true, 'default' => ''), 'ship_firstname' => array('type' => 'VARCHAR(40)', 'notnull' => true, 'default' => ''), 'ship_lastname' => array('type' => 'VARCHAR(100)', 'notnull' => true, 'default' => ''), 'ship_address' => array('type' => 'VARCHAR(40)', 'notnull' => true, 'default' => ''), 'ship_city' => array('type' => 'VARCHAR(20)', 'notnull' => true, 'default' => ''), 'ship_zip' => array('type' => 'VARCHAR(10)', 'notnull' => false), 'ship_country_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => false), 'ship_phone' => array('type' => 'VARCHAR(20)', 'notnull' => true, 'default' => ''), 'tax_price' => array('type' => 'DECIMAL(9,2)', 'notnull' => true, 'default' => '0.00'), 'currency_ship_price' => array('type' => 'DECIMAL(9,2)', 'notnull' => true, 'default' => '0.00'), 'shipping_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => false), 'payment_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => false), 'currency_payment_price' => array('type' => 'DECIMAL(9,2)', 'notnull' => true, 'default' => '0.00'), 'customer_ip' => array('type' => 'VARCHAR(50)', 'notnull' => true, 'default' => ''), 'customer_host' => array('type' => 'VARCHAR(100)', 'notnull' => true, 'default' => ''), 'customer_lang' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => ''), 'customer_browser' => array('type' => 'VARCHAR(100)', 'notnull' => true, 'default' => ''), 'customer_note' => array('type' => 'TEXT'), 'last_modified' => array('type' => 'DATETIME', 'notnull' => true, 'default' => '0000-00-00 00:00:00'), 'modified_by' => array('type' => 'VARCHAR(50)', 'notnull' => true, 'default' => '')), array('order_status' => array('fields' => array('order_status'))));
        }
        $table_name = DBPREFIX . 'module_shop_payment';
        if (Cx\Lib\UpdateUtil::table_exist($table_name) && Cx\Lib\UpdateUtil::column_exist($table_name, 'name')) {
            Cx\Lib\UpdateUtil::table($table_name, array('id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true), 'name' => array('type' => 'VARCHAR(50)', 'notnull' => false), 'processor_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'costs' => array('type' => 'DECIMAL(9,2)', 'notnull' => true, 'default' => '0.00'), 'costs_free_sum' => array('type' => 'DECIMAL(9,2)', 'notnull' => true, 'default' => '0.00'), 'sort_order' => array('type' => 'INT(5)', 'unsigned' => true, 'notnull' => false, 'default' => '0'), 'status' => array('type' => 'TINYINT(1)', 'unsigned' => true, 'notnull' => false, 'default' => '1')));
        }
        // Note:  No changes (still single language in version 3)
        $table_name = DBPREFIX . 'module_shop_payment_processors';
        Cx\Lib\UpdateUtil::table($table_name, array('id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true), 'type' => array('type' => 'ENUM(\'internal\',\'external\')', 'notnull' => true, 'default' => 'internal'), 'name' => array('type' => 'VARCHAR(100)', 'notnull' => true, 'default' => ''), 'description' => array('type' => 'TEXT'), 'company_url' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => ''), 'status' => array('type' => 'TINYINT(1)', 'unsigned' => true, 'notnull' => false, 'default' => '1'), 'picture' => array('type' => 'VARCHAR(100)', 'notnull' => true, 'default' => '')));
        Cx\Lib\UpdateUtil::sql('
            INSERT IGNORE INTO `' . DBPREFIX . 'module_shop_payment_processors` (`id`, `type`, `name`, `description`, `company_url`, `status`, `picture`)
            VALUES (12,"external","paymill_cc","","https://www.paymill.com",1,""),
                   (13,"external","paymill_elv","","https://www.paymill.com",1,""),
                   (14,"external","paymill_iban","","https://www.paymill.com",1,"")
        ');
        // Note:  No changes (still single language in version 3)
        $table_name = DBPREFIX . 'module_shop_pricelists';
        if (Cx\Lib\UpdateUtil::table_exist($table_name)) {
            Cx\Lib\UpdateUtil::table($table_name, array('id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true), 'name' => array('type' => 'VARCHAR(25)', 'notnull' => true, 'default' => ''), 'lang_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'border_on' => array('type' => 'TINYINT(1)', 'unsigned' => true, 'notnull' => true, 'default' => '1'), 'header_on' => array('type' => 'TINYINT(1)', 'unsigned' => true, 'notnull' => true, 'default' => '1'), 'header_left' => array('type' => 'TEXT', 'notnull' => false), 'header_right' => array('type' => 'TEXT', 'notnull' => false), 'footer_on' => array('type' => 'TINYINT(1)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'footer_left' => array('type' => 'TEXT', 'notnull' => false), 'footer_right' => array('type' => 'TEXT', 'notnull' => false), 'categories' => array('type' => 'TEXT')));
        }
        $table_name = DBPREFIX . 'module_shop_products';
        if (Cx\Lib\UpdateUtil::table_exist($table_name) && Cx\Lib\UpdateUtil::column_exist($table_name, 'title')) {
            $query = "\n                UPDATE `{$table_name}`\n                   SET `description`=''\n                 WHERE `description` IS NULL";
            if ($objDatabase->Execute($query) == false) {
                return _databaseError($query, $objDatabase->ErrorMsg());
            }
            Cx\Lib\UpdateUtil::table($table_name, array('id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true), 'product_id' => array('type' => 'VARCHAR(100)'), 'picture' => array('type' => 'TEXT'), 'title' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => ''), 'catid' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '1'), 'handler' => array('type' => 'ENUM(\'none\',\'delivery\',\'download\')', 'notnull' => true, 'default' => 'delivery'), 'normalprice' => array('type' => 'DECIMAL(9,2)', 'notnull' => true, 'default' => '0.00'), 'resellerprice' => array('type' => 'DECIMAL(9,2)', 'notnull' => true, 'default' => '0.00'), 'shortdesc' => array('type' => 'TEXT'), 'description' => array('type' => 'TEXT'), 'stock' => array('type' => 'INT(10)', 'notnull' => true, 'default' => '10'), 'stock_visibility' => array('type' => 'TINYINT(1)', 'unsigned' => true, 'notnull' => true, 'default' => '1'), 'discountprice' => array('type' => 'DECIMAL(9,2)', 'notnull' => true, 'default' => '0.00'), 'is_special_offer' => array('type' => 'TINYINT(1)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'property1' => array('type' => 'VARCHAR(100)', 'notnull' => false, 'default' => ''), 'property2' => array('type' => 'VARCHAR(100)', 'notnull' => false, 'default' => ''), 'status' => array('type' => 'TINYINT(1)', 'unsigned' => true, 'notnull' => true, 'default' => '1'), 'b2b' => array('type' => 'TINYINT(1)', 'unsigned' => true, 'notnull' => true, 'default' => '1'), 'b2c' => array('type' => 'TINYINT(1)', 'unsigned' => true, 'notnull' => true, 'default' => '1'), 'startdate' => array('type' => 'DATETIME', 'notnull' => true, 'default' => '0000-00-00 00:00:00'), 'enddate' => array('type' => 'DATETIME', 'notnull' => true, 'default' => '0000-00-00 00:00:00'), 'thumbnail_percent' => array('type' => 'TINYINT(2)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'thumbnail_quality' => array('type' => 'TINYINT(2)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'manufacturer' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'manufacturer_url' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => ''), 'external_link' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => ''), 'sort_order' => array('type' => 'INT(5)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'vat_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => false), 'weight' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => false), 'flags' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => ''), 'usergroups' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => ''), 'group_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => false), 'article_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => false), 'keywords' => array('type' => 'TEXT')), array('group_id' => array('fields' => array('group_id')), 'article_id' => array('fields' => array('article_id')), 'shopindex' => array('fields' => array('title', 'description'), 'type' => 'FULLTEXT'), 'flags' => array('fields' => array('flags'), 'type' => 'FULLTEXT'), 'keywords' => array('fields' => array('keywords'), 'type' => 'FULLTEXT')));
        }
        // Note:  The following three tables are renamed for version 3.
        // See Attribute::errorHandler()
        $table_name = DBPREFIX . 'module_shop_products_attributes';
        if (Cx\Lib\UpdateUtil::table_exist($table_name)) {
            Cx\Lib\UpdateUtil::table($table_name, array('attribute_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true), 'product_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'attributes_name_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'attributes_value_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'sort_id' => array('type' => 'INT(5)', 'unsigned' => true, 'notnull' => true, 'default' => '0')));
        }
        $table_name = DBPREFIX . 'module_shop_products_attributes_name';
        if (Cx\Lib\UpdateUtil::table_exist($table_name)) {
            Cx\Lib\UpdateUtil::table($table_name, array('id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true), 'name' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => ''), 'display_type' => array('type' => 'TINYINT(3)', 'unsigned' => true, 'notnull' => true, 'default' => '0')));
        }
        $table_name = DBPREFIX . 'module_shop_products_attributes_value';
        if (Cx\Lib\UpdateUtil::table_exist($table_name)) {
            Cx\Lib\UpdateUtil::table($table_name, array('id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true), 'name_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'value' => array('type' => 'VARCHAR(255)', 'notnull' => true, 'default' => ''), 'price' => array('type' => 'DECIMAL(9,2)', 'notnull' => false, 'default' => '0.00')));
        }
        // Note:  Obsolete for a while already
        $table_name = DBPREFIX . 'module_shop_products_downloads';
        if (Cx\Lib\UpdateUtil::table_exist($table_name)) {
            Cx\Lib\UpdateUtil::drop_table($table_name);
        }
        // Note:  The id field is removed for version 3 from the following
        // three tables
        $table_name = DBPREFIX . 'module_shop_rel_countries';
        if (Cx\Lib\UpdateUtil::table_exist($table_name) && Cx\Lib\UpdateUtil::column_exist($table_name, 'id')) {
            Cx\Lib\UpdateUtil::table($table_name, array('id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true), 'zones_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'countries_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0')));
        }
        $table_name = DBPREFIX . 'module_shop_rel_payment';
        Cx\Lib\UpdateUtil::table($table_name, array('id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true), 'zones_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'payment_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0')));
        Cx\Lib\UpdateUtil::sql('
            INSERT IGNORE INTO `' . DBPREFIX . 'module_shop_rel_payment` (`zones_id`, `payment_id`)
            VALUES (1,16),
                   (1,17),
                   (1,18)
        ');
        // Note: This is renamed to module_shop_rel_shipper for version 3.0
        $table_name = DBPREFIX . 'module_shop_rel_shipment';
        if (Cx\Lib\UpdateUtil::table_exist($table_name) && Cx\Lib\UpdateUtil::column_exist($table_name, 'id')) {
            Cx\Lib\UpdateUtil::table($table_name, array('id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true), 'zones_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0'), 'shipment_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'default' => '0')));
        }
        $table_name = DBPREFIX . 'module_shop_vat';
        if (Cx\Lib\UpdateUtil::table_exist($table_name) && Cx\Lib\UpdateUtil::column_exist($table_name, 'class')) {
            Cx\Lib\UpdateUtil::table($table_name, array('id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true), 'class' => array('type' => 'TINYTEXT'), 'percent' => array('type' => 'DECIMAL(5,2)', 'unsigned' => true, 'notnull' => true, 'default' => '0.00')));
        }
        $table_name = DBPREFIX . 'module_shop_zones';
        if (Cx\Lib\UpdateUtil::table_exist($table_name) && Cx\Lib\UpdateUtil::column_exist($table_name, 'zones_id')) {
            Cx\Lib\UpdateUtil::table($table_name, array('zones_id' => array('type' => 'INT(10)', 'unsigned' => true, 'notnull' => true, 'auto_increment' => true, 'primary' => true), 'zones_name' => array('type' => 'VARCHAR(64)', 'notnull' => true, 'default' => ''), 'activation_status' => array('type' => 'TINYINT(1)', 'unsigned' => true, 'notnull' => true, 'default' => '1')));
        }
        // Contrexx 3.0.0 updates from here.
        // NOTE: All of these methods return false.
        Attribute::errorHandler();
        Coupon::errorHandler();
        // Prerequisites:
        //        ShopSettings::errorHandler();
        //ShopSettings::errorHandler(); // Called by Coupon::errorHandler();Customer::errorHandler();Order::errorHandler();ShopCategory::errorHandler();
        // Prerequisites:
        //        \Cx\Core\Setting\Controller\Setting::errorHandler();
        Currency::errorHandler();
        // Prerequisites:
        //        Text::errorHandler();
        //Text::errorHandler(); // Called by Currency::errorHandler();Product::errorHandler();Payment::errorHandler();ShopCategory::errorHandler();
        Product::errorHandler();
        // Prerequisites:
        //        Text::errorHandler();
        //        Discount::errorHandler(); // Called by Customer::errorHandler();
        //        Manufacturer::errorHandler();
        // Postrequisites:
        //        Customer::errorHandler();
        //Discount::errorHandler(); // Called by Customer::errorHandler();
        //Manufacturer::errorHandler(); // Called by Product::errorHandler();
        // Prerequisites:
        //        Text::errorHandler();
        //Customer::errorHandler(); // Called by Product::errorHandler();
        // Prerequisites:
        //        ShopSettings::errorHandler();
        //        Country::errorHandler(); // Called by Order::errorHandler();
        //        Order::errorHandler(); // Calls required Country::errorHandler();
        //        Discount::errorHandler(); // Called by Product::errorHandler();
        //Order::errorHandler(); // Called by Customer::errorHandler();
        // Prerequisites:
        //        ShopSettings::errorHandler();
        //        Country::errorHandler();
        ShopMail::errorHandler();
        // Prerequisites:
        //        MailTemplate::errorHandler();
        Payment::errorHandler();
        // Prerequisites:
        //        Text::errorHandler();
        //        Zones::errorHandler();
        //        Yellowpay::errorHandler();
        //Zones::errorHandler(); // Called by Payment::errorHandler();Shipment::errorHandler();
        // Prerequisites:
        //        Text::errorHandler();
        //Yellowpay::errorHandler(); // Called by Payment::errorHandler();
        // Prerequisites:
        //        \Cx\Core\Setting\Controller\Setting::errorHandler();
        PaymentProcessing::errorHandler();
        Shipment::errorHandler();
        // Prerequisites:
        //        Zones::errorHandler();
        // TODO: Check for and resolve recursion!
        ShopCategory::errorHandler();
        // Prerequisites:
        //        Text::errorHandler();
        //        ShopSettings::errorHandler();
        Vat::errorHandler();
        // Update page templates
        // Remove
        //        [[SHOP_JAVASCRIPT_CODE]]
        Cx\Lib\UpdateUtil::migrateContentPageUsingRegex(array('module' => 'shop'), '/{SHOP_JAVASCRIPT_CODE}[\\r\\n]*/', '', array('content'), '3.0.0');
        // Replace
        // In <!-- BEGIN subCategoriesRow -->...<!-- END subCategoriesRow -->
        //    [[SHOP_PRODUCT_DETAILLINK_IMAGE]] =>
        //    index.php?section=shop[[MODULE_INDEX]]&amp;catId=[[SHOP_CATEGORY_ID]]
        Cx\Lib\UpdateUtil::migrateContentPageUsingRegex(array('module' => 'shop'), '/(<!-- *BEGIN *subCategoriesRow *-->.+?)' . '{SHOP_PRODUCT_DETAILLINK_IMAGE}' . '(.+?<!-- *END *subCategoriesRow *-->)/s', '$1index.php?section=shop{MODULE_INDEX}&amp;catId={SHOP_CATEGORY_ID}$2', array('content'), '3.0.0');
        //    [[TXT_SEE_LARGE_PICTURE]] => [[TXT_SHOP_GO_TO_CATEGORY]]
        Cx\Lib\UpdateUtil::migrateContentPageUsingRegex(array('module' => 'shop'), '/(<!-- *BEGIN *subCategoriesRow *-->.+?)' . '{TXT_SEE_LARGE_PICTURE}' . '(.+?<!-- *END *subCategoriesRow *-->)/s', '$1{TXT_SHOP_GO_TO_CATEGORY}$2', array('content'), '3.0.0');
        //    [[SHOP_PRODUCT_...]] => [[SHOP_CATEGORY_...]]
        // There may be up to nine different such placeholders!
        $subject = NULL;
        Cx\Lib\UpdateUtil::migrateContentPageUsingRegexCallback(array('module' => 'shop'), '/(<!-- *BEGIN *subCategoriesRow *-->.+?)' . '{SHOP_PRODUCT_(.*?)}' . '(.+?<!-- *END *subCategoriesRow *-->)/s', function ($subject) {
            preg_replace('/{SHOP_PRODUCT_(.*?)}/', '{SHOP_CATEGORY_$1}', $subject);
        }, array('content'), '3.0.0');
        // shop/account
        // Needs to be replaced completely
        Cx\Lib\UpdateUtil::migrateContentPageUsingRegex(array('module' => 'shop', 'cmd' => 'account'), '/^.+$/s', <<<EOF
<div id="shop"><!-- BEGIN core_message -->
  <span class="{MESSAGE_CLASS}">{MESSAGE_TEXT}</span><!-- END core_message -->
  <div id="shop_acc_data">
    <form name="account" action="{SHOP_ACCOUNT_ACTION}" method="post"
          onsubmit="copy_address()" onreset="return shopReset()">
      <div class="customer_address">
        <h2>{TXT_CUSTOMER_ADDRESS}</h2>
        <div class="shop_text">
          <p><label>{TXT_COMPANY}</label>
            <input type="text" tabindex="1" name="company" value="{SHOP_ACCOUNT_COMPANY}" />
          </p>
          <p><label>{TXT_GREETING}<font color="#ff0000">&nbsp;*</font></label>
            <select tabindex="2" name="gender">{SHOP_ACCOUNT_PREFIX}</select>
          </p>
          <p><label>{TXT_SURNAME}<font color="#ff0000">&nbsp;*</font></label>
            <input type="text" tabindex="3" name="lastname" value="{SHOP_ACCOUNT_LASTNAME}" />
          </p>
          <p><label>{TXT_FIRSTNAME}<font color="#ff0000">&nbsp;*</font></label>
            <input type="text" tabindex="4" name="firstname" value="{SHOP_ACCOUNT_FIRSTNAME}" />
          </p>
          <p><label>{TXT_ADDRESS}<font color="#ff0000">&nbsp;*</font></label>
            <input type="text" tabindex="5" name="address" value="{SHOP_ACCOUNT_ADDRESS}" />
          </p>
          <p><label>{TXT_POSTALE_CODE}<font color="#ff0000">&nbsp;*</font></label>
            <input type="text" tabindex="6" name="zip" value="{SHOP_ACCOUNT_ZIP}" />
          </p>
          <p><label>{TXT_CITY}<font color="#ff0000">&nbsp;*</font></label>
            <input type="text" tabindex="7" name="city" value="{SHOP_ACCOUNT_CITY}" />
          </p>
          <p><label>{TXT_COUNTRY}</label>
            <select name="countryId" id="countryId" tabindex="8">
            {SHOP_ACCOUNT_COUNTRY_MENUOPTIONS}
            </select>
          </p>
          <p><label>{TXT_PHONE_NUMBER}<font color="#ff0000">&nbsp;*</font></label>
            <input type="text" tabindex="9" name="phone" value="{SHOP_ACCOUNT_PHONE}" />
          </p>
          <p><label>{TXT_FAX_NUMBER}</label>
            <input type="text" tabindex="10" name="fax" value="{SHOP_ACCOUNT_FAX}" />
          </p>
        </div>
      </div><!-- BEGIN shipping_address -->
      <div class="shipping_address">
        <h2>{TXT_SHIPPING_ADDRESS}</h2>
        <p><input type="checkbox" tabindex="21" value="1" onclick="copy_address();"
          id="equal_address" name="equal_address" {SHOP_EQUAL_ADDRESS_CHECKED} />
          <label class="description" for="equal_address">{TXT_SAME_BILLING_ADDRESS}</label>
        </p>
      </div>
      <div id="shipping_address" style="display: {SHOP_EQUAL_ADDRESS_DISPLAY};">
        <div class="shop_text">
          <p><label>{TXT_COMPANY}</label>
            <input type="text" tabindex="31" name="company2" value="{SHOP_ACCOUNT_COMPANY2}" />
          </p>
          <p><label>{TXT_GREETING}<font color="#ff0000">&nbsp;*</font></label>
            <select tabindex="32" name="gender2">{SHOP_ACCOUNT_PREFIX2}</select>
          </p>
          <p><label>{TXT_SURNAME}<font color="#ff0000">&nbsp;*</font></label>
            <input type="text" tabindex="33" name="lastname2" value="{SHOP_ACCOUNT_LASTNAME2}" />
          </p>
          <p><label>{TXT_FIRSTNAME}<font color="#ff0000">&nbsp;*</font></label>
            <input type="text" tabindex="34" name="firstname2" value="{SHOP_ACCOUNT_FIRSTNAME2}" />
          </p>
          <p><label>{TXT_ADDRESS}<font color="#ff0000">&nbsp;*</font></label>
            <input type="text" tabindex="35" name="address2" value="{SHOP_ACCOUNT_ADDRESS2}" />
          </p>
          <p><label>{TXT_POSTALE_CODE}<font color="#ff0000">&nbsp;*</font></label>
            <input type="text" tabindex="36" name="zip2" value="{SHOP_ACCOUNT_ZIP2}" size="6" />
          </p>
          <p><label>{TXT_CITY}<font color="#ff0000">&nbsp;*</font></label>
            <input type="text" tabindex="37" name="city2" value="{SHOP_ACCOUNT_CITY2}" />
          </p>
          <p><label>{TXT_COUNTRY}</label>
            <input type="hidden" name="countryId2" id="countryId2" value="{SHOP_ACCOUNT_COUNTRY2_ID}" />{SHOP_ACCOUNT_COUNTRY2}
          </p>
          <p><label>{TXT_PHONE_NUMBER}<font color="#ff0000">&nbsp;*</font></label>
            <input type="text" tabindex="38" name="phone2" value="{SHOP_ACCOUNT_PHONE2}" />
          </p>
        </div>
      </div><!-- END shipping_address --><!-- BEGIN account_details -->
      <div class="account_details">
        <h2>{TXT_YOUR_ACCOUNT_DETAILS}</h2><!-- BEGIN dont_register -->
        <p>
          <input type="checkbox" tabindex="61" value="1" id="dont_register"
                 name="dont_register" {SHOP_DONT_REGISTER_CHECKED}
                 onClick="document.getElementById('account_password').style.display = (this.checked ? 'none' : 'block');" />
          <label class="description" for="dont_register">{TXT_SHOP_ACCOUNT_DONT_REGISTER}</label>
          <br />
          {TXT_SHOP_ACCOUNT_DONT_REGISTER_NOTE}
        </p><!-- END dont_register -->
        <div class="shop_text">
          <p>
            <label>{TXT_EMAIL}<font color="#ff0000">&nbsp;*</font></label>
            <input type="text" tabindex="51" name="email" value="{SHOP_ACCOUNT_EMAIL}" />
          </p>
          <div id="account_password" style="{SHOP_ACCOUNT_PASSWORD_DISPLAY};">
            <p>
              <label>{TXT_PASSWORD}<font color="#ff0000">&nbsp;*</font></label>
              <input type="password" tabindex="52" name="password" value="" />
            </p>
            <p>{TXT_SHOP_ACCOUNT_PASSWORD_HINT}</p>
          </div>
        </div>
      </div><!-- END account_details -->
      <p>
        <input type="reset" value="{TXT_RESET}" name="reset" tabindex="71" />
        <input type="submit" value="{TXT_SHOP_CONTINUE_ARROW}" name="bsubmit" tabindex="72" />
      </p>
    </form>
  </div>
</div>
<script type="text/javascript">//<![CDATA[
function copy_address() {
  with (document.account) {
    if (jQuery("#equal_address:checked").length) {
      gender2.value = gender.value;
      company2.value = company.value;
      lastname2.value = lastname.value;
      firstname2.value = firstname.value;
      address2.value = address.value;
      zip2.value = zip.value;
      city2.value = city.value;
      phone2.value = phone.value;
      countryId2.value = countryId.value;
      jQuery("#shipping_address").hide();
    } else {
      jQuery("#shipping_address").show();
// Optionally clear the shipment address
//      gender2.value = "";
//      company2.value = "";
//      lastname2.value = "";
//      firstname2.value = "";
//      address2.value = "";
//      zip2.value = "";
//      city2.value = "";
//      phone2.value = "";
    }
  }
}
jQuery(function () {
  jQuery(".customer_address").delegate("input", "blur", function() {
    if (jQuery("#equal_address:checked").length) {
      copy_address();
    }
  });
});
// Redisplay the shipping address after the reset button has been clicked
function shopReset()
{
  if (!confirm("{TXT_SHOP_FORM_RESET_CONFIRM}")) {
    return false;
  }
  jQuery("#shipping_address").show();
  return true;
}
copy_address();
//}></script>
EOF
, array('content'), '3.0.0');
        // shop/login
        // Needs to be replaced completely
        Cx\Lib\UpdateUtil::migrateContentPageUsingRegex(array('module' => 'shop', 'cmd' => 'login'), '/^.+$/s', <<<EOF
<div id="shop">
  <!-- BEGIN core_message -->
  <span class="{MESSAGE_CLASS}">{MESSAGE_TEXT}</span>
  <!-- END core_message -->
  <div class="customer_old">
    <form name="shop_login" action="index.php?section=login" method="post">
      <input name="redirect" type="hidden" value="{SHOP_LOGIN_REDIRECT}" />
      <h2>{TXT_SHOP_ACCOUNT_EXISTING_CUSTOMER}</h2>
      <p>
        <label for="username">{TXT_SHOP_EMAIL_ADDRESS}</label>
        <input type="text" maxlength="250" value="{SHOP_LOGIN_EMAIL}" id="username" name="USERNAME" />
      </p>
      <p>
        <label for="password">{TXT_SHOP_PASSWORD}</label>
        <input type="password" maxlength="50" id="password" name="PASSWORD" />
      </p>
      <p>
        <input type="submit" value="{TXT_SHOP_ACCOUNT_LOGIN}" name="login" />
      </p>
      <p>
        <a class="lostpw" href="index.php?section=login&amp;cmd=lostpw" title="{TXT_SHOP_ACCOUNT_LOST_PASSWORD}">
        {TXT_SHOP_ACCOUNT_LOST_PASSWORD}
        </a>
      </p>
    </form>
  </div>
  <div class="customer_new">
    <form name="shop_register" action="index.php?section=shop&amp;cmd=login" method="post">
      <h2>{TXT_SHOP_ACCOUNT_NEW_CUSTOMER}</h2>
      {TXT_SHOP_ACCOUNT_NOTE}<br />
      <br />
      <!-- BEGIN register -->
      <input type="submit" value="{TXT_SHOP_BUTTON_REGISTRATION}" name="baccount" />
      <!-- END register -->
      <!-- BEGIN dont_register -->
      <input type="submit" value="{TXT_SHOP_BUTTON_NO_REGISTRATION}" name="bnoaccount" />
      <!-- END dont_register -->
    </form>
  </div>
</div>
EOF
, array('content'), '3.0.0');
        // Note:  Other templates may contain new placeholders and/or blocks,
        // however, these need to be added manually for version 3.0.0 features
        // to work.
    } catch (Cx\Lib\UpdateException $e) {
        return Cx\Lib\UpdateUtil::DefaultActionHandler($e);
    }
    //update settingsDB for missing values
    if ($objUpdate->_isNewerVersion($_CONFIG['coreCmsVersion'], '3.0.0')) {
        try {
            \Cx\Lib\UpdateUtil::sql('INSERT IGNORE INTO `' . DBPREFIX . 'core_setting` (`section`, `name`, `group`, `type`, `value`)
                                    VALUES (\'shop\', \'orderitems_amount_min\', \'config\', \'text\', \'0\')');
        } catch (\Cx\Lib\UpdateException $e) {
            return \Cx\Lib\UpdateUtil::DefaultActionHandler($e);
        }
    }
    // add access id 4 for user groups which had access to 13 or 161
    if ($objUpdate->_isNewerVersion($_CONFIG['coreCmsVersion'], '3.1.0')) {
        try {
            $result = \Cx\Lib\UpdateUtil::sql("SELECT `group_id` FROM `" . DBPREFIX . "access_group_static_ids` WHERE access_id = 13 OR access_id = 161 GROUP BY `group_id`");
            if ($result !== false) {
                while (!$result->EOF) {
                    \Cx\Lib\UpdateUtil::sql("INSERT IGNORE INTO `" . DBPREFIX . "access_group_static_ids` (`access_id`, `group_id`)\n                                                VALUES (4, " . intval($result->fields['group_id']) . ")");
                    $result->MoveNext();
                }
            }
        } catch (\Cx\Lib\UpdateException $e) {
            return \Cx\Lib\UpdateUtil::DefaultActionHandler($e);
        }
    }
    try {
        // add some necessary buttons to the confirmation page
        // fix of http://bugs.contrexx.com/contrexx/ticket/2015
        Cx\Lib\UpdateUtil::migrateContentPageUsingRegexCallback(array('module' => 'shop', 'cmd' => 'confirm'), '/.*/s', function ($content) {
            $content .= '<a href="{NODE_SHOP_ACCOUNT}">{TXT_ORDER_BACK_TO_ACCOUNT}</a><br />
                             <a href="{NODE_SHOP_CART}">{TXT_ORDER_BACK_TO_CART}</a>';
        }, array('content'), '3.2.0');
    } catch (\Cx\Lib\UpdateException $e) {
        return \Cx\Lib\UpdateUtil::DefaultActionHandler($e);
    }
    try {
        $queries = array('INSERT IGNORE INTO `' . DBPREFIX . 'core_setting` (`section`, `name`, `group`, `type`, `value`, `values`, `ord`) VALUES ("shop","payment_lsv_active","config","text","1","",18)', 'INSERT IGNORE INTO `' . DBPREFIX . 'core_setting` (`section`, `name`, `group`, `type`, `value`, `values`, `ord`) VALUES ("shop","paymill_active","config","text","1","",3)', 'INSERT IGNORE INTO `' . DBPREFIX . 'core_setting` (`section`, `name`, `group`, `type`, `value`, `values`, `ord`) VALUES ("shop","paymill_live_private_key","config","text","","",0)', 'INSERT IGNORE INTO `' . DBPREFIX . 'core_setting` (`section`, `name`, `group`, `type`, `value`, `values`, `ord`) VALUES ("shop","paymill_live_public_key","config","text","","",0)', 'INSERT IGNORE INTO `' . DBPREFIX . 'core_setting` (`section`, `name`, `group`, `type`, `value`, `values`, `ord`) VALUES ("shop","paymill_live_public_key","config","text","","",0)', 'INSERT IGNORE INTO `' . DBPREFIX . 'core_setting` (`section`, `name`, `group`, `type`, `value`, `values`, `ord`) VALUES ("shop","paymill_test_private_key","config","text","","",2)', 'INSERT IGNORE INTO `' . DBPREFIX . 'core_setting` (`section`, `name`, `group`, `type`, `value`, `values`, `ord`) VALUES ("shop","paymill_test_public_key","config","text","","",16)', 'INSERT IGNORE INTO `' . DBPREFIX . 'core_setting` (`section`, `name`, `group`, `type`, `value`, `values`, `ord`) VALUES ("shop","paymill_use_test_account","config","text","0","",15)', 'INSERT IGNORE INTO `' . DBPREFIX . 'core_setting` (`section`, `name`, `group`, `type`, `value`, `values`, `ord`) VALUES (\'shop\',\'orderitems_amount_min\',\'config\',\'text\',\'0\',\'\',0);');
        foreach ($queries as $query) {
            \Cx\Lib\UpdateUtil::sql($query);
        }
    } catch (\Cx\Lib\UpdateException $e) {
        return \Cx\Lib\UpdateUtil::DefaultActionHandler($e);
    }
    return true;
}
예제 #7
0
 /**
  * View of this Orders' items
  * @global  ADONewConnection    $objDatabase
  * @global  array               $_ARRAYLANG
  * @param   HTML_Template_Sigma $objTemplate    The template
  * @param   type                $edit           If true, items are editable
  * @param   type                $total_weight   Initial value for the
  *                                              total item weight, by
  *                                              reference.
  *                                              Usually empty or zero
  * @param   type                $i              Initial value for the row
  *                                              count, by reference.
  *                                              Usually empty or zero.
  * @return  float                               The net item sum on success,
  *                                              false otherwise
  */
 function view_items($objTemplate, $edit, &$total_weight = 0, $i = 0)
 {
     global $objDatabase, $_ARRAYLANG;
     // Order items
     // c_sp
     // Mind the custom price calculation
     $objCustomer = Customer::getById($this->customer_id);
     if (!$objCustomer) {
         \Message::error(sprintf($_ARRAYLANG['TXT_SHOP_ORDER_ERROR_MISSING_CUSTOMER'], $this->customer_id));
         $objCustomer = new Customer();
     }
     $query = "\n            SELECT `id`, `product_id`, `product_name`,\n                   `price`, `quantity`, `vat_rate`, `weight`\n              FROM `" . DBPREFIX . "module_shop" . MODULE_INDEX . "_order_items`\n             WHERE `order_id`=?";
     $objResult = $objDatabase->Execute($query, array($this->id));
     if (!$objResult) {
         return self::errorHandler();
     }
     $arrProductOptions = $this->getOptionArray();
     $total_vat_amount = 0;
     $total_net_price = 0;
     // Orders with Attributes cannot currently be edited
     // (this would spoil all the options!)
     //        $have_option = false;
     while (!$objResult->EOF) {
         $item_id = $objResult->fields['id'];
         $name = $objResult->fields['product_name'];
         $price = $objResult->fields['price'];
         $quantity = $objResult->fields['quantity'];
         $vat_rate = $objResult->fields['vat_rate'];
         $product_id = $objResult->fields['product_id'];
         // Get missing product details
         $objProduct = Product::getById($product_id);
         if (!$objProduct) {
             \Message::warning(sprintf($_ARRAYLANG['TXT_SHOP_PRODUCT_NOT_FOUND'], $product_id));
             $objProduct = new Product('', 0, $name, '', $price, 0, 0, 0, $product_id);
         }
         $code = $objProduct->code();
         $distribution = $objProduct->distribution();
         if (isset($arrProductOptions[$item_id])) {
             if ($edit) {
                 // Edit options
             } else {
                 //DBG::log("Order::view_items(): Item ID $item_id, Attributes: ".var_export($arrProductOptions[$item_id], true));
                 // Verify that options are properly shown
                 foreach ($arrProductOptions[$item_id] as $attribute_id => $attribute) {
                     //DBG::log("Order::view_items(): Added option, price: $options_price");
                     foreach ($attribute as $a) {
                         $name .= '<i><br />- ' . $attribute_id . ': ' . $a['name'] . ' (' . $a['price'] . ')</i>';
                         $price += $a['price'];
                     }
                 }
             }
         }
         // c_sp
         $row_net_price = $price * $quantity;
         $row_price = $row_net_price;
         // VAT added later, if applicable
         $total_net_price += $row_net_price;
         // Here, the VAT has to be recalculated before setting up the
         // fields.  If the VAT is excluded, it must be added here.
         // Note: the old Order.vat_amount field is no longer valid,
         // individual shop_order_items *MUST* have been UPDATEd by the
         // time PHP parses this line.
         // Also note that this implies that the vat_id and
         // country_id can be ignored, as they are considered when the
         // order is placed and the VAT is applied to the order
         // accordingly.
         // Calculate the VAT amount per row, included or excluded
         $row_vat_amount = Vat::amount($vat_rate, $row_net_price);
         //\DBG::log("$row_vat_amount = Vat::amount($vat_rate, $row_net_price)");
         // and add it to the total VAT amount
         $total_vat_amount += $row_vat_amount;
         if (!Vat::isIncluded()) {
             // Add tax to price
             $row_price += $row_vat_amount;
         }
         //else {
         // VAT is disabled.
         // There shouldn't be any non-zero percentages in the order_items!
         // but if there are, there probably has been a change and we *SHOULD*
         // still treat them as if VAT had been enabled at the time the order
         // was placed!
         // That's why the else {} block is commented out.
         //}
         $weight = '-';
         if ($distribution != 'download') {
             $weight = $objResult->fields['weight'];
             if (intval($weight) > 0) {
                 $total_weight += $weight * $quantity;
             }
         }
         $itemHasOptions = !empty($arrProductOptions[$item_id]);
         $objTemplate->setVariable(array('SHOP_PRODUCT_ID' => $product_id, 'SHOP_ROWCLASS' => 'row' . (++$i % 2 + 1), 'SHOP_QUANTITY' => $quantity, 'SHOP_PRODUCT_NAME' => $name, 'SHOP_PRODUCT_PRICE' => Currency::formatPrice($price), 'SHOP_PRODUCT_SUM' => Currency::formatPrice($row_net_price), 'SHOP_P_ID' => $edit ? $item_id : $objResult->fields['product_id'], 'SHOP_PRODUCT_CODE' => $code, 'SHOP_PRODUCT_TAX_RATE' => $edit ? $vat_rate : Vat::format($vat_rate), 'SHOP_PRODUCT_TAX_AMOUNT' => Currency::formatPrice($row_vat_amount), 'SHOP_PRODUCT_WEIGHT' => Weight::getWeightString($weight), 'SHOP_ACCOUNT_VALIDITY' => \FWUser::getValidityString($weight)));
         // Get a product menu for each Product if $edit-ing.
         // Preselect the current Product ID.
         if ($edit) {
             if ($itemHasOptions && $objTemplate->blockExists('order_item_product_options_tooltip')) {
                 $objTemplate->touchBlock('order_item_product_options_tooltip');
             }
             $objTemplate->setVariable('SHOP_PRODUCT_IDS_MENU', Products::getMenuoptions($product_id, null, +$_ARRAYLANG['TXT_SHOP_PRODUCT_MENU_FORMAT'], false));
         }
         $objTemplate->parse('order_item');
         $objResult->MoveNext();
     }
     return $total_net_price;
 }
예제 #8
0
 /**
  * Show Products
  */
 function view_product_overview()
 {
     global $_ARRAYLANG;
     if (isset($_POST['bsubmit'])) {
         $this->update_products();
     }
     if (isset($_POST['multi_action'])) {
         if ($_POST['multi_action'] == 'activate') {
             Products::set_active($_POST['selectedProductId'], true);
         } elseif ($_POST['multi_action'] == 'deactivate') {
             Products::set_active($_POST['selectedProductId'], false);
         }
     }
     self::$objTemplate->addBlockfile('SHOP_PRODUCTS_FILE', 'shop_products_block', 'module_shop_product_catalog.html');
     self::$objTemplate->setGlobalVariable($_ARRAYLANG);
     $category_id = empty($_REQUEST['category_id']) ? null : intval($_REQUEST['category_id']);
     //DBG::log("Requested Category ID: $category_id");
     $manufacturer_id = empty($_REQUEST['manufacturer_id']) ? null : intval($_REQUEST['manufacturer_id']);
     $flagSpecialoffer = isset($_REQUEST['specialoffer']);
     $searchTerm = empty($_REQUEST['searchterm']) ? null : trim(contrexx_input2raw($_REQUEST['searchterm']));
     $url = \Html::getRelativeUri();
     // TODO: Strip URL parameters: Which?
     //        \Html::stripUriParam($url, '');
     $arrSorting = array('`product`.`id`' => $_ARRAYLANG['TXT_SHOP_ID'], '`product`.`active`' => $_ARRAYLANG['TXT_SHOP_PRODUCT_ACTIVE'], '`product`.`ord`' => $_ARRAYLANG['TXT_SHOP_PRODUCT_ORDER'], 'name' => $_ARRAYLANG['TXT_SHOP_PRODUCT_NAME'], 'code' => $_ARRAYLANG['TXT_SHOP_PRODUCT_CODE'], '`product`.`discountprice`' => $_ARRAYLANG['TXT_SHOP_PRODUCT_DISCOUNTPRICE'], '`product`.`normalprice`' => $_ARRAYLANG['TXT_SHOP_PRODUCT_NORMALPRICE'], '`product`.`resellerprice`' => $_ARRAYLANG['TXT_SHOP_PRODUCT_RESELLERPRICE'], '`product`.`distribution`' => $_ARRAYLANG['TXT_SHOP_PRODUCT_DISTRIBUTION'], '`product`.`stock`' => $_ARRAYLANG['TXT_SHOP_PRODUCT_STOCK']);
     $objSorting = new \Sorting($url, $arrSorting, false, 'order_shop_product');
     $limit = \Cx\Core\Setting\Controller\Setting::getValue('numof_products_per_page_backend', 'Shop');
     $tries = 2;
     while ($tries--) {
         // have to set $count again because it will be set to 0 in Products::getByShopParams
         $count = $limit;
         // Mind that $count is handed over by reference.
         $arrProducts = Products::getByShopParams($count, \Paging::getPosition(), 0, $category_id, $manufacturer_id, $searchTerm, $flagSpecialoffer, false, $objSorting->getOrder(), null, true);
         if (count($arrProducts) > 0 || \Paging::getPosition() == 0) {
             break;
         }
         \Paging::reset();
     }
     self::$objTemplate->setVariable(array('SHOP_CATEGORY_MENU' => \Html::getSelect('category_id', array(0 => $_ARRAYLANG['TXT_ALL_PRODUCT_GROUPS']) + ShopCategories::getNameArray(), $category_id), 'SHOP_SEARCH_TERM' => $searchTerm, 'SHOP_PRODUCT_TOTAL' => $count));
     if (empty($arrProducts)) {
         self::$objTemplate->touchBlock('no_product');
         return true;
     }
     self::$objTemplate->setVariable(array('SHOP_PRODUCT_PAGING' => \Paging::get($url, '<b>' . $_ARRAYLANG['TXT_PRODUCTS'] . '</b>', $count, $limit, true), 'SHOP_HEADING_PRODUCT_ID' => $objSorting->getHeaderForField('`product`.`id`'), 'SHOP_HEADING_PRODUCT_ACTIVE' => $objSorting->getHeaderForField('`product`.`active`'), 'SHOP_HEADING_PRODUCT_ORD' => $objSorting->getHeaderForField('`product`.`ord`'), 'SHOP_HEADING_PRODUCT_NAME' => $objSorting->getHeaderForField('name'), 'SHOP_HEADING_PRODUCT_CODE' => $objSorting->getHeaderForField('code'), 'SHOP_HEADING_PRODUCT_DISCOUNTPRICE' => $objSorting->getHeaderForField('`product`.`discountprice`'), 'SHOP_HEADING_PRODUCT_NORMALPRICE' => $objSorting->getHeaderForField('`product`.`normalprice`'), 'SHOP_HEADING_PRODUCT_RESELLERPRICE' => $objSorting->getHeaderForField('`product`.`resellerprice`'), 'SHOP_HEADING_PRODUCT_DISTRIBUTION' => $objSorting->getHeaderForField('`product`.`distribution`'), 'SHOP_HEADING_PRODUCT_STOCK' => $objSorting->getHeaderForField('`product`.`stock`')));
     $arrLanguages = \FWLanguage::getActiveFrontendLanguages();
     // Intended to show an edit link for all active frontend languages.
     // However, the design doesn't like it.  Limit to the current one.
     $arrLanguages = array(FRONTEND_LANG_ID => $arrLanguages[FRONTEND_LANG_ID]);
     $i = 0;
     foreach ($arrProducts as $objProduct) {
         $productStatus = '';
         $productStatusValue = '';
         $productStatusPicture = 'status_red.gif';
         if ($objProduct->active()) {
             $productStatus = \Html::ATTRIBUTE_CHECKED;
             $productStatusValue = 1;
             $productStatusPicture = 'status_green.gif';
         }
         $discount_active = '';
         $specialOfferValue = '';
         if ($objProduct->discount_active()) {
             $discount_active = \Html::ATTRIBUTE_CHECKED;
             $specialOfferValue = 1;
         }
         self::$objTemplate->setGlobalVariable(array('SHOP_ROWCLASS' => 'row' . (++$i % 2 + 1), 'SHOP_PRODUCT_ID' => $objProduct->id(), 'SHOP_PRODUCT_CODE' => $objProduct->code(), 'SHOP_PRODUCT_NAME' => contrexx_raw2xhtml($objProduct->name()), 'SHOP_PRODUCT_PRICE1' => Currency::formatPrice($objProduct->price()), 'SHOP_PRODUCT_PRICE2' => Currency::formatPrice($objProduct->resellerprice()), 'SHOP_PRODUCT_DISCOUNT' => Currency::formatPrice($objProduct->discountprice()), 'SHOP_PRODUCT_SPECIAL_OFFER' => $discount_active, 'SHOP_SPECIAL_OFFER_VALUE_OLD' => $specialOfferValue, 'SHOP_PRODUCT_VAT_MENU' => Vat::getShortMenuString($objProduct->vat_id(), 'taxId[' . $objProduct->id() . ']'), 'SHOP_PRODUCT_VAT_ID' => $objProduct->vat_id() ? $objProduct->vat_id() : 'NULL', 'SHOP_PRODUCT_DISTRIBUTION' => $objProduct->distribution(), 'SHOP_PRODUCT_STOCK' => $objProduct->stock(), 'SHOP_PRODUCT_SHORT_DESC' => $objProduct->short(), 'SHOP_PRODUCT_STATUS' => $productStatus, 'SHOP_PRODUCT_STATUS_PICTURE' => $productStatusPicture, 'SHOP_ACTIVE_VALUE_OLD' => $productStatusValue, 'SHOP_SORT_ORDER' => $objProduct->ord(), 'SHOP_DISTRIBUTION' => $_ARRAYLANG['TXT_DISTRIBUTION_' . strtoupper($objProduct->distribution())], 'SHOP_SHOW_PRODUCT_ON_START_PAGE_CHECKED' => $objProduct->shown_on_startpage() ? \Html::ATTRIBUTE_CHECKED : '', 'SHOP_SHOW_PRODUCT_ON_START_PAGE_OLD' => $objProduct->shown_on_startpage() ? '1' : '', 'SHOP_PRODUCT_NAME' => contrexx_raw2xhtml($objProduct->name())));
         // All languages active
         foreach ($arrLanguages as $lang_id => $arrLanguage) {
             self::$objTemplate->setVariable(array('SHOP_PRODUCT_LANGUAGE_ID' => $lang_id, 'SHOP_PRODUCT_LANGUAGE_EDIT' => sprintf($_ARRAYLANG['TXT_SHOP_PRODUCT_LANGUAGE_EDIT'], $lang_id, $arrLanguage['lang'], $arrLanguage['name'])));
             self::$objTemplate->parse('product_language');
         }
         self::$objTemplate->touchBlock('productRow');
         self::$objTemplate->parse('productRow');
     }
     return true;
 }