| @@ -1,4 +1,4 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | /** |
| 3 | 3 | * @version 1.0 |
| 4 | 4 | * @package Booking Calendar |
| @@ -58,8 +58,9 @@ | ||
| 58 | 58 | add_filter( 'plugin_action_links', array( $this, 'plugin_links' ), 10, 2 ); |
| 59 | 59 | // Warning message in plugin info. |
| 60 | 60 | add_filter( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 4 ); |
| 61 | 61 | |
| 62 | + // TODO: 2025-06-06 - required to be commented, if we use the Pro version as separate plugin. | |
| 62 | 63 | $this->check_if_need_to_update(); // Check upgrade, if was no activation process |
| 63 | 64 | } |
| 64 | 65 | |
| 65 | 66 | |
| @@ -105,9 +106,9 @@ | ||
| 105 | 106 | $is_delete_if_deactive = get_bk_option( $this->init_option['option-is_delete_if_deactive'] ); // check |
| 106 | 107 | |
| 107 | 108 | if ($is_delete_if_deactive == 'On') { ?> |
| 108 | 109 | <div class="plugin-update-tr"> |
| 109 | - <div class="update-message notice inline notice-warning notice-altNO" style="font-size: 1em;line-height: 2em;margin:0 5px 10px;border-left: 3px solid #dd7000;"><?php | |
| 110 | + <div class="update-message notice inline notice-error" style="line-height: 2.2em;border-left: 3px solid #cc1818;margin-left: 0;color: #cc1818;background: #fff6f4;"><?php | |
| 110 | 111 | // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
| 111 | 112 | echo $this->init_option['message-delete_data']; ?></div> |
| 112 | 113 | </div> |
| 113 | 114 | <?php |
| @@ -112,8 +113,16 @@ | ||
| 112 | 113 | </div> |
| 113 | 114 | <?php |
| 114 | 115 | } |
| 115 | 116 | |
| 117 | + $version = wpbc_get_plugin_version_title(); | |
| 118 | + | |
| 119 | + if ( 'Free' !== $version ) { | |
| 120 | + $plugin_meta[0] .= ' | ' . __( 'Version type', 'booking' ) . ': <strong>Free + ' . ucfirst( $version ) . '</strong>'; | |
| 121 | + } else { | |
| 122 | + $plugin_meta[0] .= ' | ' . __( 'Version type', 'booking' ) . ': <strong>' . ucfirst( $version ) . '</strong>'; | |
| 123 | + } | |
| 124 | + | |
| 116 | 125 | /* |
| 117 | 126 | [$plugin_meta] => Array |
| 118 | 127 | ( |
| 119 | 128 | [0] => Version 2.8.35 |
| @@ -153,9 +162,10 @@ | ||
| 153 | 162 | |
| 154 | 163 | $this_plugin = plugin_basename( WPBC_FILE ); |
| 155 | 164 | |
| 156 | 165 | if ( $file == $this_plugin ) { |
| 157 | - | |
| 166 | + | |
| 167 | + | |
| 158 | 168 | array_unshift( $links, $this->init_option['link_settings'] ); |
| 159 | 169 | |
| 160 | 170 | //array_unshift( $links, $this->init_option['link_whats_new'] ); |
| 161 | 171 | array_unshift( $links, $this->init_option['link_faq'] ); |
| @@ -160,19 +170,26 @@ | ||
| 160 | 170 | //array_unshift( $links, $this->init_option['link_whats_new'] ); |
| 161 | 171 | array_unshift( $links, $this->init_option['link_faq'] ); |
| 162 | 172 | |
| 163 | 173 | |
| 164 | - $links = array_merge( $links, array( | |
| 165 | - '<a class="wpbc_plugins_links__start_tour" title="' . esc_attr( sprintf( __('We\'ll guide you through the steps to set up WP Booking Calendar on your site.','booking'), '<strong>WP Booking Calendar</strong>' ) ) . '" href="' | |
| 166 | - . esc_url( wpbc_get_settings_url() . '&wpbc_setup_wizard=reset&_wpnonce=' . wp_create_nonce( 'wpbc_settings_url_nonce' ) ) | |
| 167 | - //. esc_url( admin_url( add_query_arg( array( 'page' => 'wpbc-about' ), 'index.php' ) ) ) | |
| 168 | - . '">' . esc_attr__( 'Start Setup Wizard', 'booking' ) . '</a>' | |
| 169 | - ) | |
| 174 | + $links = array_merge( $links, array( | |
| 175 | + '<a class="wpbc_plugins_links__start_tour" title="' . esc_attr( sprintf( __('We\'ll guide you through the steps to set up WP Booking Calendar on your site.','booking'), '<strong>WP Booking Calendar</strong>' ) ) . '" href="' | |
| 176 | + . esc_url( wpbc_get_setup_wizard_page_url() ) | |
| 177 | + //. esc_url( admin_url( add_query_arg( array( 'page' => 'wpbc-about' ), 'index.php' ) ) ) | |
| 178 | + . '">' . esc_attr__( 'Start Setup Wizard', 'booking' ) . '</a>' | |
| 179 | + ) | |
| 170 | 180 | ); |
| 171 | 181 | |
| 172 | 182 | |
| 173 | 183 | if ( ! class_exists( 'wpdev_bk_personal' ) ) { |
| 174 | - array_unshift( $links, $this->init_option['link_up'] ); | |
| 184 | + if ( wpbc_is_updated_paid_to_free() ) { | |
| 185 | + array_unshift( | |
| 186 | + $links, | |
| 187 | + '<a style="font-weight:600;" class="wpbc_plugins_links__start_tour" title="' . esc_attr( __( 'Request Update', 'booking' ) ) . '" href="' . esc_url( 'https://wpbookingcalendar.com/request-update/' ) . '">' . esc_attr__( 'Request Pro Version', 'booking' ) . '</a>' | |
| 188 | + ); | |
| 189 | + } else { | |
| 190 | + array_unshift( $links, $this->init_option['link_up'] ); | |
| 191 | + } | |
| 175 | 192 | } else { |
| 176 | 193 | if ( ! class_exists( 'wpdev_bk_multiuser' ) ) { |
| 177 | 194 | array_unshift( $links, $this->init_option['link_upgrade'] ); |
| 178 | 195 | } |
| @@ -210,67 +227,163 @@ | ||
| 210 | 227 | |
| 211 | 228 | } else { |
| 212 | 229 | |
| 213 | 230 | // Check if we was update from free to paid or from lower to higher versions, and do not make normal activation. In this case we need to make update. |
| 214 | - $is_make_activation = $this->is_update_from_lower_to_high_version(); | |
| 231 | + // TODO: 2025-11-23 - Commented, if we use the Pro version as separate plugin. | |
| 232 | + // $is_make_activation = $this->is_update_from_lower_to_high_version(); | |
| 215 | 233 | |
| 216 | 234 | } |
| 217 | 235 | |
| 218 | - // Add hook for initial activation. | |
| 219 | - if ( $is_make_activation ) { | |
| 220 | - add_action( 'plugins_loaded', array( $this, 'wpbc_activate_initial' ), 1030 ); | |
| 221 | - } | |
| 236 | + // Run the installed version's activation on the next request after files change. | |
| 237 | + if ( $is_make_activation ) { | |
| 238 | + add_action( 'init', array( $this, 'wpbc_activate_detected_update' ), 1030 ); | |
| 239 | + } | |
| 222 | 240 | } |
| 223 | 241 | } |
| 224 | 242 | |
| 225 | 243 | |
| 226 | 244 | /** |
| 227 | - * Upgrade during bulk upgrade of plugins | |
| 228 | - * | |
| 229 | - * @param type $return_val | |
| 230 | - * @param type $hook_extra | |
| 231 | - * | |
| 232 | - * @return type | |
| 233 | - */ | |
| 234 | - public function wpbc_install_in_bulk_upgrade( $return_val, $hook_extra ) { | |
| 245 | + * Run activation work after WordPress successfully replaces this plugin. | |
| 246 | + * | |
| 247 | + * WordPress continues running the previously loaded PHP code during the | |
| 248 | + * updater request. The completed-update context bridges that request to the | |
| 249 | + * newly installed code so the next request can distinguish an interactive | |
| 250 | + * Plugins-screen update from a non-interactive updater. | |
| 251 | + * | |
| 252 | + * @param bool|WP_Error $return_val Installation result. | |
| 253 | + * @param array $hook_extra WordPress upgrader context. | |
| 254 | + * | |
| 255 | + * @return bool|WP_Error Unchanged installation result. | |
| 256 | + */ | |
| 257 | + public function wpbc_install_in_bulk_upgrade( $return_val, $hook_extra ) { | |
| 235 | 258 | |
| 236 | 259 | if ( is_wp_error( $return_val ) ) { |
| 237 | 260 | return $return_val; |
| 238 | 261 | } |
| 239 | 262 | |
| 240 | - if ( isset( $hook_extra ) ) { | |
| 241 | - if ( isset( $hook_extra['plugin'] ) ) { | |
| 242 | - $file_name = basename( WPBC_FILE ); | |
| 243 | - $pos = strpos( $hook_extra['plugin'], trim( $file_name ) ); | |
| 244 | - if ( false !== $pos ) { | |
| 245 | - $this->wpbc_activate(); | |
| 246 | - } | |
| 247 | - } | |
| 248 | - } | |
| 263 | + $updated_plugin = isset( $hook_extra['plugin'] ) && is_scalar( $hook_extra['plugin'] ) | |
| 264 | + ? plugin_basename( sanitize_text_field( (string) $hook_extra['plugin'] ) ) | |
| 265 | + : ''; | |
| 266 | + if ( plugin_basename( WPBC_FILE ) === $updated_plugin ) { | |
| 267 | + $this->wpbc_activate(); | |
| 268 | + | |
| 269 | + if ( class_exists( 'WPBC_Setup_Wizard_First_Install_State' ) ) { | |
| 270 | + WPBC_Setup_Wizard_First_Install_State::record_completed_plugin_update( WPBC_FILE, WP_BK_VERSION_NUM ); | |
| 271 | + } | |
| 272 | + } | |
| 249 | 273 | |
| 250 | 274 | return $return_val; |
| 251 | 275 | } |
| 252 | 276 | |
| 253 | 277 | |
| 254 | - /** | |
| 255 | - * User clicked on "Activate" link at Plugins Menu. | |
| 256 | - * | |
| 257 | - * @return type | |
| 258 | - */ | |
| 259 | - public function wpbc_activate_initial() { | |
| 278 | + /** | |
| 279 | + * User clicked on "Activate" link at Plugins Menu. | |
| 280 | + * | |
| 281 | + * Genuine-install state is captured before activation creates canonical | |
| 282 | + * tables and options. A dedicated versioned intent lets the following request | |
| 283 | + * distinguish first-install onboarding from update/reactivation What's New, | |
| 284 | + * while the released boolean redirect transient remains backward compatible. | |
| 285 | + * | |
| 286 | + * @return void | |
| 287 | + */ | |
| 288 | + public function wpbc_activate_initial() { | |
| 289 | + $is_initial_install = function_exists( 'wpbc_is_plugin_initial_install' ) | |
| 290 | + ? wpbc_is_plugin_initial_install() | |
| 291 | + : false; | |
| 292 | + | |
| 293 | + // Activate the plugin. | |
| 294 | + $this->wpbc_activate(); | |
| 295 | + | |
| 296 | + $this->wpbc_schedule_activation_redirect( $is_initial_install, 'activation' ); | |
| 297 | + } | |
| 298 | + | |
| 299 | + /** | |
| 300 | + * Run activation after the installed plugin version changes. | |
| 301 | + * | |
| 302 | + * A matching updater handoff suppresses navigation for automatic and other | |
| 303 | + * non-interactive updates, while an interactive update opens What's New. When | |
| 304 | + * no handoff exists, the files were replaced outside the standard upgrader | |
| 305 | + * and retain the released one-time What's New behavior. | |
| 306 | + * | |
| 307 | + * @return void | |
| 308 | + */ | |
| 309 | + public function wpbc_activate_detected_update() { | |
| 310 | + $update_context = class_exists( 'WPBC_Setup_Wizard_First_Install_State' ) | |
| 311 | + ? WPBC_Setup_Wizard_First_Install_State::get_plugin_update_context( WPBC_FILE, WP_BK_VERSION_NUM ) | |
| 312 | + : false; | |
| 313 | + | |
| 314 | + $this->wpbc_activate(); | |
| 315 | + | |
| 316 | + if ( class_exists( 'WPBC_Setup_Wizard_First_Install_State' ) ) { | |
| 317 | + WPBC_Setup_Wizard_First_Install_State::clear_plugin_update_context( WPBC_FILE ); | |
| 318 | + } | |
| 319 | + | |
| 320 | + if ( | |
| 321 | + is_array( $update_context ) | |
| 322 | + && WPBC_Setup_Wizard_First_Install_State::UPDATE_SOURCE_SUPPRESSED === $update_context['source'] | |
| 323 | + ) { | |
| 324 | + return; | |
| 325 | + } | |
| 326 | + | |
| 327 | + $is_manual_update = is_array( $update_context ) | |
| 328 | + && WPBC_Setup_Wizard_First_Install_State::UPDATE_SOURCE_MANUAL === $update_context['source']; | |
| 329 | + $redirect_user_id = $is_manual_update && isset( $update_context['user_id'] ) ? absint( $update_context['user_id'] ) : null; | |
| 330 | + | |
| 331 | + $this->wpbc_schedule_activation_redirect( | |
| 332 | + false, | |
| 333 | + $is_manual_update ? 'manual_update' : 'detected_file_update', | |
| 334 | + $redirect_user_id, | |
| 335 | + $is_manual_update ? WPBC_Setup_Wizard_First_Install_State::MANUAL_UPDATE_INTENT_TTL : 30, | |
| 336 | + ! $is_manual_update | |
| 337 | + ); | |
| 338 | + } | |
| 339 | + | |
| 340 | + /** | |
| 341 | + * Schedule one allowed post-activation navigation intent. | |
| 342 | + * | |
| 343 | + * @param bool $is_initial_install Whether activation began from an empty installation. | |
| 344 | + * @param string $source Activation or update source identifier. | |
| 345 | + * @param int|null $user_id User who should receive the redirect, or null for the current user. | |
| 346 | + * @param int $intent_ttl Structured redirect lifetime in seconds. | |
| 347 | + * @param bool $write_legacy Whether to retain the released boolean redirect for older consumers. | |
| 348 | + * | |
| 349 | + * @return void | |
| 350 | + */ | |
| 351 | + private function wpbc_schedule_activation_redirect( $is_initial_install, $source, $user_id = null, $intent_ttl = 30, $write_legacy = true ) { | |
| 352 | + $is_restricted = class_exists( 'WPBC_Setup_Wizard_First_Install_State' ) | |
| 353 | + ? WPBC_Setup_Wizard_First_Install_State::is_automatic_onboarding_restricted() | |
| 354 | + : ( | |
| 355 | + is_network_admin() | |
| 356 | + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only activation context detection. | |
| 357 | + || isset( $_GET['activate-multi'] ) | |
| 358 | + || wpbc_is_this_demo() | |
| 359 | + || ( defined( 'WPBC_IS_PLAYGROUND' ) && true === WPBC_IS_PLAYGROUND ) | |
| 360 | + || defined( 'IFRAME_REQUEST' ) | |
| 361 | + ); | |
| 362 | + if ( $is_restricted ) { | |
| 363 | + return; | |
| 364 | + } | |
| 365 | + | |
| 366 | + if ( class_exists( 'WPBC_Setup_Wizard_First_Install_State' ) ) { | |
| 367 | + $redirect_intent = WPBC_Setup_Wizard_First_Install_State::create_activation_redirect_intent( | |
| 368 | + $is_initial_install, | |
| 369 | + WP_BK_VERSION_NUM, | |
| 370 | + $source, | |
| 371 | + $user_id | |
| 372 | + ); | |
| 373 | + set_transient( | |
| 374 | + WPBC_Setup_Wizard_First_Install_State::ACTIVATION_INTENT_TRANSIENT, | |
| 375 | + $redirect_intent, | |
| 376 | + absint( $intent_ttl ) | |
| 377 | + ); | |
| 378 | + } | |
| 379 | + | |
| 380 | + if ( $write_legacy ) { | |
| 381 | + // Keep the released boolean payload for older paid editions and Welcome consumers. | |
| 382 | + set_transient( $this->init_option['transient-wpbc_activation_redirect'], true, 30 ); | |
| 383 | + } | |
| 384 | + } | |
| 260 | 385 | |
| 261 | - // Activate the plugin. | |
| 262 | - $this->wpbc_activate(); | |
| 263 | - | |
| 264 | - // Bail if this demo or activating from network, or bulk. | |
| 265 | - if ( is_network_admin() || isset( $_GET['activate-multi'] ) || wpbc_is_this_demo() ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing | |
| 266 | - return; | |
| 267 | - } | |
| 268 | - | |
| 269 | - // Add the transient to redirect - Showing Welcome screen. | |
| 270 | - set_transient( $this->init_option['transient-wpbc_activation_redirect'], true, 30 ); | |
| 271 | - } | |
| 272 | - | |
| 273 | 386 | // ----------------------------------------------------------------------------------------------------------------- |
| 274 | 387 | |
| 275 | 388 | /** |
| 276 | 389 | * Run Activate |
| @@ -293,8 +406,9 @@ | ||
| 293 | 406 | /** |
| 294 | 407 | * Run Deactivate |
| 295 | 408 | */ |
| 296 | 409 | public function wpbc_deactivate() { |
| 410 | + wpbc_set_plugin_deactivation_state( true ); | |
| 297 | 411 | |
| 298 | 412 | WPBC_Action_Scheduler_Compatibility::raise_memory_limit(); |
| 299 | 413 | WPBC_Action_Scheduler_Compatibility::raise_time_limit( 300 ); |
| 300 | 414 | |
| @@ -309,5 +423,5 @@ | ||
| 309 | 423 | delete_bk_option( $this->init_option['option-activation_process'] ); |
| 310 | 424 | } |
| 311 | 425 | } |
| 312 | 426 | |
| 313 | -} | |
| 427 | +} | |