Repository navigation
Expand file tree
/
Copy pathuninstall.php
More file actions
202 lines (182 loc) · 7.52 KB
/
Copy pathuninstall.php
File metadata and controls
202 lines (182 loc) · 7.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
<?php
/**
* Uninstall script for Functionalities plugin.
*
* Removes all plugin data when the user has opted in via the
* "Delete all plugin data when uninstalling" checkbox on the dashboard.
*
* @package Functionalities
*/
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
exit;
}
$functionalities_cleanup_site = static function (): void {
// Always remove the generated Components CSS file.
if ( function_exists( 'wp_upload_dir' ) ) {
$functionalities_upload = wp_upload_dir();
if ( empty( $functionalities_upload['error'] ) ) {
$functionalities_css_dir = rtrim( (string) $functionalities_upload['basedir'], '/\\' ) . '/functionalities';
$functionalities_css_file = $functionalities_css_dir . '/components.css';
if ( is_file( $functionalities_css_file ) ) {
wp_delete_file( $functionalities_css_file );
}
// Attempt to remove directory if empty.
if ( is_dir( $functionalities_css_dir ) ) {
global $wp_filesystem;
if ( ! function_exists( 'WP_Filesystem' ) ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
}
WP_Filesystem();
if ( $wp_filesystem ) {
$wp_filesystem->rmdir( $functionalities_css_dir );
}
}
}
}
// Uninstall removes the code these events execute, even when data is kept.
wp_clear_scheduled_hook( 'functionalities_assumption_background_scan' );
wp_clear_scheduled_hook( 'functionalities_redirect_flush_buffer' );
wp_clear_scheduled_hook( 'functionalities_link_health_batch' );
wp_clear_scheduled_hook( 'functionalities_link_health_weekly' );
wp_clear_scheduled_hook( 'functionalities_activity_prune' );
// Check if user opted in to full data removal.
if ( ! get_option( 'functionalities_delete_data_on_uninstall', false ) ) {
return;
}
// Capture the site's owned path before deleting the key option. Never remove
// the shared parent: other sites may keep their data for a future reinstall.
$functionalities_data_base = rtrim( (string) apply_filters( 'functionalities_data_base_dir', WP_CONTENT_DIR . '/functionalities' ), '/\\' );
$functionalities_data_key = (string) get_option( 'functionalities_data_key', '' );
// --- Plugin options ---
$functionalities_options = array(
'functionalities_content_tools',
'functionalities_link_health',
'functionalities_site_activity',
'functionalities_link_management',
'functionalities_block_cleanup',
'functionalities_editor_links',
'functionalities_snippets',
'functionalities_schema',
'functionalities_components',
'functionalities_fonts',
'functionalities_misc',
'functionalities_login_security',
'functionalities_meta',
'functionalities_content_regression',
'functionalities_assumption_detection',
'functionalities_pwa',
'functionalities_task_manager',
'functionalities_redirect_manager',
'functionalities_svg_icons',
'functionalities_wordpress_7',
'functionalities_data_key',
'functionalities_version',
'functionalities_link_preset_last_good',
'functionalities_redirect_hit_buffer',
// Assumption detection data.
'functionalities_assumptions_detected',
'functionalities_assumptions_ignored',
'functionalities_inline_css_baseline',
'functionalities_assumptions_last_run',
'functionalities_assumption_audit',
'functionalities_assumption_scan_summary',
'functionalities_assumption_scan_status',
// Login security data.
'functionalities_login_lockouts',
// Uninstall preference itself.
'functionalities_delete_data_on_uninstall',
);
foreach ( $functionalities_options as $functionalities_opt ) {
delete_option( $functionalities_opt );
}
// --- Post meta ---
global $wpdb;
$functionalities_meta_keys = array(
'_functionalities_link_health',
'_functionalities_link_health_count',
'_functionalities_link_health_ignored',
'_functionalities_content_snapshot',
'_functionalities_regression_settings',
'_functionalities_regression_status',
'_functionalities_content_audit',
'_gt_content_license',
);
foreach ( $functionalities_meta_keys as $functionalities_meta_key ) {
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Uninstall cleanup requires direct meta_key query; runs once on uninstall only.
$wpdb->delete( $wpdb->postmeta, array( 'meta_key' => $functionalities_meta_key ) );
}
// --- Transients ---
// Login security transients (hashed IP keys).
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Uninstall cleanup requires direct query.
$wpdb->query(
$wpdb->prepare(
"DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s",
$wpdb->esc_like( '_transient_funct_login_' ) . '%',
$wpdb->esc_like( '_transient_timeout_funct_login_' ) . '%'
)
);
// Deduplicated Link Health URL checks (bounded expiring cache).
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Uninstall cleanup.
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", $wpdb->esc_like( '_transient_functionalities_link_health_' ) . '%', $wpdb->esc_like( '_transient_timeout_functionalities_link_health_' ) . '%' ) );
// Redirect manager cache transient.
delete_transient( 'func_redirects_json' );
// Link Management exception preset cache.
delete_transient( 'functionalities_link_preset' );
// Assumption detection schedule transient.
delete_transient( 'functionalities_run_assumption_detection' );
// --- Filesystem data ---
if ( '' === $functionalities_data_base ) {
return;
}
$functionalities_paths = array();
if ( preg_match( '/^[A-Za-z0-9]{8,64}$/', $functionalities_data_key ) ) {
$functionalities_paths[] = $functionalities_data_base . '/' . $functionalities_data_key;
$functionalities_paths[] = $functionalities_data_base . '/.migration-' . $functionalities_data_key . '.lock';
}
$functionalities_paths[] = $functionalities_data_base . '/.directory-key-' . get_current_blog_id() . '.lock';
// Legacy fixed paths have no site ownership marker. They can be removed on a
// single-site installation, but must be retained on multisite to avoid deleting
// a different site's data before it has migrated.
if ( ! is_multisite() ) {
foreach ( array( 'redirects.json', '404-log.json', 'tasks', 'redirects.json.lock', '404-log.json.lock', '.directory-key.lock' ) as $functionalities_legacy_name ) {
$functionalities_paths[] = $functionalities_data_base . '/' . $functionalities_legacy_name;
}
}
foreach ( $functionalities_paths as $functionalities_data_path ) {
if ( ! file_exists( $functionalities_data_path ) ) {
continue;
}
global $wp_filesystem;
if ( ! function_exists( 'WP_Filesystem' ) ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
}
if ( WP_Filesystem() && $wp_filesystem ) {
$wp_filesystem->delete( $functionalities_data_path, true );
}
}
};
if ( is_multisite() ) {
// Bound memory on large networks and honor each site's own preference.
$functionalities_offset = 0;
do {
$functionalities_blog_ids = get_sites(
array(
'fields' => 'ids',
'number' => 100,
'offset' => $functionalities_offset,
)
);
foreach ( $functionalities_blog_ids as $functionalities_blog_id ) {
switch_to_blog( (int) $functionalities_blog_id );
try {
$functionalities_cleanup_site();
} finally {
restore_current_blog();
}
}
$functionalities_blog_count = count( $functionalities_blog_ids );
$functionalities_offset += $functionalities_blog_count;
} while ( 100 === $functionalities_blog_count );
} else {
$functionalities_cleanup_site();
}