canvas-lms/lib/duplicating_objects.rb

67 lines
2.8 KiB
Ruby

# frozen_string_literal: true
#
# Copyright (C) 2017 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
module DuplicatingObjects
# Lowercases title and replaces spaces with hyphens (to allow to check for
# matching titles that differ only in case or space/hyphens)
def normalize_title(title)
title.tr(" ", "-").downcase
end
# Given a title, returns the first "non-conflicting" title. "entity"
# should provide a function "get_potentially_conflicting_titles" that
# returns a set of titles that might conflict with the entity's title.
#
# If the given title ends in "#{copy_suffix} #" (or without the number),
# tries incrementing from # (or 2 if no number is given) until one is
# found that isn't in the set returned by entity.get_potentially_conflicting_titles
#
# If not, then first tries just appending copy_suffix, and if that has a
# conflict, increments from 2 as above.
#
# For the purposes of matching, conflicts are case-insensitive and also
# treats hyphens and spaces as the same thing.
def get_copy_title(entity, copy_suffix, entity_title)
is_multiple_copy = !(normalize_title(entity_title) =~
/#{Regexp.quote(copy_suffix.downcase)}-[0-9]*$/).nil?
normalized_suffix = normalize_title(copy_suffix)
if normalize_title(entity_title).end_with?(normalized_suffix) || is_multiple_copy
potential_title = entity_title
possible_num_to_try = normalize_title(entity_title).scan(/\d+$/).first
num_to_try = possible_num_to_try ? possible_num_to_try.to_i + 1 : 2
else
potential_title = "#{entity_title} #{copy_suffix}"
num_to_try = 2
end
title_base = is_multiple_copy ? potential_title.gsub(/\d+$/, "") : potential_title + " "
title_search_term = title_base[0...-1]
conflicting_titles = entity.get_potentially_conflicting_titles(title_search_term).map do |x|
normalize_title(x)
end
return potential_title unless conflicting_titles.include?(normalize_title(potential_title))
loop do
title_attempt = "#{title_base}#{num_to_try}"
num_to_try = num_to_try.succ
return title_attempt unless conflicting_titles.include?(normalize_title(title_attempt))
end
end
end