zimbra-soap-api 0.0.7.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.irbrc +6 -0
- data/Gemfile +6 -0
- data/README +21 -0
- data/Rakefile +1 -0
- data/lib/zimbra.rb +94 -0
- data/lib/zimbra/account.rb +94 -0
- data/lib/zimbra/acl.rb +63 -0
- data/lib/zimbra/alias.rb +4 -0
- data/lib/zimbra/appointment.rb +274 -0
- data/lib/zimbra/appointment/alarm.rb +101 -0
- data/lib/zimbra/appointment/attendee.rb +97 -0
- data/lib/zimbra/appointment/invite.rb +360 -0
- data/lib/zimbra/appointment/recur_exception.rb +83 -0
- data/lib/zimbra/appointment/recur_rule.rb +184 -0
- data/lib/zimbra/appointment/reply.rb +91 -0
- data/lib/zimbra/auth.rb +46 -0
- data/lib/zimbra/base.rb +217 -0
- data/lib/zimbra/calendar.rb +27 -0
- data/lib/zimbra/common_elements.rb +51 -0
- data/lib/zimbra/cos.rb +124 -0
- data/lib/zimbra/delegate_auth_token.rb +49 -0
- data/lib/zimbra/directory.rb +175 -0
- data/lib/zimbra/distribution_list.rb +147 -0
- data/lib/zimbra/domain.rb +63 -0
- data/lib/zimbra/ext/handsoap_curb_driver.rb +21 -0
- data/lib/zimbra/ext/hash.rb +72 -0
- data/lib/zimbra/ext/string.rb +10 -0
- data/lib/zimbra/extra/date_helpers.rb +111 -0
- data/lib/zimbra/folder.rb +100 -0
- data/lib/zimbra/handsoap_account_service.rb +44 -0
- data/lib/zimbra/handsoap_service.rb +75 -0
- data/lib/zimbra/version.rb +3 -0
- data/spec/fixtures/xml_api_requests/appointments/create.xml +84 -0
- data/spec/fixtures/xml_api_responses/alarms/15_minutes_before.xml +26 -0
- data/spec/fixtures/xml_api_responses/alarms/using_all_intervals.xml +26 -0
- data/spec/fixtures/xml_api_responses/appointments/appointment_response_1.xml +40 -0
- data/spec/fixtures/xml_api_responses/attendees/one_attendee_and_one_reply.xml +27 -0
- data/spec/fixtures/xml_api_responses/attendees/three_attendees_response_1.xml +30 -0
- data/spec/fixtures/xml_api_responses/multiple_invites/recurring_with_exceptions.xml +109 -0
- data/spec/fixtures/xml_api_responses/recur_rules/day_27_of_every_2_months.xml +27 -0
- data/spec/fixtures/xml_api_responses/recur_rules/every_2_days.xml +26 -0
- data/spec/fixtures/xml_api_responses/recur_rules/every_3_weeks_on_tuesday_and_friday.xml +30 -0
- data/spec/fixtures/xml_api_responses/recur_rules/every_day_50_instances.xml +27 -0
- data/spec/fixtures/xml_api_responses/recur_rules/every_monday_wednesday_friday.xml +31 -0
- data/spec/fixtures/xml_api_responses/recur_rules/every_tuesday.xml +29 -0
- data/spec/fixtures/xml_api_responses/recur_rules/every_weekday_with_end_date.xml +34 -0
- data/spec/fixtures/xml_api_responses/recur_rules/every_year_on_february_2.xml +28 -0
- data/spec/fixtures/xml_api_responses/recur_rules/first_day_of_every_month.xml +36 -0
- data/spec/fixtures/xml_api_responses/recur_rules/first_monday_of_every_february.xml +31 -0
- data/spec/fixtures/xml_api_responses/recur_rules/first_weekend_day_of_every_month.xml +31 -0
- data/spec/fixtures/xml_api_responses/recur_rules/last_day_of_every_month.xml +36 -0
- data/spec/fixtures/xml_api_responses/recur_rules/second_day_of_every_2_months.xml +36 -0
- data/spec/fixtures/xml_api_responses/recur_rules/second_wednesday_of_every_month.xml +29 -0
- data/spec/fixtures/xml_api_responses/recur_rules/weekly_with_an_exception.xml +44 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/zimbra/acl_spec.rb +11 -0
- data/spec/zimbra/appointment/alarm_spec.rb +33 -0
- data/spec/zimbra/appointment/invite_spec.rb +62 -0
- data/spec/zimbra/appointment/recur_rule_spec.rb +307 -0
- data/spec/zimbra/appointment_spec.rb +175 -0
- data/spec/zimbra/common_elements_spec.rb +33 -0
- data/spec/zimbra/distribution_list_spec.rb +54 -0
- data/zimbra.gemspec +28 -0
- metadata +197 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
module Zimbra
|
2
|
+
class Appointment
|
3
|
+
class Alarm
|
4
|
+
class << self
|
5
|
+
def new_from_zimbra_attributes(zimbra_attributes)
|
6
|
+
new(parse_zimbra_attributes(zimbra_attributes))
|
7
|
+
end
|
8
|
+
|
9
|
+
# <alarm action="DISPLAY">
|
10
|
+
# <trigger>
|
11
|
+
# <rel neg="1" m="5" related="START"/>
|
12
|
+
# </trigger>
|
13
|
+
# <desc/>
|
14
|
+
# </alarm>
|
15
|
+
def parse_zimbra_attributes(zimbra_attributes)
|
16
|
+
attrs = { appointment_invite: zimbra_attributes[:appointment_invite] }
|
17
|
+
zimbra_attributes = Zimbra::Hash.symbolize_keys(zimbra_attributes.dup, true)
|
18
|
+
zimbra_attributes = zimbra_attributes[:trigger][:rel][:attributes]
|
19
|
+
|
20
|
+
duration_negative = (zimbra_attributes[:neg] && zimbra_attributes[:neg] == 1) ? true : false
|
21
|
+
|
22
|
+
attrs.merge({
|
23
|
+
duration_negative: duration_negative,
|
24
|
+
weeks: zimbra_attributes[:w],
|
25
|
+
days: zimbra_attributes[:d],
|
26
|
+
hours: zimbra_attributes[:h],
|
27
|
+
minutes: zimbra_attributes[:m],
|
28
|
+
seconds: zimbra_attributes[:s],
|
29
|
+
when: zimbra_attributes[:related] == "START" ? :start : :end,
|
30
|
+
repeat_count: zimbra_attributes[:count],
|
31
|
+
})
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
ATTRS = [:appointment_invite, :duration_negative, :weeks, :days, :hours, :minutes, :seconds, :when, :repeat_count] unless const_defined?(:ATTRS)
|
36
|
+
|
37
|
+
attr_accessor *ATTRS
|
38
|
+
|
39
|
+
def initialize(args = {})
|
40
|
+
@duration_negative = true
|
41
|
+
@when = :start
|
42
|
+
self.attributes = args
|
43
|
+
end
|
44
|
+
|
45
|
+
# take attributes by the xml name or our more descriptive name
|
46
|
+
def attributes=(args = {})
|
47
|
+
ATTRS.each do |attr_name|
|
48
|
+
if args.has_key?(attr_name)
|
49
|
+
self.send(:"#{attr_name}=", args[attr_name])
|
50
|
+
elsif args.has_key?(attr_name.to_s)
|
51
|
+
self.send(:"#{attr_name}=", args[attr_name.to_s])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_hash(options = {})
|
57
|
+
hash = ATTRS.inject({}) do |attr_hash, attr_name|
|
58
|
+
attr_hash[attr_name] = self.send(:"#{attr_name}")
|
59
|
+
attr_hash
|
60
|
+
end
|
61
|
+
hash.reject! { |key, value| options[:except].include?(key.to_sym) || options[:except].include?(key.to_s) } if options[:except]
|
62
|
+
hash.reject! { |key, value| !options[:only].include?(key.to_sym) && !options[:only].include?(key.to_s) } if options[:only]
|
63
|
+
hash
|
64
|
+
end
|
65
|
+
|
66
|
+
def create_xml(document)
|
67
|
+
document.add "trigger" do |trigger_element|
|
68
|
+
trigger_element.add "rel" do |rel_element|
|
69
|
+
rel_element.set_attr "neg", duration_negative ? 1 : 0
|
70
|
+
rel_element.set_attr "w", weeks if weeks && weeks > 0
|
71
|
+
rel_element.set_attr "d", days if days && days > 0
|
72
|
+
rel_element.set_attr "h", hours if hours && hours > 0
|
73
|
+
rel_element.set_attr "m", minutes if minutes && minutes > 0
|
74
|
+
rel_element.set_attr "s", seconds if seconds && seconds > 0
|
75
|
+
rel_element.set_attr "related", self.when.to_s.upcase
|
76
|
+
rel_element.set_attr "count", repeat_count if repeat_count && repeat_count > 0
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def date_time_of_alarm
|
82
|
+
return nil if appointment_invite.nil?
|
83
|
+
|
84
|
+
date_to_calc_from = if self.when == :start
|
85
|
+
appointment_invite.start_date_time
|
86
|
+
else
|
87
|
+
appointment_invite.end_date_time
|
88
|
+
end
|
89
|
+
|
90
|
+
total_seconds = seconds || 0
|
91
|
+
total_seconds += minutes * 60 if minutes
|
92
|
+
total_seconds += hours * 3600 if hours
|
93
|
+
total_seconds += days * 86400 if days
|
94
|
+
total_seconds += weeks * 86400 * 7 if weeks
|
95
|
+
total_seconds *= -1 if duration_negative
|
96
|
+
|
97
|
+
date_to_calc_from + total_seconds
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module Zimbra
|
2
|
+
class Appointment
|
3
|
+
class Attendee
|
4
|
+
ATTRS = [
|
5
|
+
:email_address, :friendly_name, :rsvp, :role, :participation_status
|
6
|
+
] unless const_defined?(:ATTRS)
|
7
|
+
|
8
|
+
attr_accessor *ATTRS
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def new_from_zimbra_attributes(zimbra_attributes)
|
12
|
+
new(parse_zimbra_attributes(zimbra_attributes))
|
13
|
+
end
|
14
|
+
|
15
|
+
def parse_zimbra_attributes(zimbra_attributes)
|
16
|
+
zimbra_attributes = Zimbra::Hash.symbolize_keys(zimbra_attributes.dup, true)
|
17
|
+
|
18
|
+
{
|
19
|
+
:email_address => zimbra_attributes[:a],
|
20
|
+
:friendly_name => zimbra_attributes[:d],
|
21
|
+
:rsvp => zimbra_attributes[:rsvp],
|
22
|
+
:role => zimbra_attributes[:role],
|
23
|
+
:participation_status => zimbra_attributes[:ptst]
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(args = {})
|
29
|
+
self.attributes = args
|
30
|
+
end
|
31
|
+
|
32
|
+
# take attributes by the xml name or our more descriptive name
|
33
|
+
def attributes=(args = {})
|
34
|
+
ATTRS.each do |attr_name|
|
35
|
+
if args.has_key?(attr_name)
|
36
|
+
self.send(:"#{attr_name}=", args[attr_name])
|
37
|
+
elsif args.has_key?(attr_name.to_s)
|
38
|
+
self.send(:"#{attr_name}=", args[attr_name.to_s])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def participation_status=(val)
|
44
|
+
@participation_status = parse_participation_status(val)
|
45
|
+
end
|
46
|
+
|
47
|
+
def participation_status_to_zimbra
|
48
|
+
possible_participation_status_values.find { |k, v| v == participation_status }.first rescue participiation_status
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_hash(options = {})
|
52
|
+
hash = {
|
53
|
+
:email_address => email_address,
|
54
|
+
:friendly_name => friendly_name,
|
55
|
+
:rsvp => rsvp,
|
56
|
+
:role => role,
|
57
|
+
:participation_status => participation_status
|
58
|
+
}
|
59
|
+
hash.reject! { |key, value| options[:except].include?(key.to_sym) || options[:except].include?(key.to_s) } if options[:except]
|
60
|
+
hash.reject! { |key, value| !options[:only].include?(key.to_sym) && !options[:only].include?(key.to_s) } if options[:only]
|
61
|
+
hash
|
62
|
+
end
|
63
|
+
|
64
|
+
def create_xml(document)
|
65
|
+
document.add "at" do |at_element|
|
66
|
+
at_element.set_attr "a", email_address
|
67
|
+
at_element.set_attr "d", friendly_name
|
68
|
+
at_element.set_attr "ptst", participation_status_to_zimbra
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def possible_participation_status_values
|
75
|
+
@possible_participation_status_values ||= {
|
76
|
+
'NE' => :needs_action,
|
77
|
+
'AC' => :accept,
|
78
|
+
'TE' => :tentative,
|
79
|
+
'DE' => :declined,
|
80
|
+
'DG' => :delegated,
|
81
|
+
'CO' => :completed,
|
82
|
+
'IN' => :in_process,
|
83
|
+
'WE' => :waiting,
|
84
|
+
'DF' => :deferred,
|
85
|
+
'New' => :needs_action,
|
86
|
+
'Accepted' => :accept,
|
87
|
+
'Declined' => :declined
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
def parse_participation_status(status)
|
92
|
+
possible_participation_status_values[status] || status
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,360 @@
|
|
1
|
+
module Zimbra
|
2
|
+
class Appointment
|
3
|
+
class Invite
|
4
|
+
ATTRS = [
|
5
|
+
:appointment,
|
6
|
+
:id, :recurrence_id, :sequence_number,
|
7
|
+
|
8
|
+
:start_date_time, :end_date_time, :date,
|
9
|
+
:name, :fragment, :description, :alarm, :alarm_zimbra_attributes, :alarm_attributes, :recurrence_rule, :recurrence_rule_zimbra_attributes, :recurrence_rule_attributes,
|
10
|
+
:attendees, :attendees_attributes, :attendees_zimbra_attributes,
|
11
|
+
:organizer_email_address, :is_organizer, :computed_free_busy_status,
|
12
|
+
:free_busy_setting, :invite_status, :all_day, :visibility, :location,
|
13
|
+
:transparency, :replies, :never_sent,
|
14
|
+
|
15
|
+
:comment, :recurrence_id_utc, :exception
|
16
|
+
] unless const_defined?(:ATTRS)
|
17
|
+
|
18
|
+
attr_accessor *ATTRS
|
19
|
+
|
20
|
+
class << self
|
21
|
+
def new_from_zimbra_attributes(zimbra_attributes)
|
22
|
+
new(parse_zimbra_attributes(zimbra_attributes))
|
23
|
+
end
|
24
|
+
|
25
|
+
def parse_zimbra_attributes(zimbra_attributes)
|
26
|
+
zimbra_attributes = Zimbra::Hash.symbolize_keys(zimbra_attributes.dup, true)
|
27
|
+
|
28
|
+
attrs = {}
|
29
|
+
|
30
|
+
attrs[:appointment] = zimbra_attributes[:appointment] if zimbra_attributes.has_key?(:appointment)
|
31
|
+
|
32
|
+
if zimbra_attributes.has_key?(:attributes)
|
33
|
+
attrs.merge!({
|
34
|
+
:id => zimbra_attributes[:attributes][:id],
|
35
|
+
:recurrence_id => zimbra_attributes[:attributes][:recurId],
|
36
|
+
:sequence_number => zimbra_attributes[:attributes][:seq],
|
37
|
+
})
|
38
|
+
end
|
39
|
+
|
40
|
+
zimbra_attributes = zimbra_attributes[:comp]
|
41
|
+
return attrs unless zimbra_attributes
|
42
|
+
|
43
|
+
attrs.merge!({
|
44
|
+
:fragment => zimbra_attributes[:fr],
|
45
|
+
:description => zimbra_attributes[:desc],
|
46
|
+
:comment => zimbra_attributes[:comment],
|
47
|
+
:alarm_zimbra_attributes => zimbra_attributes[:alarm],
|
48
|
+
:recurrence_rule_zimbra_attributes => zimbra_attributes[:recur],
|
49
|
+
:attendees_zimbra_attributes => zimbra_attributes[:at],
|
50
|
+
:never_sent => zimbra_attributes[:neverSent]
|
51
|
+
})
|
52
|
+
|
53
|
+
if zimbra_attributes[:s]
|
54
|
+
attrs[:start_date_time] = zimbra_attributes[:s][:attributes][:u]
|
55
|
+
else
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
if zimbra_attributes[:e]
|
60
|
+
attrs[:end_date_time] = zimbra_attributes[:e][:attributes][:u]
|
61
|
+
end
|
62
|
+
|
63
|
+
if zimbra_attributes[:exceptId] && zimbra_attributes[:exceptId][:attributes]
|
64
|
+
attrs[:exception] = zimbra_attributes[:exceptId][:attributes]
|
65
|
+
end
|
66
|
+
|
67
|
+
attrs[:organizer_email_address] = zimbra_attributes[:or][:attributes][:a] rescue nil
|
68
|
+
|
69
|
+
return attrs unless zimbra_attributes.has_key?(:attributes)
|
70
|
+
|
71
|
+
attrs.merge!({
|
72
|
+
:name => zimbra_attributes[:attributes][:name],
|
73
|
+
:computed_free_busy_status => zimbra_attributes[:attributes][:fba],
|
74
|
+
:free_busy_setting => zimbra_attributes[:attributes][:fb],
|
75
|
+
:date => zimbra_attributes[:attributes][:d],
|
76
|
+
:invite_status => zimbra_attributes[:attributes][:status],
|
77
|
+
:all_day => zimbra_attributes[:attributes][:allDay],
|
78
|
+
:visibility => zimbra_attributes[:attributes][:class],
|
79
|
+
:location => zimbra_attributes[:attributes][:loc],
|
80
|
+
:date => zimbra_attributes[:attributes][:d],
|
81
|
+
:transparency => zimbra_attributes[:attributes][:transp],
|
82
|
+
:is_organizer => zimbra_attributes[:attributes][:isOrg],
|
83
|
+
:recurrence_id_utc => zimbra_attributes[:attributes][:ridZ]
|
84
|
+
})
|
85
|
+
|
86
|
+
attrs
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def initialize(args = {})
|
91
|
+
self.attributes = args
|
92
|
+
end
|
93
|
+
|
94
|
+
# take attributes by the xml name or our more descriptive name
|
95
|
+
def attributes=(args = {})
|
96
|
+
ATTRS.each do |attr_name|
|
97
|
+
if args.has_key?(attr_name)
|
98
|
+
self.send(:"#{attr_name}=", args[attr_name])
|
99
|
+
elsif args.has_key?(attr_name.to_s)
|
100
|
+
self.send(:"#{attr_name}=", args[attr_name.to_s])
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def save
|
106
|
+
return false unless appointment
|
107
|
+
|
108
|
+
if appointment.new_record?
|
109
|
+
appointment.save
|
110
|
+
else
|
111
|
+
Zimbra::AppointmentService.update(appointment, id)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def cancel
|
116
|
+
return false unless appointment
|
117
|
+
return false if appointment.new_record?
|
118
|
+
|
119
|
+
Zimbra::AppointmentService.cancel(appointment, id)
|
120
|
+
end
|
121
|
+
|
122
|
+
def exception=(exception_attributes)
|
123
|
+
return @exception = nil unless exception_attributes
|
124
|
+
|
125
|
+
@exception = Zimbra::Appointment::RecurException.new_from_zimbra_attributes(exception_attributes)
|
126
|
+
end
|
127
|
+
|
128
|
+
def recurrence_rule_attributes=(attributes)
|
129
|
+
@recurrence_rule = attributes ? Zimbra::Appointment::RecurRule.new(attributes) : nil
|
130
|
+
end
|
131
|
+
|
132
|
+
def recurrence_rule_zimbra_attributes=(attributes)
|
133
|
+
@recurrence_rule = attributes ? Zimbra::Appointment::RecurRule.new_from_zimbra_attributes(attributes) : nil
|
134
|
+
end
|
135
|
+
|
136
|
+
def attendees_zimbra_attributes=(attributes)
|
137
|
+
return @attendees = [] unless attributes
|
138
|
+
|
139
|
+
attributes = attributes.is_a?(Array) ? attributes : [attributes]
|
140
|
+
@attendees = attributes.collect { |attrs| Zimbra::Appointment::Attendee.new_from_zimbra_attributes(attrs[:attributes]) }
|
141
|
+
end
|
142
|
+
|
143
|
+
def attendees_attributes=(attributes)
|
144
|
+
return @attendees = [] unless attributes
|
145
|
+
|
146
|
+
attributes = attributes.is_a?(Array) ? attributes : [attributes]
|
147
|
+
@attendees = attributes.collect { |attrs| Zimbra::Appointment::Attendee.new(attrs) }
|
148
|
+
end
|
149
|
+
|
150
|
+
def alarm_attributes=(attributes)
|
151
|
+
@alarm = attributes ? Zimbra::Appointment::Alarm.new(attributes.merge(:appointment_invite => self)) : nil
|
152
|
+
end
|
153
|
+
|
154
|
+
def alarm_zimbra_attributes=(attributes)
|
155
|
+
@alarm = attributes ? Zimbra::Appointment::Alarm.new_from_zimbra_attributes(attributes.merge(:appointment_invite => self)) : nil
|
156
|
+
end
|
157
|
+
|
158
|
+
def computed_free_busy_status=(val)
|
159
|
+
@computed_free_busy_status = parse_free_busy_status(val)
|
160
|
+
end
|
161
|
+
|
162
|
+
def free_busy_setting_to_zimbra
|
163
|
+
possible_free_busy_status_values.find { |k ,v| v == free_busy_setting }.first rescue free_busy_setting
|
164
|
+
end
|
165
|
+
|
166
|
+
def free_busy_setting=(val)
|
167
|
+
@free_busy_setting = parse_free_busy_status(val)
|
168
|
+
end
|
169
|
+
|
170
|
+
def invite_status=(val)
|
171
|
+
@invite_status = parse_invite_status(val)
|
172
|
+
end
|
173
|
+
|
174
|
+
def invite_status_to_zimbra
|
175
|
+
possible_invite_status_values.find { |k, v| v == invite_status }.first rescue invite_status
|
176
|
+
end
|
177
|
+
|
178
|
+
def visibility=(val)
|
179
|
+
@visibility = parse_visibility_status(val)
|
180
|
+
end
|
181
|
+
|
182
|
+
def visibility_to_zimbra
|
183
|
+
possible_visibility_values.find { |k, v| v == visibility }.first rescue visibility
|
184
|
+
end
|
185
|
+
|
186
|
+
def transparency_to_zimbra
|
187
|
+
possible_transparency_status_values.find { |k, v| v == transparency }.first rescue transparency
|
188
|
+
end
|
189
|
+
|
190
|
+
def transparency=(val)
|
191
|
+
@transparency = parse_transparency_status(val)
|
192
|
+
end
|
193
|
+
|
194
|
+
def all_day=(val)
|
195
|
+
@all_day = parse_all_day(val)
|
196
|
+
end
|
197
|
+
|
198
|
+
def start_date_time=(val)
|
199
|
+
@start_date_time = val.is_a?(Integer) ? parse_date_in_seconds(val) : val
|
200
|
+
end
|
201
|
+
|
202
|
+
def end_date_time=(val)
|
203
|
+
@end_date_time = val.is_a?(Integer) ? parse_date_in_seconds(val) : val
|
204
|
+
end
|
205
|
+
|
206
|
+
def date=(val)
|
207
|
+
@date = val.is_a?(Integer) ? parse_date_in_seconds(val) : val
|
208
|
+
end
|
209
|
+
|
210
|
+
def create_xml(document)
|
211
|
+
document.set_attr "id", id if id
|
212
|
+
document.set_attr "status", invite_status_to_zimbra if invite_status
|
213
|
+
document.set_attr "isOrg", is_organizer ? 1 : 0
|
214
|
+
#document.set_attr "d", date.to_i * 1000 if date
|
215
|
+
|
216
|
+
document.add "comp" do |comp|
|
217
|
+
comp.set_attr "loc", location if location
|
218
|
+
comp.set_attr "allDay", all_day ? 1 : 0
|
219
|
+
comp.set_attr "class", visibility_to_zimbra if visibility
|
220
|
+
comp.set_attr "fb", free_busy_setting_to_zimbra if free_busy_setting
|
221
|
+
comp.set_attr "isOrg", is_organizer ? 1 : 0
|
222
|
+
comp.set_attr "name", name
|
223
|
+
comp.set_attr "transp", transparency_to_zimbra if transparency
|
224
|
+
comp.set_attr "d", date.to_i * 1000 if date
|
225
|
+
|
226
|
+
if is_organizer
|
227
|
+
comp.set_attr "neverSent", never_sent ? 1 : 0
|
228
|
+
end
|
229
|
+
|
230
|
+
if description && !description.empty?
|
231
|
+
comp.add "desc", description
|
232
|
+
end
|
233
|
+
|
234
|
+
if comment && !comment.empty?
|
235
|
+
comp.add "comment", comment
|
236
|
+
end
|
237
|
+
|
238
|
+
comp.add "s" do |s_element|
|
239
|
+
s_element.set_attr "u", start_date_time.to_i * 1000
|
240
|
+
s_element.set_attr "d", start_date_time.utc.strftime("%Y%m%dT%H%M%SZ")
|
241
|
+
end
|
242
|
+
|
243
|
+
comp.add "e" do |e_element|
|
244
|
+
e_element.set_attr "u", end_date_time.to_i * 1000
|
245
|
+
e_element.set_attr "d", end_date_time.utc.strftime("%Y%m%dT%H%M%SZ")
|
246
|
+
end
|
247
|
+
|
248
|
+
if alarm
|
249
|
+
comp.add "alarm" do |alarm_element|
|
250
|
+
alarm_element.set_attr "action", "DISPLAY"
|
251
|
+
|
252
|
+
alarm.create_xml(alarm_element)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
if recurrence_rule
|
257
|
+
comp.add "recur" do |recur_element|
|
258
|
+
recur_element.add "add" do |add_element|
|
259
|
+
recurrence_rule.create_xml(add_element)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
if attendees && attendees.count > 0
|
265
|
+
attendees.each do |attendee|
|
266
|
+
attendee.create_xml(comp)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
if organizer_email_address
|
271
|
+
comp.add "or" do |or_element|
|
272
|
+
or_element.set_attr "a", organizer_email_address
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
if exception
|
277
|
+
exception.create_xml(comp)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
#
|
281
|
+
# ATTRS = [
|
282
|
+
# :recurrence_id, :sequence_number, :replies,
|
283
|
+
#
|
284
|
+
# :, :recurrence_id_utc,
|
285
|
+
end
|
286
|
+
|
287
|
+
private
|
288
|
+
|
289
|
+
def parse_date_in_seconds(seconds)
|
290
|
+
Time.at(seconds / 1000)
|
291
|
+
end
|
292
|
+
|
293
|
+
def possible_all_day_values
|
294
|
+
@possible_all_day_values ||= {
|
295
|
+
0 => false,
|
296
|
+
1 => true
|
297
|
+
}
|
298
|
+
end
|
299
|
+
|
300
|
+
def parse_all_day(val)
|
301
|
+
return val if val == true || val == false
|
302
|
+
possible_all_day_values[val.to_i] || val
|
303
|
+
end
|
304
|
+
|
305
|
+
def possible_free_busy_status_values
|
306
|
+
@possible_free_busy_status_values ||= {
|
307
|
+
'F' => :free,
|
308
|
+
'B' => :busy,
|
309
|
+
'T' => :busy_tentative,
|
310
|
+
'U' => :busy_unavailable
|
311
|
+
}
|
312
|
+
end
|
313
|
+
|
314
|
+
def parse_free_busy_status(fb_status)
|
315
|
+
possible_free_busy_status_values[fb_status] || fb_status
|
316
|
+
end
|
317
|
+
|
318
|
+
def possible_invite_status_values
|
319
|
+
@possible_invite_status_values ||= {
|
320
|
+
'TENT' => :tentative,
|
321
|
+
'CONF' => :confirmed,
|
322
|
+
'CANC' => :canceled,
|
323
|
+
'NEED' => :need, # Not sure about this one, it's not documented
|
324
|
+
'COMP' => :completed,
|
325
|
+
'INPR' => :in_progress,
|
326
|
+
'WAITING' => :waiting,
|
327
|
+
'DEFERRED' => :deferred
|
328
|
+
}
|
329
|
+
end
|
330
|
+
|
331
|
+
def parse_invite_status(status)
|
332
|
+
possible_invite_status_values[status] || status
|
333
|
+
end
|
334
|
+
|
335
|
+
def possible_visibility_values
|
336
|
+
@possible_visibility_values ||= {
|
337
|
+
'PUB' => :public,
|
338
|
+
'PRI' => :private,
|
339
|
+
'CON' => :confidential
|
340
|
+
}
|
341
|
+
end
|
342
|
+
|
343
|
+
def parse_visibility_status(status)
|
344
|
+
possible_visibility_values[status] || status
|
345
|
+
end
|
346
|
+
|
347
|
+
def possible_transparency_status_values
|
348
|
+
@possible_transparency_status_values ||= {
|
349
|
+
'O' => :opaque,
|
350
|
+
'T' => :transparent
|
351
|
+
}
|
352
|
+
end
|
353
|
+
|
354
|
+
def parse_transparency_status(status)
|
355
|
+
possible_transparency_status_values[status] || status
|
356
|
+
end
|
357
|
+
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|