Completed
Push — master ( af373c...e6c2d6 )
by Gareth
08:33
created

ExchangeWebServices::__call()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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