-->', ), 'rsvp-form' => array( 'title' => __( 'RSVP Form', 'jetpack-forms' ), 'blockTypes' => array( 'jetpack/contact-form' ), 'categories' => array( $category_slug ), 'content' => '
', ), 'registration-form' => array( 'title' => __( 'Registration Form', 'jetpack-forms' ), 'blockTypes' => array( 'jetpack/contact-form' ), 'categories' => array( $category_slug ), 'content' => '
', ), 'appointment-form' => array( 'title' => __( 'Appointment Form', 'jetpack-forms' ), 'blockTypes' => array( 'jetpack/contact-form' ), 'categories' => array( $category_slug ), 'content' => '
', ), 'feedback-form' => array( 'title' => __( 'Feedback Form', 'jetpack-forms' ), 'blockTypes' => array( 'jetpack/contact-form' ), 'categories' => array( $category_slug ), 'content' => '
', ), 'salesforce-lead-form' => array( 'title' => __( 'Salesforce Lead Form', 'jetpack-forms' ), 'blockTypes' => array( 'jetpack/contact-form' ), 'categories' => array( $category_slug ), 'content' => '
', ), ); foreach ( $patterns as $name => $pattern ) { register_block_pattern( $name, $pattern ); } } /** * Sets the 'block_template' attribute on all instances of wp:jetpack/contact-form in * the $_wp_current_template_content global variable. * * The $_wp_current_template_content global variable is hydrated immediately prior to * 'template_include' in wp-includes/template-loader.php. * * This fixes Contact Form Blocks added to FSE _templates_ (e.g. Single or 404). * * @param string $template Template to be loaded. */ public static function grunion_contact_form_set_block_template_attribute( $template ) { global $_wp_current_template_content; if ( ! is_string( $template ) ) { return $template; } if ( 'template-canvas.php' === basename( $template ) ) { Contact_Form::style_on(); $_wp_current_template_content = self::grunion_contact_form_apply_block_attribute( $_wp_current_template_content, array( 'block_template' => 'canvas', ) ); } return $template; } /** * Sets the $grunion_block_template_part_id global. * * This is part of the fix for Contact Form Blocks added to FSE _template parts_ (e.g footer). * The global is processed in Contact_Form::parse(). * * @param string $template_part_id ID for the currently rendered template part. */ public static function grunion_contact_form_set_block_template_part_id_global( $template_part_id ) { $GLOBALS['grunion_block_template_part_id'] = $template_part_id; } /** * Unsets the global when block is done rendering. * * @param string $content Rendered block content. * @param array $block The full block, including name and attributes. * @return string */ public static function grunion_contact_form_unset_block_template_part_id_global( $content, $block ) { if ( isset( $block['blockName'] ) && 'core/template-part' === $block['blockName'] && isset( $GLOBALS['grunion_block_template_part_id'] ) ) { unset( $GLOBALS['grunion_block_template_part_id'] ); } return $content; } /** * Sets the 'widget' attribute on all instances of the contact form in the widget block. * * @param string $content Existing widget block content. * @param array $instance Array of settings for the current widget. * @param \WP_Widget_Block $widget Current Block widget instance. * @return string */ public static function grunion_contact_form_filter_widget_block_content( $content, $instance, $widget ) { Contact_Form::style_on(); // Inject 'block_template' => into all instances of the contact form block. return self::grunion_contact_form_apply_block_attribute( $content, array( 'widget' => $widget->id, ) ); } /** * Deletes old spam feedbacks to keep the posts table size under control. */ public static function grunion_delete_old_spam() { global $wpdb; $grunion_delete_limit = 100; $now_gmt = current_time( 'mysql', 1 ); // Use the spam status changed date if available, otherwise fall back to post_date_gmt for backward compatibility $sql = $wpdb->prepare( " SELECT p.`ID` FROM $wpdb->posts p LEFT JOIN $wpdb->postmeta pm ON p.`ID` = pm.`post_id` AND pm.`meta_key` = '_spam_status_changed_gmt' WHERE DATE_SUB( %s, INTERVAL 15 DAY ) > COALESCE( pm.`meta_value`, p.`post_date_gmt` ) AND p.`post_type` = 'feedback' AND p.`post_status` = 'spam' LIMIT %d ", $now_gmt, $grunion_delete_limit ); $post_ids = $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching foreach ( (array) $post_ids as $post_id ) { // force a full delete, skip the trash wp_delete_post( $post_id, true ); } if ( /** * Filter if the module run OPTIMIZE TABLE on the core WP tables. * * @module contact-form * * @since 1.3.1 * @since 6.4.0 Set to false by default. * * @param bool $filter Should Jetpack optimize the table, defaults to false. */ apply_filters( 'grunion_optimize_table', false ) ) { $wpdb->query( "OPTIMIZE TABLE $wpdb->posts" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching } // if we hit the max then schedule another run if ( count( $post_ids ) >= $grunion_delete_limit ) { wp_schedule_single_event( time() + 700, 'grunion_scheduled_delete' ); } } /** * Deletes old temp feedback to keep the posts table size under control. * * @since 6.5.0 */ public static function grunion_delete_old_temp_feedback() { global $wpdb; $grunion_delete_limit = 100; $now_gmt = current_time( 'mysql', 1 ); $sql = $wpdb->prepare( " SELECT `ID` FROM $wpdb->posts WHERE DATE_SUB( %s, INTERVAL 1 DAY ) > `post_date_gmt` AND `post_type` = 'feedback' AND `post_status` = 'jp-temp-feedback' LIMIT %d ", $now_gmt, $grunion_delete_limit ); // The SQL query is already prepared with $wpdb->prepare() above, and direct query is needed for performance-critical cleanup operation $post_ids = $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching foreach ( (array) $post_ids as $post_id ) { // force a full delete, skip the trash wp_delete_post( $post_id, true ); } if ( /** * Filter if the module run OPTIMIZE TABLE on the core WP tables. * * @module contact-form * * @since 6.5.0 * * @param bool $filter Should Jetpack optimize the table, defaults to false. */ apply_filters( 'grunion_optimize_table', false ) ) { // OPTIMIZE TABLE is a MySQL-specific maintenance command that cannot be prepared and is only run when explicitly enabled via filter $wpdb->query( "OPTIMIZE TABLE $wpdb->posts" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching } // if we hit the max then schedule another run if ( count( $post_ids ) >= $grunion_delete_limit ) { wp_schedule_single_event( time() + 700, 'grunion_scheduled_delete_temp' ); } } /** * Send an event to Tracks on form submission. * * @param int $post_id - the post_id for the CPT that is created. * @param array $all_values - array containing all form fields. * @param array $extra_values - array containing extra form metadata. * * @return null|void */ public static function jetpack_tracks_record_grunion_pre_message_sent( $post_id, $all_values = array(), $extra_values = array() ) { $post = get_post( $post_id ); if ( $post ) { $extra = gmdate( 'Y-W', strtotime( $post->post_date_gmt ) ); } else { $extra = 'no-post'; } /** This action is documented in jetpack/modules/widgets/social-media-icons.php */ do_action( 'jetpack_bump_stats_extras', 'jetpack_forms_message_sent', $extra ); $form_type = isset( $extra_values['widget'] ) ? 'widget' : 'block'; $context = ''; if ( isset( $extra_values['block_template'] ) ) { $context = 'template'; } elseif ( isset( $extra_values['block_template_part'] ) ) { $context = 'template_part'; } $plugin = Contact_Form_Plugin::init(); $plugin->record_tracks_event( 'jetpack_forms_message_sent', array( 'post_id' => $post_id, 'form_type' => $form_type, 'context' => $context, 'has_consent' => empty( $all_values['email_marketing_consent'] ) ? 0 : 1, ) ); } /** * Adds a given attribute to all instances of the Contact Form block. * * @param string $content Existing content to process. * @param array $new_attr New attributes to add. * @return string */ public static function grunion_contact_form_apply_block_attribute( $content, $new_attr ) { if ( ! is_string( $content ) ) { // If the content is not a string, we cannot process it. return $content; } if ( false === stripos( $content, 'wp:jetpack/contact-form' ) ) { return $content; } // Parse blocks using WordPress core function. $blocks = parse_blocks( $content ); // Recursively modify contact form blocks. $modified_blocks = self::modify_contact_form_blocks_recursive( $blocks, $new_attr ); // Serialize back to block markup. return serialize_blocks( $modified_blocks ); } /** * Recursively modifies contact form blocks to add new attributes. * * @param array $blocks Array of parsed blocks. * @param array $new_attr New attributes to add. * @return array Modified blocks array. */ private static function modify_contact_form_blocks_recursive( $blocks, $new_attr ) { foreach ( $blocks as &$block ) { // Check if this is a contact form block. if ( 'jetpack/contact-form' === $block['blockName'] ) { // Merge new attributes with existing ones. $block['attrs'] = array_merge( $block['attrs'] ?? array(), $new_attr ); } // Recursively process inner blocks. if ( ! empty( $block['innerBlocks'] ) ) { $block['innerBlocks'] = self::modify_contact_form_blocks_recursive( $block['innerBlocks'], $new_attr ); } } return $blocks; } /** * Get a filename for export tasks * * @param string $source The filtered source for exported data. * @return string The filename without source nor date suffix. */ public static function get_export_filename( $source = '' ) { return $source === '' ? sprintf( /* translators: Site title, used to craft the export filename, eg "MySite - Jetpack Form Responses" */ __( '%s - Jetpack Form Responses', 'jetpack-forms' ), sanitize_file_name( get_bloginfo( 'name' ) ) ) : sprintf( /* translators: 1: Site title; 2: post title. Used to craft the export filename, eg "MySite - Jetpack Form Responses - Contact" */ __( '%1$s - Jetpack Form Responses - %2$s', 'jetpack-forms' ), sanitize_file_name( get_bloginfo( 'name' ) ), sanitize_file_name( $source ) ); } }
Fatal error: Uncaught Error: Class "Automattic\Jetpack\Forms\ContactForm\Util" not found in /htdocs/wp-content/plugins/jetpack/jetpack_vendor/automattic/jetpack-forms/src/class-jetpack-forms.php:23 Stack trace: #0 /htdocs/wp-content/plugins/jetpack/modules/contact-form.php(30): Automattic\Jetpack\Forms\Jetpack_Forms::load_contact_form() #1 /htdocs/wp-content/plugins/jetpack/class.jetpack.php(1686): include_once('/htdocs/wp-cont...') #2 /htdocs/wp-includes/class-wp-hook.php(341): Jetpack::load_modules('') #3 /htdocs/wp-includes/class-wp-hook.php(365): WP_Hook->apply_filters('', Array) #4 /htdocs/wp-includes/plugin.php(522): WP_Hook->do_action(Array) #5 /htdocs/wp-settings.php(720): do_action('after_setup_the...') #6 /htdocs/wp-config.php(116): require_once('/htdocs/wp-sett...') #7 /htdocs/wp-load.php(50): require_once('/htdocs/wp-conf...') #8 /htdocs/wp-blog-header.php(13): require_once('/htdocs/wp-load...') #9 /htdocs/index.php(17): require('/htdocs/wp-blog...') #10 {main} thrown in /htdocs/wp-content/plugins/jetpack/jetpack_vendor/automattic/jetpack-forms/src/class-jetpack-forms.php on line 23