123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- module CreatesTicketArticles # rubocop:disable Metrics/ModuleLength
- extend ActiveSupport::Concern
- private
- def article_create(ticket, params)
- # create article if given
- form_id = params.delete(:form_id)
- subtype = params.delete(:subtype)
- # check min. params
- raise Exceptions::UnprocessableEntity, __("Need at least an 'article body' field.") if params[:body].nil?
- # fill default values
- if params[:type_id].blank? && params[:type].blank?
- params[:type_id] = Ticket::Article::Type.lookup(name: 'note').id
- end
- if params[:sender_id].blank? && params[:sender].blank?
- sender = 'Customer'
- if current_user.permissions?('ticket.agent')
- sender = 'Agent'
- end
- params[:sender_id] = Ticket::Article::Sender.lookup(name: sender).id
- end
- # remember time accounting values
- if params[:time_unit].present?
- accounted_time_params = {
- time_unit: params[:time_unit],
- type_id: params[:accounted_time_type_id],
- type: params[:accounted_time_type],
- }
- end
- clean_params = Ticket::Article.association_name_to_id_convert(params)
- clean_params = Ticket::Article.param_cleanup(clean_params, true)
- # overwrite params
- if !current_user.permissions?('ticket.agent')
- clean_params[:sender_id] = Ticket::Article::Sender.lookup(name: 'Customer').id
- clean_params.delete(:sender)
- clean_params.delete(:origin_by_id)
- type = Ticket::Article::Type.lookup(id: clean_params[:type_id])
- if !type.name.match?(%r{^(note|web)$})
- clean_params[:type_id] = Ticket::Article::Type.lookup(name: 'note').id
- end
- clean_params.delete(:type)
- clean_params[:internal] = false
- end
- article = Ticket::Article.new(clean_params)
- article.ticket_id = ticket.id
- article.check_mentions_raises_error = true
- article.check_email_recipient_raises_error = true
- # store dataurl images to store
- attachments_inline = []
- if article.body && article.content_type =~ %r{text/html}i
- (article.body, attachments_inline) = HtmlSanitizer.replace_inline_images(article.body, ticket.id)
- end
- # find attachments in upload cache
- attachments = []
- if form_id
- attachments += UploadCache
- .new(form_id)
- .attachments
- .reject do |elem|
- UploadCache.files_include_attachment?(attachments_inline, elem) || elem.inline?
- end
- end
- # store inline attachments
- attachments_inline.each do |attachment|
- attachments << {
- data: attachment[:data],
- filename: attachment[:filename],
- preferences: attachment[:preferences],
- }
- end
- # add attachments as param
- if params[:attachments].present?
- required_keys = %w[mime-type filename data]
- preferences_keys = %w[charset mime-type]
- params[:attachments].each_with_index do |attachment, index|
- # validation
- required_keys.each do |key|
- next if attachment[key]
- raise Exceptions::UnprocessableEntity, "Attachment needs '#{key}' param for attachment with index '#{index}'"
- end
- preferences = {}
- preferences_keys.each do |key|
- next if !attachment[key]
- store_key = key.tr('-', '_').camelize.gsub(%r{(.+)([A-Z])}, '\1_\2').tr('_', '-')
- preferences[store_key] = attachment[key]
- end
- begin
- base64_data = attachment[:data].gsub(%r{[\r\n]}, '')
- attachment_data = Base64.strict_decode64(base64_data)
- rescue ArgumentError
- raise Exceptions::UnprocessableEntity, "Invalid base64 for attachment with index '#{index}'"
- end
- attachments << {
- data: attachment_data,
- filename: attachment[:filename],
- preferences: preferences,
- }
- end
- end
- article.attachments = attachments
- # set subtype of present
- article.preferences[:subtype] = subtype if subtype.present?
- article.save!
- # account time
- if accounted_time_params.present?
- clean_accounted_time_params = Ticket::TimeAccounting.association_name_to_id_convert(accounted_time_params)
- clean_accounted_time_params = Ticket::TimeAccounting.param_cleanup(clean_accounted_time_params, true)
- time_accounting = Ticket::TimeAccounting.new(
- ticket_id: article.ticket_id,
- ticket_article_id: article.id,
- **clean_accounted_time_params,
- )
- authorize! time_accounting, :create?
- time_accounting.save!
- end
- return article if form_id.blank?
- # clear in-progress state from taskbar
- Taskbar
- .where(user_id: current_user.id)
- .find { |taskbar| taskbar.persisted_form_id == form_id }
- &.update!(state: {})
- # remove temporary attachment cache
- UploadCache.new(form_id).destroy
- article
- end
- end
|