*/ function et_builder_get_built_in_dynamic_content_fields( $post_id = 0 ) { $post_type = get_post_type( $post_id ); $post_type = $post_type ? $post_type : 'post'; $post_type_object = get_post_type_object( $post_type ); $post_type_label = $post_type_object->labels->singular_name; $post_taxonomy_types = et_builder_get_taxonomy_types( get_post_type( $post_id ) ); $default_category = 'post' === $post_type ? 'category' : "${post_type}_category"; if ( ! empty( $post_taxonomy_types ) && ! isset( $post_taxonomy_types[$default_category] ) ) { // Use the 1st available taxonomy as the default value. // Do it in 2 steps in order to support PHP < 5.4 (array dereferencing). $default_category = array_keys( $post_taxonomy_types ); $default_category = $default_category[0]; } $date_format_options = array( 'default' => esc_html__( 'Default', 'et_builder' ), 'M j, Y' => esc_html__( 'Aug 6, 1999 (M j, Y)', 'et_builder' ), 'F d, Y' => esc_html__( 'August 06, 1999 (F d, Y)', 'et_builder' ), 'm/d/Y' => esc_html__( '08/06/1999 (m/d/Y)', 'et_builder' ), 'm.d.Y' => esc_html__( '08.06.1999 (m.d.Y)', 'et_builder' ), 'j M, Y' => esc_html__( '6 Aug, 1999 (j M, Y)', 'et_builder' ), 'l, M d' => esc_html__( 'Tuesday, Aug 06 (l, M d)', 'et_builder' ), 'custom' => esc_html__( 'Custom', 'et_builder' ), ); $fields = array( 'post_title' => array( // Translators: %1$s: Post type name 'label' => esc_html( sprintf( __( '%1$s Title', 'et_builder' ), $post_type_label ) ), 'type' => 'text', ), 'post_excerpt' => array( // Translators: %1$s: Post type name 'label' => esc_html( sprintf( __( '%1$s Excerpt', 'et_builder' ), $post_type_label ) ), 'type' => 'text', 'fields' => array( 'words' => array( 'label' => esc_html__( 'Number of Words', 'et_builder' ), 'type' => 'text', 'default' => '', ), 'read_more_label' => array( 'label' => esc_html__( 'Read More Text', 'et_builder' ), 'type' => 'text', 'default' => '', ), ), ), 'post_date' => array( // Translators: %1$s: Post type name 'label' => esc_html( sprintf( __( '%1$s Publish Date', 'et_builder' ), $post_type_label ) ), 'type' => 'text', 'fields' => array( 'date_format' => array( 'label' => esc_html__( 'Date Format', 'et_builder' ), 'type' => 'select', 'options' => $date_format_options, 'default' => 'default', ), 'custom_date_format' => array( 'label' => esc_html__( 'Custom Date Format', 'et_builder' ), 'type' => 'text', 'default' => '', 'show_if' => array( 'date_format' => 'custom', ), ), ), ), 'post_comment_count' => array( // Translators: %1$s: Post type name 'label' => esc_html( sprintf( __( '%1$s Comment Count', 'et_builder' ), $post_type_label ) ), 'type' => 'text', 'fields' => array( 'link_to_comments_page' => array( 'label' => esc_html__( 'Link to Comments Area', 'et_builder' ), 'type' => 'yes_no_button', 'options' => array( 'on' => esc_html__( 'Yes', 'et_builder' ), 'off' => esc_html__( 'No', 'et_builder' ), ), 'default' => 'on', ), ), ), 'post_categories' => array( // Translators: %1$s: Post type name 'label' => esc_html( sprintf( __( '%1$s Categories', 'et_builder' ), $post_type_label ) ), 'type' => 'text', 'fields' => array( 'link_to_term_page' => array( 'label' => esc_html__( 'Link to Category Index Pages', 'et_builder' ), 'type' => 'yes_no_button', 'options' => array( 'on' => esc_html__( 'Yes', 'et_builder' ), 'off' => esc_html__( 'No', 'et_builder' ), ), 'default' => 'on', ), 'separator' => array( 'label' => esc_html__( 'Categories Separator', 'et_builder' ), 'type' => 'text', 'default' => ' | ', ), 'category_type' => array( 'label' => esc_html__( 'Category Type', 'et_builder' ), 'type' => 'select', 'options' => $post_taxonomy_types, 'default' => $default_category, ), ), ), 'post_tags' => array(), 'post_link' => array( // Translators: %1$s: Post type name 'label' => esc_html( sprintf( __( '%1$s Link', 'et_builder' ), $post_type_label ) ), 'type' => 'text', 'fields' => array( 'text' => array( 'label' => esc_html__( 'Link Text', 'et_builder' ), 'type' => 'select', 'options' => array( // Translators: %1$s: Post type name 'post_title' => esc_html( sprintf( __( '%1$s Title', 'et_builder' ), $post_type_label ) ), 'custom' => esc_html__( 'Custom', 'et_builder' ), ), 'default' => 'post_title', ), 'custom_text' => array( 'label' => esc_html__( 'Custom Link Text', 'et_builder' ), 'type' => 'text', 'default' => '', 'show_if' => array( 'text' => 'custom', ), ), ), ), 'post_author' => array( // Translators: %1$s: Post type name 'label' => esc_html( sprintf( __( '%1$s Author', 'et_builder' ), $post_type_label ) ), 'type' => 'text', 'fields' => array( 'name_format' => array( 'label' => esc_html__( 'Name Format', 'et_builder' ), 'type' => 'select', 'options' => array( 'display_name' => esc_html__( 'Public Display Name', 'et_builder' ), 'first_last_name' => esc_html__( 'First & Last Name', 'et_builder' ), 'last_first_name' => esc_html__( 'Last, First Name', 'et_builder' ), 'first_name' => esc_html__( 'First Name', 'et_builder' ), 'last_name' => esc_html__( 'Last Name', 'et_builder' ), 'nickname' => esc_html__( 'Nickname', 'et_builder' ), 'username' => esc_html__( 'Username', 'et_builder' ), ), 'default' => 'display_name', ), 'link' => array( 'label' => esc_html__( 'Link Name', 'et_builder' ), 'type' => 'yes_no_button', 'options' => array( 'on' => esc_html__( 'Yes', 'et_builder' ), 'off' => esc_html__( 'No', 'et_builder' ), ), 'default' => 'off', ), 'link_destination' => array( 'label' => esc_html__( 'Link Destination', 'et_builder' ), 'type' => 'select', 'options' => array( 'author_archive' => esc_html__( 'Author Archive Page', 'et_builder' ), 'author_website' => esc_html__( 'Author Website', 'et_builder' ), ), 'default' => 'author_archive', 'show_if' => array( 'link' => 'on', ), ), ), ), 'post_author_bio' => array( 'label' => esc_html__( 'Author Bio', 'et_builder' ), 'type' => 'text', ), 'site_title' => array( 'label' => esc_html__( 'Site Title', 'et_builder' ), 'type' => 'text', ), 'site_tagline' => array( 'label' => esc_html__( 'Site Tagline', 'et_builder' ), 'type' => 'text', ), 'current_date' => array( 'label' => esc_html__( 'Current Date', 'et_builder' ), 'type' => 'text', 'fields' => array( 'date_format' => array( 'label' => esc_html__( 'Date Format', 'et_builder' ), 'type' => 'select', 'options' => $date_format_options, 'default' => 'default', ), 'custom_date_format' => array( 'label' => esc_html__( 'Custom Date Format', 'et_builder' ), 'type' => 'text', 'default' => '', 'show_if' => array( 'date_format' => 'custom', ), ), ), ), 'post_link_url' => array( // Translators: %1$s: Post type name 'label' => esc_html( sprintf( __( '%1$s Link', 'et_builder' ), $post_type_label ) ), 'type' => 'url', ), 'home_url' => array( 'label' => esc_html__( 'Homepage Link', 'et_builder' ), 'type' => 'url', ), 'post_featured_image' => array( 'label' => esc_html__( 'Featured Image', 'et_builder' ), 'type' => 'image', ), 'post_author_profile_picture' => array( // Translators: %1$s: Post type name 'label' => esc_html( sprintf( __( '%1$s Author Profile Picture', 'et_builder' ), $post_type_label ) ), 'type' => 'image', ), 'site_logo' => array( 'label' => esc_html__( 'Site Logo', 'et_builder' ), 'type' => 'image', ), ); if ( isset( $post_taxonomy_types["${post_type}_tag"] ) ) { $fields['post_tags'] = array( // Translators: %1$s: Post type name 'label' => esc_html( sprintf( __( '%1$s Tags', 'et_builder' ), $post_type_label ) ), 'type' => 'text', 'fields' => array( 'link_to_term_page' => array( 'label' => esc_html__( 'Link to Tag Index Pages', 'et_builder' ), 'type' => 'yes_no_button', 'options' => array( 'on' => esc_html__( 'Yes', 'et_builder' ), 'off' => esc_html__( 'No', 'et_builder' ), ), 'default' => 'on', ), 'separator' => array( 'label' => esc_html__( 'Tags Separator', 'et_builder' ), 'type' => 'text', 'default' => ' | ', ), 'category_type' => array( 'label' => esc_html__( 'Category Type', 'et_builder' ), 'type' => 'select', 'options' => $post_taxonomy_types, 'default' => "${post_type}_tag", ), ), ); } else { unset( $fields['post_tags'] ); } // Fill in boilerplate. foreach ( $fields as $key => $field ) { $fields[ $key ]['custom'] = false; if ( 'text' === $field['type'] ) { $settings = isset( $field['fields'] ) ? $field['fields'] : array(); $settings = array_merge( array( 'before' => array( 'label' => esc_html__( 'Before', 'et_builder' ), 'type' => 'text', 'default' => '', ), 'after' => array( 'label' => esc_html__( 'After', 'et_builder' ), 'type' => 'text', 'default' => '', ), ), $settings ); $fields[ $key ]['fields'] = $settings; } } return $fields; } /** * Get all public taxonomies associated with a given post type. * * @since 3.17.2 * * @param string $post_type * * @return array */ function et_builder_get_taxonomy_types( $post_type ) { $taxonomies = get_object_taxonomies( $post_type, 'object' ); $list = array(); if ( empty( $taxonomies ) ) { return $list; } foreach ( $taxonomies as $taxonomy ) { if ( ! empty( $taxonomy ) && $taxonomy->public && $taxonomy->show_ui ) { $list[ $taxonomy->name ] = $taxonomy->label; } } return $list; } /** * Get custom dynamic content fields. * * @since 3.17.2 * * @param integer $post_id * * @return array */ function et_builder_get_custom_dynamic_content_fields( $post_id ) { $raw_custom_fields = get_post_meta( $post_id ); $custom_fields = array(); /** * Filter post meta accepted as custom field options in dynamic content. * Post meta prefixed with `_` is considered hidden from dynamic content options by default * due to its nature as "hidden meta keys". This filter allows third parties to * circumvent this limitation. * * @since 3.17.2 * * @param array $meta_keys * @param integer $post_id * * @return array */ $display_hidden_meta_keys = apply_filters( 'et_builder_dynamic_content_display_hidden_meta_keys', array(), $post_id ); foreach ( $raw_custom_fields as $key => $values ) { if ( substr( $key, 0, 1 ) === '_' && ! in_array( $key, $display_hidden_meta_keys ) ) { // Ignore hidden meta keys. continue; } if ( substr( $key, 0, 3 ) === 'et_' ) { // Ignore ET meta keys as they are not suitable for dynamic content use. continue; } $label = str_replace( array( '_', '-' ), ' ', $key ); $label = ucwords( $label ); $label = trim( $label ); /** * Filter the display label for a custom field. * * @since 3.17.2 * * @param string $label * @param string $meta_key */ $label = apply_filters( 'et_builder_dynamic_content_custom_field_label', $label, $key ); $field = array( 'label' => $label, 'type' => 'any', 'fields' => array( 'before' => array( 'label' => esc_html__( 'Before', 'et_builder' ), 'type' => 'text', 'default' => '', 'show_on' => 'text', ), 'after' => array( 'label' => esc_html__( 'After', 'et_builder' ), 'type' => 'text', 'default' => '', 'show_on' => 'text', ), ), 'meta_key' => $key, 'custom' => true, ); if ( current_user_can( 'unfiltered_html' ) ) { $field['fields']['enable_html'] = array( 'label' => esc_html__( 'Enable raw HTML', 'et_builder' ), 'type' => 'yes_no_button', 'options' => array( 'on' => esc_html__( 'Yes', 'et_builder' ), 'off' => esc_html__( 'No', 'et_builder' ), ), 'default' => 'off', 'show_on' => 'text', ); } $custom_fields[ "custom_meta_{$key}" ] = $field; } /** * Filter available custom field options for dynamic content. * * @since 3.17.2 * * @param array $custom_fields * @param integer $post_id * @param array $raw_custom_fields * * @return array */ $custom_fields = apply_filters( 'et_builder_custom_dynamic_content_fields', $custom_fields, $post_id, $raw_custom_fields ); return $custom_fields; } /** * Get all dynamic content fields. * * @since 3.17.2 * * @param integer $post_id * @param string $context * * @return array */ function et_builder_get_dynamic_content_fields( $post_id, $context ) { $fields = et_builder_get_built_in_dynamic_content_fields( $post_id ); $custom_fields = array(); if ( 'display' === $context || et_pb_is_allowed( 'read_dynamic_content_custom_fields' ) ) { $custom_fields = et_builder_get_custom_dynamic_content_fields( $post_id ); } return array_merge( $fields, $custom_fields ); } /** * Get default value for a dynamic content field's setting. * * @since 3.17.2 * * @param integer $post_id * @param string $field * @param string $setting * * @return string */ function et_builder_get_dynamic_attribute_field_default( $post_id, $field, $setting ) { $_ = ET_Core_Data_Utils::instance(); $fields = et_builder_get_dynamic_content_fields( $post_id, 'edit' ); return $_->array_get( $fields, "$field.fields.$setting.default", '' ); } /** * Resolve dynamic content to a simple value. * * @since 3.17.2 * * @param string $name * @param array $settings * @param integer $post_id * @param string $context * @param array $overrides * * @return string */ function et_builder_resolve_dynamic_content( $name, $settings, $post_id, $context, $overrides = array(), $is_content = false ) { /** * Generic filter for content resolution based on a given field and post. * * @since 3.17.2 * * @param string $content * @param string $name * @param array $settings * @param integer $post_id * @param string $context * @param array $overrides * * @return string */ $content = apply_filters( 'et_builder_resolve_dynamic_content', '', $name, $settings, $post_id, $context, $overrides ); /** * Field-specific filter for content resolution based on a given field and post. * * @since 3.17.2 * * @param string $content * @param array $settings * @param integer $post_id * @param string $context * @param array $overrides * * @return string */ $content = apply_filters( "et_builder_resolve_dynamic_content_{$name}", $content, $settings, $post_id, $context, $overrides ); return $is_content ? do_shortcode( $content ) : $content; } /** * Wrap a dynamic content value with its before/after settings values. * * @since 3.17.2 * * @param integer $post_id * @param string $name * @param string $value * @param array $settings * * @return string */ function et_builder_wrap_dynamic_content( $post_id, $name, $value, $settings ) { $_ = ET_Core_Data_Utils::instance(); $def = 'et_builder_get_dynamic_attribute_field_default'; $before = $_->array_get( $settings, 'before', $def( $post_id, $name, 'before' ) ); $after = $_->array_get( $settings, 'after', $def( $post_id, $name, 'after' ) ); $user_id = get_post_field( 'post_author', $post_id ); if ( ! user_can( $user_id, 'unfiltered_html' ) ) { $before = esc_html( $before ); $after = esc_html( $after ); } return $before . $value . $after; } /** * Resolve built-in dynamic content fields. * * @since 3.17.2 * * @param string $content * @param string $name * @param array $settings * @param string $context * @param integer $post_id * * @return string */ function et_builder_filter_resolve_default_dynamic_content( $content, $name, $settings, $post_id, $context, $overrides ) { global $shortname; $_ = ET_Core_Data_Utils::instance(); $def = 'et_builder_get_dynamic_attribute_field_default'; $post = get_post( $post_id ); $author = get_userdata( $post->post_author ); $wrapped = false; switch ( $name ) { case 'post_title': $content = isset( $overrides[ $name ] ) ? $overrides[ $name ] : get_the_title( $post_id ); $content = esc_html( $content ); break; case 'post_excerpt': $words = (int) $_->array_get( $settings, 'words', $def( $post_id, $name, 'words' ) ); $read_more = $_->array_get( $settings, 'read_more_label', $def( $post_id, $name, 'read_more_label' ) ); $content = isset( $overrides[ $name ] ) ? $overrides[ $name ] : get_the_excerpt( $post_id ); if ( $words > 0 ) { $content = wp_trim_words( $content, $words ); } if ( ! empty( $read_more ) ) { $content .= sprintf( ' %2$s', esc_url( get_permalink( $post_id ) ), esc_html( $read_more ) ); } break; case 'post_date': $format = $_->array_get( $settings, 'date_format', $def( $post_id, $name, 'date_format' ) ); $custom_format = $_->array_get( $settings, 'custom_date_format', $def( $post_id, $name, 'custom_date_format' ) ); if ( 'default' === $format ) { $format = ''; } if ( 'custom' === $format ) { $format = $custom_format; } $content = esc_html( get_the_date( $format, $post_id ) ); break; case 'post_comment_count': $link = $_->array_get( $settings, 'link_to_comments_page', $def( $post_id, $name, 'link_to_comments_page' ) ); $link = 'on' === $link; $content = esc_html( get_comments_number( $post_id ) ); if ( $link ) { $content = sprintf( '%2$s', esc_url( get_comments_link( $post_id ) ), et_core_esc_previously( et_builder_wrap_dynamic_content( $post_id, $name, $content, $settings ) ) ); $wrapped = true; } break; case 'post_categories': // Intentional fallthrough. case 'post_tags': $post_taxonomies = et_builder_get_taxonomy_types( get_post_type( $post_id ) ); $overrides_map = array( 'category' => 'post_categories', 'post_tag' => 'post_tags' ); $link = $_->array_get( $settings, 'link_to_term_page', $def( $post_id, $name, 'link_to_category_page' ) ); $link = 'on' === $link; $separator = $_->array_get( $settings, 'separator', $def( $post_id, $name, 'separator' ) ); $separator = ! empty( $separator ) ? $separator : $def( $post_id, $name, 'separator' ); $taxonomy = $_->array_get( $settings, 'category_type', '' ); $taxonomy = isset( $post_taxonomies[ $taxonomy ] ) ? $taxonomy : $def( $post_id, $name, 'category_type' ); $ids_key = isset( $overrides_map[ $taxonomy ] ) ? $overrides_map[ $taxonomy ] : ''; $ids = isset( $overrides[ $ids_key ] ) ? array_filter( array_map( 'intval', explode( ',', $overrides[ $ids_key ] ) ) ) : array(); $terms = ! empty( $ids ) ? get_terms( array( 'taxonomy' => $taxonomy, 'include' => $ids ) ) : get_the_terms( $post_id, $taxonomy ); if ( is_array( $terms ) ) { $content = et_builder_list_terms( $terms, $link, $separator ); } else { $content = ''; } break; case 'post_link': $text = $_->array_get( $settings, 'text', $def( $post_id, $name, 'text' ) ); $custom_text = $_->array_get( $settings, 'custom_text', $def( $post_id, $name, 'custom_text' ) ); $label = 'custom' === $text ? $custom_text : get_the_title( $post_id ); $content = sprintf( '%2$s', esc_url( get_permalink( $post_id ) ), esc_html( $label ) ); break; case 'post_author': $name_format = $_->array_get( $settings, 'name_format', $def( $post_id, $name, 'name_format' ) ); $link = $_->array_get( $settings, 'link', $def( $post_id, $name, 'link' ) ); $link = 'on' === $link; $link_destination = $_->array_get( $settings, 'link_destination', $def( $post_id, $name, 'link_destination' ) ); $link_target = 'author_archive' === $link_destination ? '_self' : '_blank'; $label = ''; $url = ''; if ( false === $author ) { $content = ''; break; } switch( $name_format ) { case 'display_name': $label = $author->display_name; break; case 'first_last_name': $label = $author->first_name . ' ' . $author->last_name; break; case 'last_first_name': $label = $author->last_name . ', ' . $author->first_name; break; case 'first_name': $label = $author->first_name; break; case 'last_name': $label = $author->last_name; break; case 'nickname': $label = $author->nickname; break; case 'username': $label = $author->user_login; break; } switch ( $link_destination ) { case 'author_archive': $url = get_author_posts_url( $author->ID ); break; case 'author_website': $url = $author->user_url; break; } $content = esc_html( $label ); if ( $link && ! empty( $url ) ) { $content = sprintf( '%3$s', esc_url( $url ), esc_attr( $link_target ), et_core_esc_previously( $content ) ); } break; case 'post_author_bio': if ( false === $author ) { $content = ''; break; } $content = esc_html( $author->description ); break; case 'site_title': $content = esc_html( get_bloginfo( 'name' ) ); break; case 'site_tagline': $content = esc_html( get_bloginfo( 'description' ) ); break; case 'current_date': $format = $_->array_get( $settings, 'date_format', $def( $post_id, $name, 'date_format' ) ); $custom_format = $_->array_get( $settings, 'custom_date_format', $def( $post_id, $name, 'custom_date_format' ) ); if ( 'default' === $format ) { $format = get_option( 'date_format' ); } if ( 'custom' === $format ) { $format = $custom_format; } $content = esc_html( date( $format ) ); break; case 'post_link_url': $content = esc_url( get_permalink( $post_id ) ); break; case 'home_url': $content = esc_url( home_url( '/' ) ); break; case 'post_featured_image': if ( isset( $overrides[ $name ] ) ) { $id = (int) $overrides[ $name ]; $content = wp_get_attachment_image_url( $id, 'full' ); break; } $url = get_the_post_thumbnail_url( $post_id, 'full' ); $content = $url ? esc_url( $url ) : ''; break; case 'post_author_profile_picture': $content = get_avatar_url( $author->ID ); break; case 'site_logo': $logo = et_get_option( $shortname . '_logo' ); $content = ''; if ( ! empty( $logo ) ) { $content = esc_url( $logo ); } break; } if ( ! $wrapped ) { $content = et_builder_wrap_dynamic_content( $post_id, $name, $content, $settings ); $wrapped = true; } return $content; } add_filter( 'et_builder_resolve_dynamic_content', 'et_builder_filter_resolve_default_dynamic_content', 10, 6 ); /** * Resolve custom field dynamic content fields. * * @since 3.17.2 * * @param string $content * @param string $name * @param array $settings * @param string $context * @param integer $post_id * * @return string */ function et_builder_filter_resolve_custom_field_dynamic_content( $content, $name, $settings, $post_id, $context, $overrides ) { $fields = et_builder_get_dynamic_content_fields( $post_id, $context ); if ( empty( $fields[ $name ]['meta_key'] ) ) { return $content; } if ( 'edit' === $context && ! et_pb_is_allowed( 'read_dynamic_content_custom_fields' ) ) { if ( 'text' === $fields[ $name ]['type'] ) { return esc_html__( 'You don\'t have sufficient permissions to access this content.', 'et_builder' ); } return ''; } $_ = ET_Core_Data_Utils::instance(); $def = 'et_builder_get_dynamic_attribute_field_default'; $enable_html = $_->array_get( $settings, 'enable_html', $def( $post_id, $name, 'enable_html' ) ); $content = get_post_meta( $post_id, $fields[ $name ]['meta_key'], true ); /** * Provide a hook for third party compatibility purposes of formatting meta values. * * @since 3.17.2 * * @param string $meta_value * @param string $meta_key * @param integer $post_id */ $content = apply_filters( 'et_builder_dynamic_content_meta_value', $content, $fields[ $name ]['meta_key'], $post_id ); // Sanitize HTML contents. $content = wp_kses_post( $content ); if ( 'on' !== $enable_html ) { $content = esc_html( $content ); } $content = et_builder_wrap_dynamic_content( $post_id, $name, $content, $settings ); return $content; } add_filter( 'et_builder_resolve_dynamic_content', 'et_builder_filter_resolve_custom_field_dynamic_content', 10, 6 ); /** * Resolve a dynamic group post content field for use during editing. * * @since 3.17.2 * * @param string $field * @param array $settings * @param integer $post_id * @param array $overrides * * @return string */ function et_builder_filter_resolve_dynamic_post_content_field( $field, $settings, $post_id, $overrides = array(), $is_content = false ) { return et_builder_resolve_dynamic_content( $field, $settings, $post_id, 'edit', $overrides, $is_content ); } add_action( 'et_builder_resolve_dynamic_post_content_field', 'et_builder_filter_resolve_dynamic_post_content_field', 10, 5 ); /** * Convert a value to an ET_Builder_Value representation. * * @since 3.17.2 * * @param string $content * * @return ET_Builder_Value */ function et_builder_parse_dynamic_content( $content ) { // Replace encoded quotes. $json = str_replace( array( '“', '”', '″', "%22" ), '"', $content ); // Strip

artifacts from wpautop in before/after settings. Example: // {"dynamic":true,"content":"post_title","settings":{"before":"

//

","after":"

//

"}} // This is a rough solution implemented due to time constraints. $json = preg_replace( '~ ("(?:before|after)":") # $1 = Anchor to the before/after settings. (?: # Match cases where the value starts with the offending tag. <\/?p> # The root of all evil. [\r\n]+ # Whitespace follows the tag. )* (?: # Match cases where the value ends with the offending tag. ([^"]*) # $2 = The preceeding value. [\r\n]+ # Whitespace preceedes the tag. <\/?p> # The root of all evil. )* ~xi', '$1$2', $json ); // Remove line-breaks which break the json strings. $json = preg_replace( '/\r|\n/', '', $json ); // Strip wrapping

tag as it appears in shortcode content in certain cases (e.g. BB preview). $json = preg_replace( '/^

(.*)<\/p>$/i', '$1', trim( $json ) ); // Parse and validate dynamic content schema. $dynamic_content = json_decode( $json, true ); $is_dynamic_content = is_array( $dynamic_content ) && isset( $dynamic_content['dynamic'] ) && (bool) $dynamic_content['dynamic']; $has_content = is_array( $dynamic_content ) && isset( $dynamic_content['content'] ) && is_string( $dynamic_content['content'] ); $has_settings = is_array( $dynamic_content ) && isset( $dynamic_content['settings'] ) && is_array( $dynamic_content['settings'] ); if ( ! $is_dynamic_content || ! $has_content || ! $has_settings ) { return new ET_Builder_Value( false, wp_kses_post( $content ), array() ); } return new ET_Builder_Value( (bool) $dynamic_content['dynamic'], sanitize_text_field( $dynamic_content['content'] ), array_map( 'wp_kses_post', $dynamic_content['settings'] ) ); } /** * Callback to resolve dynamic content for preg_replace_callback. * * @since 3.17.2 * * @param array $matches * * @return string */ function et_builder_resolve_dynamic_content_in_excerpt_callback( $matches ) { global $_et_brdcie_post_id; return et_builder_parse_dynamic_content( $matches[0] )->resolve( $_et_brdcie_post_id ); } /** * Resolve dynamic content in post excerpts instead of showing raw JSON. * * @since 3.17.2 * * @param string $post_excerpt * @param integer $post_id * * @return string */ function et_builder_resolve_dynamic_content_in_excerpt( $post_excerpt, $post_id ) { // Use an obscure acronym named global variable instead of an anonymous function as we are // targeting PHP 5.2. global $_et_brdcie_post_id; $json = '/ \{ # { character (?: # non-capturing group [^{}] # anything that is not a { or } | # OR (?R) # recurse the entire pattern )* # previous group zero or more times \} # } character /x'; $_et_brdcie_post_id = $post_id; $post_excerpt = preg_replace_callback( $json, 'et_builder_resolve_dynamic_content_in_excerpt_callback', $post_excerpt ); $_et_brdcie_post_id = 0; return $post_excerpt; } add_filter( 'et_truncate_post', 'et_builder_resolve_dynamic_content_in_excerpt', 10, 2 );