Completed
Push — master ( 42a4de...b05bb8 )
by Gareth
03:31
created

ExchangeWebServices::fromCallbackToken()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

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