Skip to content

Commit c5bb1d5

Browse files
authored
Merge branch 'develop' into feature/show-category-pull
2 parents c7809e2 + 0901e23 commit c5bb1d5

5 files changed

Lines changed: 284 additions & 9 deletions

File tree

includes/bootstrap.php

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,75 @@ function() {
224224
1
225225
);
226226

227+
228+
/**
229+
* Add a deactivation modal when deactivating the plugin.
230+
*
231+
* @since x.x.x
232+
*/
233+
function register_deactivation_modal() {
234+
// Exit if deactivating plugin from sub site.
235+
$screen = get_current_screen();
236+
if ( ! ( ! is_multisite() || $screen->in_admin( 'network' ) ) ) {
237+
return;
238+
}
239+
240+
wp_enqueue_script( 'jquery-ui-dialog' );
241+
wp_enqueue_style( 'wp-jquery-ui-dialog' );
242+
243+
add_action(
244+
'admin_footer',
245+
static function () {
246+
printf(
247+
'<div id="my-modal" style="display:none;"><p>%1$s</p><p>%2$s</p><p><code>%3$s</code></p><p>%4$s</p></div>',
248+
esc_html__( 'Would you like to delete all Distributor data?', 'distributor' ),
249+
esc_html__( 'By default, the database entries are not deleted when you deactivate Distributor. If you are deleting Distributor completely from your website and want those items removed as well, add the code below to wp-config.php:', 'distributor' ),
250+
'define( \'DT_REMOVE_ALL_DATA\', true );',
251+
esc_html__( 'After adding this code, the Distributor plugin data will be removed from the website database when deleting the plugin. This will not delete the posts with their metadata other than the subscription. You can review uninstall.php (in the plugin root directory) to learn more about the deleted data. After deleting the Distributor plugin, you can remove the code from the wp-config.php file. Please make sure that this action cannot be undone; take a backup before proceeding.', 'distributor' )
252+
);
253+
}
254+
);
255+
256+
$modal_title = wp_json_encode( __( 'Distributor Deactivation', 'distributor' ) );
257+
$modal_button_title_deactivate = wp_json_encode( __( 'Deactivate', 'distributor' ) );
258+
$modal_button_title_cancel = wp_json_encode( __( 'Cancel', 'distributor' ) );
259+
$script = <<<EOD
260+
jQuery(document).ready(function($) {
261+
const deactivateButton = jQuery('#deactivate-distributor');
262+
deactivateButton.on( 'click', function() {
263+
$("#my-modal").dialog({
264+
modal: true,
265+
title: $modal_title,
266+
width: 550,
267+
buttons: [
268+
{
269+
text: $modal_button_title_cancel,
270+
class: "button-secondary",
271+
click: function() {
272+
$(this).dialog("close");
273+
}
274+
},
275+
{
276+
text:$modal_button_title_deactivate,
277+
class: 'button-primary',
278+
click: function() {
279+
$(this).dialog("close");
280+
window.location.assign(deactivateButton.attr('href'));
281+
},
282+
style: 'margin-left: 10px;'
283+
}
284+
]
285+
});
286+
287+
return false;
288+
});
289+
});
290+
EOD;
291+
292+
wp_add_inline_script( 'jquery-ui-dialog', $script );
293+
}
294+
add_action( 'load-plugins.php', __NAMESPACE__ . '\register_deactivation_modal' );
295+
227296
/**
228297
* We use setup functions to avoid unit testing WP_Mock strict mode errors.
229298
*/

includes/classes/InternalConnections/NetworkSiteConnection.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -943,7 +943,7 @@ public static function build_available_authorized_sites( $user_id = false, $cont
943943
$last_changed = self::set_sites_last_changed_time();
944944
}
945945

946-
$cache_key = "authorized_sites:$user_id:$context:$last_changed";
946+
$cache_key = "dt_authorized_sites:$user_id:$context:$last_changed";
947947
$authorized_sites = get_transient( $cache_key );
948948

949949
if ( $force || false === $authorized_sites ) {
@@ -1028,8 +1028,8 @@ public static function clear_authorized_sites_cache( $user_id = false ) {
10281028
if ( ! $last_changed ) {
10291029
self::set_sites_last_changed_time();
10301030
} else {
1031-
delete_transient( "authorized_sites:$user_id:push:$last_changed" );
1032-
delete_transient( "authorized_sites:$user_id:pull:$last_changed" );
1031+
delete_transient( "dt_authorized_sites:$user_id:push:$last_changed" );
1032+
delete_transient( "dt_authorized_sites:$user_id:pull:$last_changed" );
10331033
}
10341034
}
10351035

package-lock.json

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

uninstall.php

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
<?php
2+
/**
3+
* Distributor uninstall script.
4+
*
5+
* @package distributor
6+
* @since x.x.x
7+
*/
8+
9+
// phpcs:disable WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
10+
11+
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
12+
die;
13+
}
14+
15+
/*
16+
* Only remove ALL data if DT_REMOVE_ALL_DATA constant is set to true in user's
17+
* wp-config.php. This is to prevent data loss when deleting the plugin from the backend
18+
* and to ensure only the site owner can perform this action.
19+
*/
20+
if ( defined( 'DT_REMOVE_ALL_DATA' ) && true === DT_REMOVE_ALL_DATA ) {
21+
global $wpdb;
22+
23+
/**
24+
* Function to delete all relevant data from the site.
25+
*/
26+
function dt_delete_data() {
27+
global $wpdb;
28+
29+
// Delete post meta and posts of type 'dt_subscription'.
30+
$subscription_post_ids = $wpdb->get_col(
31+
$wpdb->prepare(
32+
"SELECT ID FROM $wpdb->posts WHERE post_type = %s",
33+
'dt_subscription'
34+
)
35+
);
36+
37+
if ( ! empty( $subscription_post_ids ) ) {
38+
$ids_string = implode( ',', array_map( 'intval', $subscription_post_ids ) );
39+
40+
// Delete subscription meta.
41+
$wpdb->query(
42+
"DELETE FROM $wpdb->postmeta WHERE post_id IN ($ids_string)"
43+
);
44+
45+
// Delete subscription posts.
46+
$wpdb->query(
47+
$wpdb->prepare(
48+
"DELETE FROM $wpdb->posts WHERE ID IN (%s)",
49+
$ids_string
50+
)
51+
);
52+
53+
// Clear the post cache.
54+
wp_cache_set_posts_last_changed();
55+
wp_cache_delete_multiple( $subscription_post_ids, 'posts' );
56+
wp_cache_delete_multiple( $subscription_post_ids, 'post_meta' );
57+
}
58+
59+
// Delete relevant options from the options table.
60+
delete_site_options();
61+
}
62+
63+
/**
64+
* Delete all relevant options from the options table.
65+
*/
66+
function delete_site_options() {
67+
global $wpdb;
68+
69+
$option_prefixes = array(
70+
'dt_',
71+
'_transient_dt_',
72+
'_transient_timeout_dt_',
73+
);
74+
75+
// Site transients can be used on single sites too.
76+
// See https://github.com/10up/distributor/pull/540#discussion_r1759587692
77+
if ( ! is_multisite() ) {
78+
$option_prefixes = array_merge(
79+
$option_prefixes,
80+
array(
81+
'_site_transient_dt_',
82+
'_site_transient_timeout_dt_',
83+
)
84+
);
85+
}
86+
87+
// Prepare the WHERE clause for the options table.
88+
$where_clause = implode( ' OR ', array_fill( 0, count( $option_prefixes ), 'option_name LIKE %s' ) );
89+
90+
// Prepare the query.
91+
$query = $wpdb->prepare(
92+
sprintf(
93+
"SELECT option_id, option_name FROM $wpdb->options WHERE %s;",
94+
$where_clause
95+
),
96+
array_map(
97+
function( $prefix ) use ( $wpdb ) {
98+
return $wpdb->esc_like( $prefix ) . '%';
99+
},
100+
$option_prefixes
101+
)
102+
);
103+
104+
// Fetch the options to delete.
105+
$options_to_delete = $wpdb->get_results( $query, ARRAY_A );
106+
107+
if ( ! empty( $options_to_delete ) ) {
108+
// Collect IDs from fetched options.
109+
$ids = array_column( $options_to_delete, 'option_id' );
110+
$ids_string = implode( ',', array_map( 'intval', $ids ) );
111+
112+
// Delete the options using the retrieved IDs.
113+
$wpdb->query(
114+
$wpdb->prepare(
115+
"DELETE FROM $wpdb->options WHERE option_id IN ($ids_string)"
116+
)
117+
);
118+
119+
// Flush the options cache.
120+
$option_names = array_column( $options_to_delete, 'option_name' );
121+
wp_cache_delete_multiple( $option_names, 'options' );
122+
123+
// Flush the alloptions cache.
124+
wp_cache_delete( 'alloptions', 'options' );
125+
}
126+
}
127+
128+
/**
129+
* Delete all relevant options from the sitemeta table (multisite only).
130+
*/
131+
function delete_sitemeta_options() {
132+
global $wpdb;
133+
134+
$option_prefixes = array(
135+
'dt_',
136+
'_site_transient_dt_',
137+
'_site_transient_timeout_dt_',
138+
);
139+
140+
// Prepare the WHERE clause for the sitemeta table.
141+
$where_clause = implode( ' OR ', array_fill( 0, count( $option_prefixes ), 'meta_key LIKE %s' ) );
142+
143+
$site_id = get_current_network_id();
144+
145+
$query = $wpdb->prepare(
146+
sprintf(
147+
"SELECT meta_id, meta_key FROM $wpdb->sitemeta WHERE site_id = %%d AND (%s);",
148+
$where_clause
149+
),
150+
array_merge(
151+
[ $site_id ],
152+
array_map(
153+
function( $prefix ) use ( $wpdb ) {
154+
return $wpdb->esc_like( $prefix ) . '%';
155+
},
156+
$option_prefixes
157+
)
158+
)
159+
);
160+
161+
// Fetch the sitemeta to delete.
162+
$sitemeta_to_delete = $wpdb->get_results( $query, ARRAY_A );
163+
164+
if ( ! empty( $sitemeta_to_delete ) ) {
165+
// Collect IDs from fetched options.
166+
$ids = array_column( $sitemeta_to_delete, 'meta_id' );
167+
$ids_string = implode( ',', array_map( 'intval', $ids ) );
168+
169+
// Delete the sitemeta using the retrieved IDs.
170+
$wpdb->query(
171+
$wpdb->prepare(
172+
"DELETE FROM $wpdb->sitemeta WHERE meta_id IN ($ids_string)"
173+
)
174+
);
175+
176+
// Flush the site options cache.
177+
$key_names = array_column( $sitemeta_to_delete, 'meta_key' );
178+
$key_names = array_map(
179+
function( $key ) use ( $site_id ) {
180+
return $site_id . ':' . $key;
181+
},
182+
$key_names
183+
);
184+
wp_cache_delete_multiple( $key_names, 'site-options' );
185+
}
186+
}
187+
188+
// Check if it's a multisite installation.
189+
if ( is_multisite() ) {
190+
// Loop through each site in the network.
191+
$sites = get_sites();
192+
foreach ( $sites as $site ) {
193+
switch_to_blog( $site->blog_id );
194+
dt_delete_data();
195+
restore_current_blog();
196+
}
197+
198+
// Delete network-wide sitemeta options.
199+
delete_sitemeta_options();
200+
} else {
201+
// Single site.
202+
dt_delete_data();
203+
}
204+
}
205+

webpack.config.release.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module.exports = {
1010
new CopyPlugin( {
1111
patterns: [
1212
{ from: 'readme.txt', to: './' },
13+
{ from: 'uninstall.php', to: './' },
1314
{ from: 'README.md', to: './' },
1415
{ from: 'CHANGELOG.md', to: './' },
1516
{ from: 'composer.json', to: './' },

0 commit comments

Comments
 (0)