Module: Async::Caldav::Handlers::Report

Defined in:
lib/async/caldav/handlers/report.rb

Class Method Summary collapse

Class Method Details

.call(path:, body:, storage:, resource_type: nil) ⇒ Object



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
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/async/caldav/handlers/report.rb', line 9

def call(path:, body:, storage:, resource_type: nil, **)
  # Detect sync-collection report
  if body&.include?('sync-collection')
    handle_sync_collection(path: path, body: body, storage: storage)
  else
    col_path = path.ensure_trailing_slash
    items = storage.list_items(col_path.to_s)
    if resource_type == :addressbook
      data_tag = 'cr:address-data'
    else
      data_tag = 'c:calendar-data'
    end
    expand_range = parse_expand(body)
    filter = parse_filter(body, resource_type)
    hrefs = extract_hrefs(body)
    if hrefs && !hrefs.empty?
      # Calendar-multiget / addressbook-multiget
      multi = storage.get_multi(hrefs)
      items = multi.select { |_, data| data }
    end
    xml = Protocol::Caldav::Multistatus.new.to_xml do |x|
      items.each do |item_path, data|
        unless data
          next
        end

        # Apply filter
        if filter
          if resource_type == :addressbook
            card = Protocol::Caldav::Vcard::Parser.parse(data[:body])
            unless card && Protocol::Caldav::Filter::Match.addressbook?(filter, card)
              next
            end
          else
            component = Protocol::Caldav::Ical::Parser.parse(data[:body])
            unless component && Protocol::Caldav::Filter::Match.calendar?(filter, component)
              next
            end
          end
        end

        item_body = data[:body]

        # Apply expand if requested (calendar items only)
        if expand_range && resource_type != :addressbook
          component = Protocol::Caldav::Ical::Parser.parse(item_body)
          if component
            item_body = Protocol::Caldav::Ical::Expand.expand(
              component,
              range_start: expand_range[:start],
              range_end:   expand_range[:end],
            )
          end
        end

        item_p = Protocol::Caldav::Path.new(item_path, storage_class: storage)
        item = Protocol::Caldav::Item.new(
          path:         item_p,
          body:         item_body,
          content_type: data[:content_type],
          etag:         data[:etag],
        )
        item.build_report(x, data_tag: data_tag)
      end
    end
    [207, Protocol::Caldav::Constants::DAV_HEADERS, [xml]]
  end
end