Completed
Pull Request — master (#83)
by
unknown
07:15
created

API   B

Complexity

Total Complexity 53

Size/Duplication

Total Lines 557
Duplicated Lines 16.52 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 75.83%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 53
c 1
b 0
f 0
lcom 1
cbo 4
dl 92
loc 557
ccs 182
cts 240
cp 0.7583
rs 7.4757

30 Methods

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

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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
12
/**
13
 * A base class for APIs
14
 *
15
 * Class BaseAPI
16
 * @package garethp\ews
17
 */
18
class API
19
{
20
    protected static $defaultClientOptions = array(
21
        'version' => ExchangeWebServices::VERSION_2010
22
    );
23
24 34
    public function __construct(ExchangeWebServices $client = null)
25
    {
26 34
        if ($client) {
27 34
            $this->setClient($client);
28 34
        }
29 34
    }
30
31
    /**
32
     * @return Type\EmailAddressType
33
     */
34 26
    public function getPrimarySmtpMailbox()
35
    {
36 26
        return $this->getClient()->getPrimarySmtpMailbox();
37
    }
38
39
    /**
40
     * Storing the API client
41
     * @var ExchangeWebServices
42
     */
43
    private $client;
44
45
    /**
46
     * Get a calendar item
47
     *
48
     * @param string $name
49
     * @return CalendarAPI
50
     */
51 6
    public function getCalendar($name = null)
52
    {
53 6
        $calendar = new CalendarAPI();
54 6
        $calendar->setClient($this->getClient());
55 6
        $calendar->pickCalendar($name);
56
57 6
        return $calendar;
58
    }
59
60
    /**
61
     * @param string $folderName
62
     * @return MailAPI
63
     */
64 6
    public function getMailbox($folderName = null)
65
    {
66 6
        $mailApi = new MailAPI();
67 6
        $mailApi->setClient($this->getClient());
68 6
        $mailApi->pickMailFolder($folderName);
69
70 6
        return $mailApi;
71
    }
72
73
    /**
74
     * Set the API client
75
     *
76
     * @param ExchangeWebServices $client
77
     * @return $this
78
     */
79 34
    public function setClient($client)
80
    {
81 34
        $this->client = $client;
82
83 34
        return $this;
84
    }
85
86
    /**
87
     * Get the API client
88
     *
89
     * @return ExchangeWebServices
90
     */
91 33
    public function getClient()
92
    {
93 33
        return $this->client;
94
    }
95
96 33
    public static function withUsernameAndPassword($server, $username, $password, $options = [])
97
    {
98 33
        return new static(ExchangeWebServices::fromUsernameAndPassword(
99 33
            $server,
100 33
            $username,
101 33
            $password,
102 33
            array_replace_recursive(self::$defaultClientOptions, $options)
103 33
        ));
104
    }
105
106 1
    public static function withCallbackToken($server, $token, $options = [])
107
    {
108 1
        return new static(ExchangeWebServices::fromCallbackToken(
109 1
            $server,
110 1
            $token,
111 1
            array_replace_recursive(self::$defaultClientOptions, $options)
112 1
        ));
113
    }
114
115 1
    public function getPrimarySmptEmailAddress()
116
    {
117 1
        if ($this->getPrimarySmtpMailbox() == null) {
118 1
            return null;
119
        }
120
121 1
        return $this->getPrimarySmtpMailbox()->getEmailAddress();
122
    }
123
124 1
    public function setPrimarySmtpEmailAddress($emailAddress)
125
    {
126 1
        $this->getClient()->setPrimarySmtpEmailAddress($emailAddress);
127
128 1
        return $this;
129
    }
130
131
    /**
132
     * Create items through the API client
133
     *
134
     * @param $items
135
     * @param array $options
136
     * @return Type
137
     */
138 16
    public function createItems($items, $options = array())
139
    {
140 16
        if (!is_array($items)) {
141
            $items = array($items);
142
        }
143
144
        $request = array(
145
            'Items' => $items
146 16
        );
147
148 16
        $request = array_replace_recursive($request, $options);
149 16
        $request = Type::buildFromArray($request);
150
151 16
        $response = $this->getClient()->CreateItem($request);
152
153 16
        return $response;
154
    }
155
156 4
    public function updateItems($items, $options = array())
157
    {
158
        $request = array(
159 4
            'ItemChanges' => $items,
160 4
            'MessageDisposition' => 'SaveOnly',
161
            'ConflictResolution' => 'AlwaysOverwrite'
162 4
        );
163
164 4
        $request = array_replace_recursive($request, $options);
165
166 4
        $request = Type::buildFromArray($request);
167
168 4
        $response = $this->getClient()->UpdateItem($request);
169 4
        if ($response instanceof UpdateItemResponseMessageType) {
0 ignored issues
show
Bug introduced by
The class garethp\ews\API\Message\...ItemResponseMessageType does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
170 4
            return $response->getItems();
171
        }
172
173
        if (!is_array($response)) {
174
            $response = array($response);
175
        }
176
177
        return $response;
178
    }
179
180 1 View Code Duplication
    public function createCalendars($names, Type\FolderIdType $parentFolder = null, $options = array())
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
181
    {
182 1
        if ($parentFolder == null) {
183 1
            $parentFolder = $this->getFolderByDistinguishedId('calendar')->getFolderId();
0 ignored issues
show
Documentation Bug introduced by
The method getFolderId does not exist on object<garethp\ews\API\Type>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
184 1
        }
185
186 1
        if (!is_array($names)) {
187 1
            $names = array($names);
188 1
        }
189
190
        $names = array_map(function ($name) {
191
            return array(
192 1
                'DisplayName' => $name,
193
                'FolderClass' => 'IPF.Appointment'
194 1
            );
195 1
        }, $names);
196
197
        $request = [
198 1
            'Folders' => ['Folder' => $names],
199 1
            'ParentFolderId' => ['FolderId' => $parentFolder->toArray()]
200 1
        ];
201
202 1
        $request = array_merge_recursive($request, $options);
203
204 1
        $this->client->CreateFolder($request);
205 1
        return true;
206
    }
207
    
208 View Code Duplication
    public function createContactsFolder($names, Type\FolderIdType $parentFolder = null, $options = array())
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
209
    {
210
        if ($parentFolder == null) {
211
            $parentFolder = $this->getFolderByDistinguishedId('contacts')->getFolderId();
0 ignored issues
show
Documentation Bug introduced by
The method getFolderId does not exist on object<garethp\ews\API\Type>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
212
        }
213
214
        if (!is_array($names)) {
215
            $names = array($names);
216
        }
217
218
        $names = array_map(function ($name) {
219
            return array(
220
                'DisplayName' => $name,
221
                'FolderClass' => 'IPF.Contact'
222
            );
223
        }, $names);
224
225
        $request = [
226
            'Folders' => ['Folder' => $names],
227
            'ParentFolderId' => ['FolderId' => $parentFolder->toArray()]
228
        ];
229
230
        $request = array_merge_recursive($request, $options);
231
232
        $this->client->CreateFolder($request);
233
        return true;
234
    }
235
236 3
    public function createFolders($names, Type\FolderIdType $parentFolder, $options = array())
237
    {
238 3
        if (!is_array($names)) {
239 2
            $names = array($names);
240 2
        }
241
242
        $names = array_map(function ($name) {
243 3
            return ['DisplayName' => $name];
244 3
        }, $names);
245
246
        $request = [
247 3
            'Folders' => ['Folder' => $names]
248 3
        ];
249
250 3
        if (!empty($parentFolder)) {
251 3
            $request['ParentFolderId'] = array('FolderId' => $parentFolder->toArray());
252 3
        }
253
254 3
        $request = array_merge_recursive($request, $options);
255
256 3
        $this->client->CreateFolder($request);
257
258 3
        return true;
259
    }
260
261
    /**
262
     * @deprecated Please use API::deleteFolders() instead
263
     *
264
     * @param Type\FolderIdType $folderId
265
     * @param array $options
266
     * @return Type
267
     */
268 3
    public function deleteFolder(Type\FolderIdType $folderId, $options = array())
269
    {
270 3
        return $this->deleteFolders($folderId, $options);
271
    }
272
273 4
    public function deleteFolders($folders, $options = array())
274
    {
275 4
        if (!is_array($folders)) {
276 3
            $folders = array($folders);
277 3
        }
278
279
        $folderIds = array_map(function ($folderId) {
280 4
            return $folderId->toArray();
281 4
        }, $folders);
282
283
        $request = [
284 4
            'DeleteType' => 'HardDelete',
285
            'FolderIds' => array(
286
                'FolderId' => $folderIds
287 4
            )
288 4
        ];
289
290 4
        $request = array_merge_recursive($request, $options);
291 4
        return $this->client->DeleteFolder($request);
292
    }
293
294
    public function moveItem(Type\ItemIdType $itemId, Type\FolderIdType $folderId, $options = array())
295
    {
296
        $request = array(
297
            'ToFolderId' => array('FolderId' => $folderId->toArray()),
298
            'ItemIds' => array('ItemId' => $itemId->toArray())
299
        );
300
301
        $request = array_merge_recursive($request, $options);
302
303
        return $this->client->MoveItem($request);
304
    }
305
306
    /**
307
     * @param $items Type\ItemIdType|Type\ItemIdType[]
308
     * @param array $options
309
     * @return bool
310
     */
311 16
    public function deleteItems($items, $options = array())
312
    {
313 16
        if (!is_array($items) || Type::arrayIsAssoc($items)) {
314 15
            $items = array($items);
315 15
        }
316
317 16
        $items = array_map(function ($item) {
318 16
            $item = Type\ItemIdType::buildFromArray($item);
319
320 16
            return $item->toArray();
321 16
        }, $items);
322
323
        $request = array(
324 16
            'ItemIds' => array('ItemId' => $items),
325
            'DeleteType' => 'MoveToDeletedItems'
326 16
        );
327
328 16
        $request = array_replace_recursive($request, $options);
329 16
        $request = Type::buildFromArray($request);
330 16
        $this->getClient()->DeleteItem($request);
331
332
        //If the delete fails, an Exception will be thrown in processResponse before it gets here
333 16
        return true;
334
    }
335
336
    /**
337
     * @param $identifier
338
     * @return Type\BaseFolderType
339
     */
340 25
    public function getFolder($identifier)
341
    {
342
        $request = array(
343
            'FolderShape' => array(
344 25
                'BaseShape' => array('_' => 'Default')
345 25
            ),
346
            'FolderIds' => $identifier
347 25
        );
348 25
        $request = Type::buildFromArray($request);
349
350 25
        $response = $this->getClient()->GetFolder($request);
351
352 25
        return $response;
353
    }
354
355
    /**
356
     * Get a folder by it's distinguishedId
357
     *
358
     * @param string $distinguishedId
359
     * @return Type\BaseFolderType
360
     */
361 25
    public function getFolderByDistinguishedId($distinguishedId)
362
    {
363 25
        return $this->getFolder(array(
364
            'DistinguishedFolderId' => array(
365 25
                'Id' => $distinguishedId,
366 25
                'Mailbox' => $this->getPrimarySmtpMailbox()
367 25
            )
368 25
        ));
369
    }
370
371
    /**
372
     * @param $folderId
373
     * @return Type\BaseFolderType
374
     */
375 4
    public function getFolderByFolderId($folderId)
376
    {
377 4
        return $this->getFolder(array(
378 4
            'FolderId' => array('Id' => $folderId, 'Mailbox' => $this->getPrimarySmtpMailbox())
379 4
        ));
380
    }
381
382
    /**
383
     * @param string|Type\FolderIdType $parentFolderId
384
     * @param array $options
385
     * @return Type\BaseFolderType[]
386
     */
387 24 View Code Duplication
    public function getChildrenFolders($parentFolderId = 'root', $options = array())
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
388
    {
389 24
        if (is_string($parentFolderId)) {
390 16
            $parentFolderId = $this->getFolderByDistinguishedId($parentFolderId)->getFolderId();
0 ignored issues
show
Documentation Bug introduced by
The method getFolderId does not exist on object<garethp\ews\API\Type>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
391 16
        }
392
393
        $request = array(
394 24
            'Traversal' => 'Shallow',
395
            'FolderShape' => array(
396
                'BaseShape' => 'AllProperties'
397 24
            ),
398
            'ParentFolderIds' => array(
399 24
                'FolderId' => $parentFolderId->toArray()
400 24
            )
401 24
        );
402
403 24
        $request = array_replace_recursive($request, $options);
404
405 24
        $request = Type::buildFromArray($request);
406
407
        /** @var \garethp\ews\API\Message\FindFolderResponseMessageType $folders */
408 24
        return $this->getClient()->FindFolder($request);
409
    }
410
411
    /**
412
     * @param string $folderName
413
     * @param string|Type\FolderIdType $parentFolderId
414
     * @param array $options
415
     * @return bool|Type\BaseFolderType
416
     */
417 24
    public function getFolderByDisplayName($folderName, $parentFolderId = 'root', $options = array())
418
    {
419 24
        $folders = $this->getChildrenFolders($parentFolderId, $options);
420
421 24
        foreach ($folders as $folder) {
0 ignored issues
show
Bug introduced by
The expression $folders of type object<garethp\ews\API\Type> is not traversable.
Loading history...
422 24
            if ($folder->getDisplayName() == $folderName) {
423 23
                return $folder;
424
            }
425 17
        }
426
427 4
        return false;
428
    }
429
430
    /**
431
     * @param $itemId array|Type\ItemIdType
432
     * @param array $options
433
     * @return Type
434
     */
435 5 View Code Duplication
    public function getItem($itemId, $options = array())
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
436
    {
437 5
        if ($itemId instanceof Type\ItemIdType) {
0 ignored issues
show
Bug introduced by
The class garethp\ews\API\Type\ItemIdType does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
438 4
            $itemId = $itemId->toArray();
439 4
        }
440
441
        $request = array(
442 5
            'ItemShape' => array('BaseShape' => 'AllProperties'),
443 5
            'ItemIds' => array('ItemId' => $itemId)
444 5
        );
445
446 5
        $request = array_replace_recursive($request, $options);
447
448 5
        return $this->getClient()->GetItem($request);
449
    }
450
451
    /**
452
     * Get a list of sync changes on a folder
453
     *
454
     * @param Type\FolderIdType $folderId
455
     * @param null $syncState
456
     * @param array $options
457
     * @return SyncFolderItemsResponseMessageType
458
     */
459 2
    public function listItemChanges($folderId, $syncState = null, $options = array())
460
    {
461
        $request = array(
462 2
            'ItemShape' => array('BaseShape' => 'AllProperties'),
463 2
            'SyncFolderId' => array('FolderId' => $folderId->toXmlObject()),
464 2
            'SyncScope' => 'NormalItems',
465
            'MaxChangesReturned' => '100'
466 2
        );
467
468 2
        if ($syncState != null) {
469 1
            $request['SyncState'] = $syncState;
470 1
            $request['ItemShape']['BaseShape'] = 'AllProperties';
471 1
        }
472
473 2
        $request = array_replace_recursive($request, $options);
474
475 2
        $request = Type::buildFromArray($request);
476 2
        $response = $this->getClient()->SyncFolderItems($request);
477
478 2
        return $response;
479
    }
480
481
    public function getServerTimezones($timezoneIDs = array(), $fullTimezoneData = false)
482
    {
483
        $request = GetServerTimeZonesType::buildFromArray(array(
484
            'returnFullTimeZoneData' => $fullTimezoneData
485
        ));
486
487
        if (!empty($timezoneIDs)) {
488
            $request->setIds($timezoneIDs);
489
        }
490
491
        $timezones = $this->getClient()->GetServerTimeZones($request);
492
        $timezones = $timezones->TimeZoneDefinition;
0 ignored issues
show
Documentation introduced by
The property TimeZoneDefinition does not exist on object<garethp\ews\API\Type>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
493
494
        if (!is_array($timezones)) {
495
            $timezones = array($timezones);
496
        }
497
498
        return $timezones;
499
    }
500
501
    /**
502
     * @param Type\ItemIdType $itemId
503
     * @param $fromType
504
     * @param $destinationType
505
     * @param $mailbox
506
     *
507
     * @return Type\ItemIdType
508
     */
509
    public function convertIdFormat(Type\ItemIdType $itemId, $fromType, $destinationType, $mailbox)
510
    {
511
        $result = $this->getClient()->ConvertId(array(
512
            'DestinationFormat' => $destinationType,
513
            'SourceIds' => array(
514
                'AlternateId' => array(
515
                    'Format' => $fromType,
516
                    'Id' => $itemId->getId(),
517
                    'Mailbox' => $mailbox
518
                )
519
            )
520
        ));
521
522
        $itemId->setId($result->getId());
0 ignored issues
show
Documentation Bug introduced by
The method getId does not exist on object<garethp\ews\API\Type>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
523
524
        return $itemId;
525
    }
526
527
    /**
528
     * @param Type\FindItemParentType|Type\FindFolderParentType $result
529
     *
530
     * @return Type\FindItemParentType|Type\FindFolderParentType
531
     */
532 2
    public function getNextPage($result)
533
    {
534 2
        if ($result->isIncludesLastItemInRange()) {
535
            return $result;
536
        }
537
538 2
        $currentPage = $result->getCurrentPage();
539 2
        $currentPage->setOffset($result->getIndexedPagingOffset());
540
541 2
        $lastRequest = $result->getLastRequest();
542 2
        $lastRequest->setIndexedPage($currentPage);
543
544 2
        if ($result instanceof Type\FindFolderParentType) {
0 ignored issues
show
Bug introduced by
The class garethp\ews\API\Type\FindFolderParentType does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
545 1
            return $this->getClient()->FindFolder($lastRequest);
546
        }
547
548 1
        return $this->getClient()->FindItem($lastRequest);
549
    }
550
551
    /**
552
     * @param Type\FolderIdType $folderId
553
     * @param string $deleteType
554
     * @param bool $deleteSubFolders
555
     * @param array $options
556
     * @return EmptyFolderResponseType
557
     */
558
    public function emptyFolder(
559
        Type\FolderIdType $folderId,
560
        $deleteType = 'SoftDelete',
561
        $deleteSubFolders = false,
562
        array $options = []
563
    ) {
564
        $request = [
565
            'DeleteType' => $deleteType,
566
            'DeleteSubFolders' => $deleteSubFolders,
567
            'FolderIds' => ['FolderId' => $folderId->toArray()]
568
        ];
569
570
        $request = array_merge_recursive($request, $options);
571
572
        return $this->getClient()->EmptyFolder($request);
573
    }
574
}
575