-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathpmpro-network-subsite.php
More file actions
433 lines (375 loc) · 15.7 KB
/
Copy pathpmpro-network-subsite.php
File metadata and controls
433 lines (375 loc) · 15.7 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
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
<?php
/**
* Plugin Name: Paid Memberships Pro - Multisite Membership Add On
* Plugin URI: https://www.paidmembershipspro.com/add-ons/pmpro-network-membership/
* Description: Centralize membership checkout, login, and admin on the main network site and restrict access to content across all of your subsites.
* Version: 0.6
* Author: Paid Memberships Pro
* Author URI: https://www.paidmembershipspro.com
* Text Domain: pmpro-network-subsite
* Domain Path: /languages
*/
/**
* Deactivate this plugin automatically if we're not on a multisite installation.
*/
function pmpro_multisite_deactivate_self() {
if ( is_multisite() ) {
return;
}
add_action( 'admin_notices', 'pmpro_multisite_show_admin_warning' );
deactivate_plugins( plugin_basename( __FILE__ ) );
}
add_action( 'admin_init', 'pmpro_multisite_deactivate_self' );
/**
* Show an admin notice that the plugin has been deactivated.
*/
function pmpro_multisite_show_admin_warning() {
if ( ! is_multisite() ) {
?>
<div class="error">
<p><?php esc_html_e( 'The Paid Memberships Pro - Multisite Membership Add-On is compatible only with multisite installations. We have automatically deactivated this plugin.', 'pmpro-network-subsite' ); ?></p>
</div>
<?php
}
}
// Don't run this plugin if it's not a multisite.
if ( ! is_multisite() ) {
return;
}
// Fake that PMPro is ready since the parent site is handling almost everything.
add_filter( 'pmpro_is_ready', '__return_true' );
/**
* Get the Main DB Prefix
*
* Thanks, Bainternet on Stack Exchange for the code to grab the DB prefix for the current site:
* https://wordpress.stackexchange.com/a/26467/3652
*/
function pmpro_multisite_membership_get_main_db_prefix() {
$main_db_prefix = get_site_option( 'pmpro_multisite_membership_main_db_prefix' );
if( empty( $main_db_prefix ) ) {
// checking if they used this constant for backwards compatability
if( defined( 'PMPRO_NETWORK_MAIN_DB_PREFIX' ) ) {
$main_db_prefix = PMPRO_NETWORK_MAIN_DB_PREFIX . '_'; //when we used constants, the trailing _ wasn't included
} else {
global $wpdb, $current_site;
$main_db_prefix = $wpdb->get_blog_prefix( $wpdb->get_var( $wpdb->prepare ( "SELECT blogs.blog_id FROM $wpdb->blogs blogs WHERE blogs.domain = '%s' AND blogs.path = '%s' ORDER BY blogs.blog_id ASC LIMIT 1", $current_site->domain, $current_site->path ) ) );
}
update_site_option( 'pmpro_multisite_membership_main_db_prefix', $main_db_prefix );
}
// Strip any characters that are not valid in a MySQL identifier to prevent
// SQL injection via a crafted prefix stored by a superadmin.
$main_db_prefix = preg_replace( '/[^a-zA-Z0-9_]/', '', $main_db_prefix );
return $main_db_prefix;
}
include( 'inc/class-pmpro-manage-multisite.php' );
PMPro_Manage_Multisite::init();
/**
* Get the advanced settings source for the current subsite.
*
* @return string 'inherit' to pull from the main site, 'custom' to use per-subsite settings.
*/
function pmpro_multisite_get_advanced_settings_source() {
return get_option( 'pmpro_multisite_advanced_settings_source', 'inherit' );
}
/**
* The PMPro option names managed on the Advanced Settings screen.
* Filterable so add-ons can append their own options.
*
* @return string[]
*/
function pmpro_multisite_get_advanced_settings_option_names() {
return apply_filters( 'pmpro_multisite_advanced_settings_options', array(
'pmpro_hide_toolbar',
'pmpro_block_dashboard',
'pmpro_filterqueries',
'pmpro_showexcerpts',
'pmpro_nonmembertext',
'pmpro_maxnotificationpriority',
'pmpro_activity_email_frequency',
'pmpro_business_address',
'pmpro_hideads',
'pmpro_wisdom_opt_out',
'pmpro_hideadslevels',
'pmpro_redirecttosubscription',
'pmpro_avatar_enabled_sitewide',
'pmpro_site_type',
// show_avatars is a WP core Discussion setting. While in inherit mode, subsite admin
// changes to Settings → Discussion → Show Avatars will have no visible effect.
'show_avatars',
) );
}
/**
* When "inherit" mode is active, register pre_option_* filters that read each
* Advanced Settings option directly from the main site's options table.
* Using pre_option_* + a direct DB read avoids any get_blog_option() recursion.
*/
function pmpro_multisite_register_advanced_settings_inheritance() {
if ( pmpro_multisite_get_advanced_settings_source() !== 'inherit' ) {
return;
}
$main_db_prefix = pmpro_multisite_membership_get_main_db_prefix();
if ( empty( $main_db_prefix ) ) {
return;
}
foreach ( pmpro_multisite_get_advanced_settings_option_names() as $option_name ) {
add_filter(
'pre_option_' . $option_name,
static function() use ( $main_db_prefix, $option_name ) {
global $wpdb;
$row = $wpdb->get_row(
$wpdb->prepare(
"SELECT option_value FROM `{$main_db_prefix}options` WHERE option_name = %s LIMIT 1",
$option_name
)
);
if ( is_object( $row ) ) {
return maybe_unserialize( $row->option_value );
}
return false;
}
);
}
// pmpro_filterqueries is read at plugin-load time in content.php (global scope, before
// pre_option_* filters can intercept it). Correct the resulting pre_get_posts hook on
// init priority 1, before any queries run.
add_action( 'init', static function() use ( $main_db_prefix ) {
global $wpdb;
remove_filter( 'pre_get_posts', 'pmpro_search_filter' );
$row = $wpdb->get_row( $wpdb->prepare(
"SELECT option_value FROM `{$main_db_prefix}options` WHERE option_name = %s LIMIT 1",
'pmpro_filterqueries'
) );
if ( is_object( $row ) && ! empty( $row->option_value ) ) {
add_filter( 'pre_get_posts', 'pmpro_search_filter' );
}
}, 1 );
// Avatars are uploaded to the main site. Point PMPro's avatar path helpers at the
// main site's upload directory via dedicated filters added to PMPro core.
add_filter( 'pmpro_avatar_basedir', 'pmpro_multisite_avatar_basedir' );
add_filter( 'pmpro_avatar_baseurl', 'pmpro_multisite_avatar_baseurl' );
}
add_action( 'plugins_loaded', 'pmpro_multisite_register_advanced_settings_inheritance', 20 );
/**
* Get the main site's upload directory info, cached for the request.
*
* @return array wp_upload_dir() result for the main site.
*/
function pmpro_multisite_get_main_upload_dir() {
static $main_upload = null;
if ( null === $main_upload ) {
switch_to_blog( pmpro_multisite_get_main_site_ID() );
$main_upload = wp_upload_dir();
restore_current_blog();
}
return $main_upload;
}
/**
* Redirect PMPro avatar basedir to the main site's uploads directory.
*
* @param string $basedir The current basedir.
* @return string The main site's basedir.
*/
function pmpro_multisite_avatar_basedir( $basedir ) {
$main_upload = pmpro_multisite_get_main_upload_dir();
return $main_upload['basedir'];
}
/**
* Redirect PMPro avatar baseurl to the main site's uploads URL.
*
* @param string $baseurl The current baseurl.
* @return string The main site's baseurl.
*/
function pmpro_multisite_avatar_baseurl( $baseurl ) {
$main_upload = pmpro_multisite_get_main_upload_dir();
return $main_upload['baseurl'];
}
// Load text domain
function pmpro_multisite_membership_load_textdomain() {
load_plugin_textdomain( 'pmpro-network-subsite', false, basename( dirname( __FILE__ ) ) . '/languages' );
}
add_action( 'init', 'pmpro_multisite_membership_load_textdomain' );
/*
Make sure this plugin loads after Paid Memberships Pro
*/
function pmpro_multisite_membership_activated_plugin() {
// ensure path to this file is via main wp plugin path
$wp_path_to_this_file = preg_replace( '/(.*)plugins\/(.*)$/', WP_PLUGIN_DIR . '/$2', __FILE__ );
$this_plugin = plugin_basename( trim( $wp_path_to_this_file ) );
// load plugins
$active_plugins = get_option( 'active_plugins' );
// where am I?
$this_plugin_key = array_search( $this_plugin, $active_plugins );
// move to end
array_splice( $active_plugins, $this_plugin_key, 1 );
$active_plugins[] = $this_plugin;
// update option
update_option( 'active_plugins', $active_plugins );
}
add_action( 'activated_plugin', 'pmpro_multisite_membership_activated_plugin' );
/*
Now update wpdb tables.
(Updated again in init to get all cases.)
*/
global $wpdb;
$wpdb->pmpro_memberships_users = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_memberships_users';
$wpdb->pmpro_membership_levels = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_membership_levels';
$wpdb->pmpro_membership_levelmeta = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_membership_levelmeta';
$wpdb->pmpro_membership_orders = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_membership_orders';
$wpdb->pmpro_membership_ordermeta = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_membership_ordermeta';
$wpdb->pmpro_discount_codes = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_discount_codes';
$wpdb->pmpro_discount_codes_levels = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_discount_codes_levels';
$wpdb->pmpro_discount_codes_uses = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_discount_codes_uses';
$wpdb->pmpro_subscriptions = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_subscriptions';
$wpdb->pmpro_subscriptionmeta = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_subscriptionmeta';
$wpdb->pmpro_groups = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_groups';
$wpdb->pmpro_membership_levels_groups = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_membership_levels_groups';
// get levels again
function pmpro_multisite_membership_init_get_levels() {
global $wpdb, $membership_levels;
if ( function_exists( 'pmpro_getAllLevels' ) ) {
$membership_levels = pmpro_getAllLevels( true, true, true );
}
}
add_action( 'init', 'pmpro_multisite_membership_init_get_levels', 1 );
/*
Hide admin stuff
*/
function pmpro_multisite_membership_init() {
// remove admin pages
remove_action( 'admin_menu', 'pmpro_add_pages' );
remove_action( 'admin_bar_menu', 'pmpro_admin_bar_menu' );
// remove membership level from edit users page
remove_action( 'show_user_profile', 'pmpro_membership_level_profile_fields' );
remove_action( 'edit_user_profile', 'pmpro_membership_level_profile_fields' );
remove_action( 'profile_update', 'pmpro_membership_level_profile_fields_update' );
// update wpdb tables again
global $wpdb;
$wpdb->pmpro_memberships_users = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_memberships_users';
$wpdb->pmpro_membership_levels = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_membership_levels';
$wpdb->pmpro_membership_levelmeta = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_membership_levelmeta';
$wpdb->pmpro_membership_orders = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_membership_orders';
$wpdb->pmpro_membership_ordermeta = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_membership_ordermeta';
$wpdb->pmpro_discount_codes = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_discount_codes';
$wpdb->pmpro_discount_codes_levels = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_discount_codes_levels';
$wpdb->pmpro_discount_codes_uses = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_discount_codes_uses';
$wpdb->pmpro_subscriptions = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_subscriptions';
$wpdb->pmpro_subscriptionmeta = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_subscriptionmeta';
$wpdb->pmpro_groups = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_groups';
$wpdb->pmpro_membership_levels_groups = pmpro_multisite_membership_get_main_db_prefix() . 'pmpro_membership_levels_groups';
}
add_action( 'init', 'pmpro_multisite_membership_init', 15 );
/**
* Replace the global $pmpro_pages with the page ID's of the main network site.
* @return array $pmpro_pages The array of page ID's for the main network site.
*/
function pmpro_multisite_get_parent_site_pages() {
global $pmpro_pages;
if ( empty( $pmpro_pages ) ) {
return;
}
// Only if the constant is defined try to rewrite.
if ( ! defined( 'PMPRO_MULTISITE_REWRITE_URLS' ) || ! PMPRO_MULTISITE_REWRITE_URLS ) {
return;
}
// Get main site ID
$main_site_id = pmpro_multisite_get_main_site_ID();
foreach( $pmpro_pages as $page_slug => $page_id ) {
if ( $page_slug == 'login' ) {
continue;
}
$pmpro_pages[ $page_slug ] = get_blog_option( $main_site_id, 'pmpro_' . $page_slug . '_page_id' );
}
}
add_action( 'init', 'pmpro_multisite_get_parent_site_pages', 20 );
/**
* Filter the pmpro_url URLs when called on the subsite.
* @return string $url The URL of the main site for equivalent page.
*/
function pmpro_multisite_pmpro_url( $url, $page, $querystring, $scheme ) {
global $pmpro_pages;
// Only if the constant is defined try to rewrite URLS.
if ( ! defined( 'PMPRO_MULTISITE_REWRITE_URLS' ) || ! PMPRO_MULTISITE_REWRITE_URLS ) {
return $url;
}
// Get main site URL of the network.
$main_site_url = get_blog_option( pmpro_multisite_get_main_site_ID(), 'siteurl' );
// Loop through $pages and generate the URL
foreach( $pmpro_pages as $page_slug => $page_id ) {
if ( $page_slug == 'login' ) {
continue;
}
if ( $page == $page_slug && ! empty( $page_id ) ) {
// Add query arg to the URL
$url = add_query_arg( 'page_id', $page_id, $main_site_url);
}
}
return $url;
}
add_filter( 'pmpro_url', 'pmpro_multisite_pmpro_url', 10, 4 );
/**
* Remove cron jobs from subsites to prevent them from running.
* @since 0.5
*/
function pmpro_multisite_remove_crons() {
// Return early if PMPro is not active.
if ( ! function_exists( 'pmpro_get_crons' ) ) {
return;
}
$crons = apply_filters( 'pmpro_multisite_core_crons', pmpro_get_crons() );
foreach ( $crons as $hook => $cron ) {
wp_clear_scheduled_hook( $hook );
}
// Remove the cron jobs from the main site too.
remove_filter( 'pre_get_ready_cron_jobs', 'pmpro_handle_schedule_crons_on_cron_ready_check' );
}
add_action( 'admin_init', 'pmpro_multisite_remove_crons' );
/**
* Reactivate PMPro cron jobs when this plugin is deactivated.
* @since 0.5
*/
function pmpro_multisite_deactivation() {
if ( function_exists( 'pmpro_maybe_schedule_crons' ) ) {
pmpro_maybe_schedule_crons();
}
}
register_deactivation_hook( __FILE__, 'pmpro_multisite_deactivation' );
/**
* Helper to get the Site ID of the stored site.
*
* @return void
*/
function pmpro_multisite_get_main_site_ID() {
global $wpdb;
if ( ! get_site_transient( 'pmpro_multisite_membership_main_site_id' ) ) {
$prefix = pmpro_multisite_membership_get_main_db_prefix();
$main_site_id = 0;
// Loop through the sites to get the main site ID we're referencing.
$sites = get_sites();
foreach( $sites as $site ) {
$bool_val = SUBDOMAIN_INSTALL;
$siteurl = $bool_val ? $site->domain : $site->domain . $site->path;
if ( $wpdb->get_blog_prefix( $site->blog_id ) === $prefix ) {
$main_site_id = (int) $site->blog_id;
}
}
// Set the transient here for a really long time, we clean it up anyway.
set_site_transient( 'pmpro_multisite_membership_main_site_id', $main_site_id, YEAR_IN_SECONDS );
} else {
$main_site_id = get_site_transient( 'pmpro_multisite_membership_main_site_id' );
}
return (int) $main_site_id;
}
/*
Function to add links to the plugin row meta
*/
function pmpro_multisite_membership_plugin_row_meta( $links, $file ) {
if ( strpos( $file, 'pmpro-network-subsite.php' ) !== false ) {
$new_links = array(
'<a href="' . esc_url( 'https://www.paidmembershipspro.com/add-ons/pmpro-network-membership/' ) . '" title="' . esc_attr__( 'View Documentation', 'pmpro-network-subsite' ) . '">' . esc_html__( 'Docs', 'pmpro-network-subsite' ) . '</a>',
'<a href="' . esc_url( 'https://www.paidmembershipspro.com/support/' ) . '" title="' . esc_attr__( 'Visit Customer Support Forum', 'pmpro-network-subsite' ) . '">' . esc_html__( 'Support', 'pmpro-network-subsite' ) . '</a>',
);
$links = array_merge( $links, $new_links );
}
return $links;
}
add_filter( 'plugin_row_meta', 'pmpro_multisite_membership_plugin_row_meta', 10, 2 );