OpenProject is the leading open source project management software.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openproject/db/migrate/migration_utils/journal_migrator_concerns.rb

142 lines
6.0 KiB

#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2017 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See doc/COPYRIGHT.rdoc for more details.
#++
module Migration
module JournalMigratorConcerns
module Attachable
def migrate_attachments(to_insert, legacy_journal, journal_id)
attachments = to_insert.keys.select { |d| d =~ attachment_key_regexp }
attachments = remove_attachments_deleted_in_current_version attachments, to_insert
attachments.each do |key|
attachment_id = attachment_key_regexp.match(key)[1]
# if an attachment was added the value contains something like:
# [nil, "blubs.png"]
# if it was removed the value is something like
# ["blubs.png", nil]
removed_filename, added_filename = *to_insert[key]
if added_filename && !removed_filename
# The attachment was added
attachable = ActiveRecord::Base.connection.select_all <<-SQL
SELECT *
FROM #{attachable_table_name} AS a
WHERE a.journal_id = #{quote_value(journal_id)} AND a.attachment_id = #{attachment_id};
SQL
if attachable.size > 1
raise AmbiguousAttachableJournalError, <<-MESSAGE.split("\n").map(&:strip!).join(' ') + "\n"
It appears there are ambiguous attachable journal data.
Please make sure attachable journal data are consistent and
that the unique constraint on journal_id and attachment_id
is met.
MESSAGE
elsif attachable.size == 0
db_execute <<-SQL
INSERT INTO #{attachable_table_name}(journal_id, attachment_id, filename)
VALUES (#{quote_value(journal_id)}, #{quote_value(attachment_id)}, #{quote_value(added_filename)});
SQL
end
elsif removed_filename && !added_filename
# The attachment was removed
# we need to make certain that no subsequent journal adds an attachable_journal
# for this attachment
to_insert.delete_if { |k, _v| k =~ /attachments_?#{attachment_id}/ }
else
raise InvalidAttachableJournalError, <<-MESSAGE.split("\n").map(&:strip!).join(' ') + "\n"
There is a journal entry for an attachment but neither the old nor the new value contains anything:
#{to_insert}
#{legacy_journal}
MESSAGE
end
end
end
# sometimes there are attachments, which were deleted in a later journal entry
# there is not need to add those attachments, so we filter them out here
def remove_attachments_deleted_in_current_version(attachments, journal_to_insert)
deleted_attachments = attachments.select { |key|
# journal_to_insert[key] is of the form
# [nil, "filename.ext"] when the attachment was added
# ["filename.ext", nil] when the attachment was removed
journal_to_insert[key].first
}
attachments.reject do |key|
deleted_attachments.any? { |del_key| key =~ /attachments#{del_key[attachment_key_regexp, 1]}/ }
end
end
def attachable_table_name
quoted_table_name('attachable_journals')
end
def attachment_key_regexp
# Attachment journal entries can be written in two ways:
# attachments123 if the attachment was added
# attachments_123 if the attachment was removed
@attachment_key_regexp ||= /attachments_?(\d+)\z/
end
end
module Customizable
def migrate_custom_values(to_insert, _legacy_journal, journal_id)
keys = to_insert.keys
values = to_insert.values
custom_values = keys.select { |d| d =~ /custom_values.*/ }
custom_values.each do |k|
custom_field_id = k.split('_values').last.to_i
value = values[keys.index k].last
customizable = db_select_all <<-SQL
SELECT *
FROM #{customizable_table_name} AS a
WHERE a.journal_id = #{quote_value(journal_id)} AND a.custom_field_id = #{custom_field_id};
SQL
if customizable.size > 1
raise AmbiguousCustomizableJournalError, <<-MESSAGE.split("\n").map(&:strip!).join(' ') + "\n"
It appears there are ambiguous customizable journal
data. Please make sure customizable journal data are
consistent and that the unique constraint on journal_id and
custom_field_id is met.
MESSAGE
elsif customizable.size == 0
db_execute <<-SQL
INSERT INTO #{customizable_table_name}(journal_id, custom_field_id, value)
VALUES (#{quote_value(journal_id)}, #{quote_value(custom_field_id)}, #{quote_value(value)});
SQL
end
end
end
def customizable_table_name
quoted_table_name('customizable_journals')
end
end
end
end