discourse/lib/feed_element_installer.rb

78 lines
1.9 KiB
Ruby

# frozen_string_literal: true
require "rexml/document"
require "rss"
class FeedElementInstaller
private_class_method :new
def self.install(element_name, feed)
# RSS Specification at http://cyber.harvard.edu/rss/rss.html#extendingRss
# > A RSS feed may contain [non-standard elements], only if those elements are *defined in a namespace*
new(element_name, feed).install if element_name.include?(":")
end
attr_reader :feed, :original_name, :element_namespace, :element_name, :element_accessor
def initialize(element_name, feed)
@feed = feed
@original_name = element_name
@element_namespace, @element_name = *element_name.split(":")
@element_accessor = "#{@element_namespace}_#{@element_name}"
end
def element_uri
@element_uri ||=
REXML::Document.new(feed).root&.attributes&.namespaces&.fetch(@element_namespace, "") || ""
end
def install
install_in_rss unless installed_in_rss?
install_in_atom unless installed_in_atom?
end
private
def install_in_rss
RSS::Rss::Channel::Item.install_text_element(
element_name,
element_uri,
"?",
element_accessor,
nil,
original_name,
)
RSS::BaseListener.install_get_text_element(element_uri, element_name, element_accessor)
end
def install_in_atom
RSS::Atom::Entry.install_text_element(
element_name,
element_uri,
"?",
element_accessor,
nil,
original_name,
)
RSS::Atom::Feed::Entry.install_text_element(
element_name,
element_uri,
"?",
element_accessor,
nil,
original_name,
)
RSS::BaseListener.install_get_text_element(element_uri, element_name, element_accessor)
end
def installed_in_rss?
RSS::Rss::Channel::Item.method_defined?(element_accessor)
end
def installed_in_atom?
RSS::Atom::Entry.method_defined?(element_accessor) ||
RSS::Atom::Feed::Entry.method_defined?(element_accessor)
end
end