dvadf
File manager - Edit - /home/centroca/public_html/wp/wp-content/plugins/nextgen-gallery/src/Display/GalleryDetector.php
Back
<?php namespace Imagely\NGG\Display; /** * Detects whether the current frontend page contains any NextGEN Gallery content. * * Used to gate asset loading — zero assets should load on pages with no gallery. * Detection runs once per request and caches the result. * * Handles: * - Shortcodes ([ngg], [ngg_images], [nggallery] and any registered aliases) * - Gutenberg blocks (imagely/main-block, imagely/nextgen-gallery) * - Widget areas (Gallery and Slideshow widgets) * - Block-based widget areas (WP 5.8+) and FSE template parts (wp_block, wp_template_part) * - Page builder postmeta (Elementor, Beaver Builder, Divi) * * False positives are acceptable. False negatives (missing a real gallery) are not. * * Apply the `nextgen_load_assets_on_page` filter to override detection for edge cases * (e.g., galleries inserted via JavaScript after page load, or custom template tags). * * Third-party integrations (page builders, custom renderers) can hook `ngg_page_has_gallery` * to return true for a given post when they know a gallery is present. */ class GalleryDetector { /** * Cached detection result for the current request. * * @var bool|null */ private static $result = null; /** * Returns true if the current page contains any NextGEN Gallery content. * Result is cached for the lifetime of the request. */ public static function has_gallery(): bool { if ( null !== self::$result ) { return self::$result; } self::$result = (bool) apply_filters( 'nextgen_load_assets_on_page', self::detect() ); return self::$result; } /** * Resets the cached result. Used in tests or when content changes after detection ran. */ public static function reset() { self::$result = null; } // ── Detection methods ───────────────────────────────────────────────────── private static function detect(): bool { // Skip REST requests — no front-end rendering. if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) { return false; } // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.ValidatedSanitizedInput.MissingUnslash if ( isset( $_SERVER['REQUEST_URI'] ) && false !== strpos( $_SERVER['REQUEST_URI'], 'wp-json' ) ) { return false; } // Skip admin pages. if ( is_admin() ) { return false; } return self::check_content() || self::check_widgets() || self::check_block_templates() || self::check_term_description(); } /** * Checks if any NGG shortcode or Gutenberg block appears in the current query's posts. * Single pass over posts for shortcode regex, block detection, page builder postmeta, * and the `ngg_page_has_gallery` filter for third-party integrations. */ private static function check_content(): bool { global $wp_query; if ( empty( $wp_query->posts ) || ! is_array( $wp_query->posts ) ) { return false; } $shortcode_manager = Shortcodes::get_instance(); $shortcodes = array_keys( $shortcode_manager->get_shortcodes() ); $pattern = null; if ( ! empty( $shortcodes ) ) { $tags = array_map( function ( $tag ) { return preg_quote( $tag, '/' ); }, $shortcodes ); $pattern = '/\[(' . implode( '|', $tags ) . ')[\s\/\]]/'; } $ngg_blocks = [ 'imagely/main-block', 'imagely/nextgen-gallery', ]; // Page builder postmeta keys that may contain serialized shortcodes or layout data. $builder_meta_keys = [ '_elementor_data', 'fl_builder_data', '_et_pb_use_builder' ]; foreach ( $wp_query->posts as $post ) { // Allow page builder integrations and custom renderers to signal a gallery is present. if ( apply_filters( 'ngg_page_has_gallery', false, $post ) ) { return true; } if ( empty( $post->post_content ) ) { continue; } if ( $pattern && preg_match( $pattern, $post->post_content ) ) { return true; } foreach ( $ngg_blocks as $block_name ) { if ( has_block( $block_name, $post ) ) { return true; } } // Check page builder postmeta for embedded NGG shortcodes (Elementor, Beaver Builder, Divi). if ( $pattern ) { foreach ( $builder_meta_keys as $meta_key ) { $meta_value = get_post_meta( $post->ID, $meta_key, true ); if ( $meta_value && is_string( $meta_value ) && preg_match( $pattern, $meta_value ) ) { return true; } } } } return false; } /** * Checks if any NextGEN widget is active in any classic sidebar. * We check for registered NGG widget ID bases in the active widgets option. * This is a conservative check — if a widget area exists with an NGG widget, * we load assets regardless of whether that sidebar renders on this page. */ private static function check_widgets(): bool { $sidebars = get_option( 'sidebars_widgets', [] ); if ( empty( $sidebars ) || ! is_array( $sidebars ) ) { return false; } // NGG widget ID bases (as registered in Widget/Gallery.php and Widget/Slideshow.php). $ngg_widget_bases = [ 'ngg-images', // Gallery widget 'slideshow', // Slideshow widget ]; foreach ( $sidebars as $sidebar => $widgets ) { if ( 'wp_inactive_widgets' === $sidebar ) { continue; } if ( ! is_array( $widgets ) ) { continue; } foreach ( $widgets as $widget_id ) { foreach ( $ngg_widget_bases as $base ) { if ( 0 === strpos( (string) $widget_id, $base ) ) { return true; } } } } return false; } /** * Checks block-based widget areas (WP 5.8+) and FSE template parts for NGG content. * wp_block posts back block widget areas; wp_template_part posts back FSE headers/footers. * An NGG block or shortcode in a global template part would render on every page. * * Result is stored in the WP object cache so Redis/Memcached provides cross-request * relief — the queries only hit the DB once until the cache is cleared. */ private static function check_block_templates(): bool { $cache_key = 'ngg_gallery_in_block_templates'; $cache_group = 'ngg_gallery_detector'; $cached = wp_cache_get( $cache_key, $cache_group ); if ( false !== $cached ) { return (bool) $cached; } // '[ngg' covers [ngg], [ngg_images], [nggallery] and any registered alias starting with [ngg. $ngg_patterns = [ 'imagely/main-block', 'imagely/nextgen-gallery', '[ngg', ]; $found = false; foreach ( [ 'wp_block', 'wp_template_part' ] as $post_type ) { if ( $found ) { break; } $posts = get_posts( [ 'post_type' => $post_type, 'posts_per_page' => -1, 'post_status' => 'publish', 'no_found_rows' => true, 'update_post_meta_cache' => false, 'update_post_term_cache' => false, ] ); foreach ( $posts as $post ) { if ( empty( $post->post_content ) ) { continue; } foreach ( $ngg_patterns as $needle ) { if ( false !== strpos( $post->post_content, $needle ) ) { $found = true; break 2; } } } } wp_cache_set( $cache_key, $found ? 1 : 0, $cache_group ); return $found; } /** * Checks if the current taxonomy/category/tag archive has an NGG shortcode or block * in the term description. Covers the WooCommerce product-category pattern (issue #74) * where galleries are placed in term descriptions rather than post content. */ private static function check_term_description(): bool { if ( ! is_category() && ! is_tag() && ! is_tax() ) { return false; } $queried_object = get_queried_object(); if ( ! $queried_object instanceof \WP_Term || empty( $queried_object->description ) ) { return false; } $description = $queried_object->description; if ( false !== strpos( $description, '[ngg' ) ) { return true; } foreach ( [ 'imagely/main-block', 'imagely/nextgen-gallery' ] as $needle ) { if ( false !== strpos( $description, $needle ) ) { return true; } } return false; } }
dvadf
dvadf
| ver. 1.4 |
Github
|
.
| PHP 7.3.33 | Generation time: 0 |
proxy
|
phpinfo
|
Settings