文件操作 - database.php
返回文件管理
返回主菜单
删除本文件
文件: /storage/v12552/stanleysteamer/public_html/wp-content/themes/bricks/includes/database.php
编辑文件内容
<?php namespace Bricks; if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly class Database { public static $posts_per_page = 0; public static $all_templates = []; // @since 2.0 public static $active_templates = []; public static $default_template_types = [ 'header', 'footer', 'archive', 'search', 'error', 'wc_archive', 'wc_product', 'wc_cart', 'wc_cart_empty', 'wc_form_checkout', 'wc_form_pay', 'wc_thankyou', 'wc_order_receipt', // Woo Phase 3 'wc_account_dashboard', 'wc_account_orders', 'wc_account_view_order', 'wc_account_downloads', 'wc_account_addresses', 'wc_account_form_edit_address', 'wc_account_form_edit_account', 'wc_account_form_login', 'wc_account_form_lost_password', 'wc_account_form_lost_password_confirmation', 'wc_account_reset_password', ]; public static $header_position = 'top'; public static $global_data = []; public static $page_data = [ 'preview_or_post_id' => 0, 'language' => '', // For WPML/Polylang (@since 1.9.9) ]; public static $global_settings = []; public static $page_settings = []; public static $adobe_fonts = []; public static $main_query_id = ''; // Holds the element ID of the main query element set in set_main_archive_query() @since 1.12.2 public function __construct() { // Initialize active templates through helper function (@since 1.12) if ( is_array( self::$active_templates ) && empty( self::$active_templates ) ) { self::init_active_templates(); } self::get_global_data(); add_action( 'pre_get_posts', [ $this, 'set_main_archive_query' ] ); // Set active templates add_action( 'wp', [ $this, 'set_active_templates' ] ); // Set page data (AJAX) add_action( 'wp_loaded', [ $this, 'set_ajax_page_data' ] ); // Set page data (no AJAX) add_action( 'wp', [ $this, 'set_page_data' ] ); // Set page data on REST API calls add_action( 'rest_api_init', [ $this, 'set_page_data' ] ); add_action( 'update_option_' . BRICKS_DB_GLOBAL_CLASSES, [ $this, 'update_option_bricks_global_classes' ], 10, 3 ); add_filter( 'wp_prepare_themes_for_js', [ $this, 'wp_prepare_themes_for_js' ] ); } /** * Initialize active templates * * @since 1.12 */ public static function init_active_templates() { self::$active_templates = [ 'header' => 0, 'footer' => 0, 'content' => 0, 'archive' => 0, 'error' => 0, 'search' => 0, 'section' => 0, // Use in "Template" 'password_protection' => 0, // @since 1.11.1 'popup' => [], // Array with popup template IDs ]; } /** * Support autoupdate * * To always show "Enable/disable auto-updates" link for Bricks. * Otherwise, link only shows when an update is available. */ public function wp_prepare_themes_for_js( $prepared_themes ) { // Add auto update support for Bricks theme if ( isset( $prepared_themes['bricks']['autoupdate']['supported'] ) ) { $prepared_themes['bricks']['autoupdate']['supported'] = true; } return $prepared_themes; } /** * Log every save of empty global classes to debug where it's coming from * * Triggered in Bricks via: * * ajax.php: wp_ajax_bricks_save_post (save post in builder) * templates.php: wp_ajax_bricks_import_template (template import) * converter.php: wp_ajax_bricks_run_converter (run converter from Bricks settings) * * @link https://developer.wordpress.org/reference/hooks/update_option_option/ * * @since 1.7 */ public function update_option_bricks_global_classes( $old_value, $new_value, $option_name ) { if ( $option_name === BRICKS_DB_GLOBAL_CLASSES ) { $old_count = is_array( $old_value ) ? count( $old_value ) : 0; $new_count = is_array( $new_value ) ? count( $new_value ) : 0; $trash = get_option( BRICKS_DB_GLOBAL_CLASSES_TRASH, [] ); $trash_count = count( $trash ); // Record only global class saves where total number of global classes changed if ( $old_count !== $new_count || $trash_count > 0 ) { $current_user = wp_get_current_user(); // Possible AJAX calls: Save post in builder, import templates, run converter $new_entry = [ 'timestamp' => time(), 'referer' => wp_get_referer(), 'action' => isset( $_POST['action'] ) ? sanitize_text_field( $_POST['action'] ) : '', 'post_id' => isset( $_POST['postId'] ) ? intval( $_POST['postId'] ) : '', 'user_id' => $current_user ? $current_user->ID : 0, 'old_count' => $old_count, 'new_count' => $new_count, 'trash_count' => $trash_count, ]; $saves = get_option( 'bricks_global_classes_changes', [] ); if ( ! is_array( $saves ) ) { $saves = []; } // Keep the first 25 changes if ( count( $saves ) >= 25 ) { array_shift( $saves ); } $saves[] = $new_entry; update_option( 'bricks_global_classes_changes', $saves, false ); } } } /** * Customize WP Main Query: Set all query_vars by user for archive/search/error template pages * So the pagination will not encounter 404 errors * * @since 1.9.1 */ public function set_main_archive_query( $query ) { if ( bricks_is_builder() || is_admin() || ! $query->is_main_query() ) { return; } $post_id = 0; $set_active_templates = $query->is_archive || $query->is_search || $query->is_error || $query->is_home; // Archive, Search, Error, Home: Get the active template if ( $set_active_templates ) { // Set active templates self::set_active_templates( $query ); // This is the template currently being used for archive/search/error/home $post_id = ! empty( self::$active_templates['content'] ) ? self::$active_templates['content'] : 0; } if ( $post_id ) { // Check if any Bricks data is set $bricks_data = self::get_data( $post_id ); // Is home page (posts page): Retrieve the Bricks data too (non-standard template setup) (@since 1.10) if ( $query->is_home && $query->get_queried_object_id() ) { $bricks_posts_page_data = self::get_data( $query->get_queried_object_id() ); // Merge the data if ( is_array( $bricks_posts_page_data ) ) { $bricks_data = array_merge( $bricks_data, $bricks_posts_page_data ); } } // Start to scan through if any query element is set, main objective is get the query settings for the main archive query if ( is_array( $bricks_data ) ) { /** * STEP: Get component data * * @since 2.0 */ $bricks_data = self::get_component_data( $bricks_data ); /** * STEP: Get nested template data * * Now $bricks_data contains all the data from the main template and all nested templates. * * @since 1.9.1 */ $bricks_data = self::get_nested_template_data( $bricks_data ); /** * STEP: Arrange the $bricks_data array * * $bricks_data is not sorted by position following the builder structure, we do not know which main query settings should be used if more than 1 query ticked the is_archive_main_query * * @since 1.9.1 */ $structured_element_ids = self::elements_sequence_in_builder( $bricks_data ); // Loop through elements follow builder structure sequence, to get main archive query settings defined by the user, only the first one will be used (@since 1.9.1) $archive_query_set = false; foreach ( $structured_element_ids as $element_id ) { $element = self::get_element_by_id( $element_id, $bricks_data ); if ( ! $element ) { continue; } // STEP: Get global query settings (@since 2.1) if ( isset( $element['settings']['query'] ) ) { $element['settings']['query'] = Helpers::maybe_get_global_query_settings( $element['settings']['query'] ?? [] ); } // Certain elements 'is_archive_main_query' is not set inside query key if ( isset( $element['settings']['is_archive_main_query'] ) ) { // WooCommerce Products element if ( $element['name'] === 'woocommerce-products' ) { $element['settings']['hasLoop'] = 1; // #86c01086t; @since 1.10.2 $element['settings']['query']['is_archive_main_query'] = 1; $element['settings']['query']['post_type'] = [ 'product' ]; // #86byx62xu } } // Posts element has no 'hasLoop' key, but it's a main query if ( $element['name'] === 'posts' && isset( $element['settings']['query']['is_archive_main_query'] ) ) { $element['settings']['hasLoop'] = 1; // #86c03k1ut; @since 1.10.2 } // Exit: Not a query element if ( empty( $element['settings']['query'] ) ) { continue; } // Exit: foreach main query is already set once if ( $archive_query_set ) { break; } $object_type = $element['settings']['query']['objectType'] ?? 'post'; /** * Set main archive query * - If hasLoop is set (active query) (@since 1.9.9) * - If is_archive_main_query is set * - If objectType is one of the archive_query_supported_object_types */ if ( isset( $element['settings']['hasLoop'] ) && isset( $element['settings']['query']['is_archive_main_query'] ) && in_array( $object_type, Query::archive_query_supported_object_types() ) ) { // Unique flag to identify main archive query (@since 1.10.2) $query->set( 'brx_main_query', true ); // Set element ID to identify main query element (@since 1.12.2) self::$main_query_id = $element_id; // Use the prepared query vars instead of raw element settings (@since 1.8) // Skip merge main query 4th parameter (true) (#86c42z22c; #86c3zyd4z; @since 2.0) $query_vars = Query::prepare_query_vars_from_settings( $element['settings'], $element_id, $element['name'], true ); // Check if user set offset (@since 1.10.2) $has_offset = isset( $query_vars['offset'] ) && $query_vars['offset'] > 0; foreach ( $query_vars as $key => $value ) { if ( in_array( $key, Query::archive_query_arguments() ) ) { // Merge existing tax_query with Bricks tax_query (@since 1.9.8) if ( $key === 'tax_query' ) { $current_tax_query = $query->get( 'tax_query' ); if ( ! empty( $current_tax_query ) ) { $value = Query::merge_tax_or_meta_query_vars( $current_tax_query, $value, 'tax' ); } } // Skip user offset, calculate later if ( $has_offset && $key === 'offset' ) { continue; } $query->set( $key, $value ); } } // Search Criteria for search result template (@since 2.2) if ( $query->is_search && Search::search_template_has_custom_criteria( $post_id ) ) { // Get search-criteria settings from template settings $search_term = $query->get( 's', '' ); // Get post IDs using combined SQL search $post_ids = Search::get_search_template_criteria_post_ids( $post_id, $search_term ); $post_ids = ! empty( $post_ids ) ? $post_ids : [ 0 ]; $query->set( 'brx_original_search_term', $search_term ); // To avoid default search behavior interfering $query->set( 's', '' ); // Modify main query to include only the found post IDs $query->set( 'post__in', $post_ids ); // Since we removed the "s" parameter, we need to restore the original search term in search box or it will be empty add_filter( 'get_search_query', function( $query ) { if ( is_main_query() && is_search() ) { global $wp_query; $original_term = $wp_query->get( 'brx_original_search_term' ); if ( $original_term ) { return $original_term; } } return $query; } ); // Amend orderby only if weight score is used and no other sort is applied by user if ( Search::use_weight_score( $post_id ) && ! empty( $post_ids ) && ! isset( $query_vars['brx_sort_applied'] ) ) { $query->set( 'orderby', 'post__in' ); $query->set( 'order', '' ); $query->set( 'brx_orderby', 'weighted_relevance' ); } } /** * Handle offset * * - Calculate offset based on user offset and current page * - Fix found_posts for main query's pagination * * @since 1.10.2 */ if ( $has_offset ) { $user_offset = $query_vars['offset']; $new_offset = $user_offset + ( $query->get( 'paged', 1 ) - 1 ) * $query->get( 'posts_per_page' ); $query->set( 'offset', $new_offset ); add_filter( 'found_posts', function( $found_posts, $query ) use ( $user_offset ) { if ( bricks_is_builder() || is_admin() || ! $query->get( 'brx_main_query' ) ) { return $found_posts; } return $found_posts - $user_offset; }, 10, 2 ); } /** * Handle random seed * * Generate random seed statement and add to posts_orderby filter and target the main query * * @since 1.9.8 */ if ( Query::use_random_seed( $query_vars ) ) { $random_seed_statement = Query::get_random_seed_statement( $element_id, $query_vars ); if ( ! empty( $random_seed_statement ) ) { add_filter( 'posts_orderby', function( $orderby, $query ) use ( $random_seed_statement ) { // Exit if it's not main query if ( bricks_is_builder() || is_admin() || ! $query->get( 'brx_main_query' ) ) { return $orderby; } return $random_seed_statement; }, 10, 2 ); } } // Set flag to exit foreach $archive_query_set = true; } } } } /** * Re-init active templates * * @see #86bw4pmd0 * @since 1.9.2 */ if ( $set_active_templates ) { self::init_active_templates(); } } /** * Set active templates for use throughout the theme */ public static function set_active_templates( $post_id = 0 ) { // Check if set_active_templates already ran if ( isset( self::$active_templates['post_id'] ) ) { return; } if ( ! $post_id || is_object( $post_id ) ) { $post_id = get_the_ID(); } // NOTE: Set post ID to posts page. Code will try to find templates for the page defined as the blog page if ( is_home() ) { $post_id = get_option( 'page_for_posts' ); } $post_id = intval( $post_id ); $post_type = get_post_type( $post_id ); $preview_type = ''; // Only applicable to templates $content_type = 'content'; // = default content type // Check if post is Bricks template if ( is_singular( BRICKS_DB_TEMPLATE_SLUG ) ) { $template_type = get_post_meta( $post_id, BRICKS_DB_TEMPLATE_TYPE, true ); if ( in_array( $template_type, [ 'header', 'footer' ] ) ) { self::$active_templates[ $template_type ] = $post_id; $preview_type = Helpers::get_template_setting( 'templatePreviewType', $post_id ); switch ( $preview_type ) { case 'single': $preview_id = Helpers::get_template_setting( 'templatePreviewPostId', $post_id ); $content_type = 'content'; self::$active_templates['content'] = $preview_id; break; case 'search': $content_type = 'search'; break; case 'archive-recent-posts': case 'archive-author': case 'archive-date': case 'archive-cpt': case 'archive-term': $content_type = 'archive'; break; } } else { self::$active_templates['content'] = $post_id; $content_type = $template_type; } } // All other cases (builder & frontend) else { // Find content type needed given the current page load query $tag_templates = [ 'is_404' => 'error', 'is_search' => 'search', 'is_home' => 'content', 'is_front_page' => 'content', 'is_singular' => 'content', 'is_product_taxonomy' => 'wc_archive', 'is_post_type_archive' => 'archive', 'is_tax' => 'archive', 'is_author' => 'archive', 'is_date' => 'archive', 'is_archive' => 'archive', ]; foreach ( $tag_templates as $tag => $type ) { if ( function_exists( $tag ) && call_user_func( $tag ) ) { $content_type = $type; if ( 'content' != $type ) { $post_type = ''; $post_id = 0; } break; } } } // NOTE: Undocumented $content_type = apply_filters( 'bricks/database/content_type', $content_type, $post_id ); // NOTE: Undocumented $post_id = apply_filters( 'bricks/builder/data_post_id', $post_id ); self::$active_templates['post_id'] = $post_id; self::$active_templates['post_type'] = $post_type; self::$active_templates['content_type'] = $content_type; // Get all available templates $template_ids = self::get_all_templates_by_type(); // Preview id is only set if template is using populate content as single (with templatePreviewPostId) $preview_id = isset( $preview_id ) ? $preview_id : $post_id; $password_protection_template_id = 0; $excluded_ids = []; // For each template part, try to find the best template available foreach ( [ 'header', 'footer', 'content' ] as $template_part ) { if ( ! empty( self::$active_templates[ $template_part ] ) ) { continue; } $template_id = self::find_template_id( $template_ids, $template_part, $content_type, $preview_id, $preview_type ); // Check if this is a password protection template (@since 1.11.1) if ( Templates::get_template_type( $template_id ) === 'password_protection' && $template_part === 'content' ) { // Allow Password_Protection class to decide if the template should be rendered if ( Password_Protection::is_active( $template_id ) ) { $password_protection_template_id = $template_id; self::$active_templates[ $template_part ] = $template_id; // Set 'content' to password protection template ID self::$active_templates['password_protection'] = $template_id; // Set 'password_protection' to password protection template ID (used in form element to check if the form is in a password protected template) } else { // If password protection is not active, exclude it and find another template $excluded_ids[] = $template_id; $template_id = self::find_template_id( $template_ids, $template_part, $content_type, $preview_id, $preview_type, $excluded_ids ); self::$active_templates[ $template_part ] = $template_id; } } else { self::$active_templates[ $template_part ] = $template_id; } } // If a password protection template is active, apply exclusions if ( $password_protection_template_id ) { if ( Password_Protection::should_exclude_template_part( 'header', $password_protection_template_id ) ) { self::$active_templates['header'] = 0; } if ( Password_Protection::should_exclude_template_part( 'footer', $password_protection_template_id ) ) { self::$active_templates['footer'] = 0; } } /** * Get all popups * * @since 1.10.2: If maintenance mode is disabled OR popups are explicitly enabled in maintenance mode OR user can bypass maintenance mode. * @since 2.3.3: Use request-level maintenance state, so maintenance bypass filters still load popups. */ if ( ! Maintenance::is_applied() || self::get_setting( 'maintenanceRenderPopups' ) || Capabilities::current_user_can_bypass_maintenance_mode() ) { if ( ! $password_protection_template_id || ! Password_Protection::should_exclude_template_part( 'popup', $password_protection_template_id ) ) { self::$active_templates['popup'] = self::find_templates( $template_ids, 'popup', $preview_id, $preview_type ); } } // Ensure popup being previewed is included if ( Templates::get_template_type( $post_id ) === 'popup' && ! in_array( $post_id, self::$active_templates['popup'] ) ) { self::$active_templates['popup'][] = $post_id; } // If $content_type != header, footer, content, section, popup; set $active_template = content if ( isset( $content_type ) && ! in_array( $content_type, [ 'header', 'footer', 'section', 'content', 'popup' ] ) ) { self::$active_templates[ $content_type ] = self::$active_templates['content']; } // No templates defined, set page/cpt content if Bricks is supported if ( ! empty( $post_id ) && Helpers::is_post_type_supported( $post_id ) && empty( self::$active_templates['content'] ) ) { self::$active_templates['content'] = $post_id; } /** * Allow to modify the active templates * * @see https://academy.bricksbuilder.io/article/filter-bricks-active_templates/ * * @since 1.8.4 */ self::$active_templates = apply_filters( 'bricks/active_templates', self::$active_templates, $post_id, self::$active_templates['content_type'] ); // Set header position (to use in bricksData.headerPosition) if ( self::$active_templates['header'] > 0 ) { $header_position = Helpers::get_template_setting( 'headerPosition', intval( self::$active_templates['header'] ) ); self::$header_position = isset( $header_position ) && ! empty( $header_position ) ? $header_position : 'top'; } } /** * Finds the most suitable template id for a specific context * * @param array $template_ids Organized by type. * @param string $template_part header, footer or content. * @param string $content_type What type of content is expected: content, archive, search, error. * @param string $post_id Current post_id or preview_id. * @param string $preview_type If template, and populate content is set. * @param array $excluded_ids Array of template IDs to exclude from consideration. (@since 1.11.1) */ public static function find_template_id( $template_ids, $template_part, $content_type, $post_id, $preview_type, $excluded_ids = [] ) { $found_templates = []; // Hold all the found template ids for the context, with score 0.low XX.high [score=>template id] $disable_default_templates = self::get_setting( 'defaultTemplatesDisabled', false ); /** * STEP: Check for password protection templates first to ensure highest priority * Password protection templates should override any other matching template * * @since 1.12 */ if ( ! empty( $template_ids['body'] ) ) { foreach ( $template_ids['body'] as $template_id ) { // Skip excluded template IDs if ( in_array( $template_id, $excluded_ids, true ) ) { continue; } // Check if this is a password protection template if ( $template_part === 'content' && Templates::get_template_type( $template_id ) === 'password_protection' ) { $template_conditions = Helpers::get_template_setting( 'templateConditions', $template_id ); // Return immediately if conditions match if ( ! empty( self::screen_conditions( [], $template_id, $template_conditions, $post_id, $preview_type ) ) ) { return $template_id; } } } } // STEP: Continue with regular template evaluation if no password protection template matched // Loop for all the templates and template conditions and assign scores // 0 - Default (no condition set) // 1 - Default to a specific template type (I'm looking for a search template, and this is type search) // 2 - Entire website (condition = any) // 8 - Terms, specific archives, children of specific Post ID // 9 - Front page // 10 - Specific Post ID (best match) // 'body' list includes all template types != header, footer, section & popup $template_loop_type = $template_part === 'content' ? 'body' : $template_part; if ( empty( $template_ids[ $template_loop_type ] ) ) { return 0; } // Check template conditions foreach ( $template_ids[ $template_loop_type ] as $template_id ) { // Skip excluded template IDs (@since 1.11.1) if ( in_array( $template_id, $excluded_ids ) ) { continue; } $template_conditions = Helpers::get_template_setting( 'templateConditions', $template_id ); if ( ! $template_conditions ) { if ( ! $disable_default_templates ) { // No conditions, if defaults are possible, set it as default (but don't set a Search template as fallback of a Page content) if ( in_array( $template_part, [ 'header', 'footer' ] ) ) { $found_templates[0] = $template_id; } // If template_part is content, and this template type = content_type (search = search) then it might be a good default if ( 'content' === $template_part && 'content' !== $content_type && ! empty( $template_ids[ $content_type ] ) && in_array( $template_id, $template_ids[ $content_type ] ) ) { $found_templates[1] = $template_id; } } continue; } $found_templates = self::screen_conditions( $found_templates, $template_id, $template_conditions, $post_id, $preview_type ); } // Return template id with highest score. if ( ! empty( $found_templates ) ) { $max = max( array_keys( $found_templates ) ); return $found_templates[ $max ]; } // No template found return 0; } /** * Find all the templates available for a specific context based on the template conditions * * @param array $template_ids List of templates per template type. * @param string $template_part header, footer or content. */ public static function find_templates( $template_ids, $template_part, $post_id, $preview_type ) { $found_templates = []; $template_loop_type = $template_part === 'content' ? 'body' : $template_part; if ( empty( $template_ids[ $template_loop_type ] ) ) { return []; } // Check template conditions foreach ( $template_ids[ $template_loop_type ] as $template_id ) { $template_conditions = Helpers::get_template_setting( 'templateConditions', $template_id ); $found = self::screen_conditions( [], $template_id, $template_conditions, $post_id, $preview_type ); if ( ! empty( $found ) ) { $found_templates[] = $template_id; } } return $found_templates; } /** * Get all templates by type * - If Object Cache is enabled, it will return the cached templates * - If Object Cache is not enabled, it will query the database for all templates * - The templates are saved in static variable self::$all_templates so subsequent calls will return the cached templates * * @return array * - Array of template IDs organized by type (header, footer, content, archive) * @since 2.0 */ public static function get_all_templates_by_type() { // Last changed timestamp is set on Templates::flush_templates_cache() $last_changed = wp_cache_get_last_changed( 'bricks_' . BRICKS_DB_TEMPLATE_SLUG ); // Undocumented $cache_key = apply_filters( 'bricks/database/get_all_templates_cache_key', 'all_templates_' . $last_changed ); $output = wp_cache_get( $cache_key, 'bricks' ); if ( $output === false ) { // Maybe template_ids are already set in self::$all_templates (Non object cache) if ( isset( self::$all_templates ) && is_array( self::$all_templates ) && ! empty( self::$all_templates ) ) { return self::$all_templates; } // If not, get all templates from the database $args = [ 'post_type' => BRICKS_DB_TEMPLATE_SLUG, 'posts_per_page' => -1, 'post_status' => 'publish', 'fields' => 'ids', ]; /** * Filter query args for get_posts() * * Currently used by WPML to get correct templates (@see #862j3xyg7) * * @since 1.7 */ $args = apply_filters( 'bricks/database/bricks_get_all_templates_by_type_args', $args ); $template_ids = get_posts( $args ); // Undocumented: Allows integrations to restore query context after templates are queried. (#86c9vt6tw; @since 2.3.6) do_action( 'bricks/database/get_all_templates_by_type/after_query', $template_ids, $args ); $output = []; // Organize templates by type foreach ( $template_ids as $t_id ) { $type = get_post_meta( $t_id, BRICKS_DB_TEMPLATE_TYPE, true ); // Skip templates without type if ( ! $type ) { continue; } $output[ $type ][] = $t_id; if ( ! in_array( $type, [ 'header', 'footer', 'section', 'popup' ] ) ) { $output['body'][] = $t_id; // Adds to the 'body' template type all the other types like Content, Archive, Search Results, Error Page as they are a kind of body content } } // PHP Cache: For single request self::$all_templates = $output; // Object Cache: Set the templates cache for 1 day wp_cache_set( $cache_key, $output, 'bricks', DAY_IN_SECONDS ); } return $output; } /** * Set default header/footer template * * If no template with matching templateCondition(s) has been set. * * Can be disabled via admin setting 'defaultTemplatesDisabled'. * * @since 1.0 */ public static function set_default_template( $template_type = '' ) { if ( ! $template_type ) { return; } $disable_default_templates = self::get_setting( 'defaultTemplatesDisabled', false ); // Return if 'defaultTemplatesDisabled' is set $current_template_type = get_post_meta( get_the_ID(), BRICKS_DB_TEMPLATE_TYPE, true ); if ( $disable_default_templates && $current_template_type !== $template_type ) { return; } $template_ids = get_posts( [ 'post_type' => BRICKS_DB_TEMPLATE_SLUG, 'posts_per_page' => -1, 'meta_query' => [ [ 'key' => BRICKS_DB_TEMPLATE_TYPE, 'value' => $template_type, ], ], 'post_status' => 'publish', 'fields' => 'ids', ] ); $template_id = count( $template_ids ) ? $template_ids[0] : false; if ( $template_id ) { self::$active_templates[ $template_type ] = intval( $template_id ); } } /** * Helper function to screen a set of template or theme style conditions and check if they apply given the context * * @param array $found Holds array of found object IDs (the key is the score). * @param string $object_id Could be template_id or the style_id. * @param array $conditions Template or Theme Style conditions. * @param int $post_id Real or Preview). * @param string $preview_type The preview type (single, search, archive, etc.). * * @return array Found conditions array ($score => $object_id) */ public static function screen_conditions( $found, $object_id, $conditions, $post_id, $preview_type ) { if ( empty( $conditions ) ) { return $found; } $post_type = get_post_type( $post_id ); $is_valid = true; // Used to exclude this object if an excluding condition applies $scores = []; // Holds scores of this object_id $template_settings = Helpers::get_template_settings( $object_id ); // Check if this is a password protection template $pp_template_location = $template_settings['passwordProtectionSource'] ?? 'both'; $is_pp_template = $pp_template_location !== 'wordpress' ? Templates::get_template_type( $object_id ) === 'password_protection' : false; foreach ( $conditions as $condition ) { if ( ! $is_valid ) { break; } // Check if main template condition is set if ( ! isset( $condition['main'] ) ) { continue; } $exclude = isset( $condition['exclude'] ); if ( ! empty( $post_id ) ) { // 1. Check if template was set for a specific post ID or children if ( $condition['main'] === 'ids' && isset( $condition['ids'] ) ) { // WPML: Translate condition IDs to current language (@since 2.0) if ( \Bricks\Integrations\Wpml\Wpml::$is_active && has_filter( 'wpml_object_id' ) ) { foreach ( $condition['ids'] as &$condition_post_id ) { $condition_post_type = get_post_type( $condition_post_id ); if ( $condition_post_type ) { $condition_post_id = apply_filters( 'wpml_object_id', $condition_post_id, $condition_post_type, true ); } } } // Specific post ID if ( in_array( $post_id, $condition['ids'] ) ) { $is_valid = ! $exclude; $scores[] = 10; } // Apply to child pages elseif ( isset( $condition['idsIncludeChildren'] ) ) { $ancestors = get_post_ancestors( $post_id ); foreach ( $ancestors as $ancestor_id ) { if ( in_array( $ancestor_id, $condition['ids'] ) ) { $is_valid = ! $exclude; $scores[] = 8; // Less important than a template set for a specific ID break; } } } } // 2. Check if template was set for a specific term assigned to the post if ( $condition['main'] === 'terms' && isset( $condition['terms'] ) ) { $terms = $condition['terms']; foreach ( $terms as $term ) { $tax_term = explode( '::', $term ); $taxonomy = $tax_term[0]; $term_id = $tax_term[1]; // WPML: Translate term ID to current language (@since 2.0) if ( \Bricks\Integrations\Wpml\Wpml::$is_active && has_filter( 'wpml_object_id' ) && is_numeric( $term_id ) ) { $term_id = apply_filters( 'wpml_object_id', $term_id, $taxonomy, true ); } $post_terms = wp_get_post_terms( $post_id, $taxonomy, [ 'fields' => 'ids' ] ); if ( is_array( $post_terms ) && in_array( $term_id, $post_terms ) ) { $is_valid = ! $exclude; $scores[] = 8; } } } // 3. Check if template applies to a specific post type if ( $condition['main'] === 'postType' && isset( $condition['postType'] ) && in_array( $post_type, $condition['postType'] ) ) { $is_valid = ! $exclude; $scores[] = 7; } } // Archive (any/author/data/term) if ( is_archive() && $condition['main'] === 'archiveType' ) { if ( ! isset( $condition['archiveType'] ) ) { continue; } // Archive pages include category, tag, author, date, custom post type, and custom taxonomy based archives. if ( in_array( 'any', $condition['archiveType'] ) && ( is_archive() || strpos( $preview_type, 'archive' ) !== false ) ) { $is_valid = ! $exclude; $scores[] = 3; } // This condition allows for multiple values. Since is_archive includes all the following conditions we need to test them as well if ( in_array( 'postType', $condition['archiveType'] ) && ( is_post_type_archive() || $preview_type === 'archive-cpt' ) ) { if ( empty( $condition['archivePostTypes'] ) ) { $is_valid = ! $exclude; $scores[] = 7; } else { // Previewing a template with content set to a CPT archive if ( $preview_type === 'archive-cpt' ) { $preview_cpt = Helpers::get_template_setting( 'templatePreviewPostType', $post_id ); if ( $preview_cpt && in_array( $preview_cpt, $condition['archivePostTypes'] ) ) { $is_valid = ! $exclude; $scores[] = 8; } } // or, check if the post type archive matches the post type condition elseif ( is_post_type_archive( $condition['archivePostTypes'] ) ) { $is_valid = ! $exclude; $scores[] = 8; } } } elseif ( in_array( 'author', $condition['archiveType'] ) && ( is_author() || $preview_type === 'archive-author' ) ) { $is_valid = ! $exclude; $scores[] = 8; } elseif ( in_array( 'date', $condition['archiveType'] ) && ( is_date() || $preview_type === 'archive-date' ) ) { $is_valid = ! $exclude; $scores[] = 8; } elseif ( in_array( 'term', $condition['archiveType'] ) && ( is_category() || is_tag() || is_tax() || $preview_type === 'archive-term' ) ) { // Apply template to selected archive terms if ( isset( $condition['archiveTerms'] ) && is_array( $condition['archiveTerms'] ) ) { // Previewing a template, with populate content set to archive of term if ( $preview_type === 'archive-term' ) { // Note the post_id here is the template post Id (because in this archive situation the preview_id was not set) $preview_term = Helpers::get_template_setting( 'templatePreviewTerm', $post_id ); if ( ! empty( $preview_term ) ) { $preview_term = explode( '::', $preview_term ); $queried_taxonomy = isset( $preview_term[0] ) ? $preview_term[0] : ''; $queried_term_id = isset( $preview_term[1] ) ? intval( $preview_term[1] ) : ''; // WPML: Translate term ID to current language (@since 2.0) if ( \Bricks\Integrations\Wpml\Wpml::$is_active && has_filter( 'wpml_object_id' ) && $queried_term_id ) { $queried_term_id = apply_filters( 'wpml_object_id', $queried_term_id, $queried_taxonomy, true ); } } } // All the other situations in frontend: is_category() || is_tag() || is_tax() else { $queried_object = get_queried_object(); if ( is_object( $queried_object ) ) { $queried_term_id = intval( $queried_object->term_id ); $queried_taxonomy = $queried_object->taxonomy; // WPML: Translate term ID to current language (@since 2.0) if ( \Bricks\Integrations\Wpml\Wpml::$is_active && has_filter( 'wpml_object_id' ) && $queried_term_id ) { $queried_term_id = apply_filters( 'wpml_object_id', $queried_term_id, $queried_taxonomy, true ); } } } // Check if queried taxonomy and term_id matches any of the selected archive terms if ( ! empty( $queried_term_id ) && ! empty( $queried_taxonomy ) ) { foreach ( $condition['archiveTerms'] as $archive_term ) { $term_parts = explode( '::', $archive_term ); $taxonomy = $term_parts[0]; $term_id = $term_parts[1]; // WPML: Translate condition term ID to current language (@since 2.0) if ( \Bricks\Integrations\Wpml\Wpml::$is_active && has_filter( 'wpml_object_id' ) && is_numeric( $term_id ) && $term_id !== 'all' ) { $term_id = apply_filters( 'wpml_object_id', $term_id, $taxonomy, true ); } if ( $queried_taxonomy === $taxonomy ) { if ( $queried_term_id === intval( $term_id ) ) { $is_valid = ! $exclude; $scores[] = 8; break; } // Applied for taxonomy::all (all terms of a taxonomy) elseif ( 'all' == $term_id ) { $is_valid = ! $exclude; $scores[] = 7; break; } // The condition includes child terms, check if the queried term id is child of the term id set in the condition elseif ( isset( $condition['archiveTermsIncludeChildren'] ) && term_is_ancestor_of( $term_id, $queried_term_id, $queried_taxonomy ) ) { $is_valid = ! $exclude; $scores[] = 8; break; } } } } } // Apply template to all archives terms else { $is_valid = ! $exclude; $scores[] = 4; } } } // End archive test // Check for search elseif ( $condition['main'] === 'search' && ( is_search() || $preview_type === 'search' ) ) { $is_valid = ! $exclude; $scores[] = 8; } // Check for error elseif ( $condition['main'] === 'error' && ( is_404() || $preview_type === 'error' ) ) { $is_valid = ! $exclude; $scores[] = 8; } // Check for front page (it might compete with single post rules) if ( $condition['main'] === 'frontpage' ) { // Use 'page_on_front' option where the main query does not represent the frontend URL. if ( bricks_is_ajax_call() || bricks_is_rest_call() || ( is_admin() && $post_id ) ) { // Use 'page_on_front' option as is_front_page() is not reliable in non-frontend contexts. $front_page_id = get_option( 'page_on_front' ); // WPML: Translate front page ID to current language (@since 2.0) if ( \Bricks\Integrations\Wpml\Wpml::$is_active && has_filter( 'wpml_object_id' ) && $front_page_id ) { $front_page_id = apply_filters( 'wpml_object_id', $front_page_id, 'page', true ); } $is_front_page = absint( $post_id ) == absint( $front_page_id ); } else { $is_front_page = is_front_page(); } if ( $is_front_page ) { $is_valid = ! $exclude; $scores[] = 9; } } // Check for entire website if ( $condition['main'] === 'any' ) { $is_valid = ! $exclude; $scores[] = 2; } // Is password protection template: For each valid score increase priority by 100 if ( $is_pp_template ) { $scores = array_map( function( $score ) { return $score + 100; // Add to existing score }, $scores ); } /** * For each template (and theme style) condition allow setting a score based on custom template conditions (which are set via: builder/settings/{$this->setting_type}/controls_data) * * https://academy.bricksbuilder.io/article/filter-bricks-screen_conditions-scores/ * * @since 1.5.5 */ $scores = apply_filters( 'bricks/screen_conditions/scores', $scores, $condition, $post_id, $preview_type ); } if ( $is_valid ) { // Only remove duplicates if the theme styles loading method is set to the default, which is most-specific (@since 2.0) if ( ! self::get_setting( 'themeStylesLoadingMethod' ) ) { $scores = array_unique( $scores ); } foreach ( $scores as $score ) { $found[ $score ] = $object_id; } } return $found; } /** * Check if header or footer is disabled (via page settings) for the current context * * Page setting keys: headerDisabled, footerDisabled * * @return bool * @since 1.5.4 */ public static function is_template_disabled( $template_type ) { $setting_key = "{$template_type}Disabled"; $original_post_id = self::$page_data['original_post_id'] ?? 0; // Return: Previewing header or footer template if ( $original_post_id && Templates::get_template_type( $original_post_id ) === $template_type ) { return false; } $template_id = self::$active_templates['content'] ?? 0; /** * Post rendered through template and post has Bricks data: Get page settings from post instead of template * * @since 1.10.2: Exclude archive pages as they can't by edited directly with Bricks */ if ( $template_id && $template_id !== $original_post_id && ! is_archive() ) { $page_settings = get_post_meta( $original_post_id, BRICKS_DB_PAGE_SETTINGS, true ); if ( isset( $page_settings[ $setting_key ] ) ) { return true; } } return isset( self::$page_settings[ $setting_key ] ); } /** * Get template elements * * @since 1.0 * * @param string $content_type Type of content (header, content, footer). * @param boolean $force_post_data Force checking only the specific post data without considering templates. */ public static function get_template_data( $content_type, $force_post_data = false ) { switch ( $content_type ) { case 'header': if ( self::is_template_disabled( 'header' ) ) { return; } $meta_key = BRICKS_DB_PAGE_HEADER; break; case 'footer': if ( self::is_template_disabled( 'footer' ) ) { return; } $meta_key = BRICKS_DB_PAGE_FOOTER; break; default: $meta_key = BRICKS_DB_PAGE_CONTENT; break; } $template_id = self::$active_templates[ $content_type ] ?? false; // Only check active templates if force_post_data is false (@since 1.12.2) if ( $force_post_data ) { $template_id = false; } // No template found: Return Bricks content data if ( ! is_archive() && ! is_search() && ! $template_id && $content_type !== 'header' && $content_type !== 'footer' ) { $elements = get_post_meta( get_the_ID(), BRICKS_DB_PAGE_CONTENT, true ); } else { $elements = get_post_meta( $template_id, $meta_key, true ); } return $elements; } /** * Get Bricks data by post_id and content_area (header/content/footer) * * @since 1.0 */ public static function get_data( $post_id = 0, $content_area = '' ) { if ( ! $post_id ) { $post_id = get_the_ID(); } $meta_key = self::get_bricks_data_key( $content_area ); $elements = get_post_meta( $post_id, $meta_key, true ); return is_array( $elements ) ? $elements : []; } /** * Get the Bricks data key for a specific template type (header/content/footer) * * @since 1.5.1 * * @param string $content_area * @return string */ public static function get_bricks_data_key( $content_area = '' ) { switch ( $content_area ) { case 'header': $meta_key = BRICKS_DB_PAGE_HEADER; break; case 'footer': $meta_key = BRICKS_DB_PAGE_FOOTER; break; default: $meta_key = BRICKS_DB_PAGE_CONTENT; break; } return $meta_key; } /** * Get global settings from options table * * @since 1.0 */ public static function get_setting( $key, $default = false ) { return isset( self::$global_settings[ $key ] ) ? self::$global_settings[ $key ] : $default; } /** * Get global queries from the correct site store. * * @since 2.3.2 * * @return array */ public static function get_global_queries() { if ( is_multisite() && BRICKS_MULTISITE_USE_MAIN_SITE_GLOBAL_QUERIES ) { return get_blog_option( get_main_site_id(), BRICKS_DB_GLOBAL_QUERIES, [] ); } return get_option( BRICKS_DB_GLOBAL_QUERIES, [] ); } /** * Update global queries in the correct site store. * * @since 2.3.2 * * @param array $global_queries Global queries. * * @return bool */ public static function update_global_queries( $global_queries ) { if ( is_multisite() && BRICKS_MULTISITE_USE_MAIN_SITE_GLOBAL_QUERIES ) { $updated = update_blog_option( get_main_site_id(), BRICKS_DB_GLOBAL_QUERIES, $global_queries ); } else { $updated = update_option( BRICKS_DB_GLOBAL_QUERIES, $global_queries ); } if ( $updated ) { self::$global_data['globalQueries'] = $global_queries; } return $updated; } /** * Get global data from options table * * @since 1.0 */ public static function get_global_data() { // Components if ( is_multisite() && BRICKS_MULTISITE_USE_MAIN_SITE_COMPONENTS ) { self::$global_data['components'] = get_blog_option( get_main_site_id(), BRICKS_DB_COMPONENTS, [] ); } else { self::$global_data['components'] = get_option( BRICKS_DB_COMPONENTS, [] ); } // Color palette if ( is_multisite() && BRICKS_MULTISITE_USE_MAIN_SITE_COLOR_PALETTE ) { self::$global_data['colorPalette'] = get_blog_option( get_main_site_id(), BRICKS_DB_COLOR_PALETTE, [] ); } else { self::$global_data['colorPalette'] = get_option( BRICKS_DB_COLOR_PALETTE, [] ); } // Populate with default colors if color palette is not an array (@since 2.2) if ( ! is_array( self::$global_data['colorPalette'] ) || empty( self::$global_data['colorPalette'] ) ) { self::$global_data['colorPalette'] = self::default_color_palette(); } // Style Manager (@since 2.2) self::$global_data['styleManager'] = get_option( BRICKS_DB_STYLE_MANAGER, null ); // Global queries (@since 2.1) self::$global_data['globalQueries'] = self::get_global_queries(); // Global queries categories (@since 2.1) if ( is_multisite() && BRICKS_MULTISITE_USE_MAIN_SITE_GLOBAL_QUERIES_CATEGORIES ) { self::$global_data['globalQueriesCategories'] = get_blog_option( get_main_site_id(), BRICKS_DB_GLOBAL_QUERIES_CATEGORIES, [] ); } else { self::$global_data['globalQueriesCategories'] = get_option( BRICKS_DB_GLOBAL_QUERIES_CATEGORIES, [] ); } // Icon sets if ( is_multisite() && BRICKS_MULTISITE_USE_MAIN_SITE_ICON_SETS ) { self::$global_data['iconSets'] = get_blog_option( get_main_site_id(), BRICKS_DB_ICON_SETS, [] ); } else { self::$global_data['iconSets'] = get_option( BRICKS_DB_ICON_SETS, [] ); } // Custom icons if ( is_multisite() && BRICKS_MULTISITE_USE_MAIN_SITE_CUSTOM_ICONS ) { self::$global_data['customIcons'] = get_blog_option( get_main_site_id(), BRICKS_DB_CUSTOM_ICONS, [] ); } else { self::$global_data['customIcons'] = get_option( BRICKS_DB_CUSTOM_ICONS, [] ); } // Disabled icon sets if ( is_multisite() && BRICKS_MULTISITE_USE_MAIN_SITE_DISABLED_ICON_SETS ) { self::$global_data['disabledIconSets'] = get_blog_option( get_main_site_id(), BRICKS_DB_DISABLED_ICON_SETS, [] ); } else { self::$global_data['disabledIconSets'] = get_option( BRICKS_DB_DISABLED_ICON_SETS, [] ); } // Font favorites (@since 2.0) if ( is_multisite() && BRICKS_MULTISITE_USE_MAIN_SITE_FONT_FAVORITES ) { self::$global_data['fontFavorites'] = get_blog_option( get_main_site_id(), BRICKS_DB_FONT_FAVORITES, [] ); } else { self::$global_data['fontFavorites'] = get_option( BRICKS_DB_FONT_FAVORITES, [] ); } // Global classes if ( is_multisite() && BRICKS_MULTISITE_USE_MAIN_SITE_CLASSES ) { self::$global_data['globalClasses'] = get_blog_option( get_main_site_id(), BRICKS_DB_GLOBAL_CLASSES, [] ); } else { self::$global_data['globalClasses'] = get_option( BRICKS_DB_GLOBAL_CLASSES, [] ); } // Global classes trash if ( is_multisite() && BRICKS_MULTISITE_USE_MAIN_SITE_CLASSES ) { self::$global_data['globalClassesTrash'] = get_blog_option( get_main_site_id(), BRICKS_DB_GLOBAL_CLASSES_TRASH, [] ); } else { self::$global_data['globalClassesTrash'] = get_option( BRICKS_DB_GLOBAL_CLASSES_TRASH, [] ); } // Global classes categories if ( is_multisite() && BRICKS_MULTISITE_USE_MAIN_SITE_CLASSES_CATEGORIES ) { self::$global_data['globalClassesCategories'] = get_blog_option( get_main_site_id(), BRICKS_DB_GLOBAL_CLASSES_CATEGORIES, [] ); } else { self::$global_data['globalClassesCategories'] = get_option( BRICKS_DB_GLOBAL_CLASSES_CATEGORIES, [] ); } // Builder: Global classes locked if ( bricks_is_builder() ) { if ( is_multisite() && BRICKS_MULTISITE_USE_MAIN_SITE_CLASSES ) { self::$global_data['globalClassesLocked'] = get_blog_option( get_main_site_id(), BRICKS_DB_GLOBAL_CLASSES_LOCKED, [] ); } else { self::$global_data['globalClassesLocked'] = get_option( BRICKS_DB_GLOBAL_CLASSES_LOCKED, [] ); } } // Builder: Global classes timestamp (@since 1.9.9) if ( bricks_is_builder() ) { if ( is_multisite() && BRICKS_MULTISITE_USE_MAIN_SITE_CLASSES ) { self::$global_data['globalClassesTimestamp'] = get_blog_option( get_main_site_id(), BRICKS_DB_GLOBAL_CLASSES_TIMESTAMP, [] ); } else { self::$global_data['globalClassesTimestamp'] = get_option( BRICKS_DB_GLOBAL_CLASSES_TIMESTAMP, [] ); } } // Builder: Global classes user_id (@since 1.9.9) if ( bricks_is_builder() ) { if ( is_multisite() && BRICKS_MULTISITE_USE_MAIN_SITE_CLASSES ) { self::$global_data['globalClassesUser'] = get_blog_option( get_main_site_id(), BRICKS_DB_GLOBAL_CLASSES_USER, [] ); } else { self::$global_data['globalClassesUser'] = get_option( BRICKS_DB_GLOBAL_CLASSES_USER, [] ); } if ( ! empty( self::$global_data['globalClassesUser'] ) ) { self::$global_data['globalClassesUser'] = get_userdata( self::$global_data['globalClassesUser'] )->display_name ?? ''; } } $default_pseudo_classes = [ ':hover', ':active', ':focus', ]; if ( is_multisite() && BRICKS_MULTISITE_USE_MAIN_SITE_CLASSES ) { self::$global_data['pseudoClasses'] = get_blog_option( get_main_site_id(), BRICKS_DB_PSEUDO_CLASSES, $default_pseudo_classes ); } else { self::$global_data['pseudoClasses'] = get_option( BRICKS_DB_PSEUDO_CLASSES, $default_pseudo_classes ); } // Global elements if ( is_multisite() && BRICKS_MULTISITE_USE_MAIN_SITE_GLOBAL_ELEMENTS ) { self::$global_data['elements'] = get_blog_option( get_main_site_id(), BRICKS_DB_GLOBAL_ELEMENTS, [] ); } else { self::$global_data['elements'] = get_option( BRICKS_DB_GLOBAL_ELEMENTS, [] ); } // Global settings self::$global_data['settings'] = get_option( BRICKS_DB_GLOBAL_SETTINGS, [] ); // Remove slashes from custom CSS & JS if ( is_array( self::$global_data['settings'] ) ) { self::$global_data['settings'] = stripslashes_deep( self::$global_data['settings'] ); } // Set global gettings self::$global_settings = self::$global_data['settings']; /** * Disable lazy load in builder * * To generate template screenshots in builder. * * @since 1.10 */ if ( bricks_is_builder_call() ) { self::$global_settings['disableLazyLoad'] = true; } // Global variables, if not disable in Bricks settings (since 1.9.8) if ( ! isset( self::$global_settings['disableVariablesManager'] ) ) { if ( is_multisite() && BRICKS_MULTISITE_USE_MAIN_SITE_VARIABLES_CATEGORIES ) { self::$global_data['globalVariables'] = get_blog_option( get_main_site_id(), BRICKS_DB_GLOBAL_VARIABLES, [] ); } else { self::$global_data['globalVariables'] = get_option( BRICKS_DB_GLOBAL_VARIABLES, [] ); } } // Global variables categories (since 1.9.8) if ( is_multisite() && BRICKS_MULTISITE_USE_MAIN_SITE_VARIABLES_CATEGORIES ) { self::$global_data['globalVariablesCategories'] = get_blog_option( get_main_site_id(), BRICKS_DB_GLOBAL_VARIABLES_CATEGORIES, [] ); } else { self::$global_data['globalVariablesCategories'] = get_option( BRICKS_DB_GLOBAL_VARIABLES_CATEGORIES, [] ); } // Adobe fonts: If project ID set (@since 1.7.1) if ( ! empty( self::$global_settings['adobeFontsProjectId'] ) ) { self::$adobe_fonts = get_option( BRICKS_DB_ADOBE_FONTS, [] ); } } /** * Default color palette (https://www.materialui.co/colors) * * Only used if no custom colorPalette is saved in db. * * @since 1.0 * * @since 2.2: Use 'light' key for colors instead of 'hex' * * @return array */ public static function default_color_palette() { $colors = [ // Grey [ 'light' => '#f5f5f5', 'raw' => 'var(--bricks-color-grey-100)' ], [ 'light' => '#e0e0e0', 'raw' => 'var(--bricks-color-grey-300)' ], [ 'light' => '#9e9e9e', 'raw' => 'var(--bricks-color-grey-500)' ], [ 'light' => '#616161', 'raw' => 'var(--bricks-color-grey-700)' ], [ 'light' => '#424242', 'raw' => 'var(--bricks-color-grey-800)' ], [ 'light' => '#212121', 'raw' => 'var(--bricks-color-grey-900)' ], // Warm colors [ 'light' => '#ffeb3b', 'raw' => 'var(--bricks-color-yellow)', ], [ 'light' => '#ffc107', 'raw' => 'var(--bricks-color-amber)', ], [ 'light' => '#ff9800', 'raw' => 'var(--bricks-color-orange)', ], [ 'light' => '#ff5722', 'raw' => 'var(--bricks-color-deep-orange)', ], [ 'light' => '#f44336', 'raw' => 'var(--bricks-color-red)', ], [ 'light' => '#9c27b0', 'raw' => 'var(--bricks-color-purple)', ], // Cool colors [ 'light' => '#2196f3', 'raw' => 'var(--bricks-color-blue)', ], [ 'light' => '#03a9f4', 'raw' => 'var(--bricks-color-light-blue)', ], [ 'light' => '#81D4FA', 'raw' => 'var(--bricks-color-sky-blue)', ], [ 'light' => '#4caf50', 'raw' => 'var(--bricks-color-green)', ], [ 'light' => '#8bc34a', 'raw' => 'var(--bricks-color-light-green)', ], [ 'light' => '#cddc39', 'raw' => 'var(--bricks-color-lime)', ], ]; $colors = apply_filters( 'bricks/builder/color_palette', $colors ); foreach ( $colors as $index => $color ) { $color_id = Helpers::generate_random_id( false ); $colors[ $index ]['id'] = $color_id; } $palettes[] = [ 'id' => Helpers::generate_random_id( false ), 'name' => 'Default', 'colors' => $colors, ]; return $palettes; } /** * Set page data needed for AJAX calls (builder) * * @since 1.3 */ public static function set_ajax_page_data() { if ( ! bricks_is_ajax_call() || empty( $_POST['action'] ) || strpos( $_POST['action'], 'bricks_' ) !== 0 ) { return; } // In the "bricks_regenerate_css_file" ajax call, the post ID is set in the "data" property $post_id = isset( $_POST['postId'] ) ? intval( $_POST['postId'] ) : ( isset( $_POST['data'] ) && is_numeric( $_POST['data'] ) ? intval( $_POST['data'] ) : 0 ); self::$page_data['original_post_id'] = $post_id; self::$page_data['post_id'] = $post_id; /** * Set current page type * * Currently in AJAX calls set it to empty string (can be improved in the future). * * @since 1.8 */ self::$page_data['current_page_type'] = ''; // Check for template preview post ID $template_preview_post_id = Helpers::get_template_setting( 'templatePreviewPostId', $post_id ); self::$page_data['preview_or_post_id'] = empty( $template_preview_post_id ) ? $post_id : $template_preview_post_id; /** * Set current page type if the this is bricks template * * Helpers::is_bricks_template() and Helpers::get_queried_object() rely on this. * * @since 1.9.5 */ if ( Helpers::is_bricks_preview() && get_post_type( $post_id ) === BRICKS_DB_TEMPLATE_SLUG ) { self::$page_data['current_page_type'] = 'post'; } } /** * Get page data from post meta * * @since 1.0 */ public static function set_page_data( $post_id = 0 ) { if ( ! $post_id || is_object( $post_id ) ) { $post_id = get_the_ID(); } /** * Frontend: Current page is not a single post page * * E.g.: archive, search results, author page, etc. * * To get the user_id on the author page, we need to get the queried object ID. * * @since 1.7.1 */ if ( ! is_singular() && ! bricks_is_builder_call() ) { $post_id = get_queried_object_id(); } // Home: Set post ID to posts page if ( is_home() ) { $post_id = get_option( 'page_for_posts' ); } // NOTE: Undocumented $post_id = apply_filters( 'bricks/builder/data_post_id', $post_id ); // @since 1.8 - Set current page type self::$page_data['current_page_type'] = apply_filters( 'bricks/builder/current_page_type', self::get_current_page_type( get_queried_object() ) ); // Keep $original_post_id integrity. set_page_data() also runs on Assets::generate_inline_css() for inner templates self::$page_data['original_post_id'] = ! empty( self::$page_data['original_post_id'] ) ? self::$page_data['original_post_id'] : $post_id; // $preview_or_post_id gets populated with template preview post ID OR original post ID $template_preview_post_id = get_post_type( self::$page_data['original_post_id'] ) === BRICKS_DB_TEMPLATE_SLUG ? Helpers::get_template_setting( 'templatePreviewPostId', self::$page_data['original_post_id'] ) : 0; self::$page_data['preview_or_post_id'] = empty( $template_preview_post_id ) ? self::$page_data['original_post_id'] : $template_preview_post_id; self::$page_data['post_id'] = $post_id; // Page header $page_header = self::get_data( $post_id, 'header' ); self::$page_data['header'] = is_array( $page_header ) && count( $page_header ) ? $page_header : []; // Page content $page_content = self::get_data( $post_id, 'content' ); self::$page_data['content'] = is_array( $page_content ) && count( $page_content ) ? $page_content : []; // Page footer $page_footer = self::get_data( $post_id, 'footer' ); self::$page_data['footer'] = is_array( $page_footer ) && count( $page_footer ) ? $page_footer : []; /** * Page settings * * Builder: Use $post_id * Frontend: Use active template ID * * @see #86bx4t5v3 */ $page_settings_id = $post_id; if ( ! bricks_is_builder() && ! empty( self::$active_templates['content'] ) ) { $page_settings_id = self::$active_templates['content']; } $page_settings = get_post_meta( $page_settings_id, BRICKS_DB_PAGE_SETTINGS, true ); self::$page_data['settings'] = is_array( $page_settings ) && count( $page_settings ) ? $page_settings : []; /** * Remove slashes from custom JS * * @since 1.9.5: Skip page settings custom CSS as its not auto-escaped as the global settings, which are stored in the options table * @since 1.10: Skip page settings custom JavaScript as well */ if ( is_array( self::$page_data['settings'] ) ) { foreach ( self::$page_data['settings'] as $key => $value ) { if ( $key === 'customCss' || $key === 'customScriptsHeader' || $key === 'customScriptsBodyHeader' || $key === 'customScriptsBodyFooter' ) { continue; } self::$page_data['settings'][ $key ] = stripslashes_deep( $value ); } } // Set page gettings self::$page_settings = self::$page_data['settings']; } /** * Return current page type, not considering AJAX calls * * @param object $object Queried object. * * @since 1.8 */ public static function get_current_page_type( $object ) { if ( is_search() ) { return 'search'; } if ( is_404() ) { return '404'; } if ( is_a( $object, 'WP_Post' ) ) { return 'post'; } if ( is_a( $object, 'WP_Term' ) ) { return 'term'; } if ( is_a( $object, 'WP_User' ) ) { return 'user'; } if ( is_a( $object, 'WP_Post_Type' ) ) { return 'archive'; } if ( is_object( $object ) ) { return strtolower( get_class( $object ) ); } } /** * Get Components data with improved performance and nested component support * Currently set to a maximum depth of 10 to prevent infinite recursion * - If the main query set inside 10 nested components then this logic will not work, practically impossible right? * * @since 2.0 * @param array $bricks_data The elements data array * @return array The modified elements data with components settings and nested components included */ public static function get_component_data( $bricks_data = [], $max_depth = 10 ) { // Early return if not an array if ( ! is_array( $bricks_data ) || empty( $bricks_data ) ) { return $bricks_data; } // Process all components recursively with depth tracking return self::process_components_recursive( $bricks_data, [], $max_depth ); } /** * Process components recursively with depth tracking * * @since 2.0 * @param array $elements Elements to process * @param array $processed_ids IDs of already processed components to prevent circular references * @param int $depth_remaining Remaining recursion depth * @param string $parent_component_id Parent component ID (for nested components) * @param string $parent_instance_id Parent instance ID (for nested components) * @return array Processed elements with all nested components */ private static function process_components_recursive( $elements, $processed_ids = [], $depth_remaining = 10, $parent_component_id = '', $parent_instance_id = '' ) { // Prevent infinite recursion if ( $depth_remaining <= 0 ) { return $elements; } $result = []; $elements_to_add = []; // First pass: Process all elements and identify components foreach ( $elements as $element ) { $component_id = $element['cid'] ?? false; // Not a component - add to result unchanged if ( ! $component_id ) { $result[] = $element; continue; } // Prevent circular references $instance_key = $component_id . '_' . ( $element['id'] ?? '' ); if ( in_array( $instance_key, $processed_ids, true ) ) { $result[] = $element; continue; } // Mark this component as processed $processed_ids[] = $instance_key; // Get component instance $component_instance = Helpers::get_component_instance( $element ); if ( ! $component_instance || empty( $component_instance['elements'] ) ) { $result[] = $element; continue; } $component_elements = $component_instance['elements']; // Update the component element with settings from component instance foreach ( $component_elements as $component_element ) { // Set hierarchy tracking data $component_element['parentComponent'] = $component_id; $component_element['instanceId'] = $element['id']; // Track root component for deeper nesting (optional) if ( $parent_component_id ) { $component_element['rootComponent'] = $parent_component_id; $component_element['rootInstanceId'] = $parent_instance_id; } // If this is the main component element, update the original element if ( $component_element['id'] === $component_id ) { if ( ! empty( $component_element['settings'] ) ) { $element['settings'] = $component_element['settings']; } if ( ! empty( $component_element['children'] ) ) { $element['children'] = $component_element['children']; } } // Otherwise, collect for adding later else { $elements_to_add[] = $component_element; } } // Add the updated element to results $result[] = $element; } // Second pass: Process all collected nested elements (if any) if ( ! empty( $elements_to_add ) ) { // Process nested components recursively with reduced depth $processed_nested_elements = self::process_components_recursive( $elements_to_add, $processed_ids, $depth_remaining - 1, $parent_component_id ?: $component_id, $parent_instance_id ?: ( $element['id'] ?? '' ) ); // Merge processed nested elements into result $result = array_merge( $result, $processed_nested_elements ); } return $result; } /** * Recursively retrieve nested template data * * @param array $bricks_data The elements data array to search for template elements * * Add 3 more parameters to prvent infinite recursion (#86c99238z; @since 2.3.3) * @param array $processed_template_ids Array of already processed template IDs to prevent infinite loops * @param int $depth Current recursion depth * @param int $max_depth Maximum recursion depth to prevent infinite loops (10 for now, can be adjusted as needed) * * @return array * * @since 1.9.1 */ public static function get_nested_template_data( $bricks_data = [], $processed_template_ids = [], $depth = 0, $max_depth = 10 ) { // If the input is not an array, return it as is if ( ! is_array( $bricks_data ) ) { return $bricks_data; } // Safety check to prevent infinite recursion (#86c99238z; @since 2.3.3) if ( $depth > $max_depth ) { return $bricks_data; } // STEP: Find template elements in the array $found_template_elements = array_filter( $bricks_data, function( $element ) { return isset( $element['name'] ) && in_array( $element['name'], [ 'template' ] ); } ); // If no template elements found, return the original array if ( empty( $found_template_elements ) ) { return $bricks_data; } // STEP: Retrieve nested template data from the $found_template_elements $nested_template_data = []; $new_template_found = false; foreach ( $found_template_elements as $element ) { $template_id = isset( $element['settings']['template'] ) ? $element['settings']['template'] : false; // If no template ID found, skip to the next element if ( ! $template_id ) { continue; } // Prevent processing the same template multiple times (in case of circular references) (#86c99238z; @since 2.3.3) if ( in_array( $template_id, $processed_template_ids, true ) ) { continue; } $processed_template_ids[] = $template_id; // Mark this template as processed $new_template_found = true; // Retrieve the template data using the template ID $template_data = get_post_meta( $template_id, BRICKS_DB_PAGE_CONTENT, true ); // If template data found, merge it into the $nested_template_data if ( ! empty( $template_data ) && is_array( $template_data ) ) { // Store the template data in $nested_template_data $nested_template_data = array_replace_recursive( $nested_template_data, $template_data ); // Store the template data in the page data (might be used later) self::$page_data['template_data'][ $template_id ] = $template_data; } } // If no new template found, return the original array to prevent infinite loops (#86c99238z; @since 2.3.3) if ( ! $new_template_found || empty( $nested_template_data ) ) { return $bricks_data; } // STEP: Maybe there are nested template element inside $nested_template_data (recursion) $recursive_nested_template_data = self::get_nested_template_data( $nested_template_data, $processed_template_ids, $depth + 1, $max_depth ); if ( ! empty( $recursive_nested_template_data ) ) { $bricks_data = array_merge_recursive( $bricks_data, $recursive_nested_template_data ); } return $bricks_data; } /** * Get elements sequence in builder * * This is used to determine the order of elements in the builder. * * @since 1.9.1 * * @return array (sequence of ids) */ public static function elements_sequence_in_builder( $elements ) { $top_level_elements = []; // Get top level elements foreach ( $elements as $element ) { if ( ! isset( $element['parent'] ) || empty( $element['parent'] ) ) { $top_level_elements[] = $element; } } $sequence_of_ids = []; // Get sequence of ids starting from top level elements foreach ( $top_level_elements as $element ) { $sequence_of_ids[] = $element['id']; $sequence_of_ids = array_merge( $sequence_of_ids, self::get_ids_by_children( $elements, $element ) ); } return $sequence_of_ids; } /** * Get sequence of ids by children * * @since 1.9.1 */ public static function get_ids_by_children( $elements, $parent_element ) { $sequence = []; $children_ids = isset( $parent_element['children'] ) ? $parent_element['children'] : false; // Follow the order of the children foreach ( $children_ids as $child_id ) { $sequence[] = $child_id; $child_element = self::get_element_by_id( $child_id, $elements ); if ( is_array( $child_element ) && isset( $child_element['children'] ) && ! empty( $child_element['children'] ) ) { $sequence = array_merge( $sequence, self::get_ids_by_children( $elements, $child_element ) ); // Recursion } } return $sequence; } /** * Get the element by id from elements array * * @since 1.9.1 */ public static function get_element_by_id( $element_id, $elements ) { $element = array_filter( $elements, function( $element ) use ( $element_id ) { return $element['id'] === $element_id; } ); if ( ! empty( $element ) ) { return array_shift( $element ); } return false; } /** * Set page data language for WPML or Polylang * #86c94gr3q * * @since 2.3.2 */ public static function set_page_data_language( $language ) { if ( empty( $language ) || ! is_string( $language ) ) { return; } self::$page_data['language'] = sanitize_key( $language ); } }
修改文件时间
将文件时间修改为当前时间的前一年
删除文件