Completed
Push — master ( b75b09...1d6059 )
by Justin
11:39 queued 04:37
created

WPSC_Payment_Gateway::default_credit_card_form()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 62
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 36
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 62
rs 8.9167

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
final class WPSC_Payment_Gateways {
4
5
	/**
6
	 * Contain a key-value array of gateway names and gateway class names
7
	 *
8
	 * @access private
9
	 * @static
10
	 * @var array
11
	 * @since 3.9
12
	 */
13
	private static $gateways = array();
14
15
	/**
16
	 * Contain an array of payment gateway objects
17
	 *
18
	 * @access private
19
	 * @static
20
	 * @var array
21
	 * @since 3.9
22
	 */
23
	private static $instances = array();
24
25
	/**
26
	 * Contains the cached metadata of the registered payment gateways, so that the
27
	 * plugin doesn't have to load the gateway's files to determine its metadata
28
	 *
29
	 * @access private
30
	 * @static
31
	 *
32
	 * @since 3.9
33
	 *
34
	 * @var array
35
	 */
36
	private static $payment_gateway_cache = array();
37
38
	/**
39
	 * Contains the names of active gateways that use this API
40
	 *
41
	 * @access private
42
	 * @static
43
	 * @since 3.9
44
	 *
45
	 * @var array
46
	 */
47
	private static $active_gateways = array();
48
49
	/**
50
	 * Return a particular payment gateway object
51
	 *
52
	 * @access public
53
	 * @param string $gateway Name of the payment gateway you want to get
54
	 * @return object
55
	 * @since 3.9
56
	 */
57
	public static function &get( $gateway, $meta = false ) {
58
59
		if ( empty( self::$instances[ $gateway ] ) ) {
60
61
			if ( ! $meta ) {
62
				$meta = self::$gateways[ $gateway ];
63
			}
64
65
			if ( ! file_exists( $meta['path'] ) ) {
66
				WPSC_Payment_Gateways::flush_cache();
67
			}
68
69
			require_once( $meta['path'] );
70
71
			$class_name = $meta['class'];
72
73
			$options = array(
74
				'http_client' => new WPSC_Payment_Gateway_HTTP(),
75
			);
76
77
			if ( ! class_exists( $class_name ) ) {
78
				$error = new WP_Error( 'wpsc_invalid_payment_gateway', sprintf( __( 'Invalid payment gateway: Class %s does not exist.', 'wp-e-commerce' ), $class_name ) );
79
				return $error;
80
			}
81
82
			self::$instances[ $gateway ] = new $class_name( $options );
83
		}
84
85
		return self::$instances[ $gateway ];
86
	}
87
88
	public static function init() {
89
90
		add_action( 'wpsc_submit_gateway_options', array( 'WPSC_Payment_Gateway_Setting', 'action_update_payment_gateway_settings' ) );
91
92
		if ( ! defined( 'WPSC_PAYMENT_GATEWAY_DEBUG' ) || WPSC_PAYMENT_GATEWAY_DEBUG == false ) {
93
			add_action( 'init', array( 'WPSC_Payment_Gateways', 'action_save_payment_gateway_cache' ), 99 );
94
		 } else {
95
			WPSC_Payment_Gateways::flush_cache();
96
		 }
97
98
		WPSC_Payment_Gateways::register_dir( WPSC_MERCHANT_V3_PATH . '/gateways' );
99
100
		// Call the Active Gateways init function
101
		self::initialize_gateways();
102
103
		if ( isset( $_REQUEST['payment_gateway'] ) && isset( $_REQUEST['payment_gateway_callback'] ) ) {
104
			add_action( 'init', array( 'WPSC_Payment_Gateways', 'action_process_callbacks' ) );
105
		}
106
	}
107
108
	public static function action_process_callbacks() {
109
		$gateway = self::get( $_REQUEST['payment_gateway'] );
110
		$function_name = "callback_{$_REQUEST['payment_gateway_callback']}";
111
		$callback = array( $gateway, $function_name );
112
113
		if ( is_callable( $callback ) ) {
114
			$gateway->$function_name();
115
		}
116
	}
117
118
	/**
119
	 * Check to see whether a gateway is registered using this new API
120
	 *
121
	 * @access public
122
	 * @since 3.9
123
	 *
124
	 * @param string $gateway Gateway name (derived from the filename without .php extension)
125
	 * @return bool True if it's already registered.
126
	 */
127
	public static function is_registered( $gateway ) {
128
		return ! empty( self::$gateways[ $gateway ] );
129
	}
130
131
	/**
132
	 * Automatically scan a directory for payment gateways and load the classes.
133
	 *
134
	 * The structure of this directory should follow the same rules of the wp-content/plugins
135
	 * structure.
136
	 *
137
	 * All of the files inside the directory will be assumed as payment gateway modules.
138
	 * Files with the same name as those sub-folders will be included as payment
139
	 * gateway modules.
140
	 *
141
	 * For example, if we have the following directory structure:
142
	 * payment-gateways/
143
	 * |-- test-gateway-1.php
144
	 * |-- test-gateway-2.php
145
	 * |-- some-folder/
146
	 *     |-- class.php
147
	 *     |-- functions.php
148
	 *
149
	 * The following files will be loaded as payment gateway modules: test-gateway-1.php,
150
	 * test-gateway-2.php
151
	 * See WPSC_Payment_Gateways::register_file() for file and class naming convention
152
	 *
153
	 * @access public
154
	 * @since 3.9
155
	 * @uses WPSC_Payment_Gateways::register_file()
156
	 *
157
	 * @param string $dir Path to the directory
158
	 * @param string $main_file File name of the class to load
159
	 * @return mixed Return true if successfully loaded all the payment gateway in
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use object|boolean|null.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
160
	 * the directory.
161
	 * Otherwise return a WP_Error object.
162
	 */
163
	public static function register_dir( $dir, $main_file = '' ) {
0 ignored issues
show
Unused Code introduced by
The parameter $main_file is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
164
		$dir = trailingslashit( $dir );
165
		$main_file = basename( $dir ) . '.php';
166
167
		// scan files in dir
168
		$files = scandir( $dir );
169
170
		if ( in_array( $main_file, $files ) ) {
171
			return self::register_file( $dir . $main_file );
172
		}
173
174
		foreach ( $files as $file ) {
175
			$path = $dir . $file;
176
177
			if ( pathinfo( $path, PATHINFO_EXTENSION ) != 'php' || in_array( $file, array( '.', '..' ) ) || is_dir( $path ) ) {
178
				continue;
179
			}
180
181
			$return = self::register_file( $path );
182
183
			if ( is_wp_error( $return ) ) {
184
				//We should log this
185
			}
186
		}
187
	}
188
189
	/**
190
	 * Register a file as a payment gateway module.
191
	 *
192
	 * The payment gateway inside the file must be defined as a subclass of WPSC_Payment_Gateway.
193
	 *
194
	 * The file name should be lowercase, using hyphens or underscores between words
195
	 * instead of spaces. The class name must have "WPSC_Payment_Gateway_" as the
196
	 * prefix, followed by the file name, in which words are capitalized and connected
197
	 * by underscore.
198
	 *
199
	 * For example, if the file name is "paypal-pro.php", then the class name inside
200
	 * the file must be WPSC_Payment_Gateway_Paypal_Pro.
201
	 *
202
	 * @access public
203
	 * @since 3.9
204
	 * @see WPSC_Payment_Gateways::register_dir()
205
	 *
206
	 * @param string $file Absolute path to the file containing the payment gateway
207
	 * class
208
	 * @return mixed Return true if the file is successfully included and contains
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use object|boolean.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
209
	 * a valid class. Otherwise, a WP_Error object is returned.
210
	 */
211
	public static function register_file( $file ) {
212
213
		if ( empty( self::$payment_gateway_cache ) ) {
214
			self::$payment_gateway_cache = get_option( 'wpsc_payment_gateway_cache', array() );
215
		}
216
217
		$filename = basename( $file, '.php' );
218
219
		// payment gateway already exists in cache
220
		if ( isset( self::$payment_gateway_cache[ $filename ] ) ) {
221
			self::$gateways[ $filename ] = self::$payment_gateway_cache[ $filename ];
222
		}
223
224
		// if payment gateway is not in cache, load metadata
225
		$classname = ucwords( str_replace( '-', ' ', $filename ) );
226
		$classname = 'WPSC_Payment_Gateway_' . str_replace( ' ', '_', $classname );
227
228
		if ( file_exists( $file ) ) {
229
			require_once $file;
230
		}
231
232
		if ( is_callable( array( $classname, 'load' ) ) && ! call_user_func( array( $classname, 'load' ) ) ) {
233
234
			self::unregister_file( $filename );
235
236
			$error = new WP_Error( 'wpsc-payment', __( 'Error', 'wp-e-commerce' ) );
237
238
			return $error;
239
		}
240
241
		$meta = array(
242
			'class'        => $classname,
243
			'path'         => $file,
244
			'internalname' => $filename, // compat with older API
245
		);
246
247
		$gateway = self::get( $filename, $meta );
248
249
		if ( is_wp_error( $gateway ) ) {
250
			return $gateway;
251
		}
252
253
		$meta['name']  = $gateway->get_title();
254
		$meta['image'] = $gateway->get_image_url();
255
		$meta['mark']  = $gateway->get_mark_html();
256
257
		self::$gateways[ $filename ] = $meta;
258
259
		return true;
260
	}
261
262
	public static function unregister_file( $filename ) {
263
		if ( isset( self::$gateways[ $filename ] ) ) {
264
			unset( self::$gateways[ $filename ] );
265
		}
266
	}
267
268
	/**
269
	 * Updates the payment gateway cache when it's changed.
270
	 *
271
	 * This function is hooked into WordPress' wp_loaded action
272
	 *
273
	 * @access public
274
	 * @static
275
	 * @since 3.9
276
	 *
277
	 * @return void
278
	 */
279
	public static function action_save_payment_gateway_cache() {
280
		if ( self::$payment_gateway_cache != self::$gateways ) {
281
			update_option( 'wpsc_payment_gateway_cache', self::$gateways );
282
		}
283
	}
284
285
	/**
286
	 * Flush the payment gateways cache.
287
	 *
288
	 * @access public
289
	 * @static
290
	 * @since 3.9
291
	 * @return void
292
	 */
293
	public static function flush_cache() {
294
		delete_option( 'wpsc_payment_gateway_cache' );
295
	}
296
297
	/**
298
	 * Gets metadata of a certain payment gateway. This is better than calling WPSC_Payment_Gateways->get( $gateway_name )->get_title()
299
	 * and the likes of it, since it doesn't require the gateway itself to be loaded.
300
	 *
301
	 * @access public
302
	 * @static
303
	 * @since 3.9
304
	 *
305
	 * @param string $gateway
306
	 * @return mixed Array containing the metadata. If the gateway is not registered,
307
	 *               returns false.
308
	 */
309
	public static function get_meta( $gateway ) {
310
		return isset( self::$gateways[$gateway] ) ? self::$gateways[$gateway] : false;
311
	}
312
313
	/**
314
	 *
315
	 * Return an array containing registered gateway names.
316
	 *
317
	 * @access public
318
	 * @since 3.9
319
	 *
320
	 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<integer|string>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
321
	 */
322
	public static function get_gateways() {
323
		return array_keys( self::$gateways );
324
	}
325
326
	/**
327
	 *
328
	 * Return an array containing active gateway names.
329
	 *
330
	 * @access public
331
	 * @since 3.9
332
	 *
333
	 * @return array
334
	 */
335
	public static function get_active_gateways() {
336
		if ( empty( self::$active_gateways ) ) {
337
			$selected_gateways = get_option( 'custom_gateway_options', array() );
338
			$registered_gateways = self::get_gateways();
339
			self::$active_gateways = array_intersect( $selected_gateways, $registered_gateways );
340
		}
341
342
		return apply_filters( 'wpsc_get_active_gateways', array_values( self::$active_gateways ) );
343
	}
344
345
	/**
346
	 * Initialize the Active Gateways
347
	 *
348
	 * @access public
349
	 * @since 4.0
350
	 *
351
	 * @return void
352
	 */
353
	public static function initialize_gateways() {
354
		$active_gateways = self::get_active_gateways();
355
356
		foreach( $active_gateways as $gateway_id ) {
357
			$gateway = self::get( $gateway_id );
358
			$gateway->init();
359
		}
360
	}
361
362
	/**
363
	 * Returns all known currencies without fractions.
364
	 *
365
	 * Our internal list has not been updated in some time, so returning a filterable list
366
	 * for ever-changing economies and currencies should prove helpful.
367
	 *
368
	 * @link http://www.currency-iso.org/dam/downloads/table_a1.xml
369
	 *
370
	 * @since  4.0
371
	 *
372
	 * @return array Currency ISO codes that do not use fractions.
373
	 */
374
	public static function currencies_without_fractions() {
375
376
		$currencies = array(
377
			'JPY',
378
			'HUF',
379
			'VND',
380
			'BYR',
381
			'XOF',
382
			'BIF',
383
			'XAF',
384
			'CLP',
385
			'KMF',
386
			'DJF',
387
			'XPF',
388
			'GNF',
389
			'ISK',
390
			'GNF',
391
			'KRW',
392
			'PYG',
393
			'RWF',
394
			'UGX',
395
			'UYI',
396
			'VUV',
397
		);
398
399
		return (array) apply_filters( 'wpsc_currencies_without_fractions', $currencies );
400
	}
401
402
	/**
403
	 * Gets an array of countries in the EU.
404
	 *
405
	 * MC (monaco) and IM (Isle of Man, part of UK) also use VAT.
406
	 *
407
	 * @since  4.0
408
	 * @param  $type Type of countries to retrieve. Blank for EU member countries. eu_vat for EU VAT countries.
409
	 * @return string[]
410
	 */
411
	public function get_european_union_countries( $type = '' ) {
412
		$countries = array( 'AT', 'BE', 'BG', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HU', 'HR', 'IE', 'IT', 'LT', 'LU', 'LV', 'MT', 'NL', 'PL', 'PT', 'RO', 'SE', 'SI', 'SK' );
413
414
		if ( 'eu_vat' === $type ) {
415
			$countries[] = 'MC';
416
			$countries[] = 'IM';
417
		}
418
419
		return $countries;
420
	}
421
422
	/**
423
	 * No instantiation for this class
424
	 *
425
	 * @access private
426
	 * @since 3.9
427
	 *
428
	 */
429
	private function __construct() {}
430
}
431
432
abstract class WPSC_Payment_Gateway {
433
434
	/**
435
	 * Object that allows manipulation of payment gateway settings in a consistent
436
	 * manner
437
	 *
438
	 * @access public
439
	 * @var WPSC_Payment_Gateway_Setting
440
	 */
441
442
	public $setting;
443
444
	public $purchase_log;
445
446
	public $checkout_data;
447
448
	public $currency_code;
449
450
	public $title;
451
452
	/**
453
	 * Supported features such as 'default_credit_card_form', 'refunds'.
454
	 * @var array
455
	 */
456
	public $supports = array();
457
458
	/**
459
	 * Display default credit card form.
460
	 *
461
	 * @param  array $args
462
	 * @param  array $fields
463
	 * @since
464
	 */
465
	public function default_credit_card_form( $args = array(), $fields = array() ) {
466
467
		if ( $this->supports( 'tev1' ) && '1.0' == get_option( 'wpsc_get_active_theme_engine' ) ) {
468
			// Show 2.0 gateway API table-based code
469
			?>
470
				<table class="wpsc_checkout_table <?php echo wpsc_gateway_form_field_style(); ?>">
471
					<tr>
472
						<td><?php _e( 'Card Number', 'wp-e-commerce' ); ?></td>
473
						<td>
474
							<input type='text' id='card_number' value='' autocomplete="off" />
475
						</td>
476
					</tr>
477
					<tr>
478
						<td><?php _e( 'Expiration Date', 'wp-e-commerce' ); ?></td>
479
						<td>
480
							<input type='text' id='card_expiry_month' value='' autocomplete="off" maxlength='2' size='3' placeholder="<?php esc_attr_e( 'MM', 'wp-e-commerce' ); ?>" />&nbsp;
481
							<input type='text' id='card_expiry_year' value='' autocomplete="off" maxlength='2' size='3' placeholder="<?php esc_attr_e( 'YY', 'wp-e-commerce' ); ?>" />
482
						</td>
483
					</tr>
484
					<tr>
485
						<td><?php _e( 'Card Code', 'wp-e-commerce' ); ?></td>
486
						<td>
487
							<input type='text' id='card_code' value='' autocomplete="off" size='5' maxlength='4' placeholder="<?php esc_attr_e( 'CVC', 'wp-e-commerce' ); ?>" />
488
						</td>
489
					</tr>
490
				</table>
491
			<?php
492
		} else {
493
			$default_args = array(
494
				'fields_have_names' => true, // Some gateways like stripe don't need names as the form is tokenized.
495
			);
496
497
			$args = wp_parse_args( $args, apply_filters( 'wpsc_default_credit_card_form_args', $default_args, $this->setting->gateway_name ) );
498
			$default_fields = array(
499
				'card-number-field' => '<p class="form-row form-row-wide">
500
					<label for="' . esc_attr( $this->setting->gateway_name ) . '-card-number">' . __( 'Card Number', 'wp-e-commerce' ) . ' <span class="required">*</span></label>
501
					<input id="' . esc_attr( $this->setting->gateway_name ) . '-card-number" class="input-text wpsc-credit-card-form-card-number" type="text" maxlength="20" autocomplete="off" placeholder="•••• •••• •••• ••••" />
502
				</p>',
503
				'card-expiry-field' => '<p class="form-row form-row-first">
504
					<label for="' . esc_attr( $this->setting->gateway_name ) . '-card-expiry">' . __( 'Expiration Date (MM/YY)', 'wp-e-commerce' ) . ' <span class="required">*</span></label>
505
					<input id="' . esc_attr( $this->setting->gateway_name ) . '-card-expiry" class="input-text wpsc-credit-card-form-card-expiry" type="text" autocomplete="off" placeholder="' . esc_attr__( 'MM / YY', 'wp-e-commerce' ) . '" />
506
				</p>',
507
				'card-cvc-field' => '<p class="form-row form-row-last">
508
					<label for="' . esc_attr( $this->setting->gateway_name ) . '-card-cvc">' . __( 'Card Code', 'wp-e-commerce' ) . ' <span class="required">*</span></label>
509
					<input id="' . esc_attr( $this->setting->gateway_name ) . '-card-cvc" class="input-text wpsc-credit-card-form-card-cvc" type="text" autocomplete="off" placeholder="' . esc_attr__( 'CVC', 'wp-e-commerce' ) . '" />
510
				</p>'
511
			);
512
			$fields = wp_parse_args( $fields, apply_filters( 'wpsc_default_credit_card_form_fields', $default_fields, $this->setting->gateway_name ) );
513
			?>
514
			<fieldset id="<?php echo $this->setting->gateway_name; ?>-cc-form">
515
				<?php do_action( 'wpsc_default_credit_card_form_start', $this->setting->gateway_name ); ?>
516
				<?php
517
					foreach ( $fields as $field ) {
518
						echo $field;
519
					}
520
				?>
521
				<?php do_action( 'wpsc_default_credit_card_form_end', $this->setting->gateway_name ); ?>
522
				<div class="clear"></div>
523
			</fieldset>
524
		<?php
525
		}
526
	}
527
528
529
	/**
530
	 * Check if a gateway supports a given feature.
531
	 *
532
	 * Gateways should override this to declare support (or lack of support) for a feature.
533
	 *
534
	 * @param string $feature string The name of a feature to test support for.
535
	 * @return bool True if the gateway supports the feature, false otherwise.
536
	 * @since
537
	 */
538
	public function supports( $feature ) {
539
		return apply_filters( 'wpsc_payment_gateway_supports', in_array( $feature, $this->supports ) ? true : false, $feature, $this );
540
	}
541
542
	/**
543
	 * If There are no payment fields show the description if set.
544
	 * Override this in your gateway if you have some.
545
	 */
546
	public function payment_fields() {
547
		if ( $this->supports( 'default_credit_card_form' ) ) {
548
			$this->default_credit_card_form();
549
		}
550
	}
551
552
	/**
553
	 * Return the title of the payment gateway. For this to work, $this->title must
554
	 * be set already.
555
	 *
556
	 * It is recommended that the payment gateway title be properly localized using __()
557
	 *
558
	 * @access public
559
	 * @since 3.9
560
	 * @see __()
561
	 *
562
	 * @return string
563
	 */
564
	public function get_title() {
565
		$title = empty( $this->title ) ? '' : $this->title;
566
		return apply_filters( 'wpsc_payment_gateway_title', $title );
567
	}
568
569
	/**
570
	 * Display the payment gateway settings form as seen in WP eCommerce Settings area.
571
	 * This method must be overridden by subclasses.
572
	 *
573
	 * @abstract
574
	 * @access public
575
	 * @since 3.9
576
	 *
577
	 * @return void
578
	 */
579
	public function setup_form() {
580
		$checkout_field_types = array(
581
			'billing'  => __( 'Billing Fields' , 'wp-e-commerce' ),
582
			'shipping' => __( 'Shipping Fields', 'wp-e-commerce' ),
583
		);
584
585
		$fields = array(
586
			'firstname' => __( 'First Name' , 'wp-e-commerce' ),
587
			'lastname'  => __( 'Last Name'  , 'wp-e-commerce' ),
588
			'address'   => __( 'Address'    , 'wp-e-commerce' ),
589
			'city'      => __( 'City'       , 'wp-e-commerce' ),
590
			'state'     => __( 'State'      , 'wp-e-commerce' ),
591
			'country'   => __( 'Country'    , 'wp-e-commerce' ),
592
			'postcode'  => __( 'Postal Code', 'wp-e-commerce' ),
593
		);
594
595
		$checkout_form = WPSC_Checkout_Form::get();
596
597
		foreach ( $checkout_field_types as $field_type => $title ): ?>
598
			<tr>
599
				<td colspan="2">
600
					<h4><?php echo esc_html( $title ); ?></h4>
601
				</td>
602
			</tr>
603
			<?php foreach ( $fields as $field_name => $field_title ):
604
				$unique_name = $field_type . $field_name;
605
				$selected_id = $this->setting->get( "checkout_field_{$unique_name}", $checkout_form->get_field_id_by_unique_name( $unique_name ) );
606
			?>
607
				<tr>
608
					<td>
609
						<label for="manual-form-<?php echo esc_attr( $unique_name ); ?>"><?php echo esc_html( $field_title ); ?></label>
610
					</td>
611
					<td>
612
						<select name="<?php echo $this->setting->get_field_name( "checkout_field_{$unique_name}" ); ?>" id="manual-form-<?php echo esc_attr( $unique_name ); ?>">
613
							<?php $checkout_form->field_drop_down_options( $selected_id ); ?>
614
						</select>
615
					</td>
616
				</tr>
617
			<?php endforeach;
618
		endforeach;
619
	}
620
621
	/**
622
	 * Process and send payment details to payment gateways
623
	 *
624
	 * @abstract
625
	 * @access public
626
	 * @since 3.9
627
	 *
628
	 * @return void
629
	 */
630
	abstract public function process();
631
632
	/**
633
	 * Returns the URL to the logo of the payment gateway (or any representative image).
634
	 *
635
	 * @access public
636
	 * @since 3.9
637
	 *
638
	 * @return mixed False if there's no image defined.
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use boolean.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
639
	 */
640
	public function get_image_url() {
641
		return false;
642
	}
643
644
	/**
645
	 * Returns the HTML of the logo of the payment gateway.
646
	 *
647
	 * @access public
648
	 * @since 3.9
649
	 *
650
	 * @return mixed False if there's no html defined.
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use boolean.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
651
	 */
652
	public function get_mark_html() {
653
		return false;
654
	}
655
656
	public function set_purchase_log( &$purchase_log ) {
657
		$this->purchase_log = &$purchase_log;
658
		$this->checkout_data = new WPSC_Checkout_Form_Data( $purchase_log->get( 'id' ) );
659
	}
660
661
	public function get_currency_code() {
662
		if ( ! $this->currency_code ) {
663
			$country = new WPSC_Country( get_option( 'currency_type' ) );
664
			$currency = $country->get( 'currency_code' );
665
		} else {
666
			$currency = $this->currency_code;
667
		}
668
669
		return $currency;
670
	}
671
672
	public function get_notification_url() {
673
		return add_query_arg( 'wpsc_action', 'gateway_notification', (get_option( 'siteurl' ) . "/index.php" ) );
674
	}
675
676
	public function get_transaction_results_url() {
677
		return get_option( 'transact_url' );
678
	}
679
680
	public function get_shopping_cart_url() {
681
		return get_option( 'shopping_cart_url' );
682
	}
683
684
	public function get_shopping_cart_payment_url() {
685
686
		$te = get_option( 'wpsc_get_active_theme_engine', '1.0' );
687
688
		return '1.0' !== $te ? wpsc_get_checkout_url( 'shipping-and-billing' ) : get_option( 'shopping_cart_url' );
689
	}
690
691
	public function get_products_page_url() {
692
		return get_option( 'product_list_url' );
693
	}
694
695
	public function go_to_transaction_results() {
696
		//Now to do actions once the payment has been attempted
697
		switch ( $this->purchase_log->get( 'processed' ) ) {
698
			case 3:
699
				// payment worked
700
				do_action('wpsc_payment_successful');
701
				break;
702
			case 1:
703
				// payment declined
704
				do_action('wpsc_payment_failed');
705
				break;
706
			case 2:
707
				// something happened with the payment
708
				do_action('wpsc_payment_incomplete');
709
				break;
710
		}
711
712
		$transaction_url_with_sessionid = add_query_arg( 'sessionid', $this->purchase_log->get( 'sessionid' ), get_option( 'transact_url' ) );
713
		wp_redirect( $transaction_url_with_sessionid );
714
715
		exit();
716
	}
717
718
	/**
719
	 * Payment gateway constructor.
720
	 *
721
	 * Use WPSC_Payment_Gateways::get( $gateway_name ) instead.
722
	 *
723
	 * @access public
724
	 * @return WPSC_Payment_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...
725
	 */
726
	public function __construct() {
727
728
		$this->setting = new WPSC_Payment_Gateway_Setting( get_class( $this ) );
729
	}
730
731
	/**
732
	 * Gateway initialization function.
733
	 *
734
	 * You should use this function for hooks with actions and filters that are required by the gateway.
735
	 *
736
	 * @access public
737
	 * @since 4.0
738
	 *
739
	 * @return void
740
	 */
741
	public function init() {}
742
}
743
744
class WPSC_Payment_Gateway_Setting {
745
	/**
746
	 * Contain settings of the payment gateway
747
	 *
748
	 * @access private
749
	 * @var array
750
	 */
751
	private $settings;
752
753
	/**
754
	 * Contain unsaved settings of the payment gateway. This is useful when the saving of the settings
755
	 * are deferred.
756
	 *
757
	 * @access private
758
	 * @var array
759
	 */
760
	private $unsaved_settings = array();
761
762
	/**
763
	 * Name of the gateway
764
	 *
765
	 * @access private
766
	 * @var string
767
	 */
768
	public $gateway_name = '';
769
770
	/**
771
	 * Name of the option containing all the settings in WP DB
772
	 *
773
	 * @access private
774
	 * @var string
775
	 */
776
	private $option_name = '';
777
778
	/**
779
	 * Save settings when the payment gateway setup form is updated
780
	 *
781
	 * @access public
782
	 * @static
783
	 * @return void
784
	 *
785
	 * @since 3.9
786
	 */
787
	public static function action_update_payment_gateway_settings() {
788
		if ( ! empty( $_POST['wpsc_payment_gateway_settings'] ) )
789
			foreach ( $_POST['wpsc_payment_gateway_settings'] as $gateway_name => $new_settings ) {
790
				$settings = new WPSC_Payment_Gateway_Setting( $gateway_name );
791
				$settings->merge( $new_settings );
792
			}
793
	}
794
795
	/**
796
	 * Constructor
797
	 *
798
	 * @access public
799
	 *
800
	 * @param string $gateway_name Name of the gateway
0 ignored issues
show
Documentation introduced by
There is no parameter named $gateway_name. Did you maybe mean $gateway_name_or_class?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
801
	 * @return WPSC_Payment_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...
802
	 */
803
	public function __construct( $gateway_name_or_class ) {
804
		$name = str_replace( 'wpsc_payment_gateway_', '', strtolower( $gateway_name_or_class ) );
805
		$name = str_replace( array( ' ', '-' ), '_', $name );
806
		$this->gateway_name = $name;
807
		$this->option_name = 'wpsc_payment_gateway_' . $this->gateway_name;
808
	}
809
810
	/**
811
	 * Lazy load the settings from the DB when necessary
812
	 *
813
	 * @access private
814
	 * @return void
815
	 */
816
	private function lazy_load() {
817
		if ( is_null( $this->settings ) ) {
818
			$this->settings = get_option( $this->option_name, array() );
819
		}
820
	}
821
822
	/**
823
	 * Get the value of a setting
824
	 *
825
	 * @param string $setting
826
	 * @return mixed
827
	 * @since 3.9
828
	 */
829
	public function get( $setting, $default = false ) {
830
		$this->lazy_load();
831
		return isset( $this->settings[ $setting ] ) ? $this->settings[ $setting ] : $default;
832
	}
833
834
	/**
835
	 * Set the value of a setting
836
	 *
837
	 * @param string $setting
838
	 * @param mixed $value
839
	 * @param bool $defer True if you want to defer saving the settings array to the database
840
	 * @return void
841
	 * @since 3.9
842
	 */
843
	public function set( $setting, $value, $defer = false ) {
844
		$this->lazy_load();
845
		$this->unsaved_settings[ $setting ] = $value;
846
		if ( ! $defer ) {
847
			$this->save();
848
		}
849
	}
850
851
	/**
852
	 * Overwrite current settings with an array of settings
853
	 *
854
	 * @access public
855
	 * @param string $settings Settings that you want to overwrite upon current settings
856
	 * @param string $defer Optional. Defaults to false. True if you want to defer
0 ignored issues
show
Documentation introduced by
Should the type for parameter $defer not be false|string?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
857
	 *                      saving the settings array to the database.
858
	 * @return void
859
	 * @since 3.9
860
	 */
861
	public function merge( $settings, $defer = false ) {
862
		$this->lazy_load();
863
		$this->unsaved_settings = array_merge( $this->unsaved_settings, $settings );
864
		if ( ! $defer ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $defer of type false|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
865
			$this->save();
866
		}
867
	}
868
869
	/**
870
	 * Returns the field name of the setting on payment gateway setup form
871
	 *
872
	 * @access public
873
	 * @param string $setting Setting names
874
	 * @return string
875
	 * @since 3.9
876
	 */
877
	public function get_field_name( $setting ) {
878
		return "wpsc_payment_gateway_settings[{$this->gateway_name}][{$setting}]";
879
	}
880
881
	/**
882
	 * Save the settings into the database
883
	 *
884
	 * @return void
885
	 * @since 3.9
886
	 */
887
	public function save() {
888
		$this->settings = array_merge( $this->settings, $this->unsaved_settings );
889
		$this->unsaved_settings = array();
890
		update_option( $this->option_name, $this->settings );
891
	}
892
}
893
894
add_action( 'wpsc_loaded', array( 'WPSC_Payment_Gateways', 'init' ) );
895