Completed
Push — master ( d7c914...6c6572 )
by Gareth
11:08 queued 07:24
created

ExchangeWebServices::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

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