setMainTable('categories'); $this->addvalidOrderingFieldName(self::$_validOrderingFields); $toCheck = VmConfig::get('browse_cat_orderby_field','category_name'); if(!in_array($toCheck, $this->_validOrderingFieldName)){ $toCheck = 'category_name'; } $this->_selectedOrdering = $toCheck; $this->_selectedOrderingDir = VmConfig::get('cat_brws_orderby_dir', 'ASC'); $this->setToggleName('shared'); self::$_optimisedCatSql = VmConfig::get('optimisedCatSql', true); if(VmConfig::get('UseCachegetChildCategoryList',true)){ self::$cache = VmConfig::getCache('com_virtuemart_cats',''); $cachedCats = self::$cache->get('com_virtuemart_cats'); if($cachedCats){ self::$cats = $cachedCats; } } self::$xrefTableMedias = new TableCategory_medias($this->_db); self::$sdebug = (int)VmConfig::get('debug_Sql',0); } public function checkIfCached($virtuemart_category_id,$childs=TRUE){ $childs = (int)$childs; return !empty($this->_cache[$virtuemart_category_id][(int)$childs][VmLanguage::$currLangTag]); } /** * Retrieve the detail record for the current $id if the data has not already been loaded. * * @author RickG, jseros, Max Milbers */ public function getCategory($virtuemart_category_id=null, $childs=TRUE, $fe = true){ //if(!empty($virtuemart_category_id)) $this->_id = (int)$virtuemart_category_id; if(isset($virtuemart_category_id)){ $this->_id = $this->setId($virtuemart_category_id); } else if(empty($this->_id)){ $this->setIdByRequest(); } $childs = (int)$childs; //vmdebug('getCategory '.$this->_id.' '.$childs); if (isset($this->_cache[$this->_id][$childs][VmLanguage::$currLangTag])) { //vmdebug('Found cached cat '.$this->_id); return clone($this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]); } else { if($childs and !empty($this->_cache[$this->_id][0][VmLanguage::$currLangTag])){ $this->_cache[$this->_id][1][VmLanguage::$currLangTag] = clone($this->_cache[$this->_id][0][VmLanguage::$currLangTag]); //vmdebug('Found cached cat, but without children'); } else if(!$childs and !empty($this->_cache[$this->_id][1][VmLanguage::$currLangTag])){ $t = clone($this->_cache[$this->_id][1][VmLanguage::$currLangTag]); $t->children = false; $t->haschildren = null; $t->productcount = false; //$t->parents = false; $this->_cache[$this->_id][0][VmLanguage::$currLangTag] = $t; //vmdebug('Use already loaded category with children '.$this->_id); return $t; } else { $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag] = $this->getTable('categories'); if(!empty($this->_id)){ $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->_langTag = VmConfig::$vmlang; $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->load($this->_id); $xrefTable = $this->getTable('category_medias'); $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->virtuemart_media_id = $xrefTable->load((int)$this->_id); } else { $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->virtuemart_media_id = false; } //Fallbacks $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->categorytemplate = $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->category_template; $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->categorylayout = $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->category_layout; $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->productlayout = $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->category_product_layout; } $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->children = false; $updateCategory = false; if(!isset($this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->has_children)){ $updateCategory = true; } if(!isset($this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->has_children) or empty($virtuemart_category_id)){ $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->has_children = 1; } $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->haschildren = $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->has_children; $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->productcount = 0; $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->parents = null; if($childs){ //$this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->haschildren = $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->has_children; /* Get children if they exist */ if ($this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->has_children) { //$this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->children = $this->getCategories( true, $this->_id ); if(empty($virtuemart_category_id) and empty($this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->virtuemart_vendor_id)){ $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->virtuemart_vendor_id = 1; } $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->children = $this->getChildCategoryList($this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->virtuemart_vendor_id, $this->_id ); } } /* Get the product count if(!isset($this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->productcount)) $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->productcount = $this->countProducts($this->_id); */ if($fe){ /* Get parent for breadcrumb */ $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->parents = $this->getParentsList($this->_id); } if($updateCategory and !empty($this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]->virtuemart_category_id)){ self::updateCategory($this->_cache[$this->_id][$childs][VmLanguage::$currLangTag],$this->_db); } } return $this->_cache[$this->_id][$childs][VmLanguage::$currLangTag]; } /** * Get the list of child categories for a given category, is cached * * @param int $virtuemart_category_id Category id to check for child categories * @return object List of objects containing the child categories * */ public function getChildCategoryList($vendorId, $virtuemart_category_id,$selectedOrdering = null, $orderDir = null, $media = true) { if($selectedOrdering===null){ /*if($useCache){ $selectedOrdering = $this->_selectedOrdering; } else {*/ $selectedOrdering = VmConfig::get('browse_cat_orderby_field','category_name'); //} } if(trim($selectedOrdering) == 'c.ordering'){ $selectedOrdering = 'c.ordering,category_name'; } if(empty($selectedOrdering) or !in_array($selectedOrdering, self::$_validOrderingFields)){ $selectedOrdering = 'c.ordering,category_name'; } if($orderDir===null){ /*if($useCache){ $orderDir = $this->_selectedOrderingDir; } else {*/ $orderDir = VmConfig::get('cat_brws_orderby_dir', 'ASC'); //} } $validOrderingDir = array('ASC','DESC'); if(!in_array(strtoupper($orderDir), $validOrderingDir)){ $orderDir = 'ASC'; } $onlyPublished = true; if(!VmConfig::isSite() and (vmAccess::manager(array('category','product','product.edit'),0, 0)) ){ $onlyPublished = false; } //$key = (int)$vendorId.'_'.(int)$virtuemart_category_id.$selectedOrdering.$orderDir.VmLanguage::$currLangTag ; //We have here our internal key to preven calling of the cache //if (! array_key_exists ($key,$_childCategoryList)){ $childList = self::getChildCategoryListObject($vendorId, $virtuemart_category_id, -1, $onlyPublished, $media, '', $selectedOrdering, $orderDir); if(self::$cache!==null and self::$updateCache) { self::$cache->store(self::$cats, 'com_virtuemart_cats'); self::$updateCache = false; } return $childList; } /** * @deprecated use getChildCategoryListObject instead * @return array|mixed */ static public function getChildCategoryListObjectByCachedOption($vendorId, $virtuemart_category_id, $onlyPublished, $media, $keyword, $selectedOrdering, $orderDir, $limitStart = 0, $limit = 0){ vmSetStartTime('com_virtuemart_cat_childs'); self::$cats = VirtueMartModelCategory::getChildCategoryListObject($vendorId, $virtuemart_category_id, -1, $onlyPublished, $media, $keyword, $selectedOrdering, $orderDir, 0, 0); if(self::$cache!==null and self::$updateCache) { self::$cache->store(self::$cats, 'com_virtuemart_cats'); self::$updateCache = false; } vmTime('Deprecated getChildCategoryListObjectByCachedOption used, use getChildCategoryListObject instead '.$virtuemart_category_id,'com_virtuemart_cat_childs'); return self::$cats; } /** * Be aware we need the lang to assure that the cache works properly. The cache needs all parameters * in the function call to use the right hash * * @author Max Milbers * @param $vendorId * @param $category_parent_id Loads the children of the given parent * @param $childId loads a single category * @param null $selectedOrdering * @param null $orderDir * @param $lang * @return mixed */ static public function getChildCategoryListObject($vendorId, $category_parent_id = 0, $level = -1, $onlyPublished = true, $media = true, $keyword = '', $selectedOrdering = null, $orderDir = null, $limitStart = 0, $limit = 0) { vmStartTimer('getChildCategoryListObject'); $hP = (int)$vendorId.'_'.(int)$category_parent_id.'_'.str_replace(' ','',$selectedOrdering).(int)$onlyPublished.$orderDir.$limitStart.'_'.$keyword.'_'.$limit.VmLanguage::$currLangTag; $h = $hP.(int)$media; if ( isset(self::$cats[$h])){ //vmdebug('getChildCategoryListObject return cached '.$h); return self::$cats[$h]; } else { //vmdebug('getChildCategoryListObject did not find, cached '.$h); if($media) { $hMedia = $hP . 0; if (isset(self::$cats[$hMedia])) { vmdebug('getChildCategoryListObject return category ADD requested media, but cached ' . $hMedia); //$xrefTableMedias = new TableCategory_medias($db); foreach (self::$cats[$hMedia] as $i => $child) { if (!self::$_optimisedCatSql) { $child->has_medias = 1; } if (self::$_optimisedCatSql and !isset($child->has_medias) ){ $db = JFactory::getDbo(); self::updateCategory($child, $db); } if ($child->has_medias) { self::$xrefTableMedias->_loaded = false; self::$xrefTableMedias->virtuemart_category_id = 0; self::$xrefTableMedias->virtuemart_media_id = array(); self::$xrefTableMedias->ordering = 0; $child->virtuemart_media_id = self::$xrefTableMedias->load($child->virtuemart_category_id); } else { $child->virtuemart_media_id = false; } self::$cats[$h][$i] = $child; } if (!isset(self::$cats[$h])) { self::$cats[$h] = array(); } return self::$cats[$h]; } } else { $hMedia = $hP . 1; if (isset(self::$cats[$hMedia])) { vmdebug('getChildCategoryListObject return category with media unrequested, but cached ' . $hMedia); return self::$cats[$hMedia]; } } } self::$updateCache = true; $langFields = array('category_name','category_description','metadesc','metakey','customtitle','slug'); $join = ' FROM #__virtuemart_categories as c '.implode(' ',self::joinLangTables('#__virtuemart_categories','c','virtuemart_category_id')); if(self::$_optimisedCatSql){ $select = ' c.category_parent_id, c.`ordering`'; } else { $select = ' cx.category_parent_id, cx.`ordering`'; $join .= ' LEFT JOIN `#__virtuemart_category_categories` as cx on c.`virtuemart_category_id` = cx.`category_child_id` '; } $select .= ', c.virtuemart_category_id, c.virtuemart_vendor_id, c.category_template, c.category_layout, c.category_product_layout, c.products_per_row, c.limit_list_step, c.limit_list_initial, c.hits, c.cat_params, c.metarobot, c.metaauthor, c.shared, c.`published`, c.has_children, c.has_medias, '.implode(', ',self::joinLangSelectFields($langFields)); $where = array(); if ( empty( $keyword )) { if(self::$_optimisedCatSql){ $tprefx = 'c'; } else { $tprefx = 'cx'; } if($category_parent_id>=0){ $where[]= ' ('.$tprefx.'.`category_parent_id` = ' . (int)$category_parent_id .')'; } } if(VmConfig::get('multix')!='none'){ if(empty($vendorId)){ //$where[]= ' c.`shared` = 1 ' ; } else { $where[]= ' (c.`virtuemart_vendor_id` = ' . (int)$vendorId .' OR c.`shared` = 1) '; } } if($onlyPublished) { $where[]= ' c.`published` = 1 '; } /*if(!empty($where)){ $query .= 'WHERE '.implode(' AND ',$where); }/*/ $whereOr = array(); if( !empty( $keyword ) ) { $db = JFactory::getDBO(); $keyword = $db->escape( $keyword, true ); $keyword = '"%' .str_replace(array(' ','-'),'%', $keyword). '%"'; //$keyword = $db->escape( $keyword, true ); $fields = self::joinLangLikeFields($langFields,$keyword); $whereOr = array_merge($whereOr, $fields); } $whereString = ''; if (count($where) > 0 or count($whereOr)){ $whereString = ' WHERE '; if (count($where) > 0){ $whereString .= implode(' AND ', $where); if (count($whereOr) > 0){ $whereString .= ' AND '; } } if (count($whereOr) > 0){ $whereString .= '('.implode(' OR ', $whereOr).')'; } } else { $whereString = ''; } $query = 'SELECT '.$select.' '.$join.' '.$whereString; if(!empty($selectedOrdering)) { $query .= ' ORDER BY '.$selectedOrdering.' '.$orderDir; } if(self::$_withLimit){ if($limitStart and $limit){ $query .= ' LIMIT '.$limitStart.','.$limit; } else if($limit){ $query .= ' LIMIT '.$limit; } } $db = JFactory::getDBO(); $db->setQuery( $query ); $childList = $db->loadObjectList('virtuemart_category_id'); if(self::$sdebug) vmdebug('getChildCategoryListObject',$query); if(!empty($childList)){ if($media){ foreach($childList as &$child){ if(!self::$_optimisedCatSql){ $child->has_medias = 1; $child->has_children = 1; } if(self::$_optimisedCatSql and !empty($child->virtuemart_category_id) and (!isset($child->has_children) or !isset($child->has_medias) or !isset($child->category_parent_id)) ){ self::updateCategory($child,$db); } if($child->has_medias){ self::$xrefTableMedias->_loaded = false; self::$xrefTableMedias->virtuemart_category_id = 0; self::$xrefTableMedias->virtuemart_media_id = array(); self::$xrefTableMedias->ordering = 0; $child->virtuemart_media_id = self::$xrefTableMedias->load($child->virtuemart_category_id); } else { $child->virtuemart_media_id = false; } } } } //$count = count($childList); //vmdebug('getChildCategoryListObject count result '.$query,$count ); self::$cats[$h] = $childList; vmTime('getChildCategoryListObject summed up '.$h,'getChildCategoryListObject',false); return $childList; } /** * Returns the category Tree * @param int $parentId ParentId * @param int $level Level * @param bool $onlyPublished only published * @param string $keyword search keyword * @param string $limitStart limitStart for Pagination * @param string $limit * @param false $tree * @param int $vendorId * @return array|mixed */ public function getCategoryTree($parentId=0, $level = -1, $onlyPublished = true,$keyword = '', $limitStart = '',$limit = '', $tree = false, $vendorId = 0){ $sortedCats = array(); if($limitStart === '' or $limit === ''){ $limits = $this->setPaginationLimits(); if($limitStart === '') $limitStart = $limits[0]; if($limit === '') $limit = $limits[1]; } self::$_withLimit = false; if(empty($parentId)){ $parentId = 0; } if(empty($vendorId)) $vendorId = vmAccess::isSuperVendor(); if($keyword!=''){ //$sortedCats = self::getCategories($onlyPublished, false, false, $keyword); $sortedCats = self::getChildCategoryListObject($vendorId, $parentId, -1, $onlyPublished, true, $keyword, $this->_selectedOrdering, $this->_selectedOrderingDir); //$sortedCats = $this->getChildCategoryListObject( $vendorId, $parentId, false, $onlyPublished, true, $keyword); if(!empty($sortedCats)){ $siblingCount = count($sortedCats); foreach ($sortedCats as $key => &$category) { $category->siblingCount = $siblingCount; } } $this->_total = count($sortedCats); } else { $sortedCats = VirtueMartModelCategory::getCatsTree($tree, $vendorId, $parentId, 10, false, $onlyPublished, $this->_selectedOrdering,$this->_selectedOrderingDir); //vmdebug('My sorted cats '.$parentId,$sortedCats); $this->_total = count($sortedCats); } self::$_withLimit = true; $this->_limitStart = $limitStart; $this->_limit = $limit; $this->getPagination(); if(self::$cache!==null and self::$updateCache){ self::$cache->store(self::$cats, 'com_virtuemart_cats'); self::$updateCache = false; } if(empty($limit)){ //vmdebug('my $sortedCats sliced by NO LIMIT',$sortedCats); return $sortedCats; } else { $sortedCats = array_slice($sortedCats, $limitStart,$limit); return $sortedCats; } } static public $catsTree = null; static public function getCatsTree( $tree = false, $vendorId = 1, $category_parent_id = 0, $maxLevel = 10, $media = false, $onlyPublished = true, $selectedOrdering = 'c.ordering,category_name', $selectedOrderingDir = 'ASC'){ vmSetStartTime('hm'); $hP = (int)$vendorId.'_'.(int)$category_parent_id.'_'.str_replace(' ','',$selectedOrdering).(int)$onlyPublished.$selectedOrderingDir.VmLanguage::$currLangTag; $h = $hP.(int)$media; if ( isset(self::$catsTree[$h])){ //vmdebug('getChildCategoryListObject return cached '.$h); return self::$catsTree[$h]; } self::$_withLimit = false; $allCats = VirtueMartModelCategory::getChildCategoryListObject($vendorId, -1, -1, $onlyPublished, $media, null, $selectedOrdering, $selectedOrderingDir ); //vmdebug('my $allCats',$allCats); $parentList = array(); $myNewList = array(); //reset($allCats); //for( $i=0; $icategory_parent_id == $parentLevelId){ $parentList[$cat->virtuemart_category_id] = $cat; } else { $myNewList[$cat->category_parent_id][$cat->virtuemart_category_id] = $cat; } } //vmdebug('my childList',$myNewList); vmTime('Loading all categories', 'hm'); self::$_withLimit = true; //vmTime('Sorting first loop', 'hm'); $veryNew = array(); $unset = array(); //vmdebug('my $parentList before sortCats',$parentList,$myNewList); self::sortCats($parentLevelId, $parentList, $myNewList, $veryNew, $unset, 0, $tree, $maxLevel); //vmdebug('my sortCats after sortCats',$veryNew); vmTime('sortCats', 'hm'); self::$catsTree[$h] = $veryNew; return $veryNew; } static public function sortCats($parentLevelId, $parentList, $myNewList, &$veryNew, &$unset, $level, $tree = false, $maxlevel = 100) { foreach($parentList as $category_id_ofParent=>$cat){ $cat->level = $level; $veryNew[$category_id_ofParent] = $cat; if($level>$maxlevel){ vmdebug('sortCats max level reached '.$level,$maxlevel); continue; } if(isset($myNewList[$category_id_ofParent]) ){ $childs = $myNewList[$category_id_ofParent]; if($tree){ $cat->childs = $childs; $cat->children = &$cat->childs; foreach($childs as $child){ $unset[] = $child->virtuemart_category_id; } } self::sortCats( $parentLevelId, $childs, $myNewList, $veryNew, $unset, $level + 1, $tree, $maxlevel); } else { //vmdebug('sortCats no children '.$level,$cat->virtuemart_category_id); } //$veryNew[$category_id_ofParent] = $cat; } //vmdebug('my sortCats $veryNew',$veryNew,$unset); if($level == 0 and $tree){ foreach($unset as $virtuemart_category_id){ unset($veryNew[$virtuemart_category_id]); } //vmdebug('my $veryNew',$veryNew); foreach($veryNew as $i=>$cat){ if($cat->category_parent_id!=$parentLevelId){ unset($veryNew[$i]); } } } } /** * Gets the total number of entries per vendor * @author Max Milbers * @return int Total number of entries in the database */ public function getTotal() { if (empty($this->_total)) { $db = JFactory::getDbo(); $vendorId = vmAccess::isSuperVendor(); $venWhere = ''; if(!empty($vendorId)){ $venWhere = ' WHERE virtuemart_vendor_id = '.$vendorId.' '; } $query = 'SELECT `'.$this->_db->escape($this->_idName).'` FROM `'.$this->_db->escape($this->_maintable).'` '.$venWhere;; $db->setQuery( $query ); if(!$db->execute()){ if(empty($this->_maintable)) vmError('Model '.get_class( $this ).' has no maintable set'); $this->_total = 0; } else { $this->_total = $db->getNumRows(); } } return $this->_total; } /** * count the products in a category * * @author Max Milbers * @return array list of categories product is in */ public function countProducts($cat_id=0) { $db = JFactory::getDBO(); $vendorId = 1; if ($cat_id > 0) { $q = 'SELECT count(`p`.virtuemart_product_id) AS total FROM `#__virtuemart_product_categories` as `pc` LEFT JOIN `#__virtuemart_products` as `p` ON `pc`.virtuemart_product_id = `p`.virtuemart_product_id WHERE `pc`.`virtuemart_category_id` = "'.(int)$cat_id.'" AND `p`.`virtuemart_vendor_id` = "'.(int)$vendorId.'" AND `p`.`published` = "1" '; $db->setQuery($q); $count = $db->loadResult(); } else $count=0 ; return $count; } /** * Order any category * * @author jseros * @param int $id category id * @param int $movement movement number * @return bool */ public function orderCategory($id, $movement){ //retrieving the category table object //and loading data $row = $this->getTable('categories'); $row->load($id); $return = $row->move( $movement, 'category_parent_id = "'.(int)$row->category_parent_id.'"' ); self::clearCategoryRelatedCaches(); return $return; } /** * Order category group * * @author jseros * @param array $cats categories to order * @return bool */ public function saveOrder($cats, $order, $filter = NULL){ $total = count( $cats ); $groupings = array(); $row = $this->getTable('categories'); $rowLegacy = $this->getTable('category_categories'); $query = 'SELECT `category_parent_id` FROM `#__virtuemart_categories` c WHERE c.`virtuemart_category_id` = %s'; $db = JFactory::getDBO(); // update ordering values //for( $i=0; $i < $total; $i++ ) { foreach( $order as $id => $ord ) { $row->load( (int)$id ); $db->setQuery( sprintf($query, (int)$id ), 0 ,1 ); $parent = $db->loadObject(); $groupings[] = $parent->category_parent_id; if ($row->ordering != $ord) { $row->ordering = $ord; if (!$row->toggle('ordering',$row->ordering)) { return false; } /*$q = 'UPDATE #__virtuemart_category_categories SET ordering ="'.$row->ordering.'" WHERE category_child_id = "'.$cats[$i].'" '; $this->_db->setQuery($q); $this->_db->execute();*/ } } // execute reorder for each parent group $groupings = array_unique( $groupings ); foreach ($groupings as $group){ $row->fixOrdering('category_parent_id = "'.(int)$group.'"'); $row->synchroniseTableOrdering($group); } self::clearCategoryRelatedCaches(); return true; } /** * Bind the post data to the category table and save it * * @author jseros, Max Milbers * @return int category id stored */ public function store(&$data) { vRequest::vmCheckToken(); if(!vmAccess::manager('category.edit')){ vmWarn('Insufficient permission to store category'); return false; } else if( empty($data['virtuemart_category_id']) and !vmAccess::manager('category.create')){ vmWarn('Insufficient permission to create category'); return false; } $table = $this->getTable('categories'); if ( !array_key_exists ('category_template' , $data ) ){ $data['category_template'] = $data['category_layout'] = $data['category_product_layout'] = '' ; } $data['category_template'] = isset($data['categorytemplate'])? $data['categorytemplate']:null; $data['category_layout'] = isset($data['categorylayout'])? $data['categorylayout']:null; $data['category_product_layout'] = isset($data['productlayout'])? $data['productlayout']:null; if($data['category_parent_id'] == $data['virtuemart_category_id']){ $data['category_parent_id'] = 0; } $data['has_children'] = 0; if(!empty($data['virtuemart_category_id'])){ $data['has_children'] = (int)$this->hasChildren($data['virtuemart_category_id']); } vDispatcher::importVMPlugins('vmcustom'); vDispatcher::trigger('plgVmBeforeStoreCategory',array(&$data, &$table)); $table->bindChecknStore($data); if(!empty($data['virtuemart_category_id'])){ $xdata['category_child_id'] = (int)$data['virtuemart_category_id']; $xdata['category_parent_id'] = empty($data['category_parent_id'])? 0:(int)$data['category_parent_id']; $xdata['ordering'] = empty($data['ordering'])? 0: (int)$data['ordering']; $tableXref = $this->getTable('category_categories'); $tableXref->bindChecknStore($xdata); } // Process the images $mediaModel = VmModel::getModel('Media'); $file_id = $mediaModel->storeMedia($data,'category'); $file_id = empty($file_id)? 0: 1; if($table->has_medias!=$file_id){ $q = 'UPDATE #__virtuemart_categories SET `has_medias`='.$file_id.' WHERE `virtuemart_category_id`='.$data['virtuemart_category_id'].';'; $db = JFactory::getDbo(); $db->setQuery($q); $db->execute(); } self::clearCategoryRelatedCaches(); if(!empty($data['category_parent_id'])){ $q = 'UPDATE #__virtuemart_categories SET `has_children`= 1 WHERE `virtuemart_category_id`='.$data['category_parent_id'].';'; $db = JFactory::getDbo(); $db->setQuery($q); $db->execute(); } vDispatcher::trigger('plgVmAfterStoreCategory',array(&$data, &$table)); return $data['virtuemart_category_id'] ; } /** * Delete all categories selected * * @author jseros * @param array $cids categories to remove * @return boolean if the item remove was successful */ public function remove($cids) { vRequest::vmCheckToken(); if(!vmAccess::manager('category.delete')){ vmWarn('Insufficient permissions to delete category'); return false; } $table = $this->getTable('categories'); foreach($cids as &$cid) { //Update Parent "has_children" $table->load($cid); if($table->category_parent_id){ $has_children = $this->hasChildren($table->category_parent_id); $q = 'UPDATE #__virtuemart_categories SET `has_children`='.(int)$has_children.' WHERE `virtuemart_category_id`='.$table->category_parent_id.';'; $db = JFactory::getDbo(); $db->setQuery($q); $db->execute(); } if (!$table->delete($cid)) { return false; } $db = JFactory::getDbo(); $q = 'SELECT `virtuemart_customfield_id` FROM `#__virtuemart_product_customfields` as pc '; $q .= 'LEFT JOIN `#__virtuemart_customs`as c ON pc.`virtuemart_custom_id` = c.`virtuemart_custom_id` WHERE pc.`customfield_value` = "' . $cid . '" AND `field_type`= "Z"'; $db->setQuery($q); $list = $db->loadColumn(); if ($list) { $listInString = implode(',',$list); //Delete media xref $query = 'DELETE FROM `#__virtuemart_product_customfields` WHERE `virtuemart_customfield_id` IN ('. $listInString .') '; $db->setQuery($query); try { $db->execute(); } catch (Exception $e){ vmError('category remove '.$e->getMessage()); } } vDispatcher::importVMPlugins ('vmcustom'); vDispatcher::trigger ('plgVmOnDeleteCategory', array($cid)); } $cidInString = implode(',',$cids); //Delete media xref $query = 'DELETE FROM `#__virtuemart_category_medias` WHERE `virtuemart_category_id` IN ('. $cidInString .') '; $db->setQuery($query); try { $db->execute(); } catch (Exception $e){ vmError('category_medias remove '.$e->getMessage()); } //deleting product relations $query = 'DELETE FROM `#__virtuemart_product_categories` WHERE `virtuemart_category_id` IN ('. $cidInString .') '; $db->setQuery($query); try { $db->execute(); } catch (Exception $e){ vmError('category_product_categories remove '.$e->getMessage()); } //deleting category relations $query = 'DELETE FROM `#__virtuemart_category_categories` WHERE `category_child_id` IN ('. $cidInString .') '; $db->setQuery($query); try { $db->execute(); } catch (Exception $e){ vmError('category_category_categories remove '.$e->getMessage()); } //updating parent relations $query = 'UPDATE `#__virtuemart_category_categories` SET `category_parent_id` = 0 WHERE `category_parent_id` IN ('. $cidInString .') '; $db->setQuery($query); try { $db->execute(); } catch (Exception $e){ vmError('category_category_categories update '.$e->getMessage()); } self::clearCategoryRelatedCaches(); return true; } static public function clearCategoryRelatedCaches(){ $cache = VmConfig::getCache(); $cache->clean('com_virtuemart_cats'); $cache->clean('com_virtuemart_cats_route'); $cache->clean('com_virtuemart_cats_dropdown'); $cache->clean('mod_virtuemart_product'); $cache->clean('mod_virtuemart_category'); $cache->clean('com_virtuemart_orderby_manus'); vmdebug('Category related caches cleared'); } /** * Checks for children of the category $virtuemart_category_id * * @param int $virtuemart_category_id the category ID to check * @return boolean true when the category has childs, false when not */ static public function hasChildren($virtuemart_category_id, $useXref = false) { static $hasChildrenCache=array(); if(!isset($hasChildrenCache[$virtuemart_category_id])){ $db = JFactory::getDBO(); if(self::$_optimisedCatSql and !$useXref){ $q = 'virtuemart_category_id FROM `#__virtuemart_categories`'; } else { $q = '`category_child_id` FROM `#__virtuemart_category_categories`'; } $db->setQuery('SELECT '. $q .' WHERE `category_parent_id` = "'.(int)$virtuemart_category_id.'"'); $db->execute(); $res = $db->loadResult(); if ($res){ $hasChildrenCache[$virtuemart_category_id] = true; } else { $hasChildrenCache[$virtuemart_category_id] = false; } } return $hasChildrenCache[$virtuemart_category_id]; } /** * Creates a bulleted of the children of this category if they exist * * @todo Add vendor ID * @param int $virtuemart_category_id the category ID to create the list of * @return array containing the child categories */ public function getParentsList($virtuemart_category_id) { static $menuCatid = null; if(!isset($menuCatid)){ $menu = JFactory::getApplication()->getMenu(); $Itemid = vRequest::getInt('Itemid',false); if (empty($Itemid)) { $menuItem = $menu->getActive(); } else { $menuItem = $menu->getItem($Itemid); } $menuCatid = (empty($menuItem->query['virtuemart_category_id'])) ? 0 : $menuItem->query['virtuemart_category_id']; } if ($menuCatid == $virtuemart_category_id) return ; $parents = self::getParents($virtuemart_category_id, $menuCatid); return $parents; } static $parentsList = array(); public static function getParents($virtuemart_category_id, $menuCatid = 0){ /*$hP = (int)$vendorId.'_'.(int)$category_parent_id.'_'.str_replace(' ','',$selectedOrdering).(int)$onlyPublished.$selectedOrderingDir.VmLanguage::$currLangTag; $h = $hP.(int)$media; if ( isset(self::$catsTree[$h])){ vmdebug('getParentsList cached self::$catsTree found'.$h); } else { vmdebug('getParentsList NO cached self::$catsTree found'.$h,self::$catsTree[$h]); }*/ $tCats = self::getCategoryRecurseS($virtuemart_category_id, $menuCatid); if(!$tCats) return false; $parents_id = array_reverse($tCats); $langFields = array('virtuemart_category_id','category_name'); $select = 'SELECT '.implode(', ',self::joinLangSelectFields($langFields)).', published'; $joins = 'FROM `#__virtuemart_categories` as c '.implode(' ',self::joinLangTables('#__virtuemart_categories','c','virtuemart_category_id')); $where = 'WHERE '.implode(', ',self::joinLangSelectFields(array('virtuemart_category_id'),false)).' = '; $q = $select.' '.$joins.' '.$where; $db = JFactory::getDBO(); foreach ($parents_id as $id ) { if(isset(self::$parentsList[VmLanguage::$currLangTag][$id])){ $parents[] = self::$parentsList[VmLanguage::$currLangTag][$id]; vmdebug('getParentsList found cached',$id); } else { $db->setQuery($q.(int)$id); try { self::$parentsList[VmLanguage::$currLangTag][$id]=$db->loadObject(); $parents[] = self::$parentsList[VmLanguage::$currLangTag][$id]; } catch (Exception $e){ vmError('category getParentsList '.$e->getMessage()); if(vmEcho::$echoAdmin){ vmWarn('category with id '.(int)$id.' is missing the main language '); } } } } return $parents; } /** @deprecated */ public $categoryRecursed = 0; public static $categoryRecursedS = 0; public function getCategoryRecurse($virtuemart_category_id,$catMenuId,$idsArr=true ) { return self::getCategoryRecurseS($virtuemart_category_id, $catMenuId); } static public function getCategoryRecurseS($virtuemart_category_id, $catMenuId, $useXref = false, $forRouting = true, &$idsArr=null) { static $resId = array(); if(empty($virtuemart_category_id)) return array(); if($idsArr===null){ $idsArr = array(); self::$categoryRecursedS = 0; } else if(self::$categoryRecursedS>10){ vmWarn('Stopped getCategoryRecurse after 10 rekursions'); return false; } $hash = $virtuemart_category_id.'c'.$catMenuId; if(isset($resId[$hash])){ $ids = $resId[$hash]; } else if (!empty($virtuemart_category_id)){ $db = JFactory::getDBO(); if(self::$_optimisedCatSql and !$useXref){ $q = "SELECT `virtuemart_category_id` AS `child`, `category_parent_id` AS `parent` FROM #__virtuemart_categories WHERE `virtuemart_category_id`= ".(int)$virtuemart_category_id; } else { $q = "SELECT `category_child_id` AS `child`, `category_parent_id` AS `parent` FROM #__virtuemart_category_categories AS `xref` WHERE `xref`.`category_child_id`= ".(int)$virtuemart_category_id; } $db->setQuery($q); $ids = $resId[$hash] = $db->loadObject(); } if (isset ($ids->child) ) { if($forRouting){ $idsArr[] = $ids->child; if($ids->parent != 0 and $catMenuId != $virtuemart_category_id and $catMenuId != $ids->parent) { self::$categoryRecursedS++; self::getCategoryRecurseS($ids->parent, $catMenuId, $useXref, $forRouting, $idsArr); } } else { if(!empty($ids->parent)){ $idsArr[] = $ids->child; //vmdebug('getCategoryRecurseS There is a parent ',$ids,$idsArr); self::$categoryRecursedS++; self::getCategoryRecurseS($ids->parent, $catMenuId, $useXref, $forRouting, $idsArr); } } } else { vmdebug('getCategoryRecurseS Something went wrong my parent ',$ids); } return $idsArr ; } function toggle($field,$val = NULL, $cidname = 0,$tablename = 0, $view = false ) { $result = parent::toggle($field,$val, $cidname, $tablename, $view ); self::clearCategoryRelatedCaches(); return $result; } static function updateCategories(){ $db = JFactory::getDbo(); $q = 'SELECT * FROM #__virtuemart_categories WHERE has_children is NULL OR has_medias is NULL OR category_parent_id is NULL OR `ordering` is NULL'; $db->setQuery($q); $cats = $db->loadObjectlist(); foreach($cats as $cat){ self::updateCategory($cat, $db); } } static function updateCategory(&$cat, $db){ if(empty($cat) or $cat->virtuemart_category_id<=0) { vmTrace('updateCategory empty $cat'); return; } $set = array(); if($cat->has_children === null){ $cat->has_children = self::hasChildren($cat->virtuemart_category_id, true); $set[] = '`has_children`='.(int)$cat->has_children; } if($cat->category_parent_id === null or $cat->ordering === null){ /*if($optimised and self::$_optimisedCatSql){ $table = '#__virtuemart_category'; $whereField = 'virtuemart_category_id'; } else {*/ $table = '#__virtuemart_category_categories'; $whereField = 'category_child_id'; //} $q = 'SELECT `category_parent_id`, `ordering` FROM '.$table.' WHERE `'.$whereField.'` = "'.(int)$cat->virtuemart_category_id.'" ;'; $db->setQuery($q); $xrefRes = $db->loadAssoc(); if(!isset($xrefRes['category_parent_id'])){ //vmEcho::$echoDebug = 1; vmTrace('updateCategory'); vmdebug('updateCategory '.$q,$xrefRes); } else { $cat->category_parent_id = (int)$xrefRes['category_parent_id']; $cat->ordering = (int)$xrefRes['ordering']; $set[] = '`category_parent_id`='.$cat->category_parent_id; $set[] = '`ordering`='.$cat->ordering; } } if($cat->has_medias === null){ $q = 'SELECT count(*) FROM #__virtuemart_category_medias WHERE virtuemart_category_id = "'.$cat->virtuemart_category_id.'" ;'; $db->setQuery($q); $cat->has_medias = $db->loadResult(); $set[] = '`has_medias`='.(int)$cat->has_medias; } if(count($set)>0) { $q = 'UPDATE #__virtuemart_categories SET '.implode(', ',$set).' WHERE `virtuemart_category_id`='.$cat->virtuemart_category_id.';'; $db->setQuery($q); $db->execute(); vmdebug('Update query executed', $q); } } /** * @deprecated use getChildCategoryListObject instead. * @param bool $onlyPublished * @param bool $parentId * @param bool $childId * @param string $keyword * @param bool $vendorId * @return mixed */ public function getCategories($onlyPublished = true, $parentId = false, $childId = false, $keyword = "", $vendorId = false) { //return $this->getChildCategoryListObject( $vendorId, $parentId, $childId, $onlyPublished, true, $keyword); static $cats = array(); $select = ' c.`virtuemart_category_id`, c.`ordering`, c.`published`, c.`category_parent_id`, c.`shared`, c.`has_children` '; $joins = ' FROM `#__virtuemart_categories` as c '; $where = array(); if( $onlyPublished ) { $where[] = " c.`published` = 1 "; } if( $parentId !== false ){ $where[] = ' c.`category_parent_id` = '. (int)$parentId; } if( $childId !== false ){ $where[] = ' c.`category_child_id` = '. (int)$childId; } if($vendorId===false){ $vendorId = vmAccess::isSuperVendor(); } if($vendorId!=1){ if(VmConfig::isSite() and $vendorId==0){ $vendorId = 1; } $where[] = ' (c.`virtuemart_vendor_id` = "'. (int)$vendorId. '" OR c.`shared` = "1") '; } $langFields = array('category_description','category_name'); $select .= ', '.implode(', ',self::joinLangSelectFields($langFields)); $joins .= implode(' ',self::joinLangTables($this->_maintable,'c','virtuemart_category_id')); $joins .= ' LEFT JOIN `#__virtuemart_category_categories` AS cx ON c.`virtuemart_category_id` = cx.`category_child_id`'; $whereOr = array(); if( !empty( $keyword ) ) { $db = JFactory::getDBO(); $keyword = $db->escape( $keyword, true ); $keyword = '"%' .str_replace(array(' ','-'),'%', $keyword). '%"'; //$keyword = $db->escape( $keyword, true ); $fields = self::joinLangLikeFields($langFields,$keyword); $whereOr = array_merge($whereOr, $fields); } $whereString = ''; if (count($where) > 0 or count($whereOr)){ $whereString = ' WHERE '; if (count($where) > 0){ $whereString .= implode(' AND ', $where); if (count($whereOr) > 0){ $whereString .= ' AND '; } } if (count($whereOr) > 0){ $whereString .= '('.implode(' OR ', $whereOr).')'; } } else { $whereString = 'WHERE 1 '; } if(trim($this->_selectedOrdering) == 'c.ordering'){ $this->_selectedOrdering = 'c.ordering, category_name'; } $ordering = $this->_getOrdering(); $hash = crc32($keyword.'.'.(int)$parentId.VmLanguage::$currLangTag.(int)$childId.$this->_selectedOrderingDir.(int)$vendorId.$this->_selectedOrdering); if(!isset($cats[$hash])){ $cats[$hash] = $this->_category_tree = $this->exeSortSearchListQuery(0,$select,$joins,$whereString,'GROUP BY virtuemart_category_id',$ordering ); $this->_total = count($cats[$hash]); } return $cats[$hash]; } /** * @deprecated */ static public function rekurseCategories($vendorId, $parentId, &$cats, $level = 2, $limitStart = 0, $limit = 0, $onlyPublished = true, $keyword = '', $selectedOrdering = 'c.ordering, category_name', $selectedOrderingDir = 'ASC', $tree = false, $deep = 0, $media = false, &$parentCategory = false){ if(($deep===0 or empty($level) or $deep <= $level) /*and (empty($limit) or count($cats)<$limit)*/){ $children = self::getChildCategoryListObject($vendorId, $parentId, -1, $onlyPublished, $media, $keyword, $selectedOrdering, $selectedOrderingDir, $limitStart, $limit); /*if(self::$cache!==null and self::$updateCache) { self::$cache->store(self::$cats, 'com_virtuemart_cats'); self::$updateCache = false; }*/ //$children = self::getChildCategoryListObject($vendorId, $parentId, false, $onlyPublished, $media, $keyword, $selectedOrdering, $selectedOrderingDir, $limitStart, $limit); //vmdebug('rekurseCategories '.$parentId,$children); $siblingCount = count($children); if($tree and $parentCategory){ $parentCategory->childs = &$children; $parentCategory->children = &$parentCategory->childs; } if($siblingCount){ foreach ($children as $key => $category) { $category->level = $deep; $category->siblingCount = $siblingCount; if((!$tree or $deep===0) and !isset($cats[$category->virtuemart_category_id])){ $cats[$category->virtuemart_category_id] = $category; } if($category->has_children){ //$deep++; self::rekurseCategories($vendorId, $category->virtuemart_category_id, $cats, $level, 0, $limit, $onlyPublished, $keyword, $selectedOrdering, $selectedOrderingDir, $tree, $deep +1, $media, $category); //$deep--; } } } } else { if($deep===0 or empty($level) or $deep <= $level){ vmdebug('rekurseCategories stopped More cats ('.count($cats).') for $parentId = '.$parentId.' than limit '.$limit); } else { //vmdebug('rekurseCategories stopped reached Deepnees',$deep,$level); } } } /** * @deprecated Use real rekurse then go to getCategoryRecurse, or if you look for the old function then go to getCategoryTree or getCatsTree instead * @param $virtuemart_category_id * @param $level * @param $onlyPublished * @param $keyword * @param $sortedCats * @param int $deep * @param int $limit */ public function rekurseCats($virtuemart_category_id, $level, $onlyPublished, $keyword, &$sortedCats, $deep=0, $limit = 0){ if(($deep===0 or empty($level) or $deep <= $level) and $childs = $this->hasChildren($virtuemart_category_id) and (empty($limit) or count($sortedCats) < $limit) ){ $childCats = self::getCategories($onlyPublished, $virtuemart_category_id, false, $keyword); if(!empty($childCats)) { $siblingCount = count($childCats); foreach ($childCats as $key => $category) { $category->level = $deep; //$category->dlevel = $deep-1; $category->siblingCount = $siblingCount; $sortedCats[] = $category; if($category->has_children){ $deep++; $this->rekurseCats($category->virtuemart_category_id,$level,$onlyPublished,$keyword,$sortedCats, $deep, $limit); $deep--; } } } } else { vmdebug('rekurseCategories stopped ',$deep,$level,$limit,count($sortedCats)); } } /** * Retrieve the detail record for the parent category of $categoryd * * @deprecated * @author jseros * @param int $categoryId Child category id * @return JTable parent category data */ public function getParentCategory( $categoryId = 0 ){ $data = $this->getRelationInfo( $categoryId ); $parentId = isset($data->category_parent_id) ? $data->category_parent_id : 0; $parent = $this->getTable('categories'); $parent->load((int) $parentId); return $parent; } /** * Retrieve category child-parent relation record * * @deprecated * @author jseros * @param int $virtuemart_category_id * @return object Record of parent relation */ public function getRelationInfo( $virtuemart_category_id = 0 ){ $db = JFactory::getDBO(); $query = 'SELECT `category_parent_id`, `ordering` FROM `#__virtuemart_category_categories` WHERE `category_child_id` = '. (int)$virtuemart_category_id; $db->setQuery($query); return $db->loadObject(); } }