module GovukPublishingComponents module Presenters # @private # Only used by the related_navigation component class RelatedNavigationHelper MAX_SECTION_LENGTH = 5 DEFINED_SECTIONS = %w( related_guides topics collections topical_events world_locations statistical_data_sets ).freeze WORLD_LOCATION_SPECIAL_CASES = { "UK Mission to the European Union" => "uk-mission-to-the-eu", }.freeze def initialize(options = {}) @content_item = options.fetch(:content_item) { raise ArgumentError, "missing argument: content_item" } @context = options.fetch(:context, nil) end def related_navigation case @context.try(:to_sym) when :sidebar { "related_items" => related_items, "related_guides" => related_guides, "collections" => related_document_collections, } when :footer { "topics" => related_topics, "topical_events" => related_topical_events, "world_locations" => related_world_locations, "statistical_data_sets" => related_statistical_data_sets, "related_external_links" => related_external_links, "related_contacts" => related_contacts, } else { "related_items" => related_items, "related_guides" => related_guides, "collections" => related_document_collections, "topics" => related_topics, "topical_events" => related_topical_events, "world_locations" => related_world_locations, "statistical_data_sets" => related_statistical_data_sets, "related_external_links" => related_external_links, "related_contacts" => related_contacts, } end end def construct_section_heading(section_title) unless section_title === "related_items" I18n.t("components.related_#{@context}_navigation." + section_title, default: [ I18n.t("components.related_navigation." + section_title), section_title.tr("_", " "), ]) end end def section_css_class(css_class, section_title, link = {}, link_is_inline = false) css_classes = [css_class] css_classes << "#{css_class}--#{@context}" unless @context.nil? css_classes << "#{css_class}--inline" if link_is_inline unless DEFINED_SECTIONS.include?(section_title) || link.fetch(:finder, false) css_classes << " #{css_class}--other" end css_classes.join(" ") end def section_data_track_count(section_title) String(@context || "sidebar") + String(section_title).camelcase end def section_heading_level @context == :footer ? "h2" : "h3" end def calculate_section_link_limit(links) links.length == MAX_SECTION_LENGTH + 1 ? MAX_SECTION_LENGTH + 1 : MAX_SECTION_LENGTH end def remaining_link_count(links) links.length - MAX_SECTION_LENGTH end def related_navigation? related_navigation.flat_map(&:last).any? end def t_locale(content, options = {}) # Check if the content string has a translation content_translation_available = translation_present?(content) # True, return locale this_locale = I18n.locale if content_translation_available # If false, return default locale this_locale = I18n.default_locale unless content_translation_available # Check if default string passed in if options[:default].present? # Check if the default string has a translation default_translation_available = translation_present?(options[:default]) # If true, return locale this_locale = I18n.locale if default_translation_available # If false, return default_locale this_locale = I18n.default_locale unless default_translation_available end this_locale end def t_lang(content, options = {}) locale = t_locale(content, options) "lang=#{locale}" unless locale.eql?(I18n.locale) end def t_locale_check(locale) locale.presence unless locale.to_s.eql?(I18n.locale.to_s) end private def translation_present?(content) default_string = "This is a string to act as a default for the `I18n.translate` method. Comparing the result reveals if there is a translation in the i18n files." I18n.translate( content, default: default_string, fallback: false, ) != default_string end def related_items related_quick_links = content_item_details_for("quick_links") if related_quick_links.any? related_quick_links + related_mainstream_content else content_item_links_for("ordered_related_items") + related_mainstream_content end end def related_world_locations content_item_links_for("world_locations") .map do |link| slug = WORLD_LOCATION_SPECIAL_CASES[link[:text]] || link[:text].parameterize link.merge(path: "/world/#{slug}/news") end end def related_statistical_data_sets content_item_links_for("related_statistical_data_sets", only: "statistical_data_set") end def related_taxons content_item_links_for("taxons", only: "taxon") end def related_topics if related_legacy_topics.any? related_legacy_topics elsif related_taxons.any? related_taxons else [] end end def related_legacy_topics mainstream_browse_page_links = content_item_links_for("mainstream_browse_pages", only: "mainstream_browse_page") topic_links = content_item_links_for("topics", only: "topic") mainstream_browse_page_links + topic_links.find_all do |topic_link| mainstream_browse_page_links.none? do |mainstream_browse_page_link| mainstream_browse_page_link[:text] == topic_link[:text] end end end def related_topical_events content_item_links_for("topical_events", only: "topical_event") end def related_contacts content_item_links_for("related", only: "contact") end def related_external_links content_item_details_for("external_related_links") end def related_mainstream_content return [] unless detailed_guide? content_item_links_for("related_mainstream_content") end def related_guides return [] unless detailed_guide? content_item_links_for("related_guides") end def related_document_collections content_item_links_for("document_collections", only: "document_collection") end def detailed_guide? @content_item["document_type"] == "detailed_guide" end def content_item_details_for(key) Array(@content_item.dig("details", key)) .map { |link| { path: link["url"], text: link["title"], rel: "external" } } end def content_item_links_for(key, only: nil) links = Array(@content_item.dig("links", key)) if key == "taxons" links = links.find_all { |link| link["phase"] == "live" } end if only.present? links = links.find_all { |link| link["document_type"] == only } end links.map { |link| { path: link["base_path"], text: link["title"], locale: link["locale"], } } end end end end