Completed
Pull Request — master (#2066)
by
unknown
08:12
created

WPSC_Payment_Gateway::get_mark_html()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 3
rs 10
cc 1
eloc 2
nc 1
nop 0
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
			}
0 ignored issues
show
introduced by
Blank line found after control structure
Loading history...
186
187
		}
188
	}
189
190
	/**
191
	 * Register a file as a payment gateway module.
192
	 *
193
	 * The payment gateway inside the file must be defined as a subclass of WPSC_Payment_Gateway.
194
	 *
195
	 * The file name should be lowercase, using hyphens or underscores between words
196
	 * instead of spaces. The class name must have "WPSC_Payment_Gateway_" as the
197
	 * prefix, followed by the file name, in which words are capitalized and connected
198
	 * by underscore.
199
	 *
200
	 * For example, if the file name is "paypal-pro.php", then the class name inside
201
	 * the file must be WPSC_Payment_Gateway_Paypal_Pro.
202
	 *
203
	 * @access public
204
	 * @since 3.9
205
	 * @see WPSC_Payment_Gateways::register_dir()
206
	 *
207
	 * @param string $file Absolute path to the file containing the payment gateway
208
	 * class
209
	 * @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...
210
	 * a valid class. Otherwise, a WP_Error object is returned.
211
	 */
212
	public static function register_file( $file ) {
213
214
		if ( empty( self::$payment_gateway_cache ) ) {
215
			self::$payment_gateway_cache = get_option( 'wpsc_payment_gateway_cache', array() );
216
		}
217
218
		$filename = basename( $file, '.php' );
219
220
		// payment gateway already exists in cache
221
		if ( isset( self::$payment_gateway_cache[ $filename ] ) ) {
222
			self::$gateways[ $filename ] = self::$payment_gateway_cache[ $filename ];
223
		}
224
225
		// if payment gateway is not in cache, load metadata
226
		$classname = ucwords( str_replace( '-', ' ', $filename ) );
227
		$classname = 'WPSC_Payment_Gateway_' . str_replace( ' ', '_', $classname );
228
229
		if ( file_exists( $file ) ) {
230
			require_once $file;
231
		}
232
233
		if ( is_callable( array( $classname, 'load' ) ) && ! call_user_func( array( $classname, 'load' ) ) ) {
234
235
			self::unregister_file( $filename );
236
237
			$error = new WP_Error( 'wpsc-payment', __( 'Error', 'wp-e-commerce' ) );
238
239
			return $error;
240
		}
241
242
		$meta = array(
243
			'class'        => $classname,
244
			'path'         => $file,
245
			'internalname' => $filename, // compat with older API
246
		);
247
248
		$gateway = self::get( $filename, $meta );
249
250
		if ( is_wp_error( $gateway ) ) {
251
			return $gateway;
252
		}
253
254
		$meta['name']  = $gateway->get_title();
255
		$meta['image'] = $gateway->get_image_url();
256
		$meta['mark']  = $gateway->get_mark_html();
257
258
		self::$gateways[ $filename ] = $meta;
259
260
		return true;
261
	}
262
263
	public static function unregister_file( $filename ) {
264
		if ( isset( self::$gateways[ $filename ] ) ) {
265
			unset( self::$gateways[ $filename ] );
266
		}
267
	}
268
269
	/**
270
	 * Updates the payment gateway cache when it's changed.
271
	 *
272
	 * This function is hooked into WordPress' wp_loaded action
273
	 *
274
	 * @access public
275
	 * @static
276
	 * @since 3.9
277
	 *
278
	 * @return void
279
	 */
280
	public static function action_save_payment_gateway_cache() {
281
		if ( self::$payment_gateway_cache != self::$gateways ) {
282
			update_option( 'wpsc_payment_gateway_cache', self::$gateways );
283
		}
284
	}
285
286
	/**
287
	 * Flush the payment gateways cache.
288
	 *
289
	 * @access public
290
	 * @static
291
	 * @since 3.9
292
	 * @return void
293
	 */
294
	public static function flush_cache() {
295
		delete_option( 'wpsc_payment_gateway_cache' );
296
	}
297
298
	/**
299
	 * Gets metadata of a certain payment gateway. This is better than calling WPSC_Payment_Gateways->get( $gateway_name )->get_title()
300
	 * and the likes of it, since it doesn't require the gateway itself to be loaded.
301
	 *
302
	 * @access public
303
	 * @static
304
	 * @since 3.9
305
	 *
306
	 * @param string $gateway
307
	 * @return mixed Array containing the metadata. If the gateway is not registered,
308
	 *               returns false.
309
	 */
310
	public static function get_meta( $gateway ) {
311
		return isset( self::$gateways[$gateway] ) ? self::$gateways[$gateway] : false;
312
	}
313
314
	/**
315
	 *
316
	 * Return an array containing registered gateway names.
317
	 *
318
	 * @access public
319
	 * @since 3.9
320
	 *
321
	 * @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...
322
	 */
323
	public static function get_gateways() {
324
		return array_keys( self::$gateways );
325
	}
326
327
	/**
328
	 *
329
	 * Return an array containing active gateway names.
330
	 *
331
	 * @access public
332
	 * @since 3.9
333
	 *
334
	 * @return array
335
	 */
336
	public static function get_active_gateways() {
337
		if ( empty( self::$active_gateways ) ) {
338
			$selected_gateways = get_option( 'custom_gateway_options', array() );
339
			$registered_gateways = self::get_gateways();
340
			self::$active_gateways = array_intersect( $selected_gateways, $registered_gateways );
341
		}
342
343
		return apply_filters( 'wpsc_get_active_gateways', array_values( self::$active_gateways ) );
344
	}
345
346
	/**
347
	 * Initialize the Active Gateways
348
	 *
349
	 * @access public
350
	 * @since 4.0
351
	 *
352
	 * @return void
353
	 */
354
	public static function initialize_gateways() {
355
		$active_gateways = self::get_active_gateways();
356
357
		foreach( $active_gateways as $gateway_id ) {
358
			$gateway = self::get( $gateway_id );
359
			$gateway->init();
360
		}
361
	}
362
363
	/**
364
	 * Returns all known currencies without fractions.
365
	 *
366
	 * Our internal list has not been updated in some time, so returning a filterable list
367
	 * for ever-changing economies and currencies should prove helpful.
368
	 *
369
	 * @link http://www.currency-iso.org/dam/downloads/table_a1.xml
370
	 *
371
	 * @since  4.0
372
	 *
373
	 * @return array Currency ISO codes that do not use fractions.
374
	 */
375
	public static function currencies_without_fractions() {
376
377
		$currencies = array(
378
			'JPY',
379
			'HUF',
380
			'VND',
381
			'BYR',
382
			'XOF',
383
			'BIF',
384
			'XAF',
385
			'CLP',
386
			'KMF',
387
			'DJF',
388
			'XPF',
389
			'GNF',
390
			'ISK',
391
			'GNF',
392
			'KRW',
393
			'PYG',
394
			'RWF',
395
			'UGX',
396
			'UYI',
397
			'VUV',
398
		);
399
400
		return (array) apply_filters( 'wpsc_currencies_without_fractions', $currencies );
401
	}
402
403
	/**
404
	 * Gets an array of countries in the EU.
405
	 *
406
	 * MC (monaco) and IM (Isle of Man, part of UK) also use VAT.
407
	 *
408
	 * @since  4.0
409
	 * @param  $type Type of countries to retrieve. Blank for EU member countries. eu_vat for EU VAT countries.
410
	 * @return string[]
411
	 */
412
	public function get_european_union_countries( $type = '' ) {
413
		$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' );
414
415
		if ( 'eu_vat' === $type ) {
416
			$countries[] = 'MC';
417
			$countries[] = 'IM';
418
		}
419
420
		return $countries;
421
	}
422
423
	/**
424
	 * No instantiation for this class
425
	 *
426
	 * @access private
427
	 * @since 3.9
428
	 *
429
	 */
430
	private function __construct() {}
431
}
432
433
abstract class WPSC_Payment_Gateway {
434
435
	/**
436
	 * Object that allows manipulation of payment gateway settings in a consistent
437
	 * manner
438
	 *
439
	 * @access public
440
	 * @var WPSC_Payment_Gateway_Setting
441
	 */
442
	 
443
	public $setting;
444
445
	public $purchase_log;
446
447
	public $checkout_data;
448
449
	public $currency_code;
450
451
	public $title;
452
453
	/**
454
	 * Supported features such as 'default_credit_card_form', 'refunds'.
455
	 * @var array
456
	 */
457
	public $supports = array();
458
459
	/**
460
	 * Display default credit card form.
461
	 *
462
	 * @param  array $args
463
	 * @param  array $fields
464
	 * @since
465
	 */
466
	public function default_credit_card_form( $args = array(), $fields = array() ) {
467
		
468
		if ( $this->supports( 'tev1' ) && '1.0' == get_option( 'wpsc_get_active_theme_engine' ) ) {
469
			// Show 2.0 gateway API table-based code
470
			?>
471
				<table class="wpsc_checkout_table <?php echo wpsc_gateway_form_field_style(); ?>">
472
					<tr>
473
						<td><?php _e( 'Card Number', 'wp-e-commerce' ); ?></td>
474
						<td>
475
							<input type='text' id='card_number' value='' autocomplete="off" />
476
						</td>
477
					</tr>
478
					<tr>
479
						<td><?php _e( 'Expiration Date', 'wp-e-commerce' ); ?></td>
480
						<td>
481
							<input type='text' id='card_expiry_month' value='' autocomplete="off" maxlength='2' size='3' placeholder="<?php esc_attr_e( 'MM', 'wp-e-commerce' ); ?>" />&nbsp;
482
							<input type='text' id='card_expiry_year' value='' autocomplete="off" maxlength='2' size='3' placeholder="<?php esc_attr_e( 'YY', 'wp-e-commerce' ); ?>" />
483
						</td>
484
					</tr>
485
					<tr>
486
						<td><?php _e( 'Card Code', 'wp-e-commerce' ); ?></td>
487
						<td>
488
							<input type='text' id='card_code' value='' autocomplete="off" size='5' maxlength='4' placeholder="<?php esc_attr_e( 'CVC', 'wp-e-commerce' ); ?>" />
489
						</td>
490
					</tr>					
491
				</table>			
492
			<?php
493
		} else {
494
			$default_args = array(
495
				'fields_have_names' => true, // Some gateways like stripe don't need names as the form is tokenized.
496
			);
497
			
498
			$args = wp_parse_args( $args, apply_filters( 'wpsc_default_credit_card_form_args', $default_args, $this->setting->gateway_name ) );
499
			$default_fields = array(
500
				'card-number-field' => '<p class="form-row form-row-wide">
501
					<label for="' . esc_attr( $this->setting->gateway_name ) . '-card-number">' . __( 'Card Number', 'wp-e-commerce' ) . ' <span class="required">*</span></label>
502
					<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="•••• •••• •••• ••••" />
503
				</p>',
504
				'card-expiry-field' => '<p class="form-row form-row-first">
505
					<label for="' . esc_attr( $this->setting->gateway_name ) . '-card-expiry">' . __( 'Expiration Date (MM/YY)', 'wp-e-commerce' ) . ' <span class="required">*</span></label>
506
					<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' ) . '" />
507
				</p>',
508
				'card-cvc-field' => '<p class="form-row form-row-last">
509
					<label for="' . esc_attr( $this->setting->gateway_name ) . '-card-cvc">' . __( 'Card Code', 'wp-e-commerce' ) . ' <span class="required">*</span></label>
510
					<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' ) . '" />
511
				</p>'
512
			);
513
			$fields = wp_parse_args( $fields, apply_filters( 'wpsc_default_credit_card_form_fields', $default_fields, $this->setting->gateway_name ) );
514
			?>
515
			<fieldset id="<?php echo $this->setting->gateway_name; ?>-cc-form">
516
				<?php do_action( 'wpsc_default_credit_card_form_start', $this->setting->gateway_name ); ?>
517
				<?php
518
					foreach ( $fields as $field ) {
519
						echo $field;
520
					}
521
				?>
522
				<?php do_action( 'wpsc_default_credit_card_form_end', $this->setting->gateway_name ); ?>
523
				<div class="clear"></div>
524
			</fieldset>
525
		<?php
526
		}
527
	}
528
	
529
	
530
	/**
531
	 * Check if a gateway supports a given feature.
532
	 *
533
	 * Gateways should override this to declare support (or lack of support) for a feature.
534
	 *
535
	 * @param string $feature string The name of a feature to test support for.
536
	 * @return bool True if the gateway supports the feature, false otherwise.
537
	 * @since
538
	 */
539
	public function supports( $feature ) {
540
		return apply_filters( 'wpsc_payment_gateway_supports', in_array( $feature, $this->supports ) ? true : false, $feature, $this );
541
	}
542
	
543
	/**
544
	 * If There are no payment fields show the description if set.
545
	 * Override this in your gateway if you have some.
546
	 */
547
	public function payment_fields() {
548
		if ( $this->supports( 'default_credit_card_form' ) ) {
549
			$this->default_credit_card_form();
550
		}
551
	}
552
	
553
	/**
554
	 * Return the title of the payment gateway. For this to work, $this->title must
555
	 * be set already.
556
	 *
557
	 * It is recommended that the payment gateway title be properly localized using __()
558
	 *
559
	 * @access public
560
	 * @since 3.9
561
	 * @see __()
562
	 *
563
	 * @return string
564
	 */
565
	public function get_title() {
566
		$title = empty( $this->title ) ? '' : $this->title;
567
		return apply_filters( 'wpsc_payment_gateway_title', $title );
568
	}
569
570
	/**
571
	 * Display the payment gateway settings form as seen in WP eCommerce Settings area.
572
	 * This method must be overridden by subclasses.
573
	 *
574
	 * @abstract
575
	 * @access public
576
	 * @since 3.9
577
	 *
578
	 * @return void
579
	 */
580
	public function setup_form() {
581
		$checkout_field_types = array(
582
			'billing'  => __( 'Billing Fields' , 'wp-e-commerce' ),
583
			'shipping' => __( 'Shipping Fields', 'wp-e-commerce' ),
584
		);
585
586
		$fields = array(
587
			'firstname' => __( 'First Name' , 'wp-e-commerce' ),
588
			'lastname'  => __( 'Last Name'  , 'wp-e-commerce' ),
589
			'address'   => __( 'Address'    , 'wp-e-commerce' ),
590
			'city'      => __( 'City'       , 'wp-e-commerce' ),
591
			'state'     => __( 'State'      , 'wp-e-commerce' ),
592
			'country'   => __( 'Country'    , 'wp-e-commerce' ),
593
			'postcode'  => __( 'Postal Code', 'wp-e-commerce' ),
594
		);
595
596
		$checkout_form = WPSC_Checkout_Form::get();
597
598
		foreach ( $checkout_field_types as $field_type => $title ): ?>
599
			<tr>
600
				<td colspan="2">
601
					<h4><?php echo esc_html( $title ); ?></h4>
602
				</td>
603
			</tr>
604
			<?php foreach ( $fields as $field_name => $field_title ):
605
				$unique_name = $field_type . $field_name;
606
				$selected_id = $this->setting->get( "checkout_field_{$unique_name}", $checkout_form->get_field_id_by_unique_name( $unique_name ) );
607
			?>
608
				<tr>
609
					<td>
610
						<label for="manual-form-<?php echo esc_attr( $unique_name ); ?>"><?php echo esc_html( $field_title ); ?></label>
611
					</td>
612
					<td>
613
						<select name="<?php echo $this->setting->get_field_name( "checkout_field_{$unique_name}" ); ?>" id="manual-form-<?php echo esc_attr( $unique_name ); ?>">
614
							<?php $checkout_form->field_drop_down_options( $selected_id ); ?>
615
						</select>
616
					</td>
617
				</tr>
618
			<?php endforeach;
619
		endforeach;
620
	}
621
622
	/**
623
	 * Process and send payment details to payment gateways
624
	 *
625
	 * @abstract
626
	 * @access public
627
	 * @since 3.9
628
	 *
629
	 * @return void
630
	 */
631
	abstract public function process();
632
633
	/**
634
	 * Returns the URL to the logo of the payment gateway (or any representative image).
635
	 *
636
	 * @access public
637
	 * @since 3.9
638
	 *
639
	 * @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...
640
	 */
641
	public function get_image_url() {
642
		return false;
643
	}
644
645
	/**
646
	 * Returns the HTML of the logo of the payment gateway.
647
	 *
648
	 * @access public
649
	 * @since 3.9
650
	 *
651
	 * @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...
652
	 */
653
	public function get_mark_html() {
654
		return false;
655
	}
656
657
	public function set_purchase_log( &$purchase_log ) {
658
		$this->purchase_log = &$purchase_log;
659
		$this->checkout_data = new WPSC_Checkout_Form_Data( $purchase_log->get( 'id' ) );
660
	}
661
662
	public function get_currency_code() {
663
		if ( ! $this->currency_code ) {
664
			$country = new WPSC_Country( get_option( 'currency_type' ) );
665
			$currency = $country->get( 'currency_code' );
666
		} else {
667
			$currency = $this->currency_code;
668
		}
669
670
		return $currency;
671
	}
672
673
	public function get_notification_url() {
674
		return add_query_arg( 'wpsc_action', 'gateway_notification', (get_option( 'siteurl' ) . "/index.php" ) );
675
	}
676
677
	public function get_transaction_results_url() {
678
		return get_option( 'transact_url' );
679
	}
680
681
	public function get_shopping_cart_url() {
682
		return get_option( 'shopping_cart_url' );
683
	}
684
685
	public function get_shopping_cart_payment_url() {
686
687
		$te = get_option( 'wpsc_get_active_theme_engine', '1.0' );
688
689
		return '1.0' !== $te ? wpsc_get_checkout_url( 'shipping-and-billing' ) : get_option( 'shopping_cart_url' );
690
	}
691
692
	public function get_products_page_url() {
693
		return get_option( 'product_list_url' );
694
	}
695
696
	public function go_to_transaction_results() {
697
		//Now to do actions once the payment has been attempted
698
		switch ( $this->purchase_log->get( 'processed' ) ) {
699
			case 3:
700
				// payment worked
701
				do_action('wpsc_payment_successful');
702
				break;
703
			case 1:
704
				// payment declined
705
				do_action('wpsc_payment_failed');
706
				break;
707
			case 2:
708
				// something happened with the payment
709
				do_action('wpsc_payment_incomplete');
710
				break;
711
		}
712
713
		$transaction_url_with_sessionid = add_query_arg( 'sessionid', $this->purchase_log->get( 'sessionid' ), get_option( 'transact_url' ) );
714
		wp_redirect( $transaction_url_with_sessionid );
715
716
		exit();
717
	}
718
719
	/**
720
	 * Payment gateway constructor.
721
	 *
722
	 * Use WPSC_Payment_Gateways::get( $gateway_name ) instead.
723
	 *
724
	 * @access public
725
	 * @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...
726
	 */
727
	public function __construct() {
728
729
		$this->setting = new WPSC_Payment_Gateway_Setting( get_class( $this ) );
730
	}
731
732
	/**
733
	 * Gateway initialization function.
734
	 *
735
	 * You should use this function for hooks with actions and filters that are required by the gateway.
736
	 *
737
	 * @access public
738
	 * @since 4.0
739
	 *
740
	 * @return void
741
	 */
742
	public function init() {}
743
}
744
745
class WPSC_Payment_Gateway_Setting {
746
	/**
747
	 * Contain settings of the payment gateway
748
	 *
749
	 * @access private
750
	 * @var array
751
	 */
752
	private $settings;
753
754
	/**
755
	 * Contain unsaved settings of the payment gateway. This is useful when the saving of the settings
756
	 * are deferred.
757
	 *
758
	 * @access private
759
	 * @var array
760
	 */
761
	private $unsaved_settings = array();
762
763
	/**
764
	 * Name of the gateway
765
	 *
766
	 * @access private
767
	 * @var string
768
	 */
769
	public $gateway_name = '';
770
771
	/**
772
	 * Name of the option containing all the settings in WP DB
773
	 *
774
	 * @access private
775
	 * @var string
776
	 */
777
	private $option_name = '';
778
779
	/**
780
	 * Save settings when the payment gateway setup form is updated
781
	 *
782
	 * @access public
783
	 * @static
784
	 * @return void
785
	 *
786
	 * @since 3.9
787
	 */
788
	public static function action_update_payment_gateway_settings() {
789
		if ( ! empty( $_POST['wpsc_payment_gateway_settings'] ) )
790
			foreach ( $_POST['wpsc_payment_gateway_settings'] as $gateway_name => $new_settings ) {
791
				$settings = new WPSC_Payment_Gateway_Setting( $gateway_name );
792
				$settings->merge( $new_settings );
793
			}
794
	}
795
796
	/**
797
	 * Constructor
798
	 *
799
	 * @access public
800
	 *
801
	 * @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...
802
	 * @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...
803
	 */
804
	public function __construct( $gateway_name_or_class ) {
805
		$name = str_replace( 'wpsc_payment_gateway_', '', strtolower( $gateway_name_or_class ) );
806
		$name = str_replace( array( ' ', '-' ), '_', $name );
807
		$this->gateway_name = $name;
808
		$this->option_name = 'wpsc_payment_gateway_' . $this->gateway_name;
809
	}
810
811
	/**
812
	 * Lazy load the settings from the DB when necessary
813
	 *
814
	 * @access private
815
	 * @return void
816
	 */
817
	private function lazy_load() {
818
		if ( is_null( $this->settings ) ) {
819
			$this->settings = get_option( $this->option_name, array() );
820
		}
821
	}
822
823
	/**
824
	 * Get the value of a setting
825
	 *
826
	 * @param string $setting
827
	 * @return mixed
828
	 * @since 3.9
829
	 */
830
	public function get( $setting, $default = false ) {
831
		$this->lazy_load();
832
		return isset( $this->settings[ $setting ] ) ? $this->settings[ $setting ] : $default;
833
	}
834
835
	/**
836
	 * Set the value of a setting
837
	 *
838
	 * @param string $setting
839
	 * @param mixed $value
840
	 * @param bool $defer True if you want to defer saving the settings array to the database
841
	 * @return void
842
	 * @since 3.9
843
	 */
844
	public function set( $setting, $value, $defer = false ) {
845
		$this->lazy_load();
846
		$this->unsaved_settings[ $setting ] = $value;
847
		if ( ! $defer ) {
848
			$this->save();
849
		}
850
	}
851
852
	/**
853
	 * Overwrite current settings with an array of settings
854
	 *
855
	 * @access public
856
	 * @param string $settings Settings that you want to overwrite upon current settings
857
	 * @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...
858
	 *                      saving the settings array to the database.
859
	 * @return void
860
	 * @since 3.9
861
	 */
862
	public function merge( $settings, $defer = false ) {
863
		$this->lazy_load();
864
		$this->unsaved_settings = array_merge( $this->unsaved_settings, $settings );
865
		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...
866
			$this->save();
867
		}
868
	}
869
870
	/**
871
	 * Returns the field name of the setting on payment gateway setup form
872
	 *
873
	 * @access public
874
	 * @param string $setting Setting names
875
	 * @return string
876
	 * @since 3.9
877
	 */
878
	public function get_field_name( $setting ) {
879
		return "wpsc_payment_gateway_settings[{$this->gateway_name}][{$setting}]";
880
	}
881
882
	/**
883
	 * Save the settings into the database
884
	 *
885
	 * @return void
886
	 * @since 3.9
887
	 */
888
	public function save() {
889
		$this->settings = array_merge( $this->settings, $this->unsaved_settings );
890
		$this->unsaved_settings = array();
891
		update_option( $this->option_name, $this->settings );
892
	}
893
}
894
895
add_action( 'wpsc_loaded', array( 'WPSC_Payment_Gateways', 'init' ) );