diff --git a/README.md b/README.md index d12e824..71e09e6 100755 --- a/README.md +++ b/README.md @@ -33,8 +33,11 @@ Go to the location where you want MyImouto to be installed, then clone the repo, * If you're not accessing the site locally, list the IP address you'll connect from in the 'safe_ips' array in _install/config.php_. * Go to your site to complete the installation. After installation is completed, you may delete the install folder. * If you have problems, read below the Troubleshooting section or report them in the issues section. + +Updating +-------- -Every time you update the files with `remote update` or something, also run `composer update` to update dependencies, specially for the framework. +Every time you update the files with `git remote update` or something, also run `composer update` to update dependencies, specially for the framework, and also `php config/boot.php db:migrate` to run database migrations. Troubleshooting --------------- diff --git a/app/controllers/CommentController.php b/app/controllers/CommentController.php index a0b9d72..68c0ee7 100755 --- a/app/controllers/CommentController.php +++ b/app/controllers/CommentController.php @@ -25,7 +25,7 @@ class CommentController extends ApplicationController { $comment = Comment::find($this->params()->id); if (current_user()->has_permission($comment)) { - $comment->updateAttributes($this->params()->comment); + $comment->updateAttributes(array_merge($this->params()->comment, ['updater_ip_addr' => $this->request()->remoteIp()])); $this->respond_to_success("Comment updated", '#index'); } else { $this->access_denied(); @@ -52,7 +52,7 @@ class CommentController extends ApplicationController } $user_id = current_user()->id; -Rails::log($this->params()->comment); + $comment = new Comment(array_merge($this->params()->comment, array('ip_addr' => $this->request()->remoteIp(), 'user_id' => $user_id))); if ($this->params()->commit == "Post without bumping") { $comment->do_not_bump_post = true; diff --git a/app/controllers/DmailController.php b/app/controllers/DmailController.php index 0d4b59a..cbdb903 100755 --- a/app/controllers/DmailController.php +++ b/app/controllers/DmailController.php @@ -36,7 +36,7 @@ class DmailController extends ApplicationController $dmail = $this->params()->dmail; if (empty($dmail['parent_id'])) $dmail['parent_id'] = null; - $this->dmail = Dmail::create(array_merge($dmail, ['from_id' => $this->current_user->id])); + $this->dmail = Dmail::create(array_merge($dmail, ['from_id' => $this->current_user->id, 'ip_addr' => $this->request()->remoteIp()])); if ($this->dmail->errors()->none()) { $this->notice("Message sent to ".$dmail['to_name']); diff --git a/app/controllers/ForumController.php b/app/controllers/ForumController.php index b6793e3..8c5696a 100755 --- a/app/controllers/ForumController.php +++ b/app/controllers/ForumController.php @@ -65,7 +65,7 @@ class ForumController extends ApplicationController if (empty($params['parent_id']) || !ctype_digit($params['parent_id'])) $params['parent_id'] = null; - $this->forum_post = ForumPost::create(array_merge($params, ['creator_id' => $this->current_user->id])); + $this->forum_post = ForumPost::create(array_merge($params, ['creator_id' => $this->current_user->id, 'ip_addr' => $this->request()->remoteIp()])); if ($this->forum_post->errors()->blank()) { if (!$this->params()->forum_post['parent_id']) { @@ -120,10 +120,12 @@ class ForumController extends ApplicationController return; } - $this->forum_post->assignAttributes($this->params()->forum_post); + $this->forum_post->assignAttributes(array_merge($this->params()->forum_post, ['updater_ip_addr' => $this->request()->remoteIp()])); if ($this->forum_post->save()) { $this->notice("Post updated"); - $this->redirectTo(["#show", 'id' => $this->forum_post->root_id(), 'page' => ceil($this->forum_post->root()->response_count / 30.0)]); + + $page = $this->params()->page ? $this->page_number() : ceil($this->forum_post->root()->response_count / 30.0); + $this->redirectTo(["#show", 'id' => $this->forum_post->root_id(), 'page' => $page]); } else { $this->_render_error($this->forum_post); } @@ -132,7 +134,7 @@ class ForumController extends ApplicationController public function show() { $this->forum_post = ForumPost::find($this->params()->id); - $this->children = ForumPost::where("parent_id = ?", $this->params()->id)->order("id")->paginate($this->page_number(), 30); + $this->children = ForumPost::where("parent_id = ?", $this->params()->id)->order("id")->paginate($this->page_number(), 30); if (!$this->current_user->is_anonymous() && $this->current_user->last_forum_topic_read_at < $this->forum_post->updated_at && $this->forum_post->updated_at < (time() - 3)) { $this->current_user->updateAttribute('last_forum_topic_read_at', $this->forum_post->updated_at); diff --git a/app/models/Advertisement.php b/app/models/Advertisement.php new file mode 100644 index 0000000..f38080a --- /dev/null +++ b/app/models/Advertisement.php @@ -0,0 +1,5 @@ +id . ":" . strtotime($this->updated_at) . ":" . $target_lang . ":" . $source_lang_list; - # TODO - // return Rails::cache()->fetch($key) { + + return Rails::cache()->fetch($key, function() use ($target_lang, $source_langs) { return $this->get_translated_formatted_body_uncached($target_lang, $source_langs); - // } + }); } public function author() diff --git a/app/models/FlaggedPostDetail.php b/app/models/FlaggedPostDetail.php index 04e49f1..8a63af2 100755 --- a/app/models/FlaggedPostDetail.php +++ b/app/models/FlaggedPostDetail.php @@ -21,21 +21,21 @@ class FlaggedPostDetail extends Rails\ActiveRecord\Base static public function new_deleted_posts($user) { - if ($user->is_anonymous()) + if ($user->is_anonymous()) { return 0; + } - return self::connection()->selectValue( - "SELECT COUNT(*) FROM flagged_post_details fpd JOIN posts p ON (p.id = fpd.post_id) " . - "WHERE p.status = 'deleted' AND p.user_id = ? AND fpd.user_id <> ? AND fpd.created_at > ?", - $user->id, $user->id, $user->last_deleted_post_seen_at + return Rails::cache()->fetch( + 'deleted_posts:'.$user->id.':'.$user->last_deleted_post_seen_at, + ['expires_in' => '1 minute'], + function() use ($user) { + return self::connection()->selectValue( + "SELECT COUNT(*) FROM flagged_post_details fpd JOIN posts p ON (p.id = fpd.post_id) " . + "WHERE p.status = 'deleted' AND p.user_id = ? AND fpd.user_id <> ? AND fpd.created_at > ?", + $user->id, $user->id, $user->last_deleted_post_seen_at + ); + } ); - # iTODO: - // return Rails.cache.fetch("deleted_posts:#{user.id}:#{user.last_deleted_post_seen_at.to_i}", :expires_in => 1.minute) do - // select_value_sql( - // "SELECT COUNT(*) FROM flagged_post_details fpd JOIN posts p ON (p.id = fpd.post_id) " + - // "WHERE p.status = 'deleted' AND p.user_id = ? AND fpd.user_id <> ? AND fpd.created_at > ?", - // user.id, user.id, user.last_deleted_post_seen_at).to_i - // end } # XXX: author and flagged_by are redundant @@ -73,4 +73,4 @@ class FlaggedPostDetail extends Rails\ActiveRecord\Base // {(options = array()) // return; api_attributes.to_xml(options.reverse_merge('root' => "flagged_post_detail")) // } -} \ No newline at end of file +} diff --git a/app/models/ForumPost.php b/app/models/ForumPost.php index ddcfd2f..bf8a26b 100755 --- a/app/models/ForumPost.php +++ b/app/models/ForumPost.php @@ -18,7 +18,7 @@ class ForumPost extends Rails\ActiveRecord\Base protected function callbacks() { return [ - 'after_create' => ['initialize_last_updated_by', 'update_parent_on_create'], + 'after_create' => ['initialize_last_updated_by', 'update_parent_on_create', 'clear_cache'], 'before_destroy' => ['update_parent_on_destroy'], 'before_validation' => ['validate_title', 'validate_lock'] ]; @@ -180,4 +180,9 @@ class ForumPost extends Rails\ActiveRecord\Base { return $this->creator->name; } -} \ No newline at end of file + + protected function clear_cache() + { + Rails::cache()->delete("forum_posts"); + } +} diff --git a/app/models/History.php b/app/models/History.php index 68c1e77..af5dad7 100755 --- a/app/models/History.php +++ b/app/models/History.php @@ -104,12 +104,12 @@ class History extends Rails\ActiveRecord\Base foreach (array_reverse($stack) as $node) { $object = $node['o']; - /** - * MI: Only Pool model sets the undo (:after) callback. - * Calling it manually at the end because runCallbacks doesn't behave like in Rails. - * TODO: fix callbacks in the framework and update this. - */ - // $object->runCallbacks('undo', function() { + // /** + // * MI: Only Pool model sets the undo (:after) callback. + // * Calling it manually at the end because runCallbacks doesn't behave like in Rails. + // * TODO: fix callbacks in the framework and update this. + // */ + $object->runCallbacks('undo', function() { $changes = !empty($node['changes']) ? $node['changes'] : []; if ($changes) { @@ -137,8 +137,8 @@ class History extends Rails\ActiveRecord\Base } } } - $object->runCallbacks('after_undo'); - // }); + // $object->runCallbacks('after_undo'); + }); $object->save(); } diff --git a/app/models/Note.php b/app/models/Note.php index 3b12b80..ba1f531 100755 --- a/app/models/Note.php +++ b/app/models/Note.php @@ -61,11 +61,11 @@ class Note extends Rails\ActiveRecord\Base protected function callbacks() { - return array_merge_recursive([ + return [ 'after_save' => [ 'update_post' ] - ], $this->versioning_callbacks(), $this->versioningCallbacks()); + ]; } protected function validations() diff --git a/app/models/Pool.php b/app/models/Pool.php index 70e74cc..f691341 100755 --- a/app/models/Pool.php +++ b/app/models/Pool.php @@ -362,11 +362,11 @@ class Pool extends Rails\ActiveRecord\Base protected function callbacks() { - return array_merge_recursive([ + return [ 'before_destroy' => ['destroy_pool_posts'], 'after_save' => ['expire_cache'], 'before_validation' => ['normalize_name'], 'after_undo' => ['update_pool_links'] - ], $this->versioning_callbacks()); + ]; } } diff --git a/app/models/PoolPost.php b/app/models/PoolPost.php index 7b0d57f..3f677ba 100755 --- a/app/models/PoolPost.php +++ b/app/models/PoolPost.php @@ -42,10 +42,10 @@ class PoolPost extends Rails\ActiveRecord\Base protected function callbacks() { - return array_merge_recursive([ + return [ 'before_create' => ['set_active_changed'], # MI 'after_save' => ['expire_cache'] - ], $this->versioning_callbacks()); + ]; } public function can_change(User $user, $attribute) diff --git a/app/models/Post.php b/app/models/Post.php index b4d2a0c..529af6c 100755 --- a/app/models/Post.php +++ b/app/models/Post.php @@ -195,8 +195,9 @@ class Post extends Rails\ActiveRecord\Base public function first_delete() { - $this->updateAttributes(array('status' => 'deleted')); - $this->runCallbacks('after_delete'); + $this->runCallbacks('delete', function() { + $this->updateAttributes(array('status' => 'deleted')); + }); } public function delete_from_database() @@ -211,14 +212,14 @@ class Post extends Rails\ActiveRecord\Base $this->runCallbacks('after_destroy'); } - # This method is in status_methods public function undelete() { - $this->status = 'active'; - $this->save(); - if ($this->parent_id) { - Post::update_has_children($this->parent_id); + if ($this->status == 'active') { + return; } + $this->runCallbacks('undelete', function() { + $this->updateAttributes(['status' => 'active']); + }); } public function service_icon() @@ -228,20 +229,28 @@ class Post extends Rails\ActiveRecord\Base protected function callbacks() { - return array_merge_recursive([ - 'before_save' => ['commit_tags', 'filter_parent_id'], + return [ 'before_create' => ['set_index_timestamp'], 'after_create' => ['after_creation'], - 'after_delete' => ['clear_avatars', 'give_favorites_to_parent'], + + 'before_delete' => ['clear_avatars'], + 'after_delete' => ['give_favorites_to_parent', 'decrement_count'], + + 'after_undelete'=> ['increment_count'], + + 'before_save' => ['commit_tags', 'filter_parent_id'], 'after_save' => ['update_parent', 'save_post_history', 'expire_cache'], + 'after_destroy' => ['expire_cache'], - 'after_validation_on_create' => ['before_creation'], + 'before_validation_on_create' => [ 'download_source', 'ensure_tempfile_exists', 'determine_content_type', 'validate_content_type', 'generate_hash', 'set_image_dimensions', 'set_image_status', 'check_pending_count', 'generate_sample', - 'generate_jpeg', 'generate_preview', 'move_file'] - ], $this->versioning_callbacks()); + 'generate_jpeg', 'generate_preview', 'move_file' + ], + 'after_validation_on_create' => ['before_creation'] + ]; } protected function associations() diff --git a/app/models/Post/CountMethods.php b/app/models/Post/CountMethods.php index 4903be9..c95a6a6 100755 --- a/app/models/Post/CountMethods.php +++ b/app/models/Post/CountMethods.php @@ -5,25 +5,30 @@ trait PostCountMethods { # A small sanitation $tags = preg_replace('/ +/', ' ', trim($tags)); - - # No cache. This query is too slow, if no tags, just return row_count(). - if (!$tags) { - return self::row_count(); - } - - // cache_version = Rails.cache.read("$cache_version").to_i - # Use base64 encoding of tags query for memcache key - // tags_base64 = Base64.urlsafe_encode64(tags) - // key = "post-count/v=#{cache_version}/#{tags_base64}" + $cache_version = (int)Rails::cache()->read('$cache_version'); + # iTODO: cache hash key + $key = 'post_count.' . $tags . ':' . 'v.' . $cache_version; - // count = Rails.cache.fetch(key) { - // Post.count_by_sql(Post.generate_sql(tags, :count => true)) - // }.to_i - list($sql, $params) = Post::generate_sql($tags, array('count' => true)); - // vde($sql); - array_unshift($params, $sql); - - return Post::countBySql($params); + $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 } static public function recalculate_row_count() diff --git a/app/models/Post/StatusMethods.php b/app/models/Post/StatusMethods.php index 3abd30f..6370740 100755 --- a/app/models/Post/StatusMethods.php +++ b/app/models/Post/StatusMethods.php @@ -114,11 +114,13 @@ trait PostStatusMethods return $hold; } - public function undelete() - { - if ($this->status == 'active') - return; - $this->updateAttribute('status', 'active'); - $this->runCallbacks('after_undelete'); - } + # MI: Can't have a method with bang! + // public function undelete!() + // { + // $this->status = 'active'; + // $this->save(); + // if ($this->parent_id) { + // Post::update_has_children($this->parent_id); + // } + // } } \ No newline at end of file diff --git a/app/models/Post/TagMethods.php b/app/models/Post/TagMethods.php index 4c60029..5e6306e 100755 --- a/app/models/Post/TagMethods.php +++ b/app/models/Post/TagMethods.php @@ -324,7 +324,7 @@ trait PostTagMethods $this->new_tags = array_map(function ($x) use (&$new_tags_ids, &$new_tags_names) { $tag = Tag::find_or_create_by_name($x); if (!in_array($tag->id, $new_tags_ids)) { - $new_tags_ids[] = $tag->id; + $new_tags_ids[] = $tag->id; $new_tags_names[] = $tag->name; return $tag; } @@ -352,6 +352,10 @@ trait PostTagMethods } } + # Sort + sort($new_tags_names); + sort($this->new_tags); + $tag_set = implode(", ", array_map(function($x){return "(".$this->id.", ".$x->id.")";}, $this->new_tags)); $this->cached_tags = implode(' ', $new_tags_names); diff --git a/app/models/Tag.php b/app/models/Tag.php index 73e853a..3422014 100755 --- a/app/models/Tag.php +++ b/app/models/Tag.php @@ -315,9 +315,9 @@ class Tag extends Rails\ActiveRecord\Base # # === Parameters # * :tag_name:: The tag name to search for - # TODO static public function type_name($tag_name) { + # iTODO: hash key return Rails::cache()->fetch('tag_type.' . $tag_name, ['expires_in' => '1 day'], function() use ($tag_name) { return self::type_name_helper(str_replace(' ', '_', $tag_name)); }); @@ -362,29 +362,29 @@ class Tag extends Rails\ActiveRecord\Base # Get all tag types for the given tags. static public function batch_get_tag_types($post_tags) { - $types = []; - foreach ($post_tags as $tag) { - $types[$tag] = self::type_name($tag); - } - return $types; + $post_tags_key = []; - // $post_tags = Set.new(post_tags) - - // post_tags_key = post_tags.each_with_object([]) { |t, k| k << { :tag_type => t } } - // # Without this, the following splat will eat the last argument because - // # it'll be considered an option instead of key (being a hash). - // post_tags_key << {} - - // results = {} - // Rails.cache.read_multi(*post_tags_key).each do |cache_key, value| - // # The if cache_key is required since there's small chance read_multi - // # returning nil key on certain key names. - // results[cache_key[:tag_type]] = value if cache_key - // end - // (post_tags - results.keys).each do |tag| - // results[tag] = type_name(tag) - // end - // return results + foreach ($post_tags as $t) { + # iTODO: hash keys. + $post_tags_key[] = 'tag_type.' . $t; + } + # Without this, the following splat will eat the last argument because + # it'll be considered an option instead of key (being a hash). + $post_tags_key[] = []; + + $results = []; + $cached = call_user_func_array([Rails::cache(), 'readMulti'], $post_tags_key); + foreach ($cached as $cache_key => $value) { + # The if cache_key is required since there's small chance read_multi + # returning nil key on certain key names. + // if ($cache_key) { + $results[substr($cache_key, 9)] = $value; + // } + } + foreach( array_diff( $post_tags, array_keys($results) ) as $tag ) { + $results[$tag] = self::type_name($tag); + } + return $results; } # Returns tags (with type specified by input) related by input tag @@ -414,15 +414,6 @@ class Tag extends Rails\ActiveRecord\Base $reduced[] = ['name' => $row['name'], 'post_count' => $row['post_count']]; } return $reduced; - - // return Post::select('posts.*, tags.name AS tag_name, tags.post_count AS tag_post_count') - // ->joins('JOIN posts_tags pt ON posts.id = pt.post_id JOIN tags ON pt.tag_id = tags.id') - // ->where('posts.status <> "deleted"')->where('tags.name IN (?)', $tag) - // ->where('tags.tag_type = ?', $type)->group('tags.name')->limit($limit) - // ->take()->reduce([], function($result, $hash) { - // $result[] = ['name' => $hash->tag_name, 'post_count' => $hash->tag_post_count]; - // return $result; - // }); }); } @@ -465,6 +456,7 @@ class Tag extends Rails\ActiveRecord\Base !is_array($tags) && $tags = array($tags); + # iTODO: hash key return Rails::cache()->fetch('category.reltags.tags.' . implode(',', $tags), ['expires_in' => '1 hour'], function() use ($tags) { $from = array("posts_tags pt0"); $cond = array("pt0.post_id = pt1.post_id"); @@ -507,6 +499,13 @@ class Tag extends Rails\ActiveRecord\Base return Rails::cache()->fetch('$tag_version', function() { return 0; }); } + # Create a compact list of all active tags, sorted by post_count. + # + # "1`tagme` 2`fixme` 3`fixed`alias` " + # + # Each tag is bounded by backticks, so "`tagme`" can be used to match a whole tag. + # + # This is returned as a preencoded JSON string, so the entire block can be cached. static public function get_json_summary() { $summary_version = self::get_summary_version(); @@ -631,13 +630,13 @@ class Tag extends Rails\ActiveRecord\Base protected function callbacks() { - return array_merge_recursive([ + return [ 'after_save' => [ 'update_cache' ], 'after_create' => [ 'update_cache_on_create' ] - ], $this->versioning_callbacks()); + ]; } } diff --git a/app/models/TagAlias.php b/app/models/TagAlias.php index 252d515..5ad7a0d 100755 --- a/app/models/TagAlias.php +++ b/app/models/TagAlias.php @@ -139,4 +139,4 @@ class TagAlias extends Rails\ActiveRecord\Base { Moebooru\CacheHelper::expire_tag_version(); } -} \ No newline at end of file +} diff --git a/app/models/User.php b/app/models/User.php index 0704fb2..947d4a8 100755 --- a/app/models/User.php +++ b/app/models/User.php @@ -51,21 +51,20 @@ class User extends Rails\ActiveRecord\Base public function log($ip) { - // Rails.cache.fetch({ 'type' => :user_logs, 'id' => self.id, 'ip' => ip }, 'expires_in' => 10.minutes) do - // Rails.cache.fetch({ 'type' => :user_logs, 'id' => :all }, 'expires_id' => 1.day) do - // UserLog.where('created_at < ?', 3.days.ago).delete_all - // end - // begin - // log_entry = self.user_logs.find_or_initialize_by_ip_addr('ip_addr' => ip) - // log_entry.created_at = Time.now - // log_entry.save - // # Once in a blue moon there will be race condition on find_or_initialize - // # resulting unique key constraint violation. - // # It doesn't really affect anything so just ignore that error. - // rescue ActiveRecord::RecordNotUnique - // true - // end - // end + # iTODO: UserLog doesn't exist yet. + return; + + # iTODO: hash key + return Rails::cache()->fetch('type.user_logs;id.'.$this->id.';ip.'.$ip, ['expires_in' => '10 minutes'], function() use ($ip) { + # iTODO: hash key + Rails::cache()->fetch('type.user_logs;id.all', ['expires_in' => '1 day'], function() { + return UserLog::where('created_at < ?', date('Y-m-d 0:0:0', strtotime('-3 days')))->deleteAll(); + }); + + $log_entry = UserLog::where(['ip_addr' => $ip])->firstOrInitialize(); + $log_entry->created_at = date('Y-m-d H:i:s'); + return $log_entry->save(); + }); } # UserBlacklistMethods { @@ -200,10 +199,13 @@ class User extends Rails\ActiveRecord\Base static public function find_name($user_id) { - # iTODO: - // return Rails.cache.fetch("user_name:#{user_id}") do - return self::_find_name_helper($user_id); - // end + return Rails::cache()->fetch('user_name:' . $user_id, function() use ($user_id) { + try { + return self::find($user_id)->name; + } catch (Rails\ActiveRecord\Exception\RecordNotFoundException $e) { + return CONFIG()->default_guest_name; + } + }); } static public function find_by_name($name) @@ -221,10 +223,9 @@ class User extends Rails\ActiveRecord\Base // } - # iTODO: - protected function _update_cached_name() + protected function update_cached_name() { - // Rails::cache()->write("user_name:".$this->id, $this->name); + Rails::cache()->write("user_name:".$this->id, $this->name); } # } @@ -269,17 +270,19 @@ class User extends Rails\ActiveRecord\Base { $type = !empty($options['type']) ? $options['type'] : null; - // uploaded_tags = Rails.cache.read("uploaded_tags/#{id}/#{type}") - // return uploaded_tags unless uploaded_tags == nil + $uploaded_tags = Rails::cache()->read("uploaded_tags/". $this->id . "/" . $type); + if ($uploaded_tags) { + return $uploaded_tags; + } - // if ((Rails.env == "test") == "test") { - // # disable filtering in test mode to simplify tests - // popular_tags = "" - // } else { + if (Rails::env() == "test") { + # disable filtering in test mode to simplify tests + $popular_tags = ""; + } else { $popular_tags = implode(', ', self::connection()->selectValues("SELECT id FROM tags WHERE tag_type = " . CONFIG()->tag_types['General'] . " ORDER BY post_count DESC LIMIT 8")); if ($popular_tags) $popular_tags = "AND pt.tag_id NOT IN (${popular_tags})"; - // } + } if ($type) { $type = (int)$type; @@ -310,28 +313,28 @@ class User extends Rails\ActiveRecord\Base $uploaded_tags = self::connection()->select($sql); - // Rails.cache.write("uploaded_tags/#{id}/#{type}", uploaded_tags, 'expires_in' => 1.day) + Rails::cache()->write("uploaded_tags/" . $this->id . "/" . $type, $uploaded_tags, ['expires_in' => '1 day']); return $uploaded_tags; } - # iTODO: public function voted_tags(array $options = array()) { $type = !empty($options['type']) ? $options['type'] : null; - // $favorite_tags = Rails.cache.read("favorite_tags/#{id}/#{type}") - // if ($favorite_tags != nil) - // return $favorite_tags; + $favorite_tags = Rails::cache()->read("favorite_tags/". $this->id . "/" . $type); + if ($favorite_tags) { + return $favorite_tags; + } - // if (Rails.env == "test") { - // # disable filtering in test mode to simplify tests - // popular_tags = "" - // } else { + if (Rails::env() == "test") { + # disable filtering in test mode to simplify tests + $popular_tags = ""; + } else { $popular_tags = implode(', ', self::connection()->selectValues("SELECT id FROM tags WHERE tag_type = " . CONFIG()->tag_types['General'] . " ORDER BY post_count DESC LIMIT 8")); if ($popular_tags) $popular_tags = "AND pt.tag_id NOT IN (${popular_tags})"; - // } + } if ($type) { $type = (int)$type; @@ -362,7 +365,7 @@ class User extends Rails\ActiveRecord\Base $favorite_tags = self::connection()->select($sql); - // Rails.cache.write("favorite_tags/#{id}/#{type}", favorite_tags, 'expires_in' => 1.day) + Rails::cache()->write("favorite_tags/" . $this->id . "/" . $type, $favorite_tags, ['expires_in' => '1 day']); return $favorite_tags; } @@ -392,16 +395,14 @@ class User extends Rails\ActiveRecord\Base return $this->post_count; } - # iTODO: public function held_post_count() { - return Post::where("user_id = ? AND is_held AND status <> 'deleted'", $this->id)->count(); - // $version = (int)Rails::cache()->read("%cache_version"); - // $key = "held-post-count/v=".$version."/u=".$this->id; - - // return Rails::cache()->fetch($key) { - // Post::count(['conditions' => ["user_id = ? AND is_held AND status <> 'deleted'", $this->id]]); - // } + $version = (int)Rails::cache()->read('$cache_version'); + $key = 'held-post-count/v=' . $version . '/u=' . $this->id; + + return Rails::cache()->fetch($key, function() { + return Post::where(['user_id' => $this->id, 'is_held' => true])->where('status <> ?', 'deleted')->count(); + }); } # } @@ -794,7 +795,7 @@ class User extends Rails\ActiveRecord\Base 'before_create' => $before_create, 'before_save' => array('_encrypt_password'), 'before_validation' => array('_commit_secondary_languages'), - 'after_save' => array('_commit_blacklists', '_update_cached_name'), + 'after_save' => array('_commit_blacklists', 'update_cached_name'), 'after_create' => array('_set_default_blacklisted_tags', '_increment_count'), 'after_destroy' => array('_decrement_count') ); diff --git a/app/models/WikiPage.php b/app/models/WikiPage.php index ea03971..123fde9 100755 --- a/app/models/WikiPage.php +++ b/app/models/WikiPage.php @@ -125,10 +125,10 @@ class WikiPage extends Rails\ActiveRecord\Base protected function callbacks() { - return array_merge_recursive([ + return [ 'before_save' => ['normalize_title'], 'before_validation_on_update' => ['ensure_changed'] - ], $this->versioningCallbacks()); + ]; } protected function associations() diff --git a/app/views/forum/_post.php b/app/views/forum/_post.php index 287d839..370faf6 100755 --- a/app/views/forum/_post.php +++ b/app/views/forum/_post.php @@ -19,7 +19,7 @@