Passed
Push — master ( 56f7f0...182f6a )
by Gareth
02:15
created

API   B

Complexity

Total Complexity 47

Size/Duplication

Total Lines 516
Duplicated Lines 0 %

Test Coverage

Coverage 84.21%

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 180
dl 0
loc 516
ccs 192
cts 228
cp 0.8421
rs 8.64
c 5
b 0
f 0
wmc 47

32 Methods

Rating   Name   Duplication   Size   Complexity  
A getMailbox() 0 7 1
A withCustomAuthentication() 0 6 1
A deleteFolder() 0 3 1
A getPrimarySmptEmailAddress() 0 7 2
A __construct() 0 4 2
A getPrimarySmtpMailbox() 0 3 1
A withCallbackToken() 0 6 1
A setPrimarySmtpEmailAddress() 0 5 1
A setClient() 0 5 1
A getItem() 0 14 2
A withUsernameAndPassword() 0 7 1
A getCalendar() 0 7 1
A getClient() 0 3 1
A getFolderByFolderId() 0 9 2
A getFolderByDisplayName() 0 11 3
A createContactsFolder() 0 7 2
A createCalendars() 0 7 2
A moveItem() 0 10 1
A getFolder() 0 16 1
A createItems() 0 13 1
A updateItems() 0 18 2
A deleteItems() 0 21 1
A createFolders() 0 19 2
A deleteFolders() 0 11 1
A getFolderByDistinguishedId() 0 8 1
A listItemChanges() 0 20 2
A getChildrenFolders() 0 20 2
A getServerTimezones() 0 12 2
A getNextPage() 0 17 3
A emptyFolder() 0 15 1
A getDistinguishedFolderId() 0 6 1
A convertIdFormat() 0 16 1

How to fix   Complexity   

Complex Class

Complex classes like API often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use API, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace garethp\ews;
4
5
use garethp\ews\API\ExchangeWebServices;
6
use garethp\ews\API\Message\EmptyFolderResponseType;
7
use garethp\ews\API\Message\GetServerTimeZonesType;
8
use garethp\ews\API\Message\SyncFolderItemsResponseMessageType;
9
use garethp\ews\API\Message\UpdateItemResponseMessageType;
10
use garethp\ews\API\Type;
11
use garethp\ews\API\Type\BaseFolderIdType;
12
13
/**
14
 * A base class for APIs
15
 *
16
 * Class BaseAPI
17
 * @package garethp\ews
18
 */
19
class API
20
{
21
    protected static $defaultClientOptions = array(
22
        'version' => ExchangeWebServices::VERSION_2010
23
    );
24
25 44
    public function __construct(ExchangeWebServices $client = null)
26
    {
27 44
        if ($client) {
28 44
            $this->setClient($client);
29
        }
30
    }
31
32
    /**
33
     * @return Type\EmailAddressType
34
     */
35 34
    public function getPrimarySmtpMailbox()
36
    {
37 34
        return $this->getClient()->getPrimarySmtpMailbox();
38
    }
39
40
    /**
41
     * Storing the API client
42
     * @var ExchangeWebServices
43
     */
44
    private $client;
45
46
    /**
47
     * Get a calendar item
48
     *
49
     * @param string $name
50
     * @return CalendarAPI
51
     */
52 9
    public function getCalendar($name = null)
53
    {
54 9
        $calendar = new CalendarAPI();
55 9
        $calendar->setClient($this->getClient());
56 9
        $calendar->pickCalendar($name);
57
58 9
        return $calendar;
59
    }
60
61
    /**
62
     * @param string $folderName
63
     * @return MailAPI
64
     */
65 8
    public function getMailbox($folderName = null)
66
    {
67 8
        $mailApi = new MailAPI();
68 8
        $mailApi->setClient($this->getClient());
69 8
        $mailApi->pickMailFolder($folderName);
70
71 8
        return $mailApi;
72
    }
73
74
    /**
75
     * Set the API client
76
     *
77
     * @param ExchangeWebServices $client
78
     * @return $this
79
     */
80 44
    public function setClient($client)
81
    {
82 44
        $this->client = $client;
83
84 44
        return $this;
85
    }
86
87
    /**
88
     * Get the API client
89
     *
90
     * @return ExchangeWebServices
91
     */
92 43
    public function getClient()
93
    {
94 43
        return $this->client;
95
    }
96
97 42
    public static function withUsernameAndPassword($server, $username, $password, $options = [])
98
    {
99 42
        return new static(ExchangeWebServices::fromUsernameAndPassword(
100 42
            $server,
101 42
            $username,
102 42
            $password,
103 42
            array_replace_recursive(self::$defaultClientOptions, $options)
104 42
        ));
105
    }
106
107 1
    public static function withCallbackToken($server, $token, $options = [])
108
    {
109 1
        return new static(ExchangeWebServices::fromCallbackToken(
110 1
            $server,
111 1
            $token,
112 1
            array_replace_recursive(self::$defaultClientOptions, $options)
113 1
        ));
114
    }
115
116 1
    public static function withCustomAuthentication($server, $authentication, $options = [])
117
    {
118 1
        return new static(ExchangeWebServices::fromCustomAuthentication(
119 1
            $server,
120 1
            $authentication,
121 1
            array_replace_recursive(self::$defaultClientOptions, $options)
122 1
        ));
123
    }
124
125 1
    public function getPrimarySmptEmailAddress()
126
    {
127 1
        if ($this->getPrimarySmtpMailbox() == null) {
128 1
            return null;
129
        }
130
131 1
        return $this->getPrimarySmtpMailbox()->getEmailAddress();
132
    }
133
134 1
    public function setPrimarySmtpEmailAddress($emailAddress)
135
    {
136 1
        $this->getClient()->setPrimarySmtpEmailAddress($emailAddress);
137
138 1
        return $this;
139
    }
140
141
    /**
142
     * Create items through the API client
143
     *
144
     * @param $items
145
     * @param array $options
146
     * @return Type
147
     */
148 23
    public function createItems($items, $options = array())
149
    {
150 23
        $items = Utilities\ensureIsArray($items);
151 23
        $request = array(
152 23
            'Items' => $items
153 23
        );
154
155 23
        $request = array_replace_recursive($request, $options);
156 23
        $request = Type::buildFromArray($request);
157
158 23
        $response = $this->getClient()->CreateItem($request);
159
160 23
        return $response;
161
    }
162
163 4
    public function updateItems($items, $options = array())
164
    {
165 4
        $request = array(
166 4
            'ItemChanges' => $items,
167 4
            'MessageDisposition' => 'SaveOnly',
168 4
            'ConflictResolution' => 'AlwaysOverwrite'
169 4
        );
170
171 4
        $request = array_replace_recursive($request, $options);
172
173 4
        $request = Type::buildFromArray($request);
174
175 4
        $response = $this->getClient()->UpdateItem($request);
176 4
        if ($response instanceof UpdateItemResponseMessageType) {
177 4
            return $response->getItems();
178
        }
179
180
        return Utilities\ensureIsArray($response);
181
    }
182
183 1
    public function createCalendars($names, BaseFolderIdType $parentFolder = null, $options = array())
184
    {
185 1
        if ($parentFolder === null) {
186 1
            $parentFolder = $this->getDistinguishedFolderId('calendar');
187
        }
188
189 1
        return $this->createFolders($names, $parentFolder, $options, 'IPF.Appointment');
190
    }
191
192
    public function createContactsFolder($names, BaseFolderIdType $parentFolder = null, $options = array())
193
    {
194
        if ($parentFolder === null) {
195
            $parentFolder = $this->getDistinguishedFolderId('contacts');
196
        }
197
198
        return $this->createFolders($names, $parentFolder, $options, 'IPF.Contact');
199
    }
200
201 4
    public function createFolders($names, BaseFolderIdType $parentFolder, $options = array(), $folderClass = null)
202
    {
203 4
        $names = Utilities\ensureIsArray($names);
204 4
        $names = array_map(function ($name) use ($folderClass) {
205 4
            return ['DisplayName' => $name, 'FolderClass' => $folderClass];
206 4
        }, $names);
207
208 4
        $request = [
209 4
            'Folders' => ['Folder' => $names]
210 4
        ];
211
212 4
        if ($parentFolder !== null) {
213 4
            $request['ParentFolderId'] = $parentFolder->toArray(true);
214
        }
215
216 4
        $request = array_merge_recursive($request, $options);
217
218 4
        $this->client->CreateFolder($request);
219 4
        return true;
220
    }
221
222
    /**
223
     * @deprecated Please use API::deleteFolders() instead
224
     *
225
     * @param BaseFolderIdType $folderId
226
     * @param array $options
227
     * @return Type
228
     */
229 3
    public function deleteFolder(BaseFolderIdType $folderId, $options = array())
230
    {
231 3
        return $this->deleteFolders($folderId, $options);
232
    }
233
234 4
    public function deleteFolders($folders, $options = array())
235
    {
236 4
        $folderIds = Utilities\getFolderIds($folders);
237
238 4
        $request = [
239 4
            'DeleteType' => 'HardDelete',
240 4
            'FolderIds' => $folderIds
241 4
        ];
242
243 4
        $request = array_merge_recursive($request, $options);
244 4
        return $this->client->DeleteFolder($request);
245
    }
246
247
    public function moveItem(Type\ItemIdType $itemId, BaseFolderIdType $folderId, $options = array())
248
    {
249
        $request = array(
250
            'ToFolderId' => $folderId->toArray(true),
251
            'ItemIds' => array('ItemId' => $itemId->toArray())
252
        );
253
254
        $request = array_merge_recursive($request, $options);
255
256
        return $this->client->MoveItem($request);
257
    }
258
259
    /**
260
     * @param $items Type\ItemIdType|Type\ItemIdType[]
261
     * @param array $options
262
     * @return bool
263
     */
264 21
    public function deleteItems($items, $options = array())
265
    {
266 21
        $items = Utilities\ensureIsArray($items, true);
267
268 21
        $items = array_map(function ($item) {
269 21
            $item = Type\ItemIdType::buildFromArray($item);
270
271 21
            return $item->toArray();
0 ignored issues
show
Bug introduced by
The method toArray() does not exist on garethp\ews\API\XmlObject. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

271
            return $item->/** @scrutinizer ignore-call */ toArray();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
272 21
        }, $items);
273
274 21
        $request = array(
275 21
            'ItemIds' => array('ItemId' => $items),
276 21
            'DeleteType' => 'MoveToDeletedItems'
277 21
        );
278
279 21
        $request = array_replace_recursive($request, $options);
280 21
        $request = Type::buildFromArray($request);
281 21
        $this->getClient()->DeleteItem($request);
282
283
        //If the delete fails, an Exception will be thrown in processResponse before it gets here
284 21
        return true;
285
    }
286
287
    /**
288
     * @param $identifier
289
     * @param array $options
290
     * @return Type\BaseFolderType
291
     */
292 16
    public function getFolder($identifier, $options = [])
293
    {
294 16
        $request = array(
295 16
            'FolderShape' => array(
296 16
                'BaseShape' => array('_' => 'Default')
297 16
            ),
298 16
            'FolderIds' => $identifier
299 16
        );
300
301 16
        $request = array_replace_recursive($request, $options);
302
303 16
        $request = Type::buildFromArray($request);
304
305 16
        $response = $this->getClient()->GetFolder($request);
306
307 16
        return $response;
308
    }
309
310
    /**
311
     * Get a folder by it's distinguishedId
312
     *
313
     * @param string $distinguishedId
314
     * @param array $options
315
     * @return Type\BaseFolderType
316
     */
317 12
    public function getFolderByDistinguishedId($distinguishedId, $options = [])
318
    {
319 12
        return $this->getFolder(array(
320 12
            'DistinguishedFolderId' => array(
321 12
                'Id' => $distinguishedId,
322 12
                'Mailbox' => $this->getPrimarySmtpMailbox()
323 12
            )
324 12
        ), $options);
325
    }
326
327
    /**
328
     * @param string|BaseFolderIdType $folderId
329
     * @param array $options
330
     * @return Type\BaseFolderType
331
     * @throws API\Exception
332
     */
333 4
    public function getFolderByFolderId($folderId, $options = [])
334
    {
335 4
        if (is_string($folderId)) {
336
            $folderId = ['FolderId' => ['Id' => $folderId, 'Mailbox' => $this->getPrimarySmtpMailbox()]];
337
        } else {
338 4
            $folderId = $folderId->toArray(true);
339
        }
340
341 4
        return $this->getFolder($folderId, $options);
342
    }
343
344
    /**
345
     * @param string|BaseFolderIdType $parentFolderId
346
     * @param array $options
347
     * @return Type\BaseFolderType[]
348
     */
349 32
    public function getChildrenFolders($parentFolderId = 'root', array $options = array())
350
    {
351 32
        if (is_string($parentFolderId)) {
352 21
            $parentFolderId = $this->getDistinguishedFolderId($parentFolderId);
353
        }
354
355 32
        $request = array(
356 32
            'Traversal' => 'Shallow',
357 32
            'FolderShape' => array(
358 32
                'BaseShape' => 'AllProperties'
359 32
            ),
360 32
            'ParentFolderIds' => $parentFolderId->toArray(true)
361 32
        );
362
363 32
        $request = array_replace_recursive($request, $options);
364
365 32
        $request = Type::buildFromArray($request);
366
367
        /** @var \garethp\ews\API\Message\FindFolderResponseMessageType $folders */
368 32
        return $this->getClient()->FindFolder($request);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getClient()->FindFolder($request) returns the type garethp\ews\API\Type which is incompatible with the documented return type garethp\ews\API\Type\BaseFolderType[].
Loading history...
369
    }
370
371
    /**
372
     * @param string $folderName
373
     * @param string|BaseFolderIdType $parentFolderId
374
     * @param array $options
375
     * @return bool|Type\BaseFolderType
376
     */
377 32
    public function getFolderByDisplayName($folderName, $parentFolderId = 'root', $options = array())
378
    {
379 32
        $folders = $this->getChildrenFolders($parentFolderId, $options);
380
381 32
        foreach ($folders as $folder) {
382 32
            if ($folder->getDisplayName() === $folderName) {
383 31
                return $folder;
384
            }
385
        }
386
387 4
        return false;
388
    }
389
390
    /**
391
     * @param $itemId array|Type\ItemIdType
392
     * @param array $options
393
     * @return Type
394
     */
395 9
    public function getItem($itemId, $options = array())
396
    {
397 9
        if ($itemId instanceof Type\ItemIdType) {
398 7
            $itemId = $itemId->toArray();
399
        }
400
401 9
        $request = array(
402 9
            'ItemShape' => array('BaseShape' => 'AllProperties'),
403 9
            'ItemIds' => array('ItemId' => $itemId)
404 9
        );
405
406 9
        $request = array_replace_recursive($request, $options);
407
408 9
        return $this->getClient()->GetItem($request);
409
    }
410
411
    /**
412
     * Get a list of sync changes on a folder
413
     *
414
     * @param BaseFolderIdType $folderId
415
     * @param null $syncState
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $syncState is correct as it would always require null to be passed?
Loading history...
416
     * @param array $options
417
     * @return SyncFolderItemsResponseMessageType
418
     */
419 2
    public function listItemChanges($folderId, $syncState = null, array $options = array())
420
    {
421 2
        $request = array(
422 2
            'ItemShape' => array('BaseShape' => 'AllProperties'),
423 2
            'SyncFolderId' => $folderId->toArray(true),
424 2
            'SyncScope' => 'NormalItems',
425 2
            'MaxChangesReturned' => '100'
426 2
        );
427
428 2
        if ($syncState != null) {
429 1
            $request['SyncState'] = $syncState;
430 1
            $request['ItemShape']['BaseShape'] = 'AllProperties';
431
        }
432
433 2
        $request = array_replace_recursive($request, $options);
434
435 2
        $request = Type::buildFromArray($request);
436 2
        $response = $this->getClient()->SyncFolderItems($request);
437
438 2
        return $response;
439
    }
440
441 1
    public function getServerTimezones($timezoneIDs = array(), $fullTimezoneData = false)
442
    {
443 1
        $request = GetServerTimeZonesType::buildFromArray(array(
444 1
            'returnFullTimeZoneData' => $fullTimezoneData
445 1
        ));
446
447 1
        if (!empty($timezoneIDs)) {
448
            $request->setIds($timezoneIDs);
0 ignored issues
show
Bug introduced by
The method setIds() does not exist on garethp\ews\API\XmlObject. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

448
            $request->/** @scrutinizer ignore-call */ 
449
                      setIds($timezoneIDs);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
449
        }
450
451 1
        $timezones = $this->getClient()->GetServerTimeZones($request);
452 1
        return Utilities\ensureIsArray($timezones);
453
    }
454
455
    /**
456
     * @param Type\ItemIdType $itemId
457
     * @param $fromType
458
     * @param $destinationType
459
     * @param $mailbox
460
     *
461
     * @return Type\ItemIdType
462
     */
463
    public function convertIdFormat(Type\ItemIdType $itemId, $fromType, $destinationType, $mailbox)
464
    {
465
        $result = $this->getClient()->ConvertId(array(
466
            'DestinationFormat' => $destinationType,
467
            'SourceIds' => array(
468
                'AlternateId' => array(
469
                    'Format' => $fromType,
470
                    'Id' => $itemId->getId(),
471
                    'Mailbox' => $mailbox
472
                )
473
            )
474
        ));
475
476
        $itemId->setId($result->getId());
0 ignored issues
show
Bug introduced by
The method getId() does not exist on garethp\ews\API\Type. It seems like you code against a sub-type of garethp\ews\API\Type such as garethp\ews\API\Type\UserMailboxType or garethp\ews\API\Type\PhoneCallIdType or garethp\ews\API\Type\PeriodType or garethp\ews\API\Type\ArrayOfTransitionsType or garethp\ews\API\Type\DirectoryEntryType or garethp\ews\API\Type\TimeZoneDefinitionType or garethp\ews\API\Type\CalendarEventDetailsType or garethp\ews\API\Type\AlternateIdType or garethp\ews\API\Type\ItemIdType or garethp\ews\API\Type\RequestAttachmentIdType or garethp\ews\API\Type\FolderIdType or garethp\ews\API\Type\DistinguishedFolderIdType. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

476
        $itemId->setId($result->/** @scrutinizer ignore-call */ getId());
Loading history...
477
478
        return $itemId;
479
    }
480
481
    /**
482
     * @param Type\FindItemParentType|Type\FindFolderParentType $result
483
     *
484
     * @return Type\FindItemParentType|Type\FindFolderParentType
485
     */
486 2
    public function getNextPage($result)
487
    {
488 2
        if ($result->isIncludesLastItemInRange()) {
489
            return $result;
490
        }
491
492 2
        $currentPage = $result->getCurrentPage();
493 2
        $currentPage->setOffset($result->getIndexedPagingOffset());
494
495 2
        $lastRequest = $result->getLastRequest();
496 2
        $lastRequest->setIndexedPage($currentPage);
497
498 2
        if ($result instanceof Type\FindFolderParentType) {
499 1
            return $this->getClient()->FindFolder($lastRequest);
500
        }
501
502 1
        return $this->getClient()->FindItem($lastRequest);
503
    }
504
505
    /**
506
     * @param BaseFolderIdType $folderId
507
     * @param string $deleteType
508
     * @param bool $deleteSubFolders
509
     * @param array $options
510
     * @return EmptyFolderResponseType
511
     */
512
    public function emptyFolder(
513
        BaseFolderIdType $folderId,
514
        $deleteType = 'SoftDelete',
515
        $deleteSubFolders = false,
516
        array $options = []
517
    ) {
518
        $request = [
519
            'DeleteType' => $deleteType,
520
            'DeleteSubFolders' => $deleteSubFolders,
521
            'FolderIds' => $folderId->toArray(true)
522
        ];
523
524
        $request = array_merge_recursive($request, $options);
525
526
        return $this->getClient()->EmptyFolder($request);
527
    }
528
529 22
    protected function getDistinguishedFolderId($id = null, $changeKey = null)
530
    {
531 22
        return new Type\DistinguishedFolderIdType(
532 22
            $id,
533 22
            $changeKey,
534 22
            $this->getPrimarySmtpMailbox()
535 22
        );
536
    }
537
}
538