ruạṛ
<?php /** * Frontend utilities. * * @since ?? * * @package Envira_Gallery */ namespace Envira\Utils; use Envira\Frontend\Gallery_Markup\Layouts\Automatic; use Envira\Frontend\Gallery_Markup\Layouts\Blogroll; use Envira\Frontend\Gallery_Markup\Layouts\BnB; use Envira\Frontend\Gallery_Markup\Layouts\BnB_Overlay; use Envira\Frontend\Gallery_Markup\Layouts\Grid; use Envira\Frontend\Gallery_Markup\Layouts\Mason; use Envira\Frontend\Gallery_Markup\Layouts\Square; use Envira\Frontend\Gallery_Markup\Layouts\Polaroid; use Envira\Frontend\Gallery_Markup\Layouts\Creative; use Envira\Frontend\Gallery_Markup\Layouts\Vertical_Focus; use Envira\Frontend\Gallery_Markup\Layouts\Grid_Fixed_Title; use Envira\Frontend\Gallery_Markup\Layouts\Spread_Harmony; use Envira\Frontend\Gallery_Markup\Layouts\Highlight_Grid; use Envira\Frontend\Gallery_Markup\Layouts\Vertical_Line_Grid; /** * Utilities shared among shortcode classes. */ class Shortcode_Utils { /** * Shortcode default attributes. Used on gallery and link shortcode. */ const DEFAULT_ATTRS = [ 'id' => null, 'limit' => null, 'settings' => null, 'type' => null, 'slug' => null, 'images' => null, 'dynamic' => null, 'cache' => true, 'gallery_images_raw' => null, 'bnb_overlay' => null, ]; /** * Main script loaded. * * @var bool */ private static $main_script_loaded = false; /** * Enqueue Main Script. * * @param array $data Gallery data. * * @return void */ public static function enqueue_main_script( $data ) { if ( self::$main_script_loaded ) { return; } // TODO pass lazy loading delay to general config because it will only read the config on one gallery if there are multiple on the same page. $lazy_loading_delay = isset( $data['config']['lazy_loading_delay'] ) ? intval( $data['config']['lazy_loading_delay'] ) : '500'; wp_enqueue_script( ENVIRA_SLUG . '-script' ); wp_localize_script( ENVIRA_SLUG . '-script', 'envira_gallery', [ 'debug' => is_envira_debug_on(), 'll_delay' => $lazy_loading_delay, 'll_initial' => 'false', 'll' => self::is_lazy_loading( $data ), 'mobile' => envira_mobile_detect()->isMobile(), ] ); self::$main_script_loaded = true; } /** * Is lazy loading option on. * * @param array $data Gallery data. * * @return bool */ public static function is_lazy_loading( $data ) { // If this is being viewed by AMP, javascript is being disabled and lazy loading shouldn't be on. $is_ll = function_exists( 'ampforwp_is_amp_endpoint' ) && ampforwp_is_amp_endpoint() ? false : filter_var( envira_get_config( 'lazy_loading', $data ), FILTER_VALIDATE_BOOLEAN ); return apply_filters( 'envira_is_lazy_loading', $is_ll, $data ); } /** * Obtain gallery data and ids from shortcode attrs. * * @param array $attrs Shortcode attributes. * * @return array|null */ public static function get_data_and_id( $attrs ) { global $post; $parsed_attrs = self::get_parsed_attrs( $attrs ); // Initialize ids. $gallery_id = null; $options_id = null; $use_cached_data = ! ( is_preview() || is_envira_debug_on() ); if ( self::DEFAULT_ATTRS === $parsed_attrs ) { // Pull gallery id from current post. For envira post_type. $gallery_id = $post->ID; $data = $use_cached_data ? envira_get_gallery( $gallery_id ) : _envira_get_gallery( $gallery_id ); } elseif ( $parsed_attrs['id'] ) { $gallery_id = (int) $parsed_attrs['id']; // Determine data by type. Probably is deprecated. if ( ! $parsed_attrs['type'] ) { $data = $use_cached_data ? _envira_get_gallery( $gallery_id ) : envira_get_gallery( $gallery_id ); } elseif ( 'widget' === $parsed_attrs['type'] && $parsed_attrs['settings'] ) { // Only used on random gallery widget. $settings = json_decode( urldecode( $parsed_attrs['settings'] ), ARRAY_A ); $base_gallery_id = (int) $settings['base_gallery_id']; $data = $use_cached_data ? envira_get_gallery( $base_gallery_id ) : _envira_get_gallery( $base_gallery_id ); // Validate gallery data exists before accessing to prevent PHP 8.x errors if ( ! $data || ! is_array( $data ) || ! isset( $data['config'] ) ) { return null; } // Null coalescing operator safely handles missing 'lightbox_enabled' key with default value of 1 $lightbox_enabled = isset( $settings['lightbox'] ) ? (int) $settings['lightbox'] : ( $data['config']['lightbox_enabled'] ?? 1 ); $data['config']['lightbox_enabled'] = $lightbox_enabled; $data['config']['sort_order'] = '1'; } else { // New filter for being able to maniupulate data for custom scenarios (widgets, Gutenberg, alien attacks, etc). $data = apply_filters( 'envira_gallery_custom_gallery_data_by_' . $parsed_attrs['type'], $use_cached_data ? envira_get_gallery( $gallery_id ) : _envira_get_gallery( $gallery_id ), $attrs, $post, $gallery_id ); } } elseif ( $parsed_attrs['slug'] ) { $gallery_id = $parsed_attrs['slug']; $data = $use_cached_data ? envira_get_gallery_by_slug( $gallery_id ) : _envira_get_gallery_by_slug( $gallery_id ); // We have the gallery data, now just translate slug into the ID. if ( $data['id'] ) { $gallery_id = (int) $data['id']; } } else { // TODO seems to be only used when 'dynamic' and 'images' attrs are passed. // A custom attribute must have been passed. Allow it to be filtered to grab data from a custom source. $data = apply_filters( 'envira_gallery_custom_gallery_data', false, $attrs, $post ); $gallery_id = isset( $data['config']['id'] ) ? $data['config']['id'] : $gallery_id; $options_id = isset( $data['dynamic_id'] ) ? $data['dynamic_id'] : $options_id; } if ( ! $options_id ) { $options_id = $gallery_id; } if ( ! $gallery_id || ! $data ) { if ( is_envira_debug_on() ) { ( 'Empty gallery or data. id: ' . print_r( $gallery_id, true ) . PHP_EOL . print_r( $data, true ) ); } return null; } if ( ! isset( $data['config'] ) ) { // Legacy lite versions do not store defaults if no settings are modified. $data['config'] = envira_get_config_defaults( $gallery_id ); } // Force shortcode to return bnb_overlay layout. if ( ! empty( $parsed_attrs['bnb_overlay'] ) ) { $data['config']['layout'] = 'bnb-overlay'; } return [ 'id' => "$gallery_id", 'options_id' => absint( $options_id ), 'data' => $data, 'parsed_attrs' => $parsed_attrs, ]; } /** * Parse shortcode attributes. * * @param array $attrs Shortcode attributes. * * @return array|null */ private static function get_parsed_attrs( $attrs ) { // Set all values to string. $parsed_attrs = array_map( 'strval', wp_parse_args( $attrs, self::DEFAULT_ATTRS ) ); // Sanitize specific attrs. $parsed_attrs['cache'] = $parsed_attrs['cache'] ? filter_var( $parsed_attrs['cache'], FILTER_VALIDATE_BOOLEAN ) : true; $parsed_attrs['limit'] = absint( $parsed_attrs['limit'] ); return $parsed_attrs; } /** * Sanitizes gallery/album description. * * @param array $data Gallery/Album data. * * @return string Gallery description */ public static function get_description( $data ) { // Check if description exists to prevent PHP 8.x warnings $description = $data['config']['description'] ?? ''; // If the WP_Embed class is available, use that to parse the content using registered oEmbed providers. if ( isset( $GLOBALS['wp_embed'] ) ) { $description = $GLOBALS['wp_embed']->autoembed( $description ); } // Get the description and apply most of the filters that apply_filters( 'the_content' ) would use // We don't use apply_filters( 'the_content' ) as this would result in a nested loop and a failure. $description = wptexturize( $description ); $description = convert_smilies( $description ); $description = wpautop( $description ); $description = prepend_attachment( $description ); return ( function_exists( 'wp_filter_content_tags' ) ) ? wp_filter_content_tags( $description ) : $description; } /** * Generates html class string from array of classes. * * @param string[] $classes Array of classes. * * @return string */ public static function classnames( $classes ) { $sanitized = array_map( 'sanitize_html_class', $classes ); // Avoid extra spaces in string by removing empty classes. $filtered = array_filter( $sanitized, function ( $class_name ) { return ! empty( $class_name ); } ); return implode( ' ', array_unique( $filtered ) ); } /** * Get the layout class. * * @param string $layout Layout name. * @param array $config Config array. * * @return object|null Layout class object. */ public static function get_layout_object( $layout, $config ) { $object = null; switch ( $layout ) { case 'automatic': $object = new Automatic( $config ); break; case 'blogroll': $object = new Blogroll( $config ); break; case 'grid': $object = new Grid( $config ); break; case 'mason': $object = new Mason( $config ); break; case 'square': $object = new Square( $config ); break; case 'bnb': $object = ( new BnB( $config ) ); break; case 'bnb-overlay': $object = ( new BnB_Overlay( $config ) ); break; case 'polaroid': $object = ( new Polaroid( $config ) ); break; case 'creative': $object = ( new Creative( $config ) ); break; case 'vertical': $object = ( new Vertical_Focus( $config ) ); break; case 'grid-fixed-title': $object = ( new Grid_Fixed_Title( $config ) ); break; case 'spread-harmony': $object = ( new Spread_Harmony( $config ) ); break; case 'highlight-grid': $object = ( new Highlight_Grid( $config ) ); break; case 'vertical-line-grid': $object = ( new Vertical_Line_Grid( $config ) ); break; default: // no default. } return $object; } /** * Outputs an individual gallery item in the grid * * @param string $gallery Gallery HTML. * @param array $data Gallery Config. * @param array $item Gallery Item (Image). * @param int $item_id Gallery Image ID. * @param int $count Index. * * @return string Gallery HTML */ public static function get_single_item_markup( $gallery, $data, $item, $item_id, $count ) { $layout = envira_get_config( 'layout', $data ); // This config is not accurate as the real one can only be obtained from the Shortcode class. // It is compatible enough for single item render. $config = $data['config']; $layout_object = self::get_layout_object( $layout, $config ); if ( 'bnb' === $layout ) { $layout_object = new BnB_Overlay( $config ); } if ( null === $layout_object ) { return "ERROR: Layout not found: $layout"; } return $layout_object->generate_gallery_item_markup( $gallery, $data, $item, $item_id, $count ); } }
cải xoăn