%s
(.*)<\/p>$/i', '$1', trim( $value ) ); return $value; } /** * Parse a JSON-encoded string into an ET_Builder_Value instance or null on failure. * * @since 3.20.2 * * @param string $json JSON-encoded string. * * @return ET_Builder_Value|null */ function et_builder_parse_dynamic_content_json( $json ) { // phpcs:disable WordPress.Security.NonceVerification -- This function does not change any stats, hence CSRF ok. $post_types = array_keys( et_builder_get_public_post_types() ); $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'] ); $has_category_type = is_array( $dynamic_content ) && isset( $dynamic_content['settings'] ) && isset( $dynamic_content['settings']['category_type'] ); // When adding a section from library get_post_type() will not work, and post type has to be fetched from $_POST. $is_added_from_library = isset( $_POST['et_post_type'] ); if ( ! $is_dynamic_content || ! $has_content || ! $has_settings ) { return null; } // Replaces layout_category with proper category_type depending on the post type on which the layout is added. if ( $has_category_type && 'post_categories' === $dynamic_content['content'] && ! 0 === substr_compare( $dynamic_content['settings']['category_type'], '_tag', - 4 ) ) { if ( $is_added_from_library ) { $correct_post_type = sanitize_text_field( $_POST['et_post_type'] ); $correct_post_type = in_array( $correct_post_type, $post_types, true ) ? $correct_post_type : 'post'; } else { $correct_post_type = get_post_type(); $correct_post_type = in_array( $correct_post_type, $post_types, true ) ? $correct_post_type : 'post'; } if ( 'post' === $correct_post_type ) { $dynamic_content['settings']['category_type'] = 'category'; } else { $dynamic_content['settings']['category_type'] = $correct_post_type . '_category'; } } return new ET_Builder_Value( (bool) $dynamic_content['dynamic'], sanitize_text_field( $dynamic_content['content'] ), array_map( 'wp_kses_post', $dynamic_content['settings'] ) ); // phpcs:enable } /** * Convert a value to an ET_Builder_Value representation. * * @since 3.17.2 * * @param string $content Value content. * * @return ET_Builder_Value */ function et_builder_parse_dynamic_content( $content ) { $json = et_builder_clean_dynamic_content( $content ); $json = preg_replace( '/^@ET-DC@(.*?)@$/', '$1', $json ); $dynamic_content = et_builder_parse_dynamic_content_json( $json ); if ( null === $dynamic_content ) { $json = base64_decode( $json ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- `base64_decode` is used to unserialize dynamic content. $dynamic_content = et_builder_parse_dynamic_content_json( $json ); } if ( null === $dynamic_content ) { return new ET_Builder_Value( false, wp_kses_post( $content ), array() ); } return $dynamic_content; } /** * Serialize dynamic content. * * @since 3.20.2 * * @param bool $dynamic Whether the value is static or dynamic. * @param string $content Value content. Represents the dynamic content type when dynamic. * @param mixed[] $settings Array of dynamic content settings. * * @return string */ function et_builder_serialize_dynamic_content( $dynamic, $content, $settings ) { // JSON_UNESCAPED_SLASHES is only supported from 5.4. $options = defined( 'JSON_UNESCAPED_SLASHES' ) ? JSON_UNESCAPED_SLASHES : 0; $result = wp_json_encode( array( 'dynamic' => $dynamic, 'content' => $content, // Force object type for keyed arrays as empty arrays will be encoded to // javascript arrays instead of empty objects. 'settings' => (object) $settings, ), $options ); // Use fallback if needed. $result = 0 === $options ? str_replace( '\/', '/', $result ) : $result; return '@ET-DC@' . base64_encode( $result ) . '@'; // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- `base64_encode` is used to serialize dynamic content. } /** * Strip dynamic content. * * @since 4.0.9 * * @param string $content Post Content. * * @return string */ function et_builder_strip_dynamic_content( $content ) { return preg_replace( '/@ET-DC@(.*?)@/', '', $content ); } /** * Reencode legacy dynamic content in post excerpts. * * @since 3.20.2 * * @param string $post_excerpt Post Excerpt. * @param integer $post_id Post Id. * * @return string */ function et_builder_reencode_legacy_dynamic_content_in_excerpt( $post_excerpt, $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'; return preg_replace_callback( $json, 'et_builder_reencode_legacy_dynamic_content_in_excerpt_callback', $post_excerpt ); } add_filter( 'et_truncate_post', 'et_builder_reencode_legacy_dynamic_content_in_excerpt', 10, 2 ); /** * Callback to reencode legacy dynamic content for preg_replace_callback. * * @since 3.20.2 * * @param array $matches PCRE match. * * @return string */ function et_builder_reencode_legacy_dynamic_content_in_excerpt_callback( $matches ) { $value = et_builder_parse_dynamic_content_json( $matches[0] ); return null === $value ? $matches[0] : $value->serialize(); } /** * Resolve dynamic content in post excerpts instead of showing raw JSON. * * @since 3.17.2 * * @param string $post_excerpt Post excerpt. * @param integer $post_id 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; $_et_brdcie_post_id = $post_id; $post_excerpt = preg_replace_callback( '/@ET-DC@.*?@/', '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 ); /** * Callback to resolve dynamic content for preg_replace_callback. * * @since 3.17.2 * * @param array $matches PCRE match. * * @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 ); }