: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
'compare' => 'NOT EXISTS',
'value' => 'https://core.trac.wordpress.org/ticket/23268',
'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') );
// 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(
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,
'value' => date('Y-m-d H:i:s', time() - 60 * 60 * 24 * 7),
'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.
* @param string $post_type_name
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 ) {
$post_type_plural = ucwords( $post_type->labels->name );
$taxonomies = get_object_taxonomies( $post_type_name, 'objects' );
'label' => et_core_intentionally_unescaped( $post_type_plural, 'react_jsx' ),
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' ),
'validate' => 'et_theme_builder_template_setting_validate_singular_post_type_all',
if ( 'page' === $post_type_name ) {
$group['settings'][] = array(
'label' => et_core_intentionally_unescaped( __( 'Homepage', 'et_builder' ), 'react_jsx' ),
'validate' => 'et_theme_builder_template_setting_validate_homepage',
} else if ( 'post' === $post_type_name || $post_type->has_archive ) {
$group['settings'][] = array(
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 ) ), '/' ),
'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 %
$show = apply_filters( 'et_theme_builder_template_settings_options_posts_with_specific_term', $taxonomy->show_ui );
$taxonomy_plural = ucwords( $taxonomy->labels->name );
$use_short_plural = in_array( $taxonomy->name, array(
// Translators: %1$s: Post type plural name; %2$s: Taxonomy plural name.
$label = et_core_intentionally_unescaped(
__( '%1$s with Specific %2$s', 'et_builder' ),
$use_short_plural ? esc_html__( 'Tags', 'et_builder' ) : $taxonomy_plural
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(
__( '%1$s in Specific %2$s', 'et_builder' ),
$use_short_plural ? esc_html__( 'Categories', 'et_builder' ) : $taxonomy_plural
$group['settings'][] = array(
ET_THEME_BUILDER_SETTING_SEPARATOR,
array( 'singular', 'taxonomy', $taxonomy->name, 'term', 'id', '' )
// Translators: %1$s: Post type plural name; %2$s: Taxonomy plural name.
'validate' => 'et_theme_builder_template_setting_validate_singular_taxonomy_term_id',
'label' => $taxonomy_plural,
'value' => $taxonomy->name,
$group['settings'][] = array(
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' ),
'validate' => 'et_theme_builder_template_setting_validate_singular_post_type_id',
'label' => $post_type_plural,
'value' => $post_type_name,
if ( is_post_type_hierarchical( $post_type_name ) ) {
$group['settings'][] = array(
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' ),
'validate' => 'et_theme_builder_template_setting_validate_singular_post_type_children_id',
'label' => $post_type_plural,
'value' => $post_type_name,
* Get the template settings options for all archive pages.
function et_theme_builder_get_template_settings_options_for_archive_pages() {
$taxonomies = get_taxonomies( array(
$taxonomies = array_merge(
'category' => get_taxonomy( 'category' ),
'post_tag' => get_taxonomy( 'post_tag' ),
'label' => et_core_intentionally_unescaped( __( 'Archive Pages', 'et_builder' ), 'react_jsx' ),
ET_THEME_BUILDER_SETTING_SEPARATOR,
array( 'archive', 'all' )
'label' => et_core_intentionally_unescaped( __( 'All Archive Pages', 'et_builder' ), 'react_jsx' ),
'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:
$show = apply_filters( 'et_theme_builder_template_settings_options_term_pages', $taxonomy->public && $taxonomy->show_ui );
$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' );
} else if ( false !== strpos( $taxonomy->name, 'cat' ) ) {
// Use singular for Category.
$taxonomy_name = ucwords( $taxonomy->labels->singular_name );
$group['settings'][] = array(
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' ),
'validate' => 'et_theme_builder_template_setting_validate_archive_taxonomy_all',
$group['settings'][] = array(
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' ),
'validate' => 'et_theme_builder_template_setting_validate_archive_taxonomy_term_id',
'label' => $taxonomy_plural,
'value' => $taxonomy->name,
$group['settings'][] = array(
ET_THEME_BUILDER_SETTING_SEPARATOR,
array( 'archive', 'user', 'all' )
'label' => et_core_intentionally_unescaped( __( 'All Author Pages', 'et_builder' ), 'react_jsx' ),
'validate' => 'et_theme_builder_template_setting_validate_archive_user_all',
$group['settings'][] = array(
ET_THEME_BUILDER_SETTING_SEPARATOR,
array( 'archive', 'user', 'id', '' )
'label' => et_core_intentionally_unescaped( __( 'Specific Author Page', 'et_builder' ), 'react_jsx' ),
'validate' => 'et_theme_builder_template_setting_validate_archive_user_id',
'label' => et_core_intentionally_unescaped( __( 'Users', 'et_builder' ), 'react_jsx' ),
$group['settings'][] = array(
ET_THEME_BUILDER_SETTING_SEPARATOR,
array( 'archive', 'user', 'role', '' )
'label' => et_core_intentionally_unescaped( __( 'Specific Author Page By Role', 'et_builder' ), 'react_jsx' ),
'validate' => 'et_theme_builder_template_setting_validate_archive_user_role',
'label' => et_core_intentionally_unescaped( __( 'Roles', 'et_builder' ), 'react_jsx' ),
$group['settings'][] = array(
ET_THEME_BUILDER_SETTING_SEPARATOR,
array( 'archive', 'date', 'all' )
'label' => et_core_intentionally_unescaped( __( 'All Date Pages', 'et_builder' ), 'react_jsx' ),
'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' );
* 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.
function et_theme_builder_get_template_settings_options() {
$post_types = get_post_types( 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' ),
'label' => et_core_intentionally_unescaped( __( 'Search Results', 'et_builder' ), 'react_jsx' ),
'validate' => 'et_theme_builder_template_setting_validate_search',
'label' => et_core_intentionally_unescaped( __( '404 Page', 'et_builder' ), 'react_jsx' ),
'validate' => 'et_theme_builder_template_setting_validate_404',
* Filters available template settings options.
$options = apply_filters( 'et_theme_builder_template_settings_options', $options );
* Get flat array of template setting options from the current live and draft theme builder posts.
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 )
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 ) ) {
if ( ! is_array( $exclude_from ) ) {
$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.
* @param string[] $setting_ids
function et_theme_builder_load_template_setting_options( $setting_ids ) {
$flat_parent_settings = et_theme_builder_get_flat_template_settings_options();
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.
if ( ! isset( $groups[ $parent_id ] ) ) {
$groups[ $parent_id ] = array(
'parent' => $flat_parent_settings[ $parent_id ],
$groups[ $parent_id ]['settings'][ $setting_id ] = $entity_id;
foreach ( $groups as $parent_id => $group ) {
et_theme_builder_get_template_setting_child_options( $group['parent'], $group['settings'] )
* Get a flat array of template setting options.
function et_theme_builder_get_flat_template_settings_options() {
$settings = et_theme_builder_get_template_settings_options();
foreach ( $settings as $group ) {
foreach ( $group['settings'] as $setting ) {