/** * Create thumbnail and update the corresponding ShopCategory records * * Scans the ShopCategories with the given IDs. If a non-empty picture * string with a reasonable extension is encountered, determines whether * the corresponding thumbnail is available and up to date or not. * If not, tries to load the file and to create a thumbnail. * Note that only single file names are supported! * Also note that this method returns a string with information about * problems that were encountered. * It skips records which contain no or invalid image * names, thumbnails that cannot be created, and records which refuse * to be updated! * The reasoning behind this is that this method is currently only called * from within some {@link _import()} methods. The focus lies on importing; * whether or not thumbnails can be created is secondary, as the * process can be repeated if there is a problem. * @param integer $id The ShopCategory ID * @param integer $maxWidth The maximum thubnail width * @param integer $maxHeight The maximum thubnail height * @param integer $quality The thumbnail quality * @return string Empty string on success, a string * with error messages otherwise. * @global array * @static * @author Reto Kohli <*****@*****.**> */ static function makeThumbnailById($id, $maxWidth = 120, $maxHeight = 80, $quality = 90) { /* Note: The size and quality parameters should be taken from the settings as follows: \Cx\Core\Setting\Controller\Setting::getValue('thumbnail_max_width','Shop'), \Cx\Core\Setting\Controller\Setting::getValue('thumbnail_max_height','Shop'), \Cx\Core\Setting\Controller\Setting::getValue('thumbnail_quality','Shop') */ global $_ARRAYLANG; if ($id <= 0) { return sprintf($_ARRAYLANG['TXT_SHOP_INVALID_CATEGORY_ID'], $id); } $objCategory = ShopCategory::getById($id, LANGID); if (!$objCategory) { return sprintf($_ARRAYLANG['TXT_SHOP_INVALID_CATEGORY_ID'], $id); } $imageName = $objCategory->picture(); $imagePath = SHOP_CATEGORY_IMAGE_PATH . '/' . $imageName; // Only try to create thumbs from entries that contain a // plain text file name (i.e. from an import) if ($imageName == '' || !preg_match('/\\.(?:jpe?g|gif|png)$/', $imageName)) { return sprintf($_ARRAYLANG['TXT_SHOP_UNSUPPORTED_IMAGE_FORMAT'], $id, $imageName); } // If the picture is missing, skip it. if (!file_exists($imagePath)) { return sprintf($_ARRAYLANG['TXT_SHOP_MISSING_CATEGORY_IMAGES'], $id, $imageName); } // If the thumbnail exists and is newer than the picture, // don't create it again. $thumb_name = ImageManager::getThumbnailFilename($imagePath); if (file_exists($thumb_name) && filemtime($thumb_name) > filemtime($imagePath)) { return ''; } // Already included by the Shop. $objImageManager = new \ImageManager(); // Create thumbnail. // Deleting the old thumb beforehand is integrated into // _createThumbWhq(). if (!$objImageManager->_createThumbWhq(SHOP_CATEGORY_IMAGE_PATH . '/', SHOP_CATEGORY_IMAGE_WEB_PATH . '/', $imageName, $maxWidth, $maxHeight, $quality)) { return sprintf($_ARRAYLANG['TXT_SHOP_ERROR_CREATING_CATEGORY_THUMBNAIL'], $id); } return ''; }
/** * Set up the shop page with products and discounts * * @param array $product_ids The optional array of Product IDs. * Overrides any URL parameters if set * @return boolean True on success, false otherwise * @global ADONewConnection $objDatabase Database connection object * @global array $_ARRAYLANG Language array * @global array $_CONFIG Core configuration array, see {@link /config/settings.php} * @global string(?) $themesPages Themes pages(?) */ static function view_product_overview($product_ids = null) { global $_ARRAYLANG; // activate javascript shadowbox \JS::activate('shadowbox'); $flagSpecialoffer = intval(\Cx\Core\Setting\Controller\Setting::getValue('show_products_default', 'Shop')); if (isset($_REQUEST['cmd']) && $_REQUEST['cmd'] == 'discounts') { $flagSpecialoffer = Products::DEFAULT_VIEW_DISCOUNTS; } $flagLastFive = isset($_REQUEST['lastFive']); $product_id = isset($_REQUEST['productId']) ? intval($_REQUEST['productId']) : null; $cart_id = null; if (isset($_REQUEST['referer']) && $_REQUEST['referer'] == 'cart') { $cart_id = $product_id; $product_id = Cart::get_product_id($cart_id); } $manufacturer_id = isset($_REQUEST['manufacturerId']) ? intval($_REQUEST['manufacturerId']) : null; $term = isset($_REQUEST['term']) ? trim(contrexx_input2raw($_REQUEST['term'])) : null; $category_id = isset($_REQUEST['catId']) ? intval($_REQUEST['catId']) : null; if (!($product_id || $category_id || $manufacturer_id || $term || $cart_id)) { // NOTE: This is different from NULL // in that it enables listing the subcategories $category_id = 0; } // Validate parameters if ($product_id && empty($category_id)) { $objProduct = Product::getById($product_id); if ($objProduct) { $category_id = $objProduct->category_id(); } if (isset($_SESSION['shop']['previous_category_id'])) { $category_id_previous = $_SESSION['shop']['previous_category_id']; foreach (preg_split('/\\s*,\\s*/', $category_id) as $id) { if ($category_id_previous == intval($id)) { $category_id = $category_id_previous; } } } } // Remember visited Products if ($product_id) { self::rememberVisitedProducts($product_id); } $objCategory = null; if ($category_id && empty($product_id)) { $objCategory = ShopCategory::getById($category_id); if (!$objCategory) { $category_id = null; } } $shopMenu = '<form method="post" action="' . \Cx\Core\Routing\Url::fromModuleAndCmd('Shop', '') . '">' . '<input type="text" name="term" value="' . htmlentities($term, ENT_QUOTES, CONTREXX_CHARSET) . '" style="width:150px;" /> ' . '<select name="catId" style="width:150px;">' . '<option value="0">' . $_ARRAYLANG['TXT_ALL_PRODUCT_GROUPS'] . '</option>' . ShopCategories::getMenuoptions($category_id) . '</select> ' . Manufacturer::getMenu('manufacturerId', $manufacturer_id, true) . '<input type="submit" name="bsubmit" value="' . $_ARRAYLANG['TXT_SEARCH'] . '" style="width:66px;" />' . '</form>'; self::$objTemplate->setGlobalVariable($_ARRAYLANG + array('SHOP_MENU' => $shopMenu, 'SHOP_SEARCH_TERM' => htmlentities($term, ENT_QUOTES, CONTREXX_CHARSET), 'SHOP_CATEGORIES_MENUOPTIONS' => ShopCategories::getMenuoptions($category_id, true, 0, true), 'SHOP_MANUFACTURER_MENUOPTIONS' => Manufacturer::getMenuoptions($manufacturer_id, true))); // Only show the cart info when the JS cart is not active! global $_CONFIGURATION; if (empty($_CONFIGURATION['custom']['shopJsCart'])) { self::$objTemplate->setVariable(array('SHOP_CART_INFO' => self::cart_info())); } // Exclude Category list from search results if ($term == '') { self::showCategories($category_id); } if (self::$objTemplate->blockExists('shopNextCategoryLink')) { $nextCat = ShopCategory::getNextShopCategoryId($category_id); $objCategory = ShopCategory::getById($nextCat); if ($objCategory) { self::$objTemplate->setVariable(array('SHOP_NEXT_CATEGORY_ID' => $nextCat, 'SHOP_NEXT_CATEGORY_TITLE' => str_replace('"', '"', $objCategory->name()))); } } $pagingCmd = !empty($_REQUEST['cmd']) ? '&cmd=' . contrexx_input2raw($_REQUEST['cmd']) : ''; $pagingCatId = ''; $pagingManId = ''; $pagingTerm = ''; // TODO: This probably breaks paging in search results! // Should only reset the flag conditionally, but add the URL parameters in // any case, methinks! if ($category_id > 0 && $term == '') { $flagSpecialoffer = false; $pagingCatId = "&catId={$category_id}"; } if ($manufacturer_id > 0) { $flagSpecialoffer = false; $pagingManId = "&manufacturer_id={$manufacturer_id}"; } if ($term != '') { $flagSpecialoffer = false; $pagingTerm = '&term=' . htmlentities($term, ENT_QUOTES, CONTREXX_CHARSET); } // The Product count is passed by reference and set to the total // number of records, though only as many as specified by the core // paging limit are returned in the array. $limit = \Cx\Core\Setting\Controller\Setting::getValue('numof_products_per_page_frontend', 'Shop'); //\DBG::activate(DBG_ERROR_FIREPHP); // Use Sorting class for the Product order $uri = \Html::getRelativeUri_entities(); $arrOrder = array('product.ord' => $_ARRAYLANG['TXT_SHOP_ORDER_PRODUCT_ORD'], 'name' => $_ARRAYLANG['TXT_SHOP_ORDER_PRODUCT_TITLE'], 'code' => $_ARRAYLANG['TXT_SHOP_ORDER_PRODUCT_CODE'], 'price' => $_ARRAYLANG['TXT_SHOP_ORDER_PRODUCT_PRICE'], 'id' => $_ARRAYLANG['TXT_SHOP_ORDER_PRODUCT_DATE'], 'bestseller' => $_ARRAYLANG['TXT_SHOP_ORDER_PRODUCT_BESTSELLER']); $defaultOrder = \Sorting::getFieldindex(Products::$arrProductOrder[\Cx\Core\Setting\Controller\Setting::getValue('product_sorting', 'Shop')]); $objSorting = new \Sorting($uri, $arrOrder, true, 'shop_order_products', $defaultOrder); //\DBG::log("Sorting headers: ".var_export($objSorting->getHeaderArray(), true)); $count = $limit; $arrProduct = array(); if ($product_ids) { $arrProduct = self::getValidProducts($product_ids); $product_id = null; // Suppress meta title from single Product } elseif ($product_id) { $arrProduct = self::getValidProducts(array($product_id)); } else { $arrProduct = Products::getByShopParams($count, \Paging::getPosition(), $product_id, $category_id, $manufacturer_id, $term, $flagSpecialoffer, $flagLastFive, $objSorting->getOrder(), self::$objCustomer && self::$objCustomer->is_reseller()); } // Only show sorting when there's enough to be sorted if ($count > 1) { $objSorting->parseHeaders(self::$objTemplate, 'shop_product_order'); } if ($count == 0 && !ShopCategories::getChildCategoryIdArray($category_id)) { //if ($term != '' || $manufacturer_id != 0 || $flagSpecialoffer) { if (self::$objTemplate->blockExists('no_product')) { self::$objTemplate->touchBlock('no_product'); } return true; } if ($objCategory) { // Only indicate the category name when there are products if ($count) { self::$objTemplate->setVariable(array('SHOP_CATEGORY_CURRENT_NAME' => contrexx_raw2xhtml($objCategory->name()), 'SHOP_PRODUCTS_IN_CATEGORY' => sprintf($_ARRAYLANG['TXT_SHOP_PRODUCTS_IN_CATEGORY'], contrexx_raw2xhtml($objCategory->name())))); } } else { // TODO: There are other cases of flag combinations that are not indivuidually // handled here yet. if ($term == '') { if ($flagSpecialoffer == Products::DEFAULT_VIEW_DISCOUNTS) { self::$objTemplate->setVariable('SHOP_PRODUCTS_IN_CATEGORY', $_ARRAYLANG['TXT_SHOP_PRODUCTS_SPECIAL_OFFER']); } else { if (self::$objTemplate->blockExists('products_in_category')) { self::$objTemplate->hideBlock('products_in_category'); } } } else { self::$objTemplate->setVariable('SHOP_PRODUCTS_IN_CATEGORY', sprintf($_ARRAYLANG['TXT_SHOP_PRODUCTS_SEARCH_RESULTS'], contrexx_raw2xhtml($term))); } } $uri = '&section=Shop' . MODULE_INDEX . $pagingCmd . $pagingCatId . $pagingManId . $pagingTerm; self::$objTemplate->setVariable(array('SHOP_PRODUCT_PAGING' => \Paging::get($uri, '', $count, $limit, $count > 0), 'SHOP_PRODUCT_TOTAL' => $count)); // Global microdata: Seller information $seller_url = \Cx\Core\Routing\Url::fromModuleAndCmd('Shop', '')->toString(); $seller_name = \Cx\Core\Setting\Controller\Setting::getValue('company', 'Shop'); if (empty($seller_name)) { $seller_name = $seller_url; } self::$objTemplate->setVariable(array('SHOP_SELLER_NAME' => $seller_name, 'SHOP_SELLER_URL' => $seller_url)); $formId = 0; $arrDefaultImageSize = $arrSize = null; foreach ($arrProduct as $objProduct) { if (!empty($product_id)) { self::$pageTitle = $objProduct->name(); } $id = $objProduct->id(); $productSubmitFunction = ''; $arrPictures = Products::get_image_array_from_base64($objProduct->pictures()); $havePicture = false; $arrProductImages = array(); foreach ($arrPictures as $index => $image) { $thumbnailPath = $pictureLink = ''; if (empty($image['img']) || $image['img'] == ShopLibrary::noPictureName) { // We have at least one picture on display already. // No need to show "no picture" three times! if ($havePicture) { continue; } $thumbnailPath = self::$defaultImage; $pictureLink = '#'; //"javascript:alert('".$_ARRAYLANG['TXT_NO_PICTURE_AVAILABLE']."');"; if (empty($arrDefaultImageSize)) { $arrDefaultImageSize = getimagesize(\Cx\Core\Core\Controller\Cx::instanciate()->getWebsitePath() . self::$defaultImage); self::scaleImageSizeToThumbnail($arrDefaultImageSize); } $arrSize = $arrDefaultImageSize; } else { $thumbnailPath = \Cx\Core\Core\Controller\Cx::instanciate()->getWebsiteImagesShopWebPath() . '/' . \ImageManager::getThumbnailFilename($image['img']); if ($image['width'] && $image['height']) { $pictureLink = contrexx_raw2encodedUrl(\Cx\Core\Core\Controller\Cx::instanciate()->getWebsiteImagesShopWebPath() . '/' . $image['img']) . '" rel="shadowbox[' . ($formId + 1) . ']'; // Thumbnail display size $arrSize = array($image['width'], $image['height']); } else { $pictureLink = '#'; if (!file_exists(\Cx\Core\Core\Controller\Cx::instanciate()->getWebsitePath() . $thumbnailPath)) { continue; } $arrSize = getimagesize(\Cx\Core\Core\Controller\Cx::instanciate()->getWebsitePath() . $thumbnailPath); } self::scaleImageSizeToThumbnail($arrSize); // Use the first available picture in microdata, if any if (!$havePicture) { $picture_url = \Cx\Core\Routing\Url::fromCapturedRequest(\Cx\Core\Core\Controller\Cx::instanciate()->getWebsiteImagesShopWebPath() . '/' . $image['img'], \Cx\Core\Core\Controller\Cx::instanciate()->getWebsiteOffsetPath(), array()); self::$objTemplate->setVariable('SHOP_PRODUCT_IMAGE', $picture_url->toString()); //\DBG::log("Set image to ".$picture_url->toString()); } } $arrProductImages[] = array('THUMBNAIL' => contrexx_raw2encodedUrl($thumbnailPath), 'THUMBNAIL_SIZE' => $arrSize[3], 'THUMBNAIL_LINK' => $pictureLink, 'POPUP_LINK' => $pictureLink, 'POPUP_LINK_NAME' => $_ARRAYLANG['TXT_SHOP_IMAGE'] . ' ' . $index); $havePicture = true; } $i = 1; foreach ($arrProductImages as $arrProductImage) { // TODO: Instead of several numbered image blocks, use a single one repeatedly self::$objTemplate->setVariable(array('SHOP_PRODUCT_THUMBNAIL_' . $i => $arrProductImage['THUMBNAIL'], 'SHOP_PRODUCT_THUMBNAIL_SIZE_' . $i => $arrProductImage['THUMBNAIL_SIZE'])); if (!empty($arrProductImage['THUMBNAIL_LINK'])) { self::$objTemplate->setVariable(array('SHOP_PRODUCT_THUMBNAIL_LINK_' . $i => $arrProductImage['THUMBNAIL_LINK'], 'TXT_SEE_LARGE_PICTURE' => $_ARRAYLANG['TXT_SEE_LARGE_PICTURE'])); } else { self::$objTemplate->setVariable('TXT_SEE_LARGE_PICTURE', contrexx_raw2xhtml($objProduct->name())); } if ($arrProductImage['POPUP_LINK']) { self::$objTemplate->setVariable('SHOP_PRODUCT_POPUP_LINK_' . $i, $arrProductImage['POPUP_LINK']); } self::$objTemplate->setVariable('SHOP_PRODUCT_POPUP_LINK_NAME_' . $i, $arrProductImage['POPUP_LINK_NAME']); ++$i; } $stock = $objProduct->stock_visible() ? $_ARRAYLANG['TXT_STOCK'] . ': ' . intval($objProduct->stock()) : ''; $price = $objProduct->get_custom_price(self::$objCustomer, 0, 1, true); // If there is a discountprice and it's enabled $discountPrice = ''; if ($objProduct->discountprice() > 0 && $objProduct->discount_active()) { $price = '<s>' . $price . '</s>'; $discountPrice = $objProduct->get_custom_price(self::$objCustomer, 0, 1, false); } $groupCountId = $objProduct->group_id(); $groupArticleId = $objProduct->article_id(); $groupCustomerId = 0; if (self::$objCustomer) { $groupCustomerId = self::$objCustomer->group_id(); } self::showDiscountInfo($groupCustomerId, $groupArticleId, $groupCountId, 1); /* OLD $price = Currency::getCurrencyPrice( $objProduct->getCustomerPrice(self::$objCustomer) ); $discountPrice = ''; $discount_active = $objProduct->discount_active(); if ($discount_active) { $discountPrice = $objProduct->discountprice(); if ($discountPrice > 0) { $price = "<s>$price</s>"; $discountPrice = Currency::getCurrencyPrice($discountPrice); } } */ $short = $objProduct->short(); $longDescription = $objProduct->long(); $detailLink = null; // Detaillink is required for microdata (even when longdesc // is empty) $detail_url = \Cx\Core\Routing\Url::fromModuleAndCmd('Shop', 'details', FRONTEND_LANG_ID, array('productId' => $objProduct->id()))->toString(); self::$objTemplate->setVariable('SHOP_PRODUCT_DETAIL_URL', $detail_url); if (!$product_id && !empty($longDescription)) { $detailLink = '<a href="' . $detail_url . '"' . ' title="' . $_ARRAYLANG['TXT_MORE_INFORMATIONS'] . '">' . $_ARRAYLANG['TXT_MORE_INFORMATIONS'] . '</a>'; self::$objTemplate->setVariable('SHOP_PRODUCT_DETAILLINK', $detailLink); } // Check Product flags. // Only the meter flag is currently implemented and in use. $flagMeter = $objProduct->testFlag('__METER__'); // Submit button name and function. // Calling productOptions() also sets the $flagMultipart variable // to the appropriate encoding type for the form if // any upload fields are in use. $flagMultipart = false; $productSubmitName = $productSubmitFunction = ''; if (isset($_GET['cmd']) && $_GET['cmd'] == 'details' && isset($_GET['referer']) && $_GET['referer'] == 'cart') { $productSubmitName = "updateProduct[{$cart_id}]"; $productSubmitFunction = self::productOptions($id, $formId, $cart_id, $flagMultipart); } else { $productSubmitName = 'addProduct'; $productSubmitFunction = self::productOptions($id, $formId, $cart_id, $flagMultipart); } $shopProductFormName = "shopProductForm{$formId}"; $row = $formId % 2 + 1; self::$objTemplate->setVariable(array('SHOP_ROWCLASS' => 'row' . $row, 'SHOP_PRODUCT_ID' => $objProduct->id(), 'SHOP_PRODUCT_TITLE' => contrexx_raw2xhtml($objProduct->name()), 'SHOP_PRODUCT_DESCRIPTION' => $short, 'SHOP_PRODUCT_DETAILDESCRIPTION' => $longDescription ? $longDescription : $short, 'SHOP_PRODUCT_FORM_NAME' => $shopProductFormName, 'SHOP_PRODUCT_SUBMIT_NAME' => $productSubmitName, 'SHOP_PRODUCT_SUBMIT_FUNCTION' => $productSubmitFunction, 'SHOP_FORM_ENCTYPE' => $flagMultipart ? ' enctype="multipart/form-data"' : '', 'TXT_SHOP_PRODUCT_COUNT' => $flagMeter ? $_ARRAYLANG['TXT_SHOP_PRODUCT_METER'] : $_ARRAYLANG['TXT_SHOP_PRODUCT_COUNT'], 'SHOP_CURRENCY_CODE' => Currency::getActiveCurrencyCode())); if ($objProduct->code()) { self::$objTemplate->setVariable('SHOP_PRODUCT_CUSTOM_ID', htmlentities($objProduct->code(), ENT_QUOTES, CONTREXX_CHARSET)); } $manufacturer_name = $manufacturer_url = $manufacturer_link = ''; $manufacturer_id = $objProduct->manufacturer_id(); if ($manufacturer_id) { $manufacturer_name = Manufacturer::getNameById($manufacturer_id, FRONTEND_LANG_ID); $manufacturer_url = Manufacturer::getUrlById($manufacturer_id, FRONTEND_LANG_ID); } if (!empty($manufacturer_url) || !empty($manufacturer_name)) { if (empty($manufacturer_name)) { $manufacturer_name = $manufacturer_url; } if (!empty($manufacturer_url)) { $manufacturer_link = '<a href="' . $manufacturer_url . '">' . $manufacturer_name . '</a>'; } // TODO: Test results for any combination of name and url self::$objTemplate->setVariable(array('SHOP_MANUFACTURER_NAME' => $manufacturer_name, 'SHOP_MANUFACTURER_URL' => $manufacturer_url, 'SHOP_MANUFACTURER_LINK' => $manufacturer_link, 'TXT_SHOP_MANUFACTURER_LINK' => $_ARRAYLANG['TXT_SHOP_MANUFACTURER_LINK'])); } // This is the old Product field for the Manufacturer URI. // This is now extended by the Manufacturer table and should thus // get a new purpose. As it is product specific, it could be // renamed and reused as a link to individual Products! $externalLink = $objProduct->uri(); if (!empty($externalLink)) { self::$objTemplate->setVariable(array('SHOP_EXTERNAL_LINK' => '<a href="' . $externalLink . '" title="' . $_ARRAYLANG['TXT_SHOP_EXTERNAL_LINK'] . '" target="_blank">' . $_ARRAYLANG['TXT_SHOP_EXTERNAL_LINK'] . '</a>')); } if ($price) { self::$objTemplate->setGlobalVariable(array('SHOP_PRODUCT_PRICE' => $price, 'SHOP_PRODUCT_PRICE_UNIT' => Currency::getActiveCurrencySymbol())); } // Only show the discount price if it's actually in use, // avoid an "empty <font> tag" HTML warning if ($discountPrice) { self::$objTemplate->setGlobalVariable(array('SHOP_PRODUCT_DISCOUNTPRICE' => $discountPrice, 'SHOP_PRODUCT_DISCOUNTPRICE_UNIT' => Currency::getActiveCurrencySymbol())); if (self::$objTemplate->blockExists('price_discount')) { self::$objTemplate->touchBlock('price_discount'); } } else { if (self::$objTemplate->blockExists('price')) { self::$objTemplate->touchBlock('price'); } } // Special outlet ShopCategory with discounts varying daily. // This should be implemented in a more generic way, in the // Discount class maybe. if ($objProduct->is_outlet()) { self::$objTemplate->setVariable(array('TXT_SHOP_DISCOUNT_TODAY' => $_ARRAYLANG['TXT_SHOP_DISCOUNT_TODAY'], 'SHOP_DISCOUNT_TODAY' => $objProduct->getOutletDiscountRate() . '%', 'TXT_SHOP_PRICE_TODAY' => $_ARRAYLANG['TXT_SHOP_PRICE_TODAY'], 'SHOP_PRICE_TODAY' => Currency::getCurrencyPrice($objProduct->getDiscountedPrice()), 'SHOP_PRICE_TODAY_UNIT' => Currency::getActiveCurrencySymbol())); } if ($objProduct->stock_visible()) { self::$objTemplate->setVariable(array('SHOP_PRODUCT_STOCK' => $stock)); } if ($detailLink) { self::$objTemplate->setVariable(array('SHOP_PRODUCT_DETAILLINK' => $detailLink)); } $distribution = $objProduct->distribution(); $weight = ''; if ($distribution == 'delivery') { $weight = $objProduct->weight(); } // Hide the weight if it is zero or disabled in the configuration if ($weight > 0 && \Cx\Core\Setting\Controller\Setting::getValue('weight_enable', 'Shop')) { self::$objTemplate->setVariable(array('TXT_SHOP_PRODUCT_WEIGHT' => $_ARRAYLANG['TXT_SHOP_PRODUCT_WEIGHT'], 'SHOP_PRODUCT_WEIGHT' => Weight::getWeightString($weight))); } if (Vat::isEnabled()) { self::$objTemplate->setVariable(array('SHOP_PRODUCT_TAX_PREFIX' => Vat::isIncluded() ? $_ARRAYLANG['TXT_SHOP_VAT_PREFIX_INCL'] : $_ARRAYLANG['TXT_SHOP_VAT_PREFIX_EXCL'], 'SHOP_PRODUCT_TAX' => Vat::getShort($objProduct->vat_id()))); } // Add flag images for flagged Products $strImage = ''; $strFlags = $objProduct->flags(); $arrVirtual = ShopCategories::getVirtualCategoryNameArray(FRONTEND_LANG_ID); foreach (explode(' ', $strFlags) as $strFlag) { if (in_array($strFlag, $arrVirtual)) { $strImage .= '<img src="images/content/' . $strFlag . '.jpg" alt="' . $strFlag . '" />'; } } if ($strImage) { self::$objTemplate->setVariable('SHOP_PRODUCT_FLAG_IMAGE', $strImage); } $minimum_order_quantity = $objProduct->minimum_order_quantity(); //Activate Quantity-Inputfield when minimum_order_quantity exists if (self::$objTemplate->blockExists('orderQuantity') && $minimum_order_quantity > 0) { self::$objTemplate->setVariable('SHOP_PRODUCT_MINIMUM_ORDER_QUANTITY', contrexx_raw2xhtml($objProduct->minimum_order_quantity())); } elseif (self::$objTemplate->blockExists('orderQuantity') && !$minimum_order_quantity) { self::$objTemplate->hideBlock('orderQuantity'); } if (self::$objTemplate->blockExists('shopProductRow')) { self::$objTemplate->parse('shopProductRow'); } ++$formId; } return true; }
/** * Returns the child ShopCategory of this with the given name, if found. * * Returns false if the query fails, or if no child ShopCategory of * that name can be found. * //Note that if there are two or more children of the same name (and with * //active status, if $active is true), a warning will be echo()ed. * //This is by design. * @static * @param string $strName The child ShopCategory name * @param boolean $active If true, only active ShopCategories * are considered. * @return mixed The ShopCategory on success, * false otherwise. * @global ADONewConnection $objDatabase Database connection object * @global array * @author Reto Kohli <*****@*****.**> */ static function getChildNamed($strName, $active = true) { global $objDatabase; $query = "\n SELECT id\n FROM " . DBPREFIX . "module_shop" . MODULE_INDEX . "_categories\n WHERE " . ($active ? 'active=1 AND' : '') . "\n parent_id={$this->parent_id} AND\n catname='" . addslashes($strName) . "'\n ORDER BY ord ASC"; $objResult = $objDatabase->Execute($query); if (!$objResult) { return false; } // if ($objResult->RecordCount() > 1) echo("ShopCategory::getChildNamed($strName, $active): ".$_ARRAYLANG['TXT_SHOP_WARNING_MULTIPLE_CATEGORIES_WITH_SAME_NAME'].'<br />'); if (!$objResult->EOF) { return ShopCategory::getById($objResult->fields['id']); } return false; }
/** * Apply the flags to all Products matching the given Product code * * Any Product and ShopCategory carrying one or more of the names * of any ShopCategory marked as "__VIRTUAL__" is cloned and added * to that category. Those having any such flags removed are deleted * from the respective category. Identical copies of the same Products * are recognized by their "product_id" (the Product code). * * Note that in this current version, only the flags of Products are * tested and applied. Products are cloned and added together with * their immediate parent ShopCategories (aka "Article"). * * Thus, all Products within the same "Article" ShopCategory carry the * same flags, as does the containing ShopCategory itself. * @param integer $productCode The Product code (*NOT* the ID). * This must be non-empty! * @param string $strNewFlags The new flags for the Product * @static * @author Reto Kohli <*****@*****.**> */ static function changeFlagsByProductCode($productCode, $strNewFlags) { if (empty($productCode)) { return false; } // Get all available flags. These are represented by the names // of virtual root ShopCategories. $arrVirtual = ShopCategories::getVirtualCategoryNameArray(); // Get the affected identical Products $arrProduct = Products::getByCustomId($productCode); // No way we can do anything useful without them. if (count($arrProduct) == 0) { return false; } // Get the Product flags. As they're all the same, we'll use the // first one here. // Note that this object is used for reference only and is never stored. // Its database entry will be updated along the way, however. $_objProduct = $arrProduct[0]; $strOldFlags = $_objProduct->getFlags(); // Flag indicating whether the article has been cloned already // for all new flags set. $flagCloned = false; // Now apply the changes to all those identical Products, their parent // ShopCategories, and all sibling Products within them. foreach ($arrProduct as $objProduct) { // Get the containing article ShopCategory. $category_id = $objProduct->category_id(); $objArticleCategory = ShopCategory::getById($category_id); if (!$objArticleCategory) { continue; } // Get parent (subgroup) $objSubGroupCategory = ShopCategory::getById($objArticleCategory->parent_id()); // This should not happen! if (!$objSubGroupCategory) { continue; } $subgroupName = $objSubGroupCategory->name(); // Get grandparent (group, root ShopCategory) $objRootCategory = ShopCategory::getById($objSubGroupCategory->parent_id()); if (!$objRootCategory) { continue; } // Apply the new flags to all Products and Article ShopCategories. // Update the flags of the original Article ShopCategory first $objArticleCategory->flags($strNewFlags); $objArticleCategory->store(); // Get all sibling Products affected by the same flags $arrSiblingProducts = Products::getByShopCategory($objArticleCategory->id()); // Set the new flag set for all Products within the Article // ShopCategory. foreach ($arrSiblingProducts as $objProduct) { $objProduct->flags($strNewFlags); $objProduct->store(); } // Check whether this group is affected by the changes. // If its name matches one of the flags, the Article and subgroup // may have to be removed. $strFlag = $objRootCategory->name(); if (preg_match("/{$strFlag}/", $strNewFlags)) { // The flag is still there, don't bother. continue; } // Also check whether this is a virtual root ShopCategory. if (in_array($strFlag, $arrVirtual)) { // It is one of the virtual roots, and the flag is missing. // So the Article has to be removed from this group. $objArticleCategory->delete(); $objArticleCategory = false; // And if the subgroup happens to contain no more // "Article", delete it as well. $arrChildren = $objSubGroupCategory->getChildrenIdArray(); if (count($arrChildren) == 0) { $objSubGroupCategory->delete(); } continue; } // Here, the virtual ShopCategory groups have been processed, // the only ones left are the "normal" ShopCategories. // Clone one of the Article ShopCategories for each of the // new flags set. // Already did that? if ($flagCloned) { continue; } // Find out what flags have been added. foreach ($arrVirtual as $strFlag) { // That flag is not present in the new flag set. if (!preg_match("/{$strFlag}/", $strNewFlags)) { continue; } // But it has been before. The respective branch has // been truncated above already. if (preg_match("/{$strFlag}/", $strOldFlags)) { continue; } // That is a new flag for which we have to clone the Article. // Get the affected grandparent (group, root ShopCategory) $objTargetRootCategory = ShopCategories::getChildNamed($strFlag, 0, false); if (!$objTargetRootCategory) { continue; } // Check whether the subgroup exists already $objTargetSubGroupCategory = ShopCategories::getChildNamed($subgroupName, $objTargetRootCategory->id(), false); if (!$objTargetSubGroupCategory) { // Nope, add the subgroup. $objSubGroupCategory->makeClone(); $objSubGroupCategory->parent_id($objTargetRootCategory->id()); $objSubGroupCategory->store(); $objTargetSubGroupCategory = $objSubGroupCategory; } // Check whether the Article ShopCategory exists already $objTargetArticleCategory = ShopCategories::getChildNamed($objArticleCategory->name(), $objTargetSubGroupCategory->id(), false); if ($objTargetArticleCategory) { // The Article Category already exists. } else { // Nope, clone the "Article" ShopCategory and add it to the // subgroup. Note that the flags have been set already // and don't need to be changed again here. // Also note that the cloning process includes all content // of the Article ShopCategory, but the flags will remain // unchanged. That's why the flags have already been // changed right at the beginning of the process. $objArticleCategory->makeClone(true, true); $objArticleCategory->parent_id($objTargetSubGroupCategory->id()); $objArticleCategory->store(); $objTargetArticleCategory = $objArticleCategory; } } // foreach $arrVirtual } // foreach $arrProduct // And we're done! return true; }
/** * Update all ShopCategories with the data provided by the request. * @return boolean True on success, null on noop, * false otherwise. * @author Reto Kohli <*****@*****.**> (parts) */ function update_categories() { global $_ARRAYLANG; if (empty($_POST['bcategories'])) { return null; } $success = null; foreach ($_POST['update_category_id'] as $category_id) { $ord = $_POST['ord'][$category_id]; $ord_old = $_POST['ord_old'][$category_id]; // $active = isset($_POST['active'][$category_id]); // $active_old = intval($_POST['active_old'][$category_id]); // $virtual = isset($_POST['virtual'][$category_id]); // $virtual_old = isset($_POST['virtual_old'][$category_id]); //DBG::log("Shopmanager::update_categories(): ord $ord, ord_old $ord_old, active $active, active_old $active_old"); // virtual $virtual, virtual_old $virtual_old, if ($ord != $ord_old) { $objCategory = ShopCategory::getById($category_id); $objCategory->ord($ord); // $objCategory->active($active); // $objCategory->virtual($virtual); if ($objCategory->store()) { if (is_null($success)) { $success = true; } } else { // Mind that this graciously returns false. $success = \Message::error(sprintf($_ARRAYLANG['TXT_SHOP_CATEGORY_ERROR_UPDATING'], $category_id)); } } } if ($success) { \Message::ok($_ARRAYLANG['TXT_SHOP_CATEGORIES_UPDATED_SUCCESSFULLY']); } return $success; }