Passed
Push — develop ( 550c07...6b0c19 )
by Reüel
06:46
created

Plugin::get_plugin_dir_path()   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 0
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\Recurring;
16
use Pronamic\WordPress\Pay\Core\Statuses;
17
use Pronamic\WordPress\Pay\Payments\Payment;
18
use Pronamic\WordPress\Pay\Payments\PaymentDataInterface;
19
use Pronamic\WordPress\Pay\Payments\PaymentPostType;
20
use Pronamic\WordPress\Pay\Payments\StatusChecker;
21
use Pronamic\WordPress\Pay\Subscriptions\SubscriptionPostType;
22
use WP_Query;
23
24
/**
25
 * Title: WordPress iDEAL plugin
26
 *
27
 * @author Remco Tolsma
28
 * @version 4.5.3
29
 * @since 1.0.0
30
 */
31
class Plugin {
32
	/**
33
	 * Version.
34
	 *
35
	 * @var string
36
	 */
37
	private $version = '5.0.0';
38
39
	/**
40
	 * The root file of this WordPress plugin
41
	 *
42
	 * @var string
43
	 */
44
	public static $file;
45
46
	/**
47
	 * The plugin dirname
48
	 *
49
	 * @var string
50
	 */
51
	public static $dirname;
52
53
	/**
54
	 * The timezone
55
	 *
56
	 * @var string
57
	 */
58
	const TIMEZONE = 'UTC';
59
60
	/**
61
	 * Instance.
62
	 *
63
	 * @var Plugin
64
	 */
65
	protected static $instance = null;
66
67
	/**
68
	 * Instance.
69
	 *
70
	 * @param string $file The plugin file.
71
	 */
72
	public static function instance( $file = null ) {
73
		if ( is_null( self::$instance ) ) {
74
			self::$instance = new self();
75
76
			// Backward compatibility.
77
			self::$file    = $file;
78
			self::$dirname = dirname( $file );
79
		}
80
81
		return self::$instance;
82
	}
83
84
	/**
85
	 * Plugin settings.
86
	 *
87
	 * @var Settings
88
	 */
89
	public $settings;
90
91
	/**
92
	 * Payment data storing.
93
	 *
94
	 * @var Payments\PaymentsDataStoreCPT
95
	 */
96
	public $payments_data_store;
97
98
	/**
99
	 * Subscription data storing.
100
	 *
101
	 * @var Subscriptions\SubscriptionsDataStoreCPT
102
	 */
103
	public $subscriptions_data_store;
104
105
	/**
106
	 * Gateway post type.
107
	 *
108
	 * @var GatewayPostType
109
	 */
110
	public $gateway_post_type;
111
112
	/**
113
	 * Payment post type.
114
	 *
115
	 * @var PaymentPostType
116
	 */
117
	public $payment_post_type;
118
119
	/**
120
	 * Subscription post type.
121
	 *
122
	 * @var SubscriptionPostType
123
	 */
124
	public $subscription_post_type;
125
126
	/**
127
	 * Licence manager.
128
	 *
129
	 * @var LicenseManager
130
	 */
131
	public $license_manager;
132
133
	/**
134
	 * Forms module.
135
	 *
136
	 * @var Forms\FormsModule
137
	 */
138
	public $forms_module;
139
140
	/**
141
	 * Payments module.
142
	 *
143
	 * @var Payments\PaymentsModule
144
	 */
145
	public $payments_module;
146
147
	/**
148
	 * Subsciptions module.
149
	 *
150
	 * @var Subscriptions\SubscriptionsModule
151
	 */
152
	public $subscriptions_module;
153
154
	/**
155
	 * Google analytics ecommerce.
156
	 *
157
	 * @var GoogleAnalyticsEcommerce
158
	 */
159
	public $google_analytics_ecommerce;
160
161
	/**
162
	 * Construct and initialize an Pronamic Pay plugin object
163
	 */
164
	public function __construct() {
165
		// Bootstrap the add-ons.
166
		Extensions\Charitable\Extension::bootstrap();
167
		Extensions\Give\Extension::bootstrap();
168
		Extensions\WooCommerce\Extension::bootstrap();
169
		Extensions\GravityForms\Extension::bootstrap();
170
		Extensions\Shopp\Extension::bootstrap();
171
		Extensions\Jigoshop\Extension::bootstrap();
172
		Extensions\WPeCommerce\Extension::bootstrap();
173
		Extensions\ClassiPress\Extension::bootstrap();
174
		Extensions\EventEspressoLegacy\Extension::bootstrap();
175
		Extensions\EventEspresso\Extension::bootstrap();
176
		Extensions\AppThemes\Extension::bootstrap();
177
		Extensions\S2Member\Extension::bootstrap();
178
		Extensions\Membership\Extension::bootstrap();
179
		Extensions\EasyDigitalDownloads\Extension::bootstrap();
180
		Extensions\IThemesExchange\Extension::bootstrap();
181
		Extensions\MemberPress\Extension::bootstrap();
182
		Extensions\FormidableForms\Extension::bootstrap();
183
		Extensions\RestrictContentPro\Extension::bootstrap();
184
185
		// Settings.
186
		$this->settings = new Settings( $this );
187
188
		// Data Stores.
189
		$this->payments_data_store      = new Payments\PaymentsDataStoreCPT();
190
		$this->subscriptions_data_store = new Subscriptions\SubscriptionsDataStoreCPT();
191
192
		// Post Types.
193
		$this->gateway_post_type      = new GatewayPostType();
194
		$this->payment_post_type      = new PaymentPostType();
195
		$this->subscription_post_type = new SubscriptionPostType();
196
197
		// License Manager.
198
		$this->license_manager = new LicenseManager( $this );
199
200
		// Modules.
201
		$this->forms_module         = new Forms\FormsModule( $this );
202
		$this->payments_module      = new Payments\PaymentsModule( $this );
203
		$this->subscriptions_module = new Subscriptions\SubscriptionsModule( $this );
204
205
		// Google Analytics Ecommerce.
206
		$this->google_analytics_ecommerce = new GoogleAnalyticsEcommerce();
207
208
		// Admin.
209
		if ( is_admin() ) {
210
			$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...
211
		}
212
213
		/*
214
		 * Plugins loaded.
215
		 *
216
		 * Priority should be at least lower then 8 to support the "WP eCommerce" plugin.
217
		 *
218
		 * new WP_eCommerce()
219
		 * add_action( 'plugins_loaded' , array( $this, 'init' ), 8 );
220
		 * $this->load();
221
		 * wpsc_core_load_gateways();
222
		 *
223
		 * @see https://github.com/wp-e-commerce/WP-e-Commerce/blob/branch-3.11.2/wp-shopping-cart.php#L342-L343
224
		 * @see https://github.com/wp-e-commerce/WP-e-Commerce/blob/branch-3.11.2/wp-shopping-cart.php#L26-L35
225
		 * @see https://github.com/wp-e-commerce/WP-e-Commerce/blob/branch-3.11.2/wp-shopping-cart.php#L54
226
		 * @see https://github.com/wp-e-commerce/WP-e-Commerce/blob/branch-3.11.2/wp-shopping-cart.php#L296-L297
227
		 */
228
		add_action( 'plugins_loaded', array( $this, 'plugins_loaded' ), 5 );
229
230
		// Plugin locale.
231
		add_filter( 'plugin_locale', array( $this, 'plugin_locale' ), 10, 2 );
232
233
		// If WordPress is loaded check on returns and maybe redirect requests.
234
		add_action( 'wp_loaded', array( $this, 'handle_returns' ) );
235
		add_action( 'wp_loaded', array( $this, 'maybe_redirect' ) );
236
237
		// Default date time format.
238
		add_filter( 'pronamic_datetime_default_format', array( $this, 'datetime_format' ), 10, 1 );
239
	}
240
241
	/**
242
	 * Get the version number of this plugin.
243
	 *
244
	 * @return string The version number of this plugin.
245
	 */
246
	public function get_version() {
247
		return $this->version;
248
	}
249
250
	/**
251
	 * Get plugin file path.
252
	 *
253
	 * @return string
254
	 */
255
	public function get_file() {
256
		return self::$file;
257
	}
258
259
	/**
260
	 * Get the plugin dir path.
261
	 *
262
	 * @return string
263
	 */
264
	public function get_plugin_dir_path() {
265
		return plugin_dir_path( $this->get_file() );
266
	}
267
268
	/**
269
	 * Update payment.
270
	 *
271
	 * @param Payment $payment      The payment to update.
272
	 * @param bool    $can_redirect Flag to indicate if redirect is allowed after the payment update.
273
	 */
274
	public static function update_payment( $payment = null, $can_redirect = true ) {
275
		if ( empty( $payment ) ) {
276
			return;
277
		}
278
279
		$gateway = Plugin::get_gateway( $payment->config_id );
280
281
		if ( empty( $gateway ) ) {
282
			return;
283
		}
284
285
		$amount = $payment->get_amount()->get_amount();
286
287
		if ( empty( $amount ) ) {
288
			$payment->set_status( Core\Statuses::SUCCESS );
289
		} else {
290
			$gateway->update_status( $payment );
291
292
			if ( $gateway->has_error() ) {
293
				foreach ( $gateway->error->get_error_codes() as $code ) {
294
					$payment->add_note( sprintf( '%s: %s', $code, $gateway->error->get_error_message( $code ) ) );
295
				}
296
			}
297
		}
298
299
		// Update payment in data store.
300
		$payment->save();
301
302
		// Maybe redirect.
303
		if ( wp_doing_cron() && ( empty( $payment->status ) || Statuses::OPEN === $payment->status ) ) {
304
			$can_redirect = false;
305
		}
306
307
		if ( defined( 'WP_CLI' ) && WP_CLI ) {
0 ignored issues
show
Bug introduced by
The constant Pronamic\WordPress\Pay\WP_CLI was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
308
			$can_redirect = false;
309
		}
310
311
		if ( $can_redirect ) {
312
			$url = $payment->get_return_redirect_url();
313
314
			wp_redirect( $url );
315
316
			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...
317
		}
318
	}
319
320
	/**
321
	 * Handle returns.
322
	 */
323
	public function handle_returns() {
324
		if ( ! filter_has_var( INPUT_GET, 'payment' ) ) {
325
			return;
326
		}
327
328
		$payment_id = filter_input( INPUT_GET, 'payment', FILTER_SANITIZE_NUMBER_INT );
329
330
		$payment = get_pronamic_payment( $payment_id );
331
332
		// Check if payment key is valid.
333
		$valid_key = false;
334
335
		if ( empty( $payment->key ) ) {
336
			$valid_key = true;
337
		} elseif ( filter_has_var( INPUT_GET, 'key' ) ) {
338
			$key = filter_input( INPUT_GET, 'key', FILTER_SANITIZE_STRING );
339
340
			$valid_key = ( $key === $payment->key );
341
		}
342
343
		if ( ! $valid_key ) {
344
			wp_redirect( home_url() );
345
346
			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...
347
		}
348
349
		// Check if we should redirect.
350
		$should_redirect = true;
351
352
		// Check if the request is an callback request.
353
		// Sisow gatway will extend callback requests with querystring "callback=true".
354
		if ( filter_has_var( INPUT_GET, 'callback' ) && filter_input( INPUT_GET, 'callback', FILTER_VALIDATE_BOOLEAN ) ) {
355
			$should_redirect = false;
356
		}
357
358
		// Check if the request is an notify request.
359
		// Sisow gatway will extend callback requests with querystring "notify=true".
360
		if ( filter_has_var( INPUT_GET, 'notify' ) && filter_input( INPUT_GET, 'notify', FILTER_VALIDATE_BOOLEAN ) ) {
361
			$should_redirect = false;
362
		}
363
364
		self::update_payment( $payment, $should_redirect );
365
	}
366
367
	/**
368
	 * Maybe redirect.
369
	 */
370
	public function maybe_redirect() {
371
		if ( ! filter_has_var( INPUT_GET, 'payment_redirect' ) ) {
372
			return;
373
		}
374
375
		$payment_id = filter_input( INPUT_GET, 'payment_redirect', FILTER_SANITIZE_NUMBER_INT );
376
377
		$payment = get_pronamic_payment( $payment_id );
378
379
		// HTML Answer.
380
		$html_answer = $payment->get_meta( 'ogone_directlink_html_answer' );
381
382
		if ( ! empty( $html_answer ) ) {
383
			echo $html_answer; // WPCS: XSS ok.
384
385
			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...
386
		}
387
388
		$redirect_message = $payment->get_meta( 'payment_redirect_message' );
389
390
		if ( ! empty( $redirect_message ) ) {
391
			$key = filter_input( INPUT_GET, 'key', FILTER_SANITIZE_STRING );
392
393
			if ( $key !== $payment->key ) {
394
				wp_redirect( home_url() );
395
396
				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...
397
			}
398
399
			// @see https://github.com/woothemes/woocommerce/blob/2.3.11/includes/class-wc-cache-helper.php
400
			// @see https://www.w3-edge.com/products/w3-total-cache/
401
			if ( ! defined( 'DONOTCACHEPAGE' ) ) {
402
				define( 'DONOTCACHEPAGE', true );
403
			}
404
405
			if ( ! defined( 'DONOTCACHEDB' ) ) {
406
				define( 'DONOTCACHEDB', true );
407
			}
408
409
			if ( ! defined( 'DONOTMINIFY' ) ) {
410
				define( 'DONOTMINIFY', true );
411
			}
412
413
			if ( ! defined( 'DONOTCDN' ) ) {
414
				define( 'DONOTCDN', true );
415
			}
416
417
			if ( ! defined( 'DONOTCACHEOBJECT' ) ) {
418
				define( 'DONOTCACHEOBJECT', true );
419
			}
420
421
			nocache_headers();
422
423
			include Plugin::$dirname . '/views/redirect-message.php';
424
425
			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...
426
		}
427
428
		$gateway = Plugin::get_gateway( $payment->config_id );
429
430
		if ( $gateway && $gateway->is_html_form() ) {
431
			$gateway->start( $payment );
432
433
			$error = $gateway->get_error();
434
435
			if ( is_wp_error( $error ) ) {
436
				Plugin::render_errors( $error );
437
			} else {
438
				$gateway->redirect( $payment );
439
			}
440
		}
441
442
		if ( ! empty( $payment->action_url ) ) {
443
			wp_redirect( $payment->action_url );
444
445
			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...
446
		}
447
	}
448
449
	/**
450
	 * Get number payments.
451
	 *
452
	 * @return int
453
	 */
454
	public static function get_number_payments() {
455
		$number = false;
456
457
		$count = wp_count_posts( 'pronamic_payment' );
458
459
		if ( isset( $count, $count->payment_completed ) ) {
460
			$number = intval( $count->payment_completed );
461
		}
462
463
		return $number;
464
	}
465
466
	/**
467
	 * Setup, creates or updates database tables. Will only run when version changes.
468
	 */
469
	public function plugins_loaded() {
470
		// Load plugin text domain.
471
		$rel_path = dirname( plugin_basename( self::$file ) );
472
473
		load_plugin_textdomain( 'pronamic_ideal', false, $rel_path . '/languages' );
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

473
		load_plugin_textdomain( 'pronamic_ideal', /** @scrutinizer ignore-type */ false, $rel_path . '/languages' );
Loading history...
474
475
		load_plugin_textdomain( 'pronamic-money', false, $rel_path . '/vendor/pronamic/wp-money/languages' );
476
477
		// Gateway Integrations.
478
		$integrations = new GatewayIntegrations();
479
480
		$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...
481
482
		// Maybes.
483
		self::maybe_set_active_payment_methods();
484
	}
485
486
	/**
487
	 * Filter plugin locale.
488
	 *
489
	 * @param string $locale A WordPress locale identifier.
490
	 * @param string $domain A WordPress text domain indentifier.
491
	 *
492
	 * @return string
493
	 */
494
	public function plugin_locale( $locale, $domain ) {
495
		if ( 'pronamic_ideal' !== $domain ) {
496
			return $locale;
497
		}
498
499
		if ( 'nl_NL_formal' === $locale ) {
500
			return 'nl_NL';
501
		}
502
503
		if ( 'nl_BE' === $locale ) {
504
			return 'nl_NL';
505
		}
506
507
		return $locale;
508
	}
509
510
	/**
511
	 * Default date time format.
512
	 *
513
	 * @param string $format Format.
514
	 *
515
	 * @return string|void
516
	 */
517
	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

517
	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...
518
		return _x( 'D j M Y \a\t H:i', 'default datetime format', 'pronamic_ideal' );
519
	}
520
521
	/**
522
	 * Get default error message.
523
	 *
524
	 * @return string
525
	 */
526
	public static function get_default_error_message() {
527
		return __( 'Something went wrong with the payment. Please try again later or pay another way.', 'pronamic_ideal' );
528
	}
529
530
	/**
531
	 * Get config select options.
532
	 *
533
	 * @param null|string $payment_method The gateway configuration options for the specified payment method.
534
	 *
535
	 * @return array
536
	 */
537
	public static function get_config_select_options( $payment_method = null ) {
538
		$args = array(
539
			'post_type' => 'pronamic_gateway',
540
			'orderby'   => 'post_title',
541
			'order'     => 'ASC',
542
			'nopaging'  => true,
543
		);
544
545
		if ( $payment_method ) {
546
			$args['post__in'] = PaymentMethods::get_config_ids( $payment_method );
547
		}
548
549
		$query = new WP_Query( $args );
550
551
		$options = array( __( '— Select Configuration —', 'pronamic_ideal' ) );
552
553
		foreach ( $query->posts as $post ) {
554
			$id = $post->ID;
555
556
			$options[ $id ] = sprintf(
557
				'%s (%s)',
558
				get_the_title( $id ),
559
				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

559
				/** @scrutinizer ignore-type */ get_post_meta( $id, '_pronamic_gateway_mode', true )
Loading history...
560
			);
561
		}
562
563
		return $options;
564
	}
565
566
	/**
567
	 * Maybe set active payment methods option.
568
	 *
569
	 * @since unreleased
570
	 */
571
	public static function maybe_set_active_payment_methods() {
572
		$active_methods = get_option( 'pronamic_pay_active_payment_methods' );
573
574
		if ( is_array( $active_methods ) ) {
575
			return;
576
		}
577
578
		PaymentMethods::update_active_payment_methods();
579
	}
580
581
	/**
582
	 * Render errors.
583
	 *
584
	 * @param array|WP_Error $errors An array with errors to render.
0 ignored issues
show
Bug introduced by
The type Pronamic\WordPress\Pay\WP_Error was not found. Did you mean WP_Error? If so, make sure to prefix the type with \.
Loading history...
585
	 */
586
	public static function render_errors( $errors = array() ) {
587
		if ( ! is_array( $errors ) ) {
588
			$errors = array( $errors );
589
		}
590
591
		foreach ( $errors as $error ) {
592
			include Plugin::$dirname . '/views/error.php';
593
		}
594
	}
595
596
	/**
597
	 * Get gateway.
598
	 *
599
	 * @param string|integer|boolean $config_id A gateway configuration ID.
600
	 *
601
	 * @return Gateway|null
602
	 */
603
	public static function get_gateway( $config_id ) {
604
		if ( empty( $config_id ) ) {
605
			return null;
606
		}
607
608
		$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

608
		$gateway_id = get_post_meta( /** @scrutinizer ignore-type */ $config_id, '_pronamic_gateway_id', true );
Loading history...
609
		$mode       = get_post_meta( $config_id, '_pronamic_gateway_mode', true );
610
		$is_utf8    = strcasecmp( get_bloginfo( 'charset' ), 'UTF-8' ) === 0;
611
612
		$config = Core\ConfigProvider::get_config( $gateway_id, $config_id );
613
614
		switch ( $gateway_id ) {
615
			case 'abnamro-ideal-easy':
616
			case 'abnamro-ideal-only-kassa':
617
			case 'abnamro-internetkassa':
618
				$config->form_action_url = sprintf(
619
					'https://internetkassa.abnamro.nl/ncol/%s/orderstandard%s.asp',
620
					'test' === $mode ? 'test' : 'prod',
621
					$is_utf8 ? '_utf8' : ''
622
				);
623
624
				break;
625
			case 'abnamro-ideal-zelfbouw-v3':
626
				$config->payment_server_url = 'https://abnamro.ideal-payment.de/ideal/iDEALv3';
627
628
				if ( 'test' === $mode ) {
629
					$config->payment_server_url = 'https://abnamro-test.ideal-payment.de/ideal/iDEALv3';
630
				}
631
632
				$config->certificates = array();
633
634
				break;
635
			case 'deutschebank-ideal-expert-v3':
636
				$config->payment_server_url = 'https://myideal.db.com/ideal/iDealv3';
637
638
				$config->certificates = array();
639
640
				break;
641
			case 'ideal-simulator-ideal-basic':
642
				$config->url = 'https://www.ideal-simulator.nl/lite/';
643
644
				break;
645
			case 'ideal-simulator-ideal-advanced-v3':
646
				$config->payment_server_url = 'https://www.ideal-checkout.nl/simulator/';
647
648
				$config->certificates = array();
649
650
				break;
651
			case 'ing-ideal-basic':
652
				$config->url = 'https://ideal.secure-ing.com/ideal/mpiPayInitIng.do';
653
654
				if ( 'test' === $mode ) {
655
					$config->url = 'https://idealtest.secure-ing.com/ideal/mpiPayInitIng.do';
656
				}
657
658
				break;
659
			case 'ing-ideal-advanced-v3':
660
				$config->payment_server_url = 'https://ideal.secure-ing.com/ideal/iDEALv3';
661
662
				if ( 'test' === $mode ) {
663
					$config->payment_server_url = 'https://idealtest.secure-ing.com/ideal/iDEALv3';
664
				}
665
666
				$config->certificates = array();
667
668
				break;
669
			case 'mollie-ideal-basic':
670
				$config->url = 'https://secure.mollie.nl/xml/idealAcquirer/lite/';
671
672
				if ( 'test' === $mode ) {
673
					$config->url = 'https://secure.mollie.nl/xml/idealAcquirer/testmode/lite/';
674
				}
675
676
				break;
677
			case 'postcode-ideal':
678
				$config->payment_server_url = 'https://ideal.postcode.nl/ideal';
679
680
				if ( 'test' === $mode ) {
681
					$config->payment_server_url = 'https://ideal-test.postcode.nl/ideal';
682
				}
683
684
				$config->certificates = array();
685
686
				break;
687
			case 'rabobank-ideal-professional-v3':
688
				$config->payment_server_url = 'https://ideal.rabobank.nl/ideal/iDEALv3';
689
690
				if ( 'test' === $mode ) {
691
					$config->payment_server_url = 'https://idealtest.rabobank.nl/ideal/iDEALv3';
692
				}
693
694
				$config->certificates = array();
695
696
				break;
697
			case 'sisow-ideal-basic':
698
				$config->url = 'https://www.sisow.nl/Sisow/iDeal/IssuerHandler.ashx';
699
700
				if ( 'test' === $mode ) {
701
					$config->url = 'https://www.sisow.nl/Sisow/iDeal/IssuerHandler.ashx/test';
702
				}
703
704
				break;
705
		}
706
707
		$gateway = Core\GatewayFactory::create( $config );
708
709
		return $gateway;
710
	}
711
712
	/**
713
	 * Start a payment.
714
	 *
715
	 * @param string               $config_id      A gateway configuration ID.
716
	 * @param Gateway              $gateway        The gateway to start the payment at.
717
	 * @param PaymentDataInterface $data           A payment data interface object with all the required payment info.
718
	 * @param string|null          $payment_method The payment method to use to start the payment.
719
	 *
720
	 * @return Payment
721
	 */
722
	public static function start( $config_id, Gateway $gateway, PaymentDataInterface $data, $payment_method = null ) {
723
		$payment = new Payments\Payment();
724
725
		$payment->title               = sprintf( __( 'Payment for %s', 'pronamic_ideal' ), $data->get_title() );
726
		$payment->user_id             = $data->get_user_id();
0 ignored issues
show
Bug introduced by
The property user_id does not exist on Pronamic\WordPress\Pay\Payments\Payment. Did you mean user_ip?
Loading history...
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

726
		/** @scrutinizer ignore-call */ 
727
  $payment->user_id             = $data->get_user_id();
Loading history...
727
		$payment->config_id           = $config_id;
0 ignored issues
show
Documentation Bug introduced by
The property $config_id was declared of type integer, but $config_id is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
728
		$payment->key                 = uniqid( 'pay_' );
729
		$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

729
		/** @scrutinizer ignore-call */ 
730
  $payment->order_id            = $data->get_order_id();
Loading history...
730
		$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

730
		/** @scrutinizer ignore-call */ 
731
  $payment->language            = $data->get_language();
Loading history...
731
		$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

731
		/** @scrutinizer ignore-call */ 
732
  $payment->locale              = $data->get_language_and_country();
Loading history...
732
		$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

732
		/** @scrutinizer ignore-call */ 
733
  $payment->entrance_code       = $data->get_entrance_code();
Loading history...
733
		$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

733
		/** @scrutinizer ignore-call */ 
734
  $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...
734
		$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

734
		/** @scrutinizer ignore-call */ 
735
  $payment->source              = $data->get_source();
Loading history...
735
		$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

735
		/** @scrutinizer ignore-call */ 
736
  $payment->source_id           = $data->get_source_id();
Loading history...
736
		$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

736
		/** @scrutinizer ignore-call */ 
737
  $payment->email               = $data->get_email();
Loading history...
737
		$payment->status              = null;
738
		$payment->method              = $payment_method;
739
		$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

739
		/** @scrutinizer ignore-call */ 
740
  $payment->issuer              = $data->get_issuer( $payment_method );
Loading history...
740
		$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

740
		/** @scrutinizer ignore-call */ 
741
  $payment->first_name          = $data->get_first_name();
Loading history...
741
		$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

741
		/** @scrutinizer ignore-call */ 
742
  $payment->last_name           = $data->get_last_name();
Loading history...
742
		$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

742
		/** @scrutinizer ignore-call */ 
743
  $payment->customer_name       = $data->get_customer_name();
Loading history...
743
		$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

743
		/** @scrutinizer ignore-call */ 
744
  $payment->address             = $data->get_address();
Loading history...
744
		$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

744
		/** @scrutinizer ignore-call */ 
745
  $payment->zip                 = $data->get_zip();
Loading history...
745
		$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

745
		/** @scrutinizer ignore-call */ 
746
  $payment->city                = $data->get_city();
Loading history...
746
		$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

746
		/** @scrutinizer ignore-call */ 
747
  $payment->country             = $data->get_country();
Loading history...
747
		$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

747
		/** @scrutinizer ignore-call */ 
748
  $payment->telephone_number    = $data->get_telephone_number();
Loading history...
748
		$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

748
		/** @scrutinizer ignore-call */ 
749
  $payment->analytics_client_id = $data->get_analytics_client_id();
Loading history...
749
		$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

749
		/** @scrutinizer ignore-call */ 
750
  $payment->recurring           = $data->get_recurring();
Loading history...
750
		$payment->subscription        = $data->get_subscription();
751
		$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

751
		/** @scrutinizer ignore-call */ 
752
  $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...
752
		$payment->set_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

752
		$payment->set_amount( $data->/** @scrutinizer ignore-call */ get_amount() );
Loading history...
753
		$payment->set_credit_card( $data->get_credit_card() );
754
755
		// User Agent (@see https://github.com/WordPress/WordPress/blob/4.9.4/wp-includes/comment.php#L1962-L1965).
756
		$payment->user_agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : null;
757
758
		// IP (@see https://github.com/WordPress/WordPress/blob/4.9.4/wp-includes/comment.php#L1957-L1960).
759
		$payment->user_ip = isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : null;
760
761
		return self::start_payment( $payment, $gateway );
762
	}
763
764
	/**
765
	 * Start payment.
766
	 *
767
	 * @param Payment $payment The payment to start at the specified gateway.
768
	 * @param Gateway $gateway The gateway to start the payment at.
769
	 *
770
	 * @return Payment
771
	 */
772
	public static function start_payment( Payment $payment, Gateway $gateway ) {
773
		global $pronamic_ideal;
774
775
		$pronamic_ideal->payments_data_store->create( $payment );
776
777
		// Prevent payment start at gateway if amount is empty.
778
		$amount = $payment->get_amount()->get_amount();
779
780
		if ( empty( $amount ) ) {
781
			// Keep track of free payments to update during shutdown.
782
			pronamic_pay_plugin()->payments_module->free[] = $payment->get_id();
783
784
			return $payment;
785
		}
786
787
		// Start payment at the gateway.
788
		$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...
789
790
		// Add gateway errors as payment notes.
791
		if ( $gateway->has_error() ) {
792
			foreach ( $gateway->error->get_error_codes() as $code ) {
793
				$payment->add_note( sprintf( '%s: %s', $code, $gateway->error->get_error_message( $code ) ) );
794
			}
795
		}
796
797
		// Set payment status.
798
		if ( false === $result ) {
0 ignored issues
show
introduced by
The condition false === $result is always true.
Loading history...
799
			$payment->set_status( Statuses::FAILURE );
800
		} else {
801
			$payment->set_status( Statuses::OPEN );
802
		}
803
804
		// Save payment.
805
		$payment->save();
806
807
		// Update subscription status for failed payments.
808
		if ( false === $result && $payment->get_subscription() ) {
809
			// Reload payment, so subscription is available.
810
			$payment = new Payment( $payment->get_id() );
811
812
			$subscription = $payment->get_subscription();
813
814
			if ( Recurring::FIRST === $payment->recurring_type ) {
815
				// First payment - cancel subscription to prevent unwanted recurring payments
816
				// in the future, when a valid customer ID might be set for the user.
817
				$subscription->set_status( Statuses::CANCELLED );
818
			} else {
819
				$subscription->set_status( Statuses::FAILURE );
820
			}
821
822
			$subscription->save();
823
		}
824
825
		// Schedule payment status check.
826
		if ( $gateway->supports( 'payment_status_request' ) ) {
827
			StatusChecker::schedule_event( $payment );
828
		}
829
830
		return $payment;
831
	}
832
833
	/**
834
	 * Get pages.
835
	 *
836
	 * @return array
837
	 */
838
	public function get_pages() {
839
		$return = array();
840
841
		$pages = array(
842
			'completed' => __( 'Completed', 'pronamic_ideal' ),
843
			'cancel'    => __( 'Canceled', 'pronamic_ideal' ),
844
			'expired'   => __( 'Expired', 'pronamic_ideal' ),
845
			'error'     => __( 'Error', 'pronamic_ideal' ),
846
			'unknown'   => __( 'Unknown', 'pronamic_ideal' ),
847
		);
848
849
		foreach ( $pages as $key => $label ) {
850
			$id = sprintf( 'pronamic_pay_%s_page_id', $key );
851
852
			$return[ $id ] = $label;
853
		}
854
855
		return $return;
856
	}
857
}
858