/** * Fill the object's arrProducts array * @param array|null * @return array */ protected function findProducts($arrCacheIds = null) { $t = Product::getTable(); $arrColumns = array(); $arrCategories = $this->findCategories(); $arrProductIds = \Database::getInstance()->query("SELECT pid FROM " . ProductCategory::getTable() . " WHERE page_id IN (" . implode(',', $arrCategories) . ")")->fetchEach('pid'); $arrTypes = \Database::getInstance()->query("SELECT id FROM " . ProductType::getTable() . " WHERE variants='1'")->fetchEach('id'); if (empty($arrProductIds)) { return array(); } list($arrFilters, $arrSorting, $strWhere, $arrValues) = $this->getFiltersAndSorting(); if (!is_array($arrValues)) { $arrValues = array(); } $arrColumns[] = "(\n ({$t}.id IN (" . implode(',', $arrProductIds) . ") AND {$t}.type NOT IN (" . implode(',', $arrTypes) . "))\n OR {$t}.pid IN (" . implode(',', $arrProductIds) . ")\n )"; if (!empty($arrCacheIds) && is_array($arrCacheIds)) { $arrColumns[] = Product::getTable() . ".id IN (" . implode(',', $arrCacheIds) . ")"; } // Apply new/old product filter if ($this->iso_newFilter == 'show_new') { $arrColumns[] = Product::getTable() . ".dateAdded>=" . Isotope::getConfig()->getNewProductLimit(); } elseif ($this->iso_newFilter == 'show_old') { $arrColumns[] = Product::getTable() . ".dateAdded<" . Isotope::getConfig()->getNewProductLimit(); } if ($this->iso_list_where != '') { $arrColumns[] = Haste::getInstance()->call('replaceInsertTags', $this->iso_list_where); } if ($strWhere != '') { $arrColumns[] = $strWhere; } $objProducts = Product::findAvailableBy($arrColumns, $arrValues, array('order' => 'c.sorting', 'filters' => $arrFilters, 'sorting' => $arrSorting)); return null === $objProducts ? array() : $objProducts->getModels(); }
/** * Models */ $GLOBALS['TL_MODELS'][\Isotope\Model\Address::getTable()] = 'Isotope\\Model\\Address'; $GLOBALS['TL_MODELS'][\Isotope\Model\Attribute::getTable()] = 'Isotope\\Model\\Attribute'; $GLOBALS['TL_MODELS'][\Isotope\Model\BasePrice::getTable()] = 'Isotope\\Model\\BasePrice'; $GLOBALS['TL_MODELS'][\Isotope\Model\Config::getTable()] = 'Isotope\\Model\\Config'; $GLOBALS['TL_MODELS'][\Isotope\Model\Document::getTable()] = 'Isotope\\Model\\Document'; $GLOBALS['TL_MODELS'][\Isotope\Model\Download::getTable()] = 'Isotope\\Model\\Download'; $GLOBALS['TL_MODELS'][\Isotope\Model\Gallery::getTable()] = 'Isotope\\Model\\Gallery'; $GLOBALS['TL_MODELS'][\Isotope\Model\Group::getTable()] = 'Isotope\\Model\\Group'; $GLOBALS['TL_MODELS'][\Isotope\Model\Label::getTable()] = 'Isotope\\Model\\Label'; $GLOBALS['TL_MODELS'][\Isotope\Model\OrderStatus::getTable()] = 'Isotope\\Model\\OrderStatus'; $GLOBALS['TL_MODELS'][\Isotope\Model\Payment::getTable()] = 'Isotope\\Model\\Payment'; $GLOBALS['TL_MODELS'][\Isotope\Model\Product::getTable()] = 'Isotope\\Model\\Product'; $GLOBALS['TL_MODELS'][\Isotope\Model\ProductCategory::getTable()] = 'Isotope\\Model\\ProductCategory'; $GLOBALS['TL_MODELS'][\Isotope\Model\ProductCollection::getTable()] = 'Isotope\\Model\\ProductCollection'; $GLOBALS['TL_MODELS'][\Isotope\Model\ProductCollectionDownload::getTable()] = 'Isotope\\Model\\ProductCollectionDownload'; $GLOBALS['TL_MODELS'][\Isotope\Model\ProductCollectionItem::getTable()] = 'Isotope\\Model\\ProductCollectionItem'; $GLOBALS['TL_MODELS'][\Isotope\Model\ProductCollectionSurcharge::getTable()] = 'Isotope\\Model\\ProductCollectionSurcharge'; $GLOBALS['TL_MODELS'][\Isotope\Model\ProductPrice::getTable()] = 'Isotope\\Model\\ProductPrice'; $GLOBALS['TL_MODELS'][\Isotope\Model\ProductCache::getTable()] = 'Isotope\\Model\\ProductCache'; $GLOBALS['TL_MODELS'][\Isotope\Model\ProductType::getTable()] = 'Isotope\\Model\\ProductType'; $GLOBALS['TL_MODELS'][\Isotope\Model\RelatedCategory::getTable()] = 'Isotope\\Model\\RelatedCategory'; $GLOBALS['TL_MODELS'][\Isotope\Model\RelatedProduct::getTable()] = 'Isotope\\Model\\RelatedProduct'; $GLOBALS['TL_MODELS'][\Isotope\Model\RequestCache::getTable()] = 'Isotope\\Model\\RequestCache'; $GLOBALS['TL_MODELS'][\Isotope\Model\Shipping::getTable()] = 'Isotope\\Model\\Shipping'; $GLOBALS['TL_MODELS'][\Isotope\Model\TaxClass::getTable()] = 'Isotope\\Model\\TaxClass'; $GLOBALS['TL_MODELS'][\Isotope\Model\TaxRate::getTable()] = 'Isotope\\Model\\TaxRate'; /** * Checkout steps
if (($objPage = \PageModel::findWithDetails($dc->id)) !== null) { $GLOBALS['TL_DCA']['tl_page']['fields']['iso_readerJumpTo']['rootNodes'] = array($objPage->rootId); } } }; /** * Extend tl_page palettes */ $GLOBALS['TL_DCA']['tl_page']['palettes']['root'] = str_replace(';{publish_legend}', ';{isotope_legend},iso_config,iso_store_id;{publish_legend}', $GLOBALS['TL_DCA']['tl_page']['palettes']['root']); $GLOBALS['TL_DCA']['tl_page']['palettes']['regular'] = str_replace(';{publish_legend}', ';{isotope_legend},iso_setReaderJumpTo;{publish_legend}', $GLOBALS['TL_DCA']['tl_page']['palettes']['regular']); /** * Add a selector to tl_page */ $GLOBALS['TL_DCA']['tl_page']['palettes']['__selector__'][] = 'iso_setReaderJumpTo'; /** * Add subpalettes to tl_page */ $GLOBALS['TL_DCA']['tl_page']['subpalettes']['iso_setReaderJumpTo'] = 'iso_readerJumpTo'; /** * Add fields to tl_page */ $GLOBALS['TL_DCA']['tl_page']['fields']['iso_config'] = array('label' => &$GLOBALS['TL_LANG']['tl_page']['iso_config'], 'exclude' => true, 'inputType' => 'select', 'foreignKey' => \Isotope\Model\Config::getTable() . '.name', 'eval' => array('includeBlankOption' => true, 'tl_class' => 'w50'), 'sql' => "int(10) unsigned NOT NULL default '0'", 'relation' => array('type' => 'hasOne', 'load' => 'lazy')); $GLOBALS['TL_DCA']['tl_page']['fields']['iso_store_id'] = array('label' => &$GLOBALS['TL_LANG']['tl_page']['iso_store_id'], 'exclude' => true, 'inputType' => 'text', 'eval' => array('mandatory' => true, 'rgxp' => 'digit', 'nospace' => true, 'maxlength' => 2, 'tl_class' => 'w50'), 'sql' => "int(2) unsigned NOT NULL default '0'"); $GLOBALS['TL_DCA']['tl_page']['fields']['iso_setReaderJumpTo'] = array('label' => &$GLOBALS['TL_LANG']['tl_page']['iso_setReaderJumpTo'], 'exclude' => true, 'inputType' => 'checkbox', 'eval' => array('submitOnChange' => true, 'tl_class' => 'clr'), 'sql' => "char(1) NOT NULL default ''"); $GLOBALS['TL_DCA']['tl_page']['fields']['iso_readerJumpTo'] = array('label' => &$GLOBALS['TL_LANG']['tl_page']['iso_readerJumpTo'], 'exclude' => true, 'inputType' => 'pageTree', 'foreignKey' => 'tl_page.title', 'explanation' => 'isoReaderJumpTo', 'eval' => array('fieldType' => 'radio', 'mandatory' => true, 'helpwizard' => true), 'sql' => "int(10) unsigned NOT NULL default '0'", 'relation' => array('type' => 'hasOne', 'load' => 'lazy')); /** * Disable header edit button */ if ($_GET['table'] == \Isotope\Model\ProductCategory::getTable()) { $GLOBALS['TL_DCA']['tl_page']['config']['notEditable'] = true; }
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; }
/** * Save page ids to product category table. This allows to retrieve all products associated to a page. * * @param mixed $varValue * @param \DataContainer $dc * * @return mixed */ public function save($varValue, \DataContainer $dc) { $arrIds = deserialize($varValue); $table = ProductCategory::getTable(); if (is_array($arrIds) && !empty($arrIds)) { $time = time(); if (\Database::getInstance()->query("DELETE FROM {$table} WHERE pid={$dc->id} AND page_id NOT IN (" . implode(',', $arrIds) . ")")->affectedRows > 0) { $dc->createNewVersion = true; } $objPages = \Database::getInstance()->execute("SELECT page_id FROM {$table} WHERE pid={$dc->id}"); $arrIds = array_diff($arrIds, $objPages->fetchEach('page_id')); if (!empty($arrIds)) { foreach ($arrIds as $id) { $sorting = (int) \Database::getInstance()->execute("SELECT MAX(sorting) AS sorting FROM {$table} WHERE page_id={$id}")->sorting + 128; \Database::getInstance()->query("INSERT INTO {$table} (pid,tstamp,page_id,sorting) VALUES ({$dc->id}, {$time}, {$id}, {$sorting})"); } $dc->createNewVersion = true; } } else { if (\Database::getInstance()->query("DELETE FROM {$table} WHERE pid={$dc->id}")->affectedRows > 0) { $dc->createNewVersion = true; } } return ''; }
<?php /** * Isotope eCommerce for Contao Open Source CMS * * Copyright (C) 2009-2014 terminal42 gmbh & Isotope eCommerce Workgroup * * @package Isotope * @link http://isotopeecommerce.org * @license http://opensource.org/licenses/lgpl-3.0.html */ \System::loadLanguageFile(\Isotope\Model\ProductType::getTable()); /** * Table tl_iso_product */ $GLOBALS['TL_DCA']['tl_iso_product'] = array('config' => array('label' => &$GLOBALS['TL_LANG']['MOD']['iso_products'][0], 'dataContainer' => 'ProductData', 'enableVersioning' => true, 'switchToEdit' => true, 'ctable' => array(\Isotope\Model\Download::getTable(), \Isotope\Model\ProductCategory::getTable(), \Isotope\Model\ProductPrice::getTable(), \Isotope\Model\AttributeOption::getTable()), 'onload_callback' => array(array('Isotope\\Backend\\Product\\DcaManager', 'load'), array('Isotope\\Backend\\Product\\Permission', 'check'), array('Isotope\\Backend\\Product\\Panel', 'applyAdvancedFilters'), array('Isotope\\Backend\\Product\\XmlSitemap', 'generate')), 'oncreate_callback' => array(array('Isotope\\Backend\\Product\\DcaManager', 'updateNewRecord')), 'oncopy_callback' => array(array('Isotope\\Backend\\Product\\Category', 'updateSorting'), array('Isotope\\Backend\\Product\\DcaManager', 'updateDateAdded')), 'onsubmit_callback' => array(array('Isotope\\Backend', 'truncateProductCache'), array('Isotope\\Backend\\Product\\XmlSitemap', 'scheduleUpdate')), 'onversion_callback' => array(array('Isotope\\Backend\\Product\\Category', 'createVersion')), 'onrestore_callback' => array(array('Isotope\\Backend\\Product\\Category', 'restoreVersion')), 'sql' => array('keys' => array('id' => 'primary', 'gid' => 'index', 'pid,language' => 'index', 'language,published,start,stop,pid' => 'index', 'start' => 'index'))), 'select' => array('buttons_callback' => array(array('Isotope\\Backend\\Product\\Button', 'forSelect'))), 'list' => array('sorting' => array('mode' => 2, 'fields' => array('name'), 'headerFields' => array('name', 'sku', 'price', 'published'), 'flag' => 1, 'panelLayout' => 'iso_buttons,iso_filter;filter;sort,iso_sorting,search,limit', 'icon' => 'system/modules/isotope/assets/images/store-open.png', 'paste_button_callback' => array('Isotope\\Backend\\Product\\PasteButton', 'generate'), 'panel_callback' => array('iso_buttons' => array('Isotope\\Backend\\Product\\Panel', 'generateFilterButtons'), 'iso_filter' => array('Isotope\\Backend\\Product\\Panel', 'generateAdvancedFilters'), 'iso_sorting' => array('Isotope\\Backend\\Product\\Panel', 'generateSortingIcon'))), 'label' => array('fields' => array('images', 'name', 'sku', 'price'), 'showColumns' => true, 'label_callback' => array('Isotope\\Backend\\Product\\Label', 'generate')), 'global_operations' => array('generate' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['generate'], 'href' => 'key=generate', 'icon' => 'new.gif'), 'groups' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['product_groups'], 'href' => 'table=' . \Isotope\Model\Group::getTable(), 'icon' => 'system/modules/isotope/assets/images/folders.png', 'attributes' => 'onclick="Backend.getScrollOffset();"', 'button_callback' => array('Isotope\\Backend\\Product\\Button', 'forGroups')), 'import' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['import'], 'href' => 'key=import', 'icon' => 'system/modules/isotope/assets/images/image--plus.png', 'attributes' => 'onclick="Backend.getScrollOffset();"'), 'all' => array('label' => &$GLOBALS['TL_LANG']['MSC']['all'], 'href' => 'act=select', 'class' => 'header_edit_all', 'attributes' => 'onclick="Backend.getScrollOffset();"')), 'operations' => array('edit' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['edit'], 'href' => 'act=edit', 'icon' => 'edit.gif'), 'copy' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['copy'], 'href' => 'act=copy&childs=1', 'icon' => 'copy.gif', 'button_callback' => array('Isotope\\Backend\\Product\\Button', 'forCopy')), 'cut' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['cut'], 'href' => 'act=cut', 'icon' => 'cut.gif', 'button_callback' => array('Isotope\\Backend\\Product\\Button', 'forCut')), 'delete' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['delete'], 'href' => 'act=delete', 'icon' => 'delete.gif', 'attributes' => 'onclick="if (!confirm(\'' . $GLOBALS['TL_LANG']['MSC']['deleteConfirm'] . '\')) return false; Backend.getScrollOffset();"', 'button_callback' => array('Isotope\\Backend\\Product\\Button', 'forDelete')), 'toggle' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['toggle'], 'icon' => 'visible.gif', 'attributes' => 'onclick="Backend.getScrollOffset(); return AjaxRequest.toggleVisibility(this, %s);"', 'button_callback' => array('Isotope\\Backend\\Product\\Button', 'forVisibilityToggle')), 'show' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['show'], 'href' => 'act=show', 'icon' => 'show.gif'), 'break' => array('button_callback' => function () { return '<br>'; }), 'variants' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['variants'], 'href' => '', 'icon' => 'system/modules/isotope/assets/images/table--pencil.png', 'button_callback' => array('Isotope\\Backend\\Product\\Button', 'forVariants')), 'related' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['related'], 'href' => 'table=' . \Isotope\Model\RelatedProduct::getTable(), 'icon' => 'system/modules/isotope/assets/images/sitemap.png', 'button_callback' => array('Isotope\\Backend\\Product\\Button', 'forRelated')), 'downloads' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['downloads'], 'href' => 'table=' . \Isotope\Model\Download::getTable(), 'icon' => 'system/modules/isotope/assets/images/paper-clip.png', 'button_callback' => array('Isotope\\Backend\\Product\\Button', 'forDownloads')), 'group' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['group'], 'href' => 'act=cut', 'icon' => 'system/modules/isotope/assets/images/folder-network.png', 'button_callback' => array('Isotope\\Backend\\Product\\Button', 'forGroup')))), 'palettes' => array('__selector__' => array('type', 'protected'), 'default' => '{general_legend},type'), 'subpalettes' => array('protected' => 'groups'), 'fields' => array('id' => array('attributes' => array('systemColumn' => true), 'sql' => "int(10) unsigned NOT NULL auto_increment"), 'pid' => array('eval' => array('submitOnChange' => true), 'attributes' => array('systemColumn' => true), 'sql' => "int(10) unsigned NOT NULL default '0'"), 'gid' => array('foreignKey' => \Isotope\Model\Group::getTable() . '.name', 'eval' => array('doNotShow' => true), 'attributes' => array('systemColumn' => true, 'inherit' => true), 'sql' => "int(10) unsigned NOT NULL default '0'", 'relation' => array('type' => 'hasOne', 'load' => 'lazy')), 'tstamp' => array('attributes' => array('systemColumn' => true), 'sql' => "int(10) unsigned NOT NULL default '0'"), 'language' => array('eval' => array('doNotShow' => true), 'attributes' => array('systemColumn' => true, 'inherit' => true), 'sql' => "varchar(5) NOT NULL default ''"), 'dateAdded' => array('label' => &$GLOBALS['TL_LANG']['MSC']['dateAdded'], 'eval' => array('rgxp' => 'datim', 'doNotCopy' => true), 'attributes' => array('fe_sorting' => true, 'systemColumn' => true), 'sql' => "int(10) unsigned NOT NULL default '0'"), 'type' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['type'], 'exclude' => true, 'filter' => true, 'inputType' => 'select', 'options_callback' => array('Isotope\\Backend\\ProductType\\Callback', 'getOptions'), 'foreignKey' => \Isotope\Model\ProductType::getTable() . '.name', 'eval' => array('mandatory' => true, 'submitOnChange' => true, 'includeBlankOption' => true, 'tl_class' => 'clr', 'helpwizard' => true), 'attributes' => array('legend' => 'general_legend', 'fixed' => true, 'inherit' => true, 'systemColumn' => true), 'sql' => "int(10) unsigned NOT NULL default '0'", 'relation' => array('type' => 'hasOne', 'load' => 'lazy'), 'explanation' => 'tl_iso_product.type'), 'pages' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['pages'], 'exclude' => true, 'inputType' => 'pageTree', 'foreignKey' => 'tl_page.title', 'eval' => array('doNotSaveEmpty' => true, 'multiple' => true, 'fieldType' => 'checkbox', 'orderField' => 'orderPages', 'tl_class' => 'clr hide_sort_hint'), 'relation' => array('type' => 'hasMany', 'load' => 'lazy'), 'attributes' => array('legend' => 'general_legend', 'fixed' => true, 'inherit' => true, 'systemColumn' => true), 'load_callback' => array(array('Isotope\\Backend\\Product\\Category', 'load')), 'save_callback' => array(array('Isotope\\Backend\\Product\\Category', 'save'))), 'orderPages' => array('eval' => array('doNotShow' => true), 'attributes' => array('systemColumn' => true, 'inherit' => true), 'sql' => "text NULL"), 'inherit' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['inherit'], 'exclude' => true, 'inputType' => 'inheritCheckbox', 'eval' => array('multiple' => true), 'attributes' => array('systemColumn' => true), 'sql' => "blob NULL"), 'alias' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['alias'], 'exclude' => true, 'search' => true, 'sorting' => true, 'inputType' => 'text', 'eval' => array('rgxp' => 'alnum', 'doNotCopy' => true, 'spaceToUnderscore' => true, 'maxlength' => 128, 'tl_class' => 'w50'), 'attributes' => array('legend' => 'general_legend', 'fixed' => true, 'inherit' => true), 'sql' => "varchar(128) NOT NULL default ''", 'save_callback' => array(array('Isotope\\Backend\\Product\\Alias', 'save'))), 'sku' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['sku'], 'exclude' => true, 'search' => true, 'sorting' => true, 'inputType' => 'text', 'eval' => array('mandatory' => true, 'maxlength' => 128, 'unique' => true, 'tl_class' => 'w50'), 'attributes' => array('legend' => 'general_legend', 'fe_sorting' => true, 'fe_search' => true), 'sql' => "varchar(128) NOT NULL default ''"), 'name' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['name'], 'exclude' => true, 'search' => true, 'sorting' => true, 'inputType' => 'text', 'eval' => array('mandatory' => true, 'tl_class' => 'clr long'), 'attributes' => array('legend' => 'general_legend', 'multilingual' => true, 'fixed' => true, 'fe_sorting' => true, 'fe_search' => true), 'sql' => "varchar(255) NOT NULL default ''"), 'teaser' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['teaser'], 'exclude' => true, 'search' => true, 'inputType' => 'textarea', 'eval' => array('style' => 'height:80px', 'tl_class' => 'clr'), 'attributes' => array('legend' => 'general_legend', 'multilingual' => true), 'sql' => "text NULL"), 'description' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['description'], 'exclude' => true, 'search' => true, 'inputType' => 'textarea', 'eval' => array('mandatory' => true, 'rte' => 'tinyMCE', 'tl_class' => 'clr'), 'attributes' => array('legend' => 'general_legend', 'multilingual' => true, 'fe_search' => true), 'sql' => "text NULL"), 'meta_title' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['meta_title'], 'exclude' => true, 'search' => true, 'inputType' => 'text', 'eval' => array('maxlength' => 255, 'tl_class' => 'clr long'), 'attributes' => array('legend' => 'meta_legend', 'multilingual' => true), 'sql' => "varchar(255) NOT NULL default ''"), 'meta_description' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['meta_description'], 'exclude' => true, 'search' => true, 'inputType' => 'textarea', 'eval' => array('style' => 'height:60px', 'tl_class' => 'clr'), 'attributes' => array('legend' => 'meta_legend', 'multilingual' => true), 'sql' => "text NULL"), 'meta_keywords' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['meta_keywords'], 'exclude' => true, 'search' => true, 'inputType' => 'textarea', 'eval' => array('style' => 'height:40px', 'tl_class' => 'clr'), 'attributes' => array('legend' => 'meta_legend', 'multilingual' => true), 'sql' => "text NULL"), 'price' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['price'], 'exclude' => true, 'inputType' => 'timePeriod', 'foreignKey' => \Isotope\Model\TaxClass::getTable() . '.name', 'eval' => array('mandatory' => true, 'maxlength' => 13, 'rgxp' => 'price', 'includeBlankOption' => true, 'blankOptionLabel' => &$GLOBALS['TL_LANG']['MSC']['taxFree'], 'doNotSaveEmpty' => true, 'tl_class' => 'w50'), 'attributes' => array('legend' => 'pricing_legend', 'fe_sorting' => true, 'dynamic' => true, 'systemColumn' => true, 'type' => '\\Isotope\\Model\\Attribute\\Price'), 'load_callback' => array(array('\\Isotope\\Backend\\Product\\Price', 'load')), 'save_callback' => array(array('\\Isotope\\Backend\\Product\\Price', 'save'))), 'prices' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['prices'], 'inputType' => 'dcaWizard', 'foreignTable' => \Isotope\Model\ProductPrice::getTable(), 'attributes' => array('systemColumn' => true), 'eval' => array('listCallback' => array('Isotope\\Backend\\ProductPrice\\Callback', 'generateWizardList'), 'applyButtonLabel' => &$GLOBALS['TL_LANG']['tl_iso_product']['prices']['apply_and_close'], 'tl_class' => 'clr')), 'price_tiers' => array('attributes' => array('type' => '\\Isotope\\Model\\Attribute\\PriceTiers'), 'tableformat' => array('min' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['price_tiers']['min'], 'format' => &$GLOBALS['TL_LANG']['tl_iso_product']['price_tiers']['min_format']), 'price' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['price_tiers']['price'], 'rgxp' => 'price'), 'tax_class' => array('doNotShow' => true))), 'baseprice' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['baseprice'], 'exclude' => true, 'inputType' => 'timePeriod', 'foreignKey' => 'tl_iso_baseprice.name', 'eval' => array('includeBlankOption' => true, 'tl_class' => 'w50'), 'attributes' => array('type' => '\\Isotope\\Model\\Attribute\\BasePrice', 'legend' => 'pricing_legend'), 'sql' => "varchar(255) NOT NULL default ''"), 'shipping_weight' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['shipping_weight'], 'exclude' => true, 'inputType' => 'timePeriod', 'default' => array('', 'kg'), 'options' => array('mg', 'g', 'kg', 't', 'ct', 'oz', 'lb', 'st', 'grain'), 'reference' => &$GLOBALS['TL_LANG']['WGT'], 'eval' => array('rgxp' => 'digit', 'tl_class' => 'w50', 'helpwizard' => true), 'attributes' => array('legend' => 'shipping_legend'), 'sql' => "varchar(255) NOT NULL default ''"), 'shipping_exempt' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['shipping_exempt'], 'exclude' => true, 'inputType' => 'checkbox', 'eval' => array('tl_class' => 'w50'), 'attributes' => array('legend' => 'shipping_legend', 'systemColumn' => true), 'sql' => "char(1) NOT NULL default ''"), 'images' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['images'], 'exclude' => true, 'inputType' => 'mediaManager', 'explanation' => 'mediaManager', 'eval' => array('extensions' => 'jpeg,jpg,png,gif', 'helpwizard' => true, 'tl_class' => 'clr'), 'attributes' => array('legend' => 'media_legend', 'fixed' => true, 'multilingual' => true, 'dynamic' => true, 'systemColumn' => true, 'fetch_fallback' => true), 'sql' => "blob NULL"), 'protected' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['protected'], 'exclude' => true, 'filter' => true, 'inputType' => 'checkbox', 'eval' => array('submitOnChange' => true, 'tl_class' => 'clr'), 'attributes' => array('legend' => 'expert_legend', 'systemColumn' => true), 'sql' => "char(1) NOT NULL default ''"), 'groups' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['groups'], 'exclude' => true, 'filter' => true, 'inputType' => 'checkbox', 'foreignKey' => 'tl_member_group.name', 'eval' => array('mandatory' => true, 'multiple' => true, 'systemColumn' => true), 'sql' => "blob NULL", 'relation' => array('type' => 'hasMany', 'load' => 'lazy')), 'guests' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['guests'], 'exclude' => true, 'inputType' => 'checkbox', 'eval' => array('tl_class' => 'w50'), 'attributes' => array('legend' => 'expert_legend', 'systemColumn' => true), 'sql' => "char(1) NOT NULL default ''"), 'cssID' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['cssID'], 'exclude' => true, 'inputType' => 'text', 'eval' => array('multiple' => true, 'size' => 2, 'tl_class' => 'w50'), 'attributes' => array('legend' => 'expert_legend'), 'sql' => "varchar(255) NOT NULL default ''"), 'published' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['published'], 'exclude' => true, 'filter' => true, 'inputType' => 'checkbox', 'eval' => array('doNotCopy' => true, 'tl_class' => 'clr'), 'attributes' => array('legend' => 'publish_legend', 'fixed' => true, 'variant_fixed' => true, 'systemColumn' => true), 'sql' => "char(1) NOT NULL default ''", 'save_callback' => array(array('Isotope\\Backend', 'truncateProductCache'))), 'start' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['start'], 'exclude' => true, 'inputType' => 'text', 'eval' => array('rgxp' => 'date', 'datepicker' => true, 'tl_class' => 'w50 wizard'), 'attributes' => array('legend' => 'publish_legend', 'fixed' => true, 'variant_fixed' => true, 'systemColumn' => true), 'sql' => "varchar(10) NOT NULL default ''"), 'stop' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['stop'], 'exclude' => true, 'inputType' => 'text', 'eval' => array('rgxp' => 'date', 'datepicker' => true, 'tl_class' => 'w50 wizard'), 'attributes' => array('legend' => 'publish_legend', 'fixed' => true, 'variant_fixed' => true, 'systemColumn' => true), 'sql' => "varchar(10) NOT NULL default ''"), 'variantFields' => array('label' => &$GLOBALS['TL_LANG'][\Isotope\Model\ProductType::getTable()]['variant_attributes']), 'source' => array('label' => &$GLOBALS['TL_LANG']['tl_iso_product']['source'], 'eval' => array('mandatory' => true, 'required' => true, 'fieldType' => 'radio')))); /** * Adjust the data configuration array in variants view */ if (\Input::get('id')) { $GLOBALS['TL_LANG']['tl_iso_product']['new'] = $GLOBALS['TL_LANG']['tl_iso_product']['new_variant']; $GLOBALS['TL_DCA']['tl_iso_product']['config']['switchToEdit'] = false; unset($GLOBALS['TL_DCA']['tl_iso_product']['list']['global_operations']['import']); unset($GLOBALS['TL_DCA']['tl_iso_product']['list']['global_operations']['groups']); } else { unset($GLOBALS['TL_DCA']['tl_iso_product']['list']['global_operations']['generate']); }
/** * 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; }
/** * Return select statement to load product data including multilingual fields * @param array an array of columns * @return string */ protected static function buildFindQuery(array $arrOptions) { $objBase = new \DcaExtractor($arrOptions['table']); $arrJoins = array(); $arrFields = array($arrOptions['table'] . ".*", "IF(" . $arrOptions['table'] . ".pid>0, parent.type, " . $arrOptions['table'] . ".type) AS type", "'" . str_replace('-', '_', $GLOBALS['TL_LANGUAGE']) . "' AS language"); foreach (Attribute::getMultilingualFields() as $attribute) { $arrFields[] = "IFNULL(translation.{$attribute}, " . $arrOptions['table'] . ".{$attribute}) AS {$attribute}"; } foreach (Attribute::getFetchFallbackFields() as $attribute) { $arrFields[] = "{$arrOptions['table']}.{$attribute} AS {$attribute}_fallback"; } $arrFields[] = "c.sorting"; $arrJoins[] = " LEFT OUTER JOIN " . \Isotope\Model\ProductCategory::getTable() . " c ON {$arrOptions['table']}.id=c.pid"; $arrJoins[] = " LEFT OUTER JOIN " . $arrOptions['table'] . " translation ON " . $arrOptions['table'] . ".id=translation.pid AND translation.language='" . str_replace('-', '_', $GLOBALS['TL_LANGUAGE']) . "'"; $arrJoins[] = " LEFT OUTER JOIN " . $arrOptions['table'] . " parent ON " . $arrOptions['table'] . ".pid=parent.id"; if ($objBase->hasRelations()) { $intCount = 0; foreach ($objBase->getRelations() as $strKey => $arrConfig) { // Automatically join the single-relation records if ($arrConfig['load'] == 'eager' || $arrOptions['eager']) { if ($arrConfig['type'] == 'hasOne' || $arrConfig['type'] == 'belongsTo') { if (is_array($arrOptions['joinAliases']) && ($key = array_search($arrConfig['table'], $arrOptions['joinAliases'])) !== false) { $strJoinAlias = $key; unset($arrOptions['joinAliases'][$key]); } else { ++$intCount; $strJoinAlias = 'j' . $intCount; } $objRelated = new \DcaExtractor($arrConfig['table']); foreach (array_keys($objRelated->getFields()) as $strField) { $arrFields[] = $strJoinAlias . '.' . $strField . ' AS ' . $strKey . '__' . $strField; } $arrJoins[] = " LEFT JOIN " . $arrConfig['table'] . " {$strJoinAlias} ON " . $arrOptions['table'] . "." . $strKey . "={$strJoinAlias}.id"; } } } } // Generate the query $strQuery = "SELECT " . implode(', ', $arrFields) . " FROM " . $arrOptions['table'] . implode("", $arrJoins); // Where condition if (!is_array($arrOptions['column'])) { $arrOptions['column'] = array($arrOptions['table'] . '.' . $arrOptions['column'] . '=?'); } // The model must never find a language record $strQuery .= " WHERE {$arrOptions['table']}.language='' AND " . implode(" AND ", $arrOptions['column']); // Group by if ($arrOptions['group'] !== null) { $strQuery .= " GROUP BY " . $arrOptions['group']; } // Order by if ($arrOptions['order'] !== null) { $strQuery .= " ORDER BY " . $arrOptions['order']; } return $strQuery; }
/** * Build a query based on the given options to count the number of products. * * @param array $arrOptions The options array * * @return string */ protected static function buildCountQuery(array $arrOptions) { $hasTranslations = static::countTranslatedProducts() > 0; $hasVariants = ProductType::countByVariants() > 0; $arrJoins = array(); $arrFields = array($arrOptions['table'] . ".*", "'" . str_replace('-', '_', $GLOBALS['TL_LANGUAGE']) . "' AS language"); if ($hasVariants) { $arrFields[] = sprintf("IF(%s.pid>0, parent.type, %s.type) AS type", $arrOptions['table'], $arrOptions['table']); } if ($hasTranslations) { foreach (Attribute::getMultilingualFields() as $attribute) { $arrFields[] = "IFNULL(translation.{$attribute}, " . $arrOptions['table'] . ".{$attribute}) AS {$attribute}"; } } $arrJoins[] = sprintf(" LEFT OUTER JOIN %s c ON %s.id=c.pid", ProductCategory::getTable(), $arrOptions['table']); if ($hasTranslations) { $arrJoins[] = sprintf(" LEFT OUTER JOIN %s translation ON %s.id=translation.pid AND translation.language='%s'", $arrOptions['table'], $arrOptions['table'], str_replace('-', '_', $GLOBALS['TL_LANGUAGE'])); } if ($hasVariants) { $arrJoins[] = sprintf(" LEFT OUTER JOIN %s parent ON %s.pid=parent.id", $arrOptions['table'], $arrOptions['table']); } // Generate the query $strWhere = ''; $strQuery = "\n SELECT\n " . implode(', ', $arrFields) . ",\n COUNT(DISTINCT " . $arrOptions['table'] . ".id) AS count\n FROM " . $arrOptions['table'] . implode("", $arrJoins); // Where condition if (!empty($arrOptions['column'])) { if (!is_array($arrOptions['column'])) { $arrOptions['column'] = array($arrOptions['table'] . '.' . $arrOptions['column'] . '=?'); } $strWhere = " AND " . implode(" AND ", $arrOptions['column']); } // The model must never find a language record $strQuery .= " WHERE {$arrOptions['table']}.language=''" . $strWhere; // Group by if ($arrOptions['group'] !== null) { $strQuery .= " GROUP BY " . $arrOptions['group']; } return $strQuery; }
/** * Load the products for the provided categories if they haven't been already * @param array * @return array */ public static function getProductsForCategories(&$arrCategories) { $strHash = md5(implode(',', $arrCategories)); if (!\Cache::has('category-products-' . $strHash)) { $c = ProductCategory::getTable(); if (!is_array($arrCategories) || empty($arrCategories)) { $arrCategories = array(0); } $strQuery = "SELECT pid AS `product_id` FROM {$c} WHERE {$c}.page_id IN (" . implode(',', $arrCategories) . ")"; $arrIds = \Database::getInstance()->prepare($strQuery)->executeUncached()->fetchEach('product_id'); \Cache::set('category-products-' . $strHash, empty($arrIds) ? array(0) : $arrIds); } return \Cache::get('category-products-' . $strHash); }
/** * Generate a filter form */ protected function generateFilters() { $this->Template->hasFilters = false; if (is_array($this->iso_filterFields) && count($this->iso_filterFields)) { $time = time(); $arrFilters = array(); $arrInput = \Input::post('filter'); $arrCategories = $this->findCategories(); foreach ($this->iso_filterFields as $strField) { $arrValues = array(); $objValues = \Database::getInstance()->execute("\n SELECT DISTINCT p1.{$strField} FROM tl_iso_product p1\n LEFT OUTER JOIN tl_iso_product p2 ON p1.pid=p2.id\n WHERE\n p1.language=''\n " . (BE_USER_LOGGED_IN === true ? '' : "AND p1.published='1' AND (p1.start='' OR p1.start<{$time}) AND (p1.stop='' OR p1.stop>{$time}) ") . "\n AND (\n p1.id IN (\n SELECT pid FROM " . \Isotope\Model\ProductCategory::getTable() . " WHERE page_id IN (" . implode(',', $arrCategories) . ")\n )\n OR p1.pid IN (\n SELECT pid FROM " . \Isotope\Model\ProductCategory::getTable() . " WHERE page_id IN (" . implode(',', $arrCategories) . ")\n )\n )\n " . (BE_USER_LOGGED_IN === true ? '' : " AND (p1.pid=0 OR (p2.published='1' AND (p2.start='' OR p2.start<{$time}) AND (p2.stop='' OR p2.stop>{$time})))") . "\n " . ($this->iso_list_where == '' ? '' : " AND " . Haste::getInstance()->call('replaceInsertTags', $this->iso_list_where))); while ($objValues->next()) { $arrValues[] = deserialize($objValues->{$strField}, false); } if ($this->blnUpdateCache && in_array($arrInput[$strField], $arrValues)) { Isotope::getRequestCache()->setFilterForModule($strField, Filter::attribute($strField)->isEqualTo($arrInput[$strField]), $this->id); } elseif ($this->blnUpdateCache && $arrInput[$strField] == '') { Isotope::getRequestCache()->removeFilterForModule($strField, $this->id); } elseif (($objFilter = Isotope::getRequestCache()->getFilterForModule($strField, $this->id)) !== null && $objFilter->valueNotIn($arrValues)) { // Request cache contains wrong value, delete it! $this->blnUpdateCache = true; Isotope::getRequestCache()->removeFilterForModule($strField, $this->id); RequestCache::deleteById(\Input::get('isorc')); } elseif (!$this->blnUpdateCache) { // Only generate options if we do not reload anyway if (empty($arrValues)) { continue; } $arrData = $GLOBALS['TL_DCA']['tl_iso_product']['fields'][$strField]; if (is_array($GLOBALS['ISO_ATTR'][$arrData['inputType']]['callback']) && !empty($GLOBALS['ISO_ATTR'][$arrData['inputType']]['callback'])) { foreach ($GLOBALS['ISO_ATTR'][$arrData['inputType']]['callback'] as $callback) { $objCallback = \System::importStatic($callback[0]); $arrData = $objCallback->{$callback[1]}($strField, $arrData, $this); } } // Use the default routine to initialize options data $arrWidget = \Widget::getAttributesFromDca($arrData, $strField); $objFilter = Isotope::getRequestCache()->getFilterForModule($strField, $this->id); if (($objAttribute = $GLOBALS['TL_DCA']['tl_iso_product']['attributes'][$strField]) !== null && $objAttribute instanceof IsotopeAttributeWithOptions) { $objAttribute->optionsSource = 'attribute'; $arrWidget['options'] = $objAttribute->getOptionsForProductFilter($arrValues); } foreach ($arrValues as $value) { $arrWidget['options'][] = array('value' => $value, 'label' => $value == '' ? ' ' : 'text'); } // Must have options to apply the filter if (!is_array($arrWidget['options'])) { continue; } foreach ($arrWidget['options'] as $k => $option) { if ($option['value'] == '') { $arrWidget['blankOptionLabel'] = $option['label']; unset($arrWidget['options'][$k]); continue; } elseif (!in_array($option['value'], $arrValues) || $option['value'] == '-') { // @deprecated IsotopeAttributeWithOptions::getOptionsForProductFilter already checks this unset($arrWidget['options'][$k]); continue; } $arrWidget['options'][$k]['default'] = null !== $objFilter && $objFilter->valueEquals($option['value']) ? '1' : ''; } // Hide fields with just one option (if enabled) if ($this->iso_filterHideSingle && count($arrWidget['options']) < 2) { continue; } $arrFilters[$strField] = $arrWidget; } } // !HOOK: alter the filters if (isset($GLOBALS['ISO_HOOKS']['generateFilters']) && is_array($GLOBALS['ISO_HOOKS']['generateFilters'])) { foreach ($GLOBALS['ISO_HOOKS']['generateFilters'] as $callback) { $objCallback = \System::importStatic($callback[0]); $arrFilters = $objCallback->{$callback}[1]($arrFilters); } } if (!empty($arrFilters)) { $this->Template->hasFilters = true; $this->Template->filterOptions = $arrFilters; } } }
private function verifySystemIntegrity() { // Just make sure no variant or translation has any categories assigned \Database::getInstance()->query("DELETE FROM " . \Isotope\Model\ProductCategory::getTable() . " WHERE pid IN (SELECT id FROM " . \Isotope\Model\Product::getTable() . " WHERE pid>0)"); }
/** * Get categories (pages) assigned to this product * * @param bool $blnPublished Only return published categories (pages) * * @return array */ public function getCategories($blnPublished = false) { $key = $blnPublished ? 'published' : 'all'; if (null === $this->arrCategories || !isset($this->arrCategories[$key])) { if ($blnPublished) { $options = ProductCategory::getFindByPidForPublishedPagesOptions($this->getProductId()); $options['table'] = ProductCategory::getTable(); $query = \Model\QueryBuilder::find($options); $values = (array) $options['value']; } else { $query = 'SELECT page_id FROM ' . ProductCategory::getTable() . ' WHERE pid=?'; $values = array($this->getProductId()); } $objCategories = \Database::getInstance()->prepare($query)->execute($values); $this->arrCategories[$key] = $objCategories->fetchEach('page_id'); // Sort categories by the backend drag&drop $arrOrder = deserialize($this->orderPages); if (!empty($arrOrder) && is_array($arrOrder)) { $this->arrCategories[$key] = array_unique(array_merge(array_intersect($arrOrder, $this->arrCategories[$key]), $this->arrCategories[$key])); } } return $this->arrCategories[$key]; }
/** * Apply advanced filters to product list view * @return void */ public function applyAdvancedFilters() { $session = $this->Session->getData(); // Store filter values in the session foreach ($_POST as $k => $v) { if (substr($k, 0, 4) != 'iso_') { continue; } // Reset the filter if ($k == \Input::post($k)) { unset($session['filter']['tl_iso_product'][$k]); } else { $session['filter']['tl_iso_product'][$k] = \Input::post($k); } } $this->Session->setData($session); if (\Input::get('id') > 0 || !isset($session['filter']['tl_iso_product'])) { return; } $arrProducts = null; // Filter the products foreach ($session['filter']['tl_iso_product'] as $k => $v) { if (substr($k, 0, 4) != 'iso_') { continue; } switch ($k) { // Show products with or without images case 'iso_noimages': $objProducts = \Database::getInstance()->execute("SELECT id FROM tl_iso_product WHERE language='' AND images " . ($v ? "IS NULL" : "IS NOT NULL")); $arrProducts = is_array($arrProducts) ? array_intersect($arrProducts, $objProducts->fetchEach('id')) : $objProducts->fetchEach('id'); break; // Show products with or without category // Show products with or without category case 'iso_nocategory': $objProducts = \Database::getInstance()->execute("SELECT id FROM tl_iso_product p WHERE pid=0 AND language='' AND (SELECT COUNT(*) FROM " . ProductCategory::getTable() . " c WHERE c.pid=p.id)" . ($v ? "=0" : ">0")); $arrProducts = is_array($arrProducts) ? array_intersect($arrProducts, $objProducts->fetchEach('id')) : $objProducts->fetchEach('id'); break; // Show new products // Show new products case 'iso_new': $date = 0; switch ($v) { case 'new_today': $date = strtotime('-1 day'); break; case 'new_week': $date = strtotime('-1 week'); break; case 'new_month': $date = strtotime('-1 month'); break; } $objProducts = \Database::getInstance()->prepare("SELECT id FROM tl_iso_product WHERE language='' AND dateAdded>=?")->execute($date); $arrProducts = is_array($arrProducts) ? array_intersect($arrProducts, $objProducts->fetchEach('id')) : $objProducts->fetchEach('id'); break; case 'iso_page': // Filter the products by pages if ($v > 0) { $objProducts = \Database::getInstance()->execute("SELECT id FROM tl_iso_product p WHERE pid=0 AND language='' AND id IN (SELECT pid FROM " . ProductCategory::getTable() . " c WHERE c.pid=p.id AND c.page_id=" . (int) $v . ")"); $arrProducts = is_array($arrProducts) ? array_intersect($arrProducts, $objProducts->fetchEach('id')) : $objProducts->fetchEach('id'); } break; default: // !HOOK: add custom advanced filters if (isset($GLOBALS['ISO_HOOKS']['applyAdvancedFilters']) && is_array($GLOBALS['ISO_HOOKS']['applyAdvancedFilters'])) { foreach ($GLOBALS['ISO_HOOKS']['applyAdvancedFilters'] as $callback) { $objCallback = \System::importStatic($callback[0]); $arrReturn = $objCallback->{$callback}[1]($k); if (is_array($arrReturn)) { $arrProducts = is_array($arrProducts) ? array_intersect($arrProducts, $arrReturn) : $arrReturn; break; } } } \System::log('Advanced product filter "' . $k . '" not found.', __METHOD__, TL_ERROR); break; } } if (is_array($arrProducts) && empty($arrProducts)) { $arrProducts = array(0); } $GLOBALS['TL_DCA']['tl_iso_product']['list']['sorting']['root'] = $arrProducts; }