このコミットが含まれているのは:
@@ -27,6 +27,9 @@ class ApplicationController < ActionController::API
|
||||
private
|
||||
|
||||
def enforce_query_contract!
|
||||
if request.query_parameters.keys.any? { _1 == 'tag_refs' || _1.start_with?('tag_refs.') }
|
||||
return head :bad_request
|
||||
end
|
||||
pairs = URI.decode_www_form(request.query_string)
|
||||
return head :bad_request if pairs.length > 1000 || pairs.map(&:first).uniq.length != pairs.length
|
||||
return head :bad_request if request.query_parameters.values.any? { !_1.is_a?(String) }
|
||||
|
||||
@@ -409,52 +409,40 @@ class PostsController < ApplicationController
|
||||
target = Locale.find_by(code:, deprecated_at: nil)
|
||||
return head :not_found unless target
|
||||
|
||||
literals = params[:tags].to_s.split
|
||||
references = tag_filter_references(literals)
|
||||
names = literals.each_with_index.map do |literal, index|
|
||||
reference = references&.[](index)
|
||||
(reference && reference['negative'] == false) ? literal : literal.sub(/\Anot:/i, '')
|
||||
end
|
||||
internal = references ? {} : TagName.where(
|
||||
language_code: source.language_code, name: names).pluck(:name, :tag_id).to_h
|
||||
canonical = references ? {} : TagName.where(
|
||||
language_code: source.language_code, primary_flg: true,
|
||||
tag_id: internal.values).pluck(:tag_id, :name).to_h
|
||||
external_names = names.map { canonical[internal[_1]] || _1 }
|
||||
external = references ? {} : ExternalTag.where(
|
||||
"CONCAT(platform, ':', name) IN (?)", external_names).pluck(
|
||||
Arel.sql("CONCAT(platform, ':', name)"), :id).to_h
|
||||
ids = references ? references.filter_map { _1['tag_id'] } : internal.values
|
||||
translated = TagName.where(language_code: target.language_code,
|
||||
primary_flg: true, tag_id: ids).pluck(:tag_id, :name).to_h
|
||||
tokens = params[:tags].to_s.split
|
||||
literals = PostTagSearch.literals(source, tokens.join(' '))
|
||||
source_ids = PostTagSearch.references_for(source, literals)
|
||||
ids = source_ids.values.flat_map(&:first).uniq
|
||||
names = TagName.where(language_code: target.language_code,
|
||||
primary_flg: true, tag_id: ids).pluck(:tag_id, :name).to_h
|
||||
filters = literals.map do |literal|
|
||||
internal, = source_ids.fetch(literal[:name])
|
||||
name = internal.empty? ? literal[:name] : names[internal.first]
|
||||
return head :unprocessable_entity unless name && internal.length <= 1
|
||||
|
||||
filters = literals.each_with_index.map do |literal, index|
|
||||
name = names[index]
|
||||
reference = if references
|
||||
references[index].except('name')
|
||||
else
|
||||
matches = {}
|
||||
matches['tag_id'] = internal[name] if internal[name]
|
||||
external_id = external[external_names[index]]
|
||||
matches['external_tag_id'] = external_id if external_id
|
||||
matches.empty? ? { 'missing' => true } : matches
|
||||
end
|
||||
name = translated[reference['tag_id']] || name
|
||||
negative = reference.fetch('negative', literal.downcase.start_with?('not:'))
|
||||
prefix = negative ? literal[/\Anot:/i] || 'not:' : ''
|
||||
reference.merge('name' => "#{ prefix }#{ name }", 'negative' => negative)
|
||||
literal[:negative] ? "not:#{ name }" : name
|
||||
end
|
||||
render json: { references: filters }
|
||||
translated = PostTagSearch.literals(target, filters.join(' '))
|
||||
target_ids = PostTagSearch.references_for(target, translated)
|
||||
literals.zip(translated).each do |literal, translation|
|
||||
unless (source_ids.fetch(literal[:name]).map(&:sort) ==
|
||||
target_ids.fetch(translation[:name]).map(&:sort))
|
||||
return head :unprocessable_entity
|
||||
end
|
||||
end
|
||||
index = 0
|
||||
filters = tokens.map do |token|
|
||||
next token if token.downcase == 'type:or'
|
||||
|
||||
value = filters[index]
|
||||
index += 1
|
||||
value
|
||||
end
|
||||
render json: { tags: filters.join(' ') }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def tag_filter_references literals
|
||||
PostTagSearch.parse_references(params.to_unsafe_h, literals)
|
||||
rescue ArgumentError, JSON::ParserError, TypeError
|
||||
raise ActionController::BadRequest
|
||||
end
|
||||
|
||||
def filtered_posts locale
|
||||
tag_names = params[:tags].to_s.split
|
||||
match_type = params[:match]
|
||||
@@ -466,19 +454,17 @@ class PostsController < ApplicationController
|
||||
end
|
||||
|
||||
def filter_posts_by_tags locale, tag_names, match_type
|
||||
references = tag_filter_references(tag_names)
|
||||
literals = PostTagSearch.literals(locale, tag_names.join(' '), references:)
|
||||
literals = PostTagSearch.literals(locale, tag_names.join(' '))
|
||||
|
||||
return Post.all if literals.empty?
|
||||
|
||||
if match_type == 'any'
|
||||
literals.reduce(Post.none) do |posts, literal|
|
||||
posts.or(tag_literal_relation(locale, literal[:name], negative: literal[:negative],
|
||||
reference: literal[:reference]))
|
||||
posts.or(tag_literal_relation(locale, literal[:name], negative: literal[:negative]))
|
||||
end
|
||||
else
|
||||
literals.reduce(Post.all) do |posts, literal|
|
||||
ids = tagged_post_ids_for(locale, literal[:name], reference: literal[:reference])
|
||||
ids = tagged_post_ids_for(locale, literal[:name])
|
||||
if literal[:negative]
|
||||
posts.where.not(id: ids)
|
||||
else
|
||||
@@ -488,8 +474,8 @@ class PostsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def tag_literal_relation locale, name, negative:, reference: nil
|
||||
ids = tagged_post_ids_for(locale, name, reference:)
|
||||
def tag_literal_relation locale, name, negative:
|
||||
ids = tagged_post_ids_for(locale, name)
|
||||
if negative
|
||||
Post.where.not(id: ids)
|
||||
else
|
||||
@@ -497,8 +483,8 @@ class PostsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def tagged_post_ids_for locale, name, reference: nil
|
||||
internal, external = PostTagSearch.references(locale, { name:, reference: })
|
||||
def tagged_post_ids_for locale, name
|
||||
internal, external = PostTagSearch.references(locale, { name: })
|
||||
Post.where(id: PostTag.where(tag_id: Array(internal)).select(:post_id))
|
||||
.or(Post.where(id: PostExternalTag.where(external_tag_id: Array(external))
|
||||
.select(:post_id))).select(:id)
|
||||
|
||||
新しいイシューから参照
ユーザーをブロックする