PluginProbe
User Registration & Membership – Free & Paid Memberships, Subscriptions, Content Restriction, User Profile, Custom User Registration & Login Builder / 5.2.3
User Registration & Membership – Free & Paid Memberships, Subscriptions, Content Restriction, User Profile, Custom User Registration & Login Builder v5.2.3
5.2.7 5.2.6 5.2.5 5.2.4 5.2.3 5.2.2 5.2.1 5.2.0 3.0 3.0.1 3.0.2 3.0.2.1 3.0.3 3.0.4 3.0.4.1 3.0.4.2 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.2.0 3.2.0.1 3.2.1 All 192 releases
user-registration / user-registration.php

user-registration.php in User Registration & Membership – Free & Paid Memberships, Subscriptions, Content Restriction, User Profile, Custom User Registration & Login Builder 5.2.3, at user-registration.php

837 lines 26.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php //phpcs:ignore
2
3 /**
4 * Plugin Name: User Registration & Membership
5 * Plugin URI: https://wpuserregistration.com/
6 * Description: The most flexible User Registration and Membership plugin for WordPress.
7 * Version: 5.2.3
8 * Author: WPEverest
9 * Author URI: https://wpuserregistration.com
10 * Text Domain: user-registration
11 * Domain Path: /languages/
12 *
13 * @package UserRegistration
14 */
15
16 if ( ! defined( 'ABSPATH' ) ) {
17 exit; // Exit if accessed directly.
18 }
19
20 if ( file_exists( __DIR__ . '/vendor/autoload.php' ) ) {
21 require_once __DIR__ . '/vendor/autoload.php';
22 }
23
24 if ( ! class_exists( 'UserRegistration' ) ) :
25
26 /**
27 * Main UserRegistration Class.
28 *
29 * @class UserRegistration
30 * @version 1.0.0
31 */
32 final class UserRegistration {
33
34
35 /**
36 * Plugin version.
37 *
38 * @var string
39 */
40 public $version = '5.2.3';
41
42 /**
43 * Session instance.
44 *
45 * @var UR_Session|UR_Session_Handler
46 */
47 public $session = null;
48
49 /**
50 * Query instance.
51 *
52 * @var UR_Query
53 */
54 public $query = null;
55
56 /**
57 * Instance of this class.
58 *
59 * @var object
60 */
61 protected static $_instance = null;
62
63 /**
64 * Instance of this form.
65 *
66 * @var object
67 */
68 public $form = null;
69
70 /**
71 * UTM Campaign.
72 *
73 * @var string
74 */
75 public $utm_campaign = 'lite-version';
76
77 /**
78 * Return an instance of this class.
79 *
80 * @return object A single instance of this class.
81 */
82 public static function instance() {
83 // If the single instance hasn't been set, set it now.
84 if ( is_null( self::$_instance ) ) {
85 self::$_instance = new self();
86 }
87
88 return self::$_instance;
89 }
90
91 /**
92 * Cloning is forbidden.
93 *
94 * @since 1.0
95 */
96 public function __clone() {
97 _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'user-registration' ), '1.0' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
98 }
99
100 /**
101 * Unserializing instances of this class is forbidden.
102 *
103 * @since 1.0
104 */
105 public function __wakeup() {
106 _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'user-registration' ), '1.0' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
107 }
108
109 /**
110 * UserRegistration Constructor.
111 */
112 public function __construct() {
113 $this->define_constants();
114 $this->includes();
115 $this->init_hooks();
116 add_action( 'plugins_loaded', array( $this, 'objects' ), 1 );
117 add_action( 'in_plugin_update_message-' . UR_PLUGIN_BASENAME, array( __CLASS__, 'in_plugin_update_message' ), 10, 2 );
118
119 do_action( 'user_registration_loaded' );
120 }
121
122 /**
123 * Hook into actions and filters.
124 */
125 private function init_hooks() {
126 register_activation_hook( __FILE__, array( 'UR_Install', 'install' ) );
127 register_shutdown_function( array( $this, 'log_errors' ) );
128 add_action( 'after_setup_theme', array( $this, 'include_template_functions' ), 11 );
129 add_action( 'init', array( $this, 'init' ), 0 );
130 add_action( 'init', array( 'UR_Shortcodes', 'init' ) );
131
132 add_filter( 'plugin_action_links_' . UR_PLUGIN_BASENAME, array( __CLASS__, 'plugin_action_links' ) );
133 add_filter( 'plugin_row_meta', array( __CLASS__, 'plugin_row_meta' ), 10, 2 );
134 }
135
136 /**
137 * Instantiate the WPML compatibility layer when WPML is active.
138 *
139 * Loading the service only when SitePress is present avoids any overhead
140 * on non-multilingual sites. The class itself uses WPML's documented
141 * filter API (no `new SitePress()`), so it cannot reintroduce the
142 * duplicate-JOIN "Not unique table/alias" errors.
143 *
144 * @since 5.2.1
145 */
146 public function init_wpml_compat() {
147 if ( ( defined( 'ICL_SITEPRESS_VERSION' ) || class_exists( 'SitePress', false ) ) && class_exists( 'UR_WPML' ) ) {
148 UR_WPML::instance();
149 }
150 }
151
152 /**
153 * Ensures fatal errors are logged so they can be picked up in the status report.
154 *
155 * @since 3.0.5
156 */
157 public function log_errors() {
158 $error = error_get_last();
159
160 if ( $error && in_array( $error['type'], array( E_ERROR, E_PARSE, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR ), true ) ) {
161 $logger = ur_get_logger();
162
163 $raw_message = isset( $error['message'] ) ? trim( wp_strip_all_tags( $error['message'] ) ) : __( 'Unknown error', 'user-registration' );
164 $file = isset( $error['file'] ) ? $error['file'] : __( 'Unknown file', 'user-registration' );
165 $line = isset( $error['line'] ) ? absint( $error['line'] ) : 0;
166
167 if ( false !== strpos( $file, 'wp-content/' ) ) {
168 $file = substr( $file, strpos( $file, 'wp-content/' ) );
169 }
170
171 $message = $raw_message;
172 $trace = '';
173
174 if ( false !== strpos( $raw_message, 'Stack trace:' ) ) {
175 $parts = explode( 'Stack trace:', $raw_message, 2 );
176
177 $message = trim( $parts[0] );
178 $trace = trim( $parts[1] );
179
180 // Remove trailing "thrown in ..." because file/line is already shown separately.
181 $trace = preg_replace( '/thrown in .*$/s', '', $trace );
182 $trace = trim( $trace );
183 }
184
185 $log = "================================================================\n";
186 $log .= sprintf(
187 /* translators: %s: error timestamp */
188 __( '[%s] CRITICAL Fatal error', 'user-registration' ),
189 gmdate( 'Y-m-d H:i:s' )
190 ) . "\n";
191 $log .= "----------------------------------------------------------------\n";
192 $log .= sprintf(
193 /* translators: %s: error message */
194 __( 'Message : %s', 'user-registration' ),
195 $message
196 ) . "\n";
197 $log .= sprintf(
198 /* translators: 1: file path, 2: line number */
199 __( 'File : %1$s:%2$d', 'user-registration' ),
200 $file,
201 $line
202 ) . "\n";
203 $log .= __( 'Status : FAILED', 'user-registration' ) . "\n";
204
205 if ( ! empty( $trace ) ) {
206 $log .= "\n" . __( 'Trace:', 'user-registration' ) . "\n";
207 $log .= $trace . "\n";
208 }
209
210 $log .= '================================================================';
211
212 $logger->critical(
213 $log,
214 array(
215 'source' => 'fatal-errors',
216 'type' => $error['type'],
217 'file' => $file,
218 'line' => $line,
219 )
220 );
221 }
222 }
223
224 /**
225 * Define FT Constants.
226 */
227 private function define_constants() {
228 $upload_dir = apply_filters( 'user_registration_upload_dir', wp_upload_dir() );
229 $this->define( 'UR_LOG_DIR', $upload_dir['basedir'] . '/ur-logs/' );
230 $this->define( 'UR_UPLOAD_PATH', $upload_dir['basedir'] . '/user_registration_uploads/' );
231 $this->define( 'UR_UPLOAD_URL', $upload_dir['baseurl'] . '/user_registration_uploads/' );
232 $this->define( 'UR_DS', DIRECTORY_SEPARATOR );
233 $this->define( 'UR_PLUGIN_FILE', __FILE__ );
234 $this->define( 'UR_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
235 $this->define( 'UR_ASSETS_URL', UR_PLUGIN_URL . 'assets' );
236 $this->define( 'UR_ABSPATH', __DIR__ . UR_DS );
237 $this->define( 'UR_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
238 $this->define( 'UR_VERSION', $this->version );
239 $this->define( 'UR_TEMPLATE_DEBUG_MODE', false );
240 $this->define( 'UR_TEMPLATE_PATH', UR_ABSPATH . 'templates/' );
241 $this->define( 'UR_ASSET_PATH', plugins_url( 'assets/', UR_PLUGIN_FILE ) );
242 $this->define( 'UR_FORM_PATH', UR_ABSPATH . 'includes' . UR_DS . 'form' . UR_DS );
243 $this->define( 'UR_SESSION_CACHE_GROUP', 'ur_session_id' );
244 $this->define( 'UR_PRO_ACTIVE', false );
245 $this->define( 'UR_DEV', false );
246 }
247
248 /**
249 * Define constant if not already set.
250 *
251 * @param string $name Name.
252 * @param string|bool $value Value.
253 */
254 private function define( $name, $value ) {
255 if ( ! defined( $name ) ) {
256 define( $name, $value );
257 }
258 }
259
260 /**
261 * What type of request is this?
262 *
263 * @param string $type admin, ajax, cron or frontend.
264 * @return bool
265 */
266 private function is_request( $type ) {
267 switch ( $type ) {
268 case 'admin':
269 return is_admin();
270 case 'ajax':
271 return defined( 'DOING_AJAX' );
272 case 'cron':
273 return defined( 'DOING_CRON' );
274 case 'frontend':
275 return ( ! is_admin() || defined( 'DOING_AJAX' ) ) && ! defined( 'DOING_CRON' );
276 }
277 }
278
279 /**
280 * Includes.
281 */
282 private function includes() {
283
284 if ( file_exists( __DIR__ . '/vendor/autoload.php' ) ) {
285 require_once __DIR__ . '/vendor/autoload.php';
286 } else {
287 if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
288 error_log( // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
289 sprintf(
290 /* translators: 1: composer command. 2: plugin directory */
291 esc_html__( 'Your installation of the User Registration is incomplete. Please run %1$s within the %2$s directory.', 'user-registration' ),
292 '`composer install`',
293 '`' . esc_html( str_replace( ABSPATH, '', __DIR__ ) ) . '`'
294 )
295 );
296 }
297
298 /**
299 * Outputs an admin notice if composer install has not been ran.
300 */
301 add_action(
302 'admin_notices',
303 function () {
304 ?>
305 <div class="notice notice-error">
306 <p>
307 <?php
308 printf(
309 /* translators: 1: composer command. 2: plugin directory */
310 esc_html__( 'Your installation of the User Registration is incomplete. Please run %1$s within the %2$s directory.', 'user-registration' ),
311 '<code>composer install</code>',
312 '<code>' . esc_html( str_replace( ABSPATH, '', __DIR__ ) ) . '</code>'
313 );
314 ?>
315 </p>
316 </div>
317 <?php
318 }
319 );
320 }
321
322 /**
323 * Class autoloader.
324 */
325 include_once UR_ABSPATH . 'includes/class-ur-autoloader.php';
326
327 /**
328 * Interfaces.
329 */
330 include_once UR_ABSPATH . 'includes/interfaces/class-ur-logger-interface.php';
331 include_once UR_ABSPATH . 'includes/interfaces/class-ur-log-handler-interface.php';
332
333 /**
334 * Abstract classes
335 */
336 include_once UR_ABSPATH . 'includes/abstracts/abstract-ur-form-field.php';
337 include_once UR_ABSPATH . 'includes/abstracts/abstract-ur-field-settings.php';
338 include_once UR_ABSPATH . 'includes/abstracts/abstract-ur-log-handler.php';
339 include_once UR_ABSPATH . 'includes/abstracts/abstract-ur-session.php';
340
341 /**
342 * Core classes.
343 */
344 include_once UR_ABSPATH . 'includes/functions-ur-core.php';
345 include_once UR_ABSPATH . 'modules/functions-ur-modules.php';
346 include_once UR_ABSPATH . 'includes/functions-ur-form.php';
347 include_once UR_ABSPATH . 'includes/class-ur-install.php';
348 include_once UR_ABSPATH . 'includes/class-ur-post-types.php'; // Registers post types.
349 include_once UR_ABSPATH . 'includes/class-ur-user-approval.php';
350 include_once UR_ABSPATH . 'includes/class-ur-smart-tags.php'; // User Approval class.
351 include_once UR_ABSPATH . 'includes/class-ur-emailer.php';
352 include_once UR_ABSPATH . 'includes/class-ur-ajax.php';
353 include_once UR_ABSPATH . 'includes/class-ur-query.php';
354 include_once UR_ABSPATH . 'includes/class-ur-email-confirmation.php';
355 include_once UR_ABSPATH . 'includes/class-ur-email-approval.php';
356 include_once UR_ABSPATH . 'includes/class-ur-privacy.php';
357 include_once UR_ABSPATH . 'includes/class-ur-form-block.php';
358 include_once UR_ABSPATH . 'includes/class-ur-cache-helper.php';
359 include_once UR_ABSPATH . 'includes/class-ur-wpml.php';
360
361 /**
362 * Block classes.
363 */
364 include_once UR_ABSPATH . 'includes/blocks/class-ur-blocks.php';
365 include_once UR_ABSPATH . 'includes/blocks/block-types/class-ur-block-abstract.php';
366 include_once UR_ABSPATH . 'includes/blocks/block-types/class-ur-block-registration-form.php';
367 include_once UR_ABSPATH . 'includes/blocks/block-types/class-ur-block-login-form.php';
368 include_once UR_ABSPATH . 'includes/blocks/block-types/class-ur-block-myaccount.php';
369 include_once UR_ABSPATH . 'includes/blocks/block-types/class-ur-block-edit-profile.php';
370 include_once UR_ABSPATH . 'includes/blocks/block-types/class-ur-block-edit-password.php';
371 include_once UR_ABSPATH . 'includes/blocks/block-types/class-ur-block-login-logout-menu.php';
372 include_once UR_ABSPATH . 'includes/blocks/block-types/class-ur-block-membership-listing.php';
373 include_once UR_ABSPATH . 'includes/blocks/block-types/class-ur-block-thank-you.php';
374 include_once UR_ABSPATH . 'includes/blocks/block-types/class-ur-block-membership-buy-now.php';
375
376 /**
377 * Navigation menu item classes.
378 */
379 include_once UR_ABSPATH . 'includes/menu-items/abstract-ur-nav-menu-item.php';
380 include_once UR_ABSPATH . 'includes/menu-items/class-ur-login-logout-nav-menu-item.php';
381
382 // Validation classes.
383 include_once UR_ABSPATH . 'includes/validation/class-ur-validation.php';
384 include_once UR_ABSPATH . 'includes/validation/class-ur-form-validation.php';
385 include_once UR_ABSPATH . 'includes/validation/class-ur-setting-validation.php';
386
387 include_once UR_ABSPATH . 'includes/RestApi/class-ur-rest-api.php';
388
389 /**
390 * Config classes.
391 */
392 include_once UR_ABSPATH . 'includes/admin/class-ur-config.php';
393
394 if ( ur_check_module_activation( 'membership' ) ) {
395 /** include modules */
396 include_once UR_ABSPATH . 'modules/membership/user-registration-membership.php';
397
398 if ( ur_check_module_activation( 'masteriyo-course-integration' ) && ( is_plugin_active( 'learning-management-system/lms.php' )
399 || is_plugin_active( 'learning-management-system-pro/lms.php' ) ) ) {
400 include_once UR_ABSPATH . 'modules/masteriyo/user-registration-masteriyo.php';
401 }
402 }
403
404 if ( ( ur_check_module_activation( 'membership' ) || ur_check_module_activation( 'payments' ) ) ) {
405 include_once UR_ABSPATH . 'modules/payment-history/Orders.php';
406 }
407
408 include_once UR_ABSPATH . 'modules/content-restriction/user-registration-content-restriction.php';
409
410 if ( ur_check_module_activation( 'membership' ) && ur_check_module_activation( 'content-restriction' ) && ur_check_module_activation( 'content-drip' ) ) {
411 include_once UR_ABSPATH . 'modules/content-drip/user-registration-content-drip.php';
412 }
413
414 include_once UR_ABSPATH . 'includes/blocks/block-types/class-ur-block-content-restriction.php';
415
416 /**
417 * Elementor classes.
418 */
419 if ( class_exists( '\Elementor\Plugin' ) ) {
420 include_once UR_ABSPATH . 'includes/3rd-party/elementor/class-ur-elementor.php';
421 }
422 /**
423 * Oxygen classes.
424 */
425 if ( in_array( 'oxygen/functions.php', get_option( 'active_plugins', array() ), true ) ) {
426 include_once UR_ABSPATH . 'includes/3rd-party/oxygen/class-ur-oxygen.php';
427 }
428 // Divi builder compatiblity.
429 if ( class_exists( 'WPEverest\URM\DiviBuilder\Builder' ) ) {
430 WPEverest\URM\DiviBuilder\Builder::init();
431 }
432
433 /**
434 * Plugin/Addon Updater.
435 */
436 include_once UR_ABSPATH . 'includes/class-ur-plugin-updater.php';
437
438 if ( $this->is_request( 'admin' ) ) {
439 include_once UR_ABSPATH . 'includes/admin/class-ur-admin.php';
440 include_once UR_ABSPATH . 'includes/abstracts/abstract-ur-meta-boxes.php';
441
442 include_once UR_ABSPATH . 'includes/admin/class-ur-admin-embed-wizard.php';
443 }
444
445 if ( $this->is_request( 'frontend' ) ) {
446 $this->frontend_includes();
447 }
448
449 if ( $this->is_request( 'frontend' ) || $this->is_request( 'cron' ) ) {
450 include_once UR_ABSPATH . 'includes/class-ur-session-handler.php';
451 }
452 include_once UR_ABSPATH . 'includes/class-ur-cron.php';
453 include_once UR_ABSPATH . 'includes/stats/class-ur-stats.php';
454 include_once UR_ABSPATH . 'includes/stats/class-ur-formbricks.php';
455 include_once UR_ABSPATH . 'includes/class-ur-captcha-conflict-manager.php';
456
457 $this->query = new UR_Query();
458
459 if ( class_exists( 'WPEverest\URM\Analytics\Analytics' ) ) {
460 WPEverest\URM\Analytics\Analytics::get_instance();
461 }
462 }
463
464 /**
465 * Include required frontend files.
466 */
467 public function frontend_includes() {
468 include_once UR_ABSPATH . 'includes/functions-ur-notice.php';
469 include_once UR_ABSPATH . 'includes/class-ur-form-handler.php'; // Form Handlers.
470 include_once UR_ABSPATH . 'includes/class-ur-frontend-scripts.php'; // Frontend Scripts.
471 include_once UR_ABSPATH . 'includes/frontend/class-ur-frontend.php';
472 include_once UR_ABSPATH . 'includes/class-ur-preview.php';
473 }
474
475 /**
476 * Function used to Init UserRegistration Template Functions - This makes them pluggable by plugins and themes.
477 */
478 public function include_template_functions() {
479 include_once UR_ABSPATH . 'includes/functions-ur-template.php';
480 }
481
482 /**
483 * Setup Objects.
484 *
485 * @since 1.7.2
486 */
487 public function objects() {
488 $this->form = new UR_Form_Handler();
489
490 // Initialize captcha conflict manager only on frontend
491 if ( $this->is_request( 'frontend' ) ) {
492 new UR_Captcha_Conflict_Manager();
493 }
494 }
495
496 /**
497 * Init UserRegistration when WordPress Initialises.
498 */
499 public function init() {
500 // Before init action.
501 do_action( 'before_user_registration_init' );
502
503 // Set up localisation.
504 $this->load_plugin_textdomain();
505
506 // Boot WPML compatibility (only when WPML is active).
507 $this->init_wpml_compat();
508
509 // Session class, handles session data for users - can be overwritten if custom handler is needed.
510 if ( $this->is_request( 'frontend' ) || $this->is_request( 'cron' ) || $this->is_request( 'admin' ) ) {
511 $session_class = apply_filters( 'user_registration_session_handler', 'UR_Session_Handler' );
512 $this->session = new $session_class();
513 }
514
515 // Init action.
516 do_action( 'user_registration_init' );
517 }
518
519 /**
520 * Load Localisation files.
521 *
522 * Note: the first-loaded translation file overrides any following ones if the same translation is present.
523 *
524 * Locales found in:
525 * - WP_LANG_DIR/user-registration/user-registration-LOCALE.mo
526 * - WP_LANG_DIR/plugins/user-registration-LOCALE.mo
527 */
528 public function load_plugin_textdomain() {
529 $locale = is_admin() && function_exists( 'get_user_locale' ) ? get_user_locale() : get_locale();
530 $locale = apply_filters( 'plugin_locale', $locale, 'user-registration' );
531
532 unload_textdomain( 'user-registration', true );
533 load_textdomain( 'user-registration', WP_LANG_DIR . '/user-registration/user-registration-' . $locale . '.mo' );
534 load_plugin_textdomain( 'user-registration', false, plugin_basename( __DIR__ ) . '/languages' );
535 }
536
537 /**
538 * Get the plugin url.
539 *
540 * @return string
541 */
542 public function plugin_url() {
543 return untrailingslashit( plugins_url( '/', __FILE__ ) );
544 }
545
546 /**
547 * Get the plugin path.
548 *
549 * @return string
550 */
551 public function plugin_path() {
552 return untrailingslashit( plugin_dir_path( __FILE__ ) );
553 }
554
555 /**
556 * Get the template path.
557 *
558 * @return string
559 */
560 public function template_path() {
561 return apply_filters( 'user_registration_template_path', 'user-registration/' );
562 }
563
564 /**
565 * Get Ajax URL.
566 *
567 * @return string
568 */
569 public function ajax_url() {
570 return admin_url( 'admin-ajax.php', 'relative' );
571 }
572
573 /**
574 * Display action links in the Plugins list table.
575 *
576 * @param array $actions Plugin Action links.
577 * @return array
578 */
579 public static function plugin_action_links( $actions ) {
580 $new_actions = array(
581 'settings' => '<a href="' . admin_url( 'admin.php?page=user-registration-settings' ) . '" aria-label="' . esc_attr__( 'View User Registration & Membership settings', 'user-registration' ) . '">' . esc_html__( 'Settings', 'user-registration' ) . '</a>',
582 );
583
584 return array_merge( $new_actions, $actions );
585 }
586
587 /**
588 * Display row meta in the Plugins list table.
589 *
590 * @param array $plugin_meta Plugin Row Meta.
591 * @param string $plugin_file Plugin Row Meta.
592 * @return array
593 */
594 public static function plugin_row_meta( $plugin_meta, $plugin_file ) {
595 if ( UR_PLUGIN_BASENAME === $plugin_file ) {
596 $new_plugin_meta = array(
597 'docs' => '<a href="' . esc_url( apply_filters( 'user_registration_docs_url', 'https://docs.wpuserregistration.com/' ) ) . '" area-label="' . esc_attr__( 'View User Registration & Membership documentation', 'user-registration' ) . '">' . esc_html__( 'Docs', 'user-registration' ) . '</a>',
598 'support' => '<a href="' . esc_url( apply_filters( 'user_registration_support_url', 'https://wpuserregistration.com/support/' ) ) . '" area-label="' . esc_attr__( 'Visit free customer support', 'user-registration' ) . '">' . __( 'Free support', 'user-registration' ) . '</a>',
599 );
600
601 return array_merge( $plugin_meta, $new_plugin_meta );
602 }
603
604 return (array) $plugin_meta;
605 }
606
607
608 /**
609 * Update notice
610 *
611 * @param array $args Plugin args.
612 */
613 public static function in_plugin_update_message( $plugin_data, $response ) {
614 if ( empty( $response ) || empty( $response->new_version ) ) {
615 return;
616 }
617 $new_version = (string) $response->new_version;
618
619 $transient_name = 'ur_upgrade_notice_' . $new_version;
620 $upgrade_notice = get_transient( $transient_name );
621
622 if ( false === $upgrade_notice ) {
623 $http_response = wp_safe_remote_get( 'https://plugins.svn.wordpress.org/user-registration/trunk/readme.txt' );
624
625 if ( ! is_wp_error( $http_response ) && ! empty( $http_response['body'] ) ) {
626 $upgrade_notice = self::parse_update_notice( $http_response['body'], $new_version );
627 set_transient( $transient_name, $upgrade_notice, 3 * DAY_IN_SECONDS );
628 }
629 }
630
631 echo wp_kses_post( $upgrade_notice );
632 }
633
634 /**
635 * Parse update notice from readme.
636 *
637 * @param string $content Readme content.
638 * @param string $new_version New version.
639 */
640 private static function parse_update_notice( $content, $new_version ) {
641 $upgrade_notice = '';
642
643 // Match all version blocks under "== Upgrade Notice =="
644 $blocks_regex = '~=\s*([\d\.]+)\s*=(.*?)(?==\s*[\d\.]+\s*=|$)~s';
645 if ( preg_match_all( $blocks_regex, $content, $matches, PREG_SET_ORDER ) ) {
646 foreach ( $matches as $match ) {
647 $version_line = trim( $match[1] );
648 $block_text = trim( $match[2] );
649
650 // Only process the block if it matches $new_version
651 if ( $version_line !== $new_version ) {
652 continue;
653 }
654
655 $notices = (array) preg_split( '~[\r\n]+~', $block_text );
656
657 $upgrade_notice .= '<div class="ur_plugin_upgrade_notice">';
658 $upgrade_notice .= '<div class="ur_plugin_upgrade_notice_body">';
659
660 foreach ( $notices as $line ) {
661 $line = trim( $line );
662 if ( empty( $line ) ) {
663 continue;
664 }
665
666 $line = preg_replace(
667 '~\[\s*([^\]]+)\s*\]\s*\(\s*([^\)]+)\s*\)~',
668 '<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>',
669 $line
670 );
671
672 // Convert headings
673 if ( preg_match( '~^###\s*(.*)~', $line, $heading ) ) {
674 $line = '<p class="upgrade-title" style="font-size:13px;font-weight:600;">' . $heading[1] . '</p>';
675 } elseif ( preg_match( '~^##\s*(.*)~', $line, $heading ) ) {
676 $line = '<p class="upgrade-heading" style="font-size:14px;font-weight:600;">' . $heading[1] . '</p>';
677 } else {
678 $line = '<p style="font-size:12px;">' . $line . '</p>';
679 }
680
681 $upgrade_notice .= wp_kses_post( $line );
682 }
683
684 $upgrade_notice .= '</div>';
685 $upgrade_notice .= '</div>';
686
687 break;
688 }
689 }
690
691 return wp_kses_post( $upgrade_notice );
692 }
693 }
694
695 endif;
696
697 /**
698 * Check to see if UR already defined and resolve conflicts while installing PRO version.
699 *
700 * @since 2.0.4
701 */
702
703 if ( ! function_exists( 'UR' ) ) {
704
705 /**
706 * Main instance of UserRegistration.
707 *
708 * Returns the main instance of FT to prevent the need to use globals.
709 *
710 * @since 1.0.0
711 * @return UserRegistration
712 */
713 function UR() {
714 return UserRegistration::instance();
715 }
716 } else {
717
718 if ( ! function_exists( 'user_registration_pro_activated' ) ) {
719 /**
720 * When Pro version is activated, deactivate free version.
721 */
722 function user_registration_pro_activated() {
723 set_transient( 'user_registration_pro_activated', true );
724 user_registration_free_deactivate();
725 }
726 }
727 add_action( 'activate_user-registration-pro/user-registration.php', 'user_registration_pro_activated' );
728
729 if ( ! function_exists( 'user_registration_free_activated' ) ) {
730 /**
731 * When user activates free version, set the value that is to be used to handle both Free and Pro activation conflict.
732 */
733 function user_registration_free_activated() {
734
735 set_transient( 'user_registration_free_activated', true );
736 }
737 }
738 add_action( 'activate_user-registration/user-registration.php', 'user_registration_free_activated' );
739
740 if ( ! function_exists( 'user_registration_free_deactivated' ) ) {
741 /**
742 * When user deactivates free version, remove the value that was used to handle both Free and Pro activation conflict.
743 */
744 function user_registration_free_deactivated() {
745
746 global $user_registration_free_activated, $user_registration_free_deactivated;
747
748 $user_registration_free_activated = (bool) get_transient( 'user_registration_free_activated' );
749 $user_registration_free_deactivated = true;
750
751 delete_transient( 'user_registration_free_activated' );
752 }
753 }
754 add_action( 'deactivate_user-registration/user-registration.php', 'user_registration_free_deactivated' );
755
756 if ( ! function_exists( 'user_registration_free_deactivate' ) ) {
757 /**
758 * Deactivate Free version if Pro is already activated.
759 *
760 * @since 1.0.0
761 */
762 function user_registration_free_deactivate() {
763
764 $plugin = 'user-registration/user-registration.php';
765
766 deactivate_plugins( $plugin );
767 do_action( 'user_registration_free_deactivate', $plugin );
768 delete_transient( 'user_registration_pro_activated' );
769 }
770 }
771
772 add_action( 'admin_init', 'user_registration_free_deactivate' );
773
774 if ( ! function_exists( 'user_registration_free_notice' ) ) {
775 /**
776 * When user wants to activate Free version alongside Pro, then display the message.
777 */
778 function user_registration_free_notice() {
779
780 global $user_registration_free_activated, $user_registration_free_deactivated;
781
782 if (
783 empty( $user_registration_free_activated ) ||
784 empty( $user_registration_free_deactivated )
785 ) {
786 return;
787 }
788
789 echo '<div class="notice-warning notice is-dismissible"><p>' . wp_kses_post( __( 'As <strong>User Registration & Membership Pro</strong> is active, <strong>User Registration & Membership Free</strong> is now not needed.', 'user-registration' ) ) . '</p></div>';
790
791 if ( isset( $_GET['activate'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
792 unset( $_GET['activate'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
793 }
794
795 unset( $user_registration_free_activated, $user_registration_free_deactivated );
796 }
797 }
798 add_action( 'admin_notices', 'user_registration_free_notice' );
799
800 // Do not process the plugin code further.
801 return;
802 }
803 /**
804 * Development: Hot reload support for webpack dev server.
805 * Enable by setting SCRIPT_DEBUG to true in wp-config.php
806 */
807 if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
808 add_filter(
809 'script_loader_src',
810 function ( $src, $handle ) {
811 $dev_scripts = array(
812 'user-registration-welcome',
813 'user-registration-dashboard',
814 'user-registration-blocks',
815 'user-registration-form-templates',
816 'user-registration-divi-builder',
817 'user-registration-content-access-rules',
818 );
819
820 if ( in_array( $handle, $dev_scripts, true ) ) {
821 $src = str_replace(
822 UR_PLUGIN_URL . 'chunks/',
823 'http://localhost:3000/',
824 $src
825 );
826 }
827
828 return $src;
829 },
830 10,
831 2
832 );
833 }
834
835 // Global for backwards compatibility.
836 $GLOBALS['user-registration'] = UR();
837