Completed
Push — master ( c7e42b...9e6269 )
by Gareth
03:51
created

ExchangeWebServices::getItemsFromResponse()   B

Complexity

Conditions 5
Paths 12

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 22
ccs 12
cts 12
cp 1
rs 8.6737
cc 5
eloc 12
nc 12
nop 1
crap 5
1
<?php
2
/**
3
 * Contains ExchangeWebServices.
4
 */
5
6
7
namespace garethp\ews\API;
8
9
use garethp\ews\API\Exception\ExchangeException;
10
use garethp\ews\API\Exception\NoResponseReturnedException;
11
use garethp\ews\API\Exception\ServiceUnavailableException;
12
use garethp\ews\API\Exception\UnauthorizedException;
13
use garethp\ews\API\Message;
14
use garethp\ews\API\Type\EmailAddressType;
15
16
/**
17
 * Base class of the Exchange Web Services application.
18
 *
19
 *
20
 *
21
 * @package php-ews\Client
22
 *
23
 * @method Type AddDelegate($request)
24
 * @method Type ApplyConversationAction($request)
25
 * @method Type ConvertId($request)
26
 * @method Type CopyFolder($request)
27
 * @method Type CopyItem($request)
28
 * @method Type CreateAttachment($request)
29
 * @method Type CreateFolder($request)
30
 * @method Type CreateItem($request)
31
 * @method Type CreateManagedFolder($request)
32
 * @method Type CreateUserConfiguration($request)
33
 * @method Type DeleteAttachment($request)
34
 * @method Type DeleteFolder($request)
35
 * @method Type DeleteItem($request)
36
 * @method Type DeleteUserConfiguration($request)
37
 * @method Type DisconnectPhoneCall($request)
38
 * @method Type EmptyFolder($request)
39
 * @method Type ExpandDL($request)
40
 * @method Type ExportItems($request)
41
 * @method Type FindConversation($request)
42
 * @method Type FindFolder($request)
43
 * @method Type FindItem($request)
44
 * @method Type FindMessageTrackingReport($request)
45
 * @method Type GetAttachment($request)
46
 * @method Type GetDelegate($request)
47
 * @method Type GetEvents($request)
48
 * @method Type GetFolder($request)
49
 * @method Type GetInboxRules($request)
50
 * @method Type GetItem($request)
51
 * @method Type GetMailTips($request)
52
 * @method Type GetMessageTrackingReport($request)
53
 * @method Type GetPasswordExpirationDate($request)
54
 * @method Type GetPhoneCallInformation($request)
55
 * @method Type GetRoomLists($request)
56
 * @method Type GetRooms($request)
57
 * @method Type GetServerTimeZones($request)
58
 * @method Type GetServiceConfiguration($request)
59
 * @method Type GetSharingFolder($request)
60
 * @method Type GetSharingMetadata($request)
61
 * @method Type GetStreamingEvents($request)
62
 * @method Type GetUserAvailability($request)
63
 * @method Type GetUserConfiguration($request)
64
 * @method Type GetUserOofSettings($request)
65
 * @method Type MoveFolder($request)
66
 * @method Type MoveItem($request)
67
 * @method Type PlayOnPhone($request)
68
 * @method Type RefreshSharingFolder($request)
69
 * @method Type RemoveDelegate($request)
70
 * @method Type ResolveNames($request)
71
 * @method Type SendItem($request)
72
 * @method Type SetUserOofSettings($request)
73
 * @method Type Subscribe($request)
74
 * @method Type SyncFolderHierarchy($request)
75
 * @method Type SyncFolderItems($request)
76
 * @method Type Unsubscribe($request)
77
 * @method Type UpdateDelegate($request)
78
 * @method Type UpdateFolder($request)
79
 * @method Type UpdateInboxRules($request)
80
 * @method Type UpdateItem($request)
81
 * @method Type UpdateUserConfiguration($request)
82
 * @method Type UploadItems($request)
83
 */
84
class ExchangeWebServices
85
{
86
87
    const VERSION_2007 = 'Exchange2007';
88
89
    const VERSION_2007_SP1 = 'Exchange2007_SP1';
90
91
    const VERSION_2007_SP2 = 'Exchange2007_SP2';
92
93
    const VERSION_2007_SP3 = 'Exchange2007_SP3';
94
95
    const VERSION_2010 = 'Exchange2010';
96
97
    const VERSION_2010_SP1 = 'Exchange2010_SP1';
98
99
    const VERSION_2010_SP2 = 'Exchange2010_SP2';
100
101
    const VERSION_2010_SP3 = 'Exchange2010_SP3';
102
103
    const VERSION_2013 = 'Exchange2013';
104
105
    const VERSION_2013_SP1 = 'Exchange2013_SP1';
106
107
    /**
108
     * Password to use when connecting to the Exchange server.
109
     *
110
     * @var string
111
     */
112
    protected $password = null;
113
114
    /**
115
     * Location of the Exchange server.
116
     *
117
     * @var string
118
     */
119
    protected $server = null;
120
121
    /**
122
     * SOAP client used to make the request
123
     *
124
     * @var NTLMSoapClient
125
     */
126
    protected $soap = null;
127
128
    /**
129
     * Username to use when connecting to the Exchange server.
130
     *
131
     * @var string
132
     */
133
    protected $username = null;
134
135
    /**
136
     * @var EmailAddressType
137
     */
138
    protected $primarySmtpMailbox = null;
139
140
    /**
141
     * A setting to check whether or not responses should be drilled down before being
142
     * returned. Setting this to false
143
     * will return the raw responses without any filtering
144
     *
145
     * @var bool
146
     */
147
    protected $drillDownResponses = true;
148
149
    /**
150
     * Miscrosoft Exchange version that we are going to connect to
151
     *
152
     * @var string
153
     */
154
    protected $version = null;
155
156
    protected $options = null;
157
158
    /**
159
     * The timezone for the client
160
     *
161
     * @var bool
162
     */
163
    protected $timezone = false;
164
165
    /**
166
     * @return EmailAddressType
167
     */
168 24
    public function getPrimarySmtpMailbox()
169
    {
170 24
        return $this->primarySmtpMailbox;
171
    }
172
173 1
    public function getPrimarySmtpEmailAddress()
174
    {
175 1
        if ($this->primarySmtpMailbox == null) {
176 1
            return null;
177
        }
178
179 1
        return $this->primarySmtpMailbox->getEmailAddress();
180
    }
181
182 2
    public function setPrimarySmtpEmailAddress($emailAddress)
183
    {
184 2
        $mailbox = new EmailAddressType();
185 2
        $mailbox->setEmailAddress($emailAddress);
186 2
        $this->primarySmtpMailbox = $mailbox;
187
188 2
        return $this;
189
    }
190
191
    /**
192
     * @param boolean $timezone
193
     */
194
    public function setTimezone($timezone)
195
    {
196
        $this->timezone = $timezone;
197
    }
198
199
    /**
200
     * @return string
201
     */
202 2
    public function getVersion()
203
    {
204 2
        return $this->version;
205
    }
206
207
    /**
208
     * @return string
209
     */
210
    public function getServer()
211
    {
212
        return $this->server;
213
    }
214
215
    /**
216
     * Constructor for the ExchangeWebServices class
217
     *
218
     * @deprecated Since 0.6.3
219
     * @param string $server
220
     * @param string $username
221
     * @param string $password
222
     * @param array $options
223
     */
224 33
    public function __construct($server = null, $username = null, $password = null, $options = array())
225
    {
226 33
        if ($server !== null) {
227 1
            $this->createClient(
228
                $server,
229 1
                ExchangeWebServicesAuth::fromUsernameAndPassword($username, $password),
230
                $options
231
            );
232
        }
233
    }
234
235 31
    public static function fromUsernameAndPassword($server, $username, $password, $options)
236
    {
237 31
        $self = new self();
238 31
        $self->createClient($server, ExchangeWebServicesAuth::fromUsernameAndPassword($username, $password), $options);
239
240 31
        return $self;
241
    }
242
243 1
    public static function fromCallbackToken($server, $token, $options)
244
    {
245 1
        $self = new self();
246 1
        $self->createClient($server, ExchangeWebServicesAuth::fromCallbackToken($token), $options);
247
248 1
        return $self;
249
    }
250
251 33
    protected function createClient($server, $auth, $options)
252
    {
253 33
        $location = 'https://'.$this->cleanServerUrl($server).'/EWS/Exchange.asmx';
254
255 33
        $options = array_replace_recursive([
256 33
            'version' => self::VERSION_2007,
257 33
            'trace' => 1,
258
            'exceptions' => true,
259 33
            'classmap' => ClassMap::getClassMap(),
260
            'drillDownResponses' => true
261
        ], $options);
262
263 33
        $this->server = $server;
264 33
        $this->version = $options['version'];
265
266 33
        $this->soap = new NTLMSoapClient(
267
            $location,
268
            $auth,
269 33
            dirname(__FILE__).'/../../Resources/wsdl/services.wsdl',
270
            $options
271
        );
272
273 33
        if (isset($options['primarySmtpEmailAddress'])) {
274 1
            $this->setPrimarySmtpEmailAddress($options['primarySmtpEmailAddress']);
275
        }
276
277 33
        if (isset($options['impersonation'])) {
278 1
            $this->setPrimarySmtpEmailAddress($options['impersonation']);
279
        }
280
281 33
        $this->drillDownResponses = $options['drillDownResponses'];
282
    }
283
284
    /**
285
     * @codeCoverageIgnore
286
     *
287
     * @param $name
288
     * @param $arguments
289
     * @return Type
290
     * @throws \garethp\ews\API\Exception
291
     */
292
    public function __call($name, $arguments)
293
    {
294
        $response = $this->getClient()->__call($name, $arguments);
295
296
        return $this->processResponse($response);
297
    }
298
299
    /**
300
     * Returns the SOAP Client that may be used to make calls against the server
301
     *
302
     * @return NTLMSoapClient
303
     */
304 30
    public function getClient()
305
    {
306 30
        return $this->soap;
307
    }
308
309
    /**
310
     * Sets the client
311
     *
312
     * @param NTLMSoapClient $client
313
     * @return $this
314
     */
315 2
    public function setClient($client)
316
    {
317 2
        $this->soap = $client;
318
319 2
        return $this;
320
    }
321
322
    /**
323
     * Cleans the server URL for usage
324
     *
325
     * @param $server
326
     * @return string
327
     */
328 40
    public function cleanServerUrl($server)
329
    {
330 40
        $url = parse_url($server);
331 40
        if (!isset($url['host']) && isset($url['path'])) {
332 35
            $url['host'] = $url['path'];
333 35
            unset($url['path']);
334
        }
335
336 40
        $server = $url['host'];
337 40
        if (isset($url['port'])) {
338 2
            $server .= ':'.$url['port'];
339
        }
340
341 40
        if (isset($url['path'])) {
342 4
            $server .= $url['path'];
343
        }
344
345 40
        $server = rtrim($server, "/");
346
347 40
        return $server;
348
    }
349
350
    /**
351
     * Process a response to verify that it succeeded and take the appropriate
352
     * action
353
     *
354
     * @param \garethp\ews\API\Message\BaseResponseMessageType $response
355
     * @return Type[]
356
     * @throws \garethp\ews\API\Exception
357
     */
358 28
    protected function processResponse($response)
359
    {
360
        // If the soap call failed then we need to thow an exception.
361 28
        $code = $this->getClient()->getResponseCode();
362 28
        $this->handleNonSuccessfulResponses($response, $code);
363
364 26
        if (!$this->drillDownResponses) {
365
            return $response;
366
        }
367
368 26
        if (!$response->exists('responseMessages')) {
369
            return $response;
370
        }
371
372 26
        $response = $response->getResponseMessages();
373 26
        $response = $this->drillDownResponseLevels($response);
374
375 26
        return $response;
376
    }
377
378
    /**
379
     * @param $response
380
     * @return array
381
     * @throws \garethp\ews\API\Exception
382
     */
383 26
    public function drillDownResponseLevels($response)
384
    {
385 26
        $items = $this->getItemsFromResponse($response);
386
387 26
        if (count($items) == 1) {
388 26
            reset($items);
389 26
            $key = key($items);
390 26
            $methodName = "get$key";
391 26
            $response = $response->$methodName();
392
393 26
            return $this->drillDownResponseLevels($response);
394
        }
395
396 26
        if (is_array($items) && isset($items[1]) && $items[1] instanceof Message\ResponseMessageType) {
0 ignored issues
show
Bug introduced by
The class garethp\ews\API\Message\ResponseMessageType 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...
397 1
            $response = array();
398 1
            foreach ($items as $responseItem) {
399 1
                $response[] = $this->drillDownResponseLevels($responseItem);
400
            }
401
402 1
            return $response;
403
        }
404
405 26
        return $response;
406
    }
407
408
    /**
409
     * @param $response
410
     * @return array
411
     * @throws ExchangeException
412
     */
413 26
    protected function getItemsFromResponse($response)
414
    {
415 26
        $items = array();
416 26
        if ($response instanceof Type) {
417 26
            $items = $response->getNonNullItems();
418
        }
419
420 26
        if (is_array($response)) {
421 1
            $items = $response;
422
        }
423
424 26
        if ($response instanceof Message\ResponseMessageType) {
0 ignored issues
show
Bug introduced by
The class garethp\ews\API\Message\ResponseMessageType 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...
425 26
            if ($response->getResponseClass() !== "Success") {
426 1
                throw new ExchangeException($response->getMessageText());
427
            }
428
429 26
            unset($items['responseClass']);
430 26
            unset($items['responseCode']);
431
        }
432
433 26
        return $items;
434
    }
435
436
    /**
437
     * @param Message\BaseResponseMessageType $response
438
     * @param $code
439
     * @throws ExchangeException
440
     * @throws NoResponseReturnedException
441
     * @throws ServiceUnavailableException
442
     * @throws UnauthorizedException
443
     */
444 28
    protected function handleNonSuccessfulResponses($response, $code)
445
    {
446 28
        if ($code == 401) {
447
            throw new UnauthorizedException();
448
        }
449
450 28
        if ($code == 503) {
451
            throw new ServiceUnavailableException();
452
        }
453
454 28
        if ($code >= 300) {
455 2
            throw new ExchangeException('SOAP client returned status of ' . $code, $code);
456
        }
457
458 26
        if (empty($response) || empty($response->getNonNullResponseMessages())) {
459
            throw new NoResponseReturnedException();
460
        }
461
    }
462
}
463