array( 'name' => esc_html__( 'Theme Builders', 'et_builder' ), 'singular_name' => esc_html__( 'Theme Builder', 'et_builder' ), 'add_new' => esc_html__( 'Add New', 'et_builder' ), 'add_new_item' => esc_html__( 'Add New Theme Builder', 'et_builder' ), 'edit_item' => esc_html__( 'Edit Theme Builder', 'et_builder' ), 'new_item' => esc_html__( 'New Theme Builder', 'et_builder' ), 'all_items' => esc_html__( 'All Theme Builders', 'et_builder' ), 'view_item' => esc_html__( 'View Theme Builder', 'et_builder' ), 'search_items' => esc_html__( 'Search Theme Builders', 'et_builder' ), 'not_found' => esc_html__( 'Nothing found', 'et_builder' ), 'not_found_in_trash' => esc_html__( 'Nothing found in Trash', 'et_builder' ), 'parent_item_colon' => '', ), 'can_export' => false, 'capability_type' => 'post', 'has_archive' => false, 'hierarchical' => false, 'map_meta_cap' => true, 'public' => false, 'publicly_queryable' => false, 'query_var' => false, 'show_ui' => false, 'show_in_rest' => false, 'rewrite' => true, 'supports' => array( 'title', 'author' ), ) ); register_post_type( ET_THEME_BUILDER_TEMPLATE_POST_TYPE, array( 'labels' => array( 'name' => esc_html__( 'Templates', 'et_builder' ), 'singular_name' => esc_html__( 'Template', 'et_builder' ), 'add_new' => esc_html__( 'Add New', 'et_builder' ), 'add_new_item' => esc_html__( 'Add New Template', 'et_builder' ), 'edit_item' => esc_html__( 'Edit Template', 'et_builder' ), 'new_item' => esc_html__( 'New Template', 'et_builder' ), 'all_items' => esc_html__( 'All Templates', 'et_builder' ), 'view_item' => esc_html__( 'View Template', 'et_builder' ), 'search_items' => esc_html__( 'Search Templates', 'et_builder' ), 'not_found' => esc_html__( 'Nothing found', 'et_builder' ), 'not_found_in_trash' => esc_html__( 'Nothing found in Trash', 'et_builder' ), 'parent_item_colon' => '', ), 'can_export' => true, 'capability_type' => 'post', 'has_archive' => false, 'hierarchical' => false, 'map_meta_cap' => true, 'public' => false, 'publicly_queryable' => $publicly_queryable, 'query_var' => false, 'show_ui' => false, 'show_in_rest' => false, 'rewrite' => true, 'supports' => array( 'title', 'author' ), ) ); register_post_type( ET_THEME_BUILDER_HEADER_LAYOUT_POST_TYPE, array( 'labels' => array( 'name' => esc_html__( 'Header Templates', 'et_builder' ), 'singular_name' => esc_html__( 'Header Template', 'et_builder' ), 'add_new' => esc_html__( 'Add New', 'et_builder' ), 'add_new_item' => esc_html__( 'Add New Header Template', 'et_builder' ), 'edit_item' => esc_html__( 'Edit Header Template', 'et_builder' ), 'new_item' => esc_html__( 'New Header Template', 'et_builder' ), 'all_items' => esc_html__( 'All Header Templates', 'et_builder' ), 'view_item' => esc_html__( 'View Header Template', 'et_builder' ), 'search_items' => esc_html__( 'Search Header Templates', 'et_builder' ), 'not_found' => esc_html__( 'Nothing found', 'et_builder' ), 'not_found_in_trash' => esc_html__( 'Nothing found in Trash', 'et_builder' ), 'parent_item_colon' => '', ), 'can_export' => true, 'capability_type' => 'post', 'has_archive' => false, 'hierarchical' => false, 'map_meta_cap' => true, 'public' => false, 'publicly_queryable' => $publicly_queryable, 'query_var' => false, 'show_ui' => false, 'show_in_rest' => false, 'rewrite' => true, 'supports' => array( 'title', 'editor', 'author', 'revisions', 'comments' ), ) ); register_post_type( ET_THEME_BUILDER_BODY_LAYOUT_POST_TYPE, array( 'labels' => array( 'name' => esc_html__( 'Body Templates', 'et_builder' ), 'singular_name' => esc_html__( 'Body Template', 'et_builder' ), 'add_new' => esc_html__( 'Add New', 'et_builder' ), 'add_new_item' => esc_html__( 'Add New Body Template', 'et_builder' ), 'edit_item' => esc_html__( 'Edit Body Template', 'et_builder' ), 'new_item' => esc_html__( 'New Body Template', 'et_builder' ), 'all_items' => esc_html__( 'All Body Templates', 'et_builder' ), 'view_item' => esc_html__( 'View Body Template', 'et_builder' ), 'search_items' => esc_html__( 'Search Body Templates', 'et_builder' ), 'not_found' => esc_html__( 'Nothing found', 'et_builder' ), 'not_found_in_trash' => esc_html__( 'Nothing found in Trash', 'et_builder' ), 'parent_item_colon' => '', ), 'can_export' => true, 'capability_type' => 'post', 'has_archive' => false, 'hierarchical' => false, 'map_meta_cap' => true, 'public' => false, 'publicly_queryable' => $publicly_queryable, 'query_var' => false, 'show_ui' => false, 'show_in_rest' => false, 'rewrite' => true, 'supports' => array( 'title', 'editor', 'author', 'revisions', 'comments' ), ) ); register_post_type( ET_THEME_BUILDER_FOOTER_LAYOUT_POST_TYPE, array( 'labels' => array( 'name' => esc_html__( 'Footer Templates', 'et_builder' ), 'singular_name' => esc_html__( 'Footer Template', 'et_builder' ), 'add_new' => esc_html__( 'Add New', 'et_builder' ), 'add_new_item' => esc_html__( 'Add New Footer Template', 'et_builder' ), 'edit_item' => esc_html__( 'Edit Footer Template', 'et_builder' ), 'new_item' => esc_html__( 'New Footer Template', 'et_builder' ), 'all_items' => esc_html__( 'All Footer Templates', 'et_builder' ), 'view_item' => esc_html__( 'View Footer Template', 'et_builder' ), 'search_items' => esc_html__( 'Search Footer Templates', 'et_builder' ), 'not_found' => esc_html__( 'Nothing found', 'et_builder' ), 'not_found_in_trash' => esc_html__( 'Nothing found in Trash', 'et_builder' ), 'parent_item_colon' => '', ), 'can_export' => true, 'capability_type' => 'post', 'has_archive' => false, 'hierarchical' => false, 'map_meta_cap' => true, 'public' => false, 'publicly_queryable' => $publicly_queryable, 'query_var' => false, 'show_ui' => false, 'show_in_rest' => false, 'rewrite' => true, 'supports' => array( 'title', 'editor', 'author', 'revisions', 'comments' ), ) ); } add_action( 'init', 'et_theme_builder_register_entities', 11 ); /** * Get array of post types that can be layouts within templates. * * @since 4.0 * * @return string[] */ function et_theme_builder_get_layout_post_types() { return array( ET_THEME_BUILDER_HEADER_LAYOUT_POST_TYPE, ET_THEME_BUILDER_BODY_LAYOUT_POST_TYPE, ET_THEME_BUILDER_FOOTER_LAYOUT_POST_TYPE, ); } /** * Convert 'header', 'body', 'footer' to the appropriate layout post type name. * * @since 4.0 * * @param string $layout_type * * @return string */ function et_theme_builder_get_valid_layout_post_type( $layout_type ) { $map = array( 'header' => ET_THEME_BUILDER_HEADER_LAYOUT_POST_TYPE, 'body' => ET_THEME_BUILDER_BODY_LAYOUT_POST_TYPE, 'footer' => ET_THEME_BUILDER_FOOTER_LAYOUT_POST_TYPE, ); if ( ! isset( $map[ $layout_type ] ) ) { return ''; } return $map[ $layout_type ]; } /** * Get whether post type is a Theme Builder layout type. * * @since 4.0 * * @param string $post_type * * @return boolean */ function et_theme_builder_is_layout_post_type( $post_type ) { return in_array( $post_type, et_theme_builder_get_layout_post_types(), true ); } /** * Get list of post content module slugs. * * @since 4.0 * * @return string[] */ function et_theme_builder_get_post_content_modules() { return array( 'et_pb_post_content', 'et_pb_fullwidth_post_content' ); } /** * Filter post types with builder support by default. * * @since 4.0 * * @param $post_types * * @return array */ function et_theme_builder_filter_builder_default_post_types( $post_types ) { return array_merge( $post_types, et_theme_builder_get_layout_post_types() ); } add_filter( 'et_builder_default_post_types', 'et_theme_builder_filter_builder_default_post_types' ); add_filter( 'et_library_builder_post_types', 'et_theme_builder_filter_builder_default_post_types' ); /** * Filter post types which should be blocklisted from appearing as options when enabling/disabling the builder. * * @param $post_types * * @return array */ function et_theme_builder_filter_builder_post_type_options_blocklist( $post_types ) { return array_merge( $post_types, et_theme_builder_get_layout_post_types(), array( ET_THEME_BUILDER_TEMPLATE_POST_TYPE ) ); } add_filter( 'et_builder_post_type_options_blocklist', 'et_theme_builder_filter_builder_default_post_types' ); /** * Filter builder status for template area posts. * * @since 4.0 * * @param $enabled * @param $post_id * * @return bool */ function et_theme_builder_filter_enable_builder_for_post_types( $enabled, $post_id ) { $post_type = get_post_type( $post_id ); if ( et_theme_builder_is_layout_post_type( $post_type ) ) { $enabled = true; } return $enabled; } add_filter( 'et_builder_fb_enabled_for_post', 'et_theme_builder_filter_enable_builder_for_post_types', 10, 2 ); /** * Get the theme builder post. * * @since 4.0 * * @param boolean $live Get the live version or the draft one. * @param boolean $create Create the post if it does not exist. * * @return integer */ function et_theme_builder_get_theme_builder_post_id( $live, $create = true ) { $status = $live ? 'publish' : 'auto-draft'; $query = new WP_Query( array( 'post_type' => ET_THEME_BUILDER_THEME_BUILDER_POST_TYPE, 'post_status' => $status, 'posts_per_page' => 1, 'orderby' => 'date', 'order' => 'desc', 'fields' => 'ids', 'no_found_rows' => true, 'update_post_meta_cache' => false, 'update_post_term_cache' => false, ) ); if ( ! empty( $query->posts ) ) { return $query->posts[0]; } if ( ! $create ) { return 0; } $post_id = wp_insert_post( array( 'post_type' => ET_THEME_BUILDER_THEME_BUILDER_POST_TYPE, 'post_status' => $status, 'post_title' => 'Theme Builder', ) ); return $post_id; } /** * Get the theme builder post's template IDs. * * @since 4.0 * * @param boolean $live Get the live version or the draft one. * * @return integer[] */ function et_theme_builder_get_theme_builder_template_ids( $live ) { $post_id = et_theme_builder_get_theme_builder_post_id( $live, false ); // Try to get the template Ids from the backup. // that maybe stored during saving templates process. // @see et_theme_builder_api_save function. $template_ids = get_option( 'et_tb_templates_backup_' . $post_id, false ); // If there is no backup available, then query the post meta. if ( false === $template_ids ) { $template_ids = get_post_meta( $post_id, '_et_template', false ); } $template_ids = is_array( $template_ids ) ? $template_ids : array(); $template_ids = array_map( 'intval', $template_ids ); return $template_ids; } /** * Get the theme builder post's templates. * * @since 4.0 * * @param boolean $live Get the live version or the draft one. * * @return array */ function et_theme_builder_get_theme_builder_templates( $live ) { return array_filter( array_map( 'et_theme_builder_get_template', et_theme_builder_get_theme_builder_template_ids( $live ) ) ); } /** * Get a template. * Returns an empty array if the template is not found. * * @since 4.0 * * @param integer $template_id * * @return array */ function et_theme_builder_get_template( $template_id ) { $post = get_post( $template_id ); if ( null === $post || ET_THEME_BUILDER_TEMPLATE_POST_TYPE !== $post->post_type ) { return array(); } $autogenerated_title = '1' === get_post_meta( $template_id, '_et_autogenerated_title', true ); $header_id = (int) get_post_meta( $post->ID, '_et_header_layout_id', true ); $header_enabled = get_post_meta( $post->ID, '_et_header_layout_enabled', true ) === '1'; $body_id = (int) get_post_meta( $post->ID, '_et_body_layout_id', true ); $body_enabled = get_post_meta( $post->ID, '_et_body_layout_enabled', true ) === '1'; $footer_id = (int) get_post_meta( $post->ID, '_et_footer_layout_id', true ); $footer_enabled = get_post_meta( $post->ID, '_et_footer_layout_enabled', true ) === '1'; $use_on = get_post_meta( $post->ID, '_et_use_on', false ); $exclude_from = get_post_meta( $post->ID, '_et_exclude_from', false ); return array( 'id' => $post->ID, 'default' => get_post_meta( $post->ID, '_et_default', true ) === '1', 'enabled' => get_post_meta( $post->ID, '_et_enabled', true ) === '1', 'title' => $autogenerated_title ? '' : $post->post_title, 'layouts' => array( 'header' => array( 'id' => $header_id, 'enabled' => $header_enabled, 'override' => 0 !== $header_id || false === $header_enabled, ), 'body' => array( 'id' => $body_id, 'enabled' => $body_enabled, 'override' => 0 !== $body_id || false === $body_enabled, ), 'footer' => array( 'id' => $footer_id, 'enabled' => $footer_enabled, 'override' => 0 !== $footer_id || false === $footer_enabled, ), ), 'use_on' => is_array( $use_on ) ? $use_on : array(), 'exclude_from' => is_array( $exclude_from ) ? $exclude_from : array(), ); } /** * Trash the theme builder draft and any unused theme builder templates and layouts. * * @since 4.0 * * @return void */ function et_theme_builder_trash_draft_and_unused_posts() { $mark_meta_key = '_et_theme_builder_marked_as_unused'; $live_id = et_theme_builder_get_theme_builder_post_id( true, false ); $draft_id = et_theme_builder_get_theme_builder_post_id( false, false ); if ( $draft_id > 0 ) { wp_trash_post( $draft_id ); } $used_templates = get_post_meta( $live_id, '_et_template', false ); $used_templates = is_array( $used_templates ) ? array_map( 'intval', $used_templates ) : array(); $used_posts = array(); foreach ( $used_templates as $template_id ) { $used_posts[] = $template_id; $used_posts[] = (int) get_post_meta( $template_id, '_et_header_layout_id', true ); $used_posts[] = (int) get_post_meta( $template_id, '_et_body_layout_id', true ); $used_posts[] = (int) get_post_meta( $template_id, '_et_footer_layout_id', true ); } $used_posts = array_filter( $used_posts ); // Unmark all used posts. foreach ( $used_posts as $post_id ) { delete_post_meta( $post_id, $mark_meta_key ); } // Mark unreferenced layouts for trashing. $posts_to_mark = new WP_Query( array( 'post_type' => array( 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, ), 'post__not_in' => $used_posts, 'posts_per_page' => -1, 'fields' => 'ids', 'meta_query' => array( array( 'key' => $mark_meta_key, 'compare' => 'NOT EXISTS', 'value' => 'https://core.trac.wordpress.org/ticket/23268', ), ), 'no_found_rows' => true, 'update_post_meta_cache' => false, 'update_post_term_cache' => false, ) ); foreach ( $posts_to_mark->posts as $post_id ) { update_post_meta( $post_id, $mark_meta_key, date( 'Y-m-d H:i:s' ) ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date -- No need to use gmdate. } // Trash any posts marked more than 7 days ago. // We only trash up to 50 posts at a time in order to avoid performance issues. // Any leftover posts will be cleaned up eventually whenever this is called again. $posts_to_trash = new WP_Query( array( 'post_type' => array( 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, ), 'posts_per_page' => 50, 'fields' => 'ids', 'meta_query' => array( array( 'key' => $mark_meta_key, 'compare' => '<', 'value' => date( 'Y-m-d H:i:s', time() - 60 * 60 * 24 * 7 ), // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date -- No need to use gmdate. 'type' => 'DATE', ), ), 'no_found_rows' => true, 'update_post_meta_cache' => false, 'update_post_term_cache' => false, ) ); foreach ( $posts_to_trash->posts as $post_id ) { wp_trash_post( $post_id ); } } /** * Get the template settings options for a given post type. * * @since 4.0 * * @param string $post_type_name * * @return array */ function et_theme_builder_get_template_settings_options_for_post_type( $post_type_name ) { $post_type = get_post_type_object( $post_type_name ); if ( null === $post_type ) { return array(); } $post_type_plural = ucwords( $post_type->labels->name ); $taxonomies = get_object_taxonomies( $post_type_name, 'objects' ); $group = array( 'label' => et_core_intentionally_unescaped( $post_type_plural, 'react_jsx' ), 'settings' => array( array( 'id' => implode( ET_THEME_BUILDER_SETTING_SEPARATOR, array( 'singular', 'post_type', $post_type_name, 'all' ) ), // Translators: %1$s: Post type plural name. 'label' => et_core_intentionally_unescaped( sprintf( __( 'All %1$s', 'et_builder' ), $post_type_plural ), 'react_jsx' ), 'priority' => 70, 'validate' => 'et_theme_builder_template_setting_validate_singular_post_type_all', ), ), ); if ( 'page' === $post_type_name ) { $group['settings'][] = array( 'id' => 'homepage', 'label' => et_core_intentionally_unescaped( __( 'Homepage', 'et_builder' ), 'react_jsx' ), 'priority' => 110, 'validate' => 'et_theme_builder_template_setting_validate_homepage', ); } elseif ( 'post' === $post_type_name || $post_type->has_archive ) { $group['settings'][] = array( 'id' => implode( ET_THEME_BUILDER_SETTING_SEPARATOR, array( 'archive', 'post_type', $post_type_name ) ), 'label' => 'post' === $post_type_name ? et_core_intentionally_unescaped( __( 'Blog', 'et_builder' ), 'react_jsx' ) // Translators: %1$s: Post type plural name. : et_core_intentionally_unescaped( sprintf( __( '%1$s Archive Page', 'et_builder' ), $post_type_plural ), 'react_jsx' ), 'title' => trim( str_replace( home_url(), '', get_post_type_archive_link( $post_type_name ) ), '/' ), 'priority' => 60, 'validate' => 'et_theme_builder_template_setting_validate_archive_post_type', ); } foreach ( $taxonomies as $taxonomy ) { /** * Filters whether the given taxonomy should be used to generate the following template settings: * - Posts with Specific % * * @since 4.3.3 * * @param boolean $show */ $show = apply_filters( 'et_theme_builder_template_settings_options_posts_with_specific_term', $taxonomy->show_ui ); if ( ! $show ) { continue; } $taxonomy_plural = ucwords( $taxonomy->labels->name ); $use_short_plural = in_array( $taxonomy->name, array( 'project_category', 'project_tag', 'product_cat', 'product_tag', ), true ); // Translators: %1$s: Post type plural name; %2$s: Taxonomy plural name. $label = et_core_intentionally_unescaped( sprintf( __( '%1$s with Specific %2$s', 'et_builder' ), $post_type_plural, $use_short_plural ? esc_html__( 'Tags', 'et_builder' ) : $taxonomy_plural ), 'react_jsx' ); if ( in_array( $taxonomy->name, array( 'category', 'project_category', 'product_cat' ), true ) ) { // Translators: %1$s: Post type plural name; %2$s: Taxonomy plural name. $label = et_core_intentionally_unescaped( sprintf( __( '%1$s in Specific %2$s', 'et_builder' ), $post_type_plural, $use_short_plural ? esc_html__( 'Categories', 'et_builder' ) : $taxonomy_plural ), 'react_jsx' ); } $group['settings'][] = array( 'id' => implode( ET_THEME_BUILDER_SETTING_SEPARATOR, array( 'singular', 'taxonomy', $taxonomy->name, 'term', 'id', '' ) ), // Translators: %1$s: Post type plural name; %2$s: Taxonomy plural name. 'label' => $label, 'priority' => 80, 'validate' => 'et_theme_builder_template_setting_validate_singular_taxonomy_term_id', 'options' => array( 'label' => $taxonomy_plural, 'type' => 'taxonomy', 'value' => $taxonomy->name, ), ); } $group['settings'][] = array( 'id' => implode( ET_THEME_BUILDER_SETTING_SEPARATOR, array( 'singular', 'post_type', $post_type_name, 'id', '' ) ), // Translators: %1$s: Post type plural name. 'label' => et_core_intentionally_unescaped( sprintf( __( 'Specific %1$s', 'et_builder' ), $post_type_plural ), 'react_jsx' ), 'priority' => 100, 'validate' => 'et_theme_builder_template_setting_validate_singular_post_type_id', 'options' => array( 'label' => $post_type_plural, 'type' => 'post_type', 'value' => $post_type_name, ), ); if ( is_post_type_hierarchical( $post_type_name ) ) { $group['settings'][] = array( 'id' => implode( ET_THEME_BUILDER_SETTING_SEPARATOR, array( 'singular', 'post_type', $post_type_name, 'children', 'id', '' ) ), // Translators: %1$s: Post type plural name. 'label' => et_core_intentionally_unescaped( sprintf( __( 'Children of Specific %1$s', 'et_builder' ), $post_type_plural ), 'react_jsx' ), 'priority' => 90, 'validate' => 'et_theme_builder_template_setting_validate_singular_post_type_children_id', 'options' => array( 'label' => $post_type_plural, 'type' => 'post_type', 'value' => $post_type_name, ), ); } return $group; } /** * Get the template settings options for all archive pages. * * @since 4.0 * * @return array */ function et_theme_builder_get_template_settings_options_for_archive_pages() { $taxonomies = get_taxonomies( array( 'public' => true, 'show_ui' => true, '_builtin' => false, ), 'objects' ); ksort( $taxonomies ); $taxonomies = array_merge( array( 'category' => get_taxonomy( 'category' ), 'post_tag' => get_taxonomy( 'post_tag' ), ), $taxonomies ); $group = array( 'label' => et_core_intentionally_unescaped( __( 'Archive Pages', 'et_builder' ), 'react_jsx' ), 'settings' => array( array( 'id' => implode( ET_THEME_BUILDER_SETTING_SEPARATOR, array( 'archive', 'all' ) ), 'label' => et_core_intentionally_unescaped( __( 'All Archive Pages', 'et_builder' ), 'react_jsx' ), 'priority' => 30, 'validate' => 'et_theme_builder_template_setting_validate_archive_all', ), ), ); foreach ( $taxonomies as $taxonomy ) { /** * Filters whether the given taxonomy should be used to generate the following template settings: * - All % Pages * - Specific % Pages * * @since 4.3.3 * * @param boolean $show */ $show = apply_filters( 'et_theme_builder_template_settings_options_term_pages', $taxonomy->public && $taxonomy->show_ui ); if ( ! $show ) { continue; } $taxonomy_plural = ucwords( $taxonomy->labels->name ); $taxonomy_name = $taxonomy_plural; if ( 'product_cat' === $taxonomy->name ) { // WooCommerce registers Product Categories with a singular name of Category instead of Product Category... $taxonomy_name = __( 'Product Category', 'et_builder' ); } elseif ( false !== strpos( $taxonomy->name, 'cat' ) ) { // Use singular for Category. $taxonomy_name = ucwords( $taxonomy->labels->singular_name ); } $group['settings'][] = array( 'id' => implode( ET_THEME_BUILDER_SETTING_SEPARATOR, array( 'archive', 'taxonomy', $taxonomy->name, 'all' ) ), // Translators: %1$s: Taxonomy name. 'label' => et_core_intentionally_unescaped( sprintf( __( 'All %1$s Pages', 'et_builder' ), $taxonomy_name ), 'react_jsx' ), 'priority' => 70, 'validate' => 'et_theme_builder_template_setting_validate_archive_taxonomy_all', ); $group['settings'][] = array( 'id' => implode( ET_THEME_BUILDER_SETTING_SEPARATOR, array( 'archive', 'taxonomy', $taxonomy->name, 'term', 'id', '' ) ), // Translators: %1$s: Taxonomy name. 'label' => et_core_intentionally_unescaped( sprintf( __( 'Specific %1$s Pages', 'et_builder' ), $taxonomy_name ), 'react_jsx' ), 'priority' => 75, 'validate' => 'et_theme_builder_template_setting_validate_archive_taxonomy_term_id', 'options' => array( 'label' => $taxonomy_plural, 'type' => 'taxonomy', 'value' => $taxonomy->name, ), ); } $group['settings'][] = array( 'id' => implode( ET_THEME_BUILDER_SETTING_SEPARATOR, array( 'archive', 'user', 'all' ) ), 'label' => et_core_intentionally_unescaped( __( 'All Author Pages', 'et_builder' ), 'react_jsx' ), 'priority' => 50, 'validate' => 'et_theme_builder_template_setting_validate_archive_user_all', ); $group['settings'][] = array( 'id' => implode( ET_THEME_BUILDER_SETTING_SEPARATOR, array( 'archive', 'user', 'id', '' ) ), 'label' => et_core_intentionally_unescaped( __( 'Specific Author Page', 'et_builder' ), 'react_jsx' ), 'priority' => 55, 'validate' => 'et_theme_builder_template_setting_validate_archive_user_id', 'options' => array( 'label' => et_core_intentionally_unescaped( __( 'Users', 'et_builder' ), 'react_jsx' ), 'type' => 'user', 'value' => '', ), ); $group['settings'][] = array( 'id' => implode( ET_THEME_BUILDER_SETTING_SEPARATOR, array( 'archive', 'user', 'role', '' ) ), 'label' => et_core_intentionally_unescaped( __( 'Specific Author Page By Role', 'et_builder' ), 'react_jsx' ), 'priority' => 53, 'validate' => 'et_theme_builder_template_setting_validate_archive_user_role', 'options' => array( 'label' => et_core_intentionally_unescaped( __( 'Roles', 'et_builder' ), 'react_jsx' ), 'type' => 'user_role', 'value' => '', ), ); $group['settings'][] = array( 'id' => implode( ET_THEME_BUILDER_SETTING_SEPARATOR, array( 'archive', 'date', 'all' ) ), 'label' => et_core_intentionally_unescaped( __( 'All Date Pages', 'et_builder' ), 'react_jsx' ), 'priority' => 40, 'validate' => 'et_theme_builder_template_setting_validate_archive_date_all', ); $_utils = ET_Core_Data_Utils::instance(); // Order settings alphabetically by label. $group['settings'] = $_utils->array_sort_by( $group['settings'], 'label' ); return $group; } /** * Get array of template setting options. * Settings that have children should have a trailing ET_THEME_BUILDER_SETTING_SEPARATOR in their id. * Settings that have children should have their id be unique even without the trailing ET_THEME_BUILDER_SETTING_SEPARATOR. * * @since 4.0 * * @return array */ function et_theme_builder_get_template_settings_options() { $post_types = get_post_types( array( 'public' => true, '_builtin' => false, ) ); sort( $post_types ); $options = array( 'page' => et_theme_builder_get_template_settings_options_for_post_type( 'page' ), 'post' => et_theme_builder_get_template_settings_options_for_post_type( 'post' ), 'archive' => et_theme_builder_get_template_settings_options_for_archive_pages(), ); foreach ( $post_types as $post_type_name ) { $options[ $post_type_name ] = et_theme_builder_get_template_settings_options_for_post_type( $post_type_name ); } $options['other'] = array( 'label' => et_core_intentionally_unescaped( __( 'Other', 'et_builder' ), 'react_jsx' ), 'settings' => array( array( 'id' => 'search', 'label' => et_core_intentionally_unescaped( __( 'Search Results', 'et_builder' ), 'react_jsx' ), 'priority' => 1, 'validate' => 'et_theme_builder_template_setting_validate_search', ), array( 'id' => '404', 'label' => et_core_intentionally_unescaped( __( '404 Page', 'et_builder' ), 'react_jsx' ), 'priority' => 1, 'validate' => 'et_theme_builder_template_setting_validate_404', ), ), ); /** * Filters available template settings options. * * @since 4.0 * * @param array */ $options = apply_filters( 'et_theme_builder_template_settings_options', $options ); return $options; } /** * Get flat array of template setting options from the current live and draft theme builder posts. * * @since 4.0 * * @return array[] */ function et_theme_builder_get_template_settings_options_for_preloading() { $templates = array_unique( array_merge( et_theme_builder_get_theme_builder_template_ids( true ), et_theme_builder_get_theme_builder_template_ids( false ) ) ); $setting_ids = array(); foreach ( $templates as $template_id ) { $use_on = get_post_meta( $template_id, '_et_use_on', false ); $exclude_from = get_post_meta( $template_id, '_et_exclude_from', false ); if ( ! is_array( $use_on ) ) { $use_on = array(); } if ( ! is_array( $exclude_from ) ) { $exclude_from = array(); } $setting_ids = array_merge( $setting_ids, $use_on, $exclude_from ); } return et_theme_builder_load_template_setting_options( array_unique( $setting_ids ) ); } /** * Sanitize an array of use_on/exclude_from conditions stripping out invalid ones. * * @since 4.0 * * @param string[] $setting_ids * * @return string[] */ function et_theme_builder_load_template_setting_options( $setting_ids ) { $flat_parent_settings = et_theme_builder_get_flat_template_settings_options(); $groups = array(); foreach ( $setting_ids as $setting_id ) { $parent_id = explode( ET_THEME_BUILDER_SETTING_SEPARATOR, $setting_id ); $entity_id = implode( '', array_slice( $parent_id, -1 ) ); $parent_id = array_slice( $parent_id, 0, -1 ); $parent_id = implode( ET_THEME_BUILDER_SETTING_SEPARATOR, $parent_id ) . ET_THEME_BUILDER_SETTING_SEPARATOR; if ( ! isset( $flat_parent_settings[ $parent_id ] ) ) { // Top-level, invalid or unknown setting. continue; } if ( ! isset( $groups[ $parent_id ] ) ) { $groups[ $parent_id ] = array( 'parent' => $flat_parent_settings[ $parent_id ], 'settings' => array(), ); } $groups[ $parent_id ]['settings'][ $setting_id ] = $entity_id; } $settings = array(); foreach ( $groups as $parent_id => $group ) { $settings = array_merge( $settings, et_theme_builder_get_template_setting_child_options( $group['parent'], $group['settings'] ) ); } return $settings; } /** * Get a flat array of template setting options. * * @since 4.0 * * @return array */ function et_theme_builder_get_flat_template_settings_options() { $settings = et_theme_builder_get_template_settings_options(); $flat = array(); foreach ( $settings as $group ) { foreach ( $group['settings'] as $setting ) { $flat[ $setting['id'] ] = $setting; } } return $flat; } function et_theme_builder_get_template_setting_child_options( $parent, $include = array(), $search = '', $page = 1, $per_page = 30 ) { $include = array_map( 'intval', $include ); if ( ! empty( $include ) ) { $search = ''; $page = 1; $per_page = -1; } $page = $page >= 1 ? $page : 1; $values = array(); /** * Fires before loading child options from the database. * * @since 4.2 * * @param string $parent_id * @param string $child_type * @param string $child_value */ do_action( 'et_theme_builder_before_get_template_setting_child_options', $parent['id'], $parent['options']['type'], $parent['options']['value'] ); switch ( $parent['options']['type'] ) { case 'post_type': $posts = get_posts( array( 'post_type' => $parent['options']['value'], 'post_status' => 'any', 'post__in' => $include, 's' => $search, 'posts_per_page' => $per_page, 'paged' => $page, ) ); foreach ( $posts as $post ) { $id = $parent['id'] . $post->ID; $values[ $id ] = array( 'id' => $id, 'parent' => $parent['id'], 'label' => et_core_intentionally_unescaped( $post->post_title, 'react_jsx' ), 'title' => et_core_intentionally_unescaped( $post->post_name, 'react_jsx' ), 'priority' => $parent['priority'], 'validate' => $parent['validate'], ); } break; case 'taxonomy': $terms = get_terms( array( 'taxonomy' => $parent['options']['value'], 'hide_empty' => false, 'include' => $include, 'search' => $search, 'number' => -1 === $per_page ? false : $per_page, 'offset' => -1 !== $per_page ? ( $page - 1 ) * $per_page : 0, ) ); foreach ( $terms as $term ) { $id = $parent['id'] . $term->term_id; $values[ $id ] = array( 'id' => $id, 'parent' => $parent['id'], 'label' => et_core_intentionally_unescaped( $term->name, 'react_jsx' ), 'title' => et_core_intentionally_unescaped( $term->slug, 'react_jsx' ), 'priority' => $parent['priority'], 'validate' => $parent['validate'], ); } break; case 'user': $users = get_users( array( 'include' => $include, 'search' => $search, 'number' => $per_page, 'paged' => $page, ) ); foreach ( $users as $user ) { $id = $parent['id'] . $user->ID; $values[ $id ] = array( 'id' => $id, 'parent' => $parent['id'], 'label' => et_core_intentionally_unescaped( $user->display_name, 'react_jsx' ), 'title' => et_core_intentionally_unescaped( $user->user_login, 'react_jsx' ), 'priority' => $parent['priority'], 'validate' => $parent['validate'], ); } break; case 'user_role': $roles = wp_roles()->get_names(); foreach ( $roles as $role => $label ) { $id = $parent['id'] . $role; $values[ $id ] = array( 'id' => $id, 'parent' => $parent['id'], 'label' => et_core_intentionally_unescaped( $label, 'react_jsx' ), 'title' => et_core_intentionally_unescaped( $role, 'react_jsx' ), 'priority' => $parent['priority'], 'validate' => $parent['validate'], ); } break; } /** * Fires after loading child options from the database. * * @since 4.2 * * @param string $parent_id * @param string $child_type * @param string $child_value */ do_action( 'et_theme_builder_after_get_template_setting_child_options', $parent['id'], $parent['options']['type'], $parent['options']['value'] ); return $values; } /** * Get the template and its layouts, if any, for the given request. * * @since 4.0 * * @param ET_Theme_Builder_Request $request Request to check against. Defaults to the current one. * @param bool $cache Cache the result or not, regardless of whether any layouts should be loaded. * @param bool $load_from_cache Load the cached result for the given post ID, if available. * * @return array Array of layouts or an empty array if no layouts should be loaded. */ function et_theme_builder_get_template_layouts( $request = null, $cache = true, $load_from_cache = true ) { static $store = array(); if ( null === $request ) { if ( is_embed() ) { // Ignore TB templates when displaying posts intended for embedding. return array(); } if ( is_et_pb_preview() ) { // Ignore TB templates when previewing. return array(); } $request = ET_Theme_Builder_Request::from_current(); } if ( null === $request || ET_GB_Block_Layout::is_layout_block_preview() ) { return array(); } $cache_key = "{$request->get_type()}:{$request->get_subtype()}:{$request->get_id()}"; if ( $load_from_cache && isset( $store[ $cache_key ] ) ) { return $store[ $cache_key ]; } $post_type = ET_Theme_Builder_Request::TYPE_SINGULAR === $request->get_type() ? $request->get_subtype() : ''; $layouts = array(); if ( et_theme_builder_is_layout_post_type( $post_type ) ) { // We are currently editing a layout in the VB. $layouts = array_replace( array( ET_THEME_BUILDER_TEMPLATE_POST_TYPE => 0, ET_THEME_BUILDER_HEADER_LAYOUT_POST_TYPE => array( 'id' => 0, 'enabled' => false, 'override' => true, ), ET_THEME_BUILDER_BODY_LAYOUT_POST_TYPE => array( 'id' => 0, 'enabled' => false, 'override' => true, ), ET_THEME_BUILDER_FOOTER_LAYOUT_POST_TYPE => array( 'id' => 0, 'enabled' => false, 'override' => true, ), ), array( $post_type => array( 'id' => $request->get_id(), 'enabled' => true, 'override' => true, ), ) ); } else { // We are currently displaying a template in the FE. $templates = et_theme_builder_get_theme_builder_templates( true ); $settings = et_theme_builder_get_flat_template_settings_options(); $template = $request->get_template( $templates, $settings ); $is_singular = is_singular(); if ( ! empty( $template ) ) { $is_default = $template['default']; $override_header = $template['layouts']['header']['override']; $override_body = $template['layouts']['body']['override']; $override_footer = $template['layouts']['footer']['override']; // The Default Website Template has a special case - it should not take over if // it does not override any areas otherwise it will take over ALL site pages. if ( ! $is_default || $override_header || $override_body || $override_footer ) { $layouts = array( ET_THEME_BUILDER_TEMPLATE_POST_TYPE => $is_singular ? $template['id'] : false, ET_THEME_BUILDER_HEADER_LAYOUT_POST_TYPE => $template['layouts']['header'], ET_THEME_BUILDER_BODY_LAYOUT_POST_TYPE => $template['layouts']['body'], ET_THEME_BUILDER_FOOTER_LAYOUT_POST_TYPE => $template['layouts']['footer'], ); } } } /** * Filter template layouts. * * @since 4.0 * * @param array $layouts */ $layouts = apply_filters( 'et_theme_builder_template_layouts', $layouts ); // Add AB Subjects array. foreach ( $layouts as $key => $layout ) { if ( is_array( $layout ) && $layout['override'] ) { $layouts[ $key ]['et_pb_ab_subjects'] = et_pb_ab_get_subjects( $layout['id'] ); } } if ( $cache ) { $store[ $cache_key ] = $layouts; } return $layouts; } /** * Get whether TB overrides the specified layout for the current request. * * @since 4.0.6 * * @param string $layout Layout post type. * * @return boolean */ function et_theme_builder_overrides_layout( $layout ) { $layouts = et_theme_builder_get_template_layouts(); return ! empty( $layouts ) && $layouts[ $layout ]['override']; } /** * Get whether the specified layout will properly render the real post content. * * @since 4.0 * * @param array $layout * * @return boolean */ function et_theme_builder_layout_has_post_content( $layout ) { if ( ! $layout['override'] ) { // The layout does not override the content so post content will render. return true; } if ( $layout['enabled'] ) { $content = get_post_field( 'post_content', $layout['id'] ); $modules = et_theme_builder_get_post_content_modules(); foreach ( $modules as $module ) { if ( has_shortcode( $content, $module ) ) { return true; } } } return false; } /** * Create or update a Theme Builder template. * * @since 4.0 * * @param integer $theme_builder_id Theme builder ID. * @param array $template Template. * @param boolean $allow_default Allow default. * * @return (integer|false) Return false on failure. */ function et_theme_builder_store_template( $theme_builder_id, $template, $allow_default ) { $_ = et_(); $raw_post_id = $_->array_get( $template, 'id', 0 ); $post_id = is_numeric( $raw_post_id ) ? (int) $raw_post_id : 0; $title = sanitize_text_field( $_->array_get( $template, 'title', '' ) ); $default = $allow_default && '1' === $_->array_get( $template, 'default', '1' ); $enabled = '1' === $_->array_get( $template, 'enabled', '1' ); $header_id = (int) $_->array_get( $template, 'layouts.header.id', 0 ); $header_enabled = (bool) $_->array_get( $template, 'layouts.header.enabled', true ); $body_id = (int) $_->array_get( $template, 'layouts.body.id', 0 ); $body_enabled = (bool) $_->array_get( $template, 'layouts.body.enabled', true ); $footer_id = (int) $_->array_get( $template, 'layouts.footer.id', 0 ); $footer_enabled = (bool) $_->array_get( $template, 'layouts.footer.enabled', true ); $use_on = array_map( 'sanitize_text_field', $_->array_get( $template, 'use_on', array() ) ); $exclude_from = array_map( 'sanitize_text_field', $_->array_get( $template, 'exclude_from', array() ) ); $exists = $post_id > 0 && ET_THEME_BUILDER_TEMPLATE_POST_TYPE === get_post_type( $post_id ) && 'publish' === get_post_status( $post_id ); $autogenerated_title = '1' === $_->array_get( $template, 'autogenerated_title', '1' ); if ( ET_THEME_BUILDER_HEADER_LAYOUT_POST_TYPE !== get_post_type( $header_id ) || 'publish' !== get_post_status( $header_id ) ) { $header_id = 0; } if ( ET_THEME_BUILDER_BODY_LAYOUT_POST_TYPE !== get_post_type( $body_id ) || 'publish' !== get_post_status( $body_id ) ) { $body_id = 0; } if ( ET_THEME_BUILDER_FOOTER_LAYOUT_POST_TYPE !== get_post_type( $footer_id ) || 'publish' !== get_post_status( $footer_id ) ) { $footer_id = 0; } if ( $exists ) { // Preform update only when needed. if ( get_post_field( 'post_title', $post_id, 'raw' ) !== $title ) { wp_update_post( array( 'ID' => $post_id, 'post_title' => $title, ) ); } // Update layout title for each template. et_theme_builder_update_layout_title( $template ); } else { $post_id = wp_insert_post( array( 'post_type' => ET_THEME_BUILDER_TEMPLATE_POST_TYPE, 'post_status' => 'publish', 'post_title' => $title, ) ); } if ( 0 === $post_id || is_wp_error( $post_id ) ) { return false; } $metas = array( '_et_autogenerated_title' => $autogenerated_title ? '1' : '0', '_et_default' => $default ? '1' : '0', '_et_enabled' => $enabled ? '1' : '0', '_et_header_layout_id' => $header_id, '_et_header_layout_enabled' => $header_enabled ? '1' : '0', '_et_body_layout_id' => $body_id, '_et_body_layout_enabled' => $body_enabled ? '1' : '0', '_et_footer_layout_id' => $footer_id, '_et_footer_layout_enabled' => $footer_enabled ? '1' : '0', ); foreach ( $metas as $key => $value ) { if ( strval( $value ) === strval( get_post_meta( $post_id, $key, true ) ) ) { continue; } update_post_meta( $post_id, $key, $value ); } // Handle _et_use_on meta. delete_post_meta( $post_id, '_et_use_on' ); if ( $use_on ) { $use_on_unique = array_unique( $use_on ); foreach ( $use_on_unique as $condition ) { add_post_meta( $post_id, '_et_use_on', $condition ); } } // Handle _et_exclude_from meta. delete_post_meta( $post_id, '_et_exclude_from' ); if ( $exclude_from ) { $exclude_from_unique = array_unique( $exclude_from ); foreach ( $exclude_from_unique as $condition ) { add_post_meta( $post_id, '_et_exclude_from', $condition ); } } return $post_id; } /** * Sanitize a Theme Builder template. * * @since 4.0 * * @param array $template * * @return array */ function et_theme_builder_sanitize_template( $template ) { $_ = et_(); $autogenerated_title = $_->array_get( $template, 'autogenerated_title', '0' ); $default = $_->array_get( $template, 'default', '0' ); $enabled = $_->array_get( $template, 'enabled', '0' ); $use_on = $_->array_get( $template, 'use_on', array() ); $exclude_from = $_->array_get( $template, 'exclude_from', array() ); $header_enabled = $_->array_get( $template, 'layouts.header.enabled', '1' ); $body_enabled = $_->array_get( $template, 'layouts.body.enabled', '1' ); $footer_enabled = $_->array_get( $template, 'layouts.footer.enabled', '1' ); $sanitized = array( 'title' => sanitize_text_field( $_->array_get( $template, 'title', '' ) ), 'autogenerated_title' => true === $autogenerated_title || '1' === $autogenerated_title, 'default' => true === $default || '1' === $default, 'enabled' => true === $enabled || '1' === $enabled, 'use_on' => array_map( 'sanitize_text_field', $use_on ), 'exclude_from' => array_map( 'sanitize_text_field', $exclude_from ), 'layouts' => array( 'header' => array( 'id' => (int) $_->array_get( $template, 'layouts.header.id', '0' ), 'enabled' => true === $header_enabled || '1' === $header_enabled, ), 'body' => array( 'id' => (int) $_->array_get( $template, 'layouts.body.id', '0' ), 'enabled' => true === $body_enabled || '1' === $body_enabled, ), 'footer' => array( 'id' => (int) $_->array_get( $template, 'layouts.footer.id', '0' ), 'enabled' => true === $footer_enabled || '1' === $footer_enabled, ), ), ); return $sanitized; } /** * Insert a Theme Builder layout post. * * @since 4.0 * * @param array $options * * @return integer|WP_Error */ function et_theme_builder_insert_layout( $options ) { $post_id = wp_insert_post( array_merge( array( 'post_status' => 'publish', 'post_title' => 'Theme Builder Layout', ), $options ), true ); if ( is_wp_error( $post_id ) ) { return $post_id; } wp_set_object_terms( $post_id, 'layout', 'layout_type', true ); et_builder_enable_for_post( $post_id ); return $post_id; } /** * Overrides cache post_type so that TB custom post types and 'page' share the same files. * * @since 4.0 * * @param string $post_type * * @return string. */ function et_theme_builder_cache_post_type( $post_type ) { if ( et_theme_builder_is_layout_post_type( $post_type ) ) { // Use a generic name for all Theme Builder post type modules // as they are identical for most practical reasons. $post_type = 'page'; } return $post_type; } add_filter( 'et_builder_cache_post_type', 'et_theme_builder_cache_post_type' ); /** * Decorate a page resource slug based on the current request and TB. * * @since 4.0.7 * * @param integer|string $post_id * @param string $resource_slug Resource slug. * * @return string */ function et_theme_builder_decorate_page_resource_slug( $post_id, $resource_slug ) { if ( ! is_numeric( $post_id ) || ! is_singular() ) { return $resource_slug; } $post_type = get_post_type( (int) $post_id ); if ( et_theme_builder_is_layout_post_type( $post_type ) ) { $resource_slug .= '-tb-for-' . ET_Post_Stack::get_main_post_id(); } else { $layout_types = et_theme_builder_get_layout_post_types(); $layouts = et_theme_builder_get_template_layouts(); foreach ( $layout_types as $type ) { if ( ! isset( $layouts[ $type ] ) || ! $layouts[ $type ]['override'] ) { continue; } $resource_slug .= '-tb-' . $layouts[ $type ]['id']; } } return $resource_slug; } add_filter( 'et_builder_cache_post_type', 'et_theme_builder_cache_post_type' ); /** * Clear cache of 3P caching plugins partially on the posts or all of them. * * @since 4.5.0 * * @param string|array $post_ids 'all' or array of post IDs. * * @return void */ function et_theme_builder_clear_wp_cache( $post_ids = 'all' ) { if ( ! et_pb_detect_cache_plugins() ) { return; } if ( empty( $post_ids ) ) { return; } if ( 'all' === $post_ids ) { et_core_clear_wp_cache(); } elseif ( is_array( $post_ids ) ) { foreach ( $post_ids as $post_id ) { et_core_clear_wp_cache( $post_id ); } } } /** * Clear cache of 3P caching plugins fully or partially after TB layouts saved. * * Clear all the cache when the template updated is: * - Default template * - Used on archive, 404, or all posts * - Non static homepage * * @since 4.5.0 * * @param int $layout_id * * @return void */ function et_theme_builder_clear_wp_post_cache( $layout_id = '' ) { $layout_type = get_post_type( $layout_id ); if ( ! et_theme_builder_is_layout_post_type( $layout_type ) ) { return; } if ( ! et_pb_detect_cache_plugins() ) { return; } // Get template of current TB layout. $template = new WP_Query( array( 'post_type' => ET_THEME_BUILDER_TEMPLATE_POST_TYPE, 'post_status' => 'publish', 'posts_per_page' => 1, 'fields' => 'ids', 'no_found_rows' => true, 'update_post_meta_cache' => false, 'update_post_term_cache' => false, 'meta_query' => array( 'relation' => 'AND', array( 'key' => '_et_enabled', 'value' => '1', 'compare' => '=', ), array( 'key' => "_{$layout_type}_id", 'value' => $layout_id, 'compare' => '=', ), array( 'key' => "_{$layout_type}_enabled", 'value' => '1', 'compare' => '=', ), array( 'key' => '_et_theme_builder_marked_as_unused', 'compare' => 'NOT EXISTS', ), ), ) ); if ( ! $template->have_posts() ) { return; } $_ = et_(); $template_id = $_->array_get( $template->posts, '0' ); $template_use_on = get_post_meta( $template_id, '_et_use_on', false ); $is_template_default = '1' === get_post_meta( $template_id, '_et_default', true ); // Unassigned Template - False or empty _et_use_on means it's unassigned. if ( empty( $template_use_on ) ) { // Clear All - If the template is 'default' because it's enabled globally. if ( $is_template_default ) { et_theme_builder_clear_wp_cache( 'all' ); } return; } $target_post_ids = array(); foreach ( $template_use_on as $location ) { $location_pieces = explode( ':', $location ); $location_first = $_->array_get( $location_pieces, '0' ); $location_last = end( $location_pieces ); if ( in_array( $location_first, array( 'archive', '404' ) ) || 'all' === $location_last ) { // Path: archive:user:id:{user_id}, singular:post_type:{post_type_slug}:all, // archive:taxonomy:{taxonomy_name}:all, etc. // Clear All - If the template is being used on 'archive:' or ':all' posts. $target_post_ids = 'all'; break; } elseif ( 'homepage' === $location_first ) { // Path: homepage $homepage_id = (int) get_option( 'page_on_front' ); $target_post_ids[] = $homepage_id; if ( ! $homepage_id ) { // Clear All - If the homepage is non static page. $target_post_ids = 'all'; break; } } elseif ( 'singular' === $location_first ) { $singular_type = $_->array_get( $location_pieces, '3' ); if ( 'id' === $singular_type ) { // Path: singular:post_type:{post_type_slug}:id:{post_id} $target_post_ids[] = (int) $_->array_get( $location_pieces, '4' ); } elseif ( 'children' === $singular_type ) { // Path: singular:post_type:{post_type_slug}:children:id:{post_id} $parent_id = (int) $_->array_get( $location_pieces, '5' ); $children_ids = get_children( array( 'posts_per_page' => -1, 'post_parent' => $parent_id, 'fields' => 'ids', ) ); $target_post_ids = array_merge( $target_post_ids, $children_ids ); } elseif ( 'term' === $singular_type ) { // Path: singular:taxonomy:{taxonomy_name}:term:id:{term_id} $taxonomy = $_->array_get( $location_pieces, '2' ); $taxonomy_object = get_taxonomy( $taxonomy ); $taxonomy_type = ! empty( $taxonomy_object->object_type ) ? $_->array_get( $taxonomy_object->object_type, '0' ) : 'post'; $term_id = (int) $_->array_get( $location_pieces, '5' ); $posts_ids = get_posts( array( 'posts_per_page' => -1, 'fields' => 'ids', 'post_type' => $taxonomy_type, 'tax_query' => array( array( 'taxonomy' => $taxonomy, 'field' => 'term_id', 'terms' => $term_id, ), ), ) ); $target_post_ids = array_merge( $target_post_ids, $posts_ids ); } } elseif ( 'woocommerce' === $location_first && et_is_woocommerce_plugin_active() && function_exists( 'wc_get_page_id' ) ) { // Path: woocommerce:my_account, woocommerce:cart, etc. $woocommerce_page = str_replace( '_', '', $_->array_get( $location_pieces, '1' ) ); $woocommerce_page_id = wc_get_page_id( $woocommerce_page ); if ( $woocommerce_page_id ) { $target_post_ids[] = $woocommerce_page_id; } } } // Remove duplicate posts. if ( is_array( $target_post_ids ) ) { $target_post_ids = array_unique( $target_post_ids ); } et_theme_builder_clear_wp_cache( $target_post_ids ); } add_action( 'et_save_post', 'et_theme_builder_clear_wp_post_cache' ); /** * * Update layout title for each template * * @param array $template Theme Builder Template. */ function et_theme_builder_update_layout_title( $template ) { if ( empty( $template['layouts'] ) ) { return; } foreach ( $template['layouts'] as $layout ) { $layout_id = (int) $layout['id']; if ( ! $layout_id ) { continue; } wp_update_post( array( 'ID' => $layout_id, 'post_title' => sanitize_text_field( $template['title'] ), ) ); } }