/** * Mass delete configuration options. * * @param array $keys Set of configuration option names * * @return null */ public function delete_array(array $keys) { $sql = 'DELETE FROM ' . $this->table . ' WHERE ' . $this->db->sql_in_set('config_name', $keys, false, true); $this->db->sql_query($sql); }
/** * Load user helper * * @param array $user_ids */ public function load_users(array $user_ids) { $user_ids[] = ANONYMOUS; // Make user_ids unique and convert to integer. $user_ids = array_map('intval', array_unique($user_ids)); // Do not load users we already have in $this->users $user_ids = array_diff($user_ids, array_keys($this->users)); if (sizeof($user_ids)) { $sql = 'SELECT * FROM ' . $this->users_table . ' WHERE ' . $this->db->sql_in_set('user_id', $user_ids); $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { $this->users[$row['user_id']] = $row; } $this->db->sql_freeresult($result); } }
/** * Updates rows in given table from a set of values to a new value. * If this results in rows violating uniqueness constraints, the duplicate * rows are merged respecting notify_status (0 takes precedence over 1). * * The only supported table is topics_watch. * * @param \src\db\driver\driver_interface $db Database object * @param string $table Table on which to perform the update * @param string $column Column whose values to change * @param array $from_values An array of values that should be changed * @param int $to_value The new value * @return null */ function src_update_rows_avoiding_duplicates_notify_status(\src\db\driver\driver_interface $db, $table, $column, $from_values, $to_value) { $sql = "SELECT {$column}, user_id, notify_status\n\t\tFROM {$table}\n\t\tWHERE " . $db->sql_in_set($column, $from_values); $result = $db->sql_query($sql); $old_user_ids = array(); while ($row = $db->sql_fetchrow($result)) { $old_user_ids[(int) $row['notify_status']][$row[$column]][] = (int) $row['user_id']; } $db->sql_freeresult($result); $sql = "SELECT {$column}, user_id\n\t\tFROM {$table}\n\t\tWHERE {$column} = " . (int) $to_value; $result = $db->sql_query($sql); $new_user_ids = array(); while ($row = $db->sql_fetchrow($result)) { $new_user_ids[$row[$column]][] = (int) $row['user_id']; } $db->sql_freeresult($result); $queries = array(); $extra_updates = array(0 => 'notify_status = 0', 1 => ''); foreach ($from_values as $from_value) { foreach ($extra_updates as $notify_status => $extra_update) { if (!isset($old_user_ids[$notify_status][$from_value])) { continue; } if (empty($new_user_ids)) { $sql = "UPDATE {$table}\n\t\t\t\t\tSET {$column} = " . (int) $to_value . "\n\t\t\t\t\tWHERE {$column} = '" . $db->sql_escape($from_value) . "'"; $queries[] = $sql; } else { $different_user_ids = array_diff($old_user_ids[$notify_status][$from_value], $new_user_ids[$to_value]); if (!empty($different_user_ids)) { $sql = "UPDATE {$table}\n\t\t\t\t\t\tSET {$column} = " . (int) $to_value . "\n\t\t\t\t\t\tWHERE {$column} = '" . $db->sql_escape($from_value) . "'\n\t\t\t\t\t\tAND " . $db->sql_in_set('user_id', $different_user_ids); $queries[] = $sql; } if ($extra_update) { $same_user_ids = array_diff($old_user_ids[$notify_status][$from_value], $different_user_ids); if (!empty($same_user_ids)) { $sql = "UPDATE {$table}\n\t\t\t\t\t\t\tSET {$extra_update}\n\t\t\t\t\t\t\tWHERE {$column} = '" . (int) $to_value . "'\n\t\t\t\t\t\t\tAND " . $db->sql_in_set('user_id', $same_user_ids); $queries[] = $sql; } } } } } if (!empty($queries)) { $db->sql_transaction('begin'); foreach ($queries as $sql) { $db->sql_query($sql); } $sql = "DELETE FROM {$table}\n\t\t\tWHERE " . $db->sql_in_set($column, $from_values); $db->sql_query($sql); $db->sql_transaction('commit'); } }
/** * Delete a notification * * @param string|array $notification_type_name Type identifier or array of item types (only acceptable if the $item_id is identical for the specified types) * @param int|array $item_id Identifier within the type (or array of ids) * @param mixed $parent_id Parent identifier within the type (or array of ids), used in combination with item_id if specified (Default: false; not checked) */ public function delete_notifications($notification_type_name, $item_id, $parent_id = false) { if (is_array($notification_type_name)) { foreach ($notification_type_name as $type) { $this->delete_notifications($type, $item_id, $parent_id); } return; } $notification_type_id = $this->get_notification_type_id($notification_type_name); $sql = 'DELETE FROM ' . $this->notifications_table . ' WHERE notification_type_id = ' . (int) $notification_type_id . ' AND ' . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id) . ($parent_id !== false ? ' AND ' . (is_array($parent_id) ? $this->db->sql_in_set('item_parent_id', $parent_id) : 'item_parent_id = ' . (int) $parent_id) : ''); $this->db->sql_query($sql); }
/** * Prepare adding a subset to the nested set * * @param array $subset_items Subset of items to add * @param array $new_parent Item containing the right bound of the new parent * @return int New right id of the parent item */ protected function prepare_adding_subset(array $subset_items, array $new_parent) { $diff = sizeof($subset_items) * 2; $sql_not_subset_items = $this->db->sql_in_set($this->column_item_id, $subset_items, true); $set_left_id = $this->db->sql_case($this->column_left_id . ' > ' . (int) $new_parent[$this->column_right_id], $this->column_left_id . ' + ' . $diff, $this->column_left_id); $set_right_id = $this->db->sql_case($this->column_right_id . ' >= ' . (int) $new_parent[$this->column_right_id], $this->column_right_id . ' + ' . $diff, $this->column_right_id); $sql = 'UPDATE ' . $this->table_name . ' SET ' . $this->column_left_id . ' = ' . $set_left_id . ', ' . $this->column_right_id . ' = ' . $set_right_id . ' WHERE ' . $sql_not_subset_items . ' ' . $this->get_sql_where('AND'); $this->db->sql_query($sql); return $new_parent[$this->column_right_id] + $diff; }
/** * Tidy up indexes: Tag 'common words' and remove * words no longer referenced in the match table */ public function tidy() { // Is the fulltext indexer disabled? If yes then we need not // carry on ... it's okay ... I know when I'm not wanted boo hoo if (!$this->config['fulltext_native_load_upd']) { set_config('search_last_gc', time(), true); return; } $destroy_cache_words = array(); // Remove common words if ($this->config['num_posts'] >= 100 && $this->config['fulltext_native_common_thres']) { $common_threshold = (double) $this->config['fulltext_native_common_thres'] / 100.0; // First, get the IDs of common words $sql = 'SELECT word_id, word_text FROM ' . SEARCH_WORDLIST_TABLE . ' WHERE word_count > ' . floor($this->config['num_posts'] * $common_threshold) . ' OR word_common = 1'; $result = $this->db->sql_query($sql); $sql_in = array(); while ($row = $this->db->sql_fetchrow($result)) { $sql_in[] = $row['word_id']; $destroy_cache_words[] = $row['word_text']; } $this->db->sql_freeresult($result); if (sizeof($sql_in)) { // Flag the words $sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . ' SET word_common = 1 WHERE ' . $this->db->sql_in_set('word_id', $sql_in); $this->db->sql_query($sql); // by setting search_last_gc to the new time here we make sure that if a user reloads because the // following query takes too long, he won't run into it again set_config('search_last_gc', time(), true); // Delete the matches $sql = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE . ' WHERE ' . $this->db->sql_in_set('word_id', $sql_in); $this->db->sql_query($sql); } unset($sql_in); } if (sizeof($destroy_cache_words)) { // destroy cached search results containing any of the words that are now common or were removed $this->destroy_cache(array_unique($destroy_cache_words)); } set_config('search_last_gc', time(), true); }
/** * Build Array for user insertion into custom profile fields table */ public function build_insert_sql_array($cp_data) { $sql_not_in = array(); foreach ($cp_data as $key => $null) { $sql_not_in[] = strncmp($key, 'pf_', 3) === 0 ? substr($key, 3) : $key; } $sql = 'SELECT f.field_type, f.field_ident, f.field_default_value, l.lang_default_value FROM ' . $this->fields_language_table . ' l, ' . $this->fields_table . ' f WHERE l.lang_id = ' . $this->user->get_iso_lang_id() . ' ' . (sizeof($sql_not_in) ? ' AND ' . $this->db->sql_in_set('f.field_ident', $sql_not_in, true) : '') . ' AND l.field_id = f.field_id'; $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { $profile_field = $this->type_collection[$row['field_type']]; $cp_data['pf_' . $row['field_ident']] = $profile_field->get_default_field_value($row); } $this->db->sql_freeresult($result); return $cp_data; }
/** * Find the users who want to receive notifications (helper) * * @param array $user_ids User IDs to check if they want to receive notifications * (Bool False to check all users besides anonymous and bots (USER_IGNORE)) * * @return array */ protected function check_user_notification_options($user_ids = false, $options = array()) { $options = array_merge(array('ignore_users' => array(), 'item_type' => $this->get_type(), 'item_id' => 0), $options); if ($user_ids === false) { $user_ids = array(); $sql = 'SELECT user_id FROM ' . USERS_TABLE . ' WHERE user_id <> ' . ANONYMOUS . ' AND user_type <> ' . USER_IGNORE; $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { $user_ids[] = $row['user_id']; } $this->db->sql_freeresult($result); } if (empty($user_ids)) { return array(); } $rowset = $resulting_user_ids = array(); $sql = 'SELECT user_id, method, notify FROM ' . $this->user_notifications_table . ' WHERE ' . $this->db->sql_in_set('user_id', $user_ids) . "\n\t\t\t\tAND item_type = '" . $this->db->sql_escape($options['item_type']) . "'\n\t\t\t\tAND item_id = " . (int) $options['item_id']; $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { $resulting_user_ids[] = $row['user_id']; if (!$row['notify'] || isset($options['ignore_users'][$row['user_id']]) && in_array($row['method'], $options['ignore_users'][$row['user_id']])) { continue; } if (!isset($rowset[$row['user_id']])) { $rowset[$row['user_id']] = array(); } $rowset[$row['user_id']][] = $row['method']; } $this->db->sql_freeresult($result); foreach ($user_ids as $user_id) { if (!in_array($user_id, $resulting_user_ids) && !isset($options['ignore_users'][$user_id])) { // No rows at all for this user, default to '' $rowset[$user_id] = array(''); } } return $rowset; }
/** * 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(); }
/** * Increments the download count of all provided attachments * * @param \src\db\driver\driver_interface $db The database object * @param array|int $ids The attach_id of each attachment * * @return null */ function src_increment_downloads($db, $ids) { if (!is_array($ids)) { $ids = array($ids); } $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET download_count = download_count + 1 WHERE ' . $db->sql_in_set('attach_id', $ids); $db->sql_query($sql); }