protected function processForm() { // get a product collection (aka cart) global $objPage; $objCart = new Cart(); // Can't call the individual rows here, it would trigger markModified and a save() $objCart->setRow(array_merge($objCart->row(), array('tstamp' => time(), 'member' => 0, 'uniqid' => null, 'config_id' => $this->iso_config_id, 'store_id' => (int) \PageModel::findByPk($objPage->rootId)->iso_store_id))); $objSubmission = $this->getSubmission(false); // add products to cart foreach ($this->arrProducts as $arrProduct) { $strProduct = 'product_' . $arrProduct['product']->id; $strQuantity = 'quantity_' . $arrProduct['product']->id; if (($this->getProductCount() > 1 || $this->getTypeCount() > 1) && !$objSubmission->{$strProduct}) { continue; } if (!$objCart->addProduct($arrProduct['product'], $arrProduct['useQuantity'] ? $objSubmission->{$strQuantity} : 1)) { $this->transformIsotopeErrorMessages(); return; } } $objCart->save(); $objOrder = $objCart->getDraftOrder(); // temporarily override the cart for generating the reviews... $objCartTmp = Isotope::getCart(); Isotope::setCart($objCart); // create steps $arrSteps = array(); $arrCheckoutInfo = array(); // billing address $objBillingAddress = new Address(); foreach ($this->arrBillingAddressFields as $strName) { $objBillingAddress->{$strName} = $objSubmission->{$strName}; } $objBillingAddress->save(); $objOrder->setBillingAddress($objBillingAddress); $objBillingAddressStep = new BillingAddress($this->objCheckoutModule); $arrSteps[] = $objBillingAddressStep; $arrCheckoutInfo['billing_address'] = $objBillingAddressStep->review()['billing_address']; // shipping address $objShippingAddress = new Address(); // standard isotope handling for distinguishing between the address types: // -> if only a billing address is available, it's also the shipping address foreach ($objSubmission->shippingaddress ? $this->arrShippingAddressFields : $this->arrBillingAddressFields as $strName) { $objShippingAddress->{str_replace('shippingaddress_', '', $strName)} = $objSubmission->{$objSubmission->shippingaddress ? $strName : str_replace('shippingaddress_', 'billingaddress_', $strName)}; } $objShippingAddress->save(); // $objOrder->setShippingAddress($objShippingAddress); // $objShippingAddressStep = new ShippingAddress($this->objCheckoutModule); // $arrSteps[] = $objShippingAddressStep; // $arrCheckoutInfo['shipping_address'] = $objShippingAddressStep->review()['shipping_address']; // add shipping method $objIsotopeShipping = Flat::findByPk($this->iso_shipping_modules); $objOrder->setShippingMethod($objIsotopeShipping); $objShippingMethodStep = new ShippingMethod($this->objCheckoutModule); $arrSteps[] = $objShippingMethodStep; $arrCheckoutInfo['shipping_method'] = $objShippingMethodStep->review()['shipping_method']; // add all the checkout info to the order $objOrder->checkout_info = $arrCheckoutInfo; $objOrder->notes = $objSubmission->notes; //... restore the former cart again Isotope::setCart($objCartTmp); $objOrder->nc_notification = $this->nc_notification; $objOrder->email_data = $this->getNotificationTokensFromSteps($arrSteps, $objOrder); // !HOOK: pre-process checkout if (isset($GLOBALS['ISO_HOOKS']['preCheckout']) && is_array($GLOBALS['ISO_HOOKS']['preCheckout'])) { foreach ($GLOBALS['ISO_HOOKS']['preCheckout'] as $callback) { $objCallback = \System::importStatic($callback[0]); if ($objCallback->{$callback}[1]($objOrder, $this->objCheckoutModule) === false) { \System::log('Callback ' . $callback[0] . '::' . $callback[1] . '() cancelled checkout for Order ID ' . $this->id, __METHOD__, TL_ERROR); $this->objCheckoutModule->redirectToStep('failed'); } } } $objOrder->lock(); $objOrder->checkout(); $objOrder->complete(); if (is_array($this->dca['config']['onsubmit_callback'])) { foreach ($this->dca['config']['onsubmit_callback'] as $key => $callback) { if ($callback[0] == 'Isotope\\Backend\\ProductCollection\\Callback' && $callback[1] == 'executeSaveHook') { unset($this->dca['config']['onsubmit_callback'][$key]); break; } } } $this->transformIsotopeErrorMessages(); parent::processForm(); }
/** * Generate the checkout step * @return string */ public function generate() { // Make sure field data is available \Controller::loadDataContainer('tl_iso_product_collection'); \System::loadLanguageFile('tl_iso_product_collection'); $objTemplate = new Template($this->strTemplate); $varValue = null; $objWidget = new FormTextArea(FormTextArea::getAttributesFromDca($GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField], $this->strField, $varValue, $this->strField, $this->strTable, $this)); $objWidget->storeValues = true; if (\Input::post('FORM_SUBMIT') == $this->strFormId) { $objWidget->validate(); $varValue = $objWidget->value; // Do not submit the field if there are errors if ($objWidget->hasErrors()) { $doNotSubmit = true; } elseif ($objWidget->submitInput()) { $objOrder = Isotope::getCart()->getDraftOrder(); // Store the form data $_SESSION['FORM_DATA'][$this->strField] = $varValue; // Set the correct empty value (see #6284, #6373) if ($varValue === '') { $varValue = $objWidget->getEmptyValue(); } // Set the new value if ($varValue !== $objOrder->{$this->strField}) { $objOrder->{$this->strField}; } } } $objTemplate->headline = $GLOBALS['TL_LANG'][$this->strTable][$this->strField][0]; $objTemplate->customerNotes = $objWidget->parse(); return $objTemplate->parse(); }
/** * Display a wildcard in the back end * @return string */ public function generate() { if (TL_MODE == 'BE') { $objTemplate = new \BackendTemplate('be_wildcard'); $objTemplate->wildcard = '### ISOTOPE ECOMMERCE: STORE CONFIG SWICHER ###'; $objTemplate->title = $this->headline; $objTemplate->id = $this->id; $objTemplate->link = $this->name; $objTemplate->href = 'contao/main.php?do=themes&table=tl_module&act=edit&id=' . $this->id; return $objTemplate->parse(); } $this->iso_config_ids = deserialize($this->iso_config_ids); if (!is_array($this->iso_config_ids) || !count($this->iso_config_ids)) { // Can't use empty() because its an object property (using __get) return ''; } if (\Input::get('config') != '') { if (in_array(\Input::get('config'), $this->iso_config_ids)) { Isotope::getCart()->config_id = \Input::get('config'); Isotope::getCart()->save(); } \Controller::redirect(preg_replace('@[?|&]config=' . \Input::get('config') . '@', '', \Environment::get('request'))); } return parent::generate(); }
/** * Generate the module */ protected function compile() { $objCart = Isotope::getCart(); $objAddress = $objCart->getShippingAddress(); $this->Template->showResults = false; $this->Template->requiresShipping = false; // There is no address if (!$objAddress->id) { return; } $this->Template->showResults = true; $arrMethods = array(); // Get the shipping methods if ($objAddress->id && $objCart->requiresShipping()) { $this->Template->requiresShipping = true; $objShippingMethods = Shipping::findMultipleByIds($this->arrShippingMethods); /* @var Shipping $objShipping */ foreach ($objShippingMethods as $objShipping) { if ($objShipping->isAvailable()) { $fltPrice = $objShipping->getPrice(); $arrMethods[] = array('label' => $objShipping->getLabel(), 'price' => $fltPrice, 'formatted_price' => Isotope::formatPriceWithCurrency($fltPrice), 'shipping' => $objShipping); } } RowClass::withKey('rowClass')->addCount('row_')->addFirstLast('row_')->addEvenOdd('row_')->applyTo($arrMethods); } $this->Template->shippingMethods = $arrMethods; }
/** * Generate the checkout step * * @return string */ public function generate() { $objTemplate = new Template($this->objModule->iso_collectionTpl); $objOrder = Isotope::getCart()->getDraftOrder(); $objOrder->addToTemplate($objTemplate, array('gallery' => $this->objModule->iso_gallery, 'sorting' => $objOrder->getItemsSortingCallable($this->objModule->iso_orderCollectionBy))); return $objTemplate->parse(); }
/** * Automatically add Billpay conditions to checkout form * * @param Form $objForm * @param \Module $objModule */ public static function addOrderCondition(Form $objForm, \Module $objModule) { if (Isotope::getCart()->hasPayment() && Isotope::getCart()->getPaymentMethod() instanceof BillpayWithSaferpay) { $strLabel = $GLOBALS['TL_LANG']['MSC']['billpay_agb_' . Isotope::getCart()->getBillingAddress()->country]; if ($strLabel == '') { throw new \LogicException('Missing BillPay AGB for country "' . Isotope::getCart()->getBillingAddress()->country . '" and language "' . $GLOBALS['TL_LANGUAGE'] . '"'); } $objForm->addFormField('billpay_confirmation', array('label' => array('', $strLabel), 'inputType' => 'checkbox', 'eval' => array('mandatory' => true))); } }
/** * Return calculated price for this shipping method * @param IsotopeProductCollection * @return float */ public function getPrice(IsotopeProductCollection $objCollection = null) { if (null === $objCollection) { $objCollection = Isotope::getCart(); } $strPrice = $this->arrData['price']; if ($this->isPercentage()) { $fltSurcharge = (double) substr($strPrice, 0, -1); $fltPrice = $objCollection->subTotal / 100 * $fltSurcharge; } else { $fltPrice = (double) $strPrice; } //Make Call to UPS API to retrieve pricing $fltPrice += $this->getLiveRateQuote($objCollection); return Isotope::calculatePrice($fltPrice, $this, 'fedex', $this->arrData['tax_class']); }
/** * Callback for add_to_cart button * * @param IsotopeProduct $objProduct * @param array $arrConfig */ public function addToCart(IsotopeProduct $objProduct, array $arrConfig = array()) { $objModule = $arrConfig['module']; $intQuantity = $objModule->iso_use_quantity && intval(\Input::post('quantity_requested')) > 0 ? intval(\Input::post('quantity_requested')) : 1; // Do not add parent of variant product to the cart if ($objProduct->hasVariants() && !$objProduct->isVariant()) { return; } if (Isotope::getCart()->addProduct($objProduct, $intQuantity, $arrConfig) !== false) { Message::addConfirmation($GLOBALS['TL_LANG']['MSC']['addedToCart']); if (!$objModule->iso_addProductJumpTo) { $this->reload(); } \Controller::redirect(\Haste\Util\Url::addQueryString('continue=' . base64_encode(\Environment::get('request')), $objModule->iso_addProductJumpTo)); } }
/** * Generate the checkout step * @return string */ public function generate() { $objTemplate = new Template($this->strTemplate); $arrAttributes = ['dateDirection' => 'gtToday', 'inputType' => 'calendar', 'eval' => ['required' => true, 'rgxp' => 'date', 'datepicker' => true]]; $varValue = null; $objWidget = new FormCalendarField(FormCalendarField::getAttributesFromDca($arrAttributes, $this->strField, $varValue, $this->strField, $this->strTable, $this)); $objWidget->storeValues = true; if (\Input::post('FORM_SUBMIT') == $this->strFormId) { $objWidget->validate(); $varValue = $objWidget->value; $rgxp = $arrAttributes['eval']['rgxp']; // Convert date formats into timestamps (check the eval setting first -> #3063) if ($varValue != '' && in_array($rgxp, array('date', 'time', 'datim'))) { try { $objDate = new \Date($varValue, \Date::getFormatFromRgxp($rgxp)); $varValue = $objDate->tstamp; } catch (\OutOfBoundsException $e) { $objWidget->addError(sprintf($GLOBALS['TL_LANG']['ERR']['invalidDate'], $varValue)); } } // Do not submit the field if there are errors if ($objWidget->hasErrors()) { $doNotSubmit = true; } elseif ($objWidget->submitInput()) { $objOrder = Isotope::getCart()->getDraftOrder(); // Store the form data $_SESSION['FORM_DATA'][$this->strField] = $varValue; // Set the correct empty value (see #6284, #6373) if ($varValue === '') { $varValue = $objWidget->getEmptyValue(); } // Set the new value if ($varValue !== $objOrder->{$this->strField}) { $objOrder->{$this->strField}; } } } $objTemplate->headline = $GLOBALS['TL_LANG'][$this->strTable]['date_picker'][0]; $objTemplate->datePicker = $objWidget->parse(); return $objTemplate->parse(); }
/** * Calculate a price, add all applicable taxes * @param float * @param array|null * @return float */ public function calculateGrossPrice($fltPrice, $arrAddresses = null) { if (!is_array($arrAddresses)) { $arrAddresses = array('billing' => Isotope::getCart()->getBillingAddress(), 'shipping' => Isotope::getCart()->getShippingAddress()); } /** @var \Isotope\Model\TaxRate $objIncludes */ if (($objIncludes = $this->getRelated('includes')) !== null && !$objIncludes->isApplicable($fltPrice, $arrAddresses)) { $fltPrice -= $objIncludes->calculateAmountIncludedInPrice($fltPrice); } if (($objRates = $this->getRelated('rates')) !== null) { /** @var \Isotope\Model\TaxRate $objTaxRate */ foreach ($objRates as $objTaxRate) { if ($objTaxRate->isApplicable($fltPrice, $arrAddresses)) { $fltPrice += $objTaxRate->calculateAmountAddedToPrice($fltPrice); if ($objTaxRate->stop) { break; } } } } return $fltPrice; }
/** * Return calculated price for this shipping method * @return float */ public function getPrice(IsotopeProductCollection $objCollection = null) { if (null === $objCollection) { $objCollection = Isotope::getCart(); } if ($this->isPercentage()) { $fltPrice = $objCollection->getSubtotal() / 100 * $this->getPercentage(); } else { $fltPrice = (double) $this->arrData['price']; } if ($this->flatCalculation == 'perProduct' || $this->flatCalculation == 'perItem') { $arrItems = $objCollection->getItems(); $intMultiplier = 0; foreach ($arrItems as $objItem) { if (!$objItem->hasProduct() || $objItem->getProduct()->isExemptFromShipping()) { continue; } $intMultiplier += $this->flatCalculation == 'perProduct' ? 1 : $objItem->quantity; } $fltPrice = $fltPrice * $intMultiplier; } return Isotope::calculatePrice($fltPrice, $this, 'price', $this->arrData['tax_class']); }
/** * Return calculated price for this shipping method * @return float */ public function getPrice(IsotopeProductCollection $objCollection = null) { if (null === $objCollection) { $objCollection = Isotope::getCart(); } if ($this->or_pricing == '1') { $fltAltPrice = $objCollection->subTotal - $objCollection->subTotal / (1 + floatval($this->alternative_price) / 100); switch ($this->alternative_price_logic) { case '1': //less $fltPrice = $this->arrData['price'] < $fltAltPrice ? $this->arrData['price'] : $fltAltPrice; break; case '2': //greater $fltPrice = $this->arrData['price'] > $fltAltPrice ? $this->arrData['price'] : $fltAltPrice; break; } return $fltPrice; } else { return $this->arrData['price']; } return Isotope::calculatePrice($fltPrice, $this, 'price', $this->arrData['tax_class']); }
/** * Prepare FIS params * @param Order * @return array */ private function prepareFISParams($objOrder) { $objBillingAddress = $objOrder->getBillingAddress(); $objShippingAddress = $objOrder->getShippingAddress(); $arrInvoice = array('ECOM_BILLTO_POSTAL_NAME_FIRST' => substr($objBillingAddress->firstname, 0, 50), 'ECOM_BILLTO_POSTAL_NAME_LAST' => substr($objBillingAddress->lastname, 0, 50), 'ECOM_SHIPTO_POSTAL_STREET_LINE1' => $objShippingAddress->street_1, 'ECOM_SHIPTO_POSTAL_POSTALCODE' => $objShippingAddress->postal, 'ECOM_SHIPTO_POSTAL_CITY' => $objShippingAddress->city, 'ECOM_SHIPTO_POSTAL_COUNTRYCODE' => strtoupper($objShippingAddress->country), 'ECOM_SHIPTO_DOB' => date('d/m/Y', $objShippingAddress->dateOfBirth), 'REF_CUSTOMERID' => substr('psp_' . $this->id . '_' . $objOrder->id . '_' . $objOrder->uniqid, 0, 17), 'ECOM_CONSUMER_GENDER' => $objBillingAddress->gender == 'male' ? 'M' : 'F'); $arrOrder = array(); $i = 1; // Need to take the items from the cart as they're not transferred to the order here yet foreach (Isotope::getCart()->getItems() as $objItem) { $objPrice = $objItem->getProduct()->getPrice(); $fltVat = Isotope::roundPrice(100 / $objPrice->getNetAmount() * $objPrice->getGrossAmount() - 100, false); $arrOrder['ITEMID' . $i] = $objItem->id; $arrOrder['ITEMNAME' . $i] = substr($objItem->getName(), 40); $arrOrder['ITEMPRICE' . $i] = $objPrice->getNetAmount(); $arrOrder['ITEMQUANT' . $i] = $objItem->quantity; $arrOrder['ITEMVATCODE' . $i] = $fltVat . '%'; $arrOrder['ITEMVAT' . $i] = Isotope::roundPrice($objPrice->getGrossAmount() - $objPrice->getNetAmount(), false); $arrOrder['FACEXCL' . $i] = $objPrice->getNetAmount(); $arrOrder['FACTOTAL' . $i] = $objPrice->getGrossAmount(); ++$i; } return array_merge($arrInvoice, $arrOrder); }
/** * Generate the next higher Document Number based on existing records * @param string * @param int * @return string */ protected function generateDocumentNumber($strPrefix, $intDigits) { $this->ensureNotLocked(); if ($this->arrData['document_number'] != '') { return $this->arrData['document_number']; } // !HOOK: generate a custom order ID if (isset($GLOBALS['ISO_HOOKS']['generateDocumentNumber']) && is_array($GLOBALS['ISO_HOOKS']['generateDocumentNumber'])) { foreach ($GLOBALS['ISO_HOOKS']['generateDocumentNumber'] as $callback) { $objCallback = \System::importStatic($callback[0]); $strOrderId = $objCallback->{$callback}[1]($this, $strPrefix, $intDigits); if ($strOrderId !== false) { $this->arrData['document_number'] = $strOrderId; break; } } } if ($this->arrData['document_number'] == '') { $strPrefix = Haste::getInstance()->call('replaceInsertTags', array($strPrefix, true)); $intPrefix = utf8_strlen($strPrefix); // Lock tables so no other order can get the same ID \Database::getInstance()->lockTables(array(static::$strTable => 'WRITE')); // Retrieve the highest available order ID $objMax = \Database::getInstance()->prepare("\n SELECT document_number\n FROM " . static::$strTable . "\n WHERE\n type=?\n " . ($strPrefix != '' ? " AND document_number LIKE '{$strPrefix}%'" : '') . "\n AND store_id=?\n ORDER BY CAST(" . ($strPrefix != '' ? "SUBSTRING(document_number, " . ($intPrefix + 1) . ")" : 'document_number') . " AS UNSIGNED) DESC\n ")->limit(1)->execute(array_search(get_called_class(), static::getModelTypes()), Isotope::getCart()->store_id); $intMax = (int) substr($objMax->document_number, $intPrefix); $this->arrData['document_number'] = $strPrefix . str_pad($intMax + 1, $intDigits, '0', STR_PAD_LEFT); } \Database::getInstance()->prepare("\n UPDATE " . static::$strTable . " SET document_number=? WHERE id=?\n ")->execute($this->arrData['document_number'], $this->id); \Database::getInstance()->unlockTables(); return $this->arrData['document_number']; }
/** * Return calculated price for this shipping method * @return float */ public function getPrice(IsotopeProductCollection $objCollection = null) { if (null === $objCollection) { $objCollection = Isotope::getCart(); } if ($this->isPercentage()) { $fltPrice = $objCollection->getSubtotal() / 100 * $this->getPercentage(); } else { $fltPrice = (double) $this->arrData['price']; } return Isotope::calculatePrice($fltPrice, $this, 'price', $this->arrData['tax_class']); }
/** * Check if the checkout can be executed * * @return bool */ protected function canCheckout() { // Redirect to login page if not logged in if ($this->iso_checkout_method == 'member' && FE_USER_LOGGED_IN !== true) { /** @type \PageModel $objJump */ $objJump = \PageModel::findPublishedById($this->iso_login_jumpTo); if (null === $objJump) { $this->Template = new \Isotope\Template('mod_message'); $this->Template->type = 'error'; $this->Template->message = $GLOBALS['TL_LANG']['ERR']['isoLoginRequired']; return false; } $objJump->loadDetails(); \Controller::redirect($objJump->getFrontendUrl(null, $objJump->language)); } elseif ($this->iso_checkout_method == 'guest' && FE_USER_LOGGED_IN === true) { $this->Template = new \Isotope\Template('mod_message'); $this->Template->type = 'error'; $this->Template->message = $GLOBALS['TL_LANG']['ERR']['checkoutNotAllowed']; return false; } // Return error message if cart is empty if (Isotope::getCart()->isEmpty()) { $this->Template = new \Isotope\Template('mod_message'); $this->Template->type = 'empty'; $this->Template->message = $GLOBALS['TL_LANG']['MSC']['noItemsInCart']; return false; } // Insufficient cart subtotal if (Isotope::getCart()->hasErrors()) { if ($this->iso_cart_jumpTo > 0) { /** @type \PageModel $objJump */ $objJump = \PageModel::findPublishedById($this->iso_cart_jumpTo); if (null !== $objJump) { $objJump->loadDetails(); \Controller::redirect($objJump->getFrontendUrl(null, $objJump->language)); } } $this->Template = new \Isotope\Template('mod_message'); $this->Template->type = 'error'; $this->Template->message = implode("</p>\n<p class=\"error message\">", Isotope::getCart()->getErrors()); return false; } return true; }
/** * Complete order if the checkout has been made. This will cleanup session data * * @return bool */ public function complete() { if ($this->isCheckoutComplete()) { unset($_SESSION['FORM_DATA']); unset($_SESSION['FILES']); // Retain custom config ID if (($objCart = Isotope::getCart()) !== null && $objCart->config_id != $this->config_id) { $objCart->config_id = $this->config_id; } return true; } return false; }
/** * Create a new address for a member and automatically set default properties * @param int * @param array|null * @return Address */ public static function createForMember($intMember, $arrFill = null) { $objAddress = new Address(); $arrData = array('pid' => $intMember, 'ptable' => 'tl_member', 'tstamp' => time(), 'store_id' => Isotope::getCart()->store_id); if (!empty($arrFill) && is_array($arrFill) && ($objMember = \MemberModel::findByPk($intMember)) !== null) { $arrData = array_intersect_key(array_merge($objMember->row(), $arrData, array('street_1' => $objMember->street, 'subdivision' => strtoupper($objMember->country . '-' . $objMember->state))), array_flip($arrFill)); } $objAddress->setRow($arrData); return $objAddress; }
/** * Create a new address for a member and automatically set default properties * * @param int $intMember * @param array|null $arrFill * * @return static */ public static function createForMember($intMember, $arrFill = null) { $objAddress = new static(); $arrData = array('pid' => $intMember, 'ptable' => 'tl_member', 'tstamp' => time(), 'store_id' => (int) Isotope::getCart()->store_id); if (!empty($arrFill) && is_array($arrFill) && ($objMember = \MemberModel::findByPk($intMember)) !== null) { // Generate address data from tl_member, limit to fields enabled in the shop configuration $arrMember = array_intersect_key(array_merge($objMember->row(), array('street_1' => $objMember->street, 'subdivision' => strtoupper($objMember->country . '-' . $objMember->state))), array_flip($arrFill)); $arrData = array_merge($arrMember, $arrData); } $objAddress->setRow($arrData); return $objAddress; }
/** * Return all available variant IDs of this product * * @return int[]|false */ public function getVariantIds() { if (null === $this->arrVariantIds) { $this->arrVariantIds = array(); // Nothing to do if we have no variants if (!$this->hasVariants()) { return $this->arrVariantIds; } $time = time(); $blnHasProtected = false; $blnHasGroups = false; $strQuery = "SELECT id, protected, groups FROM tl_iso_product WHERE pid=" . $this->getProductId() . " AND language='' AND published='1' AND (start='' OR start<{$time}) AND (stop='' OR stop>{$time})"; if (BE_USER_LOGGED_IN !== true) { $arrAttributes = $this->getVariantAttributes(); $blnHasProtected = in_array('protected', $arrAttributes); $blnHasGroups = in_array('groups', $arrAttributes); // Hide guests-only products when logged in if (FE_USER_LOGGED_IN === true && in_array('guests', $arrAttributes)) { $strQuery .= " AND (guests=''" . ($blnHasProtected ? " OR protected='1'" : '') . ")"; } elseif (FE_USER_LOGGED_IN !== true && $blnHasProtected) { $strQuery .= " AND protected=''"; } } /** @type object $objVariants */ $objVariants = \Database::getInstance()->query($strQuery); while ($objVariants->next()) { if ($blnHasProtected && $objVariants->protected) { $groups = $blnHasGroups ? deserialize($objVariants->groups) : ''; if (empty($groups) || !is_array($groups) || !count(array_intersect($groups, \FrontendUser::getInstance()->groups))) { continue; } } $this->arrVariantIds[] = $objVariants->id; } // Only show variants where a price is available if (!empty($this->arrVariantIds) && $this->hasVariantPrices()) { if ($this->hasAdvancedPrices()) { $objPrices = ProductPrice::findAdvancedByProductIdsAndCollection($this->arrVariantIds, Isotope::getCart()); } else { $objPrices = ProductPrice::findPrimaryByProductIds($this->arrVariantIds); } if (null === $objPrices) { $this->arrVariantIds = array(); } else { $this->arrVariantIds = $objPrices->fetchEach('pid'); } } } return $this->arrVariantIds; }
/** * Callback for checkout step "review". Remove rule usages if an order failed. * @todo this will no longer work */ public function cleanRuleUsages(&$objModule) { \Database::getInstance()->query("DELETE FROM tl_iso_rule_usage WHERE pid=(SELECT id FROM tl_iso_product_collection WHERE type='order' AND source_collection_id=" . (int) Isotope::getCart()->id . ")"); return ''; }
/** * Replaces Isotope specific InsertTags in Frontend * @param string * @return mixed */ public function replaceIsotopeTags($strTag) { $arrTag = trimsplit('::', $strTag); // {{isotope::*}} and {{cache_isotope::*}} insert tags if ($arrTag[0] == 'isotope' || $arrTag[0] == 'cache_isotope') { switch ($arrTag[1]) { case 'cart_items': return Isotope::getCart()->countItems(); break; case 'cart_quantity': return Isotope::getCart()->sumItemsQuantity(); break; case 'cart_items_label': $intCount = Isotope::getCart()->countItems(); if (!$intCount) { return ''; } return $intCount == 1 ? '(' . $GLOBALS['TL_LANG']['MSC']['productSingle'] . ')' : sprintf('(' . $GLOBALS['TL_LANG']['MSC']['productMultiple'] . ')', $intCount); break; case 'cart_quantity_label': $intCount = Isotope::getCart()->sumItemsQuantity(); if (!$intCount) { return ''; } return $intCount == 1 ? '(' . $GLOBALS['TL_LANG']['MSC']['productSingle'] . ')' : sprintf('(' . $GLOBALS['TL_LANG']['MSC']['productMultiple'] . ')', $intCount); break; case 'cart_subtotal': return Isotope::formatPriceWithCurrency(Isotope::getCart()->getSubtotal()); break; case 'cart_taxfree_subtotal': return Isotope::formatPriceWithCurrency(Isotope::getCart()->getTaxFreeSubtotal()); break; case 'cart_total': return Isotope::formatPriceWithCurrency(Isotope::getCart()->getTotal()); break; case 'cart_taxfree_total': return Isotope::formatPriceWithCurrency(Isotope::getCart()->getTaxFreeTotal()); break; } return ''; } elseif ($arrTag[0] == 'isolabel') { return Translation::get($arrTag[1], $arrTag[2]); } elseif ($arrTag[0] == 'order') { if (($objOrder = Order::findOneByUniqid(\Input::get('uid'))) !== null) { return $objOrder->{$arrTag[1]}; } return ''; } elseif ($arrTag[0] == 'product') { // 2 possible use cases: // {{product::attribute}} - gets the data of the current product (Product::getActive() or GET parameter "product") // {{product::attribute::product_id}} - gets the data of the specified product ID if (count($arrTag) == 3) { $objProduct = Product::findAvailableByPk($arrTag[2]); } else { if (($objProduct = Product::getActive()) === null) { $objProduct = Product::findAvailableByIdOrAlias(\Haste\Input\Input::getAutoItem('product', false, true)); } } return $objProduct !== null ? $objProduct->{$arrTag[1]} : ''; } return false; }
/** * Check if the checkout can be executed * @return bool */ protected function canCheckout() { // Redirect to login page if not logged in if ($this->iso_checkout_method == 'member' && FE_USER_LOGGED_IN !== true) { $objPage = \Database::getInstance()->prepare("SELECT id,alias FROM tl_page WHERE id=?")->limit(1)->execute($this->iso_login_jumpTo); if (!$objPage->numRows) { $this->Template = new \Isotope\Template('mod_message'); $this->Template->type = 'error'; $this->Template->message = $GLOBALS['TL_LANG']['ERR']['isoLoginRequired']; return false; } \Controller::redirect(\Controller::generateFrontendUrl($objPage->row())); } elseif ($this->iso_checkout_method == 'guest' && FE_USER_LOGGED_IN === true) { $this->Template = new \Isotope\Template('mod_message'); $this->Template->type = 'error'; $this->Template->message = $GLOBALS['TL_LANG']['ERR']['checkoutNotAllowed']; return false; } // Return error message if cart is empty if (Isotope::getCart()->isEmpty()) { $this->Template = new \Isotope\Template('mod_message'); $this->Template->type = 'empty'; $this->Template->message = $GLOBALS['TL_LANG']['MSC']['noItemsInCart']; return false; } // Insufficient cart subtotal if (Isotope::getCart()->hasErrors()) { if ($this->iso_cart_jumpTo > 0) { $objJump = \PageModel::findWithDetails($this->iso_cart_jumpTo); if (null !== $objJump) { \Controller::redirect(\Controller::generateFrontendUrl($objJump->row(), null, $objJump->language)); } } $this->Template = new \Isotope\Template('mod_message'); $this->Template->type = 'error'; $this->Template->message = implode("</p>\n<p class=\"error message\">", Isotope::getCart()->getErrors()); return false; } return true; }
/** * Replace {{isotope::}} insert tags. * * @param string $token * * @return string * * @deprecated Deprecated since version 2.3, to be removed in 3.0. */ private function getValueForIsotopeTag($token) { if (strpos($token, 'cart_') === 0) { return $this->getValueForCollectionTag(Isotope::getCart(), array('cart', substr($token, 5))); } return ''; }
/** * Generate buttons for cart template * @return array */ protected function generateButtons() { $arrButtons = array(); // Add "update cart" button $arrButtons['update'] = array('type' => 'submit', 'name' => 'button_update', 'label' => $GLOBALS['TL_LANG']['MSC']['updateCartBT']); // Add button to cart button (usually if not on the cart page) if ($this->iso_cart_jumpTo > 0) { $objJumpToCart = \PageModel::findByPk($this->iso_cart_jumpTo); if (null !== $objJumpToCart) { $arrButtons['cart'] = array('type' => 'submit', 'name' => 'button_cart', 'label' => $GLOBALS['TL_LANG']['MSC']['cartBT'], 'href' => \Controller::generateFrontendUrl($objJumpToCart->row())); if (\Input::post('FORM_SUBMIT') == $this->strFormId && \Input::post('button_cart') != '') { $this->jumpToOrReload($this->iso_cart_jumpTo); } } } // Add button to checkout page if ($this->iso_checkout_jumpTo > 0 && !Isotope::getCart()->hasErrors()) { $objJumpToCheckout = \PageModel::findByPk($this->iso_checkout_jumpTo); if (null !== $objJumpToCheckout) { $arrButtons['checkout'] = array('type' => 'submit', 'name' => 'button_checkout', 'label' => $GLOBALS['TL_LANG']['MSC']['checkoutBT'], 'href' => \Controller::generateFrontendUrl($objJumpToCheckout->row())); if (\Input::post('FORM_SUBMIT') == $this->strFormId && \Input::post('button_checkout') != '') { $this->jumpToOrReload($this->iso_checkout_jumpTo); } } } if ($this->iso_continueShopping && $this->Input->get('continue') != '') { $arrButtons['continue'] = array('type' => 'submit', 'name' => 'button_continue', 'label' => $GLOBALS['TL_LANG']['MSC']['continueShoppingBT'], 'href' => ampersand(base64_decode($this->Input->get('continue', true)))); if (\Input::post('FORM_SUBMIT') == $this->strFormId && \Input::post('button_continue') != '') { \Controller::redirect($arrButtons['continue']['href']); } } return $arrButtons; }
/** * Return review information for last page of checkout * @return string */ public function review() { return array('payment_method' => array('headline' => $GLOBALS['TL_LANG']['MSC']['payment_method'], 'info' => Isotope::getCart()->getDraftOrder()->getPaymentMethod()->checkoutReview(), 'note' => Isotope::getCart()->getDraftOrder()->getPaymentMethod()->note, 'edit' => \Isotope\Module\Checkout::generateUrlForStep('payment'))); }
/** * Calculate a price like it was in Isotope < 2.3 * * @param float $fltPrice * @param array $arrAddresses * * @return float */ public function calculateLegacyPrice($fltPrice, array $arrAddresses = null) { if (!is_array($arrAddresses)) { $arrAddresses = array('billing' => Isotope::getCart()->getBillingAddress()); if (Isotope::getCart()->requiresShipping()) { $arrAddresses['shipping'] = Isotope::getCart()->getShippingAddress(); } } /** @var \Isotope\Model\TaxRate $objIncludes */ $objIncludes = $this->getRelated('includes'); if ($objIncludes !== null && !$objIncludes->isApplicable($fltPrice, $arrAddresses)) { $fltPrice -= $objIncludes->calculateAmountIncludedInPrice($fltPrice); } return $fltPrice; }
/** * Return review information for last page of checkout * @return string */ public function review() { return array('shipping_method' => array('headline' => $GLOBALS['TL_LANG']['MSC']['shipping_method'], 'info' => Isotope::getCart()->getShippingMethod()->checkoutReview(), 'note' => Isotope::getCart()->getShippingMethod()->note, 'edit' => \Isotope\Module\Checkout::generateUrlForStep('shipping'))); }
/** * Set new address in cart * @param Isotope\Model\Address */ protected function setAddress(AddressModel $objAddress) { Isotope::getCart()->setShippingAddress($objAddress); }
/** * Fetch rules */ protected static function findByConditions($arrProcedures, $arrValues = array(), $arrProducts = null, $blnIncludeVariants = false, $arrAttributeData = array()) { // Only enabled rules $arrProcedures[] = "enabled='1'"; // Date & Time restrictions $date = date('Y-m-d'); $time = date('H:i:s'); $arrProcedures[] = "(startDate='' OR startDate <= UNIX_TIMESTAMP('{$date}'))"; $arrProcedures[] = "(endDate='' OR endDate >= UNIX_TIMESTAMP('{$date}'))"; $arrProcedures[] = "(startTime='' OR startTime <= UNIX_TIMESTAMP('1970-01-01 {$time}'))"; $arrProcedures[] = "(endTime='' OR endTime >= UNIX_TIMESTAMP('1970-01-01 {$time}'))"; // Limits $arrProcedures[] = "(limitPerConfig=0 OR limitPerConfig>(SELECT COUNT(*) FROM tl_iso_rule_usage WHERE pid=r.id AND config_id=" . (int) Isotope::getConfig()->id . " AND order_id NOT IN (SELECT id FROM tl_iso_product_collection WHERE type='order' AND source_collection_id=" . (int) Isotope::getCart()->id . ")))"; if (Isotope::getCart()->member > 0) { $arrProcedures[] = "(limitPerMember=0 OR limitPerMember>(SELECT COUNT(*) FROM tl_iso_rule_usage WHERE pid=r.id AND member_id=" . (int) \FrontendUser::getInstance()->id . " AND order_id NOT IN (SELECT id FROM tl_iso_product_collection WHERE type='order' AND source_collection_id=" . (int) Isotope::getCart()->id . ")))"; } // Store config restrictions $arrProcedures[] = "(configRestrictions=''\n OR (configRestrictions='1' AND configCondition='1' AND (SELECT COUNT(*) FROM tl_iso_rule_restriction WHERE pid=r.id AND type='configs' AND object_id=" . (int) Isotope::getConfig()->id . ")>0)\n OR (configRestrictions='1' AND configCondition='0' AND (SELECT COUNT(*) FROM tl_iso_rule_restriction WHERE pid=r.id AND type='configs' AND object_id=" . (int) Isotope::getConfig()->id . ")=0))"; // Member restrictions if (Isotope::getCart()->member > 0) { $arrGroups = array_map('intval', deserialize(\FrontendUser::getInstance()->groups, true)); $arrProcedures[] = "(memberRestrictions='none'\n OR (memberRestrictions='guests' AND memberCondition='0')\n OR (memberRestrictions='members' AND memberCondition='1' AND (SELECT COUNT(*) FROM tl_iso_rule_restriction WHERE pid=r.id AND type='members' AND object_id=" . (int) \FrontendUser::getInstance()->id . ")>0)\n OR (memberRestrictions='members' AND memberCondition='0' AND (SELECT COUNT(*) FROM tl_iso_rule_restriction WHERE pid=r.id AND type='members' AND object_id=" . (int) \FrontendUser::getInstance()->id . ")=0)\n " . (!empty($arrGroups) ? "\n OR (memberRestrictions='groups' AND memberCondition='1' AND (SELECT COUNT(*) FROM tl_iso_rule_restriction WHERE pid=r.id AND type='groups' AND object_id IN (" . implode(',', $arrGroups) . "))>0)\n OR (memberRestrictions='groups' AND memberCondition='0' AND (SELECT COUNT(*) FROM tl_iso_rule_restriction WHERE pid=r.id AND type='groups' AND object_id IN (" . implode(',', $arrGroups) . "))=0)" : '') . ")"; } else { $arrProcedures[] = "(memberRestrictions='none' OR (memberRestrictions='guests' AND memberCondition='1'))"; } // Product restrictions if (!is_array($arrProducts)) { $arrProducts = Isotope::getCart()->getItems(); } if (!empty($arrProducts)) { $arrProductIds = array(0); $arrVariantIds = array(0); $arrAttributes = array(0); $arrTypes = array(0); // Prepare product attribute condition $objAttributeRules = \Database::getInstance()->execute("SELECT * FROM " . static::$strTable . " WHERE enabled='1' AND productRestrictions='attribute' AND attributeName!='' GROUP BY attributeName, attributeCondition"); while ($objAttributeRules->next()) { $arrAttributes[] = array('attribute' => $objAttributeRules->attributeName, 'condition' => $objAttributeRules->attributeCondition, 'values' => array()); } foreach ($arrProducts as $objProduct) { if ($objProduct instanceof ProductCollectionItem) { if (!$objProduct->hasProduct()) { continue; } $objProduct = $objProduct->getProduct(); } $arrProductIds[] = (int) $objProduct->getProductId(); $arrVariantIds[] = (int) $objProduct->{$objProduct->getPk()}; $arrTypes[] = (int) $objProduct->type; if ($objProduct->isVariant()) { $arrVariantIds[] = (int) $objProduct->pid; } if ($blnIncludeVariants && $objProduct->hasVariants()) { $arrVariantIds = array_merge($arrVariantIds, $objProduct->getVariantIds()); } $arrOptions = $objProduct->getOptions(); foreach ($arrAttributes as $k => $restriction) { $varValue = null; if (isset($arrAttributeData[$restriction['attribute']])) { $varValue = $arrAttributeData[$restriction['attribute']]; } elseif (isset($arrOptions[$restriction['attribute']])) { $varValue = $arrOptions[$restriction['attribute']]; } else { $varValue = $objProduct->{$restriction['attribute']}; } if (!is_null($varValue)) { $arrAttributes[$k]['values'][] = is_array($varValue) ? serialize($varValue) : $varValue; } } } $arrProductIds = array_unique($arrProductIds); $arrVariantIds = array_unique($arrVariantIds); $arrRestrictions = array("productRestrictions='none'"); $arrRestrictions[] = "(productRestrictions='producttypes' AND productCondition='1' AND (SELECT COUNT(*) FROM tl_iso_rule_restriction WHERE pid=r.id AND type='producttypes' AND object_id IN (" . implode(',', $arrTypes) . "))>0)"; $arrRestrictions[] = "(productRestrictions='producttypes' AND productCondition='0' AND (SELECT COUNT(*) FROM tl_iso_rule_restriction WHERE pid=r.id AND type='producttypes' AND object_id IN (" . implode(',', $arrTypes) . "))=0)"; $arrRestrictions[] = "(productRestrictions='products' AND productCondition='1' AND (SELECT COUNT(*) FROM tl_iso_rule_restriction WHERE pid=r.id AND type='products' AND object_id IN (" . implode(',', $arrProductIds) . "))>0)"; $arrRestrictions[] = "(productRestrictions='products' AND productCondition='0' AND (SELECT COUNT(*) FROM tl_iso_rule_restriction WHERE pid=r.id AND type='products' AND object_id IN (" . implode(',', $arrProductIds) . "))=0)"; $arrRestrictions[] = "(productRestrictions='variants' AND productCondition='1' AND (SELECT COUNT(*) FROM tl_iso_rule_restriction WHERE pid=r.id AND type='variants' AND object_id IN (" . implode(',', $arrVariantIds) . "))>0)"; $arrRestrictions[] = "(productRestrictions='variants' AND productCondition='0' AND (SELECT COUNT(*) FROM tl_iso_rule_restriction WHERE pid=r.id AND type='variants' AND object_id IN (" . implode(',', $arrVariantIds) . "))=0)"; $arrRestrictions[] = "(productRestrictions='pages' AND productCondition='1' AND (SELECT COUNT(*) FROM tl_iso_rule_restriction WHERE pid=r.id AND type='pages' AND object_id IN (SELECT page_id FROM " . \Isotope\Model\ProductCategory::getTable() . " WHERE pid IN (" . implode(',', $arrProductIds) . ")))>0)"; $arrRestrictions[] = "(productRestrictions='pages' AND productCondition='0' AND (SELECT COUNT(*) FROM tl_iso_rule_restriction WHERE pid=r.id AND type='pages' AND object_id IN (SELECT page_id FROM " . \Isotope\Model\ProductCategory::getTable() . " WHERE pid IN (" . implode(',', $arrProductIds) . ")))=0)"; foreach ($arrAttributes as $restriction) { if (empty($restriction['values'])) { continue; } $strRestriction = "(productRestrictions='attribute' AND attributeName='" . $restriction['attribute'] . "' AND attributeCondition='" . $restriction['condition'] . "' AND "; switch ($restriction['condition']) { case 'eq': case 'neq': $strRestriction .= "attributeValue" . ($restriction['condition'] == 'neq' ? " NOT" : '') . " IN ('" . implode("','", array_map('mysql_real_escape_string', $restriction['values'])) . "')"; break; case 'lt': case 'gt': case 'elt': case 'egt': $arrOR = array(); foreach ($restriction['values'] as $value) { $arrOR[] = "attributeValue" . ($restriction['condition'] == 'lt' || $restriction['condition'] == 'elt' ? '>' : '<') . ($restriction['condition'] == 'elt' || $restriction['condition'] == 'egt' ? '=' : '') . '?'; $arrValues[] = $value; } $strRestriction .= '(' . implode(' OR ', $arrOR) . ')'; break; case 'starts': case 'ends': case 'contains': $arrOR = array(); foreach ($restriction['values'] as $value) { $arrOR[] = "? LIKE CONCAT(" . ($restriction['condition'] == 'ends' || $restriction['condition'] == 'contains' ? "'%', " : '') . "attributeValue" . ($restriction['condition'] == 'starts' || $restriction['condition'] == 'contains' ? ", '%'" : '') . ")"; $arrValues[] = $value; } $strRestriction .= '(' . implode(' OR ', $arrOR) . ')'; break; default: throw new \InvalidArgumentException('Unknown rule condition "' . $restriction['condition'] . '"'); } $arrRestrictions[] = $strRestriction . ')'; } $arrProcedures[] = '(' . implode(' OR ', $arrRestrictions) . ')'; } $objResult = \Database::getInstance()->prepare("SELECT * FROM " . static::$strTable . " r WHERE " . implode(' AND ', $arrProcedures))->execute($arrValues); if ($objResult->numRows) { return \Model\Collection::createFromDbResult($objResult, static::$strTable); } return null; }