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

OSCOM_Braintree   D

Complexity

Total Complexity 225

Size/Duplication

Total Lines 836
Duplicated Lines 72.73 %

Coupling/Cohesion

Components 2
Dependencies 1

Importance

Changes 0
Metric Value
dl 608
loc 836
rs 4.4444
c 0
b 0
f 0
wmc 225
lcom 2
cbo 1

36 Methods

Rating   Name   Duplication   Size   Complexity  
A OSCOM_Braintree() 0 9 2
C installCheck() 0 75 10
C migrate() 31 31 7
D getModules() 37 37 10
A isInstalled() 7 7 3
A getModuleInfo() 13 13 2
B hasApiCredentials() 5 15 5
A getApiCredentials() 7 7 4
C getParameters() 23 23 10
C getInputParameters() 67 67 17
D makeApiCall() 10 55 16
C drawButton() 55 55 10
C createRandomValue() 61 61 22
B saveParameter() 21 21 5
A deleteParameter() 0 3 1
B setupCredentials() 0 18 12
B formatCurrencyRaw() 13 13 5
A getCode() 0 3 1
A getTitle() 0 3 1
A getVersion() 13 13 3
A getApiVersion() 0 3 1
A getIdentifier() 0 3 1
A hasAlert() 0 3 1
A addAlert() 12 12 3
C getAlerts() 31 31 7
C install() 33 33 8
A uninstall() 17 17 3
A logUpdate() 3 5 2
C loadLanguageFile() 40 40 11
A getDef() 15 15 4
B getDirectoryContents() 17 17 5
A isWritable() 13 13 4
A rmdir() 13 13 4
A displayPath() 0 7 2
C getIpAddress() 33 33 15
B isValidIpAddress() 18 18 8

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 OSCOM_Braintree 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 OSCOM_Braintree, and based on these observations, apply Extract Interface, too.

1
<?php
2
/*
3
  $Id$
4
5
  osCommerce, Open Source E-Commerce Solutions
6
  http://www.oscommerce.com
7
8
  Copyright (c) 2016 osCommerce
9
10
  Released under the GNU General Public License
11
*/
12
13
  class OSCOM_Braintree {
14
    var $_code = 'braintree';
15
    var $_title = 'Braintree App';
16
    var $_version;
17
    var $_api_version;
18
    var $_identifier = 'osCommerce_BTapp_v1';
19
    var $_definitions = array();
20
21
    function OSCOM_Braintree() {
22
      if ( !class_exists('Braintree', false) ) {
23
        include(DIR_FS_CATALOG . 'includes/apps/braintree/lib/Braintree.php');
24
      }
25
26
      $this->_api_version = Braintree_Version::get();
27
28
      $this->installCheck();
29
    }
30
31
    function installCheck() {
32
      if (!defined('OSCOM_APP_PAYPAL_BRAINTREE_CC_SORT_ORDER')) {
33
        $installed = explode(';', MODULE_PAYMENT_INSTALLED);
34
        $installed_pos = array_search('braintree_cc.php', $installed);
35
36
        if ( $installed_pos === false ) {
37
          $installed[] = 'braintree_cc.php';
38
39
          $this->saveParameter('MODULE_PAYMENT_INSTALLED', implode(';', $installed));
40
        }
41
42
        $this->saveParameter('OSCOM_APP_PAYPAL_BRAINTREE_CC_SORT_ORDER', '0', 'Sort Order', 'Sort order of display. Lowest is displayed first.');
43
44
        $check_query = tep_db_query('show tables like "customers_braintree_tokens"');
45
        if (!tep_db_num_rows($check_query)) {
46
          $sql = <<<EOD
47
CREATE TABLE customers_braintree_tokens (
48
  id int NOT NULL auto_increment,
49
  customers_id int NOT NULL,
50
  braintree_token varchar(255) NOT NULL,
51
  card_type varchar(32) NOT NULL,
52
  number_filtered varchar(20) NOT NULL,
53
  expiry_date char(6) NOT NULL,
54
  date_added datetime NOT NULL,
55
  PRIMARY KEY (id),
56
  KEY idx_cbraintreet_customers_id (customers_id),
57
  KEY idx_cbraintreet_token (braintree_token)
58
) CHARACTER SET utf8 COLLATE utf8_unicode_ci;
59
EOD;
60
61
          tep_db_query($sql);
62
        }
63
      }
64
65
      if ( !defined('OSCOM_APP_PAYPAL_BRAINTREE_TRANSACTIONS_ORDER_STATUS_ID') ) {
66
        $check_query = tep_db_query("select orders_status_id from " . TABLE_ORDERS_STATUS . " where orders_status_name = 'Braintree [Transactions]' limit 1");
67
68
        if (tep_db_num_rows($check_query) < 1) {
69
          $status_query = tep_db_query("select max(orders_status_id) as status_id from " . TABLE_ORDERS_STATUS);
70
          $status = tep_db_fetch_array($status_query);
71
72
          $status_id = $status['status_id']+1;
73
74
          $languages = tep_get_languages();
75
76
          foreach ($languages as $lang) {
77
            tep_db_query("insert into " . TABLE_ORDERS_STATUS . " (orders_status_id, language_id, orders_status_name) values ('" . $status_id . "', '" . $lang['id'] . "', 'Braintree [Transactions]')");
78
          }
79
80
          $flags_query = tep_db_query("describe " . TABLE_ORDERS_STATUS . " public_flag");
81
          if (tep_db_num_rows($flags_query) == 1) {
82
            tep_db_query("update " . TABLE_ORDERS_STATUS . " set public_flag = 0 and downloads_flag = 0 where orders_status_id = '" . $status_id . "'");
83
          }
84
        } else {
85
          $check = tep_db_fetch_array($check_query);
86
87
          $status_id = $check['orders_status_id'];
88
        }
89
90
        $this->saveParameter('OSCOM_APP_PAYPAL_BRAINTREE_TRANSACTIONS_ORDER_STATUS_ID', $status_id);
91
      }
92
93
      if (!defined('MODULE_CONTENT_ACCOUNT_BRAINTREE_CARDS_SORT_ORDER')) {
94
        $cm = explode(';', MODULE_CONTENT_INSTALLED);
95
        $pos = array_search('account/cm_account_braintree_cards', $cm);
96
97
        if ($pos === false) {
98
          $cm[] = 'account/cm_account_braintree_cards';
99
100
          $this->saveParameter('MODULE_CONTENT_INSTALLED', implode(';', $cm));
101
        }
102
103
        $this->saveParameter('MODULE_CONTENT_ACCOUNT_BRAINTREE_CARDS_SORT_ORDER', '0', 'Sort Order', 'Sort order of display. Lowest is displayed first.');
104
      }
105
    }
106
107 View Code Duplication
    function migrate() {
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...
108
      $migrated = false;
109
110
      foreach ( $this->getModules() as $module ) {
111
        if ( !defined('OSCOM_APP_PAYPAL_BRAINTREE_' . $module . '_STATUS') ) {
112
          $this->saveParameter('OSCOM_APP_PAYPAL_BRAINTREE_' . $module . '_STATUS', '');
113
114
          $class = 'OSCOM_Braintree_' . $module;
115
116
          if ( !class_exists($class) ) {
117
            $this->loadLanguageFile('modules/' . $module . '/' . $module . '.php');
118
119
            include(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . $module . '/' . $module . '.php');
120
          }
121
122
          $m = new $class();
123
124
          if ( method_exists($m, 'canMigrate') && $m->canMigrate() ) {
125
            $m->migrate($this);
126
127
            if ( $migrated === false ) {
128
              $migrated = true;
129
            }
130
          }
131
        }
132
      }
133
134
      $this->deleteParameter('MODULE_CONTENT_ACCOUNT_BRAINTREE_CARDS_STATUS');
135
136
      return $migrated;
137
    }
138
139 View Code Duplication
    function getModules() {
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...
140
      static $result;
141
142
      if ( !isset($result) ) {
143
        $result = array();
144
145
        if ( $dir = @dir(DIR_FS_CATALOG . 'includes/apps/braintree/modules/') ) {
146
          while ( $file = $dir->read() ) {
147
            if ( !in_array($file, array('.', '..')) && is_dir(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . $file) && file_exists(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . $file . '/' . $file . '.php') ) {
148
              $sort_order = $this->getModuleInfo($file, 'sort_order');
149
150
              if ( is_numeric($sort_order) ) {
151
                $counter = (int)$sort_order;
152
              } else {
153
                $counter = count($result);
154
              }
155
156
              while ( true ) {
157
                if ( isset($result[$counter]) ) {
158
                  $counter++;
159
160
                  continue;
161
                }
162
163
                $result[$counter] = $file;
164
165
                break;
166
              }
167
            }
168
          }
169
170
          ksort($result, SORT_NUMERIC);
171
        }
172
      }
173
174
      return $result;
175
    }
176
177 View Code Duplication
    function isInstalled($module) {
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...
178
      if ( file_exists(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . basename($module) . '/' . basename($module) . '.php') ) {
179
        return defined('OSCOM_APP_PAYPAL_BRAINTREE_' . basename($module) . '_STATUS') && tep_not_null(constant('OSCOM_APP_PAYPAL_BRAINTREE_' . basename($module) . '_STATUS'));
180
      }
181
182
      return false;
183
    }
184
185 View Code Duplication
    function getModuleInfo($module, $info) {
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...
186
      $class = 'OSCOM_Braintree_' . $module;
187
188
      if ( !class_exists($class) ) {
189
        $this->loadLanguageFile('modules/' . $module . '/' . $module . '.php');
190
191
        include(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . $module . '/' . $module . '.php');
192
      }
193
194
      $m = new $class();
195
196
      return $m->{'_' . $info};
197
    }
198
199
    function hasApiCredentials($server) {
200
      $server = ($server == 'live') ? '' : 'SANDBOX_';
201
202
      $creds = array('OSCOM_APP_PAYPAL_BRAINTREE_' . $server . 'MERCHANT_ID',
203
                     'OSCOM_APP_PAYPAL_BRAINTREE_' . $server . 'PUBLIC_KEY',
204
                     'OSCOM_APP_PAYPAL_BRAINTREE_' . $server . 'PRIVATE_KEY');
205
206 View Code Duplication
      foreach ( $creds as $c ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
207
        if ( !defined($c) || (strlen(trim(constant($c))) < 1) ) {
208
          return false;
209
        }
210
      }
211
212
      return true;
213
    }
214
215 View Code Duplication
    function getApiCredentials($server, $type) {
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...
216
      if ( ($server == 'live') && defined('OSCOM_APP_PAYPAL_BRAINTREE_LIVE_API_' . strtoupper($type)) ) {
217
        return constant('OSCOM_APP_PAYPAL_BRAINTREE_LIVE_API_' . strtoupper($type));
218
      } elseif ( defined('OSCOM_APP_PAYPAL_BRAINTREE_SANDBOX_API_' . strtoupper($type)) ) {
219
        return constant('OSCOM_APP_PAYPAL_BRAINTREE_SANDBOX_API_' . strtoupper($type));
220
      }
221
    }
222
223 View Code Duplication
    function getParameters($module) {
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...
224
      $result = array();
225
226
      if ( $module == 'G' ) {
227
        if ( $dir = @dir(DIR_FS_CATALOG . 'includes/apps/braintree/cfg_params/') ) {
228
          while ( $file = $dir->read() ) {
229
            if ( !is_dir(DIR_FS_CATALOG . 'includes/apps/braintree/cfg_params/' . $file) && (substr($file, strrpos($file, '.')) == '.php') ) {
230
              $result[] = 'OSCOM_APP_PAYPAL_BRAINTREE_' . strtoupper(substr($file, 0, strrpos($file, '.')));
231
            }
232
          }
233
        }
234
      } else {
235
        if ( $dir = @dir(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . $module . '/cfg_params/') ) {
236
          while ( $file = $dir->read() ) {
237
            if ( !is_dir(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . $module . '/cfg_params/' . $file) && (substr($file, strrpos($file, '.')) == '.php') ) {
238
              $result[] = 'OSCOM_APP_PAYPAL_BRAINTREE_' . $module . '_' . strtoupper(substr($file, 0, strrpos($file, '.')));
239
            }
240
          }
241
        }
242
      }
243
244
      return $result;
245
    }
246
247 View Code Duplication
    function getInputParameters($module) {
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...
248
      $result = array();
249
250
      if ( $module == 'G' ) {
251
        $cut = 'OSCOM_APP_PAYPAL_BRAINTREE_';
252
      } else {
253
        $cut = 'OSCOM_APP_PAYPAL_BRAINTREE_' . $module . '_';
254
      }
255
256
      $cut_length = strlen($cut);
257
258
      foreach ( $this->getParameters($module) as $key ) {
259
        $p = strtolower(substr($key, $cut_length));
260
261
        if ( $module == 'G' ) {
262
          $cfg_class = 'OSCOM_Braintree_Cfg_' . $p;
263
264
          if ( !class_exists($cfg_class) ) {
265
            $this->loadLanguageFile('cfg_params/' . $p . '.php');
266
267
            include(DIR_FS_CATALOG . 'includes/apps/braintree/cfg_params/' . $p . '.php');
268
          }
269
        } else {
270
          $cfg_class = 'OSCOM_Braintree_' . $module . '_Cfg_' . $p;
271
272
          if ( !class_exists($cfg_class) ) {
273
            $this->loadLanguageFile('modules/' . $module . '/cfg_params/' . $p . '.php');
274
275
            include(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . $module . '/cfg_params/' . $p . '.php');
276
          }
277
        }
278
279
        $cfg = new $cfg_class();
280
281
        if ( !defined($key) ) {
282
          $this->saveParameter($key, $cfg->default, isset($cfg->title) ? $cfg->title : null, isset($cfg->description) ? $cfg->description : null, isset($cfg->set_func) ? $cfg->set_func : null);
283
        }
284
285
        if ( !isset($cfg->app_configured) || ($cfg->app_configured !== false) ) {
286
          if ( isset($cfg->sort_order) && is_numeric($cfg->sort_order) ) {
287
            $counter = (int)$cfg->sort_order;
288
          } else {
289
            $counter = count($result);
290
          }
291
292
          while ( true ) {
293
            if ( isset($result[$counter]) ) {
294
              $counter++;
295
296
              continue;
297
            }
298
299
            $set_field = $cfg->getSetField();
300
301
            if ( !empty($set_field) ) {
302
              $result[$counter] = $set_field;
303
            }
304
305
            break;
306
          }
307
        }
308
      }
309
310
      ksort($result, SORT_NUMERIC);
311
312
      return $result;
313
    }
314
315
    function makeApiCall($url, $parameters = null, $headers = null) {
316
      $server = parse_url($url);
317
318
      if ( !isset($server['port']) ) {
319
        $server['port'] = ($server['scheme'] == 'https') ? 443 : 80;
320
      }
321
322
      if ( !isset($server['path']) ) {
323
        $server['path'] = '/';
324
      }
325
326
      $curl = curl_init($server['scheme'] . '://' . $server['host'] . $server['path'] . (isset($server['query']) ? '?' . $server['query'] : ''));
327
      curl_setopt($curl, CURLOPT_PORT, $server['port']);
328
      curl_setopt($curl, CURLOPT_HEADER, false);
329
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
330
      curl_setopt($curl, CURLOPT_FORBID_REUSE, true);
331
      curl_setopt($curl, CURLOPT_FRESH_CONNECT, true);
332
      curl_setopt($curl, CURLOPT_ENCODING, ''); // disable gzip
333
334
      if ( isset($parameters) ) {
335
        curl_setopt($curl, CURLOPT_POST, true);
336
        curl_setopt($curl, CURLOPT_POSTFIELDS, $parameters);
337
      }
338
339 View Code Duplication
      if ( isset($headers) && is_array($headers) && !empty($headers) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
340
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
341
      }
342
343 View Code Duplication
      if ( isset($server['user']) && isset($server['pass']) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
344
        curl_setopt($curl, CURLOPT_USERPWD, $server['user'] . ':' . $server['pass']);
345
      }
346
347
      if ( defined('OSCOM_APP_PAYPAL_BRAINTREE_VERIFY_SSL') && (OSCOM_APP_PAYPAL_BRAINTREE_VERIFY_SSL == '1') ) {
348
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
349
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
350
351
        if ( file_exists(DIR_FS_CATALOG . 'includes/cacert.pem') ) {
352
          curl_setopt($curl, CURLOPT_CAINFO, DIR_FS_CATALOG . 'includes/cacert.pem');
353
        }
354
      } else {
355
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
356
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
357
      }
358
359 View Code Duplication
      if ( defined('OSCOM_APP_PAYPAL_BRAINTREE_PROXY') && tep_not_null(OSCOM_APP_PAYPAL_BRAINTREE_PROXY) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
360
        curl_setopt($curl, CURLOPT_HTTPPROXYTUNNEL, true);
361
        curl_setopt($curl, CURLOPT_PROXY, OSCOM_APP_PAYPAL_BRAINTREE_PROXY);
362
      }
363
364
      $result = curl_exec($curl);
365
366
      curl_close($curl);
367
368
      return $result;
369
    }
370
371 View Code Duplication
    function drawButton($title = null, $link = null, $type = null, $params = null, $force_css = false) {
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...
372
      $colours = array('success' => '#1cb841',
373
                       'error' => '#ca3c3c',
374
                       'warning' => '#ebaa16',
375
                       'info' => '#42B8DD',
376
                       'primary' => '#0078E7');
377
378
      if ( !isset($type) || !in_array($type, array_keys($colours)) ) {
379
        $type = 'info';
380
      }
381
382
      $css = 'font-size:14px;color:#fff;padding:8px 16px;border:0;border-radius:4px;text-shadow:0 1px 1px rgba(0, 0, 0, 0.2);text-decoration:none;display:inline-block;cursor:pointer;white-space:nowrap;vertical-align:baseline;text-align:center;background-color:' . $colours[$type] . ';';
383
384
      $button = '';
385
386
      if ( isset($link) ) {
387
        $button .= '<a href="' . $link . '" class="bt-button';
388
389
        if ( isset($type) ) {
390
          $button .= ' bt-button-' . $type;
391
        }
392
393
        $button .= '"';
394
395
        if ( isset($params) ) {
396
          $button .= ' ' . $params;
397
        }
398
399
        if ( $force_css == true ) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
400
          $button .= ' style="' . $css . '"';
401
        }
402
403
        $button .= '>' . $title . '</a>';
404
      } else {
405
        $button .= '<button type="submit" class="bt-button';
406
407
        if ( isset($type) ) {
408
          $button .= ' bt-button-' . $type;
409
        }
410
411
        $button .= '"';
412
413
        if ( isset($params) ) {
414
          $button .= ' ' . $params;
415
        }
416
417
        if ( $force_css == true ) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
418
          $button .= ' style="' . $css . '"';
419
        }
420
421
        $button .= '>' . $title . '</button>';
422
      }
423
424
      return $button;
425
    }
426
427 View Code Duplication
    function createRandomValue($length, $type = 'mixed') {
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...
428
      if ( ($type != 'mixed') && ($type != 'chars') && ($type != 'digits')) $type = 'mixed';
429
430
      $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
431
      $digits = '0123456789';
432
433
      $base = '';
434
435
      if ( ($type == 'mixed') || ($type == 'chars') ) {
436
        $base .= $chars;
437
      }
438
439
      if ( ($type == 'mixed') || ($type == 'digits') ) {
440
        $base .= $digits;
441
      }
442
443
      $value = '';
444
445
      if ( !class_exists('PasswordHash') && file_exists(DIR_FS_CATALOG . 'includes/classes/passwordhash.php') ) {
446
        include(DIR_FS_CATALOG . 'includes/classes/passwordhash.php');
447
448
        $hasher = new PasswordHash(10, true);
449
450
        do {
451
          $random = base64_encode($hasher->get_random_bytes($length));
452
453
          for ($i = 0, $n = strlen($random); $i < $n; $i++) {
454
            $char = substr($random, $i, 1);
455
456
            if ( strpos($base, $char) !== false ) {
457
              $value .= $char;
458
            }
459
          }
460
        } while ( strlen($value) < $length );
461
462
        if ( strlen($value) > $length ) {
463
          $value = substr($value, 0, $length);
464
        }
465
466
        return $value;
467
      }
468
469
// fallback for v2.3.1
470
      while ( strlen($value) < $length ) {
471
        if ($type == 'digits') {
472
          $char = tep_rand(0,9);
473
        } else {
474
          $char = chr(tep_rand(0,255));
475
        }
476
477
        if ( $type == 'mixed' ) {
478
          if (preg_match('/^[a-z0-9]$/i', $char)) $value .= $char;
479
        } elseif ($type == 'chars') {
480
          if (preg_match('/^[a-z]$/i', $char)) $value .= $char;
481
        } elseif ($type == 'digits') {
482
          if (preg_match('/^[0-9]$/i', $char)) $value .= $char;
483
        }
484
      }
485
486
      return $value;
487
    }
488
489 View Code Duplication
    function saveParameter($key, $value, $title = null, $description = null, $set_func = null) {
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...
490
      if ( !defined($key) ) {
491
        if ( !isset($title) ) {
492
          $title = 'Braintree App Parameter';
493
        }
494
495
        if ( !isset($description) ) {
496
          $description = 'A parameter for the Braintree Application.';
497
        }
498
499
        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('" . tep_db_input($title) . "', '" . tep_db_input($key) . "', '" . tep_db_input($value) . "', '" . tep_db_input($description) . "', '6', '0', now())");
500
501
        if ( isset($set_func) ) {
502
          tep_db_query("update " . TABLE_CONFIGURATION . " set set_function = '" . tep_db_input($set_func) . "' where configuration_key = '" . tep_db_input($key) . "'");
503
        }
504
505
        define($key, $value);
506
      } else {
507
        tep_db_query("update " . TABLE_CONFIGURATION . " set configuration_value = '" . tep_db_input($value) . "' where configuration_key = '" . tep_db_input($key) . "'");
508
      }
509
    }
510
511
    function deleteParameter($key) {
512
      tep_db_query("delete from " . TABLE_CONFIGURATION . " where configuration_key = '" . tep_db_input($key) . "'");
513
    }
514
515
    function setupCredentials($server = null) {
516
      $status = ((isset($server) && ($server === 'live')) || (!isset($server) && (OSCOM_APP_PAYPAL_BRAINTREE_CC_STATUS === '1'))) ? '1' : '0';
517
518
      Braintree_Configuration::environment($status === '1' ? 'production' : 'sandbox');
519
      Braintree_Configuration::merchantId($status === '1' ? OSCOM_APP_PAYPAL_BRAINTREE_MERCHANT_ID : OSCOM_APP_PAYPAL_BRAINTREE_SANDBOX_MERCHANT_ID);
520
      Braintree_Configuration::publicKey($status === '1' ? OSCOM_APP_PAYPAL_BRAINTREE_PUBLIC_KEY : OSCOM_APP_PAYPAL_BRAINTREE_SANDBOX_PUBLIC_KEY);
521
      Braintree_Configuration::privateKey($status === '1' ? OSCOM_APP_PAYPAL_BRAINTREE_PRIVATE_KEY : OSCOM_APP_PAYPAL_BRAINTREE_SANDBOX_PRIVATE_KEY);
522
523
      if (defined('OSCOM_APP_PAYPAL_BRAINTREE_PROXY') && tep_not_null(OSCOM_APP_PAYPAL_BRAINTREE_PROXY)) {
524
        $url = parse_url(OSCOM_APP_PAYPAL_BRAINTREE_PROXY);
525
526
        Braintree_Configuration::proxyHost($url['host']);
527
528
        if (isset($url['port'])) {
529
          Braintree_Configuration::proxyPort($url['port']);
530
        }
531
      }
532
    }
533
534 View Code Duplication
    function formatCurrencyRaw($total, $currency_code = null, $currency_value = null) {
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...
535
      global $currencies, $currency;
536
537
      if ( !isset($currency_code) ) {
538
        $currency_code = tep_session_is_registered('currency') ? $currency : DEFAULT_CURRENCY;
539
      }
540
541
      if ( !isset($currency_value) || !is_numeric($currency_value) ) {
542
        $currency_value = $currencies->currencies[$currency_code]['value'];
543
      }
544
545
      return number_format(tep_round($total * $currency_value, $currencies->currencies[$currency_code]['decimal_places']), $currencies->currencies[$currency_code]['decimal_places'], '.', '');
546
    }
547
548
    function getCode() {
549
      return $this->_code;
550
    }
551
552
    function getTitle() {
553
      return $this->_title;
554
    }
555
556 View Code Duplication
    function getVersion() {
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...
557
      if ( !isset($this->_version) ) {
558
        $version = trim(file_get_contents(DIR_FS_CATALOG . 'includes/apps/braintree/version.txt'));
559
560
        if ( is_numeric($version) ) {
561
          $this->_version = $version;
562
        } else {
563
          trigger_error('OSCOM APP [BRAINTREE]: Could not read App version number.');
564
        }
565
      }
566
567
      return $this->_version;
568
    }
569
570
    function getApiVersion() {
571
      return $this->_api_version;
572
    }
573
574
    function getIdentifier() {
575
      return $this->_identifier;
576
    }
577
578
    function hasAlert() {
579
      return tep_session_is_registered('OSCOM_Braintree_Alerts');
580
    }
581
582 View Code Duplication
    function addAlert($message, $type) {
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...
583
      global $OSCOM_Braintree_Alerts;
584
585
      if ( in_array($type, array('error', 'warning', 'success')) ) {
586
        if ( !tep_session_is_registered('OSCOM_Braintree_Alerts') ) {
587
          $OSCOM_Braintree_Alerts = array();
588
          tep_session_register('OSCOM_Braintree_Alerts');
589
        }
590
591
        $OSCOM_Braintree_Alerts[$type][] = $message;
592
      }
593
    }
594
595 View Code Duplication
    function getAlerts() {
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...
596
      global $OSCOM_Braintree_Alerts;
597
598
      $output = '';
599
600
      if ( tep_session_is_registered('OSCOM_Braintree_Alerts') && !empty($OSCOM_Braintree_Alerts) ) {
601
        $result = array();
602
603
        foreach ( $OSCOM_Braintree_Alerts as $type => $messages ) {
604
          if ( in_array($type, array('error', 'warning', 'success')) ) {
605
            $m = '<ul class="bt-alerts-' . $type . '">';
606
607
            foreach ( $messages as $message ) {
608
              $m .= '<li>' . tep_output_string_protected($message) . '</li>';
609
            }
610
611
            $m .= '</ul>';
612
613
            $result[] = $m;
614
          }
615
        }
616
617
        if ( !empty($result) ) {
618
          $output .= '<div class="bt-alerts">' . implode("\n", $result) . '</div>';
619
        }
620
      }
621
622
      tep_session_unregister('OSCOM_Braintree_Alerts');
623
624
      return $output;
625
    }
626
627 View Code Duplication
    function install($module) {
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...
628
      $cut_length = strlen('OSCOM_APP_PAYPAL_BRAINTREE_' . $module . '_');
629
630
      foreach ( $this->getParameters($module) as $key ) {
631
        $p = strtolower(substr($key, $cut_length));
632
633
        $cfg_class = 'OSCOM_Braintree_' . $module . '_Cfg_' . $p;
634
635
        if ( !class_exists($cfg_class) ) {
636
          $this->loadLanguageFile('modules/' . $module . '/cfg_params/' . $p . '.php');
637
638
          include(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . $module . '/cfg_params/' . $p . '.php');
639
        }
640
641
        $cfg = new $cfg_class();
642
643
        $this->saveParameter($key, $cfg->default, isset($cfg->title) ? $cfg->title : null, isset($cfg->description) ? $cfg->description : null, isset($cfg->set_func) ? $cfg->set_func : null);
644
      }
645
646
      $m_class = 'OSCOM_Braintree_' . $module;
647
648
      if ( !class_exists($m_class) ) {
649
        $this->loadLanguageFile('modules/' . $module . '/' . $module . '.php');
650
651
        include(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . $module . '/' . $module . '.php');
652
      }
653
654
      $m = new $m_class();
655
656
      if ( method_exists($m, 'install') ) {
657
        $m->install($this);
658
      }
659
    }
660
661 View Code Duplication
    function uninstall($module) {
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...
662
      tep_db_query("delete from " . TABLE_CONFIGURATION . " where configuration_key like 'OSCOM_APP_PAYPAL_BRAINTREE_" . tep_db_input($module) . "_%'");
663
664
      $m_class = 'OSCOM_Braintree_' . $module;
665
666
      if ( !class_exists($m_class) ) {
667
        $this->loadLanguageFile('modules/' . $module . '/' . $module . '.php');
668
669
        include(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . $module . '/' . $module . '.php');
670
      }
671
672
      $m = new $m_class();
673
674
      if ( method_exists($m, 'uninstall') ) {
675
        $m->uninstall($this);
676
      }
677
    }
678
679
    function logUpdate($message, $version) {
680 View Code Duplication
      if ( is_writable(DIR_FS_CATALOG . 'includes/apps/braintree/work') ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
681
        file_put_contents(DIR_FS_CATALOG . 'includes/apps/braintree/work/update_log-' . $version . '.php', '[' . date('d-M-Y H:i:s') . '] ' . $message . "\n", FILE_APPEND);
682
      }
683
    }
684
685 View Code Duplication
    public function loadLanguageFile($filename, $lang = null) {
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...
686
      global $language;
687
688
      $lang = isset($lang) ? basename($lang) : basename($language);
689
690
      if ( $lang != 'english' ) {
691
        $this->loadLanguageFile($filename, 'english');
692
      }
693
694
      $pathname = DIR_FS_CATALOG . 'includes/apps/braintree/languages/' . $lang . '/' . $filename;
695
696
      if ( file_exists($pathname) ) {
697
        $contents = file($pathname);
698
699
        $ini_array = array();
700
701
        foreach ( $contents as $line ) {
702
          $line = trim($line);
703
704
          if ( !empty($line) && (substr($line, 0, 1) != '#') ) {
705
            $delimiter = strpos($line, '=');
706
707
            if ( ($delimiter !== false) && (preg_match('/^[A-Za-z0-9_-]/', substr($line, 0, $delimiter)) === 1) && (substr_count(substr($line, 0, $delimiter), ' ') == 1) ) {
708
              $key = trim(substr($line, 0, $delimiter));
709
              $value = trim(substr($line, $delimiter + 1));
710
711
              $ini_array[$key] = $value;
712
            } elseif ( isset($key) ) {
713
              $ini_array[$key] .= "\n" . $line;
714
            }
715
          }
716
        }
717
718
        unset($contents);
719
720
        $this->_definitions = array_merge($this->_definitions, $ini_array);
721
722
        unset($ini_array);
723
      }
724
    }
725
726 View Code Duplication
    function getDef($key, $values = null) {
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...
727
      $def = isset($this->_definitions[$key]) ? $this->_definitions[$key] : $key;
728
729
      if ( is_array($values) ) {
730
        $keys = array_keys($values);
731
732
        foreach ( $keys as &$k ) {
733
          $k = ':' . $k;
734
        }
735
736
        $def = str_replace($keys, array_values($values), $def);
737
      }
738
739
      return $def;
740
    }
741
742 View Code Duplication
    function getDirectoryContents($base, &$result = array()) {
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...
743
      foreach ( scandir($base) as $file ) {
744
        if ( ($file == '.') || ($file == '..') ) {
745
          continue;
746
        }
747
748
        $pathname = $base . '/' . $file;
749
750
        if ( is_dir($pathname) ) {
751
          $this->getDirectoryContents($pathname, $result);
752
        } else {
753
          $result[] = str_replace('\\', '/', $pathname); // Unix style directory separator "/"
754
        }
755
      }
756
757
      return $result;
758
    }
759
760 View Code Duplication
    function isWritable($location) {
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...
761
      if ( !file_exists($location) ) {
762
        while ( true ) {
763
          $location = dirname($location);
764
765
          if ( file_exists($location) ) {
766
            break;
767
          }
768
        }
769
      }
770
771
      return is_writable($location);
772
    }
773
774 View Code Duplication
    function rmdir($dir) {
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...
775
      foreach ( scandir($dir) as $file ) {
776
        if ( !in_array($file, array('.', '..')) ) {
777
          if ( is_dir($dir . '/' . $file) ) {
778
            $this->rmdir($dir . '/' . $file);
779
          } else {
780
            unlink($dir . '/' . $file);
781
          }
782
        }
783
      }
784
785
      return rmdir($dir);
786
    }
787
788
    function displayPath($pathname) {
789
      if ( DIRECTORY_SEPARATOR == '/' ) {
790
        return $pathname;
791
      }
792
793
      return str_replace('/', DIRECTORY_SEPARATOR, $pathname);
794
    }
795
// OSCOM v2.2rc2a compatibility
796 View Code Duplication
    function getIpAddress() {
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...
797
      if ( function_exists('tep_get_ip_address') ) {
798
        return tep_get_ip_address();
799
      }
800
      global $HTTP_SERVER_VARS;
801
      $ip_address = null;
802
      $ip_addresses = array();
803
      if (isset($HTTP_SERVER_VARS['HTTP_X_FORWARDED_FOR']) && !empty($HTTP_SERVER_VARS['HTTP_X_FORWARDED_FOR'])) {
804
        foreach ( array_reverse(explode(',', $HTTP_SERVER_VARS['HTTP_X_FORWARDED_FOR'])) as $x_ip ) {
805
          $x_ip = trim($x_ip);
806
          if ($this->isValidIpAddress($x_ip)) {
807
            $ip_addresses[] = $x_ip;
808
          }
809
        }
810
      }
811
      if (isset($HTTP_SERVER_VARS['HTTP_CLIENT_IP']) && !empty($HTTP_SERVER_VARS['HTTP_CLIENT_IP'])) {
812
        $ip_addresses[] = $HTTP_SERVER_VARS['HTTP_CLIENT_IP'];
813
      }
814
      if (isset($HTTP_SERVER_VARS['HTTP_X_CLUSTER_CLIENT_IP']) && !empty($HTTP_SERVER_VARS['HTTP_X_CLUSTER_CLIENT_IP'])) {
815
        $ip_addresses[] = $HTTP_SERVER_VARS['HTTP_X_CLUSTER_CLIENT_IP'];
816
      }
817
      if (isset($HTTP_SERVER_VARS['HTTP_PROXY_USER']) && !empty($HTTP_SERVER_VARS['HTTP_PROXY_USER'])) {
818
        $ip_addresses[] = $HTTP_SERVER_VARS['HTTP_PROXY_USER'];
819
      }
820
      $ip_addresses[] = $HTTP_SERVER_VARS['REMOTE_ADDR'];
821
      foreach ( $ip_addresses as $ip ) {
822
        if (!empty($ip) && $this->isValidIpAddress($ip)) {
823
          $ip_address = $ip;
824
          break;
825
        }
826
      }
827
      return $ip_address;
828
    }
829
// OSCOM v2.2rc2a compatibility
830 View Code Duplication
    function isValidIpAddress($ip_address) {
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...
831
      if ( function_exists('tep_validate_ip_address') ) {
832
        return tep_validate_ip_address($ip_address);
833
      }
834
      if (function_exists('filter_var') && defined('FILTER_VALIDATE_IP')) {
835
        return filter_var($ip_address, FILTER_VALIDATE_IP, array('flags' => FILTER_FLAG_IPV4));
836
      }
837
      if (preg_match('/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/', $ip_address)) {
838
        $parts = explode('.', $ip_address);
839
        foreach ($parts as $ip_parts) {
840
          if ( (intval($ip_parts) > 255) || (intval($ip_parts) < 0) ) {
841
            return false; // number is not within 0-255
842
          }
843
        }
844
        return true;
845
      }
846
      return false;
847
    }
848
  }
849
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
850