menu_item_update_action.rb 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. # Copyright (C) 2012-2023 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 }.sum(&:reload)
  31. end
  32. # Mass-update KB menu items in a given location
  33. #
  34. # @param [KnowledgeBase] knowledge_base
  35. # @param [Hash] location_params
  36. #
  37. # @option location_params [Integer] :kb_locale_id
  38. # @option location_params [String] :location header or footer
  39. # @option location_params [[<Hash>]] :menu_items @see #update_order
  40. def self.update_location_using_params!(knowledge_base, location_params)
  41. action = new(
  42. knowledge_base.kb_locales.find(location_params[:kb_locale_id]),
  43. location_params[:location],
  44. location_params[:menu_items]
  45. )
  46. action.perform!
  47. action.scope
  48. end
  49. private
  50. def update_order
  51. old_items = scope.to_a
  52. @menu_items_data
  53. .reject { |elem| elem[:_destroy] }
  54. .each_with_index do |data_elem, index|
  55. item = old_items.find { |record| record.id == data_elem[:id] } || scope.build
  56. item.position = index
  57. item.title = data_elem[:title]
  58. item.url = data_elem[:url]
  59. item.new_tab = data_elem[:new_tab]
  60. item.save!
  61. end
  62. end
  63. def remove_deleted
  64. @menu_items_data
  65. .select { |elem| elem[:_destroy] }
  66. .pluck(:id)
  67. .tap { |array| @kb_locale.menu_items.where(id: array).destroy_all }
  68. end
  69. def all_ids_present?
  70. old_ids = scope.pluck(:id)
  71. new_ids = @menu_items_data.filter_map { |elem| elem[:id]&.to_i }
  72. old_ids.sort == new_ids.sort
  73. end
  74. def raise_unprocessable
  75. raise Exceptions::UnprocessableEntity, __('Provide position of all items in scope')
  76. end
  77. end
  78. end