viewpoint 0.1.9 → 0.1.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,197 @@
1
+ FolderId => 'older:FolderId'
2
+ ParentFolderId => 'folder:ParentFolderId'
3
+ DisplayName => 'folder:DisplayName'
4
+ UnreadCount => 'folder:UnreadCount'
5
+ TotalCount => 'folder:TotalCount'
6
+ ChildFolderCount => 'folder:ChildFolderCount'
7
+ FolderClass => 'folder:FolderClass'
8
+ SearchParameters => 'folder:SearchParameters'
9
+ ManagedFolderInformation => 'folder:ManagedFolderInformation'
10
+ PermissionSet => 'folder:PermissionSet'
11
+ EffectiveRights => 'folder:EffectiveRights'
12
+ SharingEffectiveRights => 'folder:SharingEffectiveRights'
13
+ ItemId => 'item:ItemId'
14
+ ParentFolderId => 'item:ParentFolderId'
15
+ ItemClass => 'item:ItemClass'
16
+ MimeContent => 'item:MimeContent'
17
+ Attachments => 'item:Attachments'
18
+ Subject => 'item:Subject'
19
+ DateTimeReceived => 'item:DateTimeReceived'
20
+ Size => 'item:Size'
21
+ Categories => 'item:Categories'
22
+ HasAttachments => 'item:HasAttachments'
23
+ Importance => 'item:Importance'
24
+ InReplyTo => 'item:InReplyTo'
25
+ InternetMessageHeaders => 'item:InternetMessageHeaders'
26
+ IsAssociated => 'item:IsAssociated'
27
+ IsDraft => 'item:IsDraft'
28
+ IsFromMe => 'item:IsFromMe'
29
+ IsResend => 'item:IsResend'
30
+ IsSubmitted => 'item:IsSubmitted'
31
+ IsUnmodified => 'item:IsUnmodified'
32
+ DateTimeSent => 'item:DateTimeSent'
33
+ DateTimeCreated => 'item:DateTimeCreated'
34
+ Body => 'item:Body'
35
+ ResponseObjects => 'item:ResponseObjects'
36
+ Sensitivity => 'item:Sensitivity'
37
+ ReminderDueBy => 'item:ReminderDueBy'
38
+ ReminderIsSet => 'item:ReminderIsSet'
39
+ ReminderMinutesBeforeStart => 'item:ReminderMinutesBeforeStart'
40
+ DisplayTo => 'item:DisplayTo'
41
+ DisplayCc => 'item:DisplayCc'
42
+ Culture => 'item:Culture'
43
+ EffectiveRights => 'item:EffectiveRights'
44
+ LastModifiedName => 'item:LastModifiedName'
45
+ LastModifiedTime => 'item:LastModifiedTime'
46
+ ConversationId => 'item:ConversationId'
47
+ UniqueBody => 'item:UniqueBody'
48
+ WebClientReadFormQueryString => 'item:WebClientReadFormQueryString'
49
+ WebClientEditFormQueryString => 'item:WebClientEditFormQueryString'
50
+ ConversationIndex => 'message:ConversationIndex'
51
+ ConversationTopic => 'message:ConversationTopic'
52
+ InternetMessageId => 'message:InternetMessageId'
53
+ IsRead => 'message:IsRead'
54
+ IsResponseRequested => 'message:IsResponseRequested'
55
+ IsReadReceiptRequested => 'message:IsReadReceiptRequested'
56
+ IsDeliveryReceiptRequested => 'message:IsDeliveryReceiptRequested'
57
+ References => 'message:References'
58
+ ReplyTo => 'message:ReplyTo'
59
+ From => 'message:From'
60
+ Sender => 'message:Sender'
61
+ ToRecipients => 'message:ToRecipients'
62
+ CcRecipients => 'message:CcRecipients'
63
+ BccRecipients => 'message:BccRecipients'
64
+ AssociatedCalendarItemId => 'meeting:AssociatedCalendarItemId'
65
+ IsDelegated => 'meeting:IsDelegated'
66
+ IsOutOfDate => 'meeting:IsOutOfDate'
67
+ HasBeenProcessed => 'meeting:HasBeenProcessed'
68
+ ResponseType => 'meeting:ResponseType'
69
+ MeetingRequestType => 'meetingRequest:MeetingRequestType'
70
+ IntendedFreeBusyStatus => 'meetingRequest:IntendedFreeBusyStatus'
71
+ Start => 'calendar:Start'
72
+ End => 'calendar:End'
73
+ OriginalStart => 'calendar:OriginalStart'
74
+ IsAllDayEvent => 'calendar:IsAllDayEvent'
75
+ LegacyFreeBusyStatus => 'calendar:LegacyFreeBusyStatus'
76
+ Location => 'calendar:Location'
77
+ When => 'calendar:When'
78
+ IsMeeting => 'calendar:IsMeeting'
79
+ IsCancelled => 'calendar:IsCancelled'
80
+ IsRecurring => 'calendar:IsRecurring'
81
+ MeetingRequestWasSent => 'calendar:MeetingRequestWasSent'
82
+ IsResponseRequested => 'calendar:IsResponseRequested'
83
+ CalendarItemType => 'calendar:CalendarItemType'
84
+ MyResponseType => 'calendar:MyResponseType'
85
+ Organizer => 'calendar:Organizer'
86
+ RequiredAttendees => 'calendar:RequiredAttendees'
87
+ OptionalAttendees => 'calendar:OptionalAttendees'
88
+ Resources => 'calendar:Resources'
89
+ ConflictingMeetingCount => 'calendar:ConflictingMeetingCount'
90
+ AdjacentMeetingCount => 'calendar:AdjacentMeetingCount'
91
+ ConflictingMeetings => 'calendar:ConflictingMeetings'
92
+ AdjacentMeetings => 'calendar:AdjacentMeetings'
93
+ Duration => 'calendar:Duration'
94
+ TimeZone => 'calendar:TimeZone'
95
+ AppointmentReplyTime => 'calendar:AppointmentReplyTime'
96
+ AppointmentSequenceNumber => 'calendar:AppointmentSequenceNumber'
97
+ AppointmentState => 'calendar:AppointmentState'
98
+ Recurrence => 'calendar:Recurrence'
99
+ FirstOccurrence => 'calendar:FirstOccurrence'
100
+ LastOccurrence => 'calendar:LastOccurrence'
101
+ ModifiedOccurrences => 'calendar:ModifiedOccurrences'
102
+ DeletedOccurrences => 'calendar:DeletedOccurrences'
103
+ MeetingTimeZone => 'calendar:MeetingTimeZone'
104
+ ConferenceType => 'calendar:ConferenceType'
105
+ AllowNewTimeProposal => 'calendar:AllowNewTimeProposal'
106
+ IsOnlineMeeting => 'calendar:IsOnlineMeeting'
107
+ MeetingWorkspaceUrl => 'calendar:MeetingWorkspaceUrl'
108
+ NetShowUrl => 'calendar:NetShowUrl'
109
+ UID => 'calendar:UID'
110
+ RecurrenceId => 'calendar:RecurrenceId'
111
+ DateTimeStamp => 'calendar:DateTimeStamp'
112
+ StartTimeZone => 'calendar:StartTimeZone'
113
+ EndTimeZone => 'calendar:EndTimeZone'
114
+ ActualWork => 'task:ActualWork'
115
+ AssignedTime => 'task:AssignedTime'
116
+ BillingInformation => 'task:BillingInformation'
117
+ ChangeCount => 'task:ChangeCount'
118
+ Companies => 'task:Companies'
119
+ CompleteDate => 'task:CompleteDate'
120
+ Contacts => 'task:Contacts'
121
+ DelegationState => 'task:DelegationState'
122
+ Delegator => 'task:Delegator'
123
+ DueDate => 'task:DueDate'
124
+ IsAssignmentEditable => 'task:IsAssignmentEditable'
125
+ IsComplete => 'task:IsComplete'
126
+ IsRecurring => 'task:IsRecurring'
127
+ IsTeamTask => 'task:IsTeamTask'
128
+ Mileage => 'task:Mileage'
129
+ Owner => 'task:Owner'
130
+ PercentComplete => 'task:PercentComplete'
131
+ Recurrence => 'task:Recurrence'
132
+ StartDate => 'task:StartDate'
133
+ Status => 'task:Status'
134
+ StatusDescription => 'task:StatusDescription'
135
+ TotalWork => 'task:TotalWork'
136
+ AssistantName => 'contacts:AssistantName'
137
+ Birthday => 'contacts:Birthday'
138
+ BusinessHomePage => 'contacts:BusinessHomePage'
139
+ Children => 'contacts:Children'
140
+ Companies => 'contacts:Companies'
141
+ CompanyName => 'contacts:CompanyName'
142
+ CompleteName => 'contacts:CompleteName'
143
+ ContactSource => 'contacts:ContactSource'
144
+ Culture => 'contacts:Culture'
145
+ Department => 'contacts:Department'
146
+ DisplayName => 'contacts:DisplayName'
147
+ EmailAddresses => 'contacts:EmailAddresses'
148
+ FileAs => 'contacts:FileAs'
149
+ FileAsMapping => 'contacts:FileAsMapping'
150
+ Generation => 'contacts:Generation'
151
+ GivenName => 'contacts:GivenName'
152
+ HasPicture => 'contacts:HasPicture'
153
+ ImAddresses => 'contacts:ImAddresses'
154
+ Initials => 'contacts:Initials'
155
+ JobTitle => 'contacts:JobTitle'
156
+ Manager => 'contacts:Manager'
157
+ MiddleName => 'contacts:MiddleName'
158
+ Mileage => 'contacts:Mileage'
159
+ Nickname => 'contacts:Nickname'
160
+ OfficeLocation => 'contacts:OfficeLocation'
161
+ PhoneNumbers => 'contacts:PhoneNumbers'
162
+ PhysicalAddresses => 'contacts:PhysicalAddresses'
163
+ PostalAddressIndex => 'contacts:PostalAddressIndex'
164
+ Profession => 'contacts:Profession'
165
+ SpouseName => 'contacts:SpouseName'
166
+ Surname => 'contacts:Surname'
167
+ WeddingAnniversary => 'contacts:WeddingAnniversary'
168
+ Members => 'distributionlist:Members'
169
+ PostedTime => 'postitem:PostedTime'
170
+ ConversationId => 'conversation:ConversationId'
171
+ ConversationTopic => 'conversation:ConversationTopic'
172
+ UniqueRecipients => 'conversation:UniqueRecipients'
173
+ GlobalUniqueRecipients => 'conversation:GlobalUniqueRecipients'
174
+ UniqueUnreadSenders => 'conversation:UniqueUnreadSenders'
175
+ GlobalUniqueUnreadSenders => 'conversation:GlobalUniqueUnreadSenders'
176
+ UniqueSenders => 'conversation:UniqueSenders'
177
+ GlobalUniqueSenders => 'conversation:GlobalUniqueSenders'
178
+ LastDeliveryTime => 'conversation:LastDeliveryTime'
179
+ GlobalLastDeliveryTime => 'conversation:GlobalLastDeliveryTime'
180
+ Categories => 'conversation:Categories'
181
+ GlobalCategories => 'conversation:GlobalCategories'
182
+ FlagStatus => 'conversation:FlagStatus'
183
+ GlobalFlagStatus => 'conversation:GlobalFlagStatus'
184
+ HasAttachments => 'conversation:HasAttachments'
185
+ GlobalHasAttachments => 'conversation:GlobalHasAttachments'
186
+ MessageCount => 'conversation:MessageCount'
187
+ GlobalMessageCount => 'conversation:GlobalMessageCount'
188
+ UnreadCount => 'conversation:UnreadCount'
189
+ GlobalUnreadCount => 'conversation:GlobalUnreadCount'
190
+ Size => 'conversation:Size'
191
+ GlobalSize => 'conversation:GlobalSize'
192
+ ItemClasses => 'conversation:ItemClasses'
193
+ GlobalItemClasses => 'conversation:GlobalItemClasses'
194
+ Importance => 'conversation:Importance'
195
+ GlobalImportance => 'conversation:GlobalImportance'
196
+ ItemIds => 'conversation:ItemIds'
197
+ GlobalItemIds => 'conversation:GlobalItemIds'
@@ -0,0 +1 @@
1
+ :folder_id => 'older:FolderId', :parent_folder_id => 'folder:ParentFolderId', :display_name => 'folder:DisplayName', :unread_count => 'folder:UnreadCount', :total_count => 'folder:TotalCount', :child_folder_count => 'folder:ChildFolderCount', :folder_class => 'folder:FolderClass', :search_parameters => 'folder:SearchParameters', :managed_folder_information => 'folder:ManagedFolderInformation', :permission_set => 'folder:PermissionSet', :effective_rights => 'folder:EffectiveRights', :sharing_effective_rights => 'folder:SharingEffectiveRights', :item_id => 'item:ItemId', :parent_folder_id => 'item:ParentFolderId', :item_class => 'item:ItemClass', :mime_content => 'item:MimeContent', :attachments => 'item:Attachments', :subject => 'item:Subject', :date_time_received => 'item:DateTimeReceived', :size => 'item:Size', :categories => 'item:Categories', :has_attachments => 'item:HasAttachments', :importance => 'item:Importance', :in_reply_to => 'item:InReplyTo', :internet_message_headers => 'item:InternetMessageHeaders', :is_associated => 'item:IsAssociated', :is_draft => 'item:IsDraft', :is_from_me => 'item:IsFromMe', :is_resend => 'item:IsResend', :is_submitted => 'item:IsSubmitted', :is_unmodified => 'item:IsUnmodified', :date_time_sent => 'item:DateTimeSent', :date_time_created => 'item:DateTimeCreated', :body => 'item:Body', :response_objects => 'item:ResponseObjects', :sensitivity => 'item:Sensitivity', :reminder_due_by => 'item:ReminderDueBy', :reminder_is_set => 'item:ReminderIsSet', :reminder_minutes_before_start => 'item:ReminderMinutesBeforeStart', :display_to => 'item:DisplayTo', :display_cc => 'item:DisplayCc', :culture => 'item:Culture', :effective_rights => 'item:EffectiveRights', :last_modified_name => 'item:LastModifiedName', :last_modified_time => 'item:LastModifiedTime', :conversation_id => 'item:ConversationId', :unique_body => 'item:UniqueBody', :web_client_read_form_query_string => 'item:WebClientReadFormQueryString', :web_client_edit_form_query_string => 'item:WebClientEditFormQueryString', :conversation_index => 'message:ConversationIndex', :conversation_topic => 'message:ConversationTopic', :internet_message_id => 'message:InternetMessageId', :is_read => 'message:IsRead', :is_response_requested => 'message:IsResponseRequested', :is_read_receipt_requested => 'message:IsReadReceiptRequested', :is_delivery_receipt_requested => 'message:IsDeliveryReceiptRequested', :references => 'message:References', :reply_to => 'message:ReplyTo', :from => 'message:From', :sender => 'message:Sender', :to_recipients => 'message:ToRecipients', :cc_recipients => 'message:CcRecipients', :bcc_recipients => 'message:BccRecipients', :associated_calendar_item_id => 'meeting:AssociatedCalendarItemId', :is_delegated => 'meeting:IsDelegated', :is_out_of_date => 'meeting:IsOutOfDate', :has_been_processed => 'meeting:HasBeenProcessed', :response_type => 'meeting:ResponseType', :meeting_request_type => 'meetingRequest:MeetingRequestType', :intended_free_busy_status => 'meetingRequest:IntendedFreeBusyStatus', :start => 'calendar:Start', :end => 'calendar:End', :original_start => 'calendar:OriginalStart', :is_all_day_event => 'calendar:IsAllDayEvent', :legacy_free_busy_status => 'calendar:LegacyFreeBusyStatus', :location => 'calendar:Location', :when => 'calendar:When', :is_meeting => 'calendar:IsMeeting', :is_cancelled => 'calendar:IsCancelled', :is_recurring => 'calendar:IsRecurring', :meeting_request_was_sent => 'calendar:MeetingRequestWasSent', :is_response_requested => 'calendar:IsResponseRequested', :calendar_item_type => 'calendar:CalendarItemType', :my_response_type => 'calendar:MyResponseType', :organizer => 'calendar:Organizer', :required_attendees => 'calendar:RequiredAttendees', :optional_attendees => 'calendar:OptionalAttendees', :resources => 'calendar:Resources', :conflicting_meeting_count => 'calendar:ConflictingMeetingCount', :adjacent_meeting_count => 'calendar:AdjacentMeetingCount', :conflicting_meetings => 'calendar:ConflictingMeetings', :adjacent_meetings => 'calendar:AdjacentMeetings', :duration => 'calendar:Duration', :time_zone => 'calendar:TimeZone', :appointment_reply_time => 'calendar:AppointmentReplyTime', :appointment_sequence_number => 'calendar:AppointmentSequenceNumber', :appointment_state => 'calendar:AppointmentState', :recurrence => 'calendar:Recurrence', :first_occurrence => 'calendar:FirstOccurrence', :last_occurrence => 'calendar:LastOccurrence', :modified_occurrences => 'calendar:ModifiedOccurrences', :deleted_occurrences => 'calendar:DeletedOccurrences', :meeting_time_zone => 'calendar:MeetingTimeZone', :conference_type => 'calendar:ConferenceType', :allow_new_time_proposal => 'calendar:AllowNewTimeProposal', :is_online_meeting => 'calendar:IsOnlineMeeting', :meeting_workspace_url => 'calendar:MeetingWorkspaceUrl', :net_show_url => 'calendar:NetShowUrl', :u_i_d => 'calendar:UID', :recurrence_id => 'calendar:RecurrenceId', :date_time_stamp => 'calendar:DateTimeStamp', :start_time_zone => 'calendar:StartTimeZone', :end_time_zone => 'calendar:EndTimeZone', :actual_work => 'task:ActualWork', :assigned_time => 'task:AssignedTime', :billing_information => 'task:BillingInformation', :change_count => 'task:ChangeCount', :companies => 'task:Companies', :complete_date => 'task:CompleteDate', :contacts => 'task:Contacts', :delegation_state => 'task:DelegationState', :delegator => 'task:Delegator', :due_date => 'task:DueDate', :is_assignment_editable => 'task:IsAssignmentEditable', :is_complete => 'task:IsComplete', :is_recurring => 'task:IsRecurring', :is_team_task => 'task:IsTeamTask', :mileage => 'task:Mileage', :owner => 'task:Owner', :percent_complete => 'task:PercentComplete', :recurrence => 'task:Recurrence', :start_date => 'task:StartDate', :status => 'task:Status', :status_description => 'task:StatusDescription', :total_work => 'task:TotalWork', :assistant_name => 'contacts:AssistantName', :birthday => 'contacts:Birthday', :business_home_page => 'contacts:BusinessHomePage', :children => 'contacts:Children', :companies => 'contacts:Companies', :company_name => 'contacts:CompanyName', :complete_name => 'contacts:CompleteName', :contact_source => 'contacts:ContactSource', :culture => 'contacts:Culture', :department => 'contacts:Department', :display_name => 'contacts:DisplayName', :email_addresses => 'contacts:EmailAddresses', :file_as => 'contacts:FileAs', :file_as_mapping => 'contacts:FileAsMapping', :generation => 'contacts:Generation', :given_name => 'contacts:GivenName', :has_picture => 'contacts:HasPicture', :im_addresses => 'contacts:ImAddresses', :initials => 'contacts:Initials', :job_title => 'contacts:JobTitle', :manager => 'contacts:Manager', :middle_name => 'contacts:MiddleName', :mileage => 'contacts:Mileage', :nickname => 'contacts:Nickname', :office_location => 'contacts:OfficeLocation', :phone_numbers => 'contacts:PhoneNumbers', :physical_addresses => 'contacts:PhysicalAddresses', :postal_address_index => 'contacts:PostalAddressIndex', :profession => 'contacts:Profession', :spouse_name => 'contacts:SpouseName', :surname => 'contacts:Surname', :wedding_anniversary => 'contacts:WeddingAnniversary', :members => 'distributionlist:Members', :posted_time => 'postitem:PostedTime', :conversation_id => 'conversation:ConversationId', :conversation_topic => 'conversation:ConversationTopic', :unique_recipients => 'conversation:UniqueRecipients', :global_unique_recipients => 'conversation:GlobalUniqueRecipients', :unique_unread_senders => 'conversation:UniqueUnreadSenders', :global_unique_unread_senders => 'conversation:GlobalUniqueUnreadSenders', :unique_senders => 'conversation:UniqueSenders', :global_unique_senders => 'conversation:GlobalUniqueSenders', :last_delivery_time => 'conversation:LastDeliveryTime', :global_last_delivery_time => 'conversation:GlobalLastDeliveryTime', :categories => 'conversation:Categories', :global_categories => 'conversation:GlobalCategories', :flag_status => 'conversation:FlagStatus', :global_flag_status => 'conversation:GlobalFlagStatus', :has_attachments => 'conversation:HasAttachments', :global_has_attachments => 'conversation:GlobalHasAttachments', :message_count => 'conversation:MessageCount', :global_message_count => 'conversation:GlobalMessageCount', :unread_count => 'conversation:UnreadCount', :global_unread_count => 'conversation:GlobalUnreadCount', :size => 'conversation:Size', :global_size => 'conversation:GlobalSize', :item_classes => 'conversation:ItemClasses', :global_item_classes => 'conversation:GlobalItemClasses', :importance => 'conversation:Importance', :global_importance => 'conversation:GlobalImportance', :item_ids => 'conversation:ItemIds', :global_item_ids => 'conversation:GlobalItemIds'
@@ -43,27 +43,25 @@ module Viewpoint
43
43
  # <SharingEffectiveRights/>
44
44
  end
45
45
 
46
- # Find Items
47
- # @see GenericFolder#find_items
48
- def find_items(start_date = nil, end_date = nil)
49
- opts ||= {}
50
- if(!start_date.nil? && !end_date.nil?)
51
- opts = {:calendar_view => {:max_entries_returned => 256, :start_date => start_date, :end_date => end_date}}
52
- end
53
- super(opts)
54
- end
55
- alias :items_between :find_items
56
-
57
46
  # Fetch only items from today (since midnight)
58
- def todays_items
47
+ def todays_items(opts = {})
59
48
  #This is a bit convoluted for pre-1.9.x ruby versions that don't support to_datetime
60
- find_items(DateTime.parse(Date.today.to_s), DateTime.parse((Date.today + 1).to_s))
49
+ items_between(DateTime.parse(Date.today.to_s), DateTime.parse((Date.today + 1).to_s), opts)
61
50
  end
62
51
 
63
52
  # Fetch items since a give DateTime
64
53
  # @param [DateTime] start_date_time the time to fetch Items since.
65
- def items_since(start_date_time)
66
- find_items(start_date_time, DateTime.now)
54
+ def items_since(start_date_time, opts = {})
55
+ items_between(start_date_time, DateTime.now, opts)
56
+ end
57
+
58
+ # Find Calendar Items between two dates
59
+ # @param [DateTime] start_date the date to start the search from
60
+ # @param [DateTime] end_date the date to end the search at
61
+ # @param [Hash] opts misc opts like restrictions, etc
62
+ def items_between(start_date, end_date, opts = {})
63
+ opts[:calendar_view] = {:max_entries_returned => 256, :start_date => start_date, :end_date => end_date}
64
+ find_items(opts)
67
65
  end
68
66
 
69
67
  end # CalendarFolder
@@ -87,6 +87,89 @@ module Viewpoint
87
87
 
88
88
  def init_methods
89
89
  super()
90
+
91
+ define_str_var :file_as, :file_as_mapping, :display_name, :job_title, :given_name, :surname
92
+ define_attr_str_var :complete_name, :first_name, :middle_name, :last_name, :initials, :full_name
93
+ define_inet_addresses :email_addresses, :im_addresses
94
+ define_phone_numbers :phone_numbers
95
+ define_physical_addresses :physical_addresses
96
+ end
97
+
98
+ # Define email_addresses or im_addresses for a Contact
99
+ def define_inet_addresses(*inet_addresses)
100
+ inet_addresses.each do |itype|
101
+ eval "@#{itype} ||= {}"
102
+ return unless self.instance_variable_get("@#{itype}").empty?
103
+ if(@ews_item.has_key?(itype))
104
+ @ews_methods << itype
105
+ if(@ews_item[itype][:entry].is_a?(Array))
106
+ @ews_item[itype][:entry].each do |entry|
107
+ next if entry.keys.length == 1
108
+ eval "@#{itype}[entry[:key].ruby_case.to_sym] = (entry.has_key?(:text) ? entry[:text] : '')"
109
+ end
110
+ else
111
+ entry = @ews_item[itype][:entry]
112
+ next if entry.keys.length == 1
113
+ eval "@#{itype}[entry[:key].ruby_case.to_sym] = (entry.has_key?(:text) ? entry[:text] : '')"
114
+ end
115
+ self.instance_eval <<-EOF
116
+ def #{itype}
117
+ self.instance_variable_get "@#{itype}"
118
+ end
119
+ EOF
120
+ else
121
+ @ews_methods_undef << itype
122
+ end
123
+ end
124
+ end
125
+
126
+ def define_phone_numbers(phone_numbers)
127
+ @phone_numbers ||= {}
128
+ return unless @phone_numbers.empty?
129
+ if(@ews_item.has_key?(phone_numbers))
130
+ if(@ews_item[phone_numbers][:entry].is_a?(Array))
131
+ @ews_item[phone_numbers][:entry].each do |entry|
132
+ next if entry.keys.length == 1
133
+ @phone_numbers[entry[:key].ruby_case.to_sym] = (entry.has_key?(:text) ? entry[:text] : "")
134
+ end
135
+ else # it is a Hash then
136
+ entry = @ews_item[phone_numbers][:entry]
137
+ return if entry.keys.length == 1
138
+ @phone_numbers[entry[:key].ruby_case.to_sym] = (entry.has_key?(:text) ? entry[:text] : "")
139
+ end
140
+ self.instance_eval <<-EOF
141
+ def #{phone_numbers}
142
+ @phone_numbers
143
+ end
144
+ EOF
145
+ @ews_methods << phone_numbers
146
+ else
147
+ @ews_methods_undef << itype
148
+ end
149
+ end
150
+
151
+ # Define physical_addresses for a Contact
152
+ def define_physical_addresses(physical_addresses)
153
+ @physical_addresses ||= {}
154
+ return unless @physical_addresses.empty?
155
+ if(@ews_item.has_key?(physical_addresses))
156
+ @ews_methods << physical_addresses
157
+ @ews_item[physical_addresses][:entry].each do |entry|
158
+ next if entry.keys.length == 1
159
+ key = entry.delete(:key)
160
+ @physical_addresses[key.ruby_case.to_sym] = {}
161
+ entry.each_pair do |ekey,ev|
162
+ @physical_addresses[key.ruby_case.to_sym][ekey] = ev[:text]
163
+ end
164
+ end
165
+ self.instance_eval <<-EOF
166
+ def #{physical_addresses}
167
+ @physical_addresses
168
+ end
169
+ EOF
170
+ else
171
+ @ews_methods_undef << itype
172
+ end
90
173
  end
91
174
 
92
175
  end # Contact
@@ -215,7 +215,7 @@ module Viewpoint
215
215
 
216
216
  # Find Items
217
217
  def find_items(opts = {})
218
- item_shape = {:base_shape => 'Default'}
218
+ item_shape = opts.has_key?(:item_shape) ? opts.delete(:item_shape) : {:base_shape => 'Default'}
219
219
  item_shape[:additional_properties] = {:field_uRI => ['item:ParentFolderId']}
220
220
  resp = (Viewpoint::EWS::EWS.instance).ews.find_item([@folder_id], 'Shallow', item_shape, opts)
221
221
  if(resp.status == 'Success')
@@ -232,27 +232,27 @@ module Viewpoint
232
232
  end
233
233
 
234
234
  # Fetch only items from today (since midnight)
235
- def todays_items
235
+ def todays_items(opts = {})
236
236
  #opts = {:query_string => ["Received:today"]}
237
237
  #This is a bit convoluted for pre-1.9.x ruby versions that don't support to_datetime
238
- items_since(DateTime.parse(Date.today.to_s))
238
+ items_since(DateTime.parse(Date.today.to_s), opts)
239
239
  end
240
240
 
241
241
  # Fetch items since a give DateTime
242
242
  # @param [DateTime] date_time the time to fetch Items since.
243
- def items_since(date_time)
243
+ def items_since(date_time, opts = {})
244
244
  restr = {:restriction =>
245
245
  {:is_greater_than_or_equal_to =>
246
246
  [{:field_uRI => {:field_uRI=>'item:DateTimeReceived'}},
247
247
  {:field_uRI_or_constant =>{:constant => {:value=>date_time}}}]
248
248
  }}
249
- find_items(restr)
249
+ find_items(opts.merge(restr))
250
250
  end
251
251
 
252
252
  # Fetch items between a given time period
253
253
  # @param [DateTime] start_date the time to start fetching Items from
254
254
  # @param [DateTime] end_date the time to stop fetching Items from
255
- def items_between(start_date, end_date)
255
+ def items_between(start_date, end_date, opts={})
256
256
  restr = {:restriction => {:and => [
257
257
  {:is_greater_than_or_equal_to =>
258
258
  [{:field_uRI => {:field_uRI=>'item:DateTimeReceived'}},
@@ -261,7 +261,7 @@ module Viewpoint
261
261
  [{:field_uRI => {:field_uRI=>'item:DateTimeReceived'}},
262
262
  {:field_uRI_or_constant=>{:constant => {:value =>end_date}}}]}
263
263
  ]}}
264
- find_items(restr)
264
+ find_items(opts.merge(restr))
265
265
  end
266
266
 
267
267
  # Search on the item subject
@@ -323,8 +323,9 @@ module Viewpoint
323
323
  # an array of ItemIds are returned wich is a Hash in the form:
324
324
  # {:id=>"item id", :change_key=>"change key"}
325
325
  # See: http://msdn.microsoft.com/en-us/library/aa565609.aspx
326
- def sync_items!(sync_amount = 256, sync_all = false)
327
- resp = (Viewpoint::EWS::EWS.instance).ews.sync_folder_items(@folder_id, @sync_state, sync_amount)
326
+ def sync_items!(sync_amount = 256, sync_all = false, opts = {})
327
+ item_shape = opts.has_key?(:item_shape) ? opts.delete(:item_shape) : {:base_shape => 'Default'}
328
+ resp = (Viewpoint::EWS::EWS.instance).ews.sync_folder_items(@folder_id, @sync_state, sync_amount, item_shape)
328
329
  parms = resp.items.shift
329
330
  @sync_state = parms[:sync_state]
330
331
  @synced = parms[:includes_last_item_in_range]
@@ -351,14 +352,14 @@ module Viewpoint
351
352
  # additional items. Calling this method again will clear the sync_state and synchronize
352
353
  # everything again.
353
354
  # @return [Array<Item>] returns an array of Items
354
- def sync_items_since!(datetime)
355
+ def sync_items_since!(datetime, opts={})
355
356
  clear_sync_state!
356
357
 
357
358
  begin
358
359
  items = sync_items!
359
360
  end until items.empty?
360
361
 
361
- items_since(datetime)
362
+ items_since(datetime, opts)
362
363
  end
363
364
 
364
365
  # Clears out the @sync_state so you can freshly synchronize this folder if needed
@@ -26,6 +26,7 @@ module Viewpoint
26
26
  module EWS
27
27
  class Item
28
28
  include Model
29
+ include ItemFieldUriMap
29
30
 
30
31
  # This is a class method that fetches an existing Item from the
31
32
  # Exchange Store.
@@ -69,6 +70,7 @@ module Viewpoint
69
70
  @item_id = ews_item[:item_id][:id]
70
71
  @change_key = ews_item[:item_id][:change_key]
71
72
  @text_only = false
73
+ @updates = {}
72
74
 
73
75
  init_methods
74
76
  end
@@ -86,24 +88,60 @@ module Viewpoint
86
88
  @text_only = ( txt == true ? true : false)
87
89
  end
88
90
 
91
+ # Save any pending updates that were manipulated via setter methods.
92
+ def save!
93
+ return true if @updates.empty?
94
+ if update_attribs!(@updates)
95
+ @updates = {}
96
+ true
97
+ else
98
+ false
99
+ end
100
+ end
101
+
89
102
  # Call UpdateItem for this item with the passed updates
90
103
  # @param [Hash] updates a well-formed update hash
91
- # @example {:updates=>{:set_item_field=>{:field_u_r_i=>{:field_u_r_i=>"message:IsRead"}, :message=>{:is_read=>{:text=>"true"}}}}}
104
+ # @example {:set_item_field=>{:field_u_r_i=>{:field_u_r_i=>"message:IsRead"}, :message=>{:is_read=>{:text=>"true"}}}}
92
105
  def update!(updates)
93
106
  conn = Viewpoint::EWS::EWS.instance
94
- resp = conn.ews.update_item([{:id => @item_id, :change_key => @change_key}], updates)
95
- (resp.status == 'Success') || (raise EwsError, "Trouble updating Item. #{resp.code}: #{resp.message}")
107
+ resp = conn.ews.update_item([{:id => @item_id, :change_key => @change_key}], {:updates => updates})
108
+ if resp.status == 'Success'
109
+ @item_id = resp.items.first[resp.items.first.keys.first][:item_id][:id]
110
+ @change_key = resp.items.first[resp.items.first.keys.first][:item_id][:change_key]
111
+ @shallow = true
112
+ deepen!
113
+ else
114
+ raise EwsError, "Trouble updating Item. #{resp.code}: #{resp.message}"
115
+ end
116
+
117
+ end
118
+
119
+ # This takes a hash of attributes with new values and builds the appropriate udpate hash
120
+ # @param [Hash] updates a hash that is formed like so :item_attr => newvalue
121
+ # @example {:sensitivity => {:text => 'Normal'}, :display_name => {:text => 'Test User'}}
122
+ def update_attribs!(updates)
123
+ changes = []
124
+ type = self.class.name.split(/::/).last.ruby_case.to_sym
125
+
126
+ updates.each_pair do |k,v|
127
+ raise EwsError, "Field (#{FIELD_URIS[k][:text]}) not writable by update." unless FIELD_URIS[k][:writable]
128
+ changes << {:set_item_field=>{:field_u_r_i=>{:field_u_r_i=>FIELD_URIS[k][:text]}, type=>{k => v}}}
129
+ end
130
+
131
+ update!(changes)
96
132
  end
97
133
 
98
134
  # Mark this Item as read
99
135
  def mark_read!
100
- update!({:updates=>{:set_item_field=>{:field_u_r_i=>{:field_u_r_i=>"message:IsRead"}, :message=>{:is_read=>{:text=>"true"}}}}})
136
+ field = :is_read
137
+ update!({:set_item_field=>{:field_u_r_i=>{:field_u_r_i=>FIELD_URIS[field][:text]}, :message=>{field=>{:text=>"true"}}}})
101
138
  @is_read = true
102
139
  end
103
140
 
104
141
  # Mark this Item as unread
105
142
  def mark_unread!
106
- update!({:updates=>{:set_item_field=>{:field_u_r_i=>{:field_u_r_i=>"message:IsRead"}, :message=>{:is_read=>{:text=>"false"}}}}})
143
+ field = :is_read
144
+ update!({:set_item_field=>{:field_u_r_i=>{:field_u_r_i=>FIELD_URIS[field][:text]}, :message=>{field=>{:text=>"false"}}}})
107
145
  @is_read = false
108
146
  true
109
147
  end
@@ -209,6 +247,7 @@ module Viewpoint
209
247
  end
210
248
 
211
249
 
250
+
212
251
  private
213
252
 
214
253
  # @todo Handle: