/** * Get number of groups, displayed on the legend * * @return int value of the last item displayed */ public function get_group_count() { $sql = 'SELECT group_legend FROM ' . GROUPS_TABLE . ' ORDER BY group_legend DESC'; $result = $this->db->sql_query_limit($sql, 1); $group_count = (int) $this->db->sql_fetchfield('group_legend'); $this->db->sql_freeresult($result); return $group_count; }
/** * Return correct object for specified mode * * @param string $mode The feeds mode. * @param int $forum_id Forum id specified by the script if forum feed provided. * @param int $topic_id Topic id specified by the script if topic feed provided. * * @return object Returns correct feeds object for specified mode. */ function get_feed($mode, $forum_id, $topic_id) { switch ($mode) { case 'forums': if (!$this->config['feed_overall_forums']) { return false; } return $this->container->get('feed.forums'); break; case 'topics': case 'topics_new': if (!$this->config['feed_topics_new']) { return false; } return $this->container->get('feed.topics'); break; case 'topics_active': if (!$this->config['feed_topics_active']) { return false; } return $this->container->get('feed.topics_active'); break; case 'news': // Get at least one news forum $sql = 'SELECT forum_id FROM ' . FORUMS_TABLE . ' WHERE ' . $this->db->sql_bit_and('forum_options', FORUM_OPTION_FEED_NEWS, '<> 0'); $result = $this->db->sql_query_limit($sql, 1, 0, 600); $s_feed_news = (int) $this->db->sql_fetchfield('forum_id'); $this->db->sql_freeresult($result); if (!$s_feed_news) { return false; } return $this->container->get('feed.news'); break; default: if ($topic_id && $this->config['feed_topic']) { return $this->container->get('feed.topic')->set_topic_id($topic_id); } else { if ($forum_id && $this->config['feed_forum']) { return $this->container->get('feed.forum')->set_forum_id($forum_id); } else { if ($this->config['feed_overall']) { return $this->container->get('feed.overall'); } } } return false; break; } }
/** * Collects stats that can be displayed on the index maintenance page */ protected function get_stats() { if ($this->index_created()) { $sql = 'SELECT COUNT(post_id) as total_posts FROM ' . POSTS_TABLE; $result = $this->db->sql_query($sql); $this->stats['total_posts'] = (int) $this->db->sql_fetchfield('total_posts'); $this->db->sql_freeresult($result); $sql = 'SELECT COUNT(p.post_id) as main_posts FROM ' . POSTS_TABLE . ' p, ' . SPHINX_TABLE . ' m WHERE p.post_id <= m.max_doc_id AND m.counter_id = 1'; $result = $this->db->sql_query($sql); $this->stats['main_posts'] = (int) $this->db->sql_fetchfield('main_posts'); $this->db->sql_freeresult($result); } }
/** * Add an item which already has a database row at the end of the tree * * @param int $item_id The item to be added * @return array Array with updated data, if the item was added successfully * Empty array otherwise */ protected function add_item_to_nestedset($item_id) { $sql = 'SELECT MAX(' . $this->column_right_id . ') AS ' . $this->column_right_id . ' FROM ' . $this->table_name . ' ' . $this->get_sql_where('WHERE'); $result = $this->db->sql_query($sql); $current_max_right_id = (int) $this->db->sql_fetchfield($this->column_right_id); $this->db->sql_freeresult($result); $update_item_data = array($this->column_parent_id => 0, $this->column_left_id => $current_max_right_id + 1, $this->column_right_id => $current_max_right_id + 2, $this->column_item_parents => ''); $sql = 'UPDATE ' . $this->table_name . ' SET ' . $this->db->sql_build_array('UPDATE', $update_item_data) . ' WHERE ' . $this->column_item_id . ' = ' . (int) $item_id . ' AND ' . $this->column_parent_id . ' = 0 AND ' . $this->column_left_id . ' = 0 AND ' . $this->column_right_id . ' = 0'; $this->db->sql_query($sql); return $this->db->sql_affectedrows() == 1 ? $update_item_data : array(); }
function get_excluded_forums() { static $forum_ids; // Matches acp/acp_srcrd.php $cache_name = 'feed_excluded_forum_ids'; if (!isset($forum_ids) && ($forum_ids = $this->cache->get('_' . $cache_name)) === false) { $sql = 'SELECT forum_id FROM ' . FORUMS_TABLE . ' WHERE ' . $this->db->sql_bit_and('forum_options', FORUM_OPTION_FEED_EXCLUDE, '<> 0'); $result = $this->db->sql_query($sql); $forum_ids = array(); while ($forum_id = (int) $this->db->sql_fetchfield('forum_id')) { $forum_ids[$forum_id] = $forum_id; } $this->db->sql_freeresult($result); $this->cache->put('_' . $cache_name, $forum_ids); } return $forum_ids; }
/** * Delete a subscription * * @param string $item_type Type identifier of the subscription * @param int $item_id The id of the item * @param string $method The method of the notification e.g. '', 'email', or 'jabber' * @param bool|int $user_id The user_id to add the subscription for (bool false for current user) */ public function delete_subscription($item_type, $item_id = 0, $method = '', $user_id = false) { $user_id = $user_id === false ? $this->user->data['user_id'] : $user_id; // If no method, make sure that no other notification methods for this item are selected before deleting if ($method === '') { $sql = 'SELECT COUNT(*) as num_notifications FROM ' . $this->user_notifications_table . "\n\t\t\t\tWHERE item_type = '" . $this->db->sql_escape($item_type) . "'\n\t\t\t\t\tAND item_id = " . (int) $item_id . ' AND user_id = ' . (int) $user_id . "\n\t\t\t\t\tAND method <> ''\n\t\t\t\t\tAND notify = 1"; $this->db->sql_query($sql); $num_notifications = $this->db->sql_fetchfield('num_notifications'); $this->db->sql_freeresult(); if ($num_notifications) { return; } } $sql = 'UPDATE ' . $this->user_notifications_table . "\n\t\t\tSET notify = 0\n\t\t\tWHERE item_type = '" . $this->db->sql_escape($item_type) . "'\n\t\t\t\tAND item_id = " . (int) $item_id . ' AND user_id = ' . (int) $user_id . "\n\t\t\t\tAND method = '" . $this->db->sql_escape($method) . "'"; $this->db->sql_query($sql); if (!$this->db->sql_affectedrows()) { $sql = 'INSERT INTO ' . $this->user_notifications_table . ' ' . $this->db->sql_build_array('INSERT', array('item_type' => $item_type, 'item_id' => (int) $item_id, 'user_id' => (int) $user_id, 'method' => $method, 'notify' => 0)); $this->db->sql_query($sql); } }
/** * Module Remove * * Remove a module * * @param string $class The module class(acp|mcp|ucp) * @param int|string|bool $parent The parent module_id|module_langname(0 for no parent). * Use false to ignore the parent check and check class wide. * @param int|string $module The module id|module_langname * specify that here * @return null * @throws \src\db\migration\exception */ public function remove($class, $parent = 0, $module = '') { // Imitation of module_add's "automatic" and "manual" method so the uninstaller works from the same set of instructions for umil_auto if (is_array($module)) { if (isset($module['module_langname'])) { // Manual Method return $this->remove($class, $parent, $module['module_langname']); } // Failed. if (!isset($module['module_basename'])) { throw new \src\db\migration\exception('MODULE_NOT_EXIST'); } // Automatic method $basename = $module['module_basename']; $module_info = $this->get_module_info($class, $basename); foreach ($module_info['modes'] as $mode => $info) { if (!isset($module['modes']) || in_array($mode, $module['modes'])) { $this->remove($class, $parent, $info['title']); } } } else { if (!$this->exists($class, $parent, $module)) { return; } $parent_sql = ''; if ($parent !== false) { // Allows '' to be sent as 0 $parent = $parent ?: 0; if (!is_numeric($parent)) { $sql = 'SELECT module_id FROM ' . $this->modules_table . "\n\t\t\t\t\t\tWHERE module_langname = '" . $this->db->sql_escape($parent) . "'\n\t\t\t\t\t\t\tAND module_class = '" . $this->db->sql_escape($class) . "'"; $result = $this->db->sql_query($sql); $module_id = $this->db->sql_fetchfield('module_id'); $this->db->sql_freeresult($result); // we know it exists from the module_exists check $parent_sql = 'AND parent_id = ' . (int) $module_id; } else { $parent_sql = 'AND parent_id = ' . (int) $parent; } } $module_ids = array(); if (!is_numeric($module)) { $sql = 'SELECT module_id FROM ' . $this->modules_table . "\n\t\t\t\t\tWHERE module_langname = '" . $this->db->sql_escape($module) . "'\n\t\t\t\t\t\tAND module_class = '" . $this->db->sql_escape($class) . "'\n\t\t\t\t\t\t{$parent_sql}"; $result = $this->db->sql_query($sql); while ($module_id = $this->db->sql_fetchfield('module_id')) { $module_ids[] = (int) $module_id; } $this->db->sql_freeresult($result); } else { $module_ids[] = (int) $module; } if (!class_exists('acp_modules')) { include $this->src_root_path . 'includes/acp/acp_modules.' . $this->php_ext; $this->user->add_lang('acp/modules'); } $acp_modules = new \acp_modules(); $acp_modules->module_class = $class; foreach ($module_ids as $module_id) { $result = $acp_modules->delete_module($module_id); if (!empty($result)) { return; } } $this->cache->destroy("_modules_{$class}"); } }
/** * Moves an item up/down * * @param int $teampage_id teampage_id of the item to be moved * @param int $delta number of steps: * - positive = move up * - negative = move down * @return bool True if the group was moved successfully */ public function move_teampage($teampage_id, $delta) { $delta = (int) $delta; if (!$delta) { return false; } $move_up = $delta > 0 ? true : false; $data = $this->get_teampage_values($teampage_id); $current_value = (int) $data['teampage_position']; if ($current_value != self::GROUP_DISABLED) { $this->db->sql_transaction('begin'); if (!$move_up && $data['teampage_parent'] == self::NO_PARENT) { // If we move items down, we need to grab the one sibling more, // so we do not ignore the children of the previous sibling. // We will remove the additional sibling later on. $delta = abs($delta) + 1; } $sql = 'SELECT teampage_id, teampage_position FROM ' . TEAMPAGE_TABLE . ' WHERE teampage_parent = ' . (int) $data['teampage_parent'] . ' AND teampage_position' . ($move_up ? ' < ' : ' > ') . $current_value . ' ORDER BY teampage_position' . ($move_up ? ' DESC' : ' ASC'); $result = $this->db->sql_query_limit($sql, $delta); $sibling_count = 0; $sibling_limit = $delta; // Reset the delta, as we recalculate the new real delta $delta = 0; while ($row = $this->db->sql_fetchrow($result)) { $sibling_count++; $delta = $current_value - $row['teampage_position']; // Remove the additional sibling we added previously // But only, if we included it, this is not be the case // when we reached the end of our list if (!$move_up && $data['teampage_parent'] == self::NO_PARENT && $sibling_count == $sibling_limit) { $delta++; } } $this->db->sql_freeresult($result); if ($delta) { $sql = 'SELECT COUNT(teampage_id) as num_items FROM ' . TEAMPAGE_TABLE . ' WHERE teampage_id = ' . (int) $teampage_id . ' OR teampage_parent = ' . (int) $teampage_id; $result = $this->db->sql_query($sql); $num_items = (int) $this->db->sql_fetchfield('num_items'); $this->db->sql_freeresult($result); // First we move all items between our current value and the target value up/down 1, // so we have a gap for our item to move. $sql = 'UPDATE ' . TEAMPAGE_TABLE . ' SET teampage_position = teampage_position' . ($move_up ? ' + ' : ' - ') . $num_items . ' WHERE teampage_position' . ($move_up ? ' >= ' : ' <= ') . ($current_value - $delta) . ' AND teampage_position' . ($move_up ? ' < ' : ' > ') . $current_value . ' AND NOT (teampage_id = ' . (int) $teampage_id . ' OR teampage_parent = ' . (int) $teampage_id . ')'; $this->db->sql_query($sql); $delta = !$move_up && $data['teampage_parent'] == self::NO_PARENT ? abs($delta) - ($num_items - 1) : abs($delta); // And now finally, when we moved some other items and built a gap, // we can move the desired item to it. $sql = 'UPDATE ' . TEAMPAGE_TABLE . ' SET teampage_position = teampage_position ' . ($move_up ? ' - ' : ' + ') . $delta . ' WHERE teampage_id = ' . (int) $teampage_id . ' OR teampage_parent = ' . (int) $teampage_id; $this->db->sql_query($sql); $this->db->sql_transaction('commit'); $this->cache->destroy('sql', TEAMPAGE_TABLE); return true; } $this->db->sql_transaction('commit'); } $this->cache->destroy('sql', TEAMPAGE_TABLE); return false; }
/** * Change visibility status of one post or all posts of a topic * * @param $visibility int Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE} * @param $post_id mixed Post ID or array of post IDs to act on, * if it is empty, all posts of topic_id will be modified * @param $topic_id int Topic where $post_id is found * @param $forum_id int Forum where $topic_id is found * @param $user_id int User performing the action * @param $time int Timestamp when the action is performed * @param $reason string Reason why the visibility was changed. * @param $is_starter bool Is this the first post of the topic changed? * @param $is_latest bool Is this the last post of the topic changed? * @param $limit_visibility mixed Limit updating per topic_id to a certain visibility * @param $limit_delete_time mixed Limit updating per topic_id to a certain deletion time * @return array Changed post data, empty array if an error occurred. */ public function set_post_visibility($visibility, $post_id, $topic_id, $forum_id, $user_id, $time, $reason, $is_starter, $is_latest, $limit_visibility = false, $limit_delete_time = false) { if (!in_array($visibility, array(ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE))) { return array(); } if ($post_id) { if (is_array($post_id)) { $where_sql = $this->db->sql_in_set('post_id', array_map('intval', $post_id)); } else { $where_sql = 'post_id = ' . (int) $post_id; } $where_sql .= ' AND topic_id = ' . (int) $topic_id; } else { $where_sql = 'topic_id = ' . (int) $topic_id; // Limit the posts to a certain visibility and deletion time // This allows us to only restore posts, that were approved // when the topic got soft deleted. So previous soft deleted // and unapproved posts are still soft deleted/unapproved if ($limit_visibility !== false) { $where_sql .= ' AND post_visibility = ' . (int) $limit_visibility; } if ($limit_delete_time !== false) { $where_sql .= ' AND post_delete_time = ' . (int) $limit_delete_time; } } $sql = 'SELECT poster_id, post_id, post_postcount, post_visibility FROM ' . $this->posts_table . ' WHERE ' . $where_sql; $result = $this->db->sql_query($sql); $post_ids = $poster_postcounts = $postcounts = $postcount_visibility = array(); while ($row = $this->db->sql_fetchrow($result)) { $post_ids[] = (int) $row['post_id']; if ($row['post_visibility'] != $visibility) { if ($row['post_postcount'] && !isset($poster_postcounts[(int) $row['poster_id']])) { $poster_postcounts[(int) $row['poster_id']] = 1; } else { if ($row['post_postcount']) { $poster_postcounts[(int) $row['poster_id']]++; } } if (!isset($postcount_visibility[$row['post_visibility']])) { $postcount_visibility[$row['post_visibility']] = 1; } else { $postcount_visibility[$row['post_visibility']]++; } } } $this->db->sql_freeresult($result); if (empty($post_ids)) { return array(); } $data = array('post_visibility' => (int) $visibility, 'post_delete_user' => (int) $user_id, 'post_delete_time' => (int) $time ?: time(), 'post_delete_reason' => truncate_string($reason, 255, 255, false)); $sql = 'UPDATE ' . $this->posts_table . ' SET ' . $this->db->sql_build_array('UPDATE', $data) . ' WHERE ' . $this->db->sql_in_set('post_id', $post_ids); $this->db->sql_query($sql); // Group the authors by post count, to reduce the number of queries foreach ($poster_postcounts as $poster_id => $num_posts) { $postcounts[$num_posts][] = $poster_id; } // Update users postcounts foreach ($postcounts as $num_posts => $poster_ids) { if (in_array($visibility, array(ITEM_REAPPROVE, ITEM_DELETED))) { $sql = 'UPDATE ' . $this->users_table . ' SET user_posts = 0 WHERE ' . $this->db->sql_in_set('user_id', $poster_ids) . ' AND user_posts < ' . $num_posts; $this->db->sql_query($sql); $sql = 'UPDATE ' . $this->users_table . ' SET user_posts = user_posts - ' . $num_posts . ' WHERE ' . $this->db->sql_in_set('user_id', $poster_ids) . ' AND user_posts >= ' . $num_posts; $this->db->sql_query($sql); } else { $sql = 'UPDATE ' . $this->users_table . ' SET user_posts = user_posts + ' . $num_posts . ' WHERE ' . $this->db->sql_in_set('user_id', $poster_ids); $this->db->sql_query($sql); } } $update_topic_postcount = true; // Sync the first/last topic information if needed if (!$is_starter && $is_latest) { if (!function_exists('update_post_information')) { include $this->src_root_path . 'includes/functions_posting.' . $this->php_ext; } // update_post_information can only update the last post info ... if ($topic_id) { update_post_information('topic', $topic_id, false); } if ($forum_id) { update_post_information('forum', $forum_id, false); } } else { if ($is_starter && $topic_id) { if (!function_exists('sync')) { include $this->src_root_path . 'includes/functions_admin.' . $this->php_ext; } // ... so we need to use sync, if the first post is changed. // The forum is resynced recursive by sync() itself. sync('topic', 'topic_id', $topic_id, true); // sync recalculates the topic replies and forum posts by itself, so we don't do that. $update_topic_postcount = false; } } $topic_update_array = array(); // Update the topic's reply count and the forum's post count if ($update_topic_postcount) { $field_alias = array(ITEM_APPROVED => 'posts_approved', ITEM_UNAPPROVED => 'posts_unapproved', ITEM_DELETED => 'posts_softdeleted', ITEM_REAPPROVE => 'posts_unapproved'); $cur_posts = array_fill_keys($field_alias, 0); foreach ($postcount_visibility as $post_visibility => $visibility_posts) { $cur_posts[$field_alias[(int) $post_visibility]] += $visibility_posts; } $sql_ary = array(); $recipient_field = $field_alias[$visibility]; foreach ($cur_posts as $field => $count) { // Decrease the count for the old statuses. if ($count && $field != $recipient_field) { $sql_ary[$field] = " - {$count}"; } } // Add up the count from all statuses excluding the recipient status. $count_increase = array_sum(array_diff($cur_posts, array($recipient_field))); if ($count_increase) { $sql_ary[$recipient_field] = " + {$count_increase}"; } if (sizeof($sql_ary)) { $forum_sql = array(); foreach ($sql_ary as $field => $value_change) { $topic_update_array[] = 'topic_' . $field . ' = topic_' . $field . $value_change; $forum_sql[] = 'forum_' . $field . ' = forum_' . $field . $value_change; } $sql = 'UPDATE ' . $this->forums_table . ' SET ' . implode(', ', $forum_sql) . ' WHERE forum_id = ' . (int) $forum_id; $this->db->sql_query($sql); } } if ($post_id) { $sql = 'SELECT 1 AS has_attachments FROM ' . POSTS_TABLE . ' WHERE topic_id = ' . (int) $topic_id . ' AND post_attachment = 1 AND post_visibility = ' . ITEM_APPROVED . ' AND ' . $this->db->sql_in_set('post_id', $post_id, true); $result = $this->db->sql_query_limit($sql, 1); $has_attachment = (bool) $this->db->sql_fetchfield('has_attachments'); $this->db->sql_freeresult($result); if ($has_attachment && $visibility == ITEM_APPROVED) { $topic_update_array[] = 'topic_attachment = 1'; } else { if (!$has_attachment && $visibility != ITEM_APPROVED) { $topic_update_array[] = 'topic_attachment = 0'; } } } if (!empty($topic_update_array)) { // Update the number for replies and posts, and update the attachments flag $sql = 'UPDATE ' . $this->topics_table . ' SET ' . implode(', ', $topic_update_array) . ' WHERE topic_id = ' . (int) $topic_id; $this->db->sql_query($sql); } return $data; }
/** * Performs a search on an author's posts without caring about message contents. Depends on display specific params * * @param string $type contains either posts or topics depending on what should be searched for * @param boolean $firstpost_only if true, only topic starting posts will be considered * @param array $sort_by_sql contains SQL code for the ORDER BY part of a query * @param string $sort_key is the key of $sort_by_sql for the selected sorting * @param string $sort_dir is either a or d representing ASC and DESC * @param string $sort_days specifies the maximum amount of days a post may be old * @param array $ex_fid_ary specifies an array of forum ids which should not be searched * @param string $post_visibility specifies which types of posts the user can view in which forums * @param int $topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched * @param array $author_ary an array of author ids * @param string $author_name specifies the author match, when ANONYMOUS is also a search-match * @param array &$id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered * @param int $start indicates the first index of the page * @param int $per_page number of ids each page is supposed to contain * @return boolean|int total number of results */ public function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $post_visibility, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page) { // No author? No posts if (!sizeof($author_ary)) { return 0; } // generate a search_key from all the options to identify the results $search_key = md5(implode('#', array('', $type, $firstpost_only ? 'firstpost' : '', '', '', $sort_days, $sort_key, $topic_id, implode(',', $ex_fid_ary), $post_visibility, implode(',', $author_ary), $author_name))); if ($start < 0) { $start = 0; } // try reading the results from cache $result_count = 0; if ($this->obtain_ids($search_key, $result_count, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE) { return $result_count; } $id_ary = array(); // Create some display specific sql strings if ($author_name) { // first one matches post of registered users, second one guests and deleted users $sql_author = '(' . $this->db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')'; } else { $sql_author = $this->db->sql_in_set('p.poster_id', $author_ary); } $sql_fora = sizeof($ex_fid_ary) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : ''; $sql_topic_id = $topic_id ? ' AND p.topic_id = ' . (int) $topic_id : ''; $sql_time = $sort_days ? ' AND p.post_time >= ' . (time() - $sort_days * 86400) : ''; $sql_firstpost = $firstpost_only ? ' AND p.post_id = t.topic_first_post_id' : ''; // Build sql strings for sorting $sql_sort = $sort_by_sql[$sort_key] . ($sort_dir == 'a' ? ' ASC' : ' DESC'); $sql_sort_table = $sql_sort_join = ''; switch ($sql_sort[0]) { case 'u': $sql_sort_table = USERS_TABLE . ' u, '; $sql_sort_join = $type == 'posts' ? ' AND u.user_id = p.poster_id ' : ' AND u.user_id = t.topic_poster '; break; case 't': $sql_sort_table = $type == 'posts' && !$firstpost_only ? TOPICS_TABLE . ' t, ' : ''; $sql_sort_join = $type == 'posts' && !$firstpost_only ? ' AND t.topic_id = p.topic_id ' : ''; break; case 'f': $sql_sort_table = FORUMS_TABLE . ' f, '; $sql_sort_join = ' AND f.forum_id = p.forum_id '; break; } $m_approve_fid_sql = ' AND ' . $post_visibility; /** * Allow changing the query used to search for posts by author in fulltext_mysql * * @event core.search_mysql_author_query_before * @var int result_count The previous result count for the format of the query. * Set to 0 to force a re-count * @var string sql_sort_table CROSS JOIN'ed table to allow doing the sort chosen * @var string sql_sort_join Condition to define how to join the CROSS JOIN'ed table specifyed in sql_sort_table * @var array author_ary Array of user_id containing the users to filter the results to * @var string author_name An extra username to search on * @var string sql_author SQL WHERE condition for the post author ids * @var int topic_id Limit the search to this topic_id only * @var string sql_topic_id SQL of topic_id * @var string sort_by_sql The possible predefined sort types * @var string sort_key The sort type used from the possible sort types * @var string sort_dir "a" for ASC or "d" dor DESC for the sort order used * @var string sql_sort The result SQL when processing sort_by_sql + sort_key + sort_dir * @var string sort_days Time, in days, that the oldest post showing can have * @var string sql_time The SQL to search on the time specifyed by sort_days * @var bool firstpost_only Wether or not to search only on the first post of the topics * @var array ex_fid_ary Forum ids that must not be searched on * @var array sql_fora SQL query for ex_fid_ary * @var string m_approve_fid_sql WHERE clause condition on post_visibility restrictions * @var int start How many posts to skip in the search results (used for pagination) * @since 3.1.5-RC1 */ $vars = array('result_count', 'sql_sort_table', 'sql_sort_join', 'author_ary', 'author_name', 'sql_author', 'topic_id', 'sql_topic_id', 'sort_by_sql', 'sort_key', 'sort_dir', 'sql_sort', 'sort_days', 'sql_time', 'firstpost_only', 'ex_fid_ary', 'sql_fora', 'm_approve_fid_sql', 'start'); extract($this->src_dispatcher->trigger_event('core.search_mysql_author_query_before', compact($vars))); // If the cache was completely empty count the results $calc_results = $result_count ? '' : 'SQL_CALC_FOUND_ROWS '; // Build the query for really selecting the post_ids if ($type == 'posts') { $sql = "SELECT {$calc_results}p.post_id\n\t\t\t\tFROM " . $sql_sort_table . POSTS_TABLE . ' p' . ($firstpost_only ? ', ' . TOPICS_TABLE . ' t ' : ' ') . "\n\t\t\t\tWHERE {$sql_author}\n\t\t\t\t\t{$sql_topic_id}\n\t\t\t\t\t{$sql_firstpost}\n\t\t\t\t\t{$m_approve_fid_sql}\n\t\t\t\t\t{$sql_fora}\n\t\t\t\t\t{$sql_sort_join}\n\t\t\t\t\t{$sql_time}\n\t\t\t\tORDER BY {$sql_sort}"; $field = 'post_id'; } else { $sql = "SELECT {$calc_results}t.topic_id\n\t\t\t\tFROM " . $sql_sort_table . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p\n\t\t\t\tWHERE {$sql_author}\n\t\t\t\t\t{$sql_topic_id}\n\t\t\t\t\t{$sql_firstpost}\n\t\t\t\t\t{$m_approve_fid_sql}\n\t\t\t\t\t{$sql_fora}\n\t\t\t\t\tAND t.topic_id = p.topic_id\n\t\t\t\t\t{$sql_sort_join}\n\t\t\t\t\t{$sql_time}\n\t\t\t\tGROUP BY t.topic_id\n\t\t\t\tORDER BY {$sql_sort}"; $field = 'topic_id'; } // Only read one block of posts from the db and then cache it $result = $this->db->sql_query_limit($sql, $this->config['search_block_size'], $start); while ($row = $this->db->sql_fetchrow($result)) { $id_ary[] = (int) $row[$field]; } $this->db->sql_freeresult($result); // retrieve the total result count if needed if (!$result_count) { $sql_found_rows = 'SELECT FOUND_ROWS() as result_count'; $result = $this->db->sql_query($sql_found_rows); $result_count = (int) $this->db->sql_fetchfield('result_count'); $this->db->sql_freeresult($result); if (!$result_count) { return false; } } if ($start >= $result_count) { $start = floor(($result_count - 1) / $per_page) * $per_page; $result = $this->db->sql_query_limit($sql, $this->config['search_block_size'], $start); while ($row = $this->db->sql_fetchrow($result)) { $id_ary[] = (int) $row[$field]; } $this->db->sql_freeresult($result); $id_ary = array_unique($id_ary); } if (sizeof($id_ary)) { $this->save_ids($search_key, '', $author_ary, $result_count, $id_ary, $start, $sort_dir); $id_ary = array_slice($id_ary, 0, $per_page); return $result_count; } return false; }
/** * Permission Unset * * Allows you to unset (remove) permissions for a certain group/role * * @param string $name The name of the role/group * @param string|array $auth_option The auth_option or array of * auth_options you would like to set * @param string $type The type (role|group) * @return null * @throws \src\db\migration\exception */ public function permission_unset($name, $auth_option, $type = 'role') { if (!is_array($auth_option)) { $auth_option = array($auth_option); } $to_remove = array(); $sql = 'SELECT auth_option_id FROM ' . ACL_OPTIONS_TABLE . ' WHERE ' . $this->db->sql_in_set('auth_option', $auth_option); $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { $to_remove[] = (int) $row['auth_option_id']; } $this->db->sql_freeresult($result); if (empty($to_remove)) { return; } $type = (string) $type; // Prevent PHP bug. switch ($type) { case 'role': $sql = 'SELECT role_id FROM ' . ACL_ROLES_TABLE . "\n\t\t\t\t\tWHERE role_name = '" . $this->db->sql_escape($name) . "'"; $this->db->sql_query($sql); $role_id = (int) $this->db->sql_fetchfield('role_id'); if (!$role_id) { throw new \src\db\migration\exception('ROLE_NOT_EXIST', $name); } $sql = 'DELETE FROM ' . ACL_ROLES_DATA_TABLE . ' WHERE ' . $this->db->sql_in_set('auth_option_id', $to_remove) . ' AND role_id = ' . (int) $role_id; $this->db->sql_query($sql); break; case 'group': $sql = 'SELECT group_id FROM ' . GROUPS_TABLE . "\n\t\t\t\t\tWHERE group_name = '" . $this->db->sql_escape($name) . "'"; $this->db->sql_query($sql); $group_id = (int) $this->db->sql_fetchfield('group_id'); if (!$group_id) { throw new \src\db\migration\exception('GROUP_NOT_EXIST', $name); } // If the group has a role set for them we will remove the requested permissions from that role. $sql = 'SELECT auth_role_id FROM ' . ACL_GROUPS_TABLE . ' WHERE group_id = ' . $group_id . ' AND auth_role_id <> 0'; $this->db->sql_query($sql); $role_id = (int) $this->db->sql_fetchfield('auth_role_id'); if ($role_id) { $sql = 'SELECT role_name FROM ' . ACL_ROLES_TABLE . ' WHERE role_id = ' . $role_id; $this->db->sql_query($sql); $role_name = $this->db->sql_fetchfield('role_name'); return $this->permission_unset($role_name, $auth_option, 'role'); } $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . ' WHERE ' . $this->db->sql_in_set('auth_option_id', $to_remove); $this->db->sql_query($sql); break; } $this->auth->acl_clear_prefetch(); }
/** * Checks whether a user can download from a particular PM * * @param \src\db\driver\driver_interface $db The database object * @param int $user_id The user id * @param int $msg_id The id of the PM that we are downloading from * * @return bool Whether the user is allowed to download from that PM or not */ function src_download_check_pm_auth($db, $user_id, $msg_id) { // Check if the attachment is within the users scope... $sql = 'SELECT msg_id FROM ' . PRIVMSGS_TO_TABLE . ' WHERE msg_id = ' . (int) $msg_id . ' AND ( user_id = ' . (int) $user_id . ' OR author_id = ' . (int) $user_id . ' )'; $result = $db->sql_query_limit($sql, 1); $allowed = (bool) $db->sql_fetchfield('msg_id'); $db->sql_freeresult($result); return $allowed; }