Completed
Branch FET-9608-locate-template-actio... (245c03)
by
unknown
1054:20 queued 1036:22
created

EE_Payment_Method   B

Complexity

Total Complexity 52

Size/Duplication

Total Lines 525
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 52
lcom 1
cbo 9
dl 0
loc 525
rs 7.9487
c 2
b 0
f 0

40 Methods

Rating   Name   Duplication   Size   Complexity  
A new_instance() 0 4 2
A new_instance_from_db() 0 3 1
A active() 0 3 1
A set_active() 0 8 3
A deactivate() 0 3 1
A button_url() 0 3 1
A set_button_url() 0 3 1
A debug_mode() 0 3 1
A set_debug_mode() 0 3 1
A description() 0 3 1
A set_description() 0 3 1
A name() 0 3 1
A set_name() 0 3 1
A open_by_default() 0 3 1
A set_open_by_default() 0 3 1
A order() 0 3 1
A set_order() 0 3 1
A slug() 0 3 1
A set_slug() 0 3 1
A type() 0 3 1
A set_type() 0 3 1
A wp_user() 0 3 1
A set_wp_user() 0 3 1
A set() 0 7 2
A admin_name() 0 3 1
A set_admin_name() 0 3 1
A admin_desc() 0 3 1
A set_admin_desc() 0 3 1
A scope() 0 3 1
A set_scope() 0 3 1
B type_obj() 0 24 4
A settings_array() 0 14 3
A button_html() 0 10 1
A get_all_usable_currencies() 0 3 1
A usable_for_currency() 0 8 3
A is_on_site() 0 3 1
A is_off_site() 0 3 1
A is_off_line() 0 3 1
A __sleep() 0 5 1
A save() 0 18 2

How to fix   Complexity   

Complex Class

Complex classes like EE_Payment_Method 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_Payment_Method, and based on these observations, apply Extract Interface, too.

1
<?php if (!defined('EVENT_ESPRESSO_VERSION')) {exit('No direct script access allowed');}
2
do_action( 'AHEE_log', __FILE__, __FUNCTION__, '' );
3
/**
4
 * Event Espresso
5
 *
6
 * Event Registration and Management Plugin for WordPress
7
 *
8
 * @ package			Event Espresso
9
 * @ author				Seth Shoultes
10
 * @ copyright		(c) 2008-2011 Event Espresso  All Rights Reserved.
11
 * @ license			{@link http://eventespresso.com/support/terms-conditions/}   * see Plugin Licensing *
12
 * @ link					{@link http://www.eventespresso.com}
13
 * @ since		 		4.0
14
 *
15
 * ------------------------------------------------------------------------
16
 *
17
 * EE_Payment_Method class
18
 * Should be parent of all payment method classes
19
 *
20
 * @package			Event Espresso
21
 * @subpackage		includes/classes/EE_Checkin.class.php
22
 * @author			Mike Nelson
23
 *
24
 * ------------------------------------------------------------------------
25
 */
26
class EE_Payment_Method extends EE_Base_Class{
27
28
	/**
29
	 * Payment Method type object, which has all the info about this type of payment method,
30
	 * including functions for processing payments, to get settings forms, etc.
31
	 * @var EE_PMT_Base
32
	 */
33
	protected $_type_obj;
34
35
36
37
	/**
38
	 * @param array $props_n_values
39
	 * @return EE_Payment_Method
40
	 * @throws \EE_Error
41
	 */
42
	public static function new_instance( $props_n_values = array()) {
43
		$has_object = parent::_check_for_object( $props_n_values, __CLASS__ );
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (_check_for_object() instead of new_instance()). Are you sure this is correct? If so, you might want to change this to $this->_check_for_object().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
44
		return $has_object ? $has_object : new self( $props_n_values, FALSE );
45
	}
46
47
48
49
	/**
50
	 * @param array $props_n_values
51
	 * @return EE_Payment_Method
52
	 * @throws \EE_Error
53
	 */
54
	public static function new_instance_from_db ( $props_n_values = array()) {
55
		return new self( $props_n_values, TRUE );
56
	}
57
58
59
60
	/**
61
	 * Checks if there is a payment method class of the given 'PMD_type', and if so returns the classname.
62
	 * Otherwise returns a normal EE_Payment_Method
63
	 * @param array $props_n_values where 'PMD_type' is a gateway name like 'Paypal_Standard','Invoice',etc (basically
64
	 * the classname minus 'EEPM_')
65
	 * @return string
66
	 */
67
//	private static function _payment_method_type($props_n_values){
68
//		EE_Registry::instance()->load_lib('Payment_Method_Manager');
69
//		$type_string = isset($props_n_values['PMD_type']) ? $props_n_values['PMD_type'] : NULL;
70
//		if(EE_Payment_Method_Manager::instance()->payment_method_type_exists($type_string)){
71
//			return 'EEPM_'.$type_string;
72
//		}else{
73
//			return __CLASS__;
74
//		}
75
//	}
76
77
78
79
	/**
80
	 * Gets whether this payment method can be used anywhere at all (ie frontend cart, admin, etc)
81
	 * @return boolean
82
	 */
83
	public function active() {
84
		return array_intersect(array_keys(EEM_Payment_Method::instance()->scopes()),$this->scope());
85
	}
86
87
88
89
	/**
90
	 * Sets this PM as active by making it usable within the CART scope. Offline gateways
91
	 * are also usable from the admin-scope as well. DOES NOT SAVE it
92
	 *
93
	 * @throws \EE_Error
94
	 */
95
	public function set_active(){
96
		$default_scopes = array(EEM_Payment_Method::scope_cart);
97
		if($this->type_obj() &&
98
			$this->type_obj()->payment_occurs() === EE_PMT_Base::offline){
99
			$default_scopes[] = EEM_Payment_Method::scope_admin;
100
		}
101
		$this->set_scope($default_scopes);
102
	}
103
104
105
106
	/**
107
	 * Makes this payment method apply to NO scopes at all. DOES NOT SAVE it.
108
	 */
109
	public function deactivate(){
110
		$this->set_scope(array());
111
	}
112
113
114
115
	/**
116
	 * Gets button_url
117
	 * @return string
118
	 */
119
	public function button_url() {
120
		return $this->get('PMD_button_url');
121
	}
122
123
124
125
	/**
126
	 * Sets button_url
127
	 * @param string $button_url
128
	 */
129
	public function set_button_url($button_url) {
130
		$this->set('PMD_button_url', $button_url);
131
	}
132
133
134
135
	/**
136
	 * Gets debug_mode
137
	 * @return boolean
138
	 */
139
	public function debug_mode() {
140
		return $this->get('PMD_debug_mode');
141
	}
142
143
144
145
	/**
146
	 * Sets debug_mode
147
	 * @param boolean $debug_mode
148
	 */
149
	public function set_debug_mode($debug_mode) {
150
		$this->set('PMD_debug_mode', $debug_mode);
151
	}
152
153
154
155
	/**
156
	 * Gets description
157
	 * @return string
158
	 */
159
	public function description() {
160
		return $this->get('PMD_desc');
161
	}
162
163
164
165
	/**
166
	 * Sets description
167
	 * @param string $description
168
	 */
169
	public function set_description($description) {
170
		$this->set('PMD_desc', $description);
171
	}
172
173
174
175
	/**
176
	 * Gets name
177
	 * @return string
178
	 */
179
	public function name() {
180
		return $this->get('PMD_name');
181
	}
182
183
184
185
	/**
186
	 * Sets name
187
	 * @param string $name
188
	 */
189
	public function set_name($name) {
190
		$this->set('PMD_name', $name);
191
	}
192
193
194
195
	/**
196
	 * Gets open_by_default
197
	 * @return boolean
198
	 */
199
	public function open_by_default() {
200
		return $this->get('PMD_open_by_default');
201
	}
202
203
204
205
	/**
206
	 * Sets open_by_default
207
	 * @param boolean $open_by_default
208
	 */
209
	public function set_open_by_default($open_by_default) {
210
		$this->set('PMD_open_by_default', $open_by_default);
211
	}
212
213
214
215
	/**
216
	 * Gets order
217
	 * @return int
218
	 */
219
	public function order() {
220
		return $this->get('PMD_order');
221
	}
222
223
224
225
	/**
226
	 * Sets order
227
	 * @param int $order
228
	 */
229
	public function set_order($order) {
230
		$this->set('PMD_order', $order);
231
	}
232
233
234
235
	/**
236
	 * Gets slug
237
	 * @return string
238
	 */
239
	public function slug() {
240
		return $this->get('PMD_slug');
241
	}
242
243
244
245
	/**
246
	 * Sets slug
247
	 * @param string $slug
248
	 */
249
	public function set_slug($slug) {
250
		$this->set('PMD_slug', $slug);
251
	}
252
253
254
255
	/**
256
	 * Gets type
257
	 * @return string
258
	 */
259
	public function type() {
260
		return $this->get('PMD_type');
261
	}
262
263
264
265
	/**
266
	 * Sets type
267
	 * @param string $type
268
	 */
269
	public function set_type($type) {
270
		$this->set('PMD_type', $type);
271
	}
272
273
274
275
	/**
276
	 * Gets wp_user
277
	 * @return int
278
	 */
279
	public function wp_user() {
280
		return $this->get('PMD_wp_user');
281
	}
282
283
284
285
286
	/**
287
	 * Sets wp_user
288
	 * @param int $wp_user_id
289
	 */
290
	public function set_wp_user($wp_user_id) {
291
		$this->set('PMD_wp_user', $wp_user_id);
292
	}
293
294
	/**
295
	 * Overrides parent so when PMD_type is changed we refresh the _type_obj
296
	 * @param string $field_name
297
	 * @param mixed $field_value
298
	 * @param boolean $use_default
299
	 */
300
	public function set( $field_name, $field_value, $use_default = FALSE ){
301
		if( $field_name === 'PMD_type' ){
302
			//the type has probably changed, so forget about its old type object
303
			$this->_type_obj = NULL;
304
		}
305
		parent::set($field_name, $field_value, $use_default);
306
	}
307
308
309
310
	/**
311
	 * Gets admin_name
312
	 * @return string
313
	 */
314
	public function admin_name() {
315
		return $this->get('PMD_admin_name');
316
	}
317
318
319
320
	/**
321
	 * Sets admin_name
322
	 * @param string $admin_name
323
	 */
324
	public function set_admin_name($admin_name) {
325
		$this->set('PMD_admin_name', $admin_name);
326
	}
327
328
329
330
	/**
331
	 * Gets admin_desc
332
	 * @return string
333
	 */
334
	public function admin_desc() {
335
		return $this->get('PMD_admin_desc');
336
	}
337
338
339
340
	/**
341
	 * Sets admin_desc
342
	 * @param string $admin_desc
343
	 */
344
	public function set_admin_desc($admin_desc) {
345
		$this->set('PMD_admin_desc', $admin_desc);
346
	}
347
348
349
350
	/**
351
	 * Gets scope
352
	 * @return array
353
	 */
354
	public function scope() {
355
		return $this->get('PMD_scope');
356
	}
357
358
359
360
	/**
361
	 * Sets scope
362
	 * @param array $scope
363
	 */
364
	public function set_scope($scope) {
365
		$this->set('PMD_scope', $scope);
366
	}
367
368
369
370
	/**
371
	 * Gets the payment method type for this payment method instance
372
	 * @return EE_PMT_Base
373
	 * @throws EE_Error
374
	 */
375
	public function type_obj(){
376
		if( ! $this->_type_obj ) {
377
			EE_Registry::instance()->load_lib( 'Payment_Method_Manager' );
378
			if ( EE_Payment_Method_Manager::instance()->payment_method_type_exists( $this->type() )) {
0 ignored issues
show
Documentation introduced by
$this->type() is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
379
				$class_name = EE_Payment_Method_Manager::instance()->payment_method_class_from_type( $this->type() );
0 ignored issues
show
Documentation introduced by
$this->type() is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
380
				if ( ! class_exists( $class_name )) {
381
					throw new EE_Error(
382
						sprintf(
383
							__( 'An attempt to use the "%1$s" payment method failed, so it was deactivated.%2$sWas the "%1$s" Plugin recently deactivated? It can be reactivated on the %3$sPlugins Admin Page%4$s', 'event_espresso' ),
384
							$class_name,
385
							'<br />',
386
							'<a href="' . admin_url('plugins.php') . '">',
387
							'</a>'
388
						)
389
					);
390
				}
391
				$r = new ReflectionClass( $class_name );
392
					$this->_type_obj = $r->newInstanceArgs( array( $this ));
393
			} else {
394
				throw new EE_Error( sprintf( __( 'A payment method of type "%1$s" does not exist. Only ones existing are: %2$s', 'event_espresso' ), $this->type(), implode(',', EE_Payment_Method_Manager::instance()->payment_method_type_names() ) ) );
395
			}
396
		}
397
		return $this->_type_obj;
398
	}
399
400
401
402
	/**
403
	 * Returns a simple array of key-value pairs combining the payment method's fields (without the 'PMD_' prefix)
404
	 * and the extra meta. Mostly used for passing off ot gateways.	 *
405
	 * @return array
406
	 */
407
	public function settings_array(){
408
		$fields = $this->model_field_array();
409
		$extra_meta = $this->all_extra_meta_array();
410
		//remove the model's prefix from the fields
411
		$combined_settings_array = array();
412
		foreach($fields as $key => $value){
413
			if(strpos($key, 'PMD_')===0){
414
				$key_sans_model_prefix = str_replace('PMD_', '', $key);
415
				$combined_settings_array [$key_sans_model_prefix] = $value;
416
			}
417
		}
418
		$combined_settings_array = array_merge( $extra_meta,$combined_settings_array );
419
		return $combined_settings_array;
420
	}
421
422
423
424
	/**
425
	 * Gets the HTML for displaying the payment method on a page.
426
	 *
427
	 * @param string $url
428
	 * @param string $css_class
429
	 * @return string of HTML for displaying the button
430
	 * @throws \EE_Error
431
	 */
432
	public function button_html( $url = '', $css_class = '' ){
433
		$payment_occurs = $this->type_obj()->payment_occurs();
434
		return '
435
		 <div id="' . $this->slug() . '-payment-option-dv" class="'. $payment_occurs .'-payment-gateway reg-page-payment-option-dv' . $css_class . '">
436
			<a id="payment-gateway-button-' . $this->slug() . '" class="reg-page-payment-option-lnk" rel="' . $this->slug() . '" href="' . $url . '" >
437
				<img src="' . $this->button_url() . '" alt="' . sprintf( esc_attr__( 'Pay using %s', 'event_espresso' ), $this->get_pretty('PMD_name','form_input') ) . '" />
438
			</a>
439
		</div>
440
';
441
	}
442
443
444
445
	/**
446
	 * Gets all the currencies which are an option for this payment method
447
	 * (as defined by the gateway and the currently active currencies)
448
	 *
449
	 * @return EE_Currency[]
450
	 * @throws \EE_Error
451
	 */
452
	public function get_all_usable_currencies(){
453
		return EEM_Currency::instance()->get_all_currencies_usable_by($this->type_obj());
454
	}
455
456
457
458
	/**
459
	 * Reports whether or not this payment method can be used for this payment method
460
	 *
461
	 * @param string $currency_code currency ID (code)
462
	 * @return boolean
463
	 * @throws \EE_Error
464
	 */
465
	public function usable_for_currency( $currency_code ) {
466
		foreach( $this->get_all_usable_currencies() as $currency_obj ) {
467
			if( $currency_obj->ID() === $currency_code ){
468
				return TRUE;
469
			}
470
		}
471
		return FALSE;
472
	}
473
474
475
476
	/**
477
	 * Returns TRUE if this payment method's gateway is an instance of EE_Onsite_Gateway
478
	 *
479
	 * @return bool
480
	 * @throws \EE_Error
481
	 */
482
	public function is_on_site(){
483
		return $this->type_obj()->payment_occurs() === EE_PMT_Base::onsite;
484
	}
485
486
487
488
	/**
489
	 * Returns TRUE if this payment method's gateway is an instance of EE_Offsite_Gateway
490
	 *
491
	 * @return bool
492
	 * @throws \EE_Error
493
	 */
494
	public function is_off_site(){
495
		return $this->type_obj()->payment_occurs() === EE_PMT_Base::offsite;
496
	}
497
498
499
500
	/**
501
	 * Returns TRUE if this payment method does not utilize a gateway
502
	 *
503
	 * @return bool
504
	 * @throws \EE_Error
505
	 */
506
	public function is_off_line(){
507
		return $this->type_obj()->payment_occurs() === EE_PMT_Base::offline;
508
	}
509
510
	/**
511
	 * Overrides default __sleep so the object type is NOT cached.
512
	 * This way we can rely on the normal EE_Payment_Method::type_obj() logic
513
	 * to load the required classes, and don't need them at the time of unserialization
514
	 * @return array
515
	 */
516
	public function __sleep(){
517
		$properties =  get_object_vars( $this );
518
		unset( $properties[ '_type_obj' ] );
519
		return array_keys( $properties );
520
	}
521
522
523
524
	/**
525
	 * Overrides parent to add some logging for when payment methods get deactivated
526
	 *
527
	 * @param array $set_cols_n_values
528
	 * @return int @see EE_Base_Class::save()
529
	 * @throws \EE_Error
530
	 */
531
	public function save( $set_cols_n_values = array() ) {
532
		$results =  parent::save( $set_cols_n_values );
533
		if( $this->get_original( 'PMD_scope' ) !== $this->get( 'PMD_scope' ) ) {
534
			EE_Log::instance()->log(
535
				__FILE__,
536
				__FUNCTION__,
537
				sprintf(
538
					__( 'Set new scope on payment method %1$s to %2$s from %3$s on URL %4$s', 'event_espresso' ),
539
					$this->name(),
540
					serialize( $this->get_original(  'PMD_scope' ) ),
541
					serialize( $this->get( 'PMD_scope' ) ),
542
					EE_Registry::instance()->REQ->get_current_page_permalink()
543
				),
544
				'payment_method_change'
545
			);
546
		}
547
		return $results;
548
	}
549
550
}
551