PluginProbe
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce / trunk
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce vtrunk
3.2.0 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.1 trunk 1.0.4 1.1.0 1.1.0.1 1.1.1 1.1.10 1.1.11 1.1.12 1.1.13 1.1.14 1.1.15 1.1.16 1.1.17 1.1.18 1.1.19 1.1.2 1.1.20 1.1.21 All 160 releases
cartflows / admin-core / api / learn.php

learn.php in CartFlows – Funnel Builder & Checkout Plugin for WooCommerce trunk, at admin-core/api/learn.php

608 lines 22.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * CartFlows Learn Data Query.
4 *
5 * @package CartFlows
6 */
7
8 namespace CartflowsAdmin\AdminCore\Api;
9
10 // Exit if accessed directly.
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit;
13 }
14
15 use CartflowsAdmin\AdminCore\Api\ApiBase;
16
17 /**
18 * Class Learn.
19 */
20 class Learn extends ApiBase {
21
22 /**
23 * Route base.
24 *
25 * @var string
26 */
27 protected $rest_base = '/admin/learn/';
28
29 /**
30 * Instance
31 *
32 * @access private
33 * @var object Class object.
34 * @since 2.2.2
35 */
36 private static $instance;
37
38 /**
39 * Initiator
40 *
41 * @since 2.2.2
42 * @return object initialized object of class.
43 */
44 public static function get_instance() {
45 if ( ! isset( self::$instance ) ) {
46 self::$instance = new self();
47 }
48 return self::$instance;
49 }
50
51 /**
52 * Init Hooks.
53 *
54 * @since 1.0.0
55 * @return void
56 */
57 public function register_routes() {
58
59 $namespace = $this->get_api_namespace();
60
61 register_rest_route(
62 $namespace,
63 $this->rest_base,
64 array(
65 array(
66 'methods' => \WP_REST_Server::READABLE,
67 'callback' => array( $this, 'get_learn_sections' ),
68 'permission_callback' => array( $this, 'get_items_permissions_check' ),
69 'args' => array(),
70 ),
71 )
72 );
73 }
74
75
76 /**
77 * Get learn sections.
78 *
79 * @param WP_REST_Request $request Full details about the request.
80 * @return \WP_REST_Response
81 */
82 public function get_learn_sections( $request ) {
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();
87
88 $sections = array(
89 array(
90 'id' => 'funnel-basics',
91 'title' => __( 'Funnel Basics', 'cartflows' ),
92 'description' => __( 'Build a solid foundation for your first funnel.', 'cartflows' ),
93 'modules' => array(
94 array(
95 'id' => 'install-woocommerce',
96 'title' => __( 'Install WooCommerce', 'cartflows' ),
97 'description' => __( 'Install WooCommerce to enable products, checkout, and payments.', 'cartflows' ),
98 'cta' => __( 'WooCommerce', 'cartflows' ),
99 'action' => 'Installs WooCommerce Instantly',
100 'action_type' => 'install_plugin',
101 'action_data' => array(
102 'plugin_slug' => 'woocommerce',
103 'plugin_init' => 'woocommerce/woocommerce.php',
104 ),
105 'learn_how' => false,
106 'is_pro' => false,
107 'completed' => $this->is_module_completed( 'install-woocommerce', 'active' === \Cartflows_Helper::get_plugin_status( 'woocommerce/woocommerce.php', true ), $completed_modules ),
108 'plugin_status' => \Cartflows_Helper::get_plugin_status( 'woocommerce/woocommerce.php', true ),
109 ),
110 array(
111 'id' => 'create-your-first-funnel',
112 'title' => __( 'Create Your First Funnel', 'cartflows' ),
113 'description' => __( 'Start by creating a funnel and selecting a ready-made template.', 'cartflows' ),
114 'cta' => __( 'Create Funnel', 'cartflows' ),
115 'action' => 'Redirects to Funnel Templates Library',
116 'action_type' => 'redirect',
117 'action_data' => array(
118 'url' => admin_url( 'admin.php?page=cartflows&path=flows' ),
119 ),
120 '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 '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 ),
123 ),
124 ),
125 ),
126 array(
127 'id' => 'design-customize-pages',
128 'title' => __( 'Design & Customize Pages', 'cartflows' ),
129 'description' => __( 'Make your funnel pages match your brand and goals.', 'cartflows' ),
130 'modules' => array(
131 array(
132 'id' => 'edit-design-funnel-pages-steps',
133 'title' => __( 'Edit & Design Funnel Pages/Steps', 'cartflows' ),
134 'description' => __( 'Customize your landing, checkout, and thank you pages using your preferred page builder.', 'cartflows' ),
135 'cta' => __( 'Edit Steps', 'cartflows' ),
136 'action' => 'Redirects to Funnel Editor',
137 'action_type' => 'redirect',
138 'action_data' => array(
139 'url' => admin_url( 'admin.php?page=cartflows&path=flows' ),
140 ),
141 '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 'is_pro' => false,
143 'completed' => $this->is_module_completed( 'edit-design-funnel-pages-steps', $this->has_step_been_edited(), $completed_modules ),
144 ),
145 ),
146 ),
147 array(
148 'id' => 'setup-products',
149 'title' => __( 'Setup Products', 'cartflows' ),
150 'description' => __( 'Add and manage the products you\'ll sell through your funnels.', 'cartflows' ),
151 'modules' => array(
152 array(
153 'id' => 'add-products',
154 'title' => __( 'Add Products', 'cartflows' ),
155 'description' => __( 'Create or import products to use in your CartFlows funnel.', 'cartflows' ),
156 'cta' => __( 'Add Products', 'cartflows' ),
157 'action' => 'Redirects to WooCommerce > Products',
158 'action_type' => 'redirect',
159 'action_data' => array(
160 'url' => admin_url( 'edit.php?post_type=product' ),
161 ),
162 '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 'is_pro' => false,
164 'completed' => $this->is_module_completed( 'add-products', intval( wp_count_posts( 'product' )->publish ) > 0, $completed_modules ),
165 ),
166 array(
167 'id' => 'assign-products-to-checkout',
168 'title' => __( 'Assign Products to Checkout', 'cartflows' ),
169 'description' => __( 'Attach products to your checkout step and control pricing & quantity.', 'cartflows' ),
170 'cta' => __( 'Select Products', 'cartflows' ),
171 'action' => 'Redirects to Funnel > Checkout Step > Products',
172 'action_type' => 'redirect',
173 'action_data' => array(
174 'url' => admin_url( 'admin.php?page=cartflows&path=flows' ),
175 ),
176 '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 'is_pro' => false,
178 'completed' => $this->is_module_completed( 'assign-products-to-checkout', $this->is_checkout_product_is_assigned(), $completed_modules ),
179 ),
180 ),
181 ),
182 array(
183 'id' => 'setup-payments',
184 'title' => __( 'Setup Payments', 'cartflows' ),
185 'description' => __( 'Accept payments securely with your preferred gateways.', 'cartflows' ),
186 'modules' => array(
187 array(
188 'id' => 'connect-payment-gateway',
189 'title' => __( 'Connect Payment Gateway', 'cartflows' ),
190 'description' => __( 'Set up Stripe, PayPal, or other WooCommerce-supported payment methods.', 'cartflows' ),
191 'cta' => __( 'Setup Payments', 'cartflows' ),
192 'action' => 'Redirects to WooCommerce > Payments',
193 'action_type' => 'redirect',
194 'action_data' => array(
195 'url' => admin_url( 'admin.php?page=wc-settings&tab=checkout' ),
196 ),
197 'learn_how' => false,
198 'is_pro' => false,
199 'completed' => $this->is_module_completed( 'connect-payment-gateway', $this->check_supported_payment_gateway_used(), $completed_modules ),
200 ),
201 ),
202 ),
203 array(
204 'id' => 'setup-cart-abandonment-recovery',
205 'title' => __( 'Setup Cart Abandonment Recovery', 'cartflows' ),
206 'description' => __( 'Recover lost revenue from incomplete checkouts.', 'cartflows' ),
207 'modules' => array(
208 array(
209 'id' => 'enable-cart-abandonment-tracking',
210 'title' => __( 'Enable Cart Abandonment Tracking', 'cartflows' ),
211 'description' => __( 'Start tracking abandoned carts automatically.', 'cartflows' ),
212 'cta' => __( 'Cart Abandonment Recovery', 'cartflows' ),
213 'action' => 'Installs CAR Free Instantly',
214 'action_type' => 'install_plugin',
215 'action_data' => array(
216 'plugin_slug' => 'woo-cart-abandonment-recovery',
217 'plugin_init' => 'woo-cart-abandonment-recovery/woo-cart-abandonment-recovery.php',
218 ),
219 'learn_how' => false,
220 '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 ),
222 'plugin_status' => \Cartflows_Helper::get_plugin_status( 'woo-cart-abandonment-recovery/woo-cart-abandonment-recovery.php', true ),
223 ),
224 array(
225 'id' => 'setup-recovery-emails',
226 'title' => __( 'Setup Recovery Emails', 'cartflows' ),
227 'description' => __( 'Edit and setup recovery emails to start recovering lost sales automatically.', 'cartflows' ),
228 'cta' => __( 'Setup Emails', 'cartflows' ),
229 'action' => 'Redirects to CAR > Follow Ups',
230 'action_type' => 'redirect',
231 'action_data' => array(
232 'url' => admin_url( 'admin.php?page=woo-cart-abandonment-recovery&path=follow-up-templates' ),
233 ),
234 'learn_how' => false,
235 'is_pro' => false,
236 'completed' => $this->is_module_completed( 'setup-recovery-emails', $this->check_folloup_emails_created(), $completed_modules ),
237 ),
238 ),
239 ),
240 array(
241 'id' => 'modernise-your-cart',
242 'title' => __( 'Modernise Your Cart', 'cartflows' ),
243 'description' => __( 'Deliver a faster, cleaner, and more conversion-focused cart experience.', 'cartflows' ),
244 'modules' => array(
245 array(
246 'id' => 'enable-modern-cart',
247 'title' => __( 'Enable Modern Cart', 'cartflows' ),
248 'description' => __( 'Switch to the modern cart layout for better UX and performance.', 'cartflows' ),
249 'cta' => __( 'Modern Cart', 'cartflows' ),
250 'action' => 'Installs MCW Free Instantly',
251 'action_type' => 'install_plugin',
252 'action_data' => array(
253 'plugin_slug' => 'modern-cart',
254 'plugin_init' => 'modern-cart/modern-cart.php',
255 ),
256 'learn_how' => false,
257 '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 ),
259 'plugin_status' => \Cartflows_Helper::get_plugin_status( 'modern-cart/modern-cart.php', true ),
260 ),
261 array(
262 'id' => 'setup-your-cart',
263 'title' => __( 'Setup Your Cart', 'cartflows' ),
264 'description' => __( 'Set up and customize your cart settings to match your brand style.', 'cartflows' ),
265 'cta' => __( 'Setup Cart', 'cartflows' ),
266 'action' => 'Redirects to MCW > Settings',
267 'action_type' => 'redirect',
268 'action_data' => array(
269 'url' => admin_url( 'admin.php?page=moderncart_settings' ),
270 ),
271 'learn_how' => false,
272 'is_pro' => false,
273 'completed' => $this->is_module_completed( 'setup-your-cart', $this->is_modern_cart_configured(), $completed_modules ),
274 ),
275 ),
276 ),
277 array(
278 'id' => 'setup-offers',
279 'title' => __( 'Setup Offers', 'cartflows' ),
280 'description' => __( 'Increase order value with smart one-click offers.', 'cartflows' ),
281 'modules' => array(
282 array(
283 'id' => 'add-order-bump',
284 'title' => __( 'Add Order Bump', 'cartflows' ),
285 'description' => __( 'Offer complementary products directly on the checkout page.', 'cartflows' ),
286 'cta' => __( 'Add Order Bump', 'cartflows' ),
287 'action' => 'Redirects to Funnel > Checkout Step > Order Bump',
288 'action_type' => 'redirect',
289 'action_data' => array(
290 'url' => admin_url( 'admin.php?page=cartflows&path=flows' ),
291 ),
292 '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 'is_pro' => ! _is_cartflows_pro(),
294 'completed' => $this->is_module_completed( 'add-order-bump', $this->has_published_order_bump(), $completed_modules ),
295 ),
296 array(
297 'id' => 'setup-upsell-downsell-offers',
298 'title' => __( 'Setup Upsell / Downsell Offers', 'cartflows' ),
299 'description' => __( 'Create one-click post-checkout offers to boost revenue.', 'cartflows' ),
300 'cta' => __( 'Add Offer Step', 'cartflows' ),
301 'action' => 'Redirects to Funnel > Checkout Step > Order Bump',
302 'action_type' => 'redirect',
303 'action_data' => array(
304 'url' => admin_url( 'admin.php?page=cartflows&path=flows' ),
305 ),
306 '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 'is_pro' => ! _is_cartflows_pro(),
308 'completed' => $this->is_module_completed( 'setup-upsell-downsell-offers', $this->has_published_offer_step(), $completed_modules ),
309 ),
310 ),
311 ),
312 );
313
314 $response = new \WP_REST_Response( $sections );
315 $response->set_status( 200 );
316
317 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 }
592
593 /**
594 * Check whether a given request has permission to read notes.
595 *
596 * @param WP_REST_Request $request Full details about the request.
597 * @return \WP_Error|boolean
598 */
599 public function get_items_permissions_check( $request ) {
600
601 if ( ! current_user_can( 'cartflows_manage_settings' ) ) {
602 return new \WP_Error( 'cartflows_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'cartflows' ), array( 'status' => rest_authorization_required_code() ) );
603 }
604
605 return true;
606 }
607 }
608