Completed
Pull Request — 23 (#431)
by Harald
10:27
created

Configuration   D

Complexity

Total Complexity 104

Size/Duplication

Total Lines 537
Duplicated Lines 7.82 %

Coupling/Cohesion

Components 2
Dependencies 4

Importance

Changes 0
Metric Value
dl 42
loc 537
rs 4.8717
c 0
b 0
f 0
wmc 104
lcom 2
cbo 4

54 Methods

Rating   Name   Duplication   Size   Complexity  
C __construct() 0 31 12
A reset() 0 4 1
A gateway() 0 4 1
A environment() 0 8 2
A merchantId() 0 7 2
A publicKey() 0 7 2
A privateKey() 0 7 2
A timeout() 0 7 2
A proxyHost() 0 7 2
A proxyPort() 0 7 2
A proxyType() 0 7 2
A isUsingProxy() 0 6 2
A proxyUser() 0 7 2
A proxyPassword() 0 7 2
A isAuthenticatedProxy() 0 6 2
A assertGlobalHasAccessTokenOrKeys() 0 4 1
B assertHasAccessTokenOrKeys() 0 14 6
A assertHasClientCredentials() 0 5 1
A assertHasClientId() 0 6 2
A assertHasClientSecret() 0 6 2
A getEnvironment() 0 4 1
A setEnvironment() 0 4 1
A getMerchantId() 0 4 1
A setMerchantId() 0 4 1
A getPublicKey() 0 4 1
A getClientId() 0 4 1
A setPublicKey() 0 4 1
A getPrivateKey() 0 4 1
A getClientSecret() 0 4 1
A setPrivateKey() 0 4 1
A setProxyHost() 0 4 1
A getProxyHost() 0 4 1
A setProxyPort() 0 4 1
A getProxyPort() 0 4 1
A setProxyType() 0 4 1
A getProxyType() 0 4 1
A setProxyUser() 0 4 1
A getProxyUser() 0 4 1
A setProxyPassword() 0 4 1
A getProxyPassword() 0 4 1
A setTimeout() 0 4 1
A getTimeout() 0 4 1
A getAccessToken() 0 4 1
A isAccessToken() 0 4 1
A isClientCredentials() 0 4 1
A baseUrl() 0 4 1
A merchantPath() 0 4 1
A caFile() 0 13 3
A portNumber() 0 7 3
A protocol() 0 4 2
B serverName() 21 21 6
B authUrl() 21 21 6
B sslOn() 0 17 6
A logMessage() 0 4 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 Configuration 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 Configuration, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace Braintree;
3
4
/**
5
 *
6
 * Configuration registry
7
 *
8
 * @package    Braintree
9
 * @subpackage Utility
10
 * @copyright  2015 Braintree, a division of PayPal, Inc.
11
 */
12
13
class Configuration
14
{
15
    public static $global;
16
17
    private $_environment = null;
18
    private $_merchantId = null;
19
    private $_publicKey = null;
20
    private $_privateKey = null;
21
    private $_clientId = null;
22
    private $_clientSecret = null;
23
    private $_accessToken = null;
24
    private $_proxyHost = null;
25
    private $_proxyPort = null;
26
    private $_proxyType = null;
27
    private $_proxyUser = null;
28
    private $_proxyPassword = null;
29
    private $_timeout = 60;
30
31
    /**
32
     * Braintree API version to use
33
     * @access public
34
     */
35
     const API_VERSION =  4;
36
37
    public function __construct($attribs = [])
38
    {
39
        foreach ($attribs as $kind => $value) {
40
            if ($kind == 'environment') {
41
                CredentialsParser::assertValidEnvironment($value);
42
                $this->_environment = $value;
43
            }
44
            if ($kind == 'merchantId') {
45
                $this->_merchantId = $value;
46
            }
47
            if ($kind == 'publicKey') {
48
                $this->_publicKey = $value;
49
            }
50
            if ($kind == 'privateKey') {
51
                $this->_privateKey = $value;
52
            }
53
        }
54
55
        if (isset($attribs['clientId']) || isset($attribs['accessToken'])) {
56
            if (isset($attribs['environment']) || isset($attribs['merchantId']) || isset($attribs['publicKey']) || isset($attribs['privateKey'])) {
57
                throw new Exception\Configuration('Cannot mix OAuth credentials (clientId, clientSecret, accessToken) with key credentials (publicKey, privateKey, environment, merchantId).');
58
            }
59
            $parsedCredentials = new CredentialsParser($attribs);
60
61
            $this->_environment = $parsedCredentials->getEnvironment();
62
            $this->_merchantId = $parsedCredentials->getMerchantId();
63
            $this->_clientId = $parsedCredentials->getClientId();
64
            $this->_clientSecret = $parsedCredentials->getClientSecret();
65
            $this->_accessToken = $parsedCredentials->getAccessToken();
66
        }
67
    }
68
69
    /**
70
     * resets configuration to default
71
     * @access public
72
     */
73
    public static function reset()
74
    {
75
        self::$global = new Configuration();
76
    }
77
78
    public static function gateway()
79
    {
80
        return new Gateway(self::$global);
81
    }
82
83
    public static function environment($value=null)
84
    {
85
        if (empty($value)) {
86
            return self::$global->getEnvironment();
87
        }
88
        CredentialsParser::assertValidEnvironment($value);
89
        self::$global->setEnvironment($value);
90
    }
91
92
    public static function merchantId($value=null)
93
    {
94
        if (empty($value)) {
95
            return self::$global->getMerchantId();
96
        }
97
        self::$global->setMerchantId($value);
98
    }
99
100
    public static function publicKey($value=null)
101
    {
102
        if (empty($value)) {
103
            return self::$global->getPublicKey();
104
        }
105
        self::$global->setPublicKey($value);
106
    }
107
108
    public static function privateKey($value=null)
109
    {
110
        if (empty($value)) {
111
            return self::$global->getPrivateKey();
112
        }
113
        self::$global->setPrivateKey($value);
114
    }
115
116
    /**
117
     * Sets or gets the read timeout to use for making requests.
118
     *
119
     * @param integer $value If provided, sets the read timeout
120
     * @return integer The read timeout used for connecting to Braintree
121
     */
122
    public static function timeout($value=null)
123
    {
124
        if (empty($value)) {
125
            return self::$global->getTimeout();
126
        }
127
        self::$global->setTimeout($value);
128
    }
129
130
    /**
131
     * Sets or gets the proxy host to use for connecting to Braintree
132
     *
133
     * @param string $value If provided, sets the proxy host
134
     * @return string The proxy host used for connecting to Braintree
135
     */
136
    public static function proxyHost($value = null)
137
    {
138
        if (empty($value)) {
139
            return self::$global->getProxyHost();
140
        }
141
        self::$global->setProxyHost($value);
142
    }
143
144
    /**
145
     * Sets or gets the port of the proxy to use for connecting to Braintree
146
     *
147
     * @param string $value If provided, sets the port of the proxy
148
     * @return string The port of the proxy used for connecting to Braintree
149
     */
150
    public static function proxyPort($value = null)
151
    {
152
        if (empty($value)) {
153
            return self::$global->getProxyPort();
154
        }
155
        self::$global->setProxyPort($value);
156
    }
157
158
    /**
159
     * Sets or gets the proxy type to use for connecting to Braintree. This value
160
     * can be any of the CURLOPT_PROXYTYPE options in PHP cURL.
161
     *
162
     * @param string $value If provided, sets the proxy type
163
     * @return string The proxy type used for connecting to Braintree
164
     */
165
    public static function proxyType($value = null)
166
    {
167
        if (empty($value)) {
168
            return self::$global->getProxyType();
169
        }
170
        self::$global->setProxyType($value);
171
    }
172
173
    /**
174
     * Specifies whether or not a proxy is properly configured
175
     *
176
     * @return bool true if a proxy is configured properly, false if not
177
     */
178
    public static function isUsingProxy()
179
    {
180
        $proxyHost = self::$global->getProxyHost();
181
        $proxyPort = self::$global->getProxyPort();
182
        return !empty($proxyHost) && !empty($proxyPort);
183
    }
184
185
    public static function proxyUser($value = null)
186
    {
187
        if (empty($value)) {
188
            return self::$global->getProxyUser();
189
        }
190
        self::$global->setProxyUser($value);
191
    }
192
193
    public static function proxyPassword($value = null)
194
    {
195
        if (empty($value)) {
196
            return self::$global->getProxyPassword();
197
        }
198
        self::$global->setProxyPassword($value);
199
    }
200
201
    /**
202
     * Specified whether or not a username and password have been provided for
203
     * use with an authenticated proxy
204
     *
205
     * @return bool true if both proxyUser and proxyPassword are present
206
     */
207
    public static function isAuthenticatedProxy()
208
    {
209
        $proxyUser = self::$global->getProxyUser();
210
        $proxyPwd = self::$global->getProxyPassword();
211
        return !empty($proxyUser) && !empty($proxyPwd);
212
    }
213
214
    public static function assertGlobalHasAccessTokenOrKeys()
215
    {
216
        self::$global->assertHasAccessTokenOrKeys();
217
    }
218
219
    public function assertHasAccessTokenOrKeys()
220
    {
221
        if (empty($this->_accessToken)) {
222
            if (empty($this->_merchantId)) {
223
                throw new Exception\Configuration('Braintree\\Configuration::merchantId needs to be set (or accessToken needs to be passed to Braintree\\Gateway).');
224
            } else if (empty($this->_environment)) {
225
                throw new Exception\Configuration('Braintree\\Configuration::environment needs to be set.');
226
            } else if (empty($this->_publicKey)) {
227
                throw new Exception\Configuration('Braintree\\Configuration::publicKey needs to be set.');
228
            } else if (empty($this->_privateKey)) {
229
                throw new Exception\Configuration('Braintree\\Configuration::privateKey needs to be set.');
230
            }
231
        }
232
    }
233
234
    public function assertHasClientCredentials()
235
    {
236
        $this->assertHasClientId();
237
        $this->assertHasClientSecret();
238
    }
239
240
    public function assertHasClientId()
241
    {
242
        if (empty($this->_clientId)) {
243
            throw new Exception\Configuration('clientId needs to be passed to Braintree\\Gateway.');
244
        }
245
    }
246
247
    public function assertHasClientSecret()
248
    {
249
        if (empty($this->_clientSecret)) {
250
            throw new Exception\Configuration('clientSecret needs to be passed to Braintree\\Gateway.');
251
        }
252
    }
253
254
    public function getEnvironment()
255
    {
256
        return $this->_environment;
257
    }
258
259
    /**
260
     * Do not use this method directly. Pass in the environment to the constructor.
261
     */
262
    public function setEnvironment($value)
263
    {
264
        $this->_environment = $value;
265
    }
266
267
    public function getMerchantId()
268
    {
269
        return $this->_merchantId;
270
    }
271
272
    /**
273
     * Do not use this method directly. Pass in the merchantId to the constructor.
274
     */
275
    public function setMerchantId($value)
276
    {
277
        $this->_merchantId = $value;
278
    }
279
280
    public function getPublicKey()
281
    {
282
        return $this->_publicKey;
283
    }
284
285
    public function getClientId()
286
    {
287
        return $this->_clientId;
288
    }
289
290
    /**
291
     * Do not use this method directly. Pass in the publicKey to the constructor.
292
     */
293
    public function setPublicKey($value)
294
    {
295
        $this->_publicKey = $value;
296
    }
297
298
    public function getPrivateKey()
299
    {
300
        return $this->_privateKey;
301
    }
302
303
    public function getClientSecret()
304
    {
305
        return $this->_clientSecret;
306
    }
307
308
    /**
309
     * Do not use this method directly. Pass in the privateKey to the constructor.
310
     */
311
    public function setPrivateKey($value)
312
    {
313
        $this->_privateKey = $value;
314
    }
315
316
    private function setProxyHost($value)
317
    {
318
        $this->_proxyHost = $value;
319
    }
320
321
    public function getProxyHost()
322
    {
323
        return $this->_proxyHost;
324
    }
325
326
    private function setProxyPort($value)
327
    {
328
        $this->_proxyPort = $value;
329
    }
330
331
    public function getProxyPort()
332
    {
333
        return $this->_proxyPort;
334
    }
335
336
    private function setProxyType($value)
337
    {
338
        $this->_proxyType = $value;
339
    }
340
341
    public function getProxyType()
342
    {
343
        return $this->_proxyType;
344
    }
345
346
    private function setProxyUser($value)
347
    {
348
        $this->_proxyUser = $value;
349
    }
350
351
    public function getProxyUser()
352
    {
353
        return $this->_proxyUser;
354
    }
355
356
    private function setProxyPassword($value)
357
    {
358
        $this->_proxyPassword = $value;
359
    }
360
361
    public function getProxyPassword()
362
    {
363
        return $this->_proxyPassword;
364
    }
365
366
    private function setTimeout($value)
367
    {
368
        $this->_timeout = $value;
369
    }
370
371
    public function getTimeout()
372
    {
373
        return $this->_timeout;
374
    }
375
376
    public function getAccessToken()
377
    {
378
        return $this->_accessToken;
379
    }
380
381
    public function isAccessToken()
382
    {
383
        return !empty($this->_accessToken);
384
    }
385
386
    public function isClientCredentials()
387
    {
388
        return !empty($this->_clientId);
389
    }
390
    /**
391
     * returns the base braintree gateway URL based on config values
392
     *
393
     * @access public
394
     * @param none
395
     * @return string braintree gateway URL
396
     */
397
    public function baseUrl()
398
    {
399
        return sprintf('%s://%s:%d', $this->protocol(), $this->serverName(), $this->portNumber());
400
    }
401
402
    /**
403
     * sets the merchant path based on merchant ID
404
     *
405
     * @access protected
406
     * @param none
407
     * @return string merchant path uri
408
     */
409
    public function merchantPath()
410
    {
411
        return '/merchants/' . $this->_merchantId;
412
    }
413
414
    /**
415
     * sets the physical path for the location of the CA certs
416
     *
417
     * @access public
418
     * @param none
419
     * @return string filepath
420
     */
421
    public function caFile($sslPath = NULL)
422
    {
423
        $sslPath = $sslPath ? $sslPath : DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR .
424
                   'ssl' . DIRECTORY_SEPARATOR;
425
        $caPath = __DIR__ . $sslPath . 'api_braintreegateway_com.ca.crt';
426
427
        if (!file_exists($caPath))
428
        {
429
            throw new Exception\SSLCaFileNotFound();
430
        }
431
432
        return $caPath;
433
    }
434
435
    /**
436
     * returns the port number depending on environment
437
     *
438
     * @access public
439
     * @param none
440
     * @return int portnumber
441
     */
442
    public function portNumber()
443
    {
444
        if ($this->sslOn()) {
445
            return 443;
446
        }
447
        return getenv("GATEWAY_PORT") ? getenv("GATEWAY_PORT") : 3000;
448
    }
449
450
    /**
451
     * returns http protocol depending on environment
452
     *
453
     * @access public
454
     * @param none
455
     * @return string http || https
456
     */
457
    public function protocol()
458
    {
459
        return $this->sslOn() ? 'https' : 'http';
460
    }
461
462
    /**
463
     * returns gateway server name depending on environment
464
     *
465
     * @access public
466
     * @param none
467
     * @return string server domain name
468
     */
469 View Code Duplication
    public function serverName()
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...
470
    {
471
        switch($this->_environment) {
472
         case 'production':
473
             $serverName = 'api.braintreegateway.com';
474
             break;
475
         case 'qa':
476
             $serverName = 'gateway.qa.braintreepayments.com';
477
             break;
478
         case 'sandbox':
479
             $serverName = 'api.sandbox.braintreegateway.com';
480
             break;
481
         case 'development':
482
         case 'integration':
483
         default:
484
             $serverName = 'localhost';
485
             break;
486
        }
487
488
        return $serverName;
489
    }
490
491 View Code Duplication
    public function authUrl()
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...
492
    {
493
        switch($this->_environment) {
494
         case 'production':
495
             $serverName = 'https://auth.venmo.com';
496
             break;
497
         case 'qa':
498
             $serverName = 'https://auth.qa.venmo.com';
499
             break;
500
         case 'sandbox':
501
             $serverName = 'https://auth.sandbox.venmo.com';
502
             break;
503
         case 'development':
504
         case 'integration':
505
         default:
506
             $serverName = 'http://auth.venmo.dev:9292';
507
             break;
508
        }
509
510
        return $serverName;
511
    }
512
513
    /**
514
     * returns boolean indicating SSL is on or off for this session,
515
     * depending on environment
516
     *
517
     * @access public
518
     * @param none
519
     * @return boolean
520
     */
521
    public function sslOn()
522
    {
523
        switch($this->_environment) {
524
         case 'integration':
525
         case 'development':
526
             $ssl = false;
527
             break;
528
         case 'production':
529
         case 'qa':
530
         case 'sandbox':
531
         default:
532
             $ssl = true;
533
             break;
534
        }
535
536
       return $ssl;
537
    }
538
539
    /**
540
     * log message to default logger
541
     *
542
     * @param string $message
543
     *
544
     */
545
    public function logMessage($message)
546
    {
547
        error_log('[Braintree] ' . $message);
548
    }
549
}
550
Configuration::reset();
551
class_alias('Braintree\Configuration', 'Braintree_Configuration');
552