public static function fast_count($tags = null) { # A small sanitation $tags = preg_replace('/ +/', ' ', trim($tags)); $cache_version = (int) Rails::cache()->read('$cache_version'); $key = ['post_count' => $tags, 'v' => $cache_version]; $count = (int) Rails::cache()->fetch($key, function () use($tags) { list($sql, $params) = Post::generate_sql($tags, ['count' => true]); array_unshift($params, $sql); return Post::countBySql($params); }); return $count; # This is just too brittle, and hard to make work with other features that may # hide posts from the index. # if tags.blank? # return select_value_sql("SELECT row_count FROM table_data WHERE name = 'posts'").to_i # else # c = select_value_sql("SELECT post_count FROM tags WHERE name = ?", tags).to_i # if c == 0 # return Post.count_by_sql(Post.generate_sql(tags, :count => true)) # else # return c # end # end }
public function show() { if (isset($this->params()->samples) && $this->params()->samples == 0) { unset($this->params()->samples); } $this->pool = Pool::find($this->params()->id); $this->browse_mode = current_user()->pool_browse_mode; $q = []; $q['pool'] = (int) $this->params()->id; $q['show_deleted_only'] = false; if ($this->browse_mode == 1) { $q['limit'] = 1000; $q['order'] = "portrait_pool"; } else { $q['limit'] = 24; } $page = (int) $this->page_number() > 0 ? (int) $this->page_number() : 1; $offset = ($page - 1) * $q['limit']; list($sql, $params) = Post::generate_sql($q, array('from_api' => true, 'offset' => $offset, 'limit' => $q['limit'])); # Stringify query so it can be passed to fast_count. $tag_query = []; foreach ($q as $tag => $value) { if ($tag == 'show_deleted_only') { $tag = 'deleted'; $value = 'all'; } $tag_query[] = $tag . ':' . $value; } $count = Post::fast_count(implode(' ', $tag_query)); $posts = Post::findBySql($sql, $params); $this->posts = new Rails\ActiveRecord\Collection($posts->members(), ['page' => $page, 'perPage' => $q['limit'], 'offset' => $offset, 'totalRows' => $count]); $this->set_title($this->pool->pretty_name()); # iTODO: $this->respondTo(['html', 'json' => function () { $this->render(['json' => json_encode(array_merge($this->pool->asJson(), ['posts' => $this->posts->asJson()]))]); }]); }
if (isset(Request::$params->samples) && Request::$params->samples == 0) { unset(Request::$params->samples); } $pool = Pool::find(array(Request::$params->id)); if (!$pool) { return 404; } $browse_mode = User::$current->pool_browse_mode; // $q = Tag::parse_query(""); $q = array(); $q['pool'] = (int) Request::$params->id; $q['show_deleted_only'] = false; if ($browse_mode == 1) { $q['limit'] = 1000; $q['order'] = "portrait_pool"; } else { $q['limit'] = 24; } // $count = Post::count_by_sql(Post::generate_sql($q, array('from_api' => true, 'count' => true))); // WillPaginate::Collection.new(params[:page], q[:limit], count) $sql = Post::generate_sql($q, array('from_api' => true, 'offset' => $offset, 'limit' => $pagination_limit)); $posts = Post::find_by_sql(array($sql), array('calc_rows' => 'found_posts')); calc_pages(); set_title($pool->pretty_name()); switch (Request::$format) { case 'json': render('json', $pool->to_json()); break; case 'xml': break; }
public function index() { $tags = $this->params()->tags; $split_tags = $tags ? array_filter(explode(' ', $tags)) : array(); $page = $this->page_number(); $this->tag_suggestions = $this->searching_pool = array(); /* if $this->current_user.is_member_or_lower? && count(split_tags) > 2 # $this->respond_to_error("You can only search up to two tags at once with a basic account", 'action' => "error") # return; # elseif count(split_tags) > 6 */ if (count($split_tags) > CONFIG()->tag_query_limit) { $this->respond_to_error("You can only search up to " . CONFIG()->tag_query_limit . " tags at once", "#error"); return; } $q = Tag::parse_query($tags); $limit = (int) $this->params()->limit; isset($q['limit']) && ($limit = (int) $q['limit']); $limit <= 0 && ($limit = CONFIG()->post_index_default_limit); $limit > 1000 && ($limit = 1000); $count = 0; $this->set_title("/" . str_replace("_", " ", $tags)); // try { $count = Post::fast_count($tags); // vde($count); // } catch(Exception $x) { // $this->respond_to_error("Error: " . $x->getMessage(), "#error"); // return; // } $this->ambiguous_tags = Tag::select_ambiguous($split_tags); if (isset($q['pool']) and is_int($q['pool'])) { $this->searching_pool = Pool::where(['id' => $q['pool']])->first(); } $from_api = $this->params()->format == "json" || $this->params()->format == "xml"; // $this->posts = Post::find_all(array('page' => $page, 'per_page' => $limit, $count)); // $this->posts = WillPaginate::Collection.new(page, limit, count); // $offset = $this->posts->offset(); // $posts_to_load = $this->posts->per_page(); $per_page = $limit; $offset = ($page - 1) * $per_page; $posts_to_load = $per_page; if (!$from_api) { # For forward preloading: // $posts_to_load += $this->posts->per_page(); $posts_to_load += $per_page; # If we're not on the first page, load the previous page for prefetching. Prefetching # the previous page when the user is scanning forward should be free, since it'll already # be in cache, so this makes scanning the index from back to front as responsive as from # front to back. if ($page and $page > 1) { // $offset -= $this->posts->per_page(); // $posts_to_load += $this->posts->per_page(); $offset -= $per_page; $posts_to_load += $per_page; } } $this->showing_holds_only = isset($q['show_holds']) && $q['show_holds'] == 'only'; list($sql, $params) = Post::generate_sql($q, array('original_query' => $tags, 'from_api' => $from_api, 'order' => "p.id DESC", 'offset' => $offset, 'limit' => $posts_to_load)); $results = Post::findBySql($sql, $params); $this->preload = new Rails\ActiveRecord\Collection(); if (!$from_api) { if ($page && $page > 1) { $this->preload = $results->slice(0, $limit); $results = $results->slice($limit); } $this->preload->merge($results->slice($limit)); $results = $results->slice(0, $limit); } # Apply can_be_seen_by filtering to the results. For API calls this is optional, and # can be enabled by specifying filter=1. if (!$from_api or $this->params()->filter) { $results->deleteIf(function ($post) { return !$post->can_be_seen_by(current_user(), array('show_deleted' => true)); }); $this->preload->deleteIf(function ($post) { return !$post->can_be_seen_by(current_user()); }); } if ($from_api and $this->params()->api_version == "2" and $this->params()->format != "json") { $this->respond_to_error("V2 API is JSON-only", array(), array('status' => 424)); return; } $this->posts = new Rails\ActiveRecord\Collection($results->members(), ['page' => $page, 'perPage' => $per_page, 'totalRows' => $count]); if ($count < CONFIG()->post_index_default_limit && count($split_tags) == 1) { $this->tag_suggestions = Tag::find_suggestions($tags); } // exit; $this->respondTo(array('html' => function () use($split_tags, $tags) { if ($split_tags) { $this->tags = Tag::parse_query($tags); } else { $this->tags = Rails::cache()->fetch('$poptags', ['expires_in' => '1 hour'], function () { return array('include' => Tag::count_by_period(date('Y-m-d', strtotime('-' . CONFIG()->post_index_tags_limit)), date('Y-m-d H:i:s'), array('limit' => 25, 'exclude_types' => CONFIG()->exclude_from_tag_sidebar))); }); } }, 'xml' => function () { $this->setLayout(false); }, 'json' => function () { if ($this->params()->api_version != "2") { $this->render(array('json' => array_map(function ($p) { return $p->api_attributes(); }, $this->posts->members()))); return; } $api_data = Post::batch_api_data($this->posts->members(), array('exclude_tags' => $this->params()->include_tags != "1", 'exclude_votes' => $this->params()->include_votes != "1", 'exclude_pools' => $this->params()->include_pools != "1", 'fake_sample_url' => CONFIG()->fake_sample_url)); $this->render(array('json' => json_encode($api_data))); })); }
$post->destroy_with_reason(Request::$params->reason ? Request::$params->reason : Request::$params->reason2, User::$current); # Include post data for the parent: deleted posts aren't counted as children, so # their has_children attribute may change. if (!empty($post->parent_id)) { $posts[] = $post->get_parent(); } } $post->reload(); $posts[] = $post; } } $posts = array_unique($posts); if (Request::$format == "json" || Request::$format == "xml") { $api_data = Post::batch_api_data($posts); } else { $api_data = array(); } if (Request::$params->commit == "Approve") { respond_to_success("Post approved", "#moderate", array('api' => $api_data)); } elseif (Request::$params->commit == "Delete") { respond_to_success("Post deleted", "#moderate", array('api' => $api_data)); } } else { if (!empty(Request::$params->query)) { $pending_posts = Post::find_by_sql(Post::generate_sql(Request::$params->query, array('pending' => true, 'order' => "id desc"))); $flagged_posts = Post::find_by_sql(Post::generate_sql(Request::$params->query, array('flagged' => true, 'order' => "id desc"))); } else { $pending_posts = Post::find('all', array('conditions' => "status = 'pending'", 'order' => "id desc")); $flagged_posts = Post::find('all', array('conditions' => "status = 'flagged'", 'order' => "id desc")); } }
// offset = @posts.offset // posts_to_load = @posts.per_page if (!$from_api) { # For forward preloading: // posts_to_load += @posts.per_page # If we're not on the first page, load the previous page for prefetching. Prefetching # the previous page when the user is scanning forward should be free, since it'll already # be in cache, so this makes scanning the index from back to front as responsive as from # front to back. // if page and page > 1 then // offset -= @posts.per_page // posts_to_load += @posts.per_page // end } $showing_holds_only = !empty($q['show_holds']) && $q['show_holds'] == 'only'; $sql = Post::generate_sql($q, array('original_query' => $tags, 'from_api' => $from_api, 'order' => "p.id DESC", 'offset' => $offset, 'limit' => $limit)); $results = Post::find_by_sql(array($sql), array('calc_rows' => 'found_posts')); $preload = array(); // if not from_api then // if page && page > 1 then // @preload = results[0, limit] || [] // results = results[limit..-1] || [] // end // @preload += results[limit..-1] || [] // results = results[0..limit-1] // end # Apply can_be_seen_by filtering to the results. For API calls this is optional, and # can be enabled by specifying filter=1. if (!$from_api or isset(Request::$params->filter) && Request::$params->filter == "1") { foreach ($results as $k => $post) { if (!$post->can_be_seen_by(User::$current, array('show_deleted' => true))) {
public static function find_by_tags($tags, array $options = array()) { list($sql, $params) = Post::generate_sql($tags, $options); return Post::findBySql($sql, $params); }
public function editPreview() { list($sql, $params) = Post::generate_sql($this->params()->tags, ['order' => "p.id DESC", 'limit' => 500]); $this->posts = Post::findBySql($sql, $params); $this->setLayout(false); }