resetExpiredCounters(); $clone_counter = false; $query_name = isset($query_name) ? $query_name : rtrim($name.'-'.implode('-', array_values($params)), '-'); $sql = 'SELECT * FROM '.TABLE_PREFIX.'Counters WHERE Name = '.$this->Conn->qstr($query_name); $count_data = $this->Conn->GetRow($sql); if (!$count_data && ($query_name != $name)) { // cloned record not found -> search for origial one $sql = 'SELECT * FROM '.TABLE_PREFIX.'Counters WHERE Name = '.$this->Conn->qstr($name); $count_data = $this->Conn->GetRow($sql); $clone_counter = true; } if (is_null($count_data['CountValue'])) { $params['PREFIX'] = TABLE_PREFIX; $count_sql = $count_data['CountQuery']; foreach ($params as $replace_from => $replace_to) { $count_sql = str_replace('<%'.$replace_from.'%>', $replace_to, $count_sql); } if ($multiple_results) { $count_data['CountValue'] = serialize($this->Conn->GetCol($count_sql)); } else { $count_data['CountValue'] = $this->Conn->GetOne($count_sql); } if ($clone_counter && !$count_data['IsClone']) { // don't clone clones $count_data['CounterId'] = 0; $count_data['Name'] = $query_name; $count_data['IsClone'] = 1; } $count_data['LastCounted'] = adodb_mktime(); $this->Conn->doInsert($count_data, TABLE_PREFIX.'Counters', 'REPLACE'); } return $multiple_results ? unserialize($count_data['CountValue']) : $count_data['CountValue']; } /** * Resets counter, which are affected by one of specified tables * * @param string $tables comma separated tables list used in counting sqls * @return void * @access public */ public function resetCounters($tables) { $tables = explode(',', $tables); $prefix_length = strlen(TABLE_PREFIX); foreach ($tables as $index => $table) { // remove prefixes if (substr($table, 0, $prefix_length) == TABLE_PREFIX) { $table = substr($table, $prefix_length); } $tables[$index] = '(TablesAffected LIKE "%|'.$table.'|%")'; } $sql = 'UPDATE '.TABLE_PREFIX.'Counters SET CountValue = NULL WHERE '.implode(' OR ', $tables); $this->Conn->Query($sql); } function resetExpiredCounters() { static $reset = false; if (!$reset) { // reset expired counts $sql = 'UPDATE '.TABLE_PREFIX.'Counters SET CountValue = NULL WHERE (LifeTime > 0) AND (LastCounted < '.adodb_mktime().' - LifeTime)'; $this->Conn->Query($sql); $reset = true; } } /** * Counts items (of specific type) in category & subcategories * * @param string $prefix * @param Array $params * @param mixed $count_sql * @return int */ function CategoryItemCount($prefix, $params, $count_sql = null) { if (!$this->Application->findModule('Var', $prefix)) { // this is not module item return $this->Application->ProcessParsedTag($prefix, 'CategoryItemCount', $params); } // 1. get root category for counting $category_id = isset($params['cat_id']) ? $params['cat_id'] : false; if (!is_numeric($category_id)) { $category_id = $this->Application->GetVar('m_cat_id'); } if (!isset($count_sql)) { $count_sql = 'COUNT(*)'; } $where_clauses = Array (); $table_name = $this->Application->getUnitOption($prefix, 'TableName'); // 1. count category items $sql = 'SELECT '.$count_sql.' FROM '.$table_name.' item_table INNER JOIN '.TABLE_PREFIX.'CategoryItems ci ON (ci.ItemResourceId = item_table.ResourceId) INNER JOIN '.TABLE_PREFIX.'Categories c ON (ci.CategoryId = c.CategoryId)'; // 2. count items from subcategories if ($category_id > 0) { // get subcategories of required category $tmp_sql = 'SELECT TreeLeft, TreeRight FROM '.TABLE_PREFIX.'Categories WHERE CategoryId = '.$category_id; $tree_info = $this->Conn->GetRow($tmp_sql); $where_clauses[] = 'c.TreeLeft BETWEEN '.$tree_info['TreeLeft'].' AND '.$tree_info['TreeRight']; } $where_clauses[] = 'item_table.Status = '.STATUS_ACTIVE; if (isset($params['today']) && $params['today']) { $today = adodb_mktime(0,0,0, adodb_date('m'), adodb_date('d'), adodb_date('Y')); $where_clauses[] = 'item_table.CreatedOn >= '.$today; } $sql .= ' WHERE ('.implode(') AND (', $where_clauses).')'; return (int)$this->Conn->GetOne($sql); } /** * Counts items (of specific type) from all categories. * * @param string $prefix Prefix. * @param boolean $today Count only items added today. * @param string|null $count_sql Sql. * * @return int * @access public */ public function ItemCount($prefix, $today = false, $count_sql = null) { $table_name = $this->Application->getUnitOption($prefix, 'TableName'); if ( !isset($count_sql) ) { $count_sql = 'COUNT(*)'; } $where_clause = array( 'ci.PrimaryCat = 1', 'c.Status = ' . STATUS_ACTIVE, ); $sql = 'SELECT ' . $count_sql . ' FROM ' . $table_name . ' item_table INNER JOIN ' . TABLE_PREFIX . 'CategoryItems ci ON ci.ItemResourceId = item_table.ResourceId INNER JOIN ' . TABLE_PREFIX . 'Categories c ON c.CategoryId = ci.CategoryId'; list ($sql, $where_clause) = $this->attachViewPermissionCheck($prefix, $sql, $where_clause, 'ci.CategoryId'); if ( $today ) { $today_date = adodb_mktime(0, 0, 0, adodb_date('m'), adodb_date('d'), adodb_date('Y')); $where_clause[] = 'item_table.CreatedOn >= ' . $today_date; } $sql .= ' WHERE (' . implode(') AND (', $where_clause) . ')'; return (int)$this->Conn->GetOne($sql); } /** * Returns categories count in system * * @param bool $today * @return int */ function CategoryCount($today = false) { $cache_key = 'category_count[%CSerial%]'; if ( $today ) { $today_date = adodb_mktime(0, 0, 0, adodb_date('m'), adodb_date('d'), adodb_date('Y')); $cache_key .= ':date=' . $today_date; } $count = $this->Application->getCache($cache_key); if ( $count === false ) { $where_clause = Array( 'c.Status = ' . STATUS_ACTIVE, ); $sql = 'SELECT COUNT(*) FROM ' . $this->Application->getUnitOption('c', 'TableName') . ' c'; list ($sql, $where_clause) = $this->attachViewPermissionCheck('c', $sql, $where_clause); if ( $today ) { $where_clause[] = 'c.CreatedOn >= ' . $today_date; } $sql .= ' WHERE (' . implode(') AND (', $where_clause) . ')'; $count = $this->Conn->GetOne($sql); if ( $count !== false ) { $this->Application->setCache($cache_key, $count); } } return $count; } /** * Updates given data to make SQL use view permission check. * * @param string $prefix Unit config prefix. * @param string $sql Sql. * @param array $where_clause Where clause. * @param string $category_field Field, where to get Category ID. * * @return array * @access public */ public function attachViewPermissionCheck($prefix, $sql, $where_clause, $category_field = 'c.CategoryId') { if ( !$this->Application->ConfigValue('CheckViewPermissionsInCatalog') ) { return array($sql, $where_clause); } list ($view_perm, $view_filter) = $this->GetPermissionClause($prefix, 'perm_cache'); $where_clause[] = $view_filter; $where_clause[] = 'perm_cache.PermId = ' . $view_perm; $sql .= ' INNER JOIN ' . TABLE_PREFIX . 'CategoryPermissionsCache perm_cache ON ' . $category_field . ' = perm_cache.CategoryId'; return array($sql, $where_clause); } /** * Returns permission limitation clause for category item lists * * @param string $prefix * @param string $table_alias * @return Array */ function GetPermissionClause($prefix, $table_alias) { $permissions_ids = $this->Application->getCache(__CLASS__ . '::' . __FUNCTION__); if ($permissions_ids === false) { $this->Conn->nextQueryCachable = true; $sql = 'SELECT PermissionConfigId, PermissionName FROM '.TABLE_PREFIX.'CategoryPermissionsConfig WHERE PermissionName LIKE "%.VIEW"'; $permissions_ids = $this->Conn->GetCol($sql, 'PermissionName'); $this->Application->setCache(__CLASS__ . '::' . __FUNCTION__, $permissions_ids); } $permission_prefix = $this->Application->getUnitOption($prefix, 'PermItemPrefix'); $view_perm = $permissions_ids[$permission_prefix . '.VIEW']; $groups = explode(',', $this->Application->RecallVar('UserGroups')); foreach ($groups as $group) { $view_filters[] = 'FIND_IN_SET('.$group.', '.$table_alias.'.acl)'; } $view_filter = implode(' OR ', $view_filters); return Array ($view_perm, $view_filter); } }