Upgarded to 4.17.4
This commit is contained in:
@ -85,7 +85,9 @@ class ET_Builder_Library {
|
||||
$this->_register_hooks();
|
||||
$this->_register_ajax_callbacks();
|
||||
|
||||
self::$_i18n = require ET_BUILDER_DIR . '/frontend-builder/i18n/library.php';
|
||||
$root_directory = defined( 'ET_BUILDER_PLUGIN_ACTIVE' ) ? ET_BUILDER_PLUGIN_DIR : get_template_directory();
|
||||
|
||||
self::$_i18n = require $root_directory . '/cloud/i18n/library.php';
|
||||
|
||||
self::$_standard_post_types = self::_standard_post_types();
|
||||
}
|
||||
@ -139,7 +141,7 @@ class ET_Builder_Library {
|
||||
*/
|
||||
protected static function _get_image_size_name( $type ) {
|
||||
$names = array(
|
||||
'thumbnail' => 'et-pb-portfolio-image',
|
||||
'thumbnail' => 'full',
|
||||
'thumbnail_small' => 'et-pb-portfolio-image',
|
||||
'screenshot' => 'et-pb-portfolio-image-single',
|
||||
);
|
||||
@ -206,11 +208,11 @@ class ET_Builder_Library {
|
||||
'id' => $category->term_id,
|
||||
'name' => $category_name,
|
||||
'slug' => $category->slug,
|
||||
'layouts' => array(),
|
||||
'items' => array(),
|
||||
);
|
||||
}
|
||||
|
||||
$layout_categories[ $category->term_id ]['layouts'][] = $index;
|
||||
$layout_categories[ $category->term_id ]['items'][] = $index;
|
||||
|
||||
$layout->categories[] = $category_name;
|
||||
$layout->category_ids[] = $category->term_id;
|
||||
@ -231,6 +233,57 @@ class ET_Builder_Library {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes layout tags for inclusion in the library UI layouts data.
|
||||
*
|
||||
* @since 3.0.99
|
||||
*
|
||||
* @param WP_POST $post Unprocessed layout.
|
||||
* @param object $layout Currently processing layout.
|
||||
* @param int $index The layout's index position.
|
||||
* @param array[] $layout_tags Processed layouts.
|
||||
*/
|
||||
protected function _process_layout_tags( $post, $layout, $index, &$layout_tags ) {
|
||||
$terms = wp_get_post_terms( $post->ID, $this->layout_tags->name );
|
||||
|
||||
if ( ! $terms ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $terms as $tag ) {
|
||||
$tag_name = self::__( html_entity_decode( $tag->name ), '@tags' );
|
||||
$tag_name = et_core_intentionally_unescaped( $tag_name, 'react_jsx' );
|
||||
|
||||
if ( ! isset( $layout_tags[ $tag->term_id ] ) ) {
|
||||
$layout_tags[ $tag->term_id ] = array(
|
||||
'id' => $tag->term_id,
|
||||
'name' => $tag_name,
|
||||
'slug' => $tag->slug,
|
||||
'items' => array(),
|
||||
);
|
||||
}
|
||||
|
||||
$layout_tags[ $tag->term_id ]['items'][] = $index;
|
||||
|
||||
$layout->tags[] = $tag_name;
|
||||
$layout->tag_ids[] = $tag->term_id;
|
||||
|
||||
if ( ! isset( $layout->tag_slug ) ) {
|
||||
$layout->tag_slug = $tag->slug;
|
||||
}
|
||||
|
||||
$id = get_post_meta( $post->ID, self::$_primary_category_key, true );
|
||||
|
||||
if ( $id ) {
|
||||
// $id is a string, $category->term_id is an int.
|
||||
if ( $id === $tag->term_id ) {
|
||||
// This is the primary category (used in the layout URL).
|
||||
$layout->tag_slug = $tag->slug;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes layout packs for inclusion in the library UI layouts data.
|
||||
*
|
||||
@ -257,7 +310,7 @@ class ET_Builder_Library {
|
||||
'name' => $pack_name,
|
||||
'slug' => $pack->slug,
|
||||
'date' => $layout->date,
|
||||
'layouts' => array(),
|
||||
'items' => array(),
|
||||
);
|
||||
}
|
||||
|
||||
@ -269,11 +322,14 @@ class ET_Builder_Library {
|
||||
$layout_packs[ $pack->term_id ]['landing_index'] = $index;
|
||||
}
|
||||
|
||||
$layout_packs[ $pack->term_id ]['layouts'][] = $index;
|
||||
$layout_packs[ $pack->term_id ]['items'][] = $index;
|
||||
|
||||
$layout_packs[ $pack->term_id ]['categories'] = $layout->categories;
|
||||
$layout_packs[ $pack->term_id ]['category_ids'] = $layout->category_ids;
|
||||
|
||||
$layout_packs[ $pack->term_id ]['tags'] = $layout->tags;
|
||||
$layout_packs[ $pack->term_id ]['tag_ids'] = $layout->tag_ids;
|
||||
|
||||
$layout->pack = $pack_name;
|
||||
$layout->pack_id = $pack->term_id;
|
||||
}
|
||||
@ -286,7 +342,15 @@ class ET_Builder_Library {
|
||||
protected function _register_ajax_callbacks() {
|
||||
add_action( 'wp_ajax_et_builder_library_get_layouts_data', array( $this, 'wp_ajax_et_builder_library_get_layouts_data' ) );
|
||||
add_action( 'wp_ajax_et_builder_library_get_layout', array( $this, 'wp_ajax_et_builder_library_get_layout' ) );
|
||||
add_action( 'wp_ajax_et_builder_library_update_terms', array( $this, 'wp_ajax_et_builder_library_update_terms' ) );
|
||||
add_action( 'wp_ajax_et_builder_library_save_temp_layout', array( $this, 'wp_ajax_et_builder_library_save_temp_layout' ) );
|
||||
add_action( 'wp_ajax_et_builder_library_update_item', array( $this, 'wp_ajax_et_builder_library_update_item' ) );
|
||||
add_action( 'wp_ajax_et_builder_library_upload_thumbnail', array( $this, 'wp_ajax_et_builder_library_upload_thumbnail' ) );
|
||||
add_action( 'wp_ajax_et_builder_library_update_account', array( $this, 'wp_ajax_et_builder_library_update_account' ) );
|
||||
add_action( 'wp_ajax_et_builder_library_remove_temp_layout', array( $this, 'wp_ajax_et_builder_library_remove_temp_layout' ) );
|
||||
add_action( 'wp_ajax_et_builder_toggle_cloud_status', array( $this, 'wp_ajax_et_builder_toggle_cloud_status' ) );
|
||||
add_action( 'wp_ajax_et_builder_library_get_cloud_token', array( $this, 'wp_ajax_et_builder_library_get_cloud_token' ) );
|
||||
add_action( 'wp_ajax_et_builder_library_clear_temp_presets', array( $this, 'wp_ajax_et_builder_library_clear_temp_presets' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -306,11 +370,12 @@ class ET_Builder_Library {
|
||||
|
||||
$this->layouts = ET_Builder_Post_Type_Layout::instance();
|
||||
$this->layout_categories = ET_Builder_Post_Taxonomy_LayoutCategory::instance();
|
||||
$this->layout_tags = ET_Builder_Post_Taxonomy_LayoutTag::instance();
|
||||
$this->layout_packs = ET_Builder_Post_Taxonomy_LayoutPack::instance();
|
||||
$this->layout_types = ET_Builder_Post_Taxonomy_LayoutType::instance();
|
||||
$this->layout_width = ET_Builder_Post_Taxonomy_LayoutWidth::instance();
|
||||
|
||||
ET_Builder_Post_Taxonomy_LayoutScope::instance();
|
||||
ET_Builder_Post_Taxonomy_LayoutWidth::instance();
|
||||
|
||||
// We manually call register_all() now to ensure the CPT and taxonomies are registered
|
||||
// at exactly the same point during the request that they were in prior releases.
|
||||
@ -327,6 +392,10 @@ class ET_Builder_Library {
|
||||
public function _register_hooks() {
|
||||
add_action( 'admin_init', 'ET_Builder_Library::update_old_layouts' );
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'wp_hook_admin_enqueue_scripts' ), 4 );
|
||||
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
|
||||
add_action( 'wp_footer', array( $this, 'render_session_expired_modal' ) );
|
||||
|
||||
add_filter( 'et_theme_builder_template_settings_options_term_pages', array( $this, 'tb_remove_unsupported_taxonomies' ), 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -343,12 +412,13 @@ class ET_Builder_Library {
|
||||
* @type int[] $packs Layout pack ids sorted alphabetically by pack name.
|
||||
* }
|
||||
*/
|
||||
protected static function _sort_builder_library_data( $categories, $packs ) {
|
||||
protected static function _sort_builder_library_data( $categories, $packs, $tags ) {
|
||||
$categories = array_values( $categories );
|
||||
$packs = array_values( $packs );
|
||||
$tags = array_values( $tags );
|
||||
$sorted = array();
|
||||
|
||||
foreach ( array( 'categories', 'packs' ) as $taxonomy ) {
|
||||
foreach ( array( 'categories', 'packs', 'tags' ) as $taxonomy ) {
|
||||
$sorted[ $taxonomy ] = array();
|
||||
|
||||
$$taxonomy = self::$_->array_sort_by( $$taxonomy, 'slug' );
|
||||
@ -384,9 +454,10 @@ class ET_Builder_Library {
|
||||
*
|
||||
* @return array $data
|
||||
*/
|
||||
public function builder_library_layouts_data() {
|
||||
public function builder_library_layouts_data( $library_type = 'layout' ) {
|
||||
$layout_categories = array();
|
||||
$layout_packs = array();
|
||||
$layout_tags = array();
|
||||
$layouts = array();
|
||||
$index = 0;
|
||||
|
||||
@ -399,7 +470,7 @@ class ET_Builder_Library {
|
||||
$posts = $this->layouts
|
||||
->query()
|
||||
->not()->with_meta( '_et_pb_built_for_post_type', $extra_layout_post_type )
|
||||
->run();
|
||||
->run( array( 'post_status' => array( 'publish', 'trash' ) ) );
|
||||
|
||||
$posts = self::$_->array_sort_by( is_array( $posts ) ? $posts : array( $posts ), 'post_name' );
|
||||
|
||||
@ -419,11 +490,22 @@ class ET_Builder_Library {
|
||||
|
||||
$layout->type = $types[0]->name;
|
||||
|
||||
// For the initial release of new library UI, only 'layouts' are needed.
|
||||
if ( 'layout' !== $layout->type ) {
|
||||
if ( $library_type !== $layout->type ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$width_values = wp_get_post_terms( $layout->id, $this->layout_width->name, array( 'fields' => 'names' ) );
|
||||
$layout->width = ! empty( $width_values ) ? $width_values[0] : 'regular';
|
||||
|
||||
$layout->row_layout = get_post_meta( $post->ID, '_et_pb_row_layout', true );
|
||||
|
||||
$layout->subtype = get_post_meta( $post->ID, '_et_pb_module_type', true );
|
||||
|
||||
if ( '' !== $layout->subtype ) {
|
||||
$module = ET_Builder_Element::get_module( $layout->subtype );
|
||||
$layout->subtitle = ! empty( $module->name ) ? $module->name : $layout->type;
|
||||
}
|
||||
|
||||
$title = html_entity_decode( $post->post_title );
|
||||
$short_name = get_post_meta( $post->ID, '_et_builder_library_short_name', true );
|
||||
|
||||
@ -458,14 +540,18 @@ class ET_Builder_Library {
|
||||
$layout->thumbnail_small = esc_url( get_the_post_thumbnail_url( $post->ID, $thumbnail_small ) );
|
||||
$layout->screenshot = esc_url( get_the_post_thumbnail_url( $post->ID, $screenshot ) );
|
||||
|
||||
$layout->is_global = $this->layouts->is_global( $layout->id );
|
||||
$layout->is_favorite = $this->layouts->is_favorite( $layout->id );
|
||||
$layout->is_landing = ! empty( $post->post_excerpt );
|
||||
$layout->description = '';
|
||||
$layout->isTrash = 'trash' === $post->post_status; // phpcs:ignore ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase -- This is valid format for the property in the Cloud App.
|
||||
$layout->categories = array();
|
||||
$layout->category_ids = array();
|
||||
|
||||
$layout->is_global = $this->layouts->is_global( $layout->id );
|
||||
$layout->is_landing = ! empty( $post->post_excerpt );
|
||||
$layout->description = '';
|
||||
$layout->tags = array();
|
||||
$layout->tag_ids = array();
|
||||
|
||||
$this->_process_layout_categories( $post, $layout, $index, $layout_categories );
|
||||
$this->_process_layout_tags( $post, $layout, $index, $layout_tags );
|
||||
$this->_process_layout_packs( $post, $layout, $index, $layout_packs );
|
||||
|
||||
wp_reset_postdata();
|
||||
@ -550,10 +636,10 @@ class ET_Builder_Library {
|
||||
* }
|
||||
*/
|
||||
$saved_layouts_data = array(
|
||||
'categories' => $layout_categories,
|
||||
'categories' => $this->_get_processed_terms( 'layout_category' ),
|
||||
'packs' => $layout_packs,
|
||||
'layouts' => $layouts,
|
||||
'sorted' => self::_sort_builder_library_data( $layout_categories, $layout_packs ),
|
||||
'tags' => $this->_get_processed_terms( 'layout_tag' ),
|
||||
'items' => $layouts,
|
||||
);
|
||||
$saved_layouts_data = apply_filters( 'et_builder_library_saved_layouts', $saved_layouts_data );
|
||||
|
||||
@ -585,6 +671,35 @@ class ET_Builder_Library {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the terms list and processes it into desired format.
|
||||
*
|
||||
* @since 4.17.0
|
||||
*
|
||||
* @param string $term_name Term Name.
|
||||
*
|
||||
* @return array $terms_by_id
|
||||
*/
|
||||
protected function _get_processed_terms( $term_name ) {
|
||||
$terms = get_terms( $term_name, array( 'hide_empty' => false ) );
|
||||
$terms_by_id = array();
|
||||
|
||||
if ( is_wp_error( $terms ) || empty( $terms ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
foreach ( $terms as $term ) {
|
||||
$term_id = $term->term_id;
|
||||
|
||||
$terms_by_id[ $term_id ]['id'] = $term_id;
|
||||
$terms_by_id[ $term_id ]['name'] = $term->name;
|
||||
$terms_by_id[ $term_id ]['slug'] = $term->slug;
|
||||
$terms_by_id[ $term_id ]['count'] = $term->count;
|
||||
}
|
||||
|
||||
return $terms_by_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters data for the 'Your Existing Pages' tab.
|
||||
*
|
||||
@ -667,9 +782,8 @@ class ET_Builder_Library {
|
||||
$layouts = array();
|
||||
$index = 0;
|
||||
|
||||
$thumbnail = self::_get_image_size_name( 'thumbnail' );
|
||||
$thumbnail = self::_get_image_size_name( 'screenshot' );
|
||||
$thumbnail_small = self::_get_image_size_name( 'thumbnail_small' );
|
||||
$screenshot = self::_get_image_size_name( 'screenshot' );
|
||||
|
||||
/**
|
||||
* Array of post types that should be listed as categories under "Existing Pages".
|
||||
@ -700,8 +814,18 @@ class ET_Builder_Library {
|
||||
// Keep track of slugs in case there are duplicates.
|
||||
$seen = array();
|
||||
|
||||
// List of post types which should be excluded from the Pages tab.
|
||||
$unsupported_post_types = array(
|
||||
ET_BUILDER_LAYOUT_POST_TYPE,
|
||||
ET_THEME_BUILDER_TEMPLATE_POST_TYPE,
|
||||
ET_THEME_BUILDER_HEADER_LAYOUT_POST_TYPE,
|
||||
ET_THEME_BUILDER_BODY_LAYOUT_POST_TYPE,
|
||||
ET_THEME_BUILDER_FOOTER_LAYOUT_POST_TYPE,
|
||||
ET_THEME_BUILDER_THEME_BUILDER_POST_TYPE,
|
||||
);
|
||||
|
||||
foreach ( $post_types as $post_type ) {
|
||||
if ( ET_BUILDER_LAYOUT_POST_TYPE === $post_type ) {
|
||||
if ( in_array( $post_type, $unsupported_post_types, true ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -789,7 +913,6 @@ class ET_Builder_Library {
|
||||
|
||||
$layout->thumbnail = esc_url( get_the_post_thumbnail_url( $post->ID, $thumbnail ) );
|
||||
$layout->thumbnail_small = esc_url( get_the_post_thumbnail_url( $post->ID, $thumbnail_small ) );
|
||||
$layout->screenshot = esc_url( get_the_post_thumbnail_url( $post->ID, $screenshot ) );
|
||||
|
||||
$layout->categories = array();
|
||||
$layout->category_ids = array( $category_id );
|
||||
@ -805,7 +928,7 @@ class ET_Builder_Library {
|
||||
|
||||
$layout->status = isset( $post_status_object->label ) ? $post_status_object->label : $post->post_status;
|
||||
|
||||
$layouts[ $layout_index++ ] = $layout;
|
||||
$layouts[] = $layout;
|
||||
|
||||
$index++;
|
||||
}
|
||||
@ -823,7 +946,7 @@ class ET_Builder_Library {
|
||||
return array(
|
||||
'categories' => $categories,
|
||||
'packs' => $packs,
|
||||
'layouts' => $layouts,
|
||||
'items' => $layouts,
|
||||
'options' => array(
|
||||
'content' => array(
|
||||
'title' => array(
|
||||
@ -833,6 +956,7 @@ class ET_Builder_Library {
|
||||
),
|
||||
'sidebar' => array(
|
||||
'title' => et_core_intentionally_unescaped( self::__( 'Find A Page' ), 'react_jsx' ),
|
||||
'filterTitle' => et_core_intentionally_unescaped( self::__( 'Post Types' ), 'react_jsx' ),
|
||||
),
|
||||
'list' => array(
|
||||
'columns' => array(
|
||||
@ -1008,7 +1132,10 @@ class ET_Builder_Library {
|
||||
public function wp_ajax_et_builder_library_get_layout() {
|
||||
et_core_security_check( 'edit_posts', 'et_builder_library_get_layout', 'nonce' );
|
||||
|
||||
$id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
|
||||
$id = isset( $_POST['id'] ) ? (int) sanitize_text_field( $_POST['id'] ) : 0;
|
||||
$content_type = isset( $_POST['contentType'] ) ? (string) sanitize_text_field( $_POST['contentType'] ) : 'processed';
|
||||
$library_type = isset( $_POST['libraryType'] ) ? (string) sanitize_text_field( $_POST['libraryType'] ) : 'layout';
|
||||
$built_for = isset( $_POST['postType'] ) ? (string) sanitize_text_field( $_POST['postType'] ) : 'page';
|
||||
|
||||
if ( empty( $id ) ) {
|
||||
wp_send_json_error();
|
||||
@ -1021,7 +1148,7 @@ class ET_Builder_Library {
|
||||
|
||||
switch ( $post_type ) {
|
||||
case ET_BUILDER_LAYOUT_POST_TYPE:
|
||||
$layouts = et_pb_retrieve_templates( 'layout', '', 'all', '0', 'all', 'all', array(), $post_type );
|
||||
$layouts = et_pb_retrieve_templates( $library_type, '', 'all', '0', $built_for, 'all', array() );
|
||||
|
||||
foreach ( $layouts as $layout ) {
|
||||
if ( $id === $layout['ID'] ) {
|
||||
@ -1032,24 +1159,34 @@ class ET_Builder_Library {
|
||||
|
||||
$result['savedShortcode'] = $result['shortcode'];
|
||||
|
||||
if ( ! isset( $_POST['is_BB'] ) ) {
|
||||
$result['savedShortcode'] = et_fb_process_shortcode( $result['savedShortcode'] );
|
||||
} else {
|
||||
$post_content_processed = do_shortcode( $result['shortcode'] );
|
||||
$result['migrations'] = ET_Builder_Module_Settings_Migration::$migrated;
|
||||
}
|
||||
if ( 'processed' === $content_type ) {
|
||||
if ( ! isset( $_POST['is_BB'] ) ) {
|
||||
$result['savedShortcode'] = et_fb_process_shortcode( $result['savedShortcode'] );
|
||||
} else {
|
||||
$post_content_processed = do_shortcode( $result['shortcode'] );
|
||||
$result['migrations'] = ET_Builder_Module_Settings_Migration::$migrated;
|
||||
}
|
||||
|
||||
unset( $result['shortcode'] );
|
||||
unset( $result['shortcode'] );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$post_content = $post->post_content;
|
||||
if ( ! isset( $_POST['is_BB'] ) ) {
|
||||
$post_content = et_fb_process_shortcode( stripslashes( $post_content ) );
|
||||
|
||||
if ( 'processed' === $content_type ) {
|
||||
if ( ! isset( $_POST['is_BB'] ) ) {
|
||||
$post_content = et_fb_process_shortcode( stripslashes( $post_content ) );
|
||||
}
|
||||
}
|
||||
|
||||
$result['savedShortcode'] = $post_content;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( 'exported' === $content_type ) {
|
||||
$result['exported'] = get_exported_content( $result['shortcode'] );
|
||||
}
|
||||
|
||||
$response = wp_json_encode(
|
||||
array(
|
||||
'success' => true,
|
||||
@ -1079,6 +1216,499 @@ class ET_Builder_Library {
|
||||
die( et_core_intentionally_unescaped( $response, 'html' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX Callback: Add/Remove Library terms for layout_tag and layout_category taxonomies.
|
||||
*
|
||||
* @since 4.17.0
|
||||
*
|
||||
* @global $_POST['payload'] Array with the terms list and update type (add/remove) for each.
|
||||
*
|
||||
* @return string JSON encoded.
|
||||
*/
|
||||
public function wp_ajax_et_builder_library_update_terms() {
|
||||
et_core_security_check( 'edit_posts', 'et_builder_library_update_terms', 'nonce' );
|
||||
$payload = isset( $_POST['payload'] ) ? (array) $_POST['payload'] : array(); // phpcs:ignore ET.Sniffs.ValidatedSanitizedInput -- $_POST['payload'] is an array, it's value sanitization is done at the time of accessing value.
|
||||
|
||||
if ( empty( $payload ) ) {
|
||||
wp_send_json_success();
|
||||
return;
|
||||
}
|
||||
|
||||
$new_terms = array();
|
||||
|
||||
foreach ( $payload as $single_item ) {
|
||||
$filter_type = $single_item['filterType'];
|
||||
$taxonomy = 'tags' === $single_item['filterType'] ? 'layout_tag' : 'layout_category';
|
||||
|
||||
switch ( $single_item['updateType'] ) {
|
||||
case 'remove':
|
||||
$term_id = (int) $single_item['id'];
|
||||
wp_delete_term( $term_id, $taxonomy );
|
||||
break;
|
||||
case 'rename':
|
||||
$term_id = (int) $single_item['id'];
|
||||
$new_name = (string) $single_item['newName'];
|
||||
|
||||
if ( '' !== $new_name ) {
|
||||
$updated_term_data = wp_update_term( $term_id, $taxonomy, array( 'name' => $new_name ) );
|
||||
|
||||
if ( ! is_wp_error( $updated_term_data ) ) {
|
||||
$new_terms[] = array(
|
||||
'name' => $new_name,
|
||||
'id' => $updated_term_data['term_id'],
|
||||
'location' => 'local',
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'add':
|
||||
$term_name = (string) $single_item['id'];
|
||||
$new_term_data = wp_insert_term( $term_name, $taxonomy );
|
||||
|
||||
if ( ! is_wp_error( $new_term_data ) ) {
|
||||
$new_terms[] = array(
|
||||
'name' => $term_name,
|
||||
'id' => $new_term_data['term_id'],
|
||||
'location' => 'local',
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wp_send_json_success(
|
||||
array(
|
||||
'newFilters' => $new_terms,
|
||||
'filterType' => $filter_type,
|
||||
'localLibraryTerms' => [
|
||||
'layout_category' => et_fb_prepare_library_terms(),
|
||||
'layout_tag' => et_fb_prepare_library_terms( 'layout_tag' ),
|
||||
],
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX Callback: Remove the Library layout after it was moved to the Cloud.
|
||||
*
|
||||
* @since 4.17.0
|
||||
*
|
||||
* @global $_POST['payload'] Array with the layout data to remove.
|
||||
*
|
||||
* @return void|string JSON encoded in case of empty payload
|
||||
*/
|
||||
public function wp_ajax_et_builder_toggle_cloud_status() {
|
||||
et_core_security_check( 'edit_posts', 'et_builder_library_toggle_item_location', 'nonce' );
|
||||
$payload = isset( $_POST['payload'] ) ? (array) $_POST['payload'] : array(); // phpcs:ignore ET.Sniffs.ValidatedSanitizedInput -- $_POST['payload'] is an array, it's value sanitization is done at the time of accessing value.
|
||||
|
||||
if ( empty( $payload ) ) {
|
||||
wp_send_json_success();
|
||||
return;
|
||||
}
|
||||
|
||||
$item_id = (int) $payload['id'];
|
||||
|
||||
wp_delete_post( $item_id, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX Callback: Save the temp layout into database with the 'draft' status
|
||||
* Uses {@see et_pb_create_layout} to submit the library post
|
||||
*
|
||||
* @since 4.17.0
|
||||
*
|
||||
* @global $_POST['payload'] Array with the layout data to create.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function wp_ajax_et_builder_library_save_temp_layout() {
|
||||
et_core_security_check( 'edit_posts', 'et_fb_save_library_modules_nonce', 'nonce' );
|
||||
|
||||
$payload = isset( $_POST['payload'] ) ? (array) $_POST['payload'] : array(); // phpcs:ignore ET.Sniffs.ValidatedSanitizedInput -- $_POST['payload'] is an array, it's value sanitization is done at the time of accessing value.
|
||||
$is_draft = 'draft' === $payload['postStatus'];
|
||||
$name = sanitize_text_field( self::$_->array_get( $payload, 'itemName', '' ) );
|
||||
$content = self::$_->array_get( $payload, 'itemContent', '' );
|
||||
$prefix = esc_html__( 'Edit Cloud Item', 'et_builder' );
|
||||
$name = $is_draft ? $prefix . ': ' . $name : $name;
|
||||
$layout_type = self::$_->array_get( $payload, 'itemType', 'layout' );
|
||||
|
||||
$tax_input = array(
|
||||
'layout_type' => sanitize_text_field( $layout_type ),
|
||||
'module_width' => sanitize_text_field( self::$_->array_get( $payload, 'moduleWidth', 'regular' ) ),
|
||||
);
|
||||
|
||||
if ( 'row' === $layout_type ) {
|
||||
$meta_input['_et_pb_row_layout'] = $payload['rowLayout'];
|
||||
}
|
||||
|
||||
if ( 'module' === $layout_type && isset( $payload['moduleType'] ) ) {
|
||||
$meta_input['_et_pb_module_type'] = $payload['moduleType'];
|
||||
}
|
||||
|
||||
$meta_input['_et_pb_built_for_post_type'] = 'page';
|
||||
|
||||
$new_layout_id = et_pb_create_layout( $name, $content, $meta_input, $tax_input, '', '', $post_status = $payload['postStatus'] );
|
||||
|
||||
wp_send_json_success(
|
||||
array(
|
||||
'layoutId' => $new_layout_id,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX Callback: Removes temp layout from the website
|
||||
*
|
||||
* @since 4.17.0
|
||||
*
|
||||
* @global $_POST['payload'] Array with the layout id to remove.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function wp_ajax_et_builder_library_remove_temp_layout() {
|
||||
et_core_security_check( 'edit_posts', 'et_fb_remove_library_modules_nonce', 'nonce' );
|
||||
$post_id = isset( $_POST['post_id'] ) ? (int) $_POST['post_id'] : '';
|
||||
|
||||
$module_presets_manager = ET_Builder_Global_Presets_Settings::instance();
|
||||
$module_presets_manager->clear_temp_presets();
|
||||
|
||||
if ( 0 === $post_id ) {
|
||||
$library_layouts = ET_Builder_Post_Type_Layout::instance();
|
||||
|
||||
$draft_posts = $library_layouts->query()->run( array( 'post_status' => array( 'draft' ) ) );
|
||||
|
||||
if ( ! empty( $draft_posts ) ) {
|
||||
if ( is_array( $draft_posts ) ) {
|
||||
// Several posts were returned.
|
||||
foreach ( $draft_posts as $post ) {
|
||||
wp_delete_post( $post->ID, true );
|
||||
}
|
||||
} else {
|
||||
// Single post was returned.
|
||||
wp_delete_post( $draft_posts->ID, true );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wp_delete_post( $post_id, true );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX Callback: Removes temp presets from the website
|
||||
*
|
||||
* @since 4.17.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function wp_ajax_et_builder_library_clear_temp_presets() {
|
||||
et_core_security_check( 'edit_posts', 'et_fb_clear_temp_presets_nonce', 'nonce' );
|
||||
|
||||
$module_presets_manager = ET_Builder_Global_Presets_Settings::instance();
|
||||
$module_presets_manager->clear_temp_presets();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 'publish' string to set the post correct status for restored library items.
|
||||
*
|
||||
* @since 4.17.0
|
||||
*
|
||||
* @return string new post status.
|
||||
*/
|
||||
public static function et_builder_set_untrash_status() {
|
||||
return 'publish';
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX Callback: Upload thumbnail and assign it to specified post.
|
||||
*
|
||||
* @since 4.17.0
|
||||
*
|
||||
* @global $_FILES['imageFile'] File to upload.
|
||||
* @global $_POST['postId'] Post id to set thumbnail for.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function wp_ajax_et_builder_library_upload_thumbnail() {
|
||||
et_core_security_check( 'edit_posts', 'et_builder_library_update_layout', 'nonce' );
|
||||
|
||||
$post_id = isset( $_POST['postId'] ) ? (int) $_POST['postId'] : '';
|
||||
$image_url_raw = isset( $_POST['imageURL'] ) ? esc_url_raw( $_POST['imageURL'] ) : ''; // phpcs:ignore ET.Sniffs.ValidVariableName.VariableNotSnakeCase -- This is valid format for the property in the Cloud App.
|
||||
|
||||
// Upload and set featured image.
|
||||
if ( $image_url_raw && '' !== $image_url_raw ) {
|
||||
$upload = media_sideload_image( $image_url_raw, $post_id, $post_id, 'id' );
|
||||
|
||||
$attachment_id = is_wp_error( $upload ) ? 0 : $upload;
|
||||
$image_url = get_attached_file( $attachment_id );
|
||||
$image_metadata = wp_generate_attachment_metadata( $attachment_id, $image_url );
|
||||
|
||||
wp_update_attachment_metadata( $attachment_id, $image_metadata );
|
||||
|
||||
$result = set_post_thumbnail( $post_id, $attachment_id );
|
||||
|
||||
wp_send_json_success();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX Callback: Update the library item (layout/section/row/module). Following updates supported:
|
||||
* - Duplicate
|
||||
* - Edit Categories/Tags. New categories/tags can be created as well.
|
||||
* - Rename
|
||||
* - Toggle Favorite status
|
||||
* - Delete
|
||||
*
|
||||
* @since 4.17.0
|
||||
*
|
||||
* @global $_POST['payload'] Array with the update details.
|
||||
*
|
||||
* @return string JSON encoded with the updated item details and new terms (which could be created in Duplicate action)
|
||||
*/
|
||||
public function wp_ajax_et_builder_library_update_item() {
|
||||
et_core_security_check( 'edit_posts', 'et_builder_library_update_layout', 'nonce' );
|
||||
$payload = isset( $_POST['payload'] ) ? (array) $_POST['payload'] : array(); // phpcs:ignore ET.Sniffs.ValidatedSanitizedInput -- $_POST['payload'] is an array, it's value sanitization is done at the time of accessing value.
|
||||
|
||||
if ( empty( $payload ) ) {
|
||||
wp_send_json_success();
|
||||
return;
|
||||
}
|
||||
|
||||
$update_details = $payload['update_details'];
|
||||
$update_type = $update_details['updateType'];
|
||||
$item_id = intval( $payload['item_id'] );
|
||||
$new_id = '';
|
||||
$categories = empty( $update_details['itemCategories'] ) ? [] : array_unique( array_map( 'intval', $update_details['itemCategories'] ) );
|
||||
$tags = empty( $update_details['itemTags'] ) ? [] : array_unique( array_map( 'intval', $update_details['itemTags'] ) );
|
||||
$new_categories = array();
|
||||
$new_tags = array();
|
||||
|
||||
$item_update = array(
|
||||
'ID' => $item_id,
|
||||
);
|
||||
|
||||
if ( ! empty( $update_details['newCategoryName'] ) ) {
|
||||
$new_names_array = explode( ',', $update_details['newCategoryName'] );
|
||||
foreach ( $new_names_array as $new_name ) {
|
||||
if ( '' !== $new_name ) {
|
||||
$new_term = wp_insert_term( $new_name, 'layout_category' );
|
||||
|
||||
if ( ! is_wp_error( $new_term ) ) {
|
||||
$categories[] = $new_term['term_id'];
|
||||
|
||||
$new_categories[] = array(
|
||||
'name' => $new_name,
|
||||
'id' => $new_term['term_id'],
|
||||
'count' => 1,
|
||||
);
|
||||
} elseif ( ! empty( $new_term->error_data ) && ! empty( $new_term->error_data['term_exists'] ) ) {
|
||||
$categories[] = $new_term->error_data['term_exists'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $update_details['newTagName'] ) ) {
|
||||
$new_names_array = explode( ',', $update_details['newTagName'] );
|
||||
|
||||
foreach ( $new_names_array as $new_name ) {
|
||||
if ( '' !== $new_name ) {
|
||||
$new_term = wp_insert_term( $new_name, 'layout_tag' );
|
||||
|
||||
if ( ! is_wp_error( $new_term ) ) {
|
||||
$tags[] = $new_term['term_id'];
|
||||
|
||||
$new_tags[] = array(
|
||||
'name' => $new_name,
|
||||
'id' => $new_term['term_id'],
|
||||
'count' => 1,
|
||||
);
|
||||
} elseif ( ! empty( $new_term->error_data ) && ! empty( $new_term->error_data['term_exists'] ) ) {
|
||||
$tags[] = $new_term->error_data['term_exists'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch ( $update_type ) {
|
||||
case 'duplicate':
|
||||
case 'duplicate_and_delete':
|
||||
case 'duplicate_premade_item':
|
||||
$is_item_from_cloud = isset( $update_details['shortcode'] );
|
||||
$title = sanitize_text_field( $update_details['itemName'] );
|
||||
$meta_input = array();
|
||||
$item_thumbnail = false;
|
||||
|
||||
if ( $is_item_from_cloud ) {
|
||||
$content = $update_details['shortcode'];
|
||||
$built_for = 'page';
|
||||
$scope = ! empty( $update_details['global'] ) && 'on' === $update_details['global'] ? 'global' : 'non_global';
|
||||
$layout_type = isset( $update_details['layoutType'] ) ? sanitize_text_field( $update_details['layoutType'] ) : 'layout';
|
||||
$module_width = isset( $update_details['moduleWidth'] ) ? sanitize_text_field( $update_details['moduleWidth'] ) : 'regular';
|
||||
$favorite_status = isset( $update_details['favoriteStatus'] ) && 'on' === sanitize_text_field( $update_details['favoriteStatus'] ) ? 'favorite' : '';
|
||||
|
||||
if ( 'row' === $layout_type ) {
|
||||
$meta_input['_et_pb_row_layout'] = $update_details['rowLayout'];
|
||||
}
|
||||
|
||||
if ( 'module' === $layout_type ) {
|
||||
$meta_input['_et_pb_module_type'] = $update_details['moduleType'];
|
||||
}
|
||||
|
||||
if ( '' !== $favorite_status ) {
|
||||
$meta_input['favorite_status'] = $favorite_status;
|
||||
}
|
||||
} else {
|
||||
$content = get_the_content( null, false, $item_id );
|
||||
$built_for = get_post_meta( $item_id, '_et_pb_built_for_post_type', true );
|
||||
$module_width = wp_get_post_terms( $item_id, 'module_width', array( 'fields' => 'names' ) );
|
||||
$module_width = is_wp_error( $module_width ) ? 'regular' : sanitize_text_field( $module_width[0] );
|
||||
$layout_type = wp_get_post_terms( $item_id, 'layout_type', array( 'fields' => 'names' ) );
|
||||
$layout_type = is_wp_error( $layout_type ) || '' === $layout_type ? 'layout' : sanitize_text_field( $layout_type[0] );
|
||||
$item_thumbnail = get_post_thumbnail_id( $item_id );
|
||||
|
||||
if ( ! empty( $update_details['global'] ) ) {
|
||||
$scope = 'on' === $update_details['global'] ? 'global' : 'non_global';
|
||||
} else {
|
||||
$scope = wp_get_post_terms( $item_id, 'scope', array( 'fields' => 'names' ) );
|
||||
$scope = is_wp_error( $scope ) ? 'non_global' : sanitize_text_field( $scope[0] );
|
||||
}
|
||||
|
||||
if ( 'row' === $layout_type ) {
|
||||
$row_layout = get_post_meta( $item_id, '_et_pb_row_layout', true );
|
||||
|
||||
$meta_input['_et_pb_row_layout'] = $row_layout;
|
||||
}
|
||||
|
||||
if ( 'module' === $layout_type ) {
|
||||
$module_type = get_post_meta( $item_id, '_et_pb_module_type', true );
|
||||
|
||||
$meta_input['_et_pb_module_type'] = $module_type;
|
||||
}
|
||||
}
|
||||
|
||||
$meta_input['_et_pb_built_for_post_type'] = $built_for;
|
||||
|
||||
$new_item = array(
|
||||
'post_title' => $title,
|
||||
'post_content' => $content,
|
||||
'post_status' => 'publish',
|
||||
'post_type' => 'et_pb_layout',
|
||||
'tax_input' => array(
|
||||
'layout_category' => $categories,
|
||||
'layout_tag' => $tags,
|
||||
'layout_type' => $layout_type,
|
||||
'scope' => $scope,
|
||||
'module_width' => $module_width,
|
||||
),
|
||||
'meta_input' => $meta_input,
|
||||
);
|
||||
|
||||
$new_id = wp_insert_post( $new_item );
|
||||
|
||||
if ( $item_thumbnail ) {
|
||||
set_post_thumbnail( $new_id, $item_thumbnail );
|
||||
}
|
||||
break;
|
||||
case 'edit_cats':
|
||||
wp_set_object_terms( $item_id, $categories, 'layout_category' );
|
||||
wp_set_object_terms( $item_id, $tags, 'layout_tag' );
|
||||
break;
|
||||
case 'rename':
|
||||
$item_update['post_title'] = sanitize_text_field( $update_details['itemName'] );
|
||||
wp_update_post( $item_update );
|
||||
break;
|
||||
case 'toggle_fav':
|
||||
$favorite_status = 'on' === sanitize_text_field( $update_details['favoriteStatus'] ) ? 'favorite' : '';
|
||||
update_post_meta( $item_id, 'favorite_status', $favorite_status );
|
||||
|
||||
break;
|
||||
case 'delete':
|
||||
wp_trash_post( $item_id );
|
||||
break;
|
||||
case 'delete_permanently':
|
||||
wp_delete_post( $item_id, true );
|
||||
break;
|
||||
case 'restore':
|
||||
// wp_untrash_post() restores the post to `draft` by default, we have to set `publish` status via filter.
|
||||
add_filter( 'wp_untrash_post_status', array( 'ET_Builder_Library', 'et_builder_set_untrash_status' ) );
|
||||
wp_untrash_post( $item_id );
|
||||
remove_filter( 'wp_untrash_post_status', array( 'ET_Builder_Library', 'et_builder_set_untrash_status' ) );
|
||||
break;
|
||||
}
|
||||
|
||||
$processed_new_tags = array();
|
||||
$processed_new_cats = array();
|
||||
|
||||
$updated_tags = get_terms(
|
||||
array(
|
||||
'taxonomy' => 'layout_tag',
|
||||
'hide_empty' => false,
|
||||
)
|
||||
);
|
||||
|
||||
$updated_categories = get_terms(
|
||||
array(
|
||||
'taxonomy' => 'layout_category',
|
||||
'hide_empty' => false,
|
||||
)
|
||||
);
|
||||
|
||||
if ( ! empty( $updated_tags ) ) {
|
||||
foreach ( $updated_tags as $single_tag ) {
|
||||
$processed_new_tags[] = array(
|
||||
'name' => $single_tag->name,
|
||||
'id' => $single_tag->term_id,
|
||||
'count' => $single_tag->count,
|
||||
'location' => 'local',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $updated_categories ) ) {
|
||||
foreach ( $updated_categories as $single_category ) {
|
||||
$processed_new_cats[] = array(
|
||||
'name' => $single_category->name,
|
||||
'id' => $single_category->term_id,
|
||||
'count' => $single_category->count,
|
||||
'location' => 'local',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
wp_send_json_success(
|
||||
array(
|
||||
'updatedItem' => $item_id,
|
||||
'newItem' => $new_id,
|
||||
'updateType' => $update_type,
|
||||
'categories' => $categories,
|
||||
'tags' => $tags,
|
||||
'updatedTerms' => array(
|
||||
'categories' => $processed_new_cats,
|
||||
'tags' => $processed_new_tags,
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX Callback: Gets Cloud access token from DB and send it to client.
|
||||
*
|
||||
* @since 4.17.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function wp_ajax_et_builder_library_get_cloud_token() {
|
||||
et_core_security_check( 'edit_posts', 'et_builder_library_get_cloud_token', 'nonce' );
|
||||
|
||||
$access_token = get_transient( 'et_cloud_access_token' );
|
||||
|
||||
wp_send_json_success(
|
||||
array(
|
||||
'accessToken' => $access_token,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX Callback: Gets layouts data for the builder's library UI.
|
||||
*
|
||||
@ -1090,7 +1720,10 @@ class ET_Builder_Library {
|
||||
*/
|
||||
public function wp_ajax_et_builder_library_get_layouts_data() {
|
||||
et_core_security_check( 'edit_posts', 'et_builder_library_get_layouts_data', 'nonce' );
|
||||
wp_send_json_success( $this->builder_library_layouts_data() );
|
||||
|
||||
$library_type = isset( $_POST['et_library_type'] ) ? (string) sanitize_text_field( $_POST['et_library_type'] ) : 'layout';
|
||||
|
||||
wp_send_json_success( $this->builder_library_layouts_data( $library_type ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1125,6 +1758,86 @@ class ET_Builder_Library {
|
||||
wp_send_json_success();
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters out library tags and categories from Theme Builder settings.
|
||||
* These taxonomies are not available on Frontend and user shouldn't be able to select it.
|
||||
*
|
||||
* @param bool $initial_value original value.
|
||||
* @param object $taxonomy taxonomy to check.
|
||||
*
|
||||
* @since 4.17.0
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function tb_remove_unsupported_taxonomies( $initial_value, $taxonomy ) {
|
||||
if ( in_array( $taxonomy->name, array( 'layout_category', 'layout_tag' ), true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $initial_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue styles.
|
||||
*
|
||||
* @since 4.17.0
|
||||
*/
|
||||
public function enqueue_scripts() {
|
||||
// Enqueue resource for edit session expire page.
|
||||
if ( $this->vb_is_editing_session_expired() ) {
|
||||
et_core_register_admin_assets();
|
||||
|
||||
wp_enqueue_style( 'et-core-admin' );
|
||||
wp_enqueue_script( 'et-core-admin' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render modal to display a message when editing session expire.
|
||||
*
|
||||
* @since 4.17.0
|
||||
*/
|
||||
public function render_session_expired_modal() {
|
||||
if ( ! $this->vb_is_editing_session_expired() ) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<div class="et-core-modal-overlay et-builder-session-expired-modal et-core-active">
|
||||
<div class="et-core-modal">
|
||||
<div class="et-core-modal-header">
|
||||
<h3 class="et-core-modal-title">
|
||||
<?php esc_html_e( 'Session Expired', 'et_builder' ); ?>
|
||||
</h3>
|
||||
<a href="#" class="et-core-modal-close" data-et-core-modal="close"></a>
|
||||
</div>
|
||||
<div id="et-builder-session-expired-modal-content">
|
||||
<div class="et-core-modal-content">
|
||||
<p>
|
||||
<?php
|
||||
esc_html_e( 'Your Cloud item editing session has expired.', 'et_builder' );
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
<a class="et-core-modal-action" href="#" data-et-core-modal="close">
|
||||
<?php esc_html_e( 'Close', 'et_builder' ); ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether editing session is expired.
|
||||
*
|
||||
* @since 4.17.0
|
||||
*/
|
||||
public function vb_is_editing_session_expired() {
|
||||
global $wp_query;
|
||||
// phpcs:ignore WordPress.Security.NonceVerification -- This function does not change any state, and is therefore not susceptible to CSRF.
|
||||
return $wp_query->is_404() && isset( $_GET['cloudItem'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues library-related styles and scripts in the admin.
|
||||
* {@see 'admin_enqueue_scripts'}
|
||||
|
Reference in New Issue
Block a user