try( bool $user_can, $caps, $id ): bool { if ( $caps === 'edit_entries_form_single' && wpforms_is_form_template( $id ) ) { $user_can = false; } return $user_can; } /** * Display admin notice for the entries page. * * @since 1.8.8 */ public function get_template_entries_notice() { if ( ! wpforms_is_admin_page( 'entries', 'list' ) ) { return; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended $form_id = ! empty( $_REQUEST['form_id'] ) ? absint( $_REQUEST['form_id'] ) : 0; // The notice should be displayed only for form templates. if ( ! wpforms_is_form_template( $form_id ) ) { return; } // If there are no entries, we don't need to display the notice on the empty state page. $entries = wpforms()->obj( 'entry' )->get_entries( [ 'form_id' => $form_id, 'limit' => 1, ] ); if ( empty( $entries ) ) { return; } /** This filter is documented in wpforms/src/Pro/Tasks/Actions/PurgeTemplateEntryTask.php */ $delay = (int) apply_filters( 'wpforms_pro_tasks_actions_purge_template_entry_task_delay', DAY_IN_SECONDS ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName Notice::warning( sprintf( /* translators: %s - delay in formatted time. */ esc_html__( 'Form template entries are for testing purposes and will be automatically deleted after %s.', 'wpforms-lite' ), // The `- 1` hack is to avoid the "1 day" message in favor of "24 hours". human_time_diff( time(), time() + $delay - 1 ) ) ); } /** * Display admin notice for the entry page. * * @since 1.8.8 */ public function get_template_entry_notice() { if ( ! wpforms_is_admin_page( 'entries', 'details' ) ) { return; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended $entry_id = ! empty( $_REQUEST['entry_id'] ) ? absint( $_REQUEST['entry_id'] ) : 0; $entry = wpforms()->obj( 'entry' )->get( $entry_id ); // If entry does not exist, we don't need to display the notice on the empty state page. if ( empty( $entry ) ) { return; } // The notice should be displayed only for form template entry. if ( ! wpforms_is_form_template( $entry->form_id ) ) { return; } $meta = wpforms()->obj( 'entry_meta' )->get_meta( [ 'entry_id' => absint( $entry_id ), 'type' => 'purge_template_entry_task', 'number' => 1, ] ); if ( empty( $meta ) ) { return; } $task = wpforms_json_decode( $meta[0]->data,true ); if ( empty( $task['timestamp'] ) ) { return; } Notice::warning( sprintf( /* translators: %s - delay in formatted time. */ esc_html__( 'Form template entries are for testing purposes. This entry will be automatically deleted in %s.', 'wpforms-lite' ), human_time_diff( time(), $task['timestamp'] ) ) ); } /** * Get the Show Templates user option. * * If the user has not set the Show Templates screen option, it will default to showing templates. * In this case, we want to show templates by default. * * @since 1.8.8 * * @return bool Whether to show templates by default. */ public function get_forms_overview_show_form_templates_option(): bool { $screen_options = get_user_option( 'wpforms_forms_overview_options' ); $result = $screen_options['wpforms_forms_overview_show_form_templates'] ?? true; return $result !== '0'; // phpcs:ignore WPForms.Formatting.EmptyLineBeforeReturn.RemoveEmptyLineBeforeReturnStatement } /** * Add `wpforms-template` post type to the form args. * * @since 1.8.8 * * @param array $args Form arguments. * * @return array */ public function add_template_post_type( array $args ): array { // Only add the post type to the form args on the overview page. if ( ! wpforms_is_admin_page( 'overview' ) ) { return $args; } // Only add the template post type if the Show Templates screen option is enabled // and `post_type` is not already set. if ( ! isset( $args['post_type'] ) && wpforms()->obj( 'forms_overview' )->overview_show_form_templates() ) { $args['post_type'] = wpforms()->obj( 'form' )::POST_TYPES; } return $args; } /** * Add user templates to the form templates list. * * @since 1.8.8 * * @param array $templates Form templates. * * @return array Form templates. */ public function add_form_templates( array $templates ): array { $user_templates = wpforms()->obj( 'form' )->get( '', [ 'post_type' => 'wpforms-template' ] ); if ( empty( $user_templates ) ) { return $templates; } foreach ( $user_templates as $template ) { $template_data = wpforms_decode( $template->post_content ); $edit_url = add_query_arg( [ 'page' => 'wpforms-builder', 'form_id' => $template->ID, ], admin_url( 'admin.php' ) ); $create_url = add_query_arg( [ 'page' => 'wpforms-builder', 'form_id' => $template->ID, 'action' => 'template_to_form', '_wpnonce' => wp_create_nonce( 'wpforms_template_to_form_form_nonce' ), ], admin_url( 'admin.php' ) ); $templates[] = [ 'name' => $template->post_title, 'slug' => 'wpforms-user-template-' . $template->ID, 'action_text' => wpforms_is_admin_page( 'builder' ) || wp_doing_ajax() ? esc_html__( 'Use Template', 'wpforms-lite' ) : esc_html__( 'Create Form', 'wpforms-lite' ), 'edit_action_text' => esc_html__( 'Edit Template', 'wpforms-lite' ), 'description' => ! empty( $template_data['settings']['template_description'] ) ? $template_data['settings']['template_description'] : '', 'source' => 'wpforms-user-template', 'create_url' => $create_url, 'edit_url' => $edit_url, 'categories' => [ 'user' ], 'has_access' => true, 'data' => $template_data, 'post_id' => $template->ID, ]; } return $templates; } /** * AJAX handler for removing user templates. * * @since 1.8.8 */ public function ajax_remove_user_template(): void { // Run a security check. check_ajax_referer( 'wpforms-form-templates', 'nonce' ); $template_id = isset( $_POST['template'] ) ? absint( $_POST['template'] ) : 0; if ( ! $template_id ) { wp_send_json_error(); } // Check for permissions for the specific template. if ( ! wpforms_current_user_can( 'delete_form_single', $template_id ) ) { wp_send_json_error( esc_html__( 'You do not have permission to delete this template.', 'wpforms-lite' ) ); } // Verify the post exists and is a template. $template = get_post( $template_id ); if ( ! $template || $template->post_type !== 'wpforms-template' ) { wp_send_json_error( esc_html__( 'Template not found.', 'wpforms-lite' ) ); } // Delete the template. $result = wp_delete_post( $template_id, true ); if ( ! $result ) { wp_send_json_error( esc_html__( 'Failed to delete the template.', 'wpforms-lite' ) ); } wp_send_json_success(); } /** * Add purge entry task. * * @since 1.8.8 * * @param array $tasks Task class list. */ public function add_purge_entry_task( $tasks ) { $tasks[] = PurgeTemplateEntryTask::class; return $tasks; } /** * Modify the form data before it is processed to disable payment processing. * * @since 1.8.8 * * @param array $form_data Form data. * * @return array */ public function process_before_form_data( $form_data ) { if ( ! isset( $form_data['id'] ) ) { return $form_data; } if ( wpforms_is_form_template( $form_data['id'] ) ) { $form_data['payments'] = []; } return $form_data; } /** * Disable Lite Connect integration for user templates while processing submission. * * @since 1.8.8 * * @param array $fields Form fields. * @param array $entry Form entry. * @param array $form_data Form data. */ public function process_entry( array $fields, array $entry, array $form_data ) { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks if ( ! wpforms_is_form_template( $form_data['id'] ) ) { return; } add_filter( 'wpforms_integrations_lite_connect_is_allowed', '__return_false' ); } } } else { // We set one so that it gets autoloaded. update_option( self::SETTINGS_OPTION_PREFIX . $setting, $value, true ); } } if ( is_numeric( $value ) ) { $value = (int) $value; } $default_array_value = null; switch ( $setting ) { case 'post_types_blacklist': $default_array_value = Defaults::$blacklisted_post_types; break; case 'taxonomies_blacklist': $default_array_value = Defaults::$blacklisted_taxonomies; break; case 'post_meta_whitelist': $default_array_value = Defaults::get_post_meta_whitelist(); break; case 'comment_meta_whitelist': $default_array_value = Defaults::get_comment_meta_whitelist(); break; case 'known_importers': $default_array_value = Defaults::get_known_importers(); break; } if ( $default_array_value ) { if ( is_array( $value ) ) { $value = array_unique( array_merge( $value, $default_array_value ) ); } else { $value = $default_array_value; } } return $value; } /** * Change multiple settings in the same time. * * @access public * @static * * @param array $new_settings The new settings. */ public static function update_settings( $new_settings ) { $validated_settings = array_intersect_key( $new_settings, self::$valid_settings ); foreach ( $validated_settings as $setting => $value ) { /** * Custom table migration logic. * * This needs to happen before the option is updated, to avoid race conditions where we update the option, * but haven't yet created the table or can't create it. * * On high-traffic sites this can lead to Sync trying to write in a non-existent table. * * So to avoid this, we're going to first try to initialize everything and then update the option. */ if ( 'custom_queue_table_enabled' === $setting ) { // Need to check the current value in the database to make sure we're not doing anything weird. $old_value = get_option( self::SETTINGS_OPTION_PREFIX . $setting, null ); if ( ! $old_value && $value ) { /** * The custom table has been enabled. * * - Initialize the custom table * - Migrate the data * * If something fails, migrate back to the options table and clean up everything about the custom table. */ $init_result = Queue_Storage_Table::initialize_custom_sync_table(); /** * Check if there was a problem when initializing the table. */ if ( is_wp_error( $init_result ) ) { /** * Unable to initialize the table properly. Set the value to `false` as we can't enable it. */ $value = false; /** * Send error to WPCOM, so we can track and take an appropriate action. */ $data = array( 'timestamp' => microtime( true ), 'error_code' => $init_result->get_error_code(), 'response_body' => $init_result->get_error_message(), ); $sender = Sender::get_instance(); $sender->send_action( 'jetpack_sync_storage_error_custom_init', $data ); } elseif ( ! Queue_Storage_Table::migrate_from_options_table_to_custom_table() ) { /** * If the migration fails, do a reverse migration and set the value to `false` as we can't * safely enable the table. */ Queue_Storage_Table::migrate_from_custom_table_to_options_table(); // Set $value to `false` as we couldn't do the migration, and we can't continue enabling the table. $value = false; /** * Send error to WPCOM, so we can track and take an appropriate action. */ $data = array( 'timestamp' => microtime( true ), // TODO: Maybe add more details here for the migration, i.e. how many items where in the queue? ); $sender = Sender::get_instance(); $sender->send_action( 'jetpack_sync_storage_error_custom_migrate', $data ); } } elseif ( $old_value && ! $value ) { if ( ! get_transient( Queue_Storage_Table::CUSTOM_QUEUE_TABLE_DISABLE_WPDB_ERROR_NOT_EXIST_FLAG ) ) { /** * The custom table has been disabled, migrate what we can from the custom table to the options table unless * the custom table doesn't exist in the DB. */ Queue_Storage_Table::migrate_from_custom_table_to_options_table(); } } } /** * Regular option update and handling */ $updated = false; if ( self::is_network_setting( $setting ) ) { if ( is_multisite() && is_main_site() ) { $updated = update_site_option( self::SETTINGS_OPTION_PREFIX . $setting, $value ); } } else { $updated = update_option( self::SETTINGS_OPTION_PREFIX . $setting, $value, true ); } // If we set the disabled option to true, clear the queues. if ( ( 'disable' === $setting || 'network_disable' === $setting ) && (bool) $value ) { $listener = Listener::get_instance(); $listener->get_sync_queue()->reset(); $listener->get_full_sync_queue()->reset(); } // Do not enable Dedicated Sync if we cannot spawn a Dedicated Sync request. if ( 'dedicated_sync_enabled' === $setting && $updated && (bool) $value ) { if ( ! Dedicated_Sender::can_spawn_dedicated_sync_request() ) { update_option( self::SETTINGS_OPTION_PREFIX . $setting, 0, true ); } } } } /** * Whether the specified setting is a network setting. * * @access public * @static * * @param string $setting Setting name. * @return boolean Whether the setting is a network setting. */ public static function is_network_setting( $setting ) { return str_starts_with( $setting, 'network_' ); } /** * Returns escaped SQL for blacklisted post types. * Can be injected directly into a WHERE clause. * * @access public * @static * * @return string SQL WHERE clause. */ public static function get_blacklisted_post_types_sql() { return 'post_type NOT IN (\'' . implode( '\', \'', array_map( 'esc_sql', static::get_setting( 'post_types_blacklist' ) ) ) . '\')'; } /** * Returns escaped values for disallowed post types. * * @access public * @static * * @return array Post type filter values */ public static function get_disallowed_post_types_structured() { return array( 'post_type' => array( 'operator' => 'NOT IN', 'values' => array_map( 'esc_sql', static::get_setting( 'post_types_blacklist' ) ), ), ); } /** * Returns escaped SQL for blacklisted taxonomies. * Can be injected directly into a WHERE clause. * * @access public * @static * * @return string SQL WHERE clause. */ public static function get_blacklisted_taxonomies_sql() { return "taxonomy NOT IN ('" . implode( "', '", array_map( 'esc_sql', static::get_setting( 'taxonomies_blacklist' ) ) ) . "')"; } /** * Returns escaped SQL for whitelisted taxonomies. * Can be injected directly into a WHERE clause. * * @access public * @static * * @return string SQL WHERE clause. */ public static function get_whitelisted_taxonomies_sql() { global $wp_taxonomies; $allowed_taxonomies = array_keys( $wp_taxonomies ); $allowed_taxonomies = array_diff( $allowed_taxonomies, static::get_setting( 'taxonomies_blacklist' ) ); return "taxonomy IN ('" . implode( "', '", array_map( 'esc_sql', $allowed_taxonomies ) ) . "')"; } /** * Returns escaped SQL for blacklisted post meta. * Can be injected directly into a WHERE clause. * * @access public * @static * * @return string SQL WHERE clause. */ public static function get_whitelisted_post_meta_sql() { return 'meta_key IN (\'' . implode( '\', \'', array_map( 'esc_sql', static::get_setting( 'post_meta_whitelist' ) ) ) . '\')'; } /** * Returns escaped SQL for allowed post meta keys. * * @access public * @static * * @return array Meta keys filter values */ public static function get_allowed_post_meta_structured() { return array( 'meta_key' => array( 'operator' => 'IN', 'values' => array_map( 'esc_sql', static::get_setting( 'post_meta_whitelist' ) ), ), ); } /** * Returns structured SQL clause for blacklisted taxonomies. * * @access public * @static * * @return array taxonomies filter values */ public static function get_blacklisted_taxonomies_structured() { return array( 'taxonomy' => array( 'operator' => 'NOT IN', 'values' => array_map( 'esc_sql', static::get_setting( 'taxonomies_blacklist' ) ), ), ); } /** * Returns structured SQL clause for allowed taxonomies. * * @access public * @static * * @return array taxonomies filter values */ public static function get_allowed_taxonomies_structured() { global $wp_taxonomies; $allowed_taxonomies = array_keys( $wp_taxonomies ); $allowed_taxonomies = array_diff( $allowed_taxonomies, static::get_setting( 'taxonomies_blacklist' ) ); return array( 'taxonomy' => array( 'operator' => 'IN', 'values' => array_map( 'esc_sql', $allowed_taxonomies ), ), ); } /** * Returns escaped SQL for blacklisted comment meta. * Can be injected directly into a WHERE clause. * * @access public * @static * * @return string SQL WHERE clause. */ public static function get_whitelisted_comment_meta_sql() { return 'meta_key IN (\'' . implode( '\', \'', array_map( 'esc_sql', static::get_setting( 'comment_meta_whitelist' ) ) ) . '\')'; } /** * Returns SQL-escaped values for allowed post meta keys. * * @access public * @static * * @return array Meta keys filter values */ public static function get_allowed_comment_meta_structured() { return array( 'meta_key' => array( 'operator' => 'IN', 'values' => array_map( 'esc_sql', static::get_setting( 'comment_meta_whitelist' ) ), ), ); } /** * Returns SQL-escaped values for allowed order_item meta keys. * * @access public * @static * * @return array Meta keys filter values */ public static function get_allowed_order_itemmeta_structured() { // Make sure that we only try to add the properties when the class exists. if ( ! class_exists( '\Automattic\Jetpack\Sync\Modules\WooCommerce' ) ) { return array(); } $values = \Automattic\Jetpack\Sync\Modules\WooCommerce::$order_item_meta_whitelist; return array( 'meta_key' => array( 'operator' => 'IN', 'values' => array_map( 'esc_sql', $values ), ), ); } /** * Returns escaped SQL for comments, excluding any spam comments. * Can be injected directly into a WHERE clause. * * @access public * @static * * @return string SQL WHERE clause. */ public static function get_comments_filter_sql() { return "comment_approved <> 'spam'"; } /** * Delete any settings options and clean up the current settings state. * * @access public * @static */ public static function reset_data() { $valid_settings = self::$valid_settings; foreach ( $valid_settings as $option => $value ) { delete_option( self::SETTINGS_OPTION_PREFIX . $option ); } self::set_importing( null ); self::set_doing_cron( null ); self::set_is_syncing( null ); self::set_is_sending( null ); } /** * Set the importing state. * * @access public * @static * * @param boolean $is_importing Whether WordPress is currently importing. */ public static function set_importing( $is_importing ) { // Set to NULL to revert to WP_IMPORTING, the standard behavior. self::$is_importing = $is_importing; } /** * Whether WordPress is currently importing. * * @access public * @static * * @return boolean Whether WordPress is currently importing. */ public static function is_importing() { if ( self::$is_importing !== null ) { return self::$is_importing; } return defined( 'WP_IMPORTING' ) && WP_IMPORTING; } /** * Whether sync is enabled. * * @access public * @static * * @return boolean Whether sync is enabled. */ public static function is_sync_enabled() { return ! ( static::get_setting( 'disable' ) || static::get_setting( 'network_disable' ) ); } /** * Set the WP cron state. * * @access public * @static * * @param boolean $is_doing_cron Whether WordPress is currently doing WP cron. */ public static function set_doing_cron( $is_doing_cron ) { // Set to NULL to revert to WP_IMPORTING, the standard behavior. self::$is_doing_cron = $is_doing_cron; } /** * Whether WordPress is currently doing WP cron. * * @access public * @static * * @return boolean Whether WordPress is currently doing WP cron. */ public static function is_doing_cron() { if ( self::$is_doing_cron !== null ) { return self::$is_doing_cron; } return defined( 'DOING_CRON' ) && DOING_CRON; } /** * Whether we are currently syncing. * * @access public * @static * * @return boolean Whether we are currently syncing. */ public static function is_syncing() { return (bool) self::$is_syncing || Constants::is_true( 'REST_API_REQUEST' ); } /** * Set the syncing state. * * @access public * @static * * @param boolean $is_syncing Whether we are currently syncing. */ public static function set_is_syncing( $is_syncing ) { self::$is_syncing = $is_syncing; } /** * Whether we are currently sending sync items. * * @access public * @static * * @return boolean Whether we are currently sending sync items. */ public static function is_sending() { return (bool) self::$is_sending; } /** * Set the sending state. * * @access public * @static * * @param boolean $is_sending Whether we are currently sending sync items. */ public static function set_is_sending( $is_sending ) { self::$is_sending = $is_sending; } /** * Whether should send from the queue * * @access public * @static * * @param string $queue_id The queue identifier. * * @return boolean Whether sync is enabled. */ public static function is_sender_enabled( $queue_id ) { return (bool) static::get_setting( $queue_id . '_sender_enabled' ); } /** * Whether checksums are enabled. * * @access public * @static * * @return boolean Whether sync is enabled. */ public static function is_checksum_enabled() { return ! (bool) static::get_setting( 'checksum_disable' ); } /** * Whether dedicated Sync flow is enabled. * * @access public * @static * * @return boolean Whether dedicated Sync flow is enabled. */ public static function is_dedicated_sync_enabled() { return (bool) static::get_setting( 'dedicated_sync_enabled' ); } /** * Whether custom queue table is enabled. * * @access public * @static * * @return boolean Whether custom queue table is enabled. */ public static function is_custom_queue_table_enabled() { return (bool) static::get_setting( 'custom_queue_table_enabled' ); } /** * Whether wpcom rest api is enabled. * * @access public * @static * * @return boolean Whether wpcom rest api is enabled. */ public static function is_wpcom_rest_api_enabled() { return (bool) static::get_setting( 'wpcom_rest_api_enabled' ); } }
Fatal error: Uncaught Error: Class "Automattic\Jetpack\Sync\Settings" not found in /htdocs/wp-content/plugins/woocommerce-payments/vendor/automattic/jetpack-sync/src/class-actions.php:305 Stack trace: #0 /htdocs/wp-content/plugins/woocommerce-payments/vendor/automattic/jetpack-sync/src/class-main.php(24): Automattic\Jetpack\Sync\Actions::sync_allowed() #1 /htdocs/wp-content/plugins/woocommerce-payments/vendor/automattic/jetpack-config/src/class-config.php(257): Automattic\Jetpack\Sync\Main::configure() #2 /htdocs/wp-content/plugins/woocommerce-payments/vendor/automattic/jetpack-config/src/class-config.php(217): Automattic\Jetpack\Config->enable_sync() #3 /htdocs/wp-content/plugins/woocommerce-payments/vendor/automattic/jetpack-config/src/class-config.php(112): Automattic\Jetpack\Config->ensure_feature('sync') #4 /htdocs/wp-includes/class-wp-hook.php(341): Automattic\Jetpack\Config->on_plugins_loaded('') #5 /htdocs/wp-includes/class-wp-hook.php(365): WP_Hook->apply_filters(NULL, Array) #6 /htdocs/wp-includes/plugin.php(522): WP_Hook->do_action(Array) #7 /htdocs/wp-settings.php(593): do_action('plugins_loaded') #8 /htdocs/wp-config.php(98): require_once('/htdocs/wp-sett...') #9 /htdocs/wp-load.php(50): require_once('/htdocs/wp-conf...') #10 /htdocs/wp-blog-header.php(13): require_once('/htdocs/wp-load...') #11 /htdocs/index.php(17): require('/htdocs/wp-blog...') #12 {main} thrown in /htdocs/wp-content/plugins/woocommerce-payments/vendor/automattic/jetpack-sync/src/class-actions.php on line 305