This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | if ( ! class_exists( 'WC_Abstract_Privacy' ) ) { |
||
3 | return; |
||
4 | } |
||
5 | |||
6 | class WC_Stripe_Privacy extends WC_Abstract_Privacy { |
||
7 | /** |
||
8 | * Constructor |
||
9 | * |
||
10 | */ |
||
11 | public function __construct() { |
||
12 | parent::__construct( __( 'Stripe', 'woocommerce-gateway-stripe' ) ); |
||
13 | |||
14 | $this->add_exporter( 'woocommerce-gateway-stripe-order-data', __( 'WooCommerce Stripe Order Data', 'woocommerce-gateway-stripe' ), array( $this, 'order_data_exporter' ) ); |
||
15 | |||
16 | if ( function_exists( 'wcs_get_subscriptions' ) ) { |
||
17 | $this->add_exporter( 'woocommerce-gateway-stripe-subscriptions-data', __( 'WooCommerce Stripe Subscriptions Data', 'woocommerce-gateway-stripe' ), array( $this, 'subscriptions_data_exporter' ) ); |
||
18 | } |
||
19 | |||
20 | $this->add_exporter( 'woocommerce-gateway-stripe-customer-data', __( 'WooCommerce Stripe Customer Data', 'woocommerce-gateway-stripe' ), array( $this, 'customer_data_exporter' ) ); |
||
21 | |||
22 | $this->add_eraser( 'woocommerce-gateway-stripe-customer-data', __( 'WooCommerce Stripe Customer Data', 'woocommerce-gateway-stripe' ), array( $this, 'customer_data_eraser' ) ); |
||
23 | $this->add_eraser( 'woocommerce-gateway-stripe-order-data', __( 'WooCommerce Stripe Data', 'woocommerce-gateway-stripe' ), array( $this, 'order_data_eraser' ) ); |
||
24 | |||
25 | add_filter( 'woocommerce_get_settings_account', array( $this, 'account_settings' ) ); |
||
26 | } |
||
27 | |||
28 | /** |
||
29 | * Add retention settings to account tab. |
||
30 | * |
||
31 | * @param array $settings |
||
32 | * @return array $settings Updated |
||
33 | */ |
||
34 | public function account_settings( $settings ) { |
||
35 | $insert_setting = array( |
||
36 | array( |
||
37 | 'title' => __( 'Retain Stripe Data', 'woocommerce-gateway-stripe' ), |
||
38 | 'desc_tip' => __( 'Retains any Stripe data such as Stripe customer ID, source ID.', 'woocommerce-gateway-stripe' ), |
||
39 | 'id' => 'woocommerce_gateway_stripe_retention', |
||
40 | 'type' => 'relative_date_selector', |
||
41 | 'placeholder' => __( 'N/A', 'woocommerce-gateway-stripe' ), |
||
42 | 'default' => '', |
||
43 | 'autoload' => false, |
||
44 | ), |
||
45 | ); |
||
46 | |||
47 | $index = null; |
||
48 | |||
49 | foreach ( $settings as $key => $value) { |
||
50 | if ( 'sectionend' === $value[ 'type' ] && 'personal_data_retention' === $value[ 'id' ] ) { |
||
51 | $index = $key; |
||
52 | break; |
||
53 | } |
||
54 | } |
||
55 | |||
56 | if ( ! is_null( $index ) ) { |
||
57 | array_splice( $settings, $index, 0, $insert_setting ); |
||
58 | } |
||
59 | |||
60 | return $settings; |
||
61 | } |
||
62 | |||
63 | /** |
||
64 | * Returns a list of orders that are using one of Stripe's payment methods. |
||
65 | * |
||
66 | * @param string $email_address |
||
67 | * @param int $page |
||
68 | * |
||
69 | * @return array WP_Post |
||
70 | */ |
||
71 | protected function get_stripe_orders( $email_address, $page ) { |
||
72 | $user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data. |
||
73 | |||
74 | $order_query = array( |
||
75 | 'payment_method' => array( 'stripe', 'stripe_alipay', 'stripe_bancontact', 'stripe_eps', 'stripe_giropay', 'stripe_ideal', 'stripe_multibanco', 'stripe_p24', 'stripe_sepa', 'stripe_sofort' ), |
||
76 | 'limit' => 10, |
||
77 | 'page' => $page, |
||
78 | ); |
||
79 | |||
80 | if ( $user instanceof WP_User ) { |
||
0 ignored issues
–
show
|
|||
81 | $order_query['customer_id'] = (int) $user->ID; |
||
82 | } else { |
||
83 | $order_query['billing_email'] = $email_address; |
||
84 | } |
||
85 | |||
86 | return wc_get_orders( $order_query ); |
||
87 | } |
||
88 | |||
89 | /** |
||
90 | * Gets the message of the privacy to display. |
||
91 | * |
||
92 | */ |
||
93 | public function get_privacy_message() { |
||
94 | /* translators: %s URL to docs */ |
||
95 | return wpautop( sprintf( __( 'By using this extension, you may be storing personal data or sharing data with an external service. <a href="%s" target="_blank">Learn more about how this works, including what you may want to include in your privacy policy.</a>', 'woocommerce-gateway-stripe' ), 'https://docs.woocommerce.com/document/privacy-payments/#woocommerce-gateway-stripe' ) ); |
||
96 | } |
||
97 | |||
98 | /** |
||
99 | * Handle exporting data for Orders. |
||
100 | * |
||
101 | * @param string $email_address E-mail address to export. |
||
102 | * @param int $page Pagination of data. |
||
103 | * |
||
104 | * @return array |
||
105 | */ |
||
106 | public function order_data_exporter( $email_address, $page = 1 ) { |
||
107 | $done = false; |
||
0 ignored issues
–
show
$done is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
108 | $data_to_export = array(); |
||
109 | |||
110 | $orders = $this->get_stripe_orders( $email_address, (int) $page ); |
||
111 | |||
112 | $done = true; |
||
113 | |||
114 | View Code Duplication | if ( 0 < count( $orders ) ) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
115 | foreach ( $orders as $order ) { |
||
116 | $data_to_export[] = array( |
||
117 | 'group_id' => 'woocommerce_orders', |
||
118 | 'group_label' => __( 'Orders', 'woocommerce-gateway-stripe' ), |
||
119 | 'item_id' => 'order-' . $order->get_id(), |
||
120 | 'data' => array( |
||
121 | array( |
||
122 | 'name' => __( 'Stripe payment id', 'woocommerce-gateway-stripe' ), |
||
123 | 'value' => get_post_meta( $order->get_id(), '_stripe_source_id', true ), |
||
124 | ), |
||
125 | array( |
||
126 | 'name' => __( 'Stripe customer id', 'woocommerce-gateway-stripe' ), |
||
127 | 'value' => get_post_meta( $order->get_id(), '_stripe_customer_id', true ), |
||
128 | ), |
||
129 | ), |
||
130 | ); |
||
131 | } |
||
132 | |||
133 | $done = 10 > count( $orders ); |
||
134 | } |
||
135 | |||
136 | return array( |
||
137 | 'data' => $data_to_export, |
||
138 | 'done' => $done, |
||
139 | ); |
||
140 | } |
||
141 | |||
142 | /** |
||
143 | * Handle exporting data for Subscriptions. |
||
144 | * |
||
145 | * @param string $email_address E-mail address to export. |
||
146 | * @param int $page Pagination of data. |
||
147 | * |
||
148 | * @return array |
||
149 | */ |
||
150 | public function subscriptions_data_exporter( $email_address, $page = 1 ) { |
||
151 | $done = false; |
||
0 ignored issues
–
show
$done is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
152 | $page = (int) $page; |
||
153 | $data_to_export = array(); |
||
154 | |||
155 | $meta_query = array( |
||
156 | 'relation' => 'AND', |
||
157 | array( |
||
158 | 'key' => '_payment_method', |
||
159 | 'value' => array( 'stripe', 'stripe_alipay', 'stripe_bancontact', 'stripe_eps', 'stripe_giropay', 'stripe_ideal', 'stripe_multibanco', 'stripe_p24', 'stripe_sepa', 'stripe_sofort' ), |
||
160 | 'compare' => 'IN', |
||
161 | ), |
||
162 | array( |
||
163 | 'key' => '_billing_email', |
||
164 | 'value' => $email_address, |
||
165 | 'compare' => '=', |
||
166 | ), |
||
167 | ); |
||
168 | |||
169 | $subscription_query = array( |
||
170 | 'posts_per_page' => 10, |
||
171 | 'page' => $page, |
||
172 | 'meta_query' => $meta_query, |
||
173 | ); |
||
174 | |||
175 | $subscriptions = wcs_get_subscriptions( $subscription_query ); |
||
176 | |||
177 | $done = true; |
||
178 | |||
179 | View Code Duplication | if ( 0 < count( $subscriptions ) ) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
180 | foreach ( $subscriptions as $subscription ) { |
||
181 | $data_to_export[] = array( |
||
182 | 'group_id' => 'woocommerce_subscriptions', |
||
183 | 'group_label' => __( 'Subscriptions', 'woocommerce-gateway-stripe' ), |
||
184 | 'item_id' => 'subscription-' . $subscription->get_id(), |
||
185 | 'data' => array( |
||
186 | array( |
||
187 | 'name' => __( 'Stripe payment id', 'woocommerce-gateway-stripe' ), |
||
188 | 'value' => get_post_meta( $subscription->get_id(), '_stripe_source_id', true ), |
||
189 | ), |
||
190 | array( |
||
191 | 'name' => __( 'Stripe customer id', 'woocommerce-gateway-stripe' ), |
||
192 | 'value' => get_post_meta( $subscription->get_id(), '_stripe_customer_id', true ), |
||
193 | ), |
||
194 | ), |
||
195 | ); |
||
196 | } |
||
197 | |||
198 | $done = 10 > count( $subscriptions ); |
||
199 | } |
||
200 | |||
201 | return array( |
||
202 | 'data' => $data_to_export, |
||
203 | 'done' => $done, |
||
204 | ); |
||
205 | } |
||
206 | |||
207 | /** |
||
208 | * Finds and exports customer data by email address. |
||
209 | * |
||
210 | * @param string $email_address The user email address. |
||
211 | * @param int $page Page. |
||
212 | * @return array An array of personal data in name value pairs |
||
213 | */ |
||
214 | public function customer_data_exporter( $email_address, $page ) { |
||
215 | $user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data. |
||
216 | $data_to_export = array(); |
||
217 | |||
218 | if ( $user instanceof WP_User ) { |
||
0 ignored issues
–
show
The class
WP_User does not exist. Did you forget a USE statement, or did you not list all dependencies?
This error could be the result of: 1. Missing dependenciesPHP Analyzer uses your Are you sure this class is defined by one of your dependencies, or did you maybe
not list a dependency in either the 2. Missing use statementPHP does not complain about undefined classes in if ($x instanceof DoesNotExist) {
// Do something.
}
If you have not tested against this specific condition, such errors might go unnoticed. ![]() |
|||
219 | $stripe_user = new WC_Stripe_Customer( $user->ID ); |
||
220 | |||
221 | $data_to_export[] = array( |
||
222 | 'group_id' => 'woocommerce_customer', |
||
223 | 'group_label' => __( 'Customer Data', 'woocommerce-gateway-stripe' ), |
||
224 | 'item_id' => 'user', |
||
225 | 'data' => array( |
||
226 | array( |
||
227 | 'name' => __( 'Stripe payment id', 'woocommerce-gateway-stripe' ), |
||
228 | 'value' => get_user_option( '_stripe_source_id', $user->ID ), |
||
229 | ), |
||
230 | array( |
||
231 | 'name' => __( 'Stripe customer id', 'woocommerce-gateway-stripe' ), |
||
232 | 'value' => $stripe_user->get_id(), |
||
233 | ), |
||
234 | ), |
||
235 | ); |
||
236 | } |
||
237 | |||
238 | return array( |
||
239 | 'data' => $data_to_export, |
||
240 | 'done' => true, |
||
241 | ); |
||
242 | } |
||
243 | |||
244 | /** |
||
245 | * Finds and erases customer data by email address. |
||
246 | * |
||
247 | * @param string $email_address The user email address. |
||
248 | * @param int $page Page. |
||
249 | * @return array An array of personal data in name value pairs |
||
250 | */ |
||
251 | public function customer_data_eraser( $email_address, $page ) { |
||
252 | $page = (int) $page; |
||
0 ignored issues
–
show
$page is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
253 | $user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data. |
||
254 | $stripe_customer_id = ''; |
||
255 | $stripe_source_id = ''; |
||
256 | |||
257 | if ( $user instanceof WP_User ) { |
||
0 ignored issues
–
show
The class
WP_User does not exist. Did you forget a USE statement, or did you not list all dependencies?
This error could be the result of: 1. Missing dependenciesPHP Analyzer uses your Are you sure this class is defined by one of your dependencies, or did you maybe
not list a dependency in either the 2. Missing use statementPHP does not complain about undefined classes in if ($x instanceof DoesNotExist) {
// Do something.
}
If you have not tested against this specific condition, such errors might go unnoticed. ![]() |
|||
258 | $stripe_customer_id = get_user_option( '_stripe_customer_id', $user->ID ); |
||
259 | $stripe_source_id = get_user_option( '_stripe_source_id', $user->ID ); |
||
260 | } |
||
261 | |||
262 | $items_removed = false; |
||
263 | $messages = array(); |
||
264 | |||
265 | if ( ! empty( $stripe_customer_id ) || ! empty( $stripe_source_id ) ) { |
||
266 | $items_removed = true; |
||
267 | delete_user_option( $user->ID, '_stripe_customer_id' ); |
||
268 | delete_user_option( $user->ID, '_stripe_source_id' ); |
||
269 | $messages[] = __( 'Stripe User Data Erased.', 'woocommerce-gateway-stripe' ); |
||
270 | } |
||
271 | |||
272 | return array( |
||
273 | 'items_removed' => $items_removed, |
||
274 | 'items_retained' => false, |
||
275 | 'messages' => $messages, |
||
276 | 'done' => true, |
||
277 | ); |
||
278 | } |
||
279 | |||
280 | /** |
||
281 | * Finds and erases order data by email address. |
||
282 | * |
||
283 | * @param string $email_address The user email address. |
||
284 | * @param int $page Page. |
||
285 | * @return array An array of personal data in name value pairs |
||
286 | */ |
||
287 | public function order_data_eraser( $email_address, $page ) { |
||
288 | $orders = $this->get_stripe_orders( $email_address, (int) $page ); |
||
289 | |||
290 | $items_removed = false; |
||
291 | $items_retained = false; |
||
292 | $messages = array(); |
||
293 | |||
294 | foreach ( (array) $orders as $order ) { |
||
295 | $order = wc_get_order( $order->get_id() ); |
||
296 | |||
297 | list( $removed, $retained, $msgs ) = $this->maybe_handle_order( $order ); |
||
298 | $items_removed |= $removed; |
||
299 | $items_retained |= $retained; |
||
300 | $messages = array_merge( $messages, $msgs ); |
||
301 | |||
302 | list( $removed, $retained, $msgs ) = $this->maybe_handle_subscription( $order ); |
||
303 | $items_removed |= $removed; |
||
304 | $items_retained |= $retained; |
||
305 | $messages = array_merge( $messages, $msgs ); |
||
306 | } |
||
307 | |||
308 | // Tell core if we have more orders to work on still |
||
309 | $done = count( $orders ) < 10; |
||
310 | |||
311 | return array( |
||
312 | 'items_removed' => $items_removed, |
||
313 | 'items_retained' => $items_retained, |
||
314 | 'messages' => $messages, |
||
315 | 'done' => $done, |
||
316 | ); |
||
317 | } |
||
318 | |||
319 | /** |
||
320 | * Handle eraser of data tied to Subscriptions |
||
321 | * |
||
322 | * @param WC_Order $order |
||
323 | * @return array |
||
324 | */ |
||
325 | protected function maybe_handle_subscription( $order ) { |
||
326 | if ( ! class_exists( 'WC_Subscriptions' ) ) { |
||
327 | return array( false, false, array() ); |
||
328 | } |
||
329 | |||
330 | if ( ! wcs_order_contains_subscription( $order ) ) { |
||
331 | return array( false, false, array() ); |
||
332 | } |
||
333 | |||
334 | $subscription = current( wcs_get_subscriptions_for_order( $order->get_id() ) ); |
||
335 | $subscription_id = $subscription->get_id(); |
||
336 | |||
337 | $stripe_source_id = get_post_meta( $subscription_id, '_stripe_source_id', true ); |
||
338 | |||
339 | if ( empty( $stripe_source_id ) ) { |
||
340 | return array( false, false, array() ); |
||
341 | } |
||
342 | |||
343 | View Code Duplication | if ( ! $this->is_retention_expired( $order->get_date_created()->getTimestamp() ) ) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
344 | /* translators: %d Order ID */ |
||
345 | return array( false, true, array( sprintf( __( 'Order ID %d is less than set retention days. Personal data retained. (Stripe)', 'woocommerce-gateway-stripe' ), $order->get_id() ) ) ); |
||
346 | } |
||
347 | |||
348 | if ( $subscription->has_status( apply_filters( 'wc_stripe_privacy_eraser_subs_statuses', array( 'on-hold', 'active' ) ) ) ) { |
||
349 | /* translators: %d Order ID */ |
||
350 | return array( false, true, array( sprintf( __( 'Order ID %d contains an active Subscription. Personal data retained. (Stripe)', 'woocommerce-gateway-stripe' ), $order->get_id() ) ) ); |
||
351 | } |
||
352 | |||
353 | $renewal_orders = WC_Subscriptions_Renewal_Order::get_renewal_orders( $order->get_id() ); |
||
354 | |||
355 | foreach ( $renewal_orders as $renewal_order_id ) { |
||
356 | delete_post_meta( $renewal_order_id, '_stripe_source_id' ); |
||
357 | delete_post_meta( $renewal_order_id, '_stripe_refund_id' ); |
||
358 | delete_post_meta( $renewal_order_id, '_stripe_customer_id' ); |
||
359 | } |
||
360 | |||
361 | delete_post_meta( $subscription_id, '_stripe_source_id' ); |
||
362 | delete_post_meta( $subscription_id, '_stripe_refund_id' ); |
||
363 | delete_post_meta( $subscription_id, '_stripe_customer_id' ); |
||
364 | |||
365 | return array( true, false, array( __( 'Stripe Subscription Data Erased.', 'woocommerce-gateway-stripe' ) ) ); |
||
366 | } |
||
367 | |||
368 | /** |
||
369 | * Handle eraser of data tied to Orders |
||
370 | * |
||
371 | * @param WC_Order $order |
||
372 | * @return array |
||
373 | */ |
||
374 | protected function maybe_handle_order( $order ) { |
||
375 | $order_id = $order->get_id(); |
||
376 | $stripe_source_id = get_post_meta( $order_id, '_stripe_source_id', true ); |
||
377 | $stripe_refund_id = get_post_meta( $order_id, '_stripe_refund_id', true ); |
||
378 | $stripe_customer_id = get_post_meta( $order_id, '_stripe_customer_id', true ); |
||
379 | |||
380 | View Code Duplication | if ( ! $this->is_retention_expired( $order->get_date_created()->getTimestamp() ) ) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
381 | /* translators: %d Order ID */ |
||
382 | return array( false, true, array( sprintf( __( 'Order ID %d is less than set retention days. Personal data retained. (Stripe)', 'woocommerce-gateway-stripe' ), $order->get_id() ) ) ); |
||
383 | } |
||
384 | |||
385 | if ( empty( $stripe_source_id ) && empty( $stripe_refund_id ) && empty( $stripe_customer_id ) ) { |
||
386 | return array( false, false, array() ); |
||
387 | } |
||
388 | |||
389 | delete_post_meta( $order_id, '_stripe_source_id' ); |
||
390 | delete_post_meta( $order_id, '_stripe_refund_id' ); |
||
391 | delete_post_meta( $order_id, '_stripe_customer_id' ); |
||
392 | |||
393 | return array( true, false, array( __( 'Stripe personal data erased.', 'woocommerce-gateway-stripe' ) ) ); |
||
394 | } |
||
395 | |||
396 | /** |
||
397 | * Checks if create date is passed retention duration. |
||
398 | * |
||
399 | */ |
||
400 | public function is_retention_expired( $created_date ) { |
||
401 | $retention = wc_parse_relative_date_option( get_option( 'woocommerce_gateway_stripe_retention' ) ); |
||
402 | $is_expired = false; |
||
403 | $time_span = time() - strtotime( $created_date ); |
||
404 | if ( empty( $retention ) || empty( $created_date ) ) { |
||
405 | return false; |
||
406 | } |
||
407 | switch ( $retention['unit'] ) { |
||
408 | case 'days': |
||
409 | $retention = $retention['number'] * DAY_IN_SECONDS; |
||
410 | if ( $time_span > $retention ) { |
||
411 | $is_expired = true; |
||
412 | } |
||
413 | break; |
||
414 | case 'weeks': |
||
415 | $retention = $retention['number'] * WEEK_IN_SECONDS; |
||
416 | if ( $time_span > $retention ) { |
||
417 | $is_expired = true; |
||
418 | } |
||
419 | break; |
||
420 | case 'months': |
||
421 | $retention = $retention['number'] * MONTH_IN_SECONDS; |
||
422 | if ( $time_span > $retention ) { |
||
423 | $is_expired = true; |
||
424 | } |
||
425 | break; |
||
426 | case 'years': |
||
427 | $retention = $retention['number'] * YEAR_IN_SECONDS; |
||
428 | if ( $time_span > $retention ) { |
||
429 | $is_expired = true; |
||
430 | } |
||
431 | break; |
||
432 | } |
||
433 | return $is_expired; |
||
434 | } |
||
435 | } |
||
436 | |||
437 | new WC_Stripe_Privacy(); |
||
438 |
This error could be the result of:
1. Missing dependencies
PHP Analyzer uses your
composer.json
file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects thecomposer.json
to be in the root folder of your repository.Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the
require
orrequire-dev
section?2. Missing use statement
PHP does not complain about undefined classes in
ìnstanceof
checks. For example, the following PHP code will work perfectly fine:If you have not tested against this specific condition, such errors might go unnoticed.