PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 4.16.9
GiveWP – Donation Plugin and Fundraising Platform v4.16.9
4.16.9 4.16.8.1 4.16.8 4.16.7.2 4.16.7.1 4.16.7 4.16.6.1 4.16.6 4.16.5.1 4.16.5 4.16.4 4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 All 255 releases
give / includes / admin / tools / data / class-give-tools-reset-stats.php

class-give-tools-reset-stats.php in GiveWP – Donation Plugin and Fundraising Platform 4.16.9, at includes/admin/tools/data/class-give-tools-reset-stats.php

489 lines 12.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Recount income and stats
4 *
5 * This class handles batch processing of resetting donations and income stats.
6 *
7 * @subpackage Admin/Tools/Give_Tools_Reset_Stats
8 * @copyright Copyright (c) 2016, GiveWP
9 * @license https://opensource.org/licenses/gpl-license GNU Public License
10 * @since 1.5
11 */
12
13 // Exit if accessed directly.
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit;
16 }
17
18 /**
19 * Give_Tools_Reset_Stats Class
20 *
21 * @since 1.5
22 */
23 class Give_Tools_Reset_Stats extends Give_Batch_Export {
24
25 /**
26 * Our export type. Used for export-type specific filters/actions
27 *
28 * @var string
29 * @since 1.5
30 */
31 public $export_type = '';
32
33 /**
34 * Allows for a non-form batch processing to be run.
35 *
36 * @since 1.5
37 * @var boolean
38 */
39 public $is_void = true;
40
41 /**
42 * Sets the number of items to pull on each step
43 *
44 * @since 1.5
45 * @var integer
46 */
47 public $per_step = 30;
48
49 /**
50 * Success message to display when reset is complete
51 *
52 * @since 4.10.0
53 * @var string
54 */
55 public $message = '';
56
57 /**
58 * Constructor.
59 */
60 public function __construct( $_step = 1 ) {
61 parent::__construct( $_step );
62
63 $this->is_writable = true;
64 }
65
66 /**
67 * Get the Export Data
68 *
69 * @access public
70 * @since 4.10.0 Added deletion logic for campaigns, campaign pages, subscriptions, events, logs, revenue, usermeta, etc.
71 * @since 1.5
72 * @global object $wpdb Used to query the database using the WordPress
73 * Database API
74 * @return bool $data The data for the CSV file
75 */
76 public function get_data() {
77 global $wpdb;
78
79 $items = $this->get_stored_data( 'give_temp_reset_ids' );
80
81 if ( ! is_array( $items ) ) {
82 return false;
83 }
84
85 $offset = ( $this->step - 1 ) * $this->per_step;
86 $step_items = array_slice( $items, $offset, $this->per_step );
87
88 if ( $step_items ) {
89
90 $step_ids = [
91 'customers' => [],
92 'forms' => [],
93 'other' => [],
94 ];
95
96 foreach ( $step_items as $item ) {
97
98 switch ( $item['type'] ) {
99 case 'customer':
100 $step_ids['customers'][] = $item['id'];
101 break;
102 case 'forms':
103 $step_ids['give_forms'][] = $item['id'];
104 break;
105 default:
106 $item_type = apply_filters( 'give_reset_item_type', 'other', $item );
107 $step_ids[ $item_type ][] = $item['id'];
108 break;
109 }
110 }
111
112 $sql = [];
113 $meta_table = give_v20_bc_table_details( 'form' );
114 $donor_meta_table_name = Give()->donor_meta->table_name;
115
116 foreach ( $step_ids as $type => $ids ) {
117
118 if ( empty( $ids ) ) {
119 continue;
120 }
121
122 $ids = implode( ',', $ids );
123
124 switch ( $type ) {
125 case 'customers':
126 // Delete all the Give related donor and its meta.
127 $sql[] = "DELETE FROM {$wpdb->donors}";
128 $sql[] = "DELETE FROM {$donor_meta_table_name}";
129 break;
130 case 'forms':
131 $sql[] = "UPDATE {$meta_table['name']} SET meta_value = 0 WHERE meta_key = '_give_form_sales' AND {$meta_table['column']['id']} IN ($ids)";
132 $sql[] = "UPDATE {$meta_table['name']} SET meta_value = 0.00 WHERE meta_key = '_give_form_earnings' AND {$meta_table['column']['id']} IN ($ids)";
133 break;
134
135 case 'other':
136 // Delete main entries of forms and donations exists in posts table.
137 $sql[] = "DELETE FROM {$wpdb->posts} WHERE id IN ($ids)";
138
139 // Delete all the meta rows of form exists in form meta table.
140 $sql[] = "DELETE FROM {$wpdb->formmeta}";
141
142 // Delete all the meta rows of donation exists in donation meta table.
143 $sql[] = "DELETE FROM {$wpdb->prefix}give_donationmeta";
144
145 // Delete all the Give related sequential ordering entries for donations.
146 $sql[] = "DELETE FROM {$wpdb->prefix}give_sequential_ordering WHERE payment_id IN ($ids)";
147
148 // Delete all the Give related comments and its meta.
149 $sql[] = "DELETE FROM {$wpdb->give_comments}";
150 $sql[] = "DELETE FROM {$wpdb->give_commentmeta}";
151
152 // Delete all the Give sessions data.
153 $sql[] = "DELETE FROM {$wpdb->prefix}give_sessions";
154
155 // Delete all Give logs data.
156 $sql[] = "DELETE FROM {$wpdb->prefix}give_log";
157
158 // Delete all Give revenue data.
159 $sql[] = "DELETE FROM {$wpdb->prefix}give_revenue";
160
161 // Delete campaigns and related data
162 $sql[] = "DELETE FROM {$wpdb->prefix}give_campaign_forms";
163 $sql[] = "DELETE FROM {$wpdb->prefix}give_campaigns";
164
165 // Delete GiveWP Campaign Pages and their meta data
166 $sql[] = "DELETE FROM {$wpdb->posts} WHERE post_type = 'page' AND id IN (SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = 'give_campaign_id')";
167 $sql[] = "DELETE FROM {$wpdb->postmeta} WHERE meta_key = 'give_campaign_id'";
168
169 // Delete subscriptions and related data
170 $sql[] = "DELETE FROM {$wpdb->prefix}give_subscriptionmeta";
171 $sql[] = "DELETE FROM {$wpdb->prefix}give_subscriptions";
172
173 // Delete events and related data
174 $sql[] = "DELETE FROM {$wpdb->prefix}give_event_tickets";
175 $sql[] = "DELETE FROM {$wpdb->prefix}give_event_ticket_types";
176 $sql[] = "DELETE FROM {$wpdb->prefix}give_events";
177
178 // Clear all Give user meta data (notices, preferences, etc.)
179 $sql[] = "DELETE FROM {$wpdb->usermeta} WHERE meta_key LIKE '%give%'";
180
181 // Reset GiveWP options to default values (preserve essential ones)
182 // Essential options that must be preserved to prevent plugin deactivation issues
183 $essential_options = [
184 'give_version', // Plugin version - needed for upgrade detection
185 'give_completed_upgrades', // Completed upgrade routines - prevents re-running
186 'give_default_api_version', // API version - needed for API functionality
187 '_give_table_check', // Database table check - prevents table recreation
188 'give_temp_reset_ids', // Temporary reset data used by this class
189 'give_settings', // Plugin settings - preserve to avoid pages recreation
190 ];
191
192 // Create SQL placeholder string for the essential options list
193 $essential_options_placeholder = implode( "','", $essential_options );
194 // Delete all GiveWP options except the essential ones to prevent deactivation issues
195 $sql[] = "DELETE FROM {$wpdb->options} WHERE option_name LIKE '%give%' AND option_name NOT IN ('{$essential_options_placeholder}')";
196
197 // Clear Action Scheduler data related to GiveWP
198 $sql[] = "DELETE FROM {$wpdb->prefix}actionscheduler_actions WHERE hook LIKE '%give%'";
199 $sql[] = "DELETE FROM {$wpdb->prefix}actionscheduler_groups WHERE slug LIKE '%give%'";
200
201 // Delete Give related categories and tags data from taxonomy tables.
202 $sql[] = $wpdb->prepare(
203 "
204 DELETE FROM $wpdb->terms
205 WHERE $wpdb->terms.term_id IN
206 (
207 SELECT $wpdb->term_taxonomy.term_id
208 FROM $wpdb->term_taxonomy
209 WHERE $wpdb->term_taxonomy.taxonomy = %s
210 OR $wpdb->term_taxonomy.taxonomy = %s
211 )
212 ",
213 [ 'give_forms_category', 'give_forms_tag' ]
214 );
215
216 $sql[] = $wpdb->prepare(
217 "
218 DELETE FROM $wpdb->term_taxonomy
219 WHERE $wpdb->term_taxonomy.taxonomy = %s
220 OR $wpdb->term_taxonomy.taxonomy = %s
221 ",
222 [ 'give_forms_category', 'give_forms_tag' ]
223 );
224
225 break;
226 }
227
228 if ( ! in_array( $type, [ 'customers', 'forms', 'other' ] ) ) {
229 // Allows other types of custom post types to filter on their own post_type
230 // and add items to the query list, for the IDs found in their post type.
231 $sql = apply_filters( "give_reset_add_queries_{$type}", $sql, $ids );
232 }
233 }
234
235 if ( is_array( $sql ) && count( $sql ) > 0 ) {
236 foreach ( $sql as $query ) {
237 $wpdb->query( $query );
238 }
239 }
240
241 return true;
242
243 }// End if().
244
245 return false;
246
247 }
248
249 /**
250 * Return the calculated completion percentage.
251 *
252 * @since 4.10.0 Check if items are set before counting to prevent fatal errors on PHP 8
253 * @since 1.5
254 * @return int
255 */
256 public function get_percentage_complete() {
257
258 $items = $this->get_stored_data( 'give_temp_reset_ids' );
259 $total = $items ? count( $items ) : 0;
260
261 $percentage = 100;
262
263 if ( $total > 0 ) {
264 $percentage = ( ( $this->per_step * $this->step ) / $total ) * 100;
265 }
266
267 if ( $percentage > 100 ) {
268 $percentage = 100;
269 }
270
271 return $percentage;
272 }
273
274 /**
275 * Set the properties specific to the payments export.
276 *
277 * @since 1.5
278 *
279 * @param array $request The Form Data passed into the batch processing.
280 */
281 public function set_properties( $request ) {
282 }
283
284 /**
285 * Process a step
286 *
287 * @since 4.10.0 Updated success message
288 * @since 1.5
289 * @return bool
290 */
291 public function process_step() {
292
293 if ( ! $this->can_export() ) {
294 wp_die(
295 esc_html__( 'You do not have permission to reset data.', 'give' ),
296 esc_html__( 'Error', 'give' ),
297 [
298 'response' => 403,
299 ]
300 );
301 }
302
303 $had_data = $this->get_data();
304
305 if ( $had_data ) {
306 $this->done = false;
307
308 return true;
309 } else {
310 update_option( 'give_earnings_total', 0, false );
311 Give_Cache::delete( Give_Cache::get_key( 'give_estimated_monthly_stats' ) );
312
313 $this->delete_data( 'give_temp_reset_ids' );
314
315 $this->done = true;
316 $this->message = esc_html__( 'Successfully reset data for campaigns, campaign pages, donation forms, subscriptions, events, revenue, donation counts, logs, etc.', 'give' );
317
318 return false;
319 }
320 }
321
322 /**
323 * Headers
324 */
325 public function headers() {
326 give_ignore_user_abort();
327 }
328
329 /**
330 * Perform the export
331 *
332 * @access public
333 * @since 1.5
334 * @return void
335 */
336 public function export() {
337
338 // Set headers
339 $this->headers();
340
341 give_die();
342 }
343
344 /**
345 * Pre Fetch
346 */
347 public function pre_fetch() {
348
349 if ( $this->step == 1 ) {
350 $this->delete_data( 'give_temp_reset_ids' );
351 }
352
353 $items = get_option( 'give_temp_reset_ids', false );
354
355 if ( false === $items ) {
356 $items = [];
357
358 $give_types_for_reset = [ 'give_forms', 'give_payment' ];
359 $give_types_for_reset = apply_filters( 'give_reset_store_post_types', $give_types_for_reset );
360
361 $args = apply_filters(
362 'give_tools_reset_stats_total_args',
363 [
364 'post_type' => $give_types_for_reset,
365 'post_status' => 'any',
366 'posts_per_page' => - 1,
367 ]
368 );
369
370 $posts = get_posts( $args );
371 foreach ( $posts as $post ) {
372 $items[] = [
373 'id' => (int) $post->ID,
374 'type' => $post->post_type,
375 ];
376 }
377
378 $donor_args = [
379 'number' => - 1,
380 ];
381 $donors = Give()->donors->get_donors( $donor_args );
382 foreach ( $donors as $donor ) {
383 $items[] = [
384 'id' => (int) $donor->id,
385 'type' => 'customer',
386 ];
387 }
388
389
390 // Allow filtering of items to remove with an unassociative array for each item
391 // The array contains the unique ID of the item, and a 'type' for you to use in the execution of the get_data method
392 $items = apply_filters( 'give_reset_items', $items );
393
394 $this->store_data( 'give_temp_reset_ids', $items );
395 }// End if().
396
397 }
398
399 /**
400 * Given a key, get the information from the Database Directly.
401 *
402 * @since 1.5
403 *
404 * @param string $key The option_name
405 *
406 * @return mixed Returns the data from the database.
407 */
408 private function get_stored_data( $key ) {
409 global $wpdb;
410 $value = $wpdb->get_var( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s", $key ) );
411
412 if ( empty( $value ) ) {
413 return false;
414 }
415
416 $maybe_json = json_decode( $value );
417 if ( ! is_null( $maybe_json ) ) {
418 $value = json_decode( $value, true );
419 }
420
421 return (array) $value;
422 }
423
424 /**
425 * Give a key, store the value.
426 *
427 * @since 1.5
428 *
429 * @param string $key The option_name.
430 * @param mixed $value The value to store.
431 *
432 * @return void
433 */
434 private function store_data( $key, $value ) {
435 global $wpdb;
436
437 $value = is_array( $value ) ? wp_json_encode( $value ) : esc_attr( $value );
438
439 $data = [
440 'option_name' => $key,
441 'option_value' => $value,
442 'autoload' => 'no',
443 ];
444
445 $formats = [
446 '%s',
447 '%s',
448 '%s',
449 ];
450
451 $wpdb->replace( $wpdb->options, $data, $formats );
452 }
453
454 /**
455 * Delete an option
456 *
457 * @since 1.5
458 *
459 * @param string $key The option_name to delete
460 *
461 * @return void
462 */
463 private function delete_data( $key ) {
464 global $wpdb;
465 $wpdb->delete(
466 $wpdb->options,
467 [
468 'option_name' => $key,
469 ]
470 );
471 }
472
473 /**
474 * Unset the properties specific to the donors export.
475 *
476 * @since 2.3.0
477 *
478 * @param array $request
479 * @param Give_Batch_Export $export
480 */
481 public function unset_properties( $request, $export ) {
482 if ( $export->done ) {
483 // Delete all the donation ids.
484 $this->delete_data( 'give_temp_reset_ids' );
485 }
486 }
487
488 }
489