menu_item_update_action.rb 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. class KnowledgeBase
  3. class MenuItemUpdateAction
  4. def initialize(kb_locale, location, menu_items_data)
  5. @kb_locale = kb_locale
  6. @location = location
  7. @menu_items_data = menu_items_data
  8. end
  9. def scope
  10. @kb_locale.menu_items.location(@location)
  11. end
  12. def perform!
  13. raise_unprocessable if !all_ids_present?
  14. KnowledgeBase::MenuItem.transaction do
  15. KnowledgeBase::MenuItem.acts_as_list_no_update do
  16. remove_deleted
  17. update_order
  18. end
  19. end
  20. end
  21. # Mass-update KB menu items
  22. #
  23. # @param [KnowledgeBase] knowledge_base
  24. # @param [[<Hash>]] params @see .update_location_params!
  25. #
  26. # @return [<KnowledgeBase::MenuItem>]
  27. def self.update_using_params!(knowledge_base, params)
  28. return if params.blank?
  29. params
  30. .map { |location_params| update_location_using_params! knowledge_base, location_params }
  31. .tap { |arr| arr.each(&:reload) }
  32. .flatten
  33. end
  34. # Mass-update KB menu items in a given location
  35. #
  36. # @param [KnowledgeBase] knowledge_base
  37. # @param [Hash] location_params
  38. #
  39. # @option location_params [Integer] :kb_locale_id
  40. # @option location_params [String] :location header or footer
  41. # @option location_params [[<Hash>]] :menu_items @see #update_order
  42. def self.update_location_using_params!(knowledge_base, location_params)
  43. action = new(
  44. knowledge_base.kb_locales.find(location_params[:kb_locale_id]),
  45. location_params[:location],
  46. location_params[:menu_items]
  47. )
  48. action.perform!
  49. action.scope
  50. end
  51. private
  52. def update_order
  53. old_items = scope.to_a
  54. @menu_items_data
  55. .reject { |elem| elem[:_destroy] }
  56. .each_with_index do |data_elem, index|
  57. item = old_items.find { |record| record.id == data_elem[:id] } || scope.build
  58. item.position = index
  59. item.title = data_elem[:title]
  60. item.url = data_elem[:url]
  61. item.new_tab = data_elem[:new_tab]
  62. item.save!
  63. end
  64. end
  65. def remove_deleted
  66. @menu_items_data
  67. .select { |elem| elem[:_destroy] }
  68. .pluck(:id)
  69. .tap { |array| @kb_locale.menu_items.where(id: array).destroy_all }
  70. end
  71. def all_ids_present?
  72. old_ids = scope.pluck(:id)
  73. new_ids = @menu_items_data.filter_map { |elem| elem[:id]&.to_i }
  74. old_ids.sort == new_ids.sort
  75. end
  76. def raise_unprocessable
  77. raise Exceptions::UnprocessableEntity, __('Provide position of all items in scope')
  78. end
  79. end
  80. end