| @@ -80,11 +80,10 @@ | ||
| 80 | 80 | * @return \WP_REST_Response |
| 81 | 81 | */ |
| 82 | 82 | public function get_learn_sections( $request ) { |
| 83 | 83 | |
| 84 | - // Get completed modules from option. | |
| 85 | - $completed_modules = get_option( 'wcf_learn_data', array() ); | |
| 86 | - $completed_modules = is_array( $completed_modules ) ? $completed_modules : array(); | |
| 84 | + // Resolved completion state — manual checks plus auto-derived state. | |
| 85 | + $learn_progress = \Cartflows_Learn_Progress::get_instance(); | |
| 87 | 86 | |
| 88 | 87 | $sections = array( |
| 89 | 88 | array( |
| 90 | 89 | 'id' => 'funnel-basics', |
| @@ -103,9 +102,9 @@ | ||
| 103 | 102 | 'plugin_init' => 'woocommerce/woocommerce.php', |
| 104 | 103 | ), |
| 105 | 104 | 'learn_how' => false, |
| 106 | 105 | 'is_pro' => false, |
| 107 | - 'completed' => $this->is_module_completed( 'install-woocommerce', 'active' === \Cartflows_Helper::get_plugin_status( 'woocommerce/woocommerce.php', true ), $completed_modules ), | |
| 106 | + 'completed' => $learn_progress->is_completed( 'install-woocommerce' ), | |
| 108 | 107 | 'plugin_status' => \Cartflows_Helper::get_plugin_status( 'woocommerce/woocommerce.php', true ), |
| 109 | 108 | ), |
| 110 | 109 | array( |
| 111 | 110 | 'id' => 'create-your-first-funnel', |
| @@ -116,11 +115,11 @@ | ||
| 116 | 115 | 'action_type' => 'redirect', |
| 117 | 116 | 'action_data' => array( |
| 118 | 117 | 'url' => admin_url( 'admin.php?page=cartflows&path=flows' ), |
| 119 | 118 | ), |
| 120 | - 'learn_how' => esc_url( 'https://cartflows.com/docs/how-to-create-your-first-cartflows-funnel/?utm_source=dashboard&utm_medium=cartflows&utm_campaign=learn_how' ), | |
| 119 | + 'learn_how' => esc_url( \Cartflows_Helper::get_kb_doc_link( 'https://cartflows.com/docs/how-to-create-your-first-cartflows-funnel/', array( 'utm_campaign' => 'learn_how' ) ) ), | |
| 121 | 120 | 'is_pro' => false, |
| 122 | - 'completed' => $this->is_module_completed( 'create-your-first-funnel', intval( wp_count_posts( CARTFLOWS_FLOW_POST_TYPE )->publish ) > 0, $completed_modules ), | |
| 121 | + 'completed' => $learn_progress->is_completed( 'create-your-first-funnel' ), | |
| 123 | 122 | ), |
| 124 | 123 | ), |
| 125 | 124 | ), |
| 126 | 125 | array( |
| @@ -137,11 +136,11 @@ | ||
| 137 | 136 | 'action_type' => 'redirect', |
| 138 | 137 | 'action_data' => array( |
| 139 | 138 | 'url' => admin_url( 'admin.php?page=cartflows&path=flows' ), |
| 140 | 139 | ), |
| 141 | - 'learn_how' => esc_url( 'https://cartflows.com/docs/editing-and-customising-funnel-steps/?utm_source=dashboard&utm_medium=cartflows&utm_campaign=learn_how' ), | |
| 140 | + 'learn_how' => esc_url( \Cartflows_Helper::get_kb_doc_link( 'https://cartflows.com/docs/editing-and-customising-funnel-steps/', array( 'utm_campaign' => 'learn_how' ) ) ), | |
| 142 | 141 | 'is_pro' => false, |
| 143 | - 'completed' => $this->is_module_completed( 'edit-design-funnel-pages-steps', $this->has_step_been_edited(), $completed_modules ), | |
| 142 | + 'completed' => $learn_progress->is_completed( 'edit-design-funnel-pages-steps' ), | |
| 144 | 143 | ), |
| 145 | 144 | ), |
| 146 | 145 | ), |
| 147 | 146 | array( |
| @@ -158,11 +157,11 @@ | ||
| 158 | 157 | 'action_type' => 'redirect', |
| 159 | 158 | 'action_data' => array( |
| 160 | 159 | 'url' => admin_url( 'edit.php?post_type=product' ), |
| 161 | 160 | ), |
| 162 | - 'learn_how' => esc_url( 'https://cartflows.com/docs/how-to-add-products-in-woocommerce/?utm_source=dashboard&utm_medium=cartflows&utm_campaign=learn_how' ), | |
| 161 | + 'learn_how' => esc_url( \Cartflows_Helper::get_kb_doc_link( 'https://cartflows.com/docs/how-to-add-products-in-woocommerce/', array( 'utm_campaign' => 'learn_how' ) ) ), | |
| 163 | 162 | 'is_pro' => false, |
| 164 | - 'completed' => $this->is_module_completed( 'add-products', intval( wp_count_posts( 'product' )->publish ) > 0, $completed_modules ), | |
| 163 | + 'completed' => $learn_progress->is_completed( 'add-products' ), | |
| 165 | 164 | ), |
| 166 | 165 | array( |
| 167 | 166 | 'id' => 'assign-products-to-checkout', |
| 168 | 167 | 'title' => __( 'Assign Products to Checkout', 'cartflows' ), |
| @@ -172,11 +171,11 @@ | ||
| 172 | 171 | 'action_type' => 'redirect', |
| 173 | 172 | 'action_data' => array( |
| 174 | 173 | 'url' => admin_url( 'admin.php?page=cartflows&path=flows' ), |
| 175 | 174 | ), |
| 176 | - 'learn_how' => esc_url( 'https://cartflows.com/docs/how-to-add-assign-products-to-a-checkout-step-in-cartflows/?utm_source=dashboard&utm_medium=cartflows&utm_campaign=learn_how' ), | |
| 175 | + 'learn_how' => esc_url( \Cartflows_Helper::get_kb_doc_link( 'https://cartflows.com/docs/how-to-add-assign-products-to-a-checkout-step-in-cartflows/', array( 'utm_campaign' => 'learn_how' ) ) ), | |
| 177 | 176 | 'is_pro' => false, |
| 178 | - 'completed' => $this->is_module_completed( 'assign-products-to-checkout', $this->is_checkout_product_is_assigned(), $completed_modules ), | |
| 177 | + 'completed' => $learn_progress->is_completed( 'assign-products-to-checkout' ), | |
| 179 | 178 | ), |
| 180 | 179 | ), |
| 181 | 180 | ), |
| 182 | 181 | array( |
| @@ -195,9 +194,9 @@ | ||
| 195 | 194 | 'url' => admin_url( 'admin.php?page=wc-settings&tab=checkout' ), |
| 196 | 195 | ), |
| 197 | 196 | 'learn_how' => false, |
| 198 | 197 | 'is_pro' => false, |
| 199 | - 'completed' => $this->is_module_completed( 'connect-payment-gateway', $this->check_supported_payment_gateway_used(), $completed_modules ), | |
| 198 | + 'completed' => $learn_progress->is_completed( 'connect-payment-gateway' ), | |
| 200 | 199 | ), |
| 201 | 200 | ), |
| 202 | 201 | ), |
| 203 | 202 | array( |
| @@ -217,9 +216,9 @@ | ||
| 217 | 216 | 'plugin_init' => 'woo-cart-abandonment-recovery/woo-cart-abandonment-recovery.php', |
| 218 | 217 | ), |
| 219 | 218 | 'learn_how' => false, |
| 220 | 219 | 'is_pro' => false, |
| 221 | - 'completed' => $this->is_module_completed( 'enable-cart-abandonment-tracking', 'active' === \Cartflows_Helper::get_plugin_status( 'woo-cart-abandonment-recovery/woo-cart-abandonment-recovery.php', true ), $completed_modules ), | |
| 220 | + 'completed' => $learn_progress->is_completed( 'enable-cart-abandonment-tracking' ), | |
| 222 | 221 | 'plugin_status' => \Cartflows_Helper::get_plugin_status( 'woo-cart-abandonment-recovery/woo-cart-abandonment-recovery.php', true ), |
| 223 | 222 | ), |
| 224 | 223 | array( |
| 225 | 224 | 'id' => 'setup-recovery-emails', |
| @@ -232,9 +231,9 @@ | ||
| 232 | 231 | 'url' => admin_url( 'admin.php?page=woo-cart-abandonment-recovery&path=follow-up-templates' ), |
| 233 | 232 | ), |
| 234 | 233 | 'learn_how' => false, |
| 235 | 234 | 'is_pro' => false, |
| 236 | - 'completed' => $this->is_module_completed( 'setup-recovery-emails', $this->check_folloup_emails_created(), $completed_modules ), | |
| 235 | + 'completed' => $learn_progress->is_completed( 'setup-recovery-emails' ), | |
| 237 | 236 | ), |
| 238 | 237 | ), |
| 239 | 238 | ), |
| 240 | 239 | array( |
| @@ -254,9 +253,9 @@ | ||
| 254 | 253 | 'plugin_init' => 'modern-cart/modern-cart.php', |
| 255 | 254 | ), |
| 256 | 255 | 'learn_how' => false, |
| 257 | 256 | 'is_pro' => false, |
| 258 | - 'completed' => $this->is_module_completed( 'enable-modern-cart', 'active' === \Cartflows_Helper::get_plugin_status( 'modern-cart/modern-cart.php', true ), $completed_modules ), | |
| 257 | + 'completed' => $learn_progress->is_completed( 'enable-modern-cart' ), | |
| 259 | 258 | 'plugin_status' => \Cartflows_Helper::get_plugin_status( 'modern-cart/modern-cart.php', true ), |
| 260 | 259 | ), |
| 261 | 260 | array( |
| 262 | 261 | 'id' => 'setup-your-cart', |
| @@ -269,9 +268,9 @@ | ||
| 269 | 268 | 'url' => admin_url( 'admin.php?page=moderncart_settings' ), |
| 270 | 269 | ), |
| 271 | 270 | 'learn_how' => false, |
| 272 | 271 | 'is_pro' => false, |
| 273 | - 'completed' => $this->is_module_completed( 'setup-your-cart', $this->is_modern_cart_configured(), $completed_modules ), | |
| 272 | + 'completed' => $learn_progress->is_completed( 'setup-your-cart' ), | |
| 274 | 273 | ), |
| 275 | 274 | ), |
| 276 | 275 | ), |
| 277 | 276 | array( |
| @@ -288,11 +287,11 @@ | ||
| 288 | 287 | 'action_type' => 'redirect', |
| 289 | 288 | 'action_data' => array( |
| 290 | 289 | 'url' => admin_url( 'admin.php?page=cartflows&path=flows' ), |
| 291 | 290 | ), |
| 292 | - 'learn_how' => esc_url( 'https://cartflows.com/docs/how-to-add-order-bumps-to-woocommerce-sales-funnel/?utm_source=dashboard&utm_medium=cartflows&utm_campaign=learn_how' ), | |
| 291 | + 'learn_how' => esc_url( \Cartflows_Helper::get_kb_doc_link( 'https://cartflows.com/docs/how-to-add-order-bumps-to-woocommerce-sales-funnel/', array( 'utm_campaign' => 'learn_how' ) ) ), | |
| 293 | 292 | 'is_pro' => ! _is_cartflows_pro(), |
| 294 | - 'completed' => $this->is_module_completed( 'add-order-bump', $this->has_published_order_bump(), $completed_modules ), | |
| 293 | + 'completed' => $learn_progress->is_completed( 'add-order-bump' ), | |
| 295 | 294 | ), |
| 296 | 295 | array( |
| 297 | 296 | 'id' => 'setup-upsell-downsell-offers', |
| 298 | 297 | 'title' => __( 'Setup Upsell / Downsell Offers', 'cartflows' ), |
| @@ -302,11 +301,11 @@ | ||
| 302 | 301 | 'action_type' => 'redirect', |
| 303 | 302 | 'action_data' => array( |
| 304 | 303 | 'url' => admin_url( 'admin.php?page=cartflows&path=flows' ), |
| 305 | 304 | ), |
| 306 | - 'learn_how' => esc_url( 'https://cartflows.com/docs/how-to-create-one-click-upsell-and-downsell-offers-in-cartflows/?utm_source=dashboard&utm_medium=cartflows&utm_campaign=learn_how' ), | |
| 305 | + 'learn_how' => esc_url( \Cartflows_Helper::get_kb_doc_link( 'https://cartflows.com/docs/how-to-create-one-click-upsell-and-downsell-offers-in-cartflows/', array( 'utm_campaign' => 'learn_how' ) ) ), | |
| 307 | 306 | 'is_pro' => ! _is_cartflows_pro(), |
| 308 | - 'completed' => $this->is_module_completed( 'setup-upsell-downsell-offers', $this->has_published_offer_step(), $completed_modules ), | |
| 307 | + 'completed' => $learn_progress->is_completed( 'setup-upsell-downsell-offers' ), | |
| 309 | 308 | ), |
| 310 | 309 | ), |
| 311 | 310 | ), |
| 312 | 311 | ); |
| @@ -314,281 +313,8 @@ | ||
| 314 | 313 | $response = new \WP_REST_Response( $sections ); |
| 315 | 314 | $response->set_status( 200 ); |
| 316 | 315 | |
| 317 | 316 | return $response; |
| 318 | - } | |
| 319 | - | |
| 320 | - /** | |
| 321 | - * Check whether a module is completed. | |
| 322 | - * | |
| 323 | - * @param string $module_id Module identifier. | |
| 324 | - * @param bool $is_auto_completed Whether the module is auto-completed. | |
| 325 | - * @param array $completed_modules Stored list of completed modules. | |
| 326 | - * | |
| 327 | - * @return bool Whether the module should be treated as completed. | |
| 328 | - */ | |
| 329 | - private function is_module_completed( $module_id, $is_auto_completed, $completed_modules ) { | |
| 330 | - | |
| 331 | - if ( $is_auto_completed ) { | |
| 332 | - return true; | |
| 333 | - } | |
| 334 | - | |
| 335 | - return in_array( $module_id, $completed_modules, true ); | |
| 336 | - } | |
| 337 | - | |
| 338 | - /** | |
| 339 | - * Checks if any checkout step has a product assigned. | |
| 340 | - * | |
| 341 | - * Iterates through recent checkout steps and determines | |
| 342 | - * if at least one has an assigned product in the 'wcf-checkout-products' meta. | |
| 343 | - * | |
| 344 | - * @since 2.2.2 | |
| 345 | - * | |
| 346 | - * @return bool True if a checkout step has a product assigned, otherwise false. | |
| 347 | - */ | |
| 348 | - public function is_checkout_product_is_assigned() { | |
| 349 | - | |
| 350 | - // Fetch the 10 most recently modified published checkout steps that have the 'wcf-checkout-products' meta key. | |
| 351 | - $steps = get_posts( | |
| 352 | - array( | |
| 353 | - 'post_type' => CARTFLOWS_STEP_POST_TYPE, // Only 'cartflows_step' post type. | |
| 354 | - 'post_status' => array( 'publish' ), // Only published posts. | |
| 355 | - 'posts_per_page' => 10, // Limit to 10 results for performance. | |
| 356 | - 'orderby' => 'modified', // Order by last modified date. | |
| 357 | - 'order' => 'DESC', // Most recently modified first. | |
| 358 | - 'fields' => 'ids', // Only retrieve post IDs for efficiency. | |
| 359 | - 'meta_query' => array( //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query | |
| 360 | - array( | |
| 361 | - 'key' => 'wcf-step-type', // Must be a checkout step. | |
| 362 | - 'value' => 'checkout', | |
| 363 | - ), | |
| 364 | - array( | |
| 365 | - 'key' => 'wcf-checkout-products', // Step must have checkout products assigned. | |
| 366 | - 'compare' => 'EXISTS', | |
| 367 | - ), | |
| 368 | - ), | |
| 369 | - ) | |
| 370 | - ); | |
| 371 | - | |
| 372 | - // If no eligible steps found, return false. | |
| 373 | - if ( empty( $steps ) ) { | |
| 374 | - return false; | |
| 375 | - } | |
| 376 | - | |
| 377 | - // Loop through each checkout step. | |
| 378 | - foreach ( $steps as $step_id ) { | |
| 379 | - // Get assigned products for current step. | |
| 380 | - $products = get_post_meta( $step_id, 'wcf-checkout-products', true ); | |
| 381 | - | |
| 382 | - // Skip if there are no products or the first product entry is empty. | |
| 383 | - if ( ! is_array( $products ) || empty( $products ) || empty( $products[0]['product'] ) ) { | |
| 384 | - continue; | |
| 385 | - } | |
| 386 | - | |
| 387 | - // Get the product ID of the first assigned product. | |
| 388 | - $product_id = $products[0]['product']; | |
| 389 | - | |
| 390 | - // Check if a valid numeric product ID is assigned. | |
| 391 | - if ( is_numeric( $product_id ) && (int) $product_id > 0 ) { | |
| 392 | - return true; // A product has been assigned to at least one checkout step. | |
| 393 | - } | |
| 394 | - } | |
| 395 | - | |
| 396 | - // If no checkout step with a valid product was found, return false. | |
| 397 | - return false; | |
| 398 | - } | |
| 399 | - | |
| 400 | - /** | |
| 401 | - * Check if a configured WooCommerce payment gateway is available. | |
| 402 | - * | |
| 403 | - * For the learn step we only need to know whether the store has at least one | |
| 404 | - * payment gateway plugin that is installed, configured, and enabled in either | |
| 405 | - * live or sandbox/test mode. WooCommerce's | |
| 406 | - * WC_Payment_Gateways::get_available_payment_gateways() already returns only | |
| 407 | - * gateways that are enabled and ready to use, so we can rely on that. | |
| 408 | - * | |
| 409 | - * @since 2.2.2 | |
| 410 | - * | |
| 411 | - * @return bool True if at least one gateway is available, otherwise false. | |
| 412 | - */ | |
| 413 | - public function check_supported_payment_gateway_used() { | |
| 414 | - | |
| 415 | - // Ensure WooCommerce is active before checking gateways. | |
| 416 | - if ( ! function_exists( 'WC' ) ) { | |
| 417 | - return false; | |
| 418 | - } | |
| 419 | - | |
| 420 | - $payment_gateways = WC()->payment_gateways(); | |
| 421 | - | |
| 422 | - if ( ! is_object( $payment_gateways ) || ! method_exists( $payment_gateways, 'get_available_payment_gateways' ) ) { | |
| 423 | - return false; | |
| 424 | - } | |
| 425 | - | |
| 426 | - // Get gateways that are installed, configured, and enabled (live or sandbox). | |
| 427 | - $available_gateways = $payment_gateways->get_available_payment_gateways(); | |
| 428 | - | |
| 429 | - if ( empty( $available_gateways ) || ! is_array( $available_gateways ) ) { | |
| 430 | - return false; | |
| 431 | - } | |
| 432 | - | |
| 433 | - // If at least one gateway is available, consider the requirement satisfied. | |
| 434 | - return true; | |
| 435 | - } | |
| 436 | - | |
| 437 | - /** | |
| 438 | - * Check if the user has created and activated follow-up recovery emails. | |
| 439 | - * | |
| 440 | - * First verifies that the Woo Cart Abandonment Recovery plugin is active. | |
| 441 | - * If it is, queries the plugin's email templates table to confirm at least | |
| 442 | - * one template exists with `is_activated = 1`. | |
| 443 | - * | |
| 444 | - * @since 2.2.2 | |
| 445 | - * | |
| 446 | - * @return bool True if at least one active follow-up email template exists, otherwise false. | |
| 447 | - */ | |
| 448 | - public function check_folloup_emails_created() { | |
| 449 | - | |
| 450 | - // Bail early if the Cart Abandonment Recovery plugin is not active. | |
| 451 | - if ( 'active' !== \Cartflows_Helper::get_plugin_status( 'woo-cart-abandonment-recovery/woo-cart-abandonment-recovery.php', true ) ) { | |
| 452 | - return false; | |
| 453 | - } | |
| 454 | - | |
| 455 | - global $wpdb; | |
| 456 | - | |
| 457 | - $template_table = $wpdb->prefix . 'cartflows_ca_email_templates'; | |
| 458 | - | |
| 459 | - // Check whether the table exists before querying it. | |
| 460 | - $table_exists = $wpdb->get_var( //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching | |
| 461 | - $wpdb->prepare( 'SHOW TABLES LIKE %s', $template_table ) | |
| 462 | - ); | |
| 463 | - | |
| 464 | - if ( ! $table_exists ) { | |
| 465 | - return false; | |
| 466 | - } | |
| 467 | - | |
| 468 | - // Count active follow-up email templates. | |
| 469 | - $active_count = (int) $wpdb->get_var( //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching | |
| 470 | - $wpdb->prepare( | |
| 471 | - "SELECT COUNT(*) FROM {$wpdb->prefix}cartflows_ca_email_templates WHERE is_activated = %d", //phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared | |
| 472 | - 1 | |
| 473 | - ) | |
| 474 | - ); | |
| 475 | - | |
| 476 | - return $active_count > 0; | |
| 477 | - } | |
| 478 | - | |
| 479 | - /** | |
| 480 | - * Check if any published checkout step has at least one order bump configured. | |
| 481 | - * | |
| 482 | - * Queries published checkout steps for the presence of the 'wcf-order-bumps' | |
| 483 | - * meta key. Only post IDs are retrieved for performance. | |
| 484 | - * | |
| 485 | - * @since 2.2.2 | |
| 486 | - * | |
| 487 | - * @return bool True if at least one published checkout step has an order bump, otherwise false. | |
| 488 | - */ | |
| 489 | - private function has_published_order_bump() { | |
| 490 | - | |
| 491 | - // Look for any published checkout step that has an order bump configured. | |
| 492 | - $steps = get_posts( | |
| 493 | - array( | |
| 494 | - 'post_type' => CARTFLOWS_STEP_POST_TYPE, | |
| 495 | - 'post_status' => 'publish', | |
| 496 | - 'posts_per_page' => 1, | |
| 497 | - 'fields' => 'ids', | |
| 498 | - 'meta_query' => array( //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query | |
| 499 | - array( | |
| 500 | - 'key' => 'wcf-step-type', | |
| 501 | - 'value' => 'checkout', | |
| 502 | - ), | |
| 503 | - array( | |
| 504 | - 'key' => 'wcf-order-bumps', | |
| 505 | - 'compare' => 'EXISTS', | |
| 506 | - ), | |
| 507 | - ), | |
| 508 | - ) | |
| 509 | - ); | |
| 510 | - | |
| 511 | - return ! empty( $steps ); | |
| 512 | - } | |
| 513 | - | |
| 514 | - /** | |
| 515 | - * Check if any published offer step (upsell or downsell) exists. | |
| 516 | - * | |
| 517 | - * Queries published steps whose 'wcf-step-type' is 'upsell' or 'downsell'. | |
| 518 | - * Only post IDs are retrieved for performance. | |
| 519 | - * | |
| 520 | - * @since 2.2.2 | |
| 521 | - * | |
| 522 | - * @return bool True if at least one published upsell or downsell step exists, otherwise false. | |
| 523 | - */ | |
| 524 | - private function has_published_offer_step() { | |
| 525 | - | |
| 526 | - // Look for any published upsell or downsell step. | |
| 527 | - $offer_steps = get_posts( | |
| 528 | - array( | |
| 529 | - 'post_type' => CARTFLOWS_STEP_POST_TYPE, | |
| 530 | - 'post_status' => 'publish', | |
| 531 | - 'posts_per_page' => 1, | |
| 532 | - 'fields' => 'ids', | |
| 533 | - 'meta_query' => array( //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query | |
| 534 | - array( | |
| 535 | - 'key' => 'wcf-step-type', | |
| 536 | - 'value' => array( 'upsell', 'downsell' ), | |
| 537 | - 'compare' => 'IN', | |
| 538 | - ), | |
| 539 | - ), | |
| 540 | - ) | |
| 541 | - ); | |
| 542 | - | |
| 543 | - return ! empty( $offer_steps ); | |
| 544 | - } | |
| 545 | - | |
| 546 | - /** | |
| 547 | - * Check if any published CartFlows step exists. | |
| 548 | - * | |
| 549 | - * @since 2.2.2 | |
| 550 | - * | |
| 551 | - * @return bool True if at least one published step exists, otherwise false. | |
| 552 | - */ | |
| 553 | - private function has_step_been_edited() { | |
| 554 | - $steps = get_posts( | |
| 555 | - array( | |
| 556 | - 'post_type' => CARTFLOWS_STEP_POST_TYPE, | |
| 557 | - 'post_status' => 'publish', | |
| 558 | - 'posts_per_page' => 1, | |
| 559 | - 'fields' => 'ids', | |
| 560 | - ) | |
| 561 | - ); | |
| 562 | - return ! empty( $steps ); | |
| 563 | - } | |
| 564 | - | |
| 565 | - /** | |
| 566 | - * Check if the Modern Cart plugin is active and has been configured by the user. | |
| 567 | - * | |
| 568 | - * Modern Cart only writes its settings options to the database when the user | |
| 569 | - * explicitly saves the settings page. A fresh install has none of these options, | |
| 570 | - * so their presence reliably indicates that the user has configured the plugin. | |
| 571 | - * | |
| 572 | - * @since 2.2.2 | |
| 573 | - * | |
| 574 | - * @return bool True if Modern Cart is active and at least one settings option exists, otherwise false. | |
| 575 | - */ | |
| 576 | - private function is_modern_cart_configured() { | |
| 577 | - | |
| 578 | - if ( 'active' !== \Cartflows_Helper::get_plugin_status( 'modern-cart/modern-cart.php', true ) ) { | |
| 579 | - return false; | |
| 580 | - } | |
| 581 | - | |
| 582 | - $setting_keys = array( 'moderncart_setting', 'moderncart_cart', 'moderncart_floating', 'moderncart_appearance' ); | |
| 583 | - | |
| 584 | - foreach ( $setting_keys as $key ) { | |
| 585 | - if ( false !== get_option( $key, false ) ) { | |
| 586 | - return true; | |
| 587 | - } | |
| 588 | - } | |
| 589 | - | |
| 590 | - return false; | |
| 591 | 317 | } |
| 592 | 318 | |
| 593 | 319 | /** |
| 594 | 320 | * Check whether a given request has permission to read notes. |