Upgarded to 4.17.4

This commit is contained in:
2022-06-23 13:17:18 +01:00
parent 80f1e87db9
commit a04fb0c7af
404 changed files with 54683 additions and 4417 deletions

View File

@ -963,7 +963,11 @@ class ET_Core_PageResource {
(array) glob( "{$cache_dir}/archive/et-{$_owner}-dynamic*" ),
(array) glob( "{$cache_dir}/search/et-{$_owner}-dynamic*" ),
(array) glob( "{$cache_dir}/notfound/et-{$_owner}-dynamic*" ),
(array) glob( "{$cache_dir}/home/et-{$_owner}-dynamic*" )
(array) glob( "{$cache_dir}/home/et-{$_owner}-dynamic*" ),
// WP Templates and Template Parts.
(array) glob( "{$cache_dir}/*/et-{$_owner}-{$_slug}-*wpe-{$_post_id}*" ),
(array) glob( "{$cache_dir}/*/*/et-{$_owner}-{$_slug}-*wpe-{$_post_id}*" ),
(array) glob( "{$cache_dir}/*/*/*/et-{$_owner}-{$_slug}-*wpe-{$_post_id}*" )
);
self::_remove_files_in_directory( $files, $cache_dir );

View File

@ -82,6 +82,8 @@ class ET_Core_Portability {
$temp_file_id = sanitize_file_name( $timestamp );
$temp_file = $this->has_temp_file( $temp_file_id, 'et_core_import' );
$include_global_presets = isset( $_POST['include_global_presets'] ) ? wp_validate_boolean( $_POST['include_global_presets'] ) : false;
$return_json = isset( $_POST['et_cloud_return_json'] ) ? wp_validate_boolean( sanitize_text_field( $_POST['et_cloud_return_json'] ) ) : false; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification is handled earlier.
$temp_presets = isset( $_POST['et_cloud_use_temp_presets'] ) ? wp_validate_boolean( sanitize_text_field( $_POST['et_cloud_use_temp_presets'] ) ) : false; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification is handled earlier.
$global_presets = '';
if ( $temp_file ) {
@ -115,6 +117,10 @@ class ET_Core_Portability {
$import = json_decode( $filesystem->get_contents( $temp_file ), true );
$import = $this->validate( $import );
if ( $return_json ) {
return array( 'jsonFromFile' => $import );
}
// Check if Import contains Google Api Settings.
if ( isset( $import['data']['et_google_api_settings'] ) && 'epanel' === $this->instance->context ) {
$et_google_api_settings = $import['data']['et_google_api_settings'];
@ -123,7 +129,7 @@ class ET_Core_Portability {
$import['data'] = $this->apply_query( $import['data'], 'set' );
if ( ! isset( $import['context'] ) || ( isset( $import['context'] ) && $import['context'] !== $this->instance->context ) ) {
$this->delete_temp_files( 'et_core_import' );
$this->delete_temp_files( 'et_core_import', [ $temp_file_id => $temp_file ] );
return array( 'message' => 'importContextFail' );
}
@ -138,13 +144,13 @@ class ET_Core_Portability {
}
if ( ! empty( $import['global_colors'] ) ) {
$import['data'] = $this->_maybe_inject_gcid( $import['data'] );
$import['data'] = $this->_maybe_inject_gcid( $import['data'], $import['global_colors'] );
}
$data = $import['data'];
$success = array( 'timestamp' => $timestamp );
$this->delete_temp_files( 'et_core_import' );
$this->delete_temp_files( 'et_core_import', [ $temp_file_id => $temp_file ] );
if ( 'options' === $this->instance->type ) {
// Reset all data besides excluded data.
@ -178,7 +184,23 @@ class ET_Core_Portability {
// Pass the post content and let js save the post.
if ( 'post' === $this->instance->type ) {
$success['postContent'] = reset( $data );
do_shortcode( $success['postContent'] );
// In some cases we receive the post array instaed of shortcode string. Handle this case.
$shortcode_string = is_array( $success['postContent'] ) && ! empty( $success['postContent']['post_content'] ) ? $success['postContent']['post_content'] : $success['postContent'];
if ( ! empty( $import['presets'] ) ) {
$preset_rewrite_map = $this->prepare_to_import_layout_presets( $import['presets'] );
$global_presets = $import['presets'];
$shortcode_object = et_fb_process_shortcode( $shortcode_string );
$this->rewrite_module_preset_ids( $shortcode_object, $import['presets'], $preset_rewrite_map );
$shortcode_string = et_fb_process_to_shortcode( $shortcode_object, array(), '', false );
}
do_shortcode( $shortcode_string );
$success['postContent'] = $shortcode_string;
$success['migrations'] = ET_Builder_Module_Settings_Migration::$migrated;
$success['presets'] = isset( $import['presets'] ) && is_array( $import['presets'] ) ? $import['presets'] : (object) array();
}
@ -232,7 +254,9 @@ class ET_Core_Portability {
}
}
if ( ! $this->import_posts( $data ) ) {
$imported_posts = $this->import_posts( $data );
if ( false === $imported_posts ) {
/**
* Filters the error message when {@see ET_Core_Portability::import()} fails.
*
@ -245,11 +269,13 @@ class ET_Core_Portability {
}
return $error_message;
} else {
$success['imported_posts'] = $imported_posts;
}
}
if ( ! empty( $global_presets ) ) {
if ( ! $this->import_global_presets( $global_presets ) ) {
if ( ! $this->import_global_presets( $global_presets, $temp_presets ) ) {
if ( $error_message = apply_filters( 'et_core_portability_import_error_message', false ) ) {
$error_message = array( 'message' => $error_message );
}
@ -275,7 +301,7 @@ class ET_Core_Portability {
*
* @return null|array
*/
public function export( $return = false ) {
public function export( $return = false, $include_used_presets = false ) {
$this->prevent_failure();
et_core_nonce_verified_previously();
@ -335,6 +361,28 @@ class ET_Core_Portability {
$post_global_colors = $this->_filter_post_data( $_POST['global_colors'] );
$global_colors = json_decode( stripslashes( $post_global_colors ) );
}
if ( $include_used_presets ) {
$used_global_presets = array();
$used_global_colors = array();
$shortcode_object = et_fb_process_shortcode( $post_data['post_content'] );
$used_global_presets = array_merge(
$this->get_used_global_presets( $shortcode_object, $used_global_presets ),
$used_global_presets
);
if ( ! empty( $used_global_presets ) ) {
$global_presets = (object) $used_global_presets;
}
$used_global_colors = $this->_get_used_global_colors( $shortcode_object, $used_global_colors, $global_presets );
if ( ! empty( $used_global_colors ) ) {
$global_colors = $this->_get_global_colors_data( $used_global_colors );
}
}
}
if ( 'post_type' === $this->instance->type ) {
@ -365,10 +413,6 @@ class ET_Core_Portability {
foreach ( $data as $post ) {
$shortcode_object = et_fb_process_shortcode( $post->post_content );
if ( 'post_type' === $this->instance->type ) {
$used_global_colors = $this->_get_used_global_colors( $shortcode_object, $used_global_colors );
}
if ( $apply_global_presets ) {
$post->post_content = et_fb_process_to_shortcode( $shortcode_object, $options, '', false );
} else {
@ -383,6 +427,10 @@ class ET_Core_Portability {
$global_presets = (object) $used_global_presets;
}
if ( 'post_type' === $this->instance->type ) {
$used_global_colors = $this->_get_used_global_colors( $shortcode_object, $used_global_colors, $global_presets );
}
if ( ! empty( $used_global_colors ) ) {
$global_colors = $this->_get_global_colors_data( $used_global_colors );
}
@ -1053,7 +1101,7 @@ class ET_Core_Portability {
*
* @return boolean
*/
public function import_global_presets( $presets ) {
public function import_global_presets( $presets, $is_temp_presets = false ) {
if ( ! is_array( $presets ) ) {
return false;
}
@ -1061,6 +1109,7 @@ class ET_Core_Portability {
$all_modules = ET_Builder_Element::get_modules();
$module_presets_manager = ET_Builder_Global_Presets_Settings::instance();
$global_presets = $module_presets_manager->get_global_presets();
$temp_presets = $module_presets_manager->get_temp_presets();
$presets_to_import = array();
foreach ( $presets as $module_type => $module_presets ) {
@ -1077,8 +1126,11 @@ class ET_Core_Portability {
$local_presets = $global_presets->$module_type->presets;
$local_preset_names = array();
foreach ( $local_presets as $preset ) {
array_push( $local_preset_names, $preset->name );
foreach ( $local_presets as $preset_id => $preset ) {
// Skip temp presets.
if ( ! isset( $temp_preset[ $module_type ]['presets'][ $preset_id ] ) ) {
array_push( $local_preset_names, $preset->name );
}
}
foreach ( $module_presets['presets'] as $preset_id => $preset ) {
@ -1097,6 +1149,9 @@ class ET_Core_Portability {
}
}
if ( $is_temp_presets ) {
et_update_option( ET_Builder_Global_Presets_Settings::GLOBAL_PRESETS_OPTION_TEMP, $presets_to_import );
}
// Merge existing Global Presets with imported ones
foreach ( $presets_to_import as $module_type => $module_presets ) {
@ -1123,8 +1178,10 @@ class ET_Core_Portability {
et_update_option( ET_Builder_Global_Presets_Settings::GLOBAL_PRESETS_OPTION, $global_presets );
$global_presets_history = ET_Builder_Global_Presets_History::instance();
$global_presets_history->add_global_history_record( $global_presets );
if ( ! $is_temp_presets ) {
$global_presets_history = ET_Builder_Global_Presets_History::instance();
$global_presets_history->add_global_history_record( $global_presets );
}
return true;
}
@ -1175,6 +1232,8 @@ class ET_Core_Portability {
*/
$posts = apply_filters( 'et_core_portability_import_posts', $posts );
$imported_posts = array();
if ( empty( $posts ) ) {
return false;
}
@ -1205,6 +1264,8 @@ class ET_Core_Portability {
) );
}
$imported_posts[] = intval( $layout_exists );
continue;
}
@ -1220,6 +1281,8 @@ class ET_Core_Portability {
continue;
}
$imported_posts[] = $post_id;
// Insert and set terms.
if ( isset( $post['terms'] ) && is_array( $post['terms'] ) ) {
$processed_terms = array();
@ -1292,7 +1355,7 @@ class ET_Core_Portability {
}
}
return true;
return $imported_posts;
}
/**
@ -1399,15 +1462,15 @@ class ET_Core_Portability {
*
* @param array $data - The multidimensional array representing a import object structure.
*/
protected function _maybe_inject_gcid( &$data ) {
protected function _maybe_inject_gcid( &$data, &$gcolors = null ) {
foreach ( $data as $post_id => &$post_data ) {
if ( is_array( $post_data ) ) {
$shortcode_object = et_fb_process_shortcode( $post_data['post_content'] );
$this->_inject_gcid( $shortcode_object );
$this->_inject_gcid( $shortcode_object, $gcolors );
$data[ $post_id ]['post_content'] = et_fb_process_to_shortcode( $shortcode_object, array(), '', false );
} else {
$shortcode_object = et_fb_process_shortcode( $post_data );
$this->_inject_gcid( $shortcode_object );
$this->_inject_gcid( $shortcode_object, $gcolors );
$data[ $post_id ] = et_fb_process_to_shortcode( $shortcode_object, array(), '', false );
}
}
@ -1424,18 +1487,27 @@ class ET_Core_Portability {
*
* @param array $shortcode_object - The multidimensional array representing a page/module structure.
*/
protected function _inject_gcid( &$shortcode_object ) {
protected function _inject_gcid( &$shortcode_object, &$global_colors ) {
foreach ( $shortcode_object as &$module ) {
// No global colors set for this module.
if ( ! empty( $module['attrs']['global_colors_info'] ) ) {
if ( ! empty( $module['attrs']['global_colors_info'] ) && ! empty( $global_colors ) ) {
$colors_array = json_decode( $module['attrs']['global_colors_info'], true );
if ( ! empty( $colors_array ) ) {
foreach ( $colors_array as $color_id => $attrs_array ) {
if ( ! empty( $attrs_array ) ) {
// Get settings for this global color.
$color = '';
foreach ( $global_colors as $gcid ) {
if ( $color_id === $gcid[0] && 'yes' === $gcid[1]['active'] ) {
$color = $gcid[1]['color'];
}
}
foreach ( $attrs_array as $attr_name ) {
if ( isset( $module['attrs'][ $attr_name ] ) && '' !== $module['attrs'][ $attr_name ] ) {
$module['attrs'][ $attr_name ] = $color_id;
// Match substring (needed for attrs like gradient stops).
$module['attrs'][ $attr_name ] = str_replace( $color, $color_id, $module['attrs'][ $attr_name ] );
}
}
}
@ -1444,7 +1516,7 @@ class ET_Core_Portability {
}
if ( isset( $module['content'] ) && is_array( $module['content'] ) ) {
$this->_inject_gcid( $module['content'] );
$this->_inject_gcid( $module['content'], $global_colors );
}
}
}
@ -1472,13 +1544,53 @@ class ET_Core_Portability {
$module_preset_id = $default_preset_id;
}
$preset_settings = array();
if ( isset( $global_presets[ $module_type ]['presets'][ $module_preset_id ] ) ) {
$module['attrs'] = array_merge( $global_presets[ $module_type ]['presets'][ $module_preset_id ]['settings'], $module['attrs'] );
$preset_settings = $global_presets[ $module_type ]['presets'][ $module_preset_id ]['settings'];
} else {
if ( isset( $global_presets[ $module_type ]['presets'][ $default_preset_id ]['settings'] ) ) {
$module['attrs'] = array_merge( $global_presets[ $module_type ]['presets'][ $default_preset_id ]['settings'], $module['attrs'] );
$preset_settings = $global_presets[ $module_type ]['presets'][ $default_preset_id ]['settings'];
}
}
$merged_global_colors_info = array();
if ( isset( $module['attrs']['global_colors_info'] ) ) {
// Retrive global_colors_info from post meta, which saved as string[][].
$gc_info_prepared = str_replace(
array( '[', ']' ),
array( '[', ']' ),
$module['attrs']['global_colors_info']
);
$used_global_colors = json_decode( $gc_info_prepared, true );
$merged_global_colors_info = $used_global_colors;
}
// Merge Global Colors from preset.
if ( isset( $preset_settings['global_colors_info'] ) ) {
$preset_global_colors = json_decode( $preset_settings['global_colors_info'], true );
if ( ! empty( $preset_global_colors ) ) {
foreach ( $preset_global_colors as $color_id => $settings_list ) {
if ( ! empty( $settings_list ) ) {
if ( isset( $used_global_colors[ $color_id ] ) ) {
$merged_global_colors_info[ $color_id ] = array_merge( $used_global_colors[ $color_id ], $settings_list );
} else {
$merged_global_colors_info[ $color_id ] = $settings_list;
}
foreach ( $settings_list as $setting_name ) {
$preset_settings[ $setting_name ] = $color_id;
}
}
}
}
}
$module['attrs'] = array_merge( $preset_settings, $module['attrs'] );
$module['attrs']['global_colors_info'] = wp_json_encode( $merged_global_colors_info );
}
if ( isset( $module['content'] ) && is_array( $module['content'] ) ) {
@ -1639,6 +1751,10 @@ class ET_Core_Portability {
* @return array
*/
protected function get_data_images( $data, $force = false ) {
if ( empty( $data ) ) {
return array();
}
$images = array();
$images_src = array();
$basenames = array(
@ -1663,8 +1779,21 @@ class ET_Core_Portability {
}
foreach ( $data as $value ) {
// If the $value is an object and there is no post_content property,
// it's unlikely to contain any image data so we can continue with the next iteration.
if ( is_object( $value ) && ! property_exists( $value, 'post_content' ) ) {
continue;
}
if ( is_array( $value ) || is_object( $value ) ) {
// If the $value contains the post_content property, set $value to use
// this object's property value instead of the entire object.
if ( is_object( $value ) && property_exists( $value, 'post_content' ) ) {
$value = $value->post_content;
}
$images = array_merge( $images, $this->get_data_images( (array) $value ) );
continue;
}
// Extract images from HTML or shortcodes.
@ -1685,10 +1814,15 @@ class ET_Core_Portability {
}
}
if ( preg_match( '/^.+?\.(jpg|jpeg|jpe|png|gif|webp)/', $value, $match ) || $force ) {
if ( preg_match( '/^.+?\.(jpg|jpeg|jpe|png|gif|svg|webp)/', $value, $match ) || $force ) {
$basename = basename( $value );
// Avoid duplicates.
// Skip if the value is not a valid URL or an image ID (integer).
if ( ! ( wp_http_validate_url( $value ) || is_int( $value ) ) ) {
continue;
}
// Skip if the images array already contains the value to avoid duplicates.
if ( isset( $images[$value] ) ) {
continue;
}
@ -1864,31 +1998,44 @@ class ET_Core_Portability {
protected function upload_images( $images ) {
$filesystem = $this->set_filesystem();
/**
* Filters whether or not to allow duplicate images to be uploaded
* during Portability import.
*
* @since 4.14.8
*
* @param bool $allow_duplicates Whether or not to allow duplicates. Default is `false`.
*/
$allow_duplicates = apply_filters( 'et_core_portability_import_attachment_allow_duplicates', false );
foreach ( $images as $key => $image ) {
$basename = sanitize_file_name( wp_basename( $image['url'] ) );
$attachments = get_posts( array(
'posts_per_page' => -1,
'post_type' => 'attachment',
'meta_key' => '_wp_attached_file',
'meta_value' => pathinfo( $basename, PATHINFO_FILENAME ),
'meta_compare' => 'LIKE',
) );
$id = 0;
$url = '';
$basename = sanitize_file_name( wp_basename( $image['url'] ) );
$id = 0;
$url = '';
// Avoid duplicates.
if ( ! is_wp_error( $attachments ) && ! empty( $attachments ) ) {
foreach ( $attachments as $attachment ) {
$attachment_url = wp_get_attachment_url( $attachment->ID );
$file = get_attached_file( $attachment->ID );
$filename = sanitize_file_name( wp_basename( $file ) );
if ( ! $allow_duplicates ) {
$attachments = get_posts( array(
'posts_per_page' => -1,
'post_type' => 'attachment',
'meta_key' => '_wp_attached_file',
'meta_value' => pathinfo( $basename, PATHINFO_FILENAME ),
'meta_compare' => 'LIKE',
) );
// Use existing image only if the content matches.
if ( $filesystem->get_contents( $file ) === base64_decode( $image['encoded'] ) ) {
$id = isset( $image['id'] ) ? $attachment->ID : 0;
$url = $attachment_url;
// Avoid duplicates.
if ( ! is_wp_error( $attachments ) && ! empty( $attachments ) ) {
foreach ( $attachments as $attachment ) {
$attachment_url = wp_get_attachment_url( $attachment->ID );
$file = get_attached_file( $attachment->ID );
$filename = sanitize_file_name( wp_basename( $file ) );
break;
// Use existing image only if the content matches.
if ( $filesystem->get_contents( $file ) === base64_decode( $image['encoded'] ) ) {
$id = isset( $image['id'] ) ? $attachment->ID : 0;
$url = $attachment_url;
break;
}
}
}
}
@ -1899,13 +2046,25 @@ class ET_Core_Portability {
$filesystem->put_contents( $temp_file, base64_decode( $image['encoded'] ) );
$filetype = wp_check_filetype_and_ext( $temp_file, $basename );
// Avoid further duplicates if the proper_file name match an existing image.
if ( isset( $filetype['proper_filename'] ) && $filetype['proper_filename'] !== $basename ) {
if ( isset( $filename ) && $filename === $filetype['proper_filename'] ) {
// Use existing image only if the basenames and content match.
if ( $filesystem->get_contents( $file ) === $filesystem->get_contents( $temp_file ) ) {
$filesystem->delete( $temp_file );
continue;
if ( ! $allow_duplicates && ! empty( $attachments ) && ! is_wp_error( $attachments ) ) {
// Avoid further duplicates if the proper_filename matches an existing image.
if ( isset( $filetype['proper_filename'] ) && $filetype['proper_filename'] !== $basename ) {
foreach ( $attachments as $attachment ) {
$attachment_url = wp_get_attachment_url( $attachment->ID );
$file = get_attached_file( $attachment->ID );
$filename = sanitize_file_name( wp_basename( $file ) );
if ( isset( $filename ) && $filename === $filetype['proper_filename'] ) {
// Use existing image only if the basenames and content match.
if ( $filesystem->get_contents( $file ) === $filesystem->get_contents( $temp_file ) ) {
$id = isset( $image['id'] ) ? $attachment->ID : 0;
$url = $attachment_url;
$filesystem->delete( $temp_file );
break;
}
}
}
}
}
@ -1914,7 +2073,19 @@ class ET_Core_Portability {
'name' => $basename,
'tmp_name' => $temp_file,
);
$upload = media_handle_sideload( $file, 0 );
$upload = media_handle_sideload( $file );
$attachment_id = is_wp_error( $upload ) ? 0 : $upload;
/**
* Fires when image attachments are created during portability import.
*
* @since 4.14.6
*
* @param int $attachment_id The attachment id or 0 if attachment upload failed.
*/
do_action( 'et_core_portability_import_attachment_created', $attachment_id );
if ( ! is_wp_error( $upload ) ) {
// Set the replacement as an id if the original image was set as an id (for gallery).
@ -2227,7 +2398,11 @@ class ET_Core_Portability {
public function get_timestamp() {
et_core_nonce_verified_previously();
return isset( $_POST['timestamp'] ) && ! empty( $_POST['timestamp'] ) ? sanitize_text_field( $_POST['timestamp'] ) : (string) current_time( 'timestamp' ); // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested -- This is used to generate the temporary file ID so we don't need the accuracy.
if ( isset( $_POST['timestamp'] ) && ! empty( $_POST['timestamp'] ) ) {
return sanitize_text_field( $_POST['timestamp'] );
}
return function_exists( 'hrtime' ) ? (string) hrtime( true ) : (string) microtime( true ); // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.hrtimeFound -- Intentional use of new PHP function
}
/**
@ -2270,10 +2445,11 @@ class ET_Core_Portability {
*
* @param array $shortcode_object The multidimensional array representing a page structure.
* @param array $used_global_colors List of global colors to merge with.
* @param array $presets Object of presets.
*
* @return array - The list of the Global Colors.
*/
protected function _get_used_global_colors( $shortcode_object, $used_global_colors = array() ) {
protected function _get_used_global_colors( $shortcode_object, $used_global_colors = array(), $presets = array() ) {
foreach ( $shortcode_object as $module ) {
if ( isset( $module['attrs']['global_colors_info'] ) ) {
// Retrive global_colors_info from post meta, which saved as string[][].
@ -2282,11 +2458,25 @@ class ET_Core_Portability {
array( '[', ']' ),
$module['attrs']['global_colors_info']
);
$used_global_colors = array_merge( $used_global_colors, json_decode( $gc_info_prepared, true ) );
// Make sure we pass array to array_merge to avoid Fatal Error.
$gc_info_array = json_decode( $gc_info_prepared, true );
$gc_info_array = is_array( $gc_info_array ) ? $gc_info_array : [];
$used_global_colors = array_merge( $used_global_colors, $gc_info_array );
}
if ( isset( $module['content'] ) && is_array( $module['content'] ) ) {
$used_global_colors = array_merge( $used_global_colors, $this->_get_used_global_colors( $module['content'], $used_global_colors ) );
$used_global_colors = array_merge( $used_global_colors, $this->_get_used_global_colors( $module['content'], $used_global_colors, $presets ) );
}
}
if ( ! empty( $presets ) ) {
foreach ( $presets as $module_type => $module_presets ) {
foreach ( $module_presets->presets as $preset_id => $preset ) {
if ( isset( $preset->settings->global_colors_info ) ) {
$used_global_colors = array_merge( $used_global_colors, json_decode( $preset->settings->global_colors_info, true ) );
}
}
}
}
@ -2450,7 +2640,7 @@ class ET_Core_Portability {
<input type="file">
<div class="et-core-clearfix"></div>
<?php if ( 'post_type' !== $this->instance->type ) : ?>
<label><input type="checkbox" name="et-core-portability-import-backup" /><?php esc_html_e( 'Download backup before importing', ET_CORE_TEXTDOMAIN ); ?></label>
<label><input type="checkbox" name="et-core-portability-import-backup" /><?php esc_html_e( 'Download Backup Before Importing', ET_CORE_TEXTDOMAIN ); // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralDomain -- intentional use of ET_CORE_TEXTDOMAIN ?></label>
<?php endif; ?>
<?php if ( 'post_type' === $this->instance->type ) : ?>
<label><input type="checkbox" name="et-core-portability-import-include-global-presets" /><?php esc_html_e( 'Import Presets', ET_CORE_TEXTDOMAIN ); ?></label>

View File

@ -1391,7 +1391,7 @@ class ET_Core_SupportCenter {
'pass_minus_one' => false,
'pass_zero' => false,
'minimum' => null,
'recommended' => '7.2 or higher',
'recommended' => '7.4 or higher',
'actual' => (float) phpversion(),
'help_text' => et_core_intentionally_unescaped( __( 'We recommend using the latest stable version of PHP. This will not only ensure compatibility with Divi, but it will also greatly speed up your website leading to less memory and CPU related issues.', 'et-core' ), 'html' ),
'learn_more' => 'http://php.net/releases/',
@ -2607,7 +2607,8 @@ class ET_Core_SupportCenter {
);
$response['token'] = '';
if ( ! empty( $site_id ) && is_string( $site_id ) ) {
$response['token'] = $account_settings['token'] . '|' . $site_id;
$account_setting_token = isset( $account_settings['token'] ) ? $account_settings['token'] : '';
$response['token'] = $account_setting_token . '|' . $site_id;
}
$response['message'] = esc_html__(
'ET Support User role has been activated.',
@ -3025,12 +3026,13 @@ class ET_Core_SupportCenter {
$site_id = get_option( 'et_support_site_id' );
$support_token_cta = '';
if ( intval( $is_et_support_user_active ) > 0 && ! empty( $site_id ) && is_string( $site_id ) ) {
$account_settings = get_option( $this->support_user_options_name );
$support_token_cta = '<a class="copy_support_token" data-token="'
. esc_attr( $account_settings['token'] . '|' . $site_id )
. '">'
. esc_html__( 'Copy Support Token', 'et-core' )
. '</a>';
$account_settings = get_option( $this->support_user_options_name );
$account_setting_token = isset( $account_settings['token'] ) ? $account_settings['token'] : '';
$support_token_cta = '<a class="copy_support_token" data-token="'
. esc_attr( $account_setting_token . '|' . $site_id )
. '">'
. esc_html__( 'Copy Support Token', 'et-core' )
. '</a>';
}
$card_content .= '<div class="et_card_cta">'

View File

@ -23,6 +23,8 @@ final class ET_Core_Updates {
private static $_this;
function __construct( $core_url, $product_version ) {
global $wp_version;
// Don't allow more than one instance of the class
if ( isset( self::$_this ) ) {
wp_die( sprintf( esc_html__( '%s: You cannot create a second instance of this class.', 'et-core' ),
@ -49,7 +51,13 @@ final class ET_Core_Updates {
add_filter( 'wp_prepare_themes_for_js', array( $this, 'replace_theme_update_notification' ) );
add_filter( 'upgrader_package_options', array( $this, 'check_upgrading_product' ) );
add_filter( 'upgrader_pre_download', array( $this, 'update_error_message' ), 20, 2 );
// The 4th paramenter, $hook_extra was added in WordPress 5.5.0.
if ( version_compare( $wp_version, '5.5.0', '>=' ) ) {
add_filter( 'upgrader_pre_download', array( $this, 'update_error_message' ), 20, 4 );
} else {
add_filter( 'upgrader_pre_download', array( $this, 'update_error_message' ), 20, 3 );
}
add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_plugins_updates' ) );
add_filter( 'plugins_api', array( $this, 'maybe_modify_plugins_changelog' ), 20, 3 );
@ -103,7 +111,9 @@ final class ET_Core_Updates {
return;
}
$message = et_get_safe_localization( __( 'For all Elegant Themes products, please <a href="http://www.elegantthemes.com/gallery/divi/documentation/update/" target="_blank">authenticate your subscription</a> via the Updates tab in your theme & plugin settings to enable product updates. Make sure that your Username and API Key have been entered correctly.', 'et-core' ) );
$message = empty( $custom_message = $this->get_custom_update_notification_message( $plugin_data['url'] ) )
? et_get_safe_localization( __( 'For all Elegant Themes products, please <a href="http://www.elegantthemes.com/gallery/divi/documentation/update/" target="_blank">authenticate your subscription</a> via the Updates tab in your theme & plugin settings to enable product updates. Make sure that your Username and API Key have been entered correctly.', 'et-core' ) )
: $custom_message;
echo "</p><p>{$message}";
}
@ -128,6 +138,22 @@ final class ET_Core_Updates {
$this->force_update_requests();
}
function get_custom_update_notification_message( $update_message ) {
$is_valid_api_key_status = empty( $account_api_key_status = get_site_option( 'et_account_api_key_status' ) ) || 'invalid' !== $account_api_key_status;
if ( $is_valid_api_key_status && false !== strpos( $update_message, '/wp-json/api/v1/changelog/product_id/' ) ) {
return et_get_safe_localization( __( '<em>The license for this Divi Marketplace product has expired. Please <a target="_blank" href="https://www.elegantthemes.com/members-area/marketplace/">renew the license</a> to continue receiving product updates and support.</em>', 'et-core' ) );
}
if ( false !== strpos( $update_message, 'Automatic update is unavailable for this theme' ) ) {
return 'expired' === $this->account_status
? et_get_safe_localization( __( '<em>Your Elegant Themes subscription has expired. You must <a href="https://www.elegantthemes.com/members-area/renew/" target="_blank">renew your account</a> to regain access to product updates and support.</em>', 'et-core' ) )
: et_get_safe_localization( __( '<em>Before you can receive product updates, you must first authenticate your Elegant Themes subscription. To do this, you need to enter both your Elegant Themes Username and your Elegant Themes API Key into the Updates Tab in your theme and plugin settings. To locate your API Key, <a href="https://www.elegantthemes.com/members-area/api/" target="_blank">log in</a> to your Elegant Themes account and navigate to the <strong>Account > API Key</strong> page. <a href="http://www.elegantthemes.com/gallery/divi/documentation/update/" target="_blank">Learn more here</a></em>. If you still get this message, please make sure that your Username and API Key have been entered correctly', 'et-core' ) );
}
return '';
}
function replace_theme_update_notification( $themes_array ) {
if ( empty( $themes_array ) ) {
return $themes_array;
@ -139,14 +165,16 @@ final class ET_Core_Updates {
foreach ( $themes_array as $id => $theme_data ) {
// replace default error message with custom message for ET themes.
if (
in_array( $id, $this->all_et_products_domains['theme'] )
&& false !== strpos( $theme_data['update'], 'Automatic update is unavailable for this theme' )
) {
if ( ! in_array( $id, $this->all_et_products_domains['theme'] )
|| false === strpos( $theme_data['update'], 'Automatic update is unavailable for this theme' ) ) {
continue;
}
if ( ! empty( $custom_message = $this->get_custom_update_notification_message( $theme_data['update'] ) ) ) {
$themes_array[ $id ]['update'] = sprintf(
'<p>%1$s<br/> %2$s</p>',
$theme_data['update'],
et_get_safe_localization( __( '<em>Before you can receive product updates, you must first authenticate your Elegant Themes subscription. To do this, you need to enter both your Elegant Themes Username and your Elegant Themes API Key into the Updates Tab in your theme and plugin settings. To locate your API Key, <a href="https://www.elegantthemes.com/members-area/api/" target="_blank">log in</a> to your Elegant Themes account and navigate to the <strong>Account > API Key</strong> page. <a href="http://www.elegantthemes.com/gallery/divi/documentation/update/" target="_blank">Learn more here</a></em>. If you still get this message, please make sure that your Username and API Key have been entered correctly', 'et-core' ) )
$custom_message
);
}
}
@ -154,7 +182,7 @@ final class ET_Core_Updates {
return $themes_array;
}
function update_error_message( $reply, $package ) {
function update_error_message( $reply, $package, $upgrader, $hook_extra = array() ) {
if ( ! $this->upgrading_et_product ) {
return $reply;
}
@ -166,8 +194,25 @@ final class ET_Core_Updates {
return $reply;
}
$hook_name = ! empty( $hook_extra['theme'] ) ? 'theme' : 'plugin';
$site_transient = 'theme' === $hook_name ? get_site_transient( 'et_update_themes' ) : get_site_transient( 'et_update_all_plugins' );
$changelog_url = '';
if ( isset( $site_transient->response ) && ! empty( $site_transient->response[ $hook_extra[ $hook_name ] ] ) ) {
$changelog_url = 'theme' === $hook_name
? $site_transient->response[ $hook_extra[ $hook_name ] ]['url']
: $site_transient->response[ $hook_extra[ $hook_name ] ]->url;
}
if ( false !== strpos( $changelog_url, '/wp-json/api/v1/changelog/product_id/' ) ) {
$error_message = $this->get_custom_update_notification_message( $changelog_url );
} else {
$error_message = 'expired' === $this->account_status
? et_get_safe_localization( __( '<em>Your Elegant Themes subscription has expired. You must <a href="https://www.elegantthemes.com/members-area/renew/" target="_blank">renew your account</a> to regain access to product updates and support.</em>', 'et-core' ) )
: et_get_safe_localization( __( '<em>Before you can receive product updates, you must first authenticate your Elegant Themes subscription. To do this, you need to enter both your Elegant Themes Username and your Elegant Themes API Key into the Updates Tab in your theme and plugin settings. To locate your API Key, <a href="https://www.elegantthemes.com/members-area/api/" target="_blank">log in</a> to your Elegant Themes account and navigate to the <strong>Account > API Key</strong> page. <a href="http://www.elegantthemes.com/gallery/divi/documentation/update/" target="_blank">Learn more here</a></em>. If you still get this message, please make sure that your Username and API Key have been entered correctly', 'et-core' ) );
}
// output custom error message for ET Products if package is empty
$error_message = et_get_safe_localization( __( '<em>Before you can receive product updates, you must first authenticate your Elegant Themes subscription. To do this, you need to enter both your Elegant Themes Username and your Elegant Themes API Key into the Updates Tab in your theme and plugin settings. To locate your API Key, <a href="https://www.elegantthemes.com/members-area/api/" target="_blank">log in</a> to your Elegant Themes account and navigate to the <strong>Account > API Key</strong> page. <a href="http://www.elegantthemes.com/gallery/divi/documentation/update/" target="_blank">Learn more here</a></em>. If you still get this message, please make sure that your Username and API Key have been entered correctly', 'et-core' ) );
return new WP_Error( 'no_package', $error_message );
}
@ -360,6 +405,15 @@ final class ET_Core_Updates {
}
foreach ( $_plugins as $file => $plugin ) {
$update_uri = isset( $plugin['UpdateURI'] ) ? $plugin['UpdateURI'] : '';
$is_et_uri = false !== strpos( $update_uri, 'elegantthemes.com' );
// Continue to the next iteration if the Update URI
// is not empty and not using Elegant Themes's domain.
if ( ! empty( $update_uri ) && ! $is_et_uri ) {
continue;
}
$plugins[ $file ] = $plugin['Version'];
}
@ -676,17 +730,15 @@ final class ET_Core_Updates {
return $url;
}
$matches = array();
$update_transient = get_site_transient( 'et_update_all_plugins' );
if ( ! is_object( $update_transient ) || empty( $update_transient->response ) ) {
return $url;
}
$matches = array();
$update_transient = get_site_transient( 'et_update_all_plugins' );
$et_updated_plugins_data = get_transient( 'et_updated_plugins_data' );
$has_last_checked = ! empty( $update_transient->last_checked ) && ! empty( $et_updated_plugins_data->last_checked );
if ( ! is_object( $update_transient ) ) {
return $url;
}
/*
* Attempt to use a cached list of updated plugins.
* Re-save the list, whenever the update transient last checked time changes.
@ -701,14 +753,18 @@ final class ET_Core_Updates {
foreach ( $update_transient->response as $response_plugin_settings ) {
$slug = sanitize_text_field( $response_plugin_settings->slug );
$et_updated_plugins_data->changelogs[ $slug ] = $response_plugin_settings->url . '?TB_iframe=true&width=1024&height=800';
$et_updated_plugins_data->changelogs[ $slug ] = esc_url_raw( $response_plugin_settings->url . '?TB_iframe=true&width=1024&height=800' );
}
set_transient( 'et_updated_plugins_data', $et_updated_plugins_data );
}
if ( empty( $et_updated_plugins_data->changelogs ) ) {
return $url;
if ( ! empty( $update_transient->no_update ) ) {
foreach ( $update_transient->no_update as $no_update_plugin_settings ) {
$slug = sanitize_text_field( $no_update_plugin_settings->slug );
$et_updated_plugins_data->changelogs[ $slug ] = esc_url_raw( $no_update_plugin_settings->url . '?TB_iframe=true&width=1024&height=800' );
}
}
preg_match( '/plugin=([^&]*)/', $path, $matches );

View File

@ -67,8 +67,25 @@ class ET_Core_API_Spam_ReCaptcha extends ET_Core_API_Spam_Provider {
}
public function is_enabled() {
return isset( $this->data['site_key'], $this->data['secret_key'] )
$has_recaptcha_module = true;
if ( class_exists( 'ET_Dynamic_Assets' ) ) {
$et_dynamic_module_framework = et_builder_dynamic_module_framework();
$is_dynamic_framework_enabled = et_builder_is_frontend() && 'on' === $et_dynamic_module_framework;
$is_dynamic_css_enabled = et_builder_is_frontend() && et_use_dynamic_css();
if ( $is_dynamic_framework_enabled && $is_dynamic_css_enabled ) {
$et_dynamic_assets = ET_Dynamic_Assets::init();
$saved_shortcodes = $et_dynamic_assets->get_saved_page_shortcodes();
$recaptcha_modules = array( 'et_pb_contact_form', 'et_pb_signup' );
$has_recaptcha_module = ! empty( array_intersect( $saved_shortcodes, $recaptcha_modules ) );
}
}
$has_key = isset( $this->data['site_key'], $this->data['secret_key'] )
&& et_()->all( array( $this->data['site_key'], $this->data['secret_key'] ) );
return $has_key && $has_recaptcha_module;
}
/**

View File

@ -83,7 +83,7 @@ class ET_Core_Cache_Directory {
}
$this->can_write = $can_write || $can_create;
$this->path = $path;
$this->path = et_()->normalize_path( $path );
$this->url = $url;
$this->_maybe_adjust_path_for_multisite( $uploads_dir_info );

View File

@ -1041,6 +1041,69 @@ class ET_Core_Data_Utils {
$buffer[15]
);
}
/**
* Append/Prepend to comma separated selectors.
*
* Example:
*
* @see UtilsTest::testAppendPrependCommaSeparatedSelectors()
*
* @param string $css_selector Comma separated CSS selectors.
* @param string $value Value to append/prepend.
* @param string $prefix_suffix Values can be `prefix` or `suffix`.
* @param bool $is_space_required Is space required? // phpcs:ignore Squiz.Commenting.FunctionComment.ParamCommentFullStop -- Respecting punctuation.
*
* @return string
*/
public function append_prepend_comma_separated_selectors(
$css_selector,
$value,
$prefix_suffix,
$is_space_required = true
) {
$css_selectors = explode( ',', $css_selector );
$css_selectors_processed = array();
$is_prefix = 'prefix' === $prefix_suffix;
foreach ( $css_selectors as $selector ) {
$selector = rtrim( ltrim( $selector ) );
if ( $is_prefix && $is_space_required ) {
$css_selectors_processed[] = sprintf( '%2$s %1$s', $selector, $value );
} elseif ( $is_prefix && ! $is_space_required ) {
$css_selectors_processed[] = sprintf( '%2$s%1$s', $selector, $value );
} elseif ( ! $is_prefix && $is_space_required ) {
$css_selectors_processed[] = sprintf( '%1$s %2$s', $selector, $value );
} elseif ( ! $is_prefix && ! $is_space_required ) {
$css_selectors_processed[] = sprintf( '%1$s%2$s', $selector, $value );
}
}
return implode( ',', $css_selectors_processed );
}
/**
* Helper function to prepare attributes for SVG.
*
* @param array $props Props.
*
* @return string
*/
public function get_svg_attrs( $props ) {
$result = '';
$attrs = array_merge(
$props,
array(
'xmlns' => 'http://www.w3.org/2000/svg',
)
);
foreach ( $attrs as $key => $value ) {
$result .= " {$key}=\"{$value}\"";
}
return $result;
}
}

View File

@ -57,7 +57,7 @@ function et_safe_mode_maybe_disable_plugins( $plugins = array() ) {
}
/** @var array Collection of plugins that we will NOT disable when Safe Mode is activated. */
$plugins_allowlist = get_option( 'et_safe_mode_plugins_allowlist' );
$plugins_allowlist = (array) get_option( 'et_safe_mode_plugins_allowlist' );
$clean_plugins = $plugins;