/** * Returns a flat count of all categories, used for paging purposes. Must use the same visibility rules as the getTree method. * * @return int */ public function countAll() { // isc customer group management does not flag all child categories as not-accessible when you untick a parent category from a customer group access list, so we can't simply count(*) to get a count of all truly visible categories // use the nested set query to do a select, but discard the results and then use a FOUND_ROWS call afterwards to get the true count of all visible categories $set = new ISC_NESTEDSET_CATEGORIES(); $sql = $set->generateGetTreeSql(array('categoryid'), ISC_NESTEDSET_START_ROOT, $this->getMaximumDepth(), null, null, true, $this->_getRestrictions()); $result = $GLOBALS['ISC_CLASS_DB']->Query($sql); if (!$result) { return false; } $result = $GLOBALS['ISC_CLASS_DB']->Query("SELECT FOUND_ROWS()"); return $GLOBALS['ISC_CLASS_DB']->FetchOne($result); }
/** * Get an array all of the child categories of the current category. * * @return array a list of all of the child categories of the current category. */ public function GetChildCategories() { $categoryId = $this->GetCategoryId(); $childCats = array(); $set = new ISC_NESTEDSET_CATEGORIES(); // use a manual query instead of getTree as it's less resource intensive since we only need an array of category ids, not array of result rows // nested set results will include the starting node, the HAVING restriction array here will drop it from the final results $sql = $set->generateGetTreeSql(array('categoryid'), $categoryId, ISC_NESTEDSET_DEPTH_ALL, null, null, true, array('`node`.`categoryid` != ' . $categoryId)); $result = $GLOBALS['ISC_CLASS_DB']->Query($sql); while ($row = $GLOBALS['ISC_CLASS_DB']->Fetch($result)) { $childCats[] = $row['categoryid']; } return $childCats; }
/** * _CheckPermissions * Create the database and perform other install-orientated tasks * * @param none * * @return void */ private function RunInstall() { $lk = ''; if(isset($_POST['LK'])) { $lk = ech0($_POST['LK']); } if(!$lk) { $installMessage = GetLang('LKBad'); $installCode = "badLicenseKey"; } if(!isset($_POST['StoreCountryLocationId']) || !isId($_POST['StoreCountryLocationId'])) { $_POST['StoreCountryLocationId'] = 227; // United States } if(!isset($_POST['StoreCurrencyCode']) || $_POST['StoreCurrencyCode'] == '') { $_POST['StoreCurrencyCode'] = 'USD'; } if(!isset($_POST['ShopPath']) || $_POST['ShopPath'] == '') { $installMessage = GetLang('InstallMissingShopPath'); $installCode = "missingShopPath"; } else if (isc_strlen($_POST['StoreCurrencyCode']) > 3) { $installMessage = GetLang('InstallInvalidStoreCurrencyCode'); $installCode = "invalidStoreCurrencyCode"; } else if(!isset($_POST['ShopPath']) || $_POST['ShopPath'] == '') { $installMessage = GetLang('InstallMissingShopPath'); $installCode = "missingShopPath"; } else if(!isset($_POST['UserEmail']) || $_POST['UserEmail'] == '') { $installMessage = GetLang('InstallMissingUserEmail'); $installCode = "missingUserEmail"; } else if(!isset($_POST['UserPass']) || $_POST['UserPass'] == '') { $installMessage = GetLang('InstallMissingUserPass'); $installCode = "missingUserPass"; } else if(!isset($_POST['dbServer']) || $_POST['dbServer'] == '') { $installMessage = GetLang('InstallMissingDbServer'); $installCode = "missingDbServer"; } else if(!isset($_POST['dbUser']) || $_POST['dbUser'] == '') { $installMessage = GetLang('InstallMissingDbUser'); $installCode = "missingDbUser"; } else if(!isset($_POST['dbPass'])) { $installMessage = GetLang('InstallMissingDbPass'); $installCode = "missingDbPass"; } else if(!isset($_POST['dbDatabase']) || $_POST['dbDatabase'] == '') { $installMessage = GetLang('InstallMissingDbDatabase'); $installCode = "missingDbDatabase"; } if(!isset($_POST['tablePrefix'])) { $_POST['tablePrefix'] = ''; } // One or more error messages were detected if(isset($installMessage)) { $errors = array( 0 => array( "code" => $installCode, "message" => $installMessage ) ); $this->ShowInstallErrors($installMessage, $errors, false, true); return; } // Try to connect to the database $db_type = GetConfig("dbType") . 'Db'; $db = new $db_type(); if(isset($GLOBALS['ISC_CFG']["dbEncoding"])) { $db->charset = $GLOBALS['ISC_CFG']["dbEncoding"]; } $connection = $db->Connect($_POST['dbServer'], $_POST['dbUser'], $_POST['dbPass'], $_POST['dbDatabase']); $db->TablePrefix = $_POST['tablePrefix']; if($connection) { $GLOBALS["ISC_CLASS_DB"] = &$db; // Are we running the required version of MySQL? $ver = $GLOBALS["ISC_CLASS_DB"]->FetchOne("select version() as ver"); $mysql_check = version_compare($ver, MYSQL_VERSION_REQUIRED); if($mysql_check < 0) { $message = sprintf(GetLang("MySQLV4Message"), MYSQL_VERSION_REQUIRED, $ver); $errors = array( 0 => array( "code" => "mysqlVersion", "extra" => $ver, "message" => $message ) ); $this->ShowInstallErrors($message, $errors, false, true); return; } else { // Run the database commands $queries = $this->template->render('install.schema.tpl'); $queries = str_replace("\r", "\n", str_replace("\r\n", "\n", $queries)); $queries = explode(";\n", $queries); $GLOBALS["ISC_CLASS_DB"]->Query("start transaction"); // Initialize the admin auth class to get the list of permissions $auth = new ISC_ADMIN_AUTH(); require_once(dirname(__FILE__) . "/class.user.php"); $userManager = GetClass('ISC_ADMIN_USER'); $pass = $_POST['UserPass']; $token = $userManager->_GenerateUserToken(); foreach($queries as $query) { $query = str_replace("%%PREFIX%%", $_POST['tablePrefix'], $query); $query = str_replace("%%EMAIL%%", $GLOBALS["ISC_CLASS_DB"]->Quote($_POST['UserEmail']), $query); $query = str_replace("%%TOKEN%%", $GLOBALS["ISC_CLASS_DB"]->Quote($token), $query); if(trim($query) != "") { $GLOBALS["ISC_CLASS_DB"]->Query($query); } } // update admin user password $user_id = $userManager->getUserByField('username', 'admin'); $userManager->updatePassword($user_id, $pass); // Give the admin user permissions $constants = get_defined_constants(); foreach($constants as $constant => $val) { if(is_numeric(strpos($constant, "AUTH_")) && strpos($constant, "AUTH_") == 0) { $newPermission = array( "permuserid" => $user_id, "permpermissionid" => $val ); $GLOBALS['ISC_CLASS_DB']->InsertQuery("permissions", $newPermission); } } // Set the version $db_version = array( 'database_version' => PRODUCT_VERSION_CODE ); $GLOBALS['ISC_CLASS_DB']->InsertQuery('config', $db_version); // Install our default currency. We need to do it here as it also needs to be in the config file $GLOBALS['ISC_CLASS_DB']->Query("DELETE FROM [|PREFIX|]currencies"); $GLOBALS['ISC_CLASS_DB']->Query("ALTER TABLE [|PREFIX|]currencies AUTO_INCREMENT=1"); $currency = array( 'currencycountryid' => $_POST['StoreCountryLocationId'], 'currencycode' => isc_strtoupper($_POST['StoreCurrencyCode']), 'currencyname' => GetLang('InstallDefaultCurrencyName'), 'currencyexchangerate' => GetConfig('DefaultCurrencyRate'), 'currencystring' => html_entity_decode(GetLang('InstallDefaultCurrencyString')), 'currencystringposition' => isc_strtolower(GetLang('InstallDefaultCurrencyStringPosition')), 'currencydecimalstring' => GetLang('InstallDefaultCurrencyDecimalString'), 'currencythousandstring' => GetLang('InstallDefaultCurrencyThousandString'), 'currencydecimalplace' => GetLang('InstallDefaultCurrencyDecimalPlace'), 'currencylastupdated' => time(), 'currencyisdefault' => 1, 'currencystatus' => 1 ); $defaultCurrencyId = $GLOBALS['ISC_CLASS_DB']->InsertQuery('currencies', $currency); // Insert the default/master shipping zone $GLOBALS['ISC_CLASS_DB']->Query("DELETE FROM [|PREFIX|]shipping_zones"); $GLOBALS['ISC_CLASS_DB']->Query("ALTER TABLE [|PREFIX|]shipping_zones AUTO_INCREMENT=1"); $masterZone = array( 'zonename' => 'Default Zone', 'zonetype' => 'country', 'zonefreeshipping' => 0, 'zonefreeshippingtotal' => 0, 'zonehandlingtype' => 'none', 'zonehandlingfee' => 0, 'zonehandlingseparate' => 1, 'zoneenabled' => 1, 'zonedefault' => 1 ); $GLOBALS['ISC_CLASS_DB']->InsertQuery('shipping_zones', $masterZone); // Is there a custom SQL file to include? $customPath = ISC_BASE_PATH.'/custom'; if(file_exists($customPath.'/install.schema.tpl')) { $template = Interspire_Template::getInstance('custominstall', $customPath, array( 'cache' => getAdminTwigTemplateCacheDirectory(), 'auto_reload' => true )); $queries = $template->render('install.schema.tpl'); $queries = str_replace("\r", "\n", str_replace("\r\n", "\n", $queries)); $queries = explode(";\n", $queries); $GLOBALS['ISC_CLASS_DB']->StartTransaction(); foreach($queries as $query) { $query = str_replace("%%PREFIX%%", $_POST['tablePrefix'], $query); if(trim($query)) { $GLOBALS['ISC_CLASS_DB']->Query($query); } } $GLOBALS['ISC_CLASS_DB']->CommitTransaction(); } // Was there an error? if($GLOBALS["ISC_CLASS_DB"]->Error() == "") { $GLOBALS["ISC_CLASS_DB"]->Query("commit"); // Save the config file foreach($_POST as $k => $v) { $GLOBALS['ISC_NEW_CFG'][$k] = $v; } // Set the email address for this user as the store admin/order email address $GLOBALS['ISC_NEW_CFG']['AdminEmail'] = $_POST['UserEmail']; $GLOBALS['ISC_NEW_CFG']['OrderEmail'] = $_POST['UserEmail']; $GLOBALS['ISC_NEW_CFG']['serverStamp'] = $_POST['LK']; $GLOBALS['ISC_CFG']['serverStamp'] = $_POST['LK']; $settings = GetClass('ISC_ADMIN_SETTINGS'); $GLOBALS['ISC_NEW_CFG']['HostingProvider'] = ""; // Can we send server details back to Interspire? // If we can, the HostingProvider global will also be set if(isset($_POST['sendServerDetails'])) { $this->SendServerDetails(); if(isset($GLOBALS['InfoImage'])) { $GLOBALS['HiddenImage'] = $GLOBALS['InfoImage']; } } $GLOBALS['ISC_NEW_CFG']['ShopPath'] = $_POST['ShopPath']; $GLOBALS['ISC_NEW_CFG']['DefaultCurrencyID'] = $defaultCurrencyId; if (isset($GLOBALS['ISC_NEW_CFG']['StoreCountryLocationId'])) { unset($GLOBALS['ISC_NEW_CFG']['StoreCountryLocationId']); } if (isset($GLOBALS['ISC_NEW_CFG']['StoreCurrencyCode'])) { unset($GLOBALS['ISC_NEW_CFG']['StoreCurrencyCode']); } // set up the product images sizes // load the product image class to get the constants GetClass('ISC_PRODUCT_IMAGE'); $GLOBALS['ISC_NEW_CFG']['ProductImagesStorewideThumbnail_width'] = ISC_PRODUCT_DEFAULT_IMAGE_SIZE_THUMBNAIL; $GLOBALS['ISC_NEW_CFG']['ProductImagesStorewideThumbnail_height'] = ISC_PRODUCT_DEFAULT_IMAGE_SIZE_THUMBNAIL; $GLOBALS['ISC_NEW_CFG']['ProductImagesProductPageImage_width'] = ISC_PRODUCT_DEFAULT_IMAGE_SIZE_STANDARD; $GLOBALS['ISC_NEW_CFG']['ProductImagesProductPageImage_height'] = ISC_PRODUCT_DEFAULT_IMAGE_SIZE_STANDARD; $GLOBALS['ISC_NEW_CFG']['ProductImagesGalleryThumbnail_width'] = ISC_PRODUCT_DEFAULT_IMAGE_SIZE_TINY; $GLOBALS['ISC_NEW_CFG']['ProductImagesGalleryThumbnail_height'] = ISC_PRODUCT_DEFAULT_IMAGE_SIZE_TINY; $GLOBALS['ISC_NEW_CFG']['ProductImagesZoomImage_width'] = ISC_PRODUCT_DEFAULT_IMAGE_SIZE_ZOOM; $GLOBALS['ISC_NEW_CFG']['ProductImagesZoomImage_height'] = ISC_PRODUCT_DEFAULT_IMAGE_SIZE_ZOOM; $GLOBALS['ISC_NEW_CFG']['ProductImagesTinyThumbnailsEnabled'] = 1; $GLOBALS['ISC_NEW_CFG']['ProductImagesImageZoomEnabled'] = 1; // Build the unique encryption token $GLOBALS['ISC_NEW_CFG']['EncryptionToken'] = $this->_BuildEncryptionToken(); // Set the install date $GLOBALS['ISC_NEW_CFG']['InstallDate'] = time(); if ($settings->CommitSettings()) { // Calling commit settings a second time to ensure the config.backup.php file // Is written with valid data $settings->CommitSettings(); // The installation is complete $GLOBALS['Password'] = $pass; // Do we need to install the sample product data? Copy that across if(isset($_POST['installSampleData']) && $_POST['installSampleData'] == 1) { $this->InstallSampleData(); } // The install schemas can't predict the nested set values if custom install scripts arbitrarily add categories or pages // Rebuilt any nested sets instead of including their values in the install schema $nestedSet = new ISC_NESTEDSET_CATEGORIES(); $nestedSet->rebuildTree(); $nestedSet = new ISC_NESTEDSET_PAGES(); $nestedSet->rebuildTree(); // Remove any existing cookies ISC_UnsetCookie("STORESUITE_CP_TOKEN"); //Initialize the data store system require_once ISC_BASE_PATH."/lib/class.datastore.php"; $GLOBALS['ISC_CLASS_DATA_STORE'] = new ISC_DATA_STORE(); // Clear the data store just in case it contains something $GLOBALS['ISC_CLASS_DATA_STORE']->Clear(); $GLOBALS['ISC_LANG']['InstallationCompleted'] = sprintf(GetLang('InstallationCompleted'), $pass); unset($_SESSION['LK'.md5(strtolower($_POST['ShopPath']))]); // The installation was complete! if($this->apiMode == 'cli') { fwrite(STDOUT, "Success:\n"); fwrite(STDOUT, "\n"); fwrite(STDOUT, "ShopPath: ".$_POST['ShopPath']."\n"); fwrite(STDOUT, "ControlPanel: ".$_POST['ShopPath']."admin/index.php\n"); fwrite(STDOUT, "Username: admin\n"); fwrite(STDOUT, "Password: "******"1.0" encoding="'.GetConfig("CharacterSet").'" ?'.">\n"; echo "<response>\n"; echo " <status>OK</status>\n"; echo " <shop>\n"; echo " <shopPath>".$_POST['ShopPath']."</shopPath>\n"; echo " <controlPanel>".$_POST['ShopPath']."admin/index.php</controlPanel>\n"; echo " </shop>\n"; echo " <user>\n"; echo " <username>admin</username>\n"; echo " <password>".$_POST['UserPass']."</password>\n"; echo " </user>\n"; echo "</response>\n"; exit; } else { $this->template->display('install.done.tpl'); } } else { $message = GetLang("ConfigErr"); $errors = array( 0 => array( "code" => "unableSaveConfig", "message" => $message ) ); $this->ShowInstallErrors($message, $errors, false, true); return; } } else { list($error, $level) = $db->GetError(); $GLOBALS["ISC_CLASS_DB"]->Query("rollback"); $message = sprintf(GetLang("DBErr"), $error); $errors = array( 0 => array( "code" => "dbError", "message" => $GLOBALS["ISC_CLASS_DB"]->Error() ) ); $this->ShowInstallErrors($message, $errors, false, true); return; } } } else { list($error, $level) = $db->GetError(); $message = sprintf(GetLang("DBErr"), $error); $errors = array( 0 => array( "code" => "dbConnectError", "message" => $error ) ); $this->ShowInstallErrors($message, $errors, false, true); return; } }
/** * Find the IDs of all subcategories. * * @param array $ids The array of category IDs. * @param array $excludes The array of IDs to exclude. * @return array The array of all subcategory IDs */ public function getSubCategories($ids=0, $excludes=array()) { if (is_array($ids) == false) { $ids = array($ids); } // Find sub category IDs. $cats = array(); $nestedSet = new ISC_NESTEDSET_CATEGORIES(); foreach ($ids as $id) { if (in_array($id, $excludes) == true) { continue; } $cats = array_merge($cats, $nestedSet->getTree(array('categoryid'), $id)); } $subcats = array(); foreach ($cats as $cat) { $subcats[] = $cat['categoryid']; } $res = array_diff($subcats, $excludes); return $res; }
protected function _GenerateImportSummary() { // rebuild the nested set data for categories $nestedSet = new ISC_NESTEDSET_CATEGORIES(); $nestedSet->rebuildTree(); // update cache of root categories $GLOBALS['ISC_CLASS_DATA_STORE']->UpdateRootCategories(); // update cache for category discounts $GLOBALS['ISC_CLASS_DATA_STORE']->UpdateCustomerGroupsCategoryDiscounts(); parent::_GenerateImportSummary(); }
/** * Update the root categories list in the data store. * * @return mixed The data that was saved if successful, false if there was a problem saving the data. */ public function UpdateRootCategories() { $nestedset = new ISC_NESTEDSET_CATEGORIES(); $data = array(); foreach ($nestedset->getTree(array('categoryid', 'catparentid', 'catname'), ISC_NESTEDSET_START_ROOT, GetConfig('CategoryListDepth') - 1, null, null, false, array('MIN(`parent`.`catvisible`) = 1')) as $category) { $data[(int)$category['catparentid']][(int)$category['categoryid']] = $category; } $this->Save('ChildCategories', array()); return $this->Save('RootCategories', $data); }
public function BuildWhereFromVars($array) { $queryWhere = ""; $joinQuery = ""; $categorySearch = false; // Is this a custom search? if(!empty($array['searchId'])) { $this->_customSearch = $GLOBALS['ISC_CLASS_ADMIN_CUSTOMSEARCH']->LoadSearch($array['searchId']); $array = array_merge($array, (array)$this->_customSearch['searchvars']); } // Are we selecting a specific product? if(isset($array['productId']) && $array['productId'] != '') { $queryWhere .= " p.productid = '" . $array['productId'] . "' AND "; // dont need to build a where if only one product searched return array("query" => $queryWhere, "join" => $joinQuery, "categorySearch"=>$categorySearch); } // If we're searching by category, we need to completely // restructure the search query - so do that first $categoryIds = array(); $nestedSet = new ISC_NESTEDSET_CATEGORIES(); if(isset($array['category']) && is_array($array['category'])) { foreach($array['category'] as $categoryId) { // All categories were selected, so don't continue if($categoryId == 0) { $categorySearch = false; break; } $categoryIds[] = (int)$categoryId; // If searching sub categories automatically, fetch & tack them on if (isset($array['subCats']) && $array['subCats'] == 1) { foreach ($nestedSet->getTree(array('categoryid'), $categoryId) as $childCategory) { $categoryIds[] = (int)$childCategory['categoryid']; } unset($childCategory); } } $categoryIds = array_unique($categoryIds); if(!empty($categoryIds)) { $categorySearch = true; } } if($categorySearch == true) { $queryWhere .= "ca.categoryid IN (" . implode(',', $categoryIds) . ") AND "; } if(isset($array['searchQuery']) && $array['searchQuery'] != "") { // Perform a full text based search on the products search table $search_query = $array['searchQuery']; $fulltext_fields = array("ps.prodname", "ps.prodcode"); $queryWhere .= "(" . $GLOBALS["ISC_CLASS_DB"]->FullText($fulltext_fields, $search_query, true); $queryWhere .= "OR ps.prodname like '%" . $GLOBALS['ISC_CLASS_DB']->Quote($search_query) . "%' "; $queryWhere .= "OR ps.prodcode = '" . $GLOBALS['ISC_CLASS_DB']->Quote($search_query) . "' "; if (isId($search_query)) { $queryWhere .= "OR p.productid='" . (int)$search_query . "'"; } $queryWhere .= ") AND "; // Add the join for the fulltext column $joinQuery .= " INNER JOIN [|PREFIX|]product_search ps ON p.productid=ps.productid "; } if(isset($array['letter']) && $array['letter'] != '') { $letter = chr(ord($array['letter'])); if($array['letter'] == '0-9') { $queryWhere .= " p.prodname NOT REGEXP('^[a-zA-Z]') AND "; } else if(isc_strlen($letter) == 1) { $queryWhere .= " p.prodname LIKE '".$GLOBALS['ISC_CLASS_DB']->Quote($letter)."%' AND "; } } if(isset($array['soldFrom']) && isset($array['soldTo']) && $array['soldFrom'] != "" && $array['soldTo'] != "") { $sold_from = (int)$array['soldFrom']; $sold_to = (int)$array['soldTo']; $queryWhere .= sprintf("(prodnumsold >= '%d' and prodnumsold <= '%d') and ", $sold_from, $sold_to); } else if(isset($array['soldFrom']) && $array['soldFrom'] != "") { $sold_from = (int)$array['soldFrom']; $queryWhere .= sprintf("prodnumsold >= '%d' and ", $sold_from); } else if(isset($array['soldTo']) && $array['soldTo'] != "") { $sold_to = (int)$array['soldTo']; $queryWhere .= sprintf("prodnumsold <= '%d' and ", $sold_to); } if(isset($array['priceFrom']) && $array['priceFrom'] != "" && isset($array['priceTo']) && $array['priceTo'] != "") { $price_from = (int)$array['priceFrom']; $price_to = (int)$array['priceTo']; $queryWhere .= sprintf(" prodcalculatedprice >= '%s' and prodcalculatedprice <= '%s' and ", $price_from, $price_to); } else if(isset($array['priceFrom']) && $array['priceFrom'] != "") { $price_from = (int)$array['priceFrom']; $queryWhere .= sprintf(" prodcalculatedprice >= '%s' and ", $price_from); } else if(isset($array['priceTo']) && $array['priceTo'] != "") { $price_to = (int)$array['priceTo']; $queryWhere .= sprintf(" prodcalculatedprice <= '%s' and ", $price_to); } if(isset($array['inventoryFrom']) && $array['inventoryFrom'] != "" && isset($array['inventoryTo']) && $array['inventoryTo'] != "") { $inventory_from =(int)$array['inventoryFrom']; $inventory_to = (int)$array['inventoryTo']; $queryWhere .= sprintf("prodcurrentinv >= '%s' and prodcurrentinv <= '%s' and ", $inventory_from, $inventory_to); } else if(isset($array['inventoryFrom']) && $array['inventoryFrom'] != "") { $inventory_from =(int) $array['inventoryFrom']; $queryWhere .= sprintf("prodcurrentinv >= '%s' and ", $inventory_from); } else if(isset($array['inventoryTo']) && $array['inventoryTo'] != "") { $inventory_to = (int)$array['inventoryTo']; $queryWhere .= sprintf("prodcurrentinv <= '%s' and ", $inventory_to); } if (isset($array['inventoryLow']) && $array['inventoryLow'] != 0) { $lowVarInvProdIds = array(); $inventoryLowVarQuery = "SELECT DISTINCT(vcproductid) FROM [|PREFIX|]product_variation_combinations WHERE vcstock<=vclowstock AND vclowstock > 0"; $result = $GLOBALS['ISC_CLASS_DB']->Query($inventoryLowVarQuery); while ($lowVarInventory = $GLOBALS['ISC_CLASS_DB']->Fetch($result)) { $lowVarInvProdIds[]=$lowVarInventory['vcproductid']; } $queryWhere .= "(prodcurrentinv <= prodlowinv AND prodlowinv > 0 AND prodinvtrack=1) OR ( prodinvtrack=2 AND p.productid in ('".implode('\',\'', $lowVarInvProdIds)."')) AND "; } if(isset($array['brand']) && $array['brand'] != "") { $brand = (int)$array['brand']; $queryWhere .= sprintf("prodbrandid = '%d' AND ", $brand); } // Product visibility if(isset($array['visibility'])) { if($array['visibility'] == 1) { $queryWhere .= "prodvisible=1 AND "; } else if($array['visibility'] === '0') { $queryWhere .= "prodvisible=0 AND "; } } // Featured products? if(isset($array['featured'])) { if($GLOBALS['ISC_CLASS_ADMIN_AUTH']->GetVendorId()) { $featuredColumn = 'prodvendorfeatured'; } else { $featuredColumn = 'prodfeatured'; } if($array['featured'] == 1) { $queryWhere .= $featuredColumn."=1 AND "; } else if($_REQUEST['featured'] === '0') { $queryWhere .= $featuredColumn."=0 AND "; } } // Free shipping if(isset($_REQUEST['freeShipping'])) { if($_REQUEST['freeShipping'] == 1) { $queryWhere .= "prodfreeshipping=1 AND "; } else if($_REQUEST['freeShipping'] === '0') { $queryWhere .= "prodfreeshipping=0 AND "; } } // Last imported products if(isset($_REQUEST['lastImport']) && $_REQUEST['lastImport'] == 1) { $queryWhere .= "last_import > 0 AND last_import in (select max(last_import) from [|PREFIX|]products) AND "; } return array("query" => $queryWhere, "join" => $joinQuery, "categorySearch" => $categorySearch); }
/** * Update the sort order of the categories when they are reordered * * @return void **/ private function UpdateCategoryOrders() { $GLOBALS['ISC_CLASS_ADMIN_ENGINE']->LoadLangFile('categories'); $this->_BuildCategoryOrders($_POST['CategoryList']); // update the nested set values // this must happen first before any other cache updates since other caches may rely on it // @todo the front end currently does not tell the backend which category was moved, only the new structure - if this takes too long to run, the front end needs changing to include which category was moved so a partial update is possible $nested = new ISC_NESTEDSET_CATEGORIES(); $nested->rebuildTree(); // Update the data store $GLOBALS['ISC_CLASS_DATA_STORE']->UpdateRootCategories(); $GLOBALS['ISC_CLASS_DATA_STORE']->UpdateCustomerGroupsCategoryDiscounts(); // Also make sure that all the root categories do NOT have any images assoiated with them $GLOBALS['ISC_CLASS_ADMIN_CATEGORY'] = GetClass('ISC_ADMIN_CATEGORY'); $GLOBALS['ISC_CLASS_ADMIN_CATEGORY']->RemoveRootImages(); $tags[] = $this->MakeXMLTag('status', 1); $tags[] = $this->MakeXMLTag('message', GetLang('CategoryOrdersUpdated'), true); $this->SendXMLHeader(); $this->SendXMLResponse($tags); die(); }
public function __construct($orderId = null) { $this->setDoubleOptIn(GetConfig('EmailIntegrationOrderDoubleOptin')); $this->setSendWelcome(GetConfig('EmailIntegrationOrderSendWelcome')); $this->setSubscriptionIP(GetIP()); if (!$orderId) { return; } $entity = new ISC_ENTITY_ORDER; $data = $entity->get($orderId); if (!$data) { throw new Interspire_EmailIntegration_Subscription_Exception; } $this->_data = $data; unset($data); // copy any form fields associated with the order + associated customer and place into local subscription data if (isId($this->_data['ordformsessionid'])) { /** @var ISC_FORM */ $form = $GLOBALS["ISC_CLASS_FORM"]; $customFields = array(); $formData = $form->getSavedSessionData($this->_data['customer']['custformsessionid']); if ($formData && !empty($formData)) { $customFields += $formData; } $formData = $form->getSavedSessionData($this->_data['ordformsessionid']); if ($formData && !empty($formData)) { $customFields += $formData; } foreach ($customFields as $fieldId => $value) { $this->_data['FormField_' . $fieldId] = $value; } } // generate fields specifically for email integration based on order data (ones that aren't covered by simple order data or by Form Fields) // get the first shipping address record because IEM had shipping method as mappable field $this->_data['shipping_method'] = ''; $shippingMethod = $GLOBALS['ISC_CLASS_DB']->FetchOne("SELECT `method` FROM [|PREFIX|]order_shipping WHERE order_id = " . (int)$orderId . " LIMIT 1", 'method'); if ($shippingMethod) { $this->_data['shipping_method'] = $shippingMethod; } // pre-formated 'full address' mappable field to pass to providers like mailchimp $this->_data['OrderSubscription_BillingAddress'] = array( 'addr1' => $this->_data['ordbillstreet1'], 'addr2' => $this->_data['ordbillstreet2'], 'city' => $this->_data['ordbillsuburb'], 'state' => $this->_data['ordbillstate'], 'zip' => $this->_data['ordbillzip'], 'country' => $this->_data['ordbillcountrycode'], ); // country-code specific fields to pass to providers like MailChimp or IEM that support (or require in IEM's case) country codes $this->_data['OrderSubscription_BillingAddress_countryiso2'] = $this->_data['ordbillcountrycode']; $this->_data['OrderSubscription_BillingAddress_countryiso3'] = GetCountryISO3ById($this->_data['ordbillcountryid']); // for email integration, we prefer sending the value of an order as the total amount rather than the stored (charged) total - which could be less than the value due to store credit or gift certificates // so, generate some columns which are internal to this subscription data and map to those instead of total_ex and total_inc $this->_data['total_ex_tax'] = $this->_data['subtotal_ex_tax'] + $this->_data['shipping_cost_ex_tax'] + $this->_data['handling_cost_ex_tax'] + $this->_data['wrapping_cost_ex_tax']; $this->_data['total_inc_tax'] = $this->_data['subtotal_inc_tax'] + $this->_data['shipping_cost_inc_tax'] + $this->_data['handling_cost_inc_tax'] + $this->_data['wrapping_cost_inc_tax']; // generated fields: end // currency values must be stored in the subscription data as both numeric and formatted so that, when translated to the mail provider, it can be sent as either a number or string depending on the destination field $moneyFields = array( 'subtotal_ex_tax', 'subtotal_inc_tax', 'subtotal_tax', 'total_ex_tax', 'total_inc_tax', 'total_tax', 'shipping_cost_ex_tax', 'shipping_cost_inc_tax', 'shipping_cost_tax', 'handling_cost_ex_tax', 'handling_cost_inc_tax', 'handling_cost_tax', 'wrapping_cost_ex_tax', 'wrapping_cost_inc_tax', 'wrapping_cost_tax', 'ordrefundedamount', 'ordstorecreditamount', 'ordgiftcertificateamount', 'orddiscountamount', 'coupon_discount', ); foreach ($moneyFields as $moneyFieldId) { $this->_data[$moneyFieldId] = array( 'numeric' => $this->_data[$moneyFieldId], 'formatted' => FormatPriceInCurrency($this->_data[$moneyFieldId], $this->_data['orddefaultcurrencyid']), ); } $set = new ISC_NESTEDSET_CATEGORIES; // instead of storing full product information, just store the data pertinent to integration rules foreach ($this->_data['products'] as $product) { $this->_products[] = $product['productid']; $this->_brands[] = $product['prodbrandid']; if ($product['prodcatids']) { foreach (explode(',', $product['prodcatids']) as $categoryId) { $this->_categories[] = $categoryId; // also include parent categories to trigger rules related to them $parents = $set->getParentPath(array('categoryid'), (int)$categoryId); foreach ($parents as $parentCategory) { $this->_categories[] = $parentCategory['categoryid']; } } } } $this->_products = array_unique($this->_products); $this->_brands = array_unique($this->_brands); $this->_categories = array_unique($this->_categories); sort($this->_products); sort($this->_brands); sort($this->_categories); // for now, don't need to store these - may need to store products when this is changed to supply ecommerce info unset($this->_data['customer']); unset($this->_data['products']); }
/** * Build an SQL query for the specified search terms. * * @param array Array of search terms * @param string String of fields to match * @param string The field to sort by * @param string The order to sort results by * @return array An array containing the query to count the number of results and a query to perform the search */ function BuildProductSearchQuery($searchTerms, $fields="", $sortField=array("score", "proddateadded"), $sortOrder="desc") { $queryWhere = array(); $joinQuery = ''; // Construct the full text search part of the query $fulltext_fields = array("ps.prodname", "ps.prodcode", "ps.proddesc", "ps.prodsearchkeywords"); if (!$fields) { $fields = "p.*, FLOOR(p.prodratingtotal/p.prodnumratings) AS prodavgrating, ".GetProdCustomerGroupPriceSQL().", "; $fields .= "pi.* "; if (isset($searchTerms['search_query']) && $searchTerms['search_query'] != "") { $fields .= ', '.$GLOBALS['ISC_CLASS_DB']->FullText($fulltext_fields, $searchTerms['search_query'], false) . " as score "; } } if(isset($searchTerms['categoryid'])) { $searchTerms['category'] = array($searchTerms['categoryid']); } // If we're searching by category, we need to completely // restructure the search query - so do that first $categorySearch = false; $categoryIds = array(); $nestedset = new ISC_NESTEDSET_CATEGORIES; if(isset($searchTerms['category']) && is_array($searchTerms['category'])) { foreach($searchTerms['category'] as $categoryId) { $categoryId = (int)$categoryId; // All categories were selected, so don't continue if($categoryId == 0) { $categorySearch = false; break; } $categoryIds[] = $categoryId; // If searching sub categories automatically, fetch & tack them on if(isset($searchTerms['searchsubs']) && $searchTerms['searchsubs'] == 'ON') { foreach ($nestedset->getTree(array('categoryid'), $categoryId) as $childCategory) { $categoryIds[] = (int)$childCategory['categoryid']; } unset($childCategory); } } $categoryIds = array_unique($categoryIds); if(!empty($categoryIds)) { $categorySearch = true; } } if($categorySearch == true) { $fromTable = '[|PREFIX|]categoryassociations a, [|PREFIX|]products p'; $queryWhere[] = 'a.productid=p.productid AND a.categoryid IN ('.implode(',', $categoryIds).')'; } else { $fromTable = '[|PREFIX|]products p'; } if (isset($searchTerms['search_query']) && $searchTerms['search_query'] != "") { // Only need the product search table if we have a search query $joinQuery .= "INNER JOIN [|PREFIX|]product_search ps ON (p.productid=ps.productid) "; } else if ($sortField == "score") { // If we don't, we better make sure we're not sorting by score $sortField = "p.prodname"; $sortOrder = "ASC"; } $joinQuery .= "LEFT JOIN [|PREFIX|]product_images pi ON (p.productid=pi.imageprodid AND pi.imageisthumb=1) "; $queryWhere[] = "p.prodvisible='1'"; // Add in the group category restrictions $permissionSql = GetProdCustomerGroupPermissionsSQL(null, false); if($permissionSql) { $queryWhere[] = $permissionSql; } // Do we need to filter on brand? if (isset($searchTerms['brand']) && $searchTerms['brand'] != "") { $brand_id = (int)$searchTerms['brand']; $queryWhere[] = "p.prodbrandid='" . $GLOBALS['ISC_CLASS_DB']->Quote($brand_id) . "'"; } // Do we need to filter on price? if (isset($searchTerms['price'])) { $queryWhere[] = "p.prodcalculatedprice='".$GLOBALS['ISC_CLASS_DB']->Quote($searchTerms['price'])."'"; } else { if (isset($searchTerms['price_from']) && is_numeric($searchTerms['price_from'])) { $queryWhere[] = "p.prodcalculatedprice >= '".$GLOBALS['ISC_CLASS_DB']->Quote($searchTerms['price_from'])."'"; } if (isset($searchTerms['price_to']) && is_numeric($searchTerms['price_to'])) { $queryWhere[] = "p.prodcalculatedprice <= '".$GLOBALS['ISC_CLASS_DB']->Quote($searchTerms['price_to'])."'"; } } // Do we need to filter on rating? if (isset($searchTerms['rating'])) { $queryWhere[] = "FLOOR(p.prodratingtotal/p.prodnumratings) = '".(int)$searchTerms['rating']."'"; } else { if (isset($searchTerms['rating_from']) && is_numeric($searchTerms['rating_from'])) { $queryWhere[] = "FLOOR(p.prodratingtotal/p.prodnumratings) >= '".(int)$searchTerms['rating_from']."'"; } if (isset($searchTerms['rating_to']) && is_numeric($searchTerms['rating_to'])) { $queryWhere[] = "FLOOR(p.prodratingtotal/p.prodnumratings) <= '".(int)$searchTerms['rating_to']."'"; } } // Do we need to filter on featured? if (isset($searchTerms['featured']) && $searchTerms['featured'] != "") { $featured = (int)$searchTerms['featured']; if ($featured == 1) { $queryWhere[] = "p.prodfeatured=1"; } else { $queryWhere[] = "p.prodfeatured=0"; } } // Do we need to filter on free shipping? if (isset($searchTerms['shipping']) && $searchTerms['shipping'] != "") { $shipping = (int)$searchTerms['shipping']; if ($shipping == 1) { $queryWhere[] = "p.prodfreeshipping='1' "; } else { $queryWhere[] = "p.prodfreeshipping='0' "; } } // Do we need to filter only products we have in stock? if (isset($searchTerms['instock']) && $searchTerms['instock'] != "") { $stock = (int)$searchTerms['instock']; if ($stock == 1) { $queryWhere[] = "(p.prodcurrentinv>0 or p.prodinvtrack=0) "; } } if (isset($searchTerms['search_query']) && $searchTerms['search_query'] != "") { $termQuery = "(" . $GLOBALS['ISC_CLASS_DB']->FullText($fulltext_fields, $searchTerms['search_query'], true); $termQuery .= "OR ps.prodname like '%" . $GLOBALS['ISC_CLASS_DB']->Quote($searchTerms['search_query']) . "%' "; $termQuery .= "OR ps.proddesc like '%" . $GLOBALS['ISC_CLASS_DB']->Quote($searchTerms['search_query']) . "%' "; $termQuery .= "OR ps.prodsearchkeywords like '%" . $GLOBALS['ISC_CLASS_DB']->Quote($searchTerms['search_query']) . "%' "; $termQuery .= "OR ps.prodcode = '" . $GLOBALS['ISC_CLASS_DB']->Quote($searchTerms['search_query']) . "') "; $queryWhere[] = $termQuery; } if (!is_array($sortField)) { $sortField = array($sortField); } if (!is_array($sortOrder)) { $sortOrder = array($sortOrder); } $sortField = array_filter($sortField); $sortOrder = array_filter($sortOrder); if (count($sortOrder) < count($sortField)) { $missing = count($sortField) - count($sortOrder); $sortOrder += array_fill(count($sortOrder), $missing, 'desc'); } else if (count($sortOrder) > count($sortField)) { $sortOrder = array_slice($sortOrder, 0, count($sortField)); } if (!empty($sortField)) { $orderBy = array(); $sortField = array_values($sortField); $sortOrder = array_values($sortOrder); foreach ($sortField as $key => $field) { $orderBy[] = $field . ' ' . $sortOrder[$key]; } $orderBy = ' ORDER BY ' . implode(',', $orderBy); } else { $orderBy = ''; } $query = " SELECT ".$fields." FROM ".$fromTable." ".$joinQuery." WHERE 1=1 AND ".implode(' AND ', $queryWhere).$orderBy; $countQuery = " SELECT COUNT(p.productid) FROM ".$fromTable." ".$joinQuery." WHERE 1=1 AND ".implode(' AND ', $queryWhere); return array( 'query' => $query, 'countQuery' => $countQuery ); }
/** * Search for products * * Method will search for all the products and return an array of product records records * * @access public * @param array $searchQuery The search query array. Currently will only understand the 'search_query' option * @param int &$totalAmount The referenced variable to store in the total amount of the result * @param int $start The optional start position of the result total. Default is 0 * @param int $limit The optional limit position of the result total. Default is -1 (no limit) * @param string $sortBy The optional order by. Default is GetConfig("SearchDefaultProductSort") * @return array The array result set on success, FALSE on error */ static public function searchForItems($searchQuery, &$totalAmount, $start=0, $limit=-1, $sortBy="") { if (trim($sortBy) == "") { $sortBy = GetConfig("SearchDefaultProductSort"); } if (!is_array($searchQuery)) { return false; } $totalAmount = 0; if (!is_array($searchQuery) || empty($searchQuery)) { return false; } $fullTextFields = array("ps.prodname", "ps.prodcode", "ps.proddesc", "ps.prodsearchkeywords"); $products = array(); $query = "SELECT SQL_CALC_FOUND_ROWS p.*, FLOOR(p.prodratingtotal/p.prodnumratings) AS prodavgrating, " . GetProdCustomerGroupPriceSQL() . ", pi.* "; if (isset($searchQuery["search_query"]) && trim($searchQuery["search_query"]) !== "") { $query .= ", (IF(p.prodname='" . $GLOBALS["ISC_CLASS_DB"]->Quote($searchQuery["search_query"]) . "', 10000, 0) + IF(p.prodcode='" . $GLOBALS["ISC_CLASS_DB"]->Quote($searchQuery["search_query"]) . "', 10000, 0) + ((" . $GLOBALS["ISC_CLASS_DB"]->FullText(array("ps.prodname"), $searchQuery["search_query"], false) . ") * 10) + " . $GLOBALS["ISC_CLASS_DB"]->FullText($fullTextFields, $searchQuery["search_query"], false) . ") AS score "; } $query .= " FROM [|PREFIX|]products p LEFT JOIN [|PREFIX|]product_images pi ON (p.productid = pi.imageprodid AND pi.imageisthumb = 1) "; // Sorting or filtering by price. Need to join the tax pricing table if(!empty($searchQuery['price']) || !empty($searchQuery['price_from']) || !empty($searchQuery['price_to']) || $sortBy == 'priceasc' || $sortBy == 'pricedesc') { $priceColumn = 'tp.calculated_price'; // Showing prices ex tax, so the tax zone ID = 0 if(getConfig('taxDefaultTaxDisplayCatalog') == TAX_PRICES_DISPLAY_EXCLUSIVE) { $taxZone = 0; } // Showing prices inc tax, so we need to fetch the applicable tax zone else { $taxZone = getClass('ISC_TAX')->determineTaxZone(); } $query .= ' JOIN [|PREFIX|]product_tax_pricing tp ON ( tp.price_reference=p.prodcalculatedprice AND tp.tax_zone_id='.$taxZone.' AND tp.tax_class_id=p.tax_class_id ) '; } else { $priceColumn = 'p.prodcalculatedprice'; } if (isset($searchQuery["categoryid"])) { $searchQuery["category"] = array($searchQuery["categoryid"]); } $searchTerms = $GLOBALS['ISC_CLASS_SEARCH']->readSearchSession(); $categorySearch = false; $categoryIds = array(); $nestedset = new ISC_NESTEDSET_CATEGORIES; if (isset($searchQuery["category"]) && is_array($searchQuery["category"])) { foreach ($searchQuery["category"] as $categoryId) { // All categories were selected, so don"t continue if (!isId($categoryId)) { $categorySearch = false; break; } $categoryIds[] = (int)$categoryId; // If searching sub categories automatically, fetch & tack them on if (isset($searchQuery["searchsubs"]) && $searchQuery["searchsubs"] == "ON") { foreach ($nestedset->getTree(array('categoryid'), $categoryId) as $childCategory) { $categoryIds[] = (int)$childCategory['categoryid']; } unset($childCategory); } } $categoryIds = array_unique($categoryIds); if (!empty($categoryIds)) { $categorySearch = true; } } if ($categorySearch == true) { $query .= " INNER JOIN [|PREFIX|]categoryassociations a ON a.productid = p.productid AND a.categoryid IN (" . implode(",", $categoryIds) . ") "; } if (isset($searchQuery["search_query"]) && trim($searchQuery["search_query"]) !== "") { $query .= " INNER JOIN [|PREFIX|]product_search ps ON p.productid = ps.productid "; } $query .= " WHERE p.prodvisible = 1 " . GetProdCustomerGroupPermissionsSQL(); // Do we need to filter on brand? if (isset($searchQuery["brand"]) && isId($searchQuery["brand"])) { $query .= " AND p.prodbrandid = " . (int)$searchQuery["brand"]; } // Do we need to filter on price? if (isset($searchQuery["price"]) && is_numeric($searchQuery["price"])) { $query .= " AND ".$priceColumn." ='" . $GLOBALS["ISC_CLASS_DB"]->Quote($searchTerms["price"]) . "'"; } else { if (isset($searchQuery["price_from"]) && is_numeric($searchQuery["price_from"])) { $query .= " AND ".$priceColumn." >= '" . $GLOBALS["ISC_CLASS_DB"]->Quote($searchQuery["price_from"]) . "'"; } if (isset($searchQuery["price_to"]) && is_numeric($searchQuery["price_to"])) { $query .= " AND ".$priceColumn." <= '" . $GLOBALS["ISC_CLASS_DB"]->Quote($searchQuery["price_to"]) . "'"; } } // Do we need to filter on rating? if (isset($searchQuery["rating"])) { $query .= " AND FLOOR(p.prodratingtotal/p.prodnumratings) = " . (int)$searchQuery["rating"]; } else { if (isset($searchQuery["rating_from"]) && is_numeric($searchQuery["rating_from"])) { $query .= " AND FLOOR(p.prodratingtotal/p.prodnumratings) >= " . (int)$searchQuery["rating_from"]; } if (isset($searchQuery["rating_to"]) && is_numeric($searchQuery["rating_to"])) { $query .= " AND FLOOR(p.prodratingtotal/p.prodnumratings) <= " . (int)$searchQuery["rating_to"]; } } // Do we need to filter on featured? if (isset($searchQuery["featured"]) && is_numeric($searchQuery["featured"])) { if ((int)$searchQuery["featured"] == 1) { $query .= " AND p.prodfeatured = 1 "; } else { $query .= " AND p.prodfeatured = 0 "; } } // Do we need to filter on free shipping? if (isset($searchQuery["shipping"]) && is_numeric($searchQuery["shipping"])) { if ((int)$searchQuery["shipping"] == 1) { $query .= " AND p.prodfreeshipping = 1 "; } else { $query .= " AND p.prodfreeshipping = 0 "; } } // Do we need to filter only products we have in stock? if (isset($searchQuery["instock"]) && is_numeric($searchQuery["instock"])) { if ((int)$searchQuery["instock"] == 1) { $query .= " AND (p.prodcurrentinv > 0 OR p.prodinvtrack = 0) "; } } if (isset($searchQuery["search_query"]) && trim($searchQuery["search_query"]) !== "") { $searchPart = array(); if (GetConfig("SearchOptimisation") == "fulltext" || GetConfig("SearchOptimisation") == "both") { $searchPart[] = $GLOBALS["ISC_CLASS_DB"]->FullText($fullTextFields, $searchQuery["search_query"], true); } if (GetConfig("SearchOptimisation") == "like" || GetConfig("SearchOptimisation") == "both") { $searchPart[] = "p.prodname LIKE '%" . $GLOBALS["ISC_CLASS_DB"]->Quote($searchQuery["search_query"]) . "%'"; $searchPart[] = "p.proddesc LIKE '%" . $GLOBALS["ISC_CLASS_DB"]->Quote($searchQuery["search_query"]) . "%'"; $searchPart[] = "p.prodsearchkeywords LIKE '%" . $GLOBALS["ISC_CLASS_DB"]->Quote($searchQuery["search_query"]) . "%'"; } $query .= " AND (ps.prodcode = '" . $GLOBALS["ISC_CLASS_DB"]->Quote($searchQuery["search_query"]) . "' OR TRUE) "; $query .= " AND (" . implode(" OR ", $searchPart) . ") "; } $orderBy = ""; switch (isc_strtolower($sortBy)) { case "relevance": if (isset($searchQuery["search_query"]) && trim($searchQuery["search_query"]) !== "") { $orderBy = "score DESC"; } break; case "featured": $orderBy = "p.prodfeatured DESC"; break; case "newest": $orderBy = "p.productid DESC"; break; case "bestselling": $orderBy = "p.prodnumsold DESC"; break; case "alphaasc": $orderBy = "p.prodname ASC"; break; case "alphadesc": $orderBy = "p.prodname DESC"; break; case "avgcustomerreview": $orderBy = "prodavgrating DESC"; break; case "priceasc": $orderBy = $priceColumn.' ASC'; break; case "pricedesc": $orderBy = $priceColumn.' DESC'; break; } if (trim($orderBy) !== "") { $query .= " ORDER BY " . $orderBy; } else { $query .= " ORDER BY p.productid DESC"; } if (is_numeric($limit) && $limit > 0) { if (is_numeric($start) && $start > 0) { $query .= " LIMIT " . (int)$start . "," . (int)$limit; } else { $query .= " LIMIT " . (int)$limit; } } $result = $GLOBALS["ISC_CLASS_DB"]->Query($query); $row = $GLOBALS["ISC_CLASS_DB"]->Fetch($result); if (!$row) { return array(); } $totalAmount = $GLOBALS["ISC_CLASS_DB"]->FetchOne("SELECT FOUND_ROWS()"); $products[$row["productid"]] = $row; while ($row = $GLOBALS["ISC_CLASS_DB"]->Fetch($result)) { $products[$row["productid"]] = $row; } return $products; }
public function rebuild_categories_nset() { $nested = new ISC_NESTEDSET_CATEGORIES(); return $nested->rebuildTree(); }