Passed
Push — master ( 052e2f...235485 )
by Chris
02:49
created

class-edu-klarnacheckout.php (25 issues)

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 5 and the first side effect is on line 2.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
defined( 'ABSPATH' ) || die( 'This plugin must be run within the scope of WordPress.' );
3
4
if ( ! class_exists( 'EDU_KlarnaCheckout' ) ) {
5
	class EDU_KlarnaCheckout extends EDU_Integration {
0 ignored issues
show
The type EDU_Integration was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
6
		public function __construct() {
7
			$this->id          = 'eduadmin-klarnacheckout';
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
8
			$this->displayName = __( 'Klarna Checkout', 'eduadmin-wp-klarna-checkout' );
0 ignored issues
show
Bug Best Practice introduced by
The property displayName does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
9
			$this->description = '';
0 ignored issues
show
Bug Best Practice introduced by
The property description does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
10
11
			$this->init_form_fields();
12
			$this->init_settings();
13
14
			add_action( 'eduadmin-checkpaymentplugins', array( $this, 'intercept_booking' ) );
15
			add_action( 'eduadmin-processbooking', array( $this, 'process_booking' ) );
16
			add_action( 'eduadmin-bookingcompleted', array( $this, 'process_klarnaresponse' ) );
17
			add_action( 'wp_loaded', array( $this, 'process_paymentstatus' ) );
18
19
			add_shortcode( 'eduadmin-klarna-testpage', array( $this, 'test_page' ) );
20
		}
21
22
		/**
23
		 * @param $attributes
24
		 */
25
		public function test_page( $attributes ) {
26
			$attributes = shortcode_atts(
27
				array(
28
					'bookingid' => 0,
29
				),
30
				normalize_empty_atts( $attributes ),
0 ignored issues
show
The function normalize_empty_atts was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

30
				/** @scrutinizer ignore-call */ 
31
    normalize_empty_atts( $attributes ),
Loading history...
31
				'test_page'
32
			);
33
34
			$event_booking = EDUAPI()->OData->Bookings->GetItem(
0 ignored issues
show
The function EDUAPI was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

34
			$event_booking = /** @scrutinizer ignore-call */ EDUAPI()->OData->Bookings->GetItem(
Loading history...
35
				intval( $attributes['bookingid'] ),
36
				null,
37
				'Customer($select=CustomerId;),ContactPerson($select=PersonId;),OrderRows',
38
				false
39
			);
40
			$_customer     = EDUAPI()->OData->Customers->GetItem(
41
				$event_booking['Customer']['CustomerId'],
42
				null,
43
				null,
44
				false
45
			);
46
			$_contact      = EDUAPI()->OData->Persons->GetItem(
47
				$event_booking['ContactPerson']['PersonId'],
48
				null,
49
				null,
50
				false
51
			);
52
53
			$ebi = new EduAdmin_BookingInfo( $event_booking, $_customer, $_contact );
0 ignored issues
show
The type EduAdmin_BookingInfo was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
54
55
			if ( ! empty( EDU()->session['klarna-order-id'] ) && ! empty( $_GET['klarna_order_id'] ) && EDU()->session['klarna-order-id'] === $_GET['klarna_order_id'] ) {
0 ignored issues
show
The function EDU was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

55
			if ( ! empty( /** @scrutinizer ignore-call */ EDU()->session['klarna-order-id'] ) && ! empty( $_GET['klarna_order_id'] ) && EDU()->session['klarna-order-id'] === $_GET['klarna_order_id'] ) {
Loading history...
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
Detected usage of a non-sanitized input variable: $_GET
Loading history...
56
				do_action( 'eduadmin-bookingcompleted', $ebi );
57
			} else {
58
				do_action( 'eduadmin-processbooking', $ebi );
59
			}
60
		}
61
62
		/**
63
		 * @param EduAdmin_BookingInfo|null $ebi
64
		 */
65
		public function intercept_booking( $ebi = null ) {
66
			if ( 'no' === $this->get_option( 'enabled', 'no' ) ) {
67
				return;
68
			}
69
70
			if ( ! empty( $_POST['act'] ) && 'bookCourse' === $_POST['act'] ) {
71
				$ebi->NoRedirect = true;
72
			}
73
		}
74
75
		/**
76
		 * @param EduAdmin_BookingInfo|null $ebi
77
		 */
78
		public function process_booking( $ebi = null ) {
79
			if ( 'no' === $this->get_option( 'enabled', 'no' ) ) {
80
				return;
81
			}
82
83
			$ebi->NoRedirect = true;
84
85
			if ( empty( EDU()->session['klarna-order-id'] ) && empty( $_GET['klarna_order_id'] ) ) {
0 ignored issues
show
The function EDU was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

85
			if ( empty( /** @scrutinizer ignore-call */ EDU()->session['klarna-order-id'] ) && empty( $_GET['klarna_order_id'] ) ) {
Loading history...
86
				$checkout = $this->create_checkout( $ebi );
87
88
				$snippet = $checkout['gui']['snippet'];
89
				echo "<div>{$snippet}</div>";
0 ignored issues
show
Expected next thing to be a escaping function, not '"<div>{$snippet}</div>"'
Loading history...
90
			}
91
		}
92
93
		public function process_klarnaresponse() {
94
			if ( 'no' === $this->get_option( 'enabled', 'no' ) ) {
95
				return;
96
			}
97
			$checkout_url  = ! checked( $this->get_option( 'test_mode', 'no' ), '1', false ) ? Klarna_Checkout_Connector::BASE_URL : Klarna_Checkout_Connector::BASE_TEST_URL;
98
			$shared_secret = $this->get_option( 'shared_secret', '' );
99
100
			if ( ! empty( $_GET['klarna_order_id'] ) && ! empty( EDU()->session['klarna-order-id'] ) && EDU()->session['klarna-order-id'] === $_GET['klarna_order_id'] ) {
0 ignored issues
show
The function EDU was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

100
			if ( ! empty( $_GET['klarna_order_id'] ) && ! empty( /** @scrutinizer ignore-call */ EDU()->session['klarna-order-id'] ) && EDU()->session['klarna-order-id'] === $_GET['klarna_order_id'] ) {
Loading history...
101
				try {
102
					$connector = Klarna_Checkout_Connector::create(
103
						$shared_secret,
104
						$checkout_url
105
					);
106
107
					$order_id = EDU()->session['klarna-order-id'];
108
109
					$order = new Klarna_Checkout_Order( $connector, $order_id );
110
111
					$order->fetch();
112
113
					$snippet = $order['gui']['snippet'];
114
					echo "<div>{$snippet}</div>";
0 ignored issues
show
Expected next thing to be a escaping function, not '"<div>{$snippet}</div>"'
Loading history...
115
					EDU()->session['klarna-order-id'] = null;
116
117
				} catch ( Klarna_Checkout_ApiErrorException $ex ) {
118
					EDU()->write_debug( $ex->getMessage() );
119
					EDU()->write_debug( $ex->getPayload() );
120
				}
121
			}
122
		}
123
124
		public function init_form_fields() {
125
			$this->setting_fields = array(
0 ignored issues
show
Bug Best Practice introduced by
The property setting_fields does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
126
				'enabled'       => array(
127
					'title'       => __( 'Enabled', 'edauadmin-wp-klarna-checkout' ),
128
					'type'        => 'checkbox',
129
					'description' => __( 'Enables/Disabled the integration with Klarna Checkout', 'eduadmin-wp-klarna-checkout' ),
130
					'default'     => 'no',
131
				),
132
				'eid'           => array(
133
					'title'       => __( 'EID', 'eduadmin-wp-klarna-checkout' ),
134
					'type'        => 'text',
135
					'description' => __( 'The EID to connect to Klarna Checkout v2', 'eduadmin-wp-klarna-checkout' ),
136
					'default'     => '',
137
				),
138
				'shared_secret' => array(
139
					'title'       => __( 'Shared secret', 'eduadmin-wp-klarna-checkout' ),
140
					'type'        => 'password',
141
					'description' => __( 'The shared secret to connect to Klarna Checkout v2', 'eduadmin-wp-klarna-checkout' ),
142
					'default'     => '',
143
				),
144
				'termsurl'      => array(
145
					'title'       => __( 'Terms and Conditions URL', 'eduadmin-wp-klarna-checkout' ),
146
					'type'        => 'text',
147
					'description' => __( 'This URL is required for Klarna Checkout', 'eduadmin-wp-klarna-checkout' ),
148
					'default'     => '',
149
				),
150
				'test_mode'     => array(
151
					'title'       => __( 'Test mode', 'eduadmin-wp-klarna-checkout' ),
152
					'type'        => 'checkbox',
153
					'description' => __( 'Enables test mode, so you can test the integration', 'eduadmin-wp-klarna-checkout' ),
154
					'default'     => 'no',
155
				),
156
			);
157
		}
158
159
		/**
160
		 * @param EduAdmin_BookingInfo|null $ebi
161
		 *
162
		 * @return Klarna_Checkout_Order|null
163
		 */
164
		public function create_checkout( $ebi = null ) {
165
166
			$checkout_url  = ! checked( $this->get_option( 'test_mode', 'no' ), '1', false ) ? Klarna_Checkout_Connector::BASE_URL : Klarna_Checkout_Connector::BASE_TEST_URL;
167
			$shared_secret = $this->get_option( 'shared_secret', '' );
168
169
			$create = array();
170
171
			$create['locale']            = strtolower( str_replace( '_', '-', get_locale() ) );
172
			$create['purchase_country']  = 'SE';
173
			$create['purchase_currency'] = get_option( 'eduadmin-currency', 'SEK' );
174
175
			$merchant              = array();
176
			$merchant['id']        = $this->get_option( 'eid', '' );
177
			$merchant['terms_uri'] = $this->get_option( 'termsurl', '' );
178
179
			$current_url = esc_url( "{$_SERVER['REQUEST_SCHEME']}://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}" );
180
0 ignored issues
show
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
181
182
			$confirmation_url = add_query_arg(
183
				array(
184
					'klarna_order_id' => '{checkout.order.id}',
185
					'booking_id'      => $ebi->EventBooking['BookingId'],
186
					'edu-valid-form'  => wp_create_nonce( 'edu-booking-confirm' ),
187
					'act'             => 'paymentCompleted'
0 ignored issues
show
Each line in an array declaration must end in a comma
Loading history...
188
				),
189
				$current_url
190
			);
191
192
			$push_url = add_query_arg(
193
				array(
194
					'klarna_order_id' => '{checkout.order.id}',
195
					'booking_id'      => $ebi->EventBooking['BookingId'],
196
					'status'          => 'push',
197
				),
198
				$current_url
199
			);
200
201
			$merchant['checkout_uri']     = $current_url;
202
			$merchant['confirmation_uri'] = $confirmation_url;
203
			$merchant['push_uri']         = $push_url;
204
205
			$create['merchant'] = $merchant;
206
207
			$create['cart']          = array();
208
			$create['cart']['items'] = array();
209
210
			foreach ( $ebi->EventBooking['OrderRows'] as $order_row ) {
211
				$cart_item = array();
212
213
				$cart_item['reference'] = $order_row['ItemNumber'];
214
				$cart_item['name']      = $order_row['Description'];
215
				$cart_item['quantity']  = intval( $order_row['Quantity'] );
216
217
				if ( ! $order_row['PriceIncVat'] ) {
218
					$price_per_unit = $order_row['PricePerUnit'] * ( 1 + ( $order_row['VatPercent'] / 100 ) ) * 100;
219
				} else {
220
					$price_per_unit = $order_row['PricePerUnit'] * 100;
221
				}
222
223
				$cart_item['unit_price']    = $price_per_unit;
224
				$cart_item['tax_rate']      = intval( $order_row['VatPercent'] * 100 );
225
				$cart_item['discount_rate'] = intval( $order_row['DiscountPercent'] * 100 );
226
227
				$create['cart']['items'][] = $cart_item;
228
			}
229
230
			try {
231
				$connector = Klarna_Checkout_Connector::create(
232
					$shared_secret,
233
					$checkout_url
234
				);
235
236
				$order = new Klarna_Checkout_Order( $connector );
237
				$order->create( $create );
238
239
				$order->fetch();
240
241
				$order_id                         = $order['id'];
242
				EDU()->session['klarna-order-id'] = $order_id;
0 ignored issues
show
The function EDU was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

242
				/** @scrutinizer ignore-call */ 
243
    EDU()->session['klarna-order-id'] = $order_id;
Loading history...
243
244
				return $order;
245
			} catch ( Klarna_Checkout_ApiErrorException $ex ) {
246
				EDU()->write_debug( $ex->getMessage() );
247
				EDU()->write_debug( $ex->getPayload() );
248
249
				return null;
250
			}
251
		}
252
253
		public function process_paymentstatus() {
254
			if ( ! empty( $_GET['klarna_order_id'] ) && ! empty( $_GET['status'] ) ) {
255
				$checkout_url  = ! checked( $this->get_option( 'test_mode', 'no' ), '1', false ) ? Klarna_Checkout_Connector::BASE_URL : Klarna_Checkout_Connector::BASE_TEST_URL;
256
				$shared_secret = $this->get_option( 'shared_secret', '' );
257
258
				try {
259
					$connector = Klarna_Checkout_Connector::create(
260
						$shared_secret,
261
						$checkout_url
262
					);
263
264
					$order_id = $_GET['klarna_order_id'];
0 ignored issues
show
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
Detected usage of a non-sanitized input variable: $_GET
Loading history...
265
266
					$order = new Klarna_Checkout_Order( $connector, $order_id );
267
268
					$order->fetch();
269
270
					if ( 'checkout_complete' === $order['status'] ) {
271
						$update           = array();
272
						$update['status'] = 'created';
273
						$order->update( $update );
274
					}
275
					exit( 0 );
0 ignored issues
show
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...
276
				} catch ( Klarna_Checkout_ApiErrorException $ex ) {
277
					EDU()->write_debug( $ex->getMessage() );
0 ignored issues
show
The function EDU was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

277
					/** @scrutinizer ignore-call */ 
278
     EDU()->write_debug( $ex->getMessage() );
Loading history...
278
					EDU()->write_debug( $ex->getPayload() );
279
					exit( 1 );
0 ignored issues
show
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...
280
				}
281
			}
282
		}
283
	}
284
}
285