Passed
Push — develop ( de1fae...b75ed1 )
by Reüel
04:29
created

Plugin::datetime_format()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Plugin
4
 *
5
 * @author    Pronamic <[email protected]>
6
 * @copyright 2005-2018 Pronamic
7
 * @license   GPL-3.0-or-later
8
 * @package   Pronamic\WordPress\Pay
9
 */
10
11
namespace Pronamic\WordPress\Pay;
12
13
use Pronamic\WordPress\Pay\Core\Gateway;
14
use Pronamic\WordPress\Pay\Core\PaymentMethods;
15
use Pronamic\WordPress\Pay\Core\Statuses;
16
use Pronamic\WordPress\Pay\Payments\Payment;
17
use Pronamic\WordPress\Pay\Payments\PaymentDataInterface;
18
use Pronamic\WordPress\Pay\Payments\PaymentPostType;
19
use Pronamic\WordPress\Pay\Payments\StatusChecker;
20
use Pronamic\WordPress\Pay\Subscriptions\SubscriptionPostType;
21
use WP_Query;
22
23
/**
24
 * Title: WordPress iDEAL plugin
25
 *
26
 * @author Remco Tolsma
27
 * @version 4.5.3
28
 * @since 1.0.0
29
 */
30
class Plugin {
31
	/**
32
	 * Version.
33
	 *
34
	 * @var string
35
	 */
36
	private $version = '5.0.0';
37
38
	/**
39
	 * The root file of this WordPress plugin
40
	 *
41
	 * @var string
42
	 */
43
	public static $file;
44
45
	/**
46
	 * The plugin dirname
47
	 *
48
	 * @var string
49
	 */
50
	public static $dirname;
51
52
	/**
53
	 * The timezone
54
	 *
55
	 * @var string
56
	 */
57
	const TIMEZONE = 'UTC';
58
59
	/**
60
	 * Instance.
61
	 *
62
	 * @var Plugin
63
	 */
64
	protected static $instance = null;
65
66
	/**
67
	 * Instance.
68
	 *
69
	 * @param string $file The plugin file.
70
	 */
71
	public static function instance( $file = null ) {
72
		if ( is_null( self::$instance ) ) {
73
			self::$instance = new self();
74
75
			// Backward compatibility.
76
			self::$file    = $file;
77
			self::$dirname = dirname( $file );
78
		}
79
80
		return self::$instance;
81
	}
82
83
	/**
84
	 * Construct and initialize an Pronamic Pay plugin object
85
	 */
86
	public function __construct() {
87
		// Bootstrap the add-ons.
88
		Extensions\Charitable\Extension::bootstrap();
89
		Extensions\Give\Extension::bootstrap();
90
		Extensions\WooCommerce\Extension::bootstrap();
91
		Extensions\GravityForms\Extension::bootstrap();
92
		Extensions\Shopp\Extension::bootstrap();
93
		Extensions\Jigoshop\Extension::bootstrap();
94
		Extensions\WPeCommerce\Extension::bootstrap();
95
		Extensions\ClassiPress\Extension::bootstrap();
96
		Extensions\EventEspressoLegacy\Extension::bootstrap();
97
		Extensions\EventEspresso\Extension::bootstrap();
98
		Extensions\AppThemes\Extension::bootstrap();
99
		Extensions\S2Member\Extension::bootstrap();
100
		Extensions\Membership\Extension::bootstrap();
101
		Extensions\EasyDigitalDownloads\Extension::bootstrap();
102
		Extensions\IThemesExchange\Extension::bootstrap();
103
		Extensions\MemberPress\Extension::bootstrap();
104
		Extensions\FormidableForms\Extension::bootstrap();
105
		Extensions\RestrictContentPro\Extension::bootstrap();
106
107
		// Settings.
108
		$this->settings = new Settings( $this );
0 ignored issues
show
Bug Best Practice introduced by
The property settings does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
109
110
		// Data Stores.
111
		$this->payments_data_store      = new Payments\PaymentsDataStoreCPT();
0 ignored issues
show
Bug Best Practice introduced by
The property payments_data_store does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
112
		$this->subscriptions_data_store = new Subscriptions\SubscriptionsDataStoreCPT();
0 ignored issues
show
Bug Best Practice introduced by
The property subscriptions_data_store does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
113
114
		// Post Types.
115
		$this->gateway_post_type      = new GatewayPostType();
0 ignored issues
show
Bug Best Practice introduced by
The property gateway_post_type does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
116
		$this->payment_post_type      = new PaymentPostType();
0 ignored issues
show
Bug Best Practice introduced by
The property payment_post_type does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
117
		$this->subscription_post_type = new SubscriptionPostType();
0 ignored issues
show
Bug Best Practice introduced by
The property subscription_post_type does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
118
119
		// License Manager.
120
		$this->license_manager = new LicenseManager( $this );
0 ignored issues
show
Bug Best Practice introduced by
The property license_manager does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
121
122
		// Modules.
123
		$this->forms_module         = new Forms\FormsModule( $this );
0 ignored issues
show
Bug Best Practice introduced by
The property forms_module does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
124
		$this->payments_module      = new Payments\PaymentsModule( $this );
0 ignored issues
show
Bug Best Practice introduced by
The property payments_module does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
125
		$this->subscriptions_module = new Subscriptions\SubscriptionsModule( $this );
0 ignored issues
show
Bug Best Practice introduced by
The property subscriptions_module does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
126
127
		// Google Analytics Ecommerce.
128
		$this->google_analytics_ecommerce = new GoogleAnalyticsEcommerce();
0 ignored issues
show
Bug Best Practice introduced by
The property google_analytics_ecommerce does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
129
130
		// Admin.
131
		if ( is_admin() ) {
132
			$this->admin = new Admin\AdminModule( $this );
0 ignored issues
show
Bug Best Practice introduced by
The property admin does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
133
		}
134
135
		/*
136
		 * Plugins loaded.
137
		 *
138
		 * Priority should be at least lower then 8 to support the "WP eCommerce" plugin.
139
		 *
140
		 * new WP_eCommerce()
141
		 * add_action( 'plugins_loaded' , array( $this, 'init' ), 8 );
142
		 * $this->load();
143
		 * wpsc_core_load_gateways();
144
		 *
145
		 * @see https://github.com/wp-e-commerce/WP-e-Commerce/blob/branch-3.11.2/wp-shopping-cart.php#L342-L343
146
		 * @see https://github.com/wp-e-commerce/WP-e-Commerce/blob/branch-3.11.2/wp-shopping-cart.php#L26-L35
147
		 * @see https://github.com/wp-e-commerce/WP-e-Commerce/blob/branch-3.11.2/wp-shopping-cart.php#L54
148
		 * @see https://github.com/wp-e-commerce/WP-e-Commerce/blob/branch-3.11.2/wp-shopping-cart.php#L296-L297
149
		 */
150
		add_action( 'plugins_loaded', array( $this, 'plugins_loaded' ), 5 );
151
152
		// Plugin locale.
153
		add_filter( 'plugin_locale', array( $this, 'plugin_locale' ), 10, 2 );
154
155
		// If WordPress is loaded check on returns and maybe redirect requests.
156
		add_action( 'wp_loaded', array( $this, 'handle_returns' ) );
157
		add_action( 'wp_loaded', array( $this, 'maybe_redirect' ) );
158
159
		// Default date time format.
160
		add_filter( 'pronamic_datetime_default_format', array( $this, 'datetime_format' ), 10, 1 );
161
	}
162
163
	/**
164
	 * Get the version number of this plugin.
165
	 *
166
	 * @return string The version number of this plugin.
167
	 */
168
	public function get_version() {
169
		return $this->version;
170
	}
171
172
	/**
173
	 * Get plugin file path.
174
	 *
175
	 * @return string
176
	 */
177
	public function get_file() {
178
		return self::$file;
179
	}
180
181
	/**
182
	 * Get the plugin dir path.
183
	 *
184
	 * @return string
185
	 */
186
	public function get_plugin_dir_path() {
187
		return plugin_dir_path( $this->get_file() );
188
	}
189
190
	/**
191
	 * Update payment.
192
	 *
193
	 * @param Payment $payment      The payment to update.
194
	 * @param bool    $can_redirect Flag to indicate if redirect is allowed after the payment update.
195
	 */
196
	public static function update_payment( $payment = null, $can_redirect = true ) {
197
		if ( empty( $payment ) ) {
198
			return;
199
		}
200
201
		$gateway = Plugin::get_gateway( $payment->config_id );
202
203
		if ( empty( $gateway ) ) {
204
			return;
205
		}
206
207
		$amount = $payment->get_amount();
208
209
		if ( empty( $amount ) ) {
210
			$payment->set_status( Core\Statuses::SUCCESS );
211
		} else {
212
			$gateway->update_status( $payment );
213
214
			if ( $gateway->has_error() ) {
215
				foreach ( $gateway->error->get_error_codes() as $code ) {
216
					$payment->add_note( sprintf( '%s: %s', $code, $gateway->error->get_error_message( $code ) ) );
217
				}
218
			}
219
		}
220
221
		// Update payment in data store.
222
		$payment->save();
223
224
		// Maybe redirect.
225
		if ( defined( 'DOING_CRON' ) && ( empty( $payment->status ) || Statuses::OPEN === $payment->status ) ) {
226
			$can_redirect = false;
227
		}
228
229
		if ( $can_redirect ) {
230
			$url = $payment->get_return_redirect_url();
231
232
			wp_redirect( $url );
233
234
			exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
235
		}
236
	}
237
238
	/**
239
	 * Handle returns.
240
	 */
241
	public function handle_returns() {
242
		if ( ! filter_has_var( INPUT_GET, 'payment' ) ) {
243
			return;
244
		}
245
246
		$payment_id = filter_input( INPUT_GET, 'payment', FILTER_SANITIZE_NUMBER_INT );
247
248
		$payment = get_pronamic_payment( $payment_id );
249
250
		// Check if payment key is valid.
251
		$valid_key = false;
252
253
		if ( empty( $payment->key ) ) {
254
			$valid_key = true;
255
		} elseif ( filter_has_var( INPUT_GET, 'key' ) ) {
256
			$key = filter_input( INPUT_GET, 'key', FILTER_SANITIZE_STRING );
257
258
			$valid_key = ( $key === $payment->key );
259
		}
260
261
		if ( ! $valid_key ) {
262
			wp_redirect( home_url() );
263
264
			exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
265
		}
266
267
		// Check if we should redirect.
268
		$should_redirect = true;
269
270
		// Check if the request is an callback request.
271
		// Sisow gatway will extend callback requests with querystring "callback=true".
272
		if ( filter_has_var( INPUT_GET, 'callback' ) && filter_input( INPUT_GET, 'callback', FILTER_VALIDATE_BOOLEAN ) ) {
273
			$should_redirect = false;
274
		}
275
276
		// Check if the request is an notify request.
277
		// Sisow gatway will extend callback requests with querystring "notify=true".
278
		if ( filter_has_var( INPUT_GET, 'notify' ) && filter_input( INPUT_GET, 'notify', FILTER_VALIDATE_BOOLEAN ) ) {
279
			$should_redirect = false;
280
		}
281
282
		self::update_payment( $payment, $should_redirect );
283
	}
284
285
	/**
286
	 * Maybe redirect.
287
	 */
288
	public function maybe_redirect() {
289
		if ( ! filter_has_var( INPUT_GET, 'payment_redirect' ) ) {
290
			return;
291
		}
292
293
		$payment_id = filter_input( INPUT_GET, 'payment_redirect', FILTER_SANITIZE_NUMBER_INT );
294
295
		$payment = get_pronamic_payment( $payment_id );
296
297
		// HTML Answer.
298
		$html_answer = $payment->get_meta( 'ogone_directlink_html_answer' );
299
300
		if ( ! empty( $html_answer ) ) {
301
			echo $html_answer; // WPCS: XSS ok.
302
303
			exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
304
		}
305
306
		$redirect_message = $payment->get_meta( 'payment_redirect_message' );
307
308
		if ( ! empty( $redirect_message ) ) {
309
			$key = filter_input( INPUT_GET, 'key', FILTER_SANITIZE_STRING );
310
311
			if ( $key !== $payment->key ) {
312
				wp_redirect( home_url() );
313
314
				exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
315
			}
316
317
			// @see https://github.com/woothemes/woocommerce/blob/2.3.11/includes/class-wc-cache-helper.php
318
			// @see https://www.w3-edge.com/products/w3-total-cache/
319
			if ( ! defined( 'DONOTCACHEPAGE' ) ) {
320
				define( 'DONOTCACHEPAGE', true );
321
			}
322
323
			if ( ! defined( 'DONOTCACHEDB' ) ) {
324
				define( 'DONOTCACHEDB', true );
325
			}
326
327
			if ( ! defined( 'DONOTMINIFY' ) ) {
328
				define( 'DONOTMINIFY', true );
329
			}
330
331
			if ( ! defined( 'DONOTCDN' ) ) {
332
				define( 'DONOTCDN', true );
333
			}
334
335
			if ( ! defined( 'DONOTCACHEOBJECT' ) ) {
336
				define( 'DONOTCACHEOBJECT', true );
337
			}
338
339
			nocache_headers();
340
341
			include Plugin::$dirname . '/views/redirect-message.php';
342
343
			exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
344
		}
345
346
		$gateway = Plugin::get_gateway( $payment->config_id );
347
348
		if ( $gateway && $gateway->is_html_form() ) {
349
			$gateway->start( $payment );
350
351
			$error = $gateway->get_error();
352
353
			if ( is_wp_error( $error ) ) {
354
				Plugin::render_errors( $error );
0 ignored issues
show
Bug introduced by
$error of type WP_Error is incompatible with the type array expected by parameter $errors of Pronamic\WordPress\Pay\Plugin::render_errors(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

354
				Plugin::render_errors( /** @scrutinizer ignore-type */ $error );
Loading history...
355
			} else {
356
				$gateway->redirect( $payment );
357
			}
358
		}
359
360
		if ( ! empty( $payment->action_url ) ) {
361
			wp_redirect( $payment->action_url );
362
363
			exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
364
		}
365
	}
366
367
	/**
368
	 * Get number payments.
369
	 *
370
	 * @return int
371
	 */
372
	public static function get_number_payments() {
373
		$number = false;
374
375
		$count = wp_count_posts( 'pronamic_payment' );
376
377
		if ( isset( $count, $count->payment_completed ) ) {
378
			$number = intval( $count->payment_completed );
379
		}
380
381
		return $number;
382
	}
383
384
	/**
385
	 * Setup, creates or updates database tables. Will only run when version changes.
386
	 */
387
	public function plugins_loaded() {
388
		// Load plugin text domain.
389
		$rel_path = dirname( plugin_basename( self::$file ) ) . '/languages/';
390
391
		load_plugin_textdomain( 'pronamic_ideal', false, $rel_path );
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type string expected by parameter $deprecated of load_plugin_textdomain(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

391
		load_plugin_textdomain( 'pronamic_ideal', /** @scrutinizer ignore-type */ false, $rel_path );
Loading history...
392
393
		// Gateway Integrations.
394
		$integrations = new GatewayIntegrations();
395
396
		$this->gateway_integrations = $integrations->register_integrations();
0 ignored issues
show
Bug Best Practice introduced by
The property gateway_integrations does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
397
398
		// Maybes.
399
		self::maybe_set_active_payment_methods();
400
	}
401
402
	/**
403
	 * Filter plugin locale.
404
	 *
405
	 * @param string $locale A WordPress locale identifier.
406
	 * @param string $domain A WordPress text domain indentifier.
407
	 *
408
	 * @return string
409
	 */
410
	public function plugin_locale( $locale, $domain ) {
411
		if ( 'pronamic_ideal' !== $domain ) {
412
			return $locale;
413
		}
414
415
		if ( 'nl_NL_formal' === $locale ) {
416
			return 'nl_NL';
417
		}
418
419
		if ( 'nl_BE' === $locale ) {
420
			return 'nl_NL';
421
		}
422
423
		return $locale;
424
	}
425
426
	/**
427
	 * Default date time format.
428
	 *
429
	 * @param string $format Format.
430
	 *
431
	 * @return string|void
432
	 */
433
	public function datetime_format( $format ) {
0 ignored issues
show
Unused Code introduced by
The parameter $format is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

433
	public function datetime_format( /** @scrutinizer ignore-unused */ $format ) {

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

Loading history...
434
		return _x( 'D j M Y \a\t H:i', 'default datetime format', 'pronamic_ideal' );
435
	}
436
437
	/**
438
	 * Get default error message.
439
	 *
440
	 * @return string
441
	 */
442
	public static function get_default_error_message() {
443
		return __( 'Something went wrong with the payment. Please try again later or pay another way.', 'pronamic_ideal' );
444
	}
445
446
	/**
447
	 * Get config select options.
448
	 *
449
	 * @param null|string $payment_method The gateway configuration options for the specified payment method.
450
	 *
451
	 * @return array
452
	 */
453
	public static function get_config_select_options( $payment_method = null ) {
454
		$args = array(
455
			'post_type' => 'pronamic_gateway',
456
			'orderby'   => 'post_title',
457
			'order'     => 'ASC',
458
			'nopaging'  => true,
459
		);
460
461
		if ( $payment_method ) {
462
			$args['post__in'] = PaymentMethods::get_config_ids( $payment_method );
463
		}
464
465
		$query = new WP_Query( $args );
466
467
		$options = array( __( '— Select Configuration —', 'pronamic_ideal' ) );
468
469
		foreach ( $query->posts as $post ) {
470
			$id = $post->ID;
471
472
			$options[ $id ] = sprintf(
473
				'%s (%s)',
474
				get_the_title( $id ),
475
				get_post_meta( $id, '_pronamic_gateway_mode', true )
0 ignored issues
show
Bug introduced by
It seems like get_post_meta($id, '_pro...ic_gateway_mode', true) can also be of type false; however, parameter $args of sprintf() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

475
				/** @scrutinizer ignore-type */ get_post_meta( $id, '_pronamic_gateway_mode', true )
Loading history...
476
			);
477
		}
478
479
		return $options;
480
	}
481
482
	/**
483
	 * Maybe set active payment methods option.
484
	 *
485
	 * @since unreleased
486
	 */
487
	public static function maybe_set_active_payment_methods() {
488
		$active_methods = get_option( 'pronamic_pay_active_payment_methods' );
489
490
		if ( is_array( $active_methods ) ) {
491
			return;
492
		}
493
494
		PaymentMethods::update_active_payment_methods();
495
	}
496
497
	/**
498
	 * Render errors.
499
	 *
500
	 * @param array $errors An array with errors to render.
501
	 */
502
	public static function render_errors( $errors = array() ) {
503
		if ( ! is_array( $errors ) ) {
0 ignored issues
show
introduced by
The condition is_array($errors) is always true.
Loading history...
504
			$errors = array( $errors );
505
		}
506
507
		foreach ( $errors as $error ) {
508
			include Plugin::$dirname . '/views/error.php';
509
		}
510
	}
511
512
	/**
513
	 * Get gateway.
514
	 *
515
	 * @param string|integer|boolean $config_id A gateway configuration ID.
516
	 *
517
	 * @return Gateway|null
518
	 */
519
	public static function get_gateway( $config_id ) {
520
		if ( empty( $config_id ) ) {
521
			return null;
522
		}
523
524
		$gateway_id = get_post_meta( $config_id, '_pronamic_gateway_id', true );
0 ignored issues
show
Bug introduced by
It seems like $config_id can also be of type string and boolean; however, parameter $post_id of get_post_meta() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

524
		$gateway_id = get_post_meta( /** @scrutinizer ignore-type */ $config_id, '_pronamic_gateway_id', true );
Loading history...
525
		$mode       = get_post_meta( $config_id, '_pronamic_gateway_mode', true );
526
		$is_utf8    = strcasecmp( get_bloginfo( 'charset' ), 'UTF-8' ) === 0;
527
528
		$config = Core\ConfigProvider::get_config( $gateway_id, $config_id );
529
530
		switch ( $gateway_id ) {
531
			case 'abnamro-ideal-easy':
532
			case 'abnamro-ideal-only-kassa':
533
			case 'abnamro-internetkassa':
534
				$config->form_action_url = sprintf(
535
					'https://internetkassa.abnamro.nl/ncol/%s/orderstandard%s.asp',
536
					'test' === $mode ? 'test' : 'prod',
537
					$is_utf8 ? '_utf8' : ''
538
				);
539
540
				break;
541
			case 'abnamro-ideal-zelfbouw-v3':
542
				$config->payment_server_url = 'https://abnamro.ideal-payment.de/ideal/iDEALv3';
543
544
				if ( 'test' === $mode ) {
545
					$config->payment_server_url = 'https://abnamro-test.ideal-payment.de/ideal/iDEALv3';
546
				}
547
548
				$config->certificates = array();
549
550
				break;
551
			case 'deutschebank-ideal-expert-v3':
552
				$config->payment_server_url = 'https://myideal.db.com/ideal/iDealv3';
553
554
				$config->certificates = array();
555
556
				break;
557
			case 'ideal-simulator-ideal-basic':
558
				$config->url = 'https://www.ideal-simulator.nl/lite/';
559
560
				break;
561
			case 'ideal-simulator-ideal-advanced-v3':
562
				$config->payment_server_url = 'https://www.ideal-checkout.nl/simulator/';
563
564
				$config->certificates = array();
565
566
				break;
567
			case 'ing-ideal-basic':
568
				$config->url = 'https://ideal.secure-ing.com/ideal/mpiPayInitIng.do';
569
570
				if ( 'test' === $mode ) {
571
					$config->url = 'https://idealtest.secure-ing.com/ideal/mpiPayInitIng.do';
572
				}
573
574
				break;
575
			case 'ing-ideal-advanced-v3':
576
				$config->payment_server_url = 'https://ideal.secure-ing.com/ideal/iDEALv3';
577
578
				if ( 'test' === $mode ) {
579
					$config->payment_server_url = 'https://idealtest.secure-ing.com/ideal/iDEALv3';
580
				}
581
582
				$config->certificates = array();
583
584
				break;
585
			case 'mollie-ideal-basic':
586
				$config->url = 'https://secure.mollie.nl/xml/idealAcquirer/lite/';
587
588
				if ( 'test' === $mode ) {
589
					$config->url = 'https://secure.mollie.nl/xml/idealAcquirer/testmode/lite/';
590
				}
591
592
				break;
593
			case 'postcode-ideal':
594
				$config->payment_server_url = 'https://ideal.postcode.nl/ideal';
595
596
				if ( 'test' === $mode ) {
597
					$config->payment_server_url = 'https://ideal-test.postcode.nl/ideal';
598
				}
599
600
				$config->certificates = array();
601
602
				break;
603
			case 'rabobank-ideal-professional-v3':
604
				$config->payment_server_url = 'https://ideal.rabobank.nl/ideal/iDEALv3';
605
606
				if ( 'test' === $mode ) {
607
					$config->payment_server_url = 'https://idealtest.rabobank.nl/ideal/iDEALv3';
608
				}
609
610
				$config->certificates = array();
611
612
				break;
613
			case 'sisow-ideal-basic':
614
				$config->url = 'https://www.sisow.nl/Sisow/iDeal/IssuerHandler.ashx';
615
616
				if ( 'test' === $mode ) {
617
					$config->url = 'https://www.sisow.nl/Sisow/iDeal/IssuerHandler.ashx/test';
618
				}
619
620
				break;
621
		}
622
623
		$gateway = Core\GatewayFactory::create( $config );
624
625
		return $gateway;
626
	}
627
628
	/**
629
	 * Start a payment.
630
	 *
631
	 * @param string               $config_id      A gateway configuration ID.
632
	 * @param Gateway              $gateway        The gateway to start the payment at.
633
	 * @param PaymentDataInterface $data           A payment data interface object with all the required payment info.
634
	 * @param string|null          $payment_method The payment method to use to start the payment.
635
	 *
636
	 * @return Payment
637
	 */
638
	public static function start( $config_id, Gateway $gateway, PaymentDataInterface $data, $payment_method = null ) {
639
		$payment = new Payments\Payment();
640
641
		$payment->title               = sprintf( __( 'Payment for %s', 'pronamic_ideal' ), $data->get_title() );
642
		$payment->user_id             = $data->get_user_id();
0 ignored issues
show
Bug introduced by
The method get_user_id() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

642
		/** @scrutinizer ignore-call */ 
643
  $payment->user_id             = $data->get_user_id();
Loading history...
643
		$payment->config_id           = $config_id;
644
		$payment->key                 = uniqid( 'pay_' );
645
		$payment->order_id            = $data->get_order_id();
0 ignored issues
show
Bug introduced by
The method get_order_id() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

645
		/** @scrutinizer ignore-call */ 
646
  $payment->order_id            = $data->get_order_id();
Loading history...
646
		$payment->currency            = $data->get_currency();
0 ignored issues
show
Bug introduced by
The method get_currency() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

646
		/** @scrutinizer ignore-call */ 
647
  $payment->currency            = $data->get_currency();
Loading history...
647
		$payment->amount              = $data->get_amount();
0 ignored issues
show
Bug introduced by
The method get_amount() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

647
		/** @scrutinizer ignore-call */ 
648
  $payment->amount              = $data->get_amount();
Loading history...
648
		$payment->language            = $data->get_language();
0 ignored issues
show
Bug introduced by
The method get_language() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

648
		/** @scrutinizer ignore-call */ 
649
  $payment->language            = $data->get_language();
Loading history...
649
		$payment->locale              = $data->get_language_and_country();
0 ignored issues
show
Bug introduced by
The method get_language_and_country() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

649
		/** @scrutinizer ignore-call */ 
650
  $payment->locale              = $data->get_language_and_country();
Loading history...
650
		$payment->entrance_code       = $data->get_entrance_code();
0 ignored issues
show
Bug introduced by
The method get_entrance_code() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

650
		/** @scrutinizer ignore-call */ 
651
  $payment->entrance_code       = $data->get_entrance_code();
Loading history...
651
		$payment->description         = $data->get_description();
0 ignored issues
show
Bug introduced by
The method get_description() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. Did you maybe mean get_subscription()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

651
		/** @scrutinizer ignore-call */ 
652
  $payment->description         = $data->get_description();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
652
		$payment->source              = $data->get_source();
0 ignored issues
show
Bug introduced by
The method get_source() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

652
		/** @scrutinizer ignore-call */ 
653
  $payment->source              = $data->get_source();
Loading history...
653
		$payment->source_id           = $data->get_source_id();
0 ignored issues
show
Bug introduced by
The method get_source_id() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

653
		/** @scrutinizer ignore-call */ 
654
  $payment->source_id           = $data->get_source_id();
Loading history...
654
		$payment->email               = $data->get_email();
0 ignored issues
show
Bug introduced by
The method get_email() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

654
		/** @scrutinizer ignore-call */ 
655
  $payment->email               = $data->get_email();
Loading history...
655
		$payment->status              = null;
656
		$payment->method              = $payment_method;
657
		$payment->issuer              = $data->get_issuer( $payment_method );
0 ignored issues
show
Bug introduced by
The method get_issuer() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

657
		/** @scrutinizer ignore-call */ 
658
  $payment->issuer              = $data->get_issuer( $payment_method );
Loading history...
658
		$payment->first_name          = $data->get_first_name();
0 ignored issues
show
Bug introduced by
The method get_first_name() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. It seems like you code against a sub-type of Pronamic\WordPress\Pay\P...ts\PaymentDataInterface such as Pronamic\WordPress\Pay\Payments\PaymentData. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

658
		/** @scrutinizer ignore-call */ 
659
  $payment->first_name          = $data->get_first_name();
Loading history...
659
		$payment->last_name           = $data->get_last_name();
0 ignored issues
show
Bug introduced by
The method get_last_name() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. It seems like you code against a sub-type of Pronamic\WordPress\Pay\P...ts\PaymentDataInterface such as Pronamic\WordPress\Pay\Payments\PaymentData. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

659
		/** @scrutinizer ignore-call */ 
660
  $payment->last_name           = $data->get_last_name();
Loading history...
660
		$payment->customer_name       = $data->get_customer_name();
0 ignored issues
show
Bug introduced by
The method get_customer_name() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

660
		/** @scrutinizer ignore-call */ 
661
  $payment->customer_name       = $data->get_customer_name();
Loading history...
661
		$payment->address             = $data->get_address();
0 ignored issues
show
Bug introduced by
The method get_address() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

661
		/** @scrutinizer ignore-call */ 
662
  $payment->address             = $data->get_address();
Loading history...
662
		$payment->zip                 = $data->get_zip();
0 ignored issues
show
Bug introduced by
The method get_zip() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

662
		/** @scrutinizer ignore-call */ 
663
  $payment->zip                 = $data->get_zip();
Loading history...
663
		$payment->city                = $data->get_city();
0 ignored issues
show
Bug introduced by
The method get_city() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

663
		/** @scrutinizer ignore-call */ 
664
  $payment->city                = $data->get_city();
Loading history...
664
		$payment->country             = $data->get_country();
0 ignored issues
show
Bug introduced by
The method get_country() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

664
		/** @scrutinizer ignore-call */ 
665
  $payment->country             = $data->get_country();
Loading history...
665
		$payment->telephone_number    = $data->get_telephone_number();
0 ignored issues
show
Bug introduced by
The method get_telephone_number() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

665
		/** @scrutinizer ignore-call */ 
666
  $payment->telephone_number    = $data->get_telephone_number();
Loading history...
666
		$payment->analytics_client_id = $data->get_analytics_client_id();
0 ignored issues
show
Bug introduced by
The method get_analytics_client_id() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. It seems like you code against a sub-type of Pronamic\WordPress\Pay\P...ts\PaymentDataInterface such as Pronamic\WordPress\Pay\Payments\PaymentData. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

666
		/** @scrutinizer ignore-call */ 
667
  $payment->analytics_client_id = $data->get_analytics_client_id();
Loading history...
667
		$payment->recurring           = $data->get_recurring();
0 ignored issues
show
Bug introduced by
The method get_recurring() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

667
		/** @scrutinizer ignore-call */ 
668
  $payment->recurring           = $data->get_recurring();
Loading history...
668
		$payment->subscription        = $data->get_subscription();
669
		$payment->subscription_id     = $data->get_subscription_id();
0 ignored issues
show
Bug introduced by
The method get_subscription_id() does not exist on Pronamic\WordPress\Pay\P...ts\PaymentDataInterface. Did you maybe mean get_subscription()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

669
		/** @scrutinizer ignore-call */ 
670
  $payment->subscription_id     = $data->get_subscription_id();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
670
		$payment->set_credit_card( $data->get_credit_card() );
671
672
		// User Agent (@see https://github.com/WordPress/WordPress/blob/4.9.4/wp-includes/comment.php#L1962-L1965).
673
		$payment->user_agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : null;
674
675
		// IP (@see https://github.com/WordPress/WordPress/blob/4.9.4/wp-includes/comment.php#L1957-L1960).
676
		$payment->user_ip = isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : null;
677
678
		return self::start_payment( $payment, $gateway );
679
	}
680
681
	/**
682
	 * Start payment.
683
	 *
684
	 * @param Payment $payment The payment to start at the specified gateway.
685
	 * @param Gateway $gateway The gateway to start the payment at.
686
	 *
687
	 * @return Payment
688
	 */
689
	public static function start_payment( Payment $payment, Gateway $gateway ) {
690
		global $pronamic_ideal;
691
692
		$pronamic_ideal->payments_data_store->create( $payment );
693
694
		// Prevent payment start at gateway if amount is empty.
695
		$amount = $payment->get_amount();
696
697
		if ( empty( $amount ) ) {
698
			// Keep track of free payments to update during shutdown.
699
			pronamic_pay_plugin()->payments_module->free[] = $payment->get_id();
700
701
			return $payment;
702
		}
703
704
		// Start payment at the gateway.
705
		$result = $gateway->start( $payment );
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $result is correct as $gateway->start($payment) targeting Pronamic\WordPress\Pay\Core\Gateway::start() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
706
707
		// Add gateway errors as payment notes.
708
		if ( $gateway->has_error() ) {
709
			foreach ( $gateway->error->get_error_codes() as $code ) {
710
				$payment->add_note( sprintf( '%s: %s', $code, $gateway->error->get_error_message( $code ) ) );
711
			}
712
		}
713
714
		// Set payment status.
715
		if ( false === $result ) {
0 ignored issues
show
introduced by
The condition false === $result is always true.
Loading history...
716
			$payment->set_status( Statuses::FAILURE );
717
		} else {
718
			$payment->set_status( Statuses::OPEN );
719
		}
720
721
		// Save payment.
722
		$payment->save();
723
724
		// Update subscription status for failed payments.
725
		if ( false === $result && $payment->get_subscription() ) {
726
			// Reload payment, so subscription is available.
727
			$payment = new Payment( $payment->get_id() );
728
729
			$subscription = $payment->get_subscription();
730
731
			if ( 'first' === $payment->recurring_type ) {
732
				// First payment - cancel subscription to prevent unwanted recurring payments
733
				// in the future, when a valid customer ID might be set for the user.
734
				$subscription->set_status( Statuses::CANCELLED );
735
			} else {
736
				$subscription->set_status( Statuses::FAILURE );
737
			}
738
739
			$subscription->save();
740
		}
741
742
		// Schedule payment status check.
743
		if ( $gateway->supports( 'payment_status_request' ) ) {
744
			StatusChecker::schedule_event( $payment );
745
		}
746
747
		return $payment;
748
	}
749
750
	/**
751
	 * Get pages.
752
	 *
753
	 * @return array
754
	 */
755
	public function get_pages() {
756
		$return = array();
757
758
		$pages = array(
759
			'completed' => __( 'Completed', 'pronamic_ideal' ),
760
			'cancel'    => __( 'Canceled', 'pronamic_ideal' ),
761
			'expired'   => __( 'Expired', 'pronamic_ideal' ),
762
			'error'     => __( 'Error', 'pronamic_ideal' ),
763
			'unknown'   => __( 'Unknown', 'pronamic_ideal' ),
764
		);
765
766
		foreach ( $pages as $key => $label ) {
767
			$id = sprintf( 'pronamic_pay_%s_page_id', $key );
768
769
			$return[ $id ] = $label;
770
		}
771
772
		return $return;
773
	}
774
}
775