summaryrefslogtreecommitdiff
path: root/lib/banzai/filter/reference_gatherer_filter.rb
blob: 96fdb06304e5f6f188cf80bf124427250532738d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
module Banzai
  module Filter
    # HTML filter that gathers all referenced records that the current user has
    # permission to view.
    #
    # Expected to be run in its own post-processing pipeline.
    #
    class ReferenceGathererFilter < HTML::Pipeline::Filter
      def initialize(*)
        super

        result[:references] ||= Hash.new { |hash, type| hash[type] = [] }
      end

      def call
        Querying.css(doc, 'a.gfm').each do |node|
          gather_references(node)
        end

        load_lazy_references unless ReferenceExtractor.lazy?

        doc
      end

      private

      def gather_references(node)
        return unless node.has_attribute?('data-reference-filter')

        reference_type = node.attr('data-reference-filter')
        reference_filter = Banzai::Filter.const_get(reference_type)

        return if context[:reference_filter] && reference_filter != context[:reference_filter]

        return if author && !reference_filter.user_can_reference?(author, node, context)

        return unless reference_filter.user_can_see_reference?(current_user, node, context)

        references = reference_filter.referenced_by(node)
        return unless references

        references.each do |type, values|
          Array.wrap(values).each do |value|
            result[:references][type] << value
          end
        end
      end

      def load_lazy_references
        refs = result[:references]
        refs.each do |type, values|
          refs[type] = ReferenceExtractor.lazily(values)
        end
      end

      def current_user
        context[:current_user]
      end

      def author
        context[:author]
      end
    end
  end
end