Пример #1
0
 /**
  * Return the PayPal form.
  *
  * @param IsotopeProductCollection|Order $objOrder  The order being places
  * @param \Module|Checkout               $objModule The checkout module instance
  *
  * @return  string
  */
 public function checkoutForm(IsotopeProductCollection $objOrder, \Module $objModule)
 {
     $arrData = array();
     $fltDiscount = 0;
     $i = 0;
     foreach ($objOrder->getItems() as $objItem) {
         // Set the active product for insert tags replacement
         if ($objItem->hasProduct()) {
             Product::setActive($objItem->getProduct());
         }
         $strConfig = '';
         $arrConfig = $objItem->getConfiguration();
         if (!empty($arrConfig)) {
             array_walk($arrConfig, function (&$option) {
                 $option = $option['label'] . ': ' . (string) $option;
             });
             $strConfig = ' (' . implode(', ', $arrConfig) . ')';
         }
         $arrData['item_number_' . ++$i] = $objItem->getSku();
         $arrData['item_name_' . $i] = \StringUtil::restoreBasicEntities($objItem->getName() . $strConfig);
         $arrData['amount_' . $i] = $objItem->getPrice();
         $arrData['quantity_' . $i] = $objItem->quantity;
     }
     foreach ($objOrder->getSurcharges() as $objSurcharge) {
         if (!$objSurcharge->addToTotal) {
             continue;
         }
         // PayPal does only support one single discount item
         if ($objSurcharge->total_price < 0) {
             $fltDiscount -= $objSurcharge->total_price;
             continue;
         }
         $arrData['item_name_' . ++$i] = $objSurcharge->label;
         $arrData['amount_' . $i] = $objSurcharge->total_price;
     }
     $objTemplate = new \Isotope\Template('iso_payment_paypal');
     $objTemplate->setData($this->arrData);
     $objTemplate->id = $this->id;
     $objTemplate->action = 'https://www.' . ($this->debug ? 'sandbox.' : '') . 'paypal.com/cgi-bin/webscr';
     $objTemplate->invoice = $objOrder->id;
     $objTemplate->data = array_map('specialchars', $arrData);
     $objTemplate->discount = $fltDiscount;
     $objTemplate->address = $objOrder->getBillingAddress();
     $objTemplate->currency = $objOrder->currency;
     $objTemplate->return = \Environment::get('base') . $objModule->generateUrlForStep('complete', $objOrder);
     $objTemplate->cancel_return = \Environment::get('base') . $objModule->generateUrlForStep('failed');
     $objTemplate->notify_url = \Environment::get('base') . 'system/modules/isotope/postsale.php?mod=pay&id=' . $this->id;
     $objTemplate->headline = specialchars($GLOBALS['TL_LANG']['MSC']['pay_with_redirect'][0]);
     $objTemplate->message = specialchars($GLOBALS['TL_LANG']['MSC']['pay_with_redirect'][1]);
     $objTemplate->slabel = specialchars($GLOBALS['TL_LANG']['MSC']['pay_with_redirect'][2]);
     $objTemplate->noscript = specialchars($GLOBALS['TL_LANG']['MSC']['pay_with_redirect'][3]);
     return $objTemplate->parse();
 }
Пример #2
0
 public static function createForRuleInCollection(RuleModel $objRule, IsotopeProductCollection $objCollection)
 {
     // Cart subtotal
     if ($objRule->minSubtotal > 0 && $objCollection->getSubtotal() < $objRule->minSubtotal || $objRule->maxSubtotal > 0 && $objCollection->getSubtotal() > $objRule->maxSubtotal) {
         return null;
     }
     $arrCollectionItems = $objCollection->getItems();
     $blnMatch = false;
     $blnPercentage = $objRule->isPercentage();
     $fltDiscount = $blnPercentage ? $objRule->getPercentage() : 0;
     $fltTotal = 0;
     $arrSubtract = array();
     $objSurcharge = new static();
     $objSurcharge->label = $objRule->getLabel();
     $objSurcharge->price = $objRule->getPercentageLabel();
     $objSurcharge->total_price = 0;
     $objSurcharge->tax_class = 0;
     $objSurcharge->before_tax = true;
     $objSurcharge->addToTotal = true;
     // Product or producttype restrictions
     if ($objRule->productRestrictions != '' && $objRule->productRestrictions != 'none') {
         $arrLimit = \Database::getInstance()->execute("SELECT object_id FROM tl_iso_rule_restriction WHERE pid={$objRule->id} AND type='{$objRule->productRestrictions}'")->fetchEach('object_id');
         if ($objRule->productRestrictions == 'pages' && !empty($arrLimit)) {
             $arrLimit = \Database::getInstance()->execute("SELECT pid FROM " . \Isotope\Model\ProductCategory::getTable() . " WHERE page_id IN (" . implode(',', $arrLimit) . ")")->fetchEach('pid');
         }
         if ($objRule->quantityMode == 'cart_products' || $objRule->quantityMode == 'cart_items') {
             $intTotal = 0;
             foreach ($arrCollectionItems as $objItem) {
                 if (!$objItem->hasProduct()) {
                     continue;
                 }
                 $objProduct = $objItem->getProduct();
                 if (($objRule->productRestrictions == 'products' || $objRule->productRestrictions == 'variants' || $objRule->productRestrictions == 'pages') && (in_array($objProduct->id, $arrLimit) || $objProduct->pid > 0 && in_array($objProduct->pid, $arrLimit)) || $objRule->productRestrictions == 'producttypes' && in_array($objProduct->type, $arrLimit)) {
                     $intTotal += $objRule->quantityMode == 'cart_items' ? $objItem->quantity : 1;
                 }
             }
         }
     } else {
         switch ($objRule->quantityMode) {
             case 'cart_products':
                 $intTotal = $objCollection->countItems();
                 break;
             case 'cart_items':
                 $intTotal = $objCollection->sumItemsQuantity();
                 break;
         }
     }
     foreach ($arrCollectionItems as $objItem) {
         if (!$objItem->hasProduct()) {
             continue;
         }
         $objProduct = $objItem->getProduct();
         // Product restrictions
         if (($objRule->productRestrictions == 'products' || $objRule->productRestrictions == 'variants' || $objRule->productRestrictions == 'pages') && (!in_array($objProduct->id, $arrLimit) && ($objProduct->pid == 0 || !in_array($objProduct->pid, $arrLimit))) || $objRule->productRestrictions == 'producttypes' && !in_array($objProduct->type, $arrLimit)) {
             continue;
         } elseif ($objRule->productRestrictions == 'attribute') {
             switch ($objRule->attributeCondition) {
                 case 'eq':
                     if (!($objProduct->{$objRule->attributeName} == $objRule->attributeValue)) {
                         continue 2;
                     }
                     break;
                 case 'neq':
                     if (!($objProduct->{$objRule->attributeName} != $objRule->attributeValue)) {
                         continue 2;
                     }
                     break;
                 case 'lt':
                     if (!($objProduct->{$objRule->attributeName} < $objRule->attributeValue)) {
                         continue 2;
                     }
                     break;
                 case 'gt':
                     if (!($objProduct->{$objRule->attributeName} > $objRule->attributeValue)) {
                         continue 2;
                     }
                     break;
                 case 'elt':
                     if (!($objProduct->{$objRule->attributeName} <= $objRule->attributeValue)) {
                         continue 2;
                     }
                     break;
                 case 'egt':
                     if (!($objProduct->{$objRule->attributeName} >= $objRule->attributeValue)) {
                         continue 2;
                     }
                     break;
                 case 'starts':
                     if (stripos($objProduct->{$objRule->attributeName}, $objRule->attributeValue) !== 0) {
                         continue 2;
                     }
                     break;
                 case 'ends':
                     if (strripos($objProduct->{$objRule->attributeName}, $objRule->attributeValue) !== strlen($objProduct->{$objRule->attributeName}) - strlen($objRule->attributeValue)) {
                         continue 2;
                     }
                     break;
                 case 'contains':
                     if (stripos($objProduct->{$objRule->attributeName}, $objRule->attributeValue) === false) {
                         continue 2;
                     }
                     break;
                 default:
                     throw new \Exception('Unknown rule condition "' . $objRule->attributeCondition . '"');
             }
         }
         // Because we apply to the quantity of only this product, we override $intTotal in every foreach loop
         // This matches tl_iso_rules.quantityMode="product_quantity"
         if ($objRule->quantityMode != 'cart_products' && $objRule->quantityMode != 'cart_items') {
             $intTotal = $objItem->quantity;
         }
         // Quantity does not match, do not apply to this product
         if ($objRule->minItemQuantity > 0 && $objRule->minItemQuantity > $intTotal || $objRule->maxItemQuantity > 0 && $objRule->maxItemQuantity < $intTotal) {
             continue;
         }
         // Apply To
         switch ($objRule->applyTo) {
             case 'products':
                 $fltPrice = $blnPercentage ? $objItem->getTotalPrice() / 100 * $fltDiscount : $objRule->discount;
                 $fltPrice = $fltPrice > 0 ? floor($fltPrice * 100) / 100 : ceil($fltPrice * 100) / 100;
                 $objSurcharge->total_price += $fltPrice;
                 $objSurcharge->setAmountForCollectionItem($fltPrice, $objItem);
                 break;
             case 'items':
                 $fltPrice = ($blnPercentage ? $objItem->getPrice() / 100 * $fltDiscount : $objRule->discount) * $objItem->quantity;
                 $fltPrice = $fltPrice > 0 ? floor($fltPrice * 100) / 100 : ceil($fltPrice * 100) / 100;
                 $objSurcharge->total_price += $fltPrice;
                 $objSurcharge->setAmountForCollectionItem($fltPrice, $objItem);
                 break;
             case 'subtotal':
                 $blnMatch = true;
                 $objSurcharge->total_price += $objItem->getTotalPrice();
                 if ($objRule->tax_class == -1) {
                     if ($blnPercentage) {
                         $fltPrice = $objItem->getTotalPrice() / 100 * $fltDiscount;
                         $objSurcharge->setAmountForCollectionItem($fltPrice, $objItem);
                     } else {
                         $arrSubtract[] = $objItem;
                         $fltTotal += (double) $objItem->getTaxFreeTotalPrice();
                     }
                 }
                 break;
         }
     }
     if ($objRule->applyTo == 'subtotal' && $blnMatch) {
         // discount total! not related to tax subtraction
         $fltPrice = $blnPercentage ? $objSurcharge->total_price / 100 * $fltDiscount : $objRule->discount;
         $objSurcharge->total_price = $fltPrice > 0 ? floor(round($fltPrice * 100, 4)) / 100 : ceil(round($fltPrice * 100, 4)) / 100;
         $objSurcharge->before_tax = $objRule->tax_class != 0 ? true : false;
         $objSurcharge->tax_class = $objRule->tax_class > 0 ? $objRule->tax_class : 0;
         // If fixed price discount with splitted taxes, calculate total amount of discount per taxed product
         if ($objRule->tax_class == -1 && !$blnPercentage) {
             foreach ($arrSubtract as $objItem) {
                 $fltPrice = $objRule->discount / 100 * (100 / $fltTotal * $objItem->getTaxFreeTotalPrice());
                 $objSurcharge->setAmountForCollectionItem($fltPrice, $objItem);
             }
         }
     }
     return $objSurcharge->total_price == 0 ? null : $objSurcharge;
 }
 /**
  * Create or add taxes for each collection item
  *
  * @param Tax[]                        $arrTaxes
  * @param IsotopeProductCollection     $objCollection
  * @param ProductCollectionSurcharge[] $arrSurcharges
  * @param Address[]                    $arrAddresses
  */
 private static function addTaxesForItems(array &$arrTaxes, IsotopeProductCollection $objCollection, array $arrSurcharges, array $arrAddresses)
 {
     foreach ($objCollection->getItems() as $objItem) {
         // This should never happen, but we can't calculate it
         if (!$objItem->hasProduct()) {
             continue;
         }
         $objProduct = $objItem->getProduct();
         /** @var \Isotope\Model\TaxClass $objTaxClass */
         $objTaxClass = $objProduct->getPrice() ? $objProduct->getPrice()->getRelated('tax_class') : null;
         // Skip products without tax class
         if (null === $objTaxClass) {
             continue;
         }
         $arrTaxIds = array();
         $fltPrice = $objItem->getTotalPrice();
         /** @var \Isotope\Model\ProductCollectionSurcharge $objSurcharge */
         foreach ($arrSurcharges as $objSurcharge) {
             $fltPrice += $objSurcharge->getAmountForCollectionItem($objItem);
         }
         /** @var \Isotope\Model\TaxRate $objIncludes */
         if (($objIncludes = $objTaxClass->getRelated('includes')) !== null) {
             if ($objIncludes->isApplicable($fltPrice, $arrAddresses)) {
                 $addToTotal = static::getTaxAddState(false);
                 $total = $addToTotal ? $objIncludes->calculateAmountAddedToPrice($fltPrice) : $objIncludes->calculateAmountIncludedInPrice($fltPrice);
                 $arrTaxIds[] = static::addTax($arrTaxes, $objTaxClass->id . '_' . $objIncludes->id, $objTaxClass->getLabel() ?: $objIncludes->getLabel(), $objIncludes->getAmount(), $objIncludes->isPercentage(), $total, $objTaxClass->applyRoundingIncrement, $addToTotal, false);
             }
         }
         if (($objRates = $objTaxClass->getRelated('rates')) !== null) {
             /** @var \Isotope\Model\TaxRate $objTaxRate */
             foreach ($objRates as $objTaxRate) {
                 if ($objTaxRate->isApplicable($fltPrice, $arrAddresses)) {
                     $addToTotal = static::getTaxAddState(true);
                     $total = $addToTotal ? $objTaxRate->calculateAmountAddedToPrice($fltPrice) : $objTaxRate->calculateAmountIncludedInPrice($fltPrice);
                     $arrTaxIds[] = static::addTax($arrTaxes, $objTaxRate->id, $objTaxRate->getLabel(), $objTaxRate->getAmount(), $objTaxRate->isPercentage(), $total, $objTaxClass->applyRoundingIncrement, $addToTotal, false);
                     if ($objTaxRate->stop) {
                         break;
                     }
                 }
             }
         }
         $strTaxId = implode(',', $arrTaxIds);
         if ($objItem->tax_id != $strTaxId) {
             $objCollection->updateItem($objItem, array('tax_id' => $strTaxId));
         }
         foreach ($arrSurcharges as $objSurcharge) {
             if ($objSurcharge->getAmountForCollectionItem($objItem) > 0) {
                 foreach ($arrTaxIds as $taxId) {
                     $objSurcharge->addTaxNumber($taxId);
                 }
             }
         }
     }
 }
Пример #4
0
 /**
  * Copy product collection items from another collection to this one (e.g. Cart to Order)
  * @param   IsotopeProductCollection
  * @return  array
  */
 public function copyItemsFrom(IsotopeProductCollection $objSource)
 {
     $this->ensureNotLocked();
     $this->updateDatabase();
     // Make sure database table has the latest prices
     $objSource->updateDatabase();
     $time = time();
     $arrIds = array();
     $arrOldItems = $objSource->getItems();
     foreach ($arrOldItems as $objOldItem) {
         // !HOOK: additional functionality when copying product to collection
         if (isset($GLOBALS['ISO_HOOKS']['copyCollectionItem']) && is_array($GLOBALS['ISO_HOOKS']['copyCollectionItem'])) {
             foreach ($GLOBALS['ISO_HOOKS']['copyCollectionItem'] as $callback) {
                 $objCallback = \System::importStatic($callback[0]);
                 if ($objCallback->{$callback}[1]($objOldItem, $objSource, $this) === false) {
                     continue;
                 }
             }
         }
         if ($objOldItem->hasProduct() && $this->hasProduct($objOldItem->getProduct())) {
             $objNewItem = $this->getItemForProduct($objOldItem->getProduct());
             $objNewItem->increaseQuantityBy($objOldItem->quantity);
         } else {
             $objNewItem = clone $objOldItem;
             $objNewItem->pid = $this->id;
             $objNewItem->tstamp = $time;
             $objNewItem->save();
         }
         $arrIds[$objOldItem->id] = $objNewItem->id;
     }
     if (!empty($arrIds)) {
         $this->tstamp = $time;
     }
     // !HOOK: additional functionality when adding product to collection
     if (isset($GLOBALS['ISO_HOOKS']['copiedCollectionItems']) && is_array($GLOBALS['ISO_HOOKS']['copiedCollectionItems'])) {
         foreach ($GLOBALS['ISO_HOOKS']['copiedCollectionItems'] as $callback) {
             $objCallback = \System::importStatic($callback[0]);
             $objCallback->{$callback}[1]($objSource, $this, $arrIds);
         }
     }
     // Empty cache
     $this->arrItems = null;
     $this->arrCache = null;
     return $arrIds;
 }
Пример #5
0
 /**
  * Create ProductCollectionDownload for all product downloads in the given collection
  *
  * @param IsotopeProductCollection $objCollection
  *
  * @return static[]
  */
 public static function createForProductsInCollection(IsotopeProductCollection $objCollection)
 {
     $arrDownloads = array();
     $t = Download::getTable();
     $time = $objCollection->locked ?: ($objCollection->tstamp ?: time());
     foreach ($objCollection->getItems() as $objItem) {
         if ($objItem->hasProduct()) {
             $objDownloads = Download::findBy(array("({$t}.pid=? OR {$t}.pid=?)", "{$t}.published='1'"), array($objItem->getProduct()->id, $objItem->getProduct()->pid));
             if (null !== $objDownloads) {
                 /** @var Download $objDownload */
                 foreach ($objDownloads as $objDownload) {
                     $objItemDownload = new static();
                     $objItemDownload->pid = $objItem->id;
                     $objItemDownload->tstamp = $time;
                     $objItemDownload->download_id = $objDownload->id;
                     if ($objDownload->downloads_allowed > 0) {
                         $objItemDownload->downloads_remaining = $objDownload->downloads_allowed * $objItem->quantity;
                     }
                     $expires = $objDownload->getExpirationTimestamp($time);
                     if (null !== $expires) {
                         $objItemDownload->expires = $expires;
                     }
                     $arrDownloads[] = $objItemDownload;
                 }
             }
         }
     }
     return $arrDownloads;
 }
 /**
  * Generate XML data for collection items
  *
  * @param IsotopeProductCollection $objCollection
  *
  * @return string
  */
 private function getCollectionItemsAsXML(IsotopeProductCollection $objCollection)
 {
     $xml = new \DOMDocument();
     $articleData = $xml->createElement('article_data');
     foreach ($objCollection->getItems() as $objItem) {
         $article = $xml->createElement('article');
         $id = $xml->createAttribute('articleid');
         $id->value = $objItem->getSku();
         $article->appendChild($id);
         $quantity = $xml->createAttribute('articlequantity');
         $quantity->value = $objItem->quantity;
         $article->appendChild($quantity);
         $name = $xml->createAttribute('articlename');
         $name->value = $objItem->getName();
         $article->appendChild($name);
         $price = $xml->createAttribute('articleprice');
         $price->value = round($objItem->getTaxFreePrice() * 100);
         $article->appendChild($price);
         $grossPrice = $xml->createAttribute('articlepricegross');
         $grossPrice->value = round($objItem->getPrice() * 100);
         $article->appendChild($grossPrice);
         $articleData->appendChild($article);
     }
     foreach ($objCollection->getSurcharges() as $objSurcharge) {
         if ($objSurcharge->total_price > 0 && !$objSurcharge instanceof Shipping && !$objSurcharge instanceof Tax) {
             $article = $xml->createElement('article');
             // Quantity is always 1 because we only have a total price
             $quantity = $xml->createAttribute('articlequantity');
             $quantity->value = 1;
             $article->appendChild($quantity);
             $name = $xml->createAttribute('articlename');
             $name->value = $objSurcharge->label;
             $article->appendChild($name);
             $price = $xml->createAttribute('articleprice');
             $price->value = round($objSurcharge->tax_free_total_price * 100);
             $article->appendChild($price);
             $grossPrice = $xml->createAttribute('articlepricegross');
             $grossPrice->value = round($objSurcharge->total_price * 100);
             $article->appendChild($grossPrice);
             $articleData->appendChild($article);
         }
     }
     $xml->appendChild($articleData);
     return $xml->saveXML($xml->documentElement);
 }
Пример #7
0
 /**
  * Build a Hash string based on the shipping address
  * @param IsotopeProductCollection
  * @return string
  */
 protected static function makeHash(IsotopeProductCollection $objCollection, $arrExtras = array())
 {
     $strBase = get_called_class();
     $strBase .= !empty($arrExtras) ? implode(',', $arrExtras) : '';
     $objShippingAddress = $objCollection->getShippingAddress();
     $strBase .= $objShippingAddress->street_1;
     $strBase .= $objShippingAddress->city;
     $strBase .= $objShippingAddress->subdivision;
     $strBase .= $objShippingAddress->postal;
     // Hash the cart too
     foreach ($objCollection->getItems() as $item) {
         $strBase .= $item->quantity;
         $strBase .= $item->id;
         $strBase .= implode(',', $item->getOptions());
     }
     return md5($strBase);
 }
Пример #8
0
 /**
  * Split tax amount amongst collection products
  * @param   IsotopeProductCollection
  * @param   \Model
  * @param   bool
  */
 public function applySplittedTax(IsotopeProductCollection $objCollection, $objSource)
 {
     $this->tax_class = 0;
     $this->before_tax = true;
     $fltTotal = 0;
     if (!$objSource->isPercentage()) {
         $fltTotal = $objCollection->getTaxFreeSubtotal();
         if ($fltTotal == 0) {
             return;
         }
     }
     foreach ($objCollection->getItems() as $objItem) {
         if ($objSource->isPercentage()) {
             $fltProductPrice = $objItem->getTotalPrice() / 100 * $objSource->getPercentage();
         } else {
             $fltProductPrice = $this->total_price / 100 * (100 / $fltTotal * $objItem->getTaxFreeTotalPrice());
         }
         $fltProductPrice = $fltProductPrice > 0 ? floor($fltProductPrice * 100) / 100 : ceil($fltProductPrice * 100) / 100;
         $this->setAmountForCollectionItem($fltProductPrice, $objItem);
     }
 }