File indexing completed on 2024-05-12 05:58:47

0001 <?php
0002 
0003 /**
0004  *  ocs-webserver
0005  *
0006  *  Copyright 2016 by pling GmbH.
0007  *
0008  *    This file is part of ocs-webserver.
0009  *
0010  *    This program is free software: you can redistribute it and/or modify
0011  *    it under the terms of the GNU Affero General Public License as
0012  *    published by the Free Software Foundation, either version 3 of the
0013  *    License, or (at your option) any later version.
0014  *
0015  *    This program is distributed in the hope that it will be useful,
0016  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
0017  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0018  *    GNU Affero General Public License for more details.
0019  *
0020  *    You should have received a copy of the GNU Affero General Public License
0021  *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
0022  **/
0023 class Default_Model_ProjectCategory
0024 {
0025     const CACHE_TREE_STORE = 'store_cat_tree';
0026     const CACHE_TREE_SECTION = 'section_cat_tree';
0027 
0028     /** @var string */
0029     protected $_dataTableName;
0030     /** @var  Default_Model_DbTable_ProjectCategory */
0031     protected $_dataTable;
0032 
0033     /**
0034      * PHP 5 allows developers to declare constructor methods for classes.
0035      * Classes which have a constructor method call this method on each newly-created object,
0036      * so it is suitable for any initialization that the object may need before it is used.
0037      *
0038      * Note: Parent constructors are not called implicitly if the child class defines a constructor.
0039      * In order to run a parent constructor, a call to parent::__construct() within the child constructor is required.
0040      *
0041      * param [ mixed $args [, $... ]]
0042      *
0043      * @param string $_dataTableName
0044      *
0045      * @link http://php.net/manual/en/language.oop5.decon.php
0046      */
0047     public function __construct($_dataTableName = 'Default_Model_DbTable_ProjectCategory')
0048     {
0049         $this->_dataTableName = $_dataTableName;
0050         $this->_dataTable = new $this->_dataTableName;
0051     }
0052 
0053     /**
0054      * @param null $store_id
0055      *
0056      * @return array
0057      * @throws Zend_Cache_Exception
0058      * @throws Zend_Exception
0059      */
0060     public function fetchTreeForView($store_id = null)
0061     {
0062         $tags = null;
0063 
0064         if (empty($store_id)) {
0065             $store_config = Zend_Registry::get('store_config');
0066             $store_id = $store_config->store_id;
0067             $tags = Zend_Registry::isRegistered('config_store_tags') ? Zend_Registry::get('config_store_tags') : array();
0068         }
0069 
0070         /** @var Zend_Cache_Core $cache */
0071         $cache = Zend_Registry::get('cache');
0072         $cache_id = __CLASS__ . '_' . __FUNCTION__ . "_{$store_id}";
0073 
0074         $tree = $cache->load($cache_id);
0075 
0076         if (false === $tree OR empty($tree)) {
0077             try {
0078                 $rows = $this->fetchCategoryTreeWithTags($store_id, $tags);
0079             } catch (Zend_Exception $e) {
0080                 Zend_Registry::get('logger')->err(__METHOD__ . ' - can not fetch categories : ' . $e->getMessage());
0081                 $modelCategories = new Default_Model_DbTable_ConfigStore();
0082                 $defaultStore = $modelCategories->fetchDefaultStoreId();
0083                 $rows = $this->fetchCategoryTreeWithTags($defaultStore->store_id, $tags);
0084             }
0085 
0086             list($rows, $tree) = $this->buildTreeForView($rows);
0087             $cache->save($tree, $cache_id, array(), 120);
0088         }
0089 
0090         return $tree;
0091     }
0092 
0093 
0094     /**
0095      * @param null $store_id
0096      *
0097      * @return array
0098      * @throws Zend_Cache_Exception
0099      * @throws Zend_Exception
0100      */
0101     public function fetchTreeForViewForProjectFavourites($store_id = null,$member_id=null)
0102     {        
0103         if (empty($store_id)) {
0104             $store_config = Zend_Registry::get('store_config');
0105             $store_id = $store_config->store_id;            
0106         }
0107         if($member_id==null)
0108         {
0109             $auth = Zend_Auth::getInstance();
0110             if ($auth->hasIdentity()) {
0111                 $this->_authMember = $auth->getStorage()->read();                
0112                 $member_id = $this->_authMember->member_id;
0113             }else
0114             {
0115                 return null;
0116             }
0117         }
0118         $sql = "
0119                 SELECT `sct`.`lft`, `sct`.`rgt`, `sct`.`project_category_id` AS `id`, `sct`.`title`, `scpc`.`count_product` AS `product_count`, `sct`.`xdg_type`, `sct`.`name_legacy`, if(`sct`.`rgt`-`sct`.`lft` = 1, 0, 1) AS `has_children`, (SELECT `project_category_id` FROM `stat_cat_tree` AS `sct2` WHERE `sct2`.`lft` < `sct`.`lft` AND `sct2`.`rgt` > `sct`.`rgt` ORDER BY `sct2`.`rgt` - `sct`.`rgt` LIMIT 1) AS `parent_id`
0120                 FROM (
0121                         SELECT `csc`.`store_id`, `csc`.`project_category_id`, `csc`.`order`, `pc`.`title`, `pc`.`lft`, `pc`.`rgt`
0122                         FROM `config_store_category` AS `csc`
0123                         JOIN `project_category` AS `pc` ON `pc`.`project_category_id` = `csc`.`project_category_id`
0124                         WHERE `csc`.`store_id` = :store_id
0125                         GROUP BY `csc`.`store_category_id`
0126                         ORDER BY `csc`.`order`, `pc`.`title`
0127                 
0128                 ) AS `cfc`
0129                 JOIN `stat_cat_tree` AS `sct` ON find_in_set(`cfc`.`project_category_id`, `sct`.`ancestor_id_path`)   
0130                 join (
0131                 
0132                     SELECT
0133                     sct2.project_category_id,          
0134                     count(distinct p.project_id) as count_product
0135                     FROM stat_cat_tree as sct1
0136                     JOIN stat_cat_tree as sct2 ON sct1.lft between sct2.lft AND sct2.rgt
0137                     left join (
0138                         SELECT project_category_id, f.project_id
0139                         from project_follower f, stat_projects p
0140                         where f.project_id = p.project_id
0141                         and f.member_id = :member_id      
0142                     ) as p on p.project_category_id = sct1.project_category_id                           
0143                     GROUP BY sct2.project_category_id
0144                 
0145                 ) AS `scpc` on  `sct`.`project_category_id` = `scpc`.`project_category_id`  
0146                 WHERE cfc.store_id = :store_id
0147                 ORDER BY cfc.`order`, sct.lft        
0148         ";
0149 
0150         $rows = $this->_dataTable->getAdapter()->fetchAll($sql,array('store_id' =>$store_id,'member_id'=>$member_id));           
0151         list($rows, $tree) = $this->buildTreeForView($rows);        
0152         return $tree;
0153     }
0154     
0155     
0156     /**
0157      * @param null $store_id
0158      *
0159      * @return array
0160      * @throws Zend_Cache_Exception
0161      * @throws Zend_Exception
0162      */
0163     public function fetchTreeForViewForProjectTagGroupTags($store_id = null, $storeTagFilter = null,$tagFilter=null)
0164     {        
0165         if (empty($store_id)) {
0166             $store_config = Zend_Registry::get('store_config');
0167             $store_id = $store_config->store_id;            
0168         }
0169 
0170         $cacheName = __FUNCTION__ . '_' . md5(serialize($storeTagFilter) . '_' . serialize($tagFilter) . '_' . serialize($store_id));
0171         /** @var Zend_Cache_Core $cache */
0172         $cache = Zend_Registry::get('cache');
0173 
0174         if (false === ($tree = $cache->load($cacheName))) {
0175             $filterString = "";
0176             //Store Tag Filter
0177             if(null != $storeTagFilter) {
0178                 if(is_array($storeTagFilter)) {
0179                     foreach ($storeTagFilter as $value) {
0180                         $filterString .= " AND FIND_IN_SET('".$value."',p.tag_ids)";
0181                     }
0182                 } else {
0183                     $filterString .= " AND FIND_IN_SET('".$storeTagFilter."',p.tag_ids)";
0184                 }
0185             }
0186             //Store-Tag-Group-Filter
0187             if (is_array($tagFilter)) {
0188                 $tagList = $tagFilter;
0189                 foreach ($tagList as $key => $value) {
0190                     if($value != null && $value != "0") {
0191                         $filterString .= " AND FIND_IN_SET('".$value."',p.tag_ids)";
0192                     }
0193                 }
0194             } else {
0195                 $filterString .= " AND FIND_IN_SET('".$tagFilter."',p.tag_ids)";
0196             }
0197 
0198             $sql = "
0199                     SELECT `sct`.`lft`, `sct`.`rgt`, `sct`.`project_category_id` AS `id`, `sct`.`title`, `scpc`.`count_product` AS `product_count`, `sct`.`xdg_type`, `sct`.`name_legacy`, if(`sct`.`rgt`-`sct`.`lft` = 1, 0, 1) AS `has_children`, (SELECT `project_category_id` FROM `stat_cat_tree` AS `sct2` WHERE `sct2`.`lft` < `sct`.`lft` AND `sct2`.`rgt` > `sct`.`rgt` ORDER BY `sct2`.`rgt` - `sct`.`rgt` LIMIT 1) AS `parent_id`
0200                     FROM (
0201                             SELECT `csc`.`store_id`, `csc`.`project_category_id`, `csc`.`order`, `pc`.`title`, `pc`.`lft`, `pc`.`rgt`
0202                             FROM `config_store_category` AS `csc`
0203                             JOIN `project_category` AS `pc` ON `pc`.`project_category_id` = `csc`.`project_category_id`
0204                             WHERE `csc`.`store_id` = :store_id
0205                             GROUP BY `csc`.`store_category_id`
0206                             ORDER BY `csc`.`order`, `pc`.`title`
0207 
0208                     ) AS `cfc`
0209                     JOIN `stat_cat_tree` AS `sct` ON find_in_set(`cfc`.`project_category_id`, `sct`.`ancestor_id_path`)   
0210                     join (
0211 
0212                         SELECT
0213                         sct2.project_category_id,          
0214                         count(distinct p.project_id) as count_product
0215                         FROM stat_cat_tree as sct1
0216                         JOIN stat_cat_tree as sct2 ON sct1.lft between sct2.lft AND sct2.rgt
0217                         left join (
0218                             SELECT project_category_id, project_id
0219                             from stat_projects p
0220                             WHERE 1=1
0221                             ".$filterString."
0222                         ) as p on p.project_category_id = sct1.project_category_id                           
0223                         GROUP BY sct2.project_category_id
0224 
0225                     ) AS `scpc` on  `sct`.`project_category_id` = `scpc`.`project_category_id`  
0226                     WHERE cfc.store_id = :store_id
0227                     ORDER BY cfc.`order`, sct.lft        
0228             ";
0229             
0230             Zend_Registry::get('logger')->debug(__METHOD__ . ' - SQL: ' . $sql);
0231 
0232             $rows = $this->_dataTable->getAdapter()->fetchAll($sql,array('store_id' =>$store_id));           
0233             list($rows, $tree) = $this->buildTreeForView($rows); 
0234             
0235             $cache->save($tree, $cacheName, array(), 1800);
0236         }
0237         return $tree;
0238     }
0239 
0240 
0241 
0242     /**
0243      * @param int|null    $store_id
0244      * @param string|null $tags
0245      *
0246      * @return array
0247      * @throws Zend_Exception
0248      */
0249     protected function fetchCategoryTreeWithTags($store_id = null, $tags = null)
0250     {
0251         if (empty($store_id)) {
0252             return array();
0253         }
0254 
0255         Zend_Registry::get('logger')->debug(__METHOD__ . ' - ' . $store_id . ' - ' . json_encode($tags));
0256 
0257         if (empty($tags)) {
0258             $statement = $this->_dataTable->getAdapter()->query("CALL fetchCatTreeForStore(:store_id)", array("store_id" => $store_id));
0259         } else {
0260             $statement = $this->_dataTable->getAdapter()->query("CALL fetchCatTreeWithTagsForStore(:store_id,:tagids)", array("store_id"=>$store_id, "tagids" => implode(',',$tags)));
0261         }
0262 
0263         $result = $statement->fetchAll();
0264 
0265 //        if (count($result) == 0) {
0266 //            throw new Zend_Exception('no categories could be found for store id: ' . $store_id);
0267 //        }
0268 
0269         return $result;
0270     }
0271 
0272     /**
0273      * @param array    $rows
0274      * @param int|null $parent_id
0275      *
0276      * @return array
0277      */
0278     protected function buildTreeForView($rows, $parent_id = null)
0279     {
0280         $result = array();
0281         $rememberParent = null;
0282 
0283         while (false === empty($rows)) {
0284             $row = array_shift($rows);
0285 
0286             $result_element = array(
0287                 'id'            => $row['id'],
0288                 'title'         => $row['title'],
0289                 'product_count' => $row['product_count'],
0290                 'xdg_type'      => $row['xdg_type'],
0291                 'name_legacy'   => $row['name_legacy'],
0292                 'has_children'  => $row['has_children'],
0293                 'parent_id'     => $row['parent_id']
0294             );
0295 
0296             //has children?
0297             if ($row['has_children'] == 1) {
0298                 $result_element['has_children'] = true;
0299                 $rememberParent = $row['id'];
0300                 list($rows, $children) = $this->buildTreeForView($rows, $rememberParent);
0301                 uasort($children, function ($a, $b) {return strcasecmp($a['title'], $b['title']);});
0302                 $result_element['children'] = $children;
0303                 $rememberParent = null;
0304             }
0305 
0306             $result[] = $result_element;
0307 
0308             if (isset($parent_id) AND isset($rows[0]['parent_id']) AND $parent_id != $rows[0]['parent_id']) {
0309                 break;
0310             }
0311         }
0312 
0313         return array($rows, $result);
0314     }
0315 
0316     /**
0317      * @param int|null $store_id If not set, the tree for the current store will be returned
0318      * @param bool     $clearCache
0319      *
0320      * @return array
0321      * @throws Zend_Cache_Exception
0322      * @throws Zend_Exception
0323      * @deprecated use fetchTreeForView
0324      */
0325     public function fetchCategoryTreeForStore($store_id = null, $clearCache = false)
0326     {
0327         if (empty($store_id)) {
0328             $store_config = Zend_Registry::get('store_config');
0329             $store_id = $store_config->store_id;
0330         }
0331 
0332         /** @var Zend_Cache_Core $cache */
0333         $cache = Zend_Registry::get('cache');
0334         $cache_id = self::CACHE_TREE_STORE . "_{$store_id}";
0335 
0336         if ($clearCache) {
0337             $cache->remove($cache_id);
0338         }
0339 
0340         if (false === ($tree = $cache->load($cache_id))) {
0341             $modelCategoryStore = new Default_Model_DbTable_ConfigStoreCategory();
0342             $rows = $modelCategoryStore->fetchCatIdsForStore((int)$store_id);
0343 
0344             if (count($rows) < 1) {
0345                 $modelCategories = new Default_Model_DbTable_ProjectCategory();
0346                 $root = $modelCategories->fetchRoot();
0347                 $rows = $modelCategories->fetchImmediateChildrenIds($root['project_category_id'], $modelCategories::ORDERED_TITLE);
0348                 $tree = $this->buildTree($rows, null, null);
0349             } else {
0350                 $tree = $this->buildTree($rows, null, (int)$store_id);
0351             }
0352 
0353             $cache->save($tree, $cache_id, array(), 600);
0354         }
0355 
0356         return $tree;
0357     } 
0358     
0359     /**
0360      * @param int|null $store_id If not set, the tree for the current store will be returned
0361      * @param bool     $clearCache
0362      *
0363      * @return array
0364      * @throws Zend_Cache_Exception
0365      * @throws Zend_Exception
0366      * @deprecated use fetchTreeForView
0367      */
0368     public function fetchCategoryTreeForSection($section_id = null, $clearCache = false)
0369     {
0370         /** @var Zend_Cache_Core $cache */
0371         $cache = Zend_Registry::get('cache');
0372         $cache_id = self::CACHE_TREE_SECTION . "_{$section_id}";
0373 
0374         if ($clearCache) {
0375             $cache->remove($cache_id);
0376         }
0377 
0378         if (false === ($tree = $cache->load($cache_id))) {
0379             $modelCategoryStore = new Default_Model_DbTable_SectionCategory();
0380             $rows = $modelCategoryStore->fetchCatIdsForSection((int)$store_id);
0381 
0382             if (count($rows) < 1) {
0383                 $modelCategories = new Default_Model_DbTable_ProjectCategory();
0384                 $root = $modelCategories->fetchRoot();
0385                 $rows = $modelCategories->fetchImmediateChildrenIds($root['project_category_id'], $modelCategories::ORDERED_TITLE);
0386                 $tree = $this->buildTree($rows, null, null);
0387             } else {
0388                 $tree = $this->buildTree($rows, null, null);
0389             }
0390 
0391             $cache->save($tree, $cache_id, array(), 600);
0392         }
0393 
0394         return $tree;
0395     } 
0396     
0397 
0398     private function buildTree($list, $parent_id = null, $store_id = null)
0399     {
0400         if (false === is_array($list)) {
0401             $list = array($list);
0402         }
0403         $modelCategories = new Default_Model_DbTable_ProjectCategory();
0404         $result = array();
0405         foreach ($list as $cat_id) {
0406             $currentCategory = $modelCategories->fetchElement($cat_id);
0407             $countProduct = $this->fetchProductCount($cat_id, $store_id);
0408 
0409             $result_element = array(
0410                 'id'            => $cat_id,
0411                 'title'         => $currentCategory['title'],
0412                 'product_count' => $countProduct,
0413                 'xdg_type'      => $currentCategory['xdg_type'],
0414                 'name_legacy'   => $currentCategory['name_legacy'],
0415                 'has_children'  => false
0416             );
0417 
0418             if (isset($parent_id)) {
0419                 $result_element['parent_id'] = $parent_id;
0420             }
0421 
0422             //has children?
0423             if (($currentCategory['rgt'] - $currentCategory['lft']) > 1) {
0424                 $result_element['has_children'] = true;
0425                 $ids = $modelCategories->fetchImmediateChildrenIds($currentCategory['project_category_id'],
0426                     $modelCategories::ORDERED_TITLE);
0427                 $result_element['children'] = $this->buildTree($ids, $currentCategory['project_category_id'], $store_id);
0428             }
0429             $result[] = $result_element;
0430         }
0431 
0432         return $result;
0433     }
0434 
0435     private function fetchProductCount($cat_id, $store_id = null)
0436     {
0437        
0438         $store_config = Zend_Registry::isRegistered('store_config') ? Zend_Registry::get('store_config') : null;
0439         $tagFilter = null;
0440         if($store_config)
0441         {
0442             $tagFilter  = Zend_Registry::isRegistered('config_store_tags') ? Zend_Registry::get('config_store_tags') : null;
0443         }else
0444         {
0445             $tagFilter = null;
0446         }
0447        
0448 
0449         if ($tagFilter) {
0450             $sql =
0451                 "SELECT count_product FROM stat_cat_prod_count WHERE project_category_id = :cat_id AND tag_id = :tags";
0452             $bind = array('cat_id' => $cat_id, 'tags' => $tagFilter);
0453         } else {
0454             $sql = "SELECT count_product FROM stat_cat_prod_count WHERE project_category_id = :cat_id AND tag_id IS NULL";
0455             $bind = array('cat_id' => $cat_id);
0456         }
0457 
0458         $result = $this->_dataTable->getAdapter()->fetchRow($sql, $bind);
0459 
0460         return (int)$result['count_product'];
0461     }
0462 
0463     /**
0464      * @param bool $clearCache
0465      *
0466      * @return array|false|mixed
0467      * @throws Zend_Cache_Exception
0468      * @throws Zend_Exception
0469      *
0470      * @deprecated use fetchTreeForView
0471      */
0472     public function fetchCategoryTreeCurrentStore($clearCache = false)
0473     {
0474         $store_config = Zend_Registry::get('store_config');
0475         $store_id = $store_config->store_id;
0476 
0477         /** @var Zend_Cache_Core $cache */
0478         $cache = Zend_Registry::get('cache');
0479         $cache_id = self::CACHE_TREE_STORE . "_{$store_id}";
0480 
0481         if ($clearCache) {
0482             $cache->remove($cache_id);
0483         }
0484 
0485         if (false === ($tree = $cache->load($cache_id))) {
0486             $list_cat_id = self::fetchCatIdsForCurrentStore();
0487             $tree = $this->buildTree($list_cat_id);
0488             $cache->save($tree, $cache_id, array(), 600);
0489         }
0490 
0491         return $tree;
0492     }
0493 
0494     /**
0495      * @return mixed|null
0496      * @throws Zend_Exception
0497      */
0498     public static function fetchCatIdsForCurrentStore()
0499     {
0500         return Zend_Registry::isRegistered('store_category_list') ? Zend_Registry::get('store_category_list') : null;
0501     }
0502 
0503     /**
0504      * @return array
0505      * @throws Zend_Exception
0506      */
0507     public function fetchCatNamesForCurrentStore()
0508     {
0509         $list_cat_id = self::fetchCatIdsForCurrentStore();
0510 
0511         $sql = "SELECT project_category_id, title FROM project_category WHERE project_category_id IN (" . implode(',', $list_cat_id)
0512             . ")";
0513 
0514         $result = $this->_dataTable->getAdapter()->fetchPairs($sql);
0515 
0516         return $result;
0517     }
0518 
0519     /**
0520      * @return array
0521      * @throws Zend_Exception
0522      */
0523     public function fetchCatNamesForID($list_cat_id)
0524     {
0525         
0526         $sql = "SELECT title FROM project_category WHERE project_category_id IN (" . implode(',', $list_cat_id)
0527             . ") order by title " ;
0528 
0529         $results = $this->_dataTable->getAdapter()->fetchAll($sql);       
0530         $values = array_map(function($row) { return $row['title']; }, $results);
0531         return $values;
0532     }
0533 
0534 
0535     /**
0536      * @return array
0537      */
0538     public function fetchCatNames()
0539     {
0540         $sql = "SELECT project_category_id, title FROM project_category";
0541 
0542         $result = $this->_dataTable->getAdapter()->fetchPairs($sql);
0543 
0544         return $result;
0545     }
0546 
0547 }