Repository navigation
Expand file tree
/
Copy pathuninstall.php
More file actions
97 lines (80 loc) · 3.37 KB
/
Copy pathuninstall.php
File metadata and controls
97 lines (80 loc) · 3.37 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
<?php
/**
* Removes everything the plugin stored, when the site asked for that.
*
* @package Assinafy\WP
*/
declare(strict_types=1);
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
die;
}
$assinafy_autoload = __DIR__ . '/vendor-prefixed/autoload.php';
if ( is_readable( $assinafy_autoload ) ) {
require_once $assinafy_autoload;
}
unset( $assinafy_autoload );
if ( ! class_exists( \Assinafy\WP\Settings::class ) ) {
return;
}
\Assinafy\WP\Plugin::for_each_site(
static function (): void {
// Outside the retention gate: it covers settings and document records, and once the
// plugin is deleted no code is left that could revoke a role grant.
\Assinafy\WP\Capabilities::uninstall();
if ( ! (bool) get_option( \Assinafy\WP\Settings::OPTION_DELETE_DATA, false ) ) {
return;
}
// Revoke before the tokens are deleted: afterwards nothing can end the Assinafy grant.
// Nobody is left to retry, so wait out a refresh in progress, until any lease taken now
// has ended, rather than delete the token it is about to replace.
$assinafy_oauth = new \Assinafy\WP\OAuthConnection( new \Assinafy\WP\Credentials() );
$assinafy_until = time() + \Assinafy\WP\RefreshLock::LEASE_SECONDS + 1;
while ( 'busy' === $assinafy_oauth->disconnect_current() && time() <= $assinafy_until ) {
sleep( 1 );
}
// Use the registry so newly added settings cannot survive an opted-in uninstall.
foreach ( array_keys( \Assinafy\WP\Settings::OPTIONS ) as $assinafy_option ) {
delete_option( $assinafy_option );
}
delete_option( \Assinafy\WP\Log::OPTION );
delete_option( \Assinafy\WP\Webhook\SigningSecret::LOCK_NAME . '.lock' );
$assinafy_retained = 0;
do {
$assinafy_documents = get_posts(
array(
'post_type' => \Assinafy\WP\Documents\DocumentPostType::POST_TYPE,
'post_status' => array_values( get_post_stati() ),
'numberposts' => 100,
'offset' => $assinafy_retained,
'orderby' => 'ID',
'order' => 'ASC',
'fields' => 'ids',
'no_found_rows' => true,
// phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.SuppressFilters_suppress_filters -- Uninstall must include all plugin records regardless of theme or language filters.
'suppress_filters' => true,
)
);
foreach ( $assinafy_documents as $assinafy_document_id ) {
if ( ! wp_delete_post( (int) $assinafy_document_id, true ) ) {
++$assinafy_retained;
}
}
$assinafy_has_more = 100 === count( $assinafy_documents );
} while ( $assinafy_has_more );
\Assinafy\WP\Plugin::deactivate( false );
// Enumerate only plugin transients and atomic send locks, then invalidate WP caches.
global $wpdb;
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Dynamic transient names have no enumeration API; this is a one-off uninstall.
$assinafy_transients = $wpdb->get_col(
$wpdb->prepare(
"SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s OR option_name LIKE %s",
$wpdb->esc_like( '_transient_assinafy_' ) . '%',
$wpdb->esc_like( '_transient_timeout_assinafy_' ) . '%',
$wpdb->esc_like( \Assinafy\WP\Documents\SendService::LOCK_PREFIX ) . '%' . $wpdb->esc_like( '.lock' )
)
);
foreach ( $assinafy_transients as $assinafy_transient ) {
delete_option( (string) $assinafy_transient );
}
}
);