public function update() { !is_array($this->params()->aliases) && ($this->params()->aliases = []); $ids = array_keys($this->params()->aliases); switch ($this->params()->commit) { case "Delete": $validate_all = true; foreach ($ids as $id) { $ta = TagAlias::find($id); if (!$ta->is_pending || $ta->creator_id != current_user()->id) { $validate_all = false; break; } } if (current_user()->is_mod_or_higher() || $validate_all) { foreach ($ids as $x) { if ($ta = TagAlias::find($x)) { $ta->destroy_and_notify(current_user(), $this->params()->reason); } } $this->notice("Tag aliases deleted"); $this->redirectTo("#index"); } else { $this->access_denied(); } break; case "Approve": if (current_user()->is_mod_or_higher()) { foreach ($ids as $x) { if (CONFIG()->is_job_task_active('approve_tag_alias')) { JobTask::create(['task_type' => "approve_tag_alias", 'status' => "pending", 'data' => ["id" => $x, "updater_id" => current_user()->id, "updater_ip_addr" => $this->request()->remoteIp()]]); } else { $ta = TagAlias::find($x); $ta->approve(current_user()->id, $this->request()->remoteIp()); } } $this->notice("Tag alias approval jobs created"); $this->redirectTo('job_task#index'); } else { $this->access_denied(); } break; default: $this->access_denied(); break; } }
function save_tags_to_cookie() { if (!empty(Request::$params->tags)) { $tags = Request::$params->tags; } elseif (!empty(Request::$params->post) && !empty(Request::$params->post['tags'])) { $tags = explode(' ', strtolower(Request::$params->post['tags'])); } else { return; } $tags = TagAlias::to_aliased($tags); if (!empty($_COOKIE["recent_tags"])) { $tags = array_merge($tags, explode(' ', $_COOKIE["recent_tags"])); } $tags = array_unique(array_filter($tags)); cookie_put("recent_tags", implode(' ', array_slice($tags, 0, 20))); }
public function execute_approve_tag_alias() { $ta = TagAlias::find($this->data->id); $updater_id = $this->data->updater_id; $updater_ip_addr = $this->data->updater_ip_addr; $ta->approve($updater_id, $updater_ip_addr); }
$ta = TagAlias::find($x); $ta->destroy_and_notify(User::$current, Request::$params->reason); } notice("Tag aliases deleted"); redirect_to("#index"); } else { access_denied(); } break; case "Approve": if (User::is('>=40')) { foreach ($ids as $x) { // if (CONFIG::enable_asynchronous_tasks) { // JobTask.create(:task_type => "approve_tag_alias", :status => "pending", :data => {"id" => x, "updater_id" => @current_user.id, "updater_ip_addr" => request.remote_ip}) // } else { // vde($x); // DB::show_query(); $ta = TagAlias::find($x); // vde($ta); // exit; $ta->approve(User::$current->id, Request::$remote_ip); // } } notice("Tag alias approval jobs created"); #TODO: redirecting to #index instead of job_task#index as job_task doesn't yet exist. redirect_to('#index'); } else { access_denied(); } break; }
protected function save_tags_to_cookie() { if ($this->params()->tags || is_array($this->params()->post) && isset($this->params()->post['tags'])) { $post_tags = isset($this->params()->post['tags']) ? (string) $this->params()->post['tags'] : ''; $tags = TagAlias::to_aliased(explode(' ', strtolower($this->params()->tags ?: $post_tags))); if ($recent_tags = trim($this->cookies()->recent_tags)) { $tags = array_merge($tags, explode(' ', $recent_tags)); } $this->cookies()->recent_tags = implode(" ", array_slice($tags, 0, 20)); } }
<?php set_title("Tag Aliases"); create_page_params(); auto_set_params(array('commit', 'query')); if (Request::$params->commit == "Search Implications") { redirect_to('tag_implication#index', array('query' => Request::$params->query)); } if (Request::$params->query) { $name = "%" . Request::$params->query . "%"; $aliases = TagAlias::find_all(array('order' => "is_pending DESC, name", 'per_page' => 20, 'conditions' => array("name LIKE ? OR alias_id IN (SELECT id FROM tags WHERE name LIKE ?)", $name, $name), 'page' => Request::$params->page)); } else { $aliases = TagAlias::find_all(array('order' => "is_pending DESC, name", 'per_page' => 20, 'page' => Request::$params->page)); } respond_to_list($aliases); calc_pages();
static function parse_query($query, $options = array()) { $q = array(); foreach (self::scan_query($query) as $token) { if (preg_match('/^([qse])$/', $token, $m)) { $q['rating'] = $m[1]; continue; } if (preg_match('/^(unlocked|deleted|ext|user|sub|vote|-vote|fav|md5|-rating|rating|width|height|mpixels|score|source|id|date|pool|-pool|parent|order|change|holds|pending|shown|limit):(.+)$/', $token, $m)) { if ($m[1] == "user") { $q['user'] = $m[2]; } elseif ($m[1] == "vote") { list($vote, $user) = explode(':', $m[2]); if ($user = User::find_by_name($user)) { $user_id = $user->id; } else { $user_id = null; } $q['vote'] = array(self::parse_helper($vote), $user_id); } elseif ($m[1] == "-vote") { if ($user = User::find_by_name($m[2])) { $user_id = $user->id; } else { $user_id = null; } $q['vote_negated'] = $user_id; // $q['vote_negated'] = User.find_by_name_nocase($m[2]).id rescue nil if (!$q['vote_negated']) { $q['error'] = "no user named " . $m[2]; } } elseif ($m[1] == "fav") { $q['fav'] = $m[2]; } elseif ($m[1] == "sub") { $q['subscriptions'] = $m[2]; } elseif ($m[1] == "md5") { $q['md5'] = $m[2]; } elseif ($m[1] == "-rating") { $q['rating_negated'] = $m[2]; } elseif ($m[1] == "rating") { $q['rating'] = $m[2]; } elseif ($m[1] == "id") { $q['post_id'] = self::parse_helper($m[2]); } elseif ($m[1] == "width") { $q['width'] = self::parse_helper($m[2]); } elseif ($m[1] == "height") { $q['height'] = self::parse_helper($m[2]); } elseif ($m[1] == "mpixels") { $q['mpixels'] = self::parse_helper($m[2], 'float'); } elseif ($m[1] == "score") { $q['score'] = self::parse_helper($m[2]); } elseif ($m[1] == "source") { $q['source'] = $m[2] . '%'; } elseif ($m[1] == "date") { $q['date'] = self::parse_helper($m[2], 'date'); } elseif ($m[1] == "pool") { $q['pool'] = $m[2]; if (preg_match('/^(\\d+)$/', $q['pool'])) { $q['pool'] = (int) $q['pool']; } } elseif ($m[1] == "-pool") { $pool = $m[2]; if (preg_match('/^(\\d+)$/', $pool)) { $pool = (int) $pool; } $q['exclude_pools'][] = $pool; } elseif ($m[1] == "parent") { $q['parent_id'] = $m[2] == "none" ? false : (int) $m[2]; } elseif ($m[1] == "order") { $q['order'] = $m[2]; } elseif ($m[1] == "unlocked") { $m[2] == "rating" && ($q['unlocked_rating'] = true); } elseif ($m[1] == "deleted") { # This naming is slightly odd, to retain API compatibility with Danbooru's "deleted:true" # search flag. if ($m[2] == "true") { $q['show_deleted_only'] = true; } elseif ($m[2] == "all") { $q['show_deleted_only'] = false; } # all posts, deleted or not } elseif ($m[1] == "ext") { $q['ext'] = $m[2]; } elseif ($m[1] == "change") { $q['change'] = self::parse_helper($m[2]); } elseif ($m[1] == "shown") { $q['shown_in_index'] = $m[2] == "true"; } elseif ($m[1] == "holds") { if ($m[2] == "true" or $m[2] == "only") { $q['show_holds'] = 'only'; } elseif ($m[2] == "all") { $q['show_holds'] = 'yes'; } elseif ($m[2] == "false") { $q['show_holds'] = 'hide'; } } elseif ($m[1] == "pending") { if ($m[2] == "true" or $m[2] == "only") { $q['show_pending'] = 'only'; } elseif ($m[2] == "all") { $q['show_pending'] = 'yes'; } elseif ($m[2] == "false") { $q['show_pending'] = 'hide'; } } elseif ($m[1] == "limit") { $q['limit'] = $m[2]; } } elseif ($token[0] == '-' && strlen($token) > 1) { $q['exclude'][] = substr($token, 1); } elseif ($token[0] == '~' && count($token) > 1) { $q['include'][] = substr($token, 1); } elseif (strstr('*', $token)) { $tags = Tag::find_all(array('conditions' => array("name LIKE ?", $token), 'select' => "name, post_count", 'limit' => 25, 'order' => "post_count DESC")); foreach ($tags as $i) { $matches = $i->name; } !$matches && ($matches = array('~no_matches~')); $q['include'] += $matches; } else { $q['related'][] = $token; } } if (!isset($options['skip_aliasing'])) { isset($q['exclude']) && ($q['exclude'] = TagAlias::to_aliased($q['exclude'])); isset($q['include']) && ($q['include'] = TagAlias::to_aliased($q['include'])); isset($q['related']) && ($q['related'] = TagAlias::to_aliased($q['related'])); } return $q; }
function commit_tags() { if ($this->is_empty_model()) { return; } $this->tags = array_filter(explode(' ', str_replace(array("\r", "\n"), '', $this->tags))); $this->current_tags = array_keys($this->parsed_cached_tags); if (empty($this->old_tags)) { $this->old_tags = $this->tags; } elseif (!is_array($this->old_tags)) { $this->old_tags = array_filter(explode(' ', $this->old_tags)); } $this->commit_metatags(); foreach ($this->tags as $k => $tag) { if (!preg_match('~^(-pool|pool|rating|parent|child):|^[qse]$~', $tag)) { continue; } if (in_array($tag, array('q', 's', 'e'))) { $tag = "rating:{$tag}"; } $subparam = explode(':', $tag); $metatag = array_shift($subparam); $param = array_shift($subparam); $subparam = empty($subparam) ? null : array_shift($subparam); switch ($metatag) { case 'rating': # Change rating. This will override rating selected on radio buttons. if (in_array($param, array('q', 's', 'e'))) { $this->rating = $param; } unset($this->tags[$k]); break; case 'pool': try { $name = $param; $seq = $subparam; # Workaround: I don't understand how can the pool be found when finding_by_name # using the id. if (ctype_digit($name)) { $pool = Pool::find_by_id($name); } else { $pool = Pool::find_by_name($name); } # Set :ignore_already_exists, so pool:1:2 can be used to change the sequence number # of a post that already exists in the pool. $options = array('user' => User::find($this->updater_user_id), 'ignore_already_exists' => true); if ($seq) { $options['sequence'] = $seq; } if (!$pool and !ctype_digit($name)) { $pool = Pool::create(array('name' => $name, 'is_public' => false, 'user_id' => $this->updater_user_id)); } if (!$pool) { continue; } if (!$pool->can_change(User::$current, null)) { continue; } $pool->add_post($this->id, $options); } catch (PostAlreadyExistsError $e) { } catch (AccessDeniedError $e) { } unset($this->tags[$k]); break; case '-pool': unset($this->tags[$k]); $name = $param; $cmd = $subparam; $pool = Pool::find_by_name($name); if (!$pool->can_change(User::$current, null)) { break; } if ($cmd == "parent") { # If we have a parent, remove ourself from the pool and add our parent in # our place. If we have no parent, do nothing and leave us in the pool. if (!empty($this->parent_id)) { $pool->transfer_post_to_parent($this->id, $this->parent_id); break; } } $pool && $pool->remove_post($id); break; case 'source': $this->source = $param; unset($this->tags[$k]); break; case 'parent': if (is_numeric($param)) { $this->parent_id = (int) $param; } unset($this->tags[$k]); break; case 'child': unset($this->tags[$k]); break; default: unset($this->tags[$k]); break; } } $new_tags = array_diff($this->tags, $this->old_tags); $new_tags = array_merge($new_tags, TagAlias::to_aliased($new_tags)); $new_tags = array_merge($new_tags, TagImplication::with_implied($new_tags)); $new_tags = array_values(array_unique($new_tags)); $old_tags = array_diff($this->old_tags, $this->tags); if (empty($new_tags) && $old_tags == $this->current_tags) { if (!in_array('tagme', $new_tags)) { $new_tags[] = 'tagme'; } if (in_array('tagme', $old_tags)) { unset($old_tags[array_search('tagme', $old_tags)]); } } foreach ($old_tags as $tag) { if (array_key_exists($tag, $this->parsed_cached_tags)) { unset($this->parsed_cached_tags[$tag]); } $tag = Tag::find_by_name($tag); if ($tag) { DB::delete('posts_tags WHERE post_id = ? AND tag_id = ?', $this->id, $tag->id); } } foreach ($new_tags as $tag) { $tag = Tag::find_or_create_by_name($tag); $this->parsed_cached_tags[$tag->name] = $tag->type_name; DB::insert_ignore('posts_tags VALUES (?, ?)', $this->id, $tag->id); } $this->tags = $this->tag_names(); $this->generate_cached_tags(); }
/** * It's strange how actions like changing pool's sequence, that updates the post via * update_batch and sends only one metatag: 'pool:$id:$seq' and doesn't send old_tags, don't * mess up the rest of the tags (because that metatag is discarted, and the post is left without * old_tags or any tag). * So we're gonna do a workaround for that: if the new tags only contain metatags, we won't * take any further action but commit such metatags. * We'll use $had_metatags for that. */ protected function commit_tags() { if ($this->isNewRecord() || !$this->new_tags) { return; } if ($this->old_tags) { # If someone else committed changes to this post before we did, # then try to merge the tag changes together. $current_tags = explode(' ', $this->cached_tags); $this->old_tags = Tag::scan_tags($this->old_tags); $this->new_tags = array_filter(array_merge(array_diff(array_merge($current_tags, $this->new_tags), $this->old_tags), array_intersect($current_tags, $this->new_tags))); } $this->commit_metatags(); $meta_tags = ['-pool:', 'pool:', 'rating:', 'parent:', 'child:', 'source:']; $ratings = ['q', 's', 'e']; $had_metatags = false; foreach ($this->new_tags as $k => $tag) { # To avoid preg_match. $is_mt = false; foreach ($meta_tags as $mt) { if (strpos($tag, $mt) === 0 || in_array($tag, $ratings)) { $is_mt = true; break; } } if (!$is_mt) { continue; } $had_metatags = true; unset($this->new_tags[$k]); if (in_array($tag, $ratings)) { $tag = 'rating:' . $tag; } $subparam = explode(':', $tag, 3); $metatag = array_shift($subparam); $param = array_shift($subparam); $subparam = empty($subparam) ? null : array_shift($subparam); switch ($metatag) { case 'rating': # Change rating. This will override rating selected on radio buttons. if (in_array($param, $ratings)) { $this->rating = $param; } break; case 'pool': try { $name = $param; $seq = $subparam; # Workaround: I don't understand how can the pool be found when finding_by_name # using the id. if (ctype_digit($name)) { $pool = Pool::where(['id' => $name])->first(); } else { $pool = Pool::where(['name' => $name])->first(); } # Set :ignore_already_exists, so pool:1:2 can be used to change the sequence number # of a post that already exists in the pool. $options = array('user' => User::where('id = ?', $this->updater_user_id)->first(), 'ignore_already_exists' => true); if ($seq) { $options['sequence'] = $seq; } if (!$pool and !ctype_digit($name)) { $pool = Pool::create(array('name' => $name, 'is_public' => false, 'user_id' => $this->updater_user_id)); } if (!$pool || !$pool->can_change(current_user(), null)) { continue; } $pool->add_post($this->id, $options); } catch (Pool_PostAlreadyExistsError $e) { } catch (Pool_AccessDeniedError $e) { } break; case '-pool': $name = $param; $cmd = $subparam; $pool = Pool::where(['name' => $name])->first(); if (!$pool->can_change(current_user(), null)) { break; } if ($cmd == "parent") { # If we have a parent, remove ourself from the pool and add our parent in # our place. If we have no parent, do nothing and leave us in the pool. if (!empty($this->parent_id)) { $pool->transfer_post_to_parent($this->id, $this->parent_id); break; } } $pool && $pool->remove_post($id); break; case 'source': $this->source = $param; break; case 'parent': if (is_numeric($param)) { $this->parent_id = (int) $param; } break; case 'child': unset($this->new_tags[$k]); break; } } if (!$this->new_tags) { if ($had_metatags) { return; } $this->new_tags[] = "tagme"; } // $this->tags = implode(' ', array_unique(TagImplication::with_implied(TagAlias::to_aliased($this->new_tags)))); $this->new_tags = TagAlias::to_aliased($this->new_tags); $this->new_tags = array_unique(TagImplication::with_implied($this->new_tags)); sort($this->new_tags); // $this->tags = implode(' ', $this->tags()); # TODO: be more selective in deleting from the join table self::connection()->executeSql("DELETE FROM posts_tags WHERE post_id = ?", $this->id); $new_tags_ids = []; $new_tags_names = []; $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_names[] = $tag->name; return $tag; } }, $this->new_tags); unset($new_tags_ids); $this->new_tags = array_filter($this->new_tags); # If any tags are newly active, expire the tag cache. if ($this->new_tags) { $any_new_tags = false; $previous_tags = explode(' ', $this->cached_tags); foreach ($this->new_tags as $tag) { # If this tag is in old_tags, then it's already active and we just removed it # in the above DELETE, so it's not really a newly activated tag. (This isn't # self.old_tags; that's the tags the user saw before he edited, not the data # we're replacing.) if ($tag->post_count == 0 and !in_array($tag->name, $previous_tags)) { $any_new_tags = true; break; } } if ($any_new_tags) { Moebooru\CacheHelper::expire_tag_version(); } } # 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); $sql = "INSERT INTO posts_tags (post_id, tag_id) VALUES " . $tag_set; self::connection()->executeSql($sql); # Store the old cached_tags, so we can expire them. $this->old_cached_tags = $this->cached_tags; // Commenting the following line; it will cause cached_tags to not to be updated. // They're set above. // $this->cached_tags = self::connection()->selectValue("SELECT cached_tags FROM posts WHERE id = " . $this->id); $this->new_tags = null; }
public function related() { if ($this->params()->type) { $this->tags = Tag::scan_tags($this->params()->tags); $this->tags = TagAlias::to_aliased($this->tags); $all = []; $tag_type = CONFIG()->tag_types[$this->params()->type]; foreach ($this->tags as $x) { $all[$x] = array_map(function ($y) use($x) { return [$y["name"], $y["post_count"]]; }, Tag::calculate_related_by_type($x, $tag_type)); } $this->tags = $all; } else { $tags = Tag::scan_tags($this->params()->tags); $this->patterns = $this->tags = []; foreach ($tags as $tag) { if (is_int(strpos($tag, "*"))) { $this->patterns[] = $tag; } else { $this->tags[] = $tag; } } unset($tags, $tag); $this->tags = TagAlias::to_aliased($this->tags); $all = []; foreach ($this->tags as $x) { $all[$x] = array_map(function ($y) { return [$y[0], $y[1]]; }, Tag::find_related($x)); } $this->tags = $all; foreach ($this->patterns as $x) { $this->tags[$x] = array_map(function ($y) { return [$y->name, $y->post_count]; }, Tag::where("name LIKE ?", '%' . $x . '%')->first()); } } $this->respondTo(['json' => function () { $this->render(['json' => json_encode($this->tags)]); }]); }
<?php required_params('tag_alias'); // vde(Request::$params->tag_alias); $ta = TagAlias::blank(Request::$params->tag_alias); // vde($ta); $ta->is_pending = true; // vde($ta); // DB::show_query(1); if ($ta->save()) { notice("Tag alias created"); } else { notice("Error: " . implode(', ', $ta->record_errors->full_messages())); } // exit; redirect_to("#index");
public static function mass_edit($start_tags, $result_tags, $updater_id, $updater_ip_addr) { foreach (Post::find_by_tags($start_tags) as $p) { $start = TagAlias::to_aliased(Tag::scan_tags($start_tags)); $result = TagAlias::to_aliased(Tag::scan_tags($result_tags)); $tags = array_merge(array_diff($p->tags(), $start), $result); $tags = implode(' ', $tags); $p->updateAttributes(array('updater_user_id' => $updater_id, 'updater_ip_addr' => $updater_ip_addr, 'tags' => $tags)); } }