Completed
Branch BUG/rest-api-between-operator-... (f62593)
by
unknown
15:49 queued 33s
created

EE_Gateway   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 494
Duplicated Lines 7.29 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

Changes 0
Metric Value
dl 36
loc 494
rs 8.8798
c 0
b 0
f 0
wmc 44
lcom 1
cbo 10

28 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A __sleep() 0 6 1
A supports_sending_refunds() 0 4 1
A supports_receiving_refunds() 0 4 1
A do_direct_refund() 0 4 1
A set_settings() 0 7 2
A set_payment_model() 0 4 1
A set_payment_log() 0 4 1
A set_template_helper() 0 4 1
A set_line_item_helper() 0 4 1
A set_money_helper() 0 4 1
A set_gateway_data_formatter() 9 12 3
A _get_gateway_formatter() 9 12 3
A set_unsupported_character_remover() 9 12 3
A _get_unsupported_character_remover() 9 12 3
A log() 0 18 5
A format_currency() 0 4 1
A currencies_supported() 0 4 1
A _sum_items_and_taxes() 0 12 3
A _can_easily_itemize_transaction_for() 0 11 2
A update_txn_based_on_payment() 0 5 1
A _get_first_event_for_payment() 0 4 1
A _get_first_event_name_for_payment() 0 4 1
A _format_partial_payment_line_item_name() 0 4 1
A _format_partial_payment_line_item_desc() 0 4 1
A _format_line_item_name() 0 4 1
A _format_line_item_desc() 0 4 1
A _format_order_description() 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 EE_Gateway 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 EE_Gateway, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
use EventEspresso\core\services\loaders\LoaderFactory;
4
use \EventEspresso\core\services\payment_methods\gateways\GatewayDataFormatterInterface;
5
use \EventEspresso\core\exceptions\InvalidEntityException;
6
use \EventEspresso\core\services\formatters\FormatterInterface;
7
8
/**
9
 * EE_Gateway
10
 * Abstract base class for all gateways for processing payments.
11
 * This has been designed in a way so that other WP Plugins
12
 * can use this class for processing payments, and theoretically any of its children,
13
 * provided they implement the interfaces it uses.
14
 * The necessary interfaces to be implemented are found in:
15
 *  /core/interfaces/payments/  and  /core/interfaces/
16
 * After constructing a gateway object, you need to set all the properties which reference many of the
17
 * needed helpers and models (see all the methods starting with "set_",
18
 * eg seg_line_item_helper which should be passed an object which implements EEHI_Line_Item_Helper; etc).
19
 *
20
 * @package            Event Espresso
21
 * @subpackage         core/libraries/payment_methods
22
 * @author             Mike Nelson
23
 */
24
abstract class EE_Gateway
25
{
26
    /**
27
     * a constant used as a possible value for $_currencies_supported to indicate
28
     * that ALL currencies are supported by this gateway
29
     */
30
    const all_currencies_supported = 'all_currencies_supported';
31
    /**
32
     * Where values are 3-letter currency codes
33
     *
34
     * @var array
35
     */
36
    protected $_currencies_supported = array();
37
    /**
38
     * Whether or not this gateway can support SENDING a refund request (ie, initiated by
39
     * admin in EE's wp-admin page)
40
     *
41
     * @var boolean
42
     */
43
    protected $_supports_sending_refunds = false;
44
45
    /**
46
     * Whether or not this gateway can support RECEIVING a refund request from the payment
47
     * provider (ie, initiated by admin on the payment prover's website who sends an IPN to EE)
48
     *
49
     * @var boolean
50
     */
51
    protected $_supports_receiving_refunds = false;
52
    /**
53
     * Model for querying for existing payments
54
     *
55
     * @var EEMI_Payment
56
     */
57
    protected $_pay_model;
58
59
    /**
60
     * Model used for adding to the payments log
61
     *
62
     * @var EEMI_Payment_Log
63
     */
64
    protected $_pay_log;
65
66
    /**
67
     * Used for formatting some input to gateways
68
     *
69
     * @var EEHI_Template
70
     */
71
    protected $_template;
72
73
    /**
74
     * Concrete class that implements EEHI_Money, used by most gateways
75
     *
76
     * @var EEHI_Money
77
     */
78
    protected $_money;
79
80
    /**
81
     * Concrete class that implements EEHI_Line_Item, used for manipulating the line item tree
82
     *
83
     * @var EEHI_Line_Item
84
     */
85
    protected $_line_item;
86
87
    /**
88
     * @var GatewayDataFormatterInterface
89
     */
90
    protected $_gateway_data_formatter;
91
92
    /**
93
     * @var FormatterInterface
94
     */
95
    protected $_unsupported_character_remover;
96
97
    /**
98
     * The ID of the payment method using this gateway
99
     *
100
     * @var int
101
     */
102
    protected $_ID;
103
104
    /**
105
     * @var $_debug_mode boolean whether to send requests to teh sandbox site or not
106
     */
107
    protected $_debug_mode;
108
    /**
109
     *
110
     * @var string $_name name to show for this payment method
111
     */
112
    protected $_name;
113
    /**
114
     *
115
     * @var string name to show fir this payment method to admin-type users
116
     */
117
    protected $_admin_name;
118
119
    /**
120
     * @return EE_Gateway
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
121
     */
122
    public function __construct()
123
    {
124
    }
125
126
    /**
127
     * We don't want to serialize models as they often have circular structures
128
     * (eg a payment model has a reference to each payment model object; and most
129
     * payments have a transaction, most transactions have a payment method;
130
     * most payment methods have a payment method type; most payment method types
131
     * have a gateway. And if a gateway serializes its models, we start at the
132
     * beginning again)
133
     *
134
     * @return array
135
     */
136
    public function __sleep()
137
    {
138
        $properties = get_object_vars($this);
139
        unset($properties['_pay_model'], $properties['_pay_log']);
140
        return array_keys($properties);
141
    }
142
143
    /**
144
     * Returns whether or not this gateway should support SENDING refunds
145
     * see $_supports_sending_refunds
146
     *
147
     * @return boolean
148
     */
149
    public function supports_sending_refunds()
150
    {
151
        return $this->_supports_sending_refunds;
152
    }
153
154
    /**
155
     * Returns whether or not this gateway should support RECEIVING refunds
156
     * see $_supports_receiving_refunds
157
     *
158
     * @return boolean
159
     */
160
    public function supports_receiving_refunds()
161
    {
162
        return $this->_supports_receiving_refunds;
163
    }
164
165
166
    /**
167
     * Tries to refund the payment specified, taking into account the extra
168
     * refund info. Note that if the gateway's _supports_sending_refunds is false,
169
     * this should just throw an exception.
170
     *
171
     * @param EE_Payment $payment
172
     * @param array      $refund_info
173
     * @return EE_Payment for the refund
174
     * @throws EE_Error
175
     */
176
    public function do_direct_refund(EE_Payment $payment, $refund_info = null)
177
    {
178
        return null;
179
    }
180
181
182
    /**
183
     * Sets the payment method's settings so the gateway knows where to send the request
184
     * etc
185
     *
186
     * @param array $settings_array
187
     */
188
    public function set_settings($settings_array)
189
    {
190
        foreach ($settings_array as $name => $value) {
191
            $property_name = "_" . $name;
192
            $this->{$property_name} = $value;
193
        }
194
    }
195
196
    /**
197
     * See this class description
198
     *
199
     * @param EEMI_Payment $payment_model
200
     */
201
    public function set_payment_model($payment_model)
202
    {
203
        $this->_pay_model = $payment_model;
204
    }
205
206
    /**
207
     * See this class description
208
     *
209
     * @param EEMI_Payment_Log $payment_log_model
210
     */
211
    public function set_payment_log($payment_log_model)
212
    {
213
        $this->_pay_log = $payment_log_model;
214
    }
215
216
    /**
217
     * See this class description
218
     *
219
     * @param EEHI_Template $template_helper
220
     */
221
    public function set_template_helper($template_helper)
222
    {
223
        $this->_template = $template_helper;
224
    }
225
226
    /**
227
     * See this class description
228
     *
229
     * @param EEHI_Line_Item $line_item_helper
230
     */
231
    public function set_line_item_helper($line_item_helper)
232
    {
233
        $this->_line_item = $line_item_helper;
234
    }
235
236
    /**
237
     * See this class description
238
     *
239
     * @param EEHI_Money $money_helper
240
     */
241
    public function set_money_helper($money_helper)
242
    {
243
        $this->_money = $money_helper;
244
    }
245
246
247
    /**
248
     * Sets the gateway data formatter helper
249
     *
250
     * @param GatewayDataFormatterInterface $gateway_data_formatter
251
     * @throws InvalidEntityException if it's not set properly
252
     */
253 View Code Duplication
    public function set_gateway_data_formatter(GatewayDataFormatterInterface $gateway_data_formatter)
254
    {
255
        if (! $gateway_data_formatter instanceof GatewayDataFormatterInterface) {
256
            throw new InvalidEntityException(
257
                is_object($gateway_data_formatter)
258
                    ? get_class($gateway_data_formatter)
259
                    : esc_html__('Not an object', 'event_espresso'),
260
                '\\EventEspresso\\core\\services\\payment_methods\\gateways\\GatewayDataFormatterInterface'
261
            );
262
        }
263
        $this->_gateway_data_formatter = $gateway_data_formatter;
264
    }
265
266
    /**
267
     * Gets the gateway data formatter
268
     *
269
     * @return GatewayDataFormatterInterface
270
     * @throws InvalidEntityException if it's not set properly
271
     */
272 View Code Duplication
    protected function _get_gateway_formatter()
273
    {
274
        if (! $this->_gateway_data_formatter instanceof GatewayDataFormatterInterface) {
275
            throw new InvalidEntityException(
276
                is_object($this->_gateway_data_formatter)
277
                    ? get_class($this->_gateway_data_formatter)
278
                    : esc_html__('Not an object', 'event_espresso'),
279
                '\\EventEspresso\\core\\services\\payment_methods\\gateways\\GatewayDataFormatterInterface'
280
            );
281
        }
282
        return $this->_gateway_data_formatter;
283
    }
284
285
286
    /**
287
     * Sets the helper which will remove unsupported characters for most gateways
288
     *
289
     * @param FormatterInterface $formatter
290
     * @return FormatterInterface
291
     * @throws InvalidEntityException
292
     */
293 View Code Duplication
    public function set_unsupported_character_remover(FormatterInterface $formatter)
294
    {
295
        if (! $formatter instanceof FormatterInterface) {
296
            throw new InvalidEntityException(
297
                is_object($formatter)
298
                    ? get_class($formatter)
299
                    : esc_html__('Not an object', 'event_espresso'),
300
                '\\EventEspresso\\core\\services\\formatters\\FormatterInterface'
301
            );
302
        }
303
        $this->_unsupported_character_remover = $formatter;
304
    }
305
306
    /**
307
     * Gets the helper which removes characters which gateways might not support, like emojis etc.
308
     *
309
     * @return FormatterInterface
310
     * @throws InvalidEntityException
311
     */
312 View Code Duplication
    protected function _get_unsupported_character_remover()
313
    {
314
        if (! $this->_unsupported_character_remover instanceof FormatterInterface) {
315
            throw new InvalidEntityException(
316
                is_object($this->_unsupported_character_remover)
317
                    ? get_class($this->_unsupported_character_remover)
318
                    : esc_html__('Not an object', 'event_espresso'),
319
                '\\EventEspresso\\core\\services\\formatters\\FormatterInterface'
320
            );
321
        }
322
        return $this->_unsupported_character_remover;
323
    }
324
325
326
    /**
327
     * @param $message
328
     * @param $payment
329
     */
330
    public function log($message, $object_logged)
331
    {
332
        if ($object_logged instanceof EEI_Payment) {
333
            $type = 'Payment';
334
            $id = $object_logged->ID();
335
        } elseif ($object_logged instanceof EEI_Payment_Method) {
336
            $type = 'Payment_Method';
337
            $id = $this->_ID;
338
        } elseif ($object_logged instanceof EEI_Transaction) {
339
            $type = 'Transaction';
340
            $id = $object_logged->ID();
341
        }
342
        // only log if we're going to store it for longer than the minimum time
343
        $reg_config = LoaderFactory::getLoader()->load('EE_Registration_Config');
344
        if ($reg_config->gateway_log_lifespan !== '1 second') {
345
            $this->_pay_log->gateway_log($message, $id, $type);
346
        }
347
    }
348
349
    /**
350
     * Formats the amount so it can generally be sent to gateways
351
     *
352
     * @param float $amount
353
     * @return string
354
     * @deprecated since 4.9.31 insetad use
355
     *             EventEspresso\core\services\payment_methods\gateways\GatewayDataFormatter::format_currency()
356
     */
357
    public function format_currency($amount)
358
    {
359
        return $this->_get_gateway_formatter()->formatCurrency($amount);
360
    }
361
362
    /**
363
     * Returns either an array of all the currency codes supported,
364
     * or a string indicating they're all supported (EE_gateway::all_currencies_supported)
365
     *
366
     * @return mixed array or string
367
     */
368
    public function currencies_supported()
369
    {
370
        return $this->_currencies_supported;
371
    }
372
373
    /**
374
     * Returns what a simple summing of items and taxes for this transaction. This
375
     * can be used to determine if some more complex line items, like promotions,
376
     * surcharges, or cancellations occurred (in which case we might want to forget
377
     * about creating an itemized list of purchases and instead only send the total due)
378
     *
379
     * @param EE_Transaction $transaction
380
     * @return float
381
     */
382
    protected function _sum_items_and_taxes(EE_Transaction $transaction)
383
    {
384
        $total_line_item = $transaction->total_line_item();
385
        $total = 0;
386
        foreach ($total_line_item->get_items() as $item_line_item) {
387
            $total += max($item_line_item->total(), 0);
388
        }
389
        foreach ($total_line_item->tax_descendants() as $tax_line_item) {
390
            $total += max($tax_line_item->total(), 0);
391
        }
392
        return $total;
393
    }
394
395
    /**
396
     * Determines whether or not we can easily itemize the transaction using only
397
     * items and taxes (ie, no promotions or surcharges or cancellations needed)
398
     *
399
     * @param EEI_Payment $payment
400
     * @return boolean
401
     */
402
    protected function _can_easily_itemize_transaction_for(EEI_Payment $payment)
403
    {
404
        return $this->_money->compare_floats(
405
            $this->_sum_items_and_taxes($payment->transaction()),
406
            $payment->transaction()->total()
407
        )
408
               && $this->_money->compare_floats(
409
                   $payment->amount(),
410
                   $payment->transaction()->total()
411
               );
412
    }
413
414
    /**
415
     * Handles updating the transaction and any other related data based on the payment.
416
     * You may be tempted to do this as part of do_direct_payment or handle_payment_update,
417
     * but doing so on those functions might be too early. It's possible that the changes
418
     * you make to teh transaction or registration or line items may just get overwritten
419
     * at that point. Instead, you should store any info you need on the payment during those
420
     * functions, and use that information at this step, which client code will decide
421
     * for you when it should be called.
422
     *
423
     * @param EE_Payment $payment
424
     * @return void
425
     */
426
    public function update_txn_based_on_payment($payment)
427
    {
428
        // maybe update the transaction or line items or registrations
429
        // but most gateways don't need to do this, because they only update the payment
430
    }
431
432
    /**
433
     * Gets the first event for this payment (it's possible that it could be for multiple)
434
     *
435
     * @param EEI_Payment $payment
436
     * @return EEI_Event|null
437
     * @deprecated since 4.9.31 instead use EEI_Payment::get_first_event()
438
     */
439
    protected function _get_first_event_for_payment(EEI_Payment $payment)
440
    {
441
        return $payment->get_first_event();
442
    }
443
444
    /**
445
     * Gets the name of the first event for which is being paid
446
     *
447
     * @param EEI_Payment $payment
448
     * @return string
449
     * @deprecated since 4.9.31 instead use EEI_Payment::get_first_event_name()
450
     */
451
    protected function _get_first_event_name_for_payment(EEI_Payment $payment)
452
    {
453
        return $payment->get_first_event_name();
454
    }
455
456
    /**
457
     * Gets the text to use for a gateway's line item name when this is a partial payment
458
     *
459
     * @deprecated since 4.9.31 instead use $this->_get_gateway_formatter()->formatPartialPaymentLineItemName($payment)
460
     * @param EE_Payment $payment
461
     * @return string
462
     */
463
    protected function _format_partial_payment_line_item_name(EEI_Payment $payment)
464
    {
465
        return $this->_get_gateway_formatter()->formatPartialPaymentLineItemName($payment);
466
    }
467
468
    /**
469
     * Gets the text to use for a gateway's line item description when this is a partial payment
470
     *
471
     * @deprecated since 4.9.31 instead use $this->_get_gateway_formatter()->formatPartialPaymentLineItemDesc()
472
     * @param EEI_Payment $payment
473
     * @return string
474
     */
475
    protected function _format_partial_payment_line_item_desc(EEI_Payment $payment)
476
    {
477
        return $this->_get_gateway_formatter()->formatPartialPaymentLineItemDesc($payment);
478
    }
479
480
    /**
481
     * Gets the name to use for a line item when sending line items to the gateway
482
     *
483
     * @deprecated since 4.9.31 instead use $this->_get_gateway_formatter()->formatLineItemName($line_item,$payment)
484
     * @param EEI_Line_Item $line_item
485
     * @param EEI_Payment   $payment
486
     * @return string
487
     */
488
    protected function _format_line_item_name(EEI_Line_Item $line_item, EEI_Payment $payment)
489
    {
490
        return $this->_get_gateway_formatter()->formatLineItemName($line_item, $payment);
491
    }
492
493
    /**
494
     * Gets the description to use for a line item when sending line items to the gateway
495
     *
496
     * @deprecated since 4.9.31 instead use $this->_get_gateway_formatter()->formatLineItemDesc($line_item, $payment))
497
     * @param EEI_Line_Item $line_item
498
     * @param EEI_Payment   $payment
499
     * @return string
500
     */
501
    protected function _format_line_item_desc(EEI_Line_Item $line_item, EEI_Payment $payment)
502
    {
503
        return $this->_get_gateway_formatter()->formatLineItemDesc($line_item, $payment);
504
    }
505
506
    /**
507
     * Gets the order description that should generlly be sent to gateways
508
     *
509
     * @deprecated since 4.9.31 instead use $this->_get_gateway_formatter()->formatOrderDescription($payment)
510
     * @param EEI_Payment $payment
511
     * @return type
512
     */
513
    protected function _format_order_description(EEI_Payment $payment)
514
    {
515
        return $this->_get_gateway_formatter()->formatOrderDescription($payment);
516
    }
517
}
518