Completed
Push — master ( c381ae...1447a4 )
by Gareth
08:30
created

CalendarAPI::pickCalendar()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 12
ccs 7
cts 7
cp 1
rs 9.4285
cc 3
eloc 7
nc 2
nop 1
crap 3
1
<?php
2
3
namespace garethp\ews;
4
5
use garethp\ews\API\Message\FreeBusyResponseType;
6
use garethp\ews\API\Type\CalendarItemType;
7
use garethp\ews\API\Type;
8
use garethp\ews\API\Enumeration;
9
use DateTime;
10
11
/**
12
 * An API end point for Calendar items
13
 *
14
 * Class API
15
 * @package garethp\ews\Calendar
16
 */
17
class CalendarAPI extends API
18
{
19
    /**
20
     * @var Type\FolderIdType
21
     */
22
    protected $folderId;
23
24
    /**
25
     * Pick a Calendar based on it's name
26
     *
27
     * @param string|null $displayName
28
     * @return $this
29
     */
30 6
    public function pickCalendar($displayName = null)
31
    {
32 6
        if ($displayName == 'default.calendar' || $displayName == null) {
33 1
            $folder = $this->getFolderByDistinguishedId('calendar');
34 1
        } else {
35 6
            $folder = $this->getFolderByDisplayName($displayName, 'calendar');
36
        }
37
38 6
        $this->folderId = $folder->getFolderId();
39
40 6
        return $this;
41
    }
42
43
    /**
44
     * @return Type\FolderIdType
45
     */
46 6
    public function getFolderId()
47
    {
48 6
        if ($this->folderId === null) {
49
            $this->pickCalendar();
50
        }
51
52 6
        return $this->folderId;
53
    }
54
55
    /**
56
     * @param Type\FolderIdType $folderId
57
     * @return $this
58
     */
59
    public function setFolderId($folderId)
60
    {
61
        $this->folderId = $folderId;
62
63
        return $this;
64
    }
65
66
    /**
67
     * Create one or more calendar items
68
     *
69
     * @param $items CalendarItemType[]|CalendarItemType|array or more calendar items to create
70
     * @param $options array Options to merge in to the request
71
     * @return Type\ItemIdType[]
72
     */
73 6
    public function createCalendarItems($items, $options = array())
74
    {
75
        //If the item passed in is an object, or if it's an associative]
76
        // array waiting to be an object, let's put it in to an array
77 3
        if (!is_array($items) || Type::arrayIsAssoc($items)) {
78 2
            $items = array($items);
79 2
        }
80
81 3
        $item = array('CalendarItem' => $items);
82
        $defaultOptions = array(
83 3
            'SendMeetingInvitations' => Enumeration\CalendarItemCreateOrDeleteOperationType::SEND_TO_NONE,
84
            'SavedItemFolderId' => array(
85 3
                'FolderId' => $this->getFolderId()->toXmlObject()
86 3
            )
87 3
        );
88
89 3
        $options = array_replace_recursive($defaultOptions, $options);
90
91 6
        $items = $this->createItems($item, $options);
92
93 3
        if (!is_array($items)) {
94 2
            $items = array($items);
95 2
        }
96
97 3
        return $items;
98
    }
99
100
    /**
101
     * Get a list of calendar items between two dates/times
102
     *
103
     * @param string|DateTime $start
104
     * @param string|DateTime $end
105
     * @param array $options
106
     * @return CalendarItemType[]|Type\FindItemParentType
107
     */
108 6
    public function getCalendarItems($start = '12:00 AM', $end = '11:59 PM', $options = array())
109
    {
110 6
        if (!($start instanceof DateTime)) {
111 6
            $start = new DateTime($start);
112 6
        }
113
114 6
        if (!($end instanceof DateTime)) {
115 6
            $end = new DateTime($end);
116 6
        }
117
118
        $request = [
119 6
            'Traversal' => 'Shallow',
120
            'ItemShape' => [
121
                'BaseShape' => 'AllProperties'
122 6
            ],
123
            'CalendarView' => [
124 6
                'MaxEntriesReturned' => 100,
125 6
                'StartDate' => $start->format('c'),
126 6
                'EndDate' => $end->format('c')
127 6
            ],
128
            'ParentFolderIds' => [
129 6
                'FolderId' => $this->getFolderId()->toXmlObject()
130 6
            ]
131 6
        ];
132
133 6
        $request = array_replace_recursive($request, $options);
134
135 6
        $request = Type::buildFromArray($request);
136 6
        $response = $this->getClient()->FindItem($request);
137 6
        $items = $response;
138
139 6
        return $items;
140
    }
141
142
    /**
143
     * @param $id
144
     * @param $changeKey
145
     * @return Type\CalendarItemType
146
     */
147 1
    public function getCalendarItem($id, $changeKey)
148
    {
149 1
        return $this->getItem(['Id' => $id, 'ChangeKey' => $changeKey]);
150
    }
151
152
    /**
153
     * Updates a calendar item with changes
154
     *
155
     * @param $itemId Type\ItemIdType
156
     * @param array $changes
157
     * @return Type\CalendarItemType[]
158
     */
159 1
    public function updateCalendarItem(Type\ItemIdType $itemId, $changes)
160
    {
161
        //Create the request
162
        $request = [
163
            'ItemChange' => [
164 1
                'ItemId' => $itemId->toArray(),
165 1
                'Updates' => API\ItemUpdateBuilder::buildUpdateItemChanges('CalendarItem', 'calendar', $changes)
166 1
            ]
167 1
        ];
168
169
        $options = [
170
            'SendMeetingInvitationsOrCancellations' => 'SendToNone'
171 1
        ];
172
173 1
        $items = $this->updateItems($request, $options)->getCalendarItem();
174
175 1
        if (!is_array($items)) {
176 1
            $items = [$items];
177 1
        }
178
179 1
        return $items;
180
    }
181
182
    /**
183
     * @param Type\ItemIdType $itemId
184
     * @param array $options
185
     * @return bool
186
     */
187 3
    public function deleteCalendarItem(Type\ItemIdType $itemId, $options = array())
188
    {
189
        $defaultOptions = array(
190
            'SendMeetingCancellations' => 'SendToNone'
191 3
        );
192
193 3
        $options = array_replace_recursive($defaultOptions, $options);
194 3
        return $this->deleteItems($itemId, $options);
195
    }
196
197
    /**
198
     * @param string $start
199
     * @param string $end
200
     * @param array $options
201
     */
202 6
    public function deleteAllCalendarItems($start = '12:00 AM', $end = '11:59 PM', $options = array())
203
    {
204 6
        $items = $this->getCalendarItems($start, $end, $options);
205 6
        foreach ($items as $item) {
0 ignored issues
show
Bug introduced by
The expression $items of type object<garethp\ews\API\Type> is not traversable.
Loading history...
206 2
            $this->deleteCalendarItem($item->getItemId());
207 6
        }
208 6
    }
209
210
    /**
211
     * Get a list of changes on the calendar items
212
     *
213
     * @param null $syncState
214
     * @param array $options
215
     * @return API\Message\SyncFolderItemsResponseMessageType
216
     */
217 1
    public function listChanges($syncState = null, $options = array())
218
    {
219 1
        return parent::listItemChanges($this->getFolderId(), $syncState, $options);
220
    }
221
222
    /**
223
     * @param Type\ItemIdType $itemId
224
     * @param string $message
225
     * @param string $sensitivity
226
     * @param array $options
227
     *
228
     * @return Type\ItemIdType[]
229
     */
230 View Code Duplication
    public function acceptMeeting($itemId, $message, $sensitivity = 'Private', $options = array())
231
    {
232
        $request = [
233
            'AcceptItem' => [
234
                'Sensitivity' => $sensitivity,
235
                'Body' => ['BodyType' => 'HTML', '_value' => $message],
236
                'ReferenceItemId' => $itemId->toArray()
237
            ]
238
        ];
239
240
        $defaultOptions = ['MessageDisposition' => 'SendOnly'];
241
        $options = array_replace_recursive($defaultOptions, $options);
242
243
        $return = $this->createItems($request, $options)->getCalendarItem();
244
        if (!is_array($request)) {
245
            $return = [$return];
246
        }
247
248
        return $return;
249
    }
250
251
    /**
252
     * @param $itemId
253
     * @param $message
254
     * @param string $sensitivity
255
     * @param array $options
256
     * @return Type\ItemIdType[]
257
     */
258 View Code Duplication
    public function declineMeeting($itemId, $message, $sensitivity = 'Private', $options = array())
259
    {
260
        $request = [
261
            'DeclineItem' => [
262
                'Sensitivity' => $sensitivity,
263
                'Body' => ['BodyType' => 'HTML', '_value' => $message],
264
                'ReferenceItemId' => $itemId->toArray()
265
            ]
266
        ];
267
268
        $defaultOptions = array('MessageDisposition' => 'SendOnly');
269
        $options = array_replace_recursive($defaultOptions, $options);
270
271
        $return = $this->createItems($request, $options)->getCalendarItem();
272
        if (!is_array($request)) {
273
            $return = array($return);
274
        }
275
276
        return $return;
277
    }
278
279
    /**
280
     * @param $startTime
281
     * @param $endTime
282
     * @param array $users
283
     * @param array $options
284
     *
285
     * @return API\Message\GetUserAvailabilityResponseType
286
     */
287
    public function getAvailabilityFor($startTime, $endTime, array $users, array $options = array())
288
    {
289
        if (!$startTime instanceof DateTime) {
290
            $startTime = new DateTime($startTime);
291
        }
292
293
        if (!$endTime instanceof DateTime) {
294
            $endTime = new DateTime($endTime);
295
        }
296
297
        $request = [
298
            'MailboxDataArray' => ['MailboxData' => []],
299
            'FreeBusyViewOptions' => [
300
                'TimeWindow' => [
301
                    'StartTime' => $startTime->format('c'),
302
                    'EndTime' => $endTime->format('c'),
303
                ],
304
                'RequestedView' => 'FreeBusyMerged',
305
                'MergedFreeBusyIntervalInMinutes' => 30
306
            ],
307
        ];
308
309
        $users = array_map(function ($user) {
310
            return [
311
                'Email' => ['Address' => $user],
312
                'AttendeeType' => 'Required',
313
                'ExcludeConflicts' => false
314
            ];
315
        }, $users);
316
317
        $request['MailboxDataArray']['MailboxData'] = $users;
318
319
        $request = array_replace_recursive($request, $options);
320
        $response = $this->getClient()->GetUserAvailability($request);
321
        return $response;
322
    }
323
324
    /**
325
     * @param $startTime
326
     * @param $endTime
327
     * @param int $period The period of time to see if users of free for (in minutes)
328
     * @param array $users
329
     * @param array $options
330
     *
331
     * @return boolean
332
     */
333
    public function areAvailable($startTime, $endTime, $period, array $users, array $options = [])
334
    {
335
        $options = array_replace_recursive($options, [
336
            'FreeBusyViewOptions' => [
337
                'MergedFreeBusyIntervalInMinutes' => $period, 'RequestedView' => 'MergedOnly'
338
            ]]);
339
        $availability = $this->getAvailabilityFor($startTime, $endTime, $users, $options);
340
341
        $availabilities = array_map(function (FreeBusyResponseType $freeBusyResponseType) {
342
            return str_split($freeBusyResponseType->getFreeBusyView()->getMergedFreeBusy());
343
        }, $availability->getFreeBusyResponseArray()->FreeBusyResponse);
344
345
        foreach ($availabilities[0] as $periodIndex => $availability) {
346
            if ($availability != 0) {
347
                continue;
348
            }
349
350
            $free = true;
351
            foreach ($availabilities as $userAvailability) {
352
                if ($userAvailability[$periodIndex] != 0) {
353
                    $free = false;
354
                    break;
355
                }
356
            }
357
358
            if ($free === false) {
359
                continue;
360
            }
361
362
            return true;
363
        }
364
365
        return false;
366
    }
367
}
368