PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.83
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.83
51.1.84 51.1.85 51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 51.1.45 51.1.46 All 39 releases
← All changes | includes/widgets/Media_Grid/Media_Grid.php +546 -20 51.1.6451.1.83 View file →
@@ -49,8 +49,9 @@
49 49
50 50 public function get_script_depends()
51 51 {
52 52 return [
53 + 'jquery',
53 54 KING_ADDONS_ASSETS_UNIQUE_KEY . '-grid-media',
54 55 KING_ADDONS_ASSETS_UNIQUE_KEY . '-isotope-kng',
55 56 KING_ADDONS_ASSETS_UNIQUE_KEY . '-slick-slick',
56 57 KING_ADDONS_ASSETS_UNIQUE_KEY . '-lightgallery-lightgallery'
@@ -799,10 +800,11 @@
799 800
800 801 $this->add_control(
801 802 'query_manual_attachment',
802 803 [
803 - 'label' => esc_html__('Add Images', 'king-addons'),
804 + 'label' => esc_html__('Add Images (Legacy)', 'king-addons'),
804 805 'type' => Controls_Manager::GALLERY,
806 + 'description' => esc_html__('Used only when "Add Images & Videos" is empty. Prefer the repeater below for images and videos together.', 'king-addons'),
805 807 'separator' => 'before',
806 808 'dynamic' => [
807 809 'active' => true,
808 810 ],
@@ -811,9 +813,79 @@
811 813 ],
812 814 ]
813 815 );
814 816
817 + $media_repeater = new Repeater();
818 +
819 + $media_repeater->add_control(
820 + 'item_type',
821 + [
822 + 'label' => esc_html__('Media Type', 'king-addons'),
823 + 'type' => Controls_Manager::SELECT,
824 + 'default' => 'image',
825 + 'options' => [
826 + 'image' => esc_html__('Image', 'king-addons'),
827 + 'video' => esc_html__('Video', 'king-addons'),
828 + ],
829 + ]
830 + );
831 +
832 + $media_repeater->add_control(
833 + 'item_image',
834 + [
835 + 'label' => esc_html__('Image', 'king-addons'),
836 + 'type' => Controls_Manager::MEDIA,
837 + 'dynamic' => [
838 + 'active' => true,
839 + ],
840 + 'description' => esc_html__('For videos, this image is used as the cover/poster in the gallery.', 'king-addons'),
841 + ]
842 + );
843 +
844 + $media_repeater->add_control(
845 + 'item_video',
846 + [
847 + 'label' => esc_html__('Video File', 'king-addons'),
848 + 'type' => Controls_Manager::MEDIA,
849 + 'media_types' => [
850 + 'video',
851 + ],
852 + 'condition' => [
853 + 'item_type' => 'video',
854 + ],
855 + ]
856 + );
857 +
815 858 $this->add_control(
859 + 'query_manual_media',
860 + [
861 + 'label' => esc_html__('Add Images & Videos', 'king-addons'),
862 + 'type' => Controls_Manager::REPEATER,
863 + 'fields' => $media_repeater->get_controls(),
864 + 'default' => [],
865 + 'title_field' => '{{{ item_type.charAt(0).toUpperCase() + item_type.slice(1) }}}',
866 + 'separator' => 'before',
867 + 'condition' => [
868 + 'query_selection' => 'manual',
869 + ],
870 + ]
871 + );
872 +
873 + $this->add_control(
874 + 'query_include_videos',
875 + [
876 + 'label' => esc_html__('Include Videos', 'king-addons'),
877 + 'type' => Controls_Manager::SWITCHER,
878 + 'default' => '',
879 + 'description' => esc_html__('Include video files from the Media Library in the Auto selection.', 'king-addons'),
880 + 'condition' => [
881 + 'query_selection' => 'dynamic',
882 + ],
883 + 'separator' => 'before',
884 + ]
885 + );
886 +
887 + $this->add_control(
816 888 'query_posts_per_page',
817 889 [
818 890 'label' => esc_html__('Items Per Page', 'king-addons'),
819 891 'type' => Controls_Manager::NUMBER,
@@ -879,8 +951,79 @@
879 951 'label_block' => true
880 952 ]
881 953 );
882 954
955 + $this->add_responsive_control(
956 + 'layout_fitrows_media_height',
957 + [
958 + 'label' => esc_html__('Media Height', 'king-addons'),
959 + 'type' => Controls_Manager::SLIDER,
960 + 'size_units' => ['px', 'vh'],
961 + 'range' => [
962 + 'px' => [
963 + 'min' => 50,
964 + 'max' => 800,
965 + ],
966 + 'vh' => [
967 + 'min' => 10,
968 + 'max' => 100,
969 + ],
970 + ],
971 + 'default' => [
972 + 'unit' => 'px',
973 + 'size' => 280,
974 + ],
975 + 'selectors' => [
976 + '{{WRAPPER}} .king-addons-grid[data-settings*="fitRows"] .king-addons-grid-media-wrap' => 'height: {{SIZE}}{{UNIT}};',
977 + ],
978 + 'condition' => [
979 + 'layout_select' => 'fitRows',
980 + ],
981 + 'separator' => 'before',
982 + ]
983 + );
984 +
985 + $this->add_responsive_control(
986 + 'layout_fitrows_image_fit',
987 + [
988 + 'label' => esc_html__('Image Fit', 'king-addons'),
989 + 'type' => Controls_Manager::SELECT,
990 + 'options' => [
991 + 'cover' => esc_html__('Cover', 'king-addons'),
992 + 'contain' => esc_html__('Contain', 'king-addons'),
993 + ],
994 + 'default' => 'cover',
995 + 'selectors' => [
996 + '{{WRAPPER}} .king-addons-grid[data-settings*="fitRows"] .king-addons-grid-image-wrap img' => 'object-fit: {{VALUE}};',
997 + ],
998 + 'condition' => [
999 + 'layout_select' => 'fitRows',
1000 + ],
1001 + ]
1002 + );
1003 +
1004 + $this->add_responsive_control(
1005 + 'layout_fitrows_image_fit_position',
1006 + [
1007 + 'label' => esc_html__('Image Fit Position', 'king-addons'),
1008 + 'type' => Controls_Manager::SELECT,
1009 + 'options' => [
1010 + 'center center' => esc_html__('Center', 'king-addons'),
1011 + 'top center' => esc_html__('Top', 'king-addons'),
1012 + 'bottom center' => esc_html__('Bottom', 'king-addons'),
1013 + 'center left' => esc_html__('Left', 'king-addons'),
1014 + 'center right' => esc_html__('Right', 'king-addons'),
1015 + ],
1016 + 'default' => 'center center',
1017 + 'selectors' => [
1018 + '{{WRAPPER}} .king-addons-grid[data-settings*="fitRows"] .king-addons-grid-image-wrap img' => 'object-position: {{VALUE}};',
1019 + ],
1020 + 'condition' => [
1021 + 'layout_select' => 'fitRows',
1022 + ],
1023 + ]
1024 + );
1025 +
883 1026 $this->add_group_control(
884 1027 Group_Control_Image_Size::get_type(),
885 1028 [
886 1029 'name' => 'layout_image_crop',
@@ -2190,8 +2333,23 @@
2190 2333 'return_value' => 'true',
2191 2334 ]
2192 2335 );
2193 2336
2337 + $this->add_control(
2338 + 'video_play_icon',
2339 + [
2340 + 'label' => esc_html__('Video Play Icon', 'king-addons'),
2341 + 'type' => Controls_Manager::ICONS,
2342 + 'skin' => 'inline',
2343 + 'label_block' => false,
2344 + 'default' => [
2345 + 'value' => 'fas fa-play',
2346 + 'library' => 'fa-solid',
2347 + ],
2348 + 'separator' => 'before',
2349 + ]
2350 + );
2351 +
2194 2352 $this->add_control_lightbox_popup_thumbnails();
2195 2353
2196 2354 $this->add_control_lightbox_popup_thumbnails_default();
2197 2355
@@ -6705,20 +6863,314 @@
6705 6863 }
6706 6864
6707 6865 public function get_max_num_pages()
6708 6866 {
6867 + $settings = $this->get_settings_for_display();
6868 +
6869 + if ('manual' === ($settings['query_selection'] ?? '')) {
6870 + return $this->get_manual_media_max_num_pages($settings);
6871 + }
6872 +
6709 6873 $query = new WP_Query($this->get_main_query_args());
6710 - $pages = (int)ceil($query->max_num_pages);
6874 + $pages = (int) ceil($query->max_num_pages);
6711 6875 wp_reset_postdata();
6876 +
6712 6877 return $pages;
6713 6878 }
6714 6879
6880 + /**
6881 + * Returns the total page count for manual media items.
6882 + *
6883 + * @param array|null $settings Widget settings.
6884 + * @return int Total number of pages.
6885 + */
6886 + public function get_manual_media_max_num_pages($settings = null)
6887 + {
6888 + $settings = $settings ?? $this->get_settings_for_display();
6889 + $items = $this->get_manual_media_items($settings);
6890 + $total = count($items);
6891 + $per_page = (int) ($settings['query_posts_per_page'] ?? 10);
6892 +
6893 + if ($per_page <= 0 || 0 === $total) {
6894 + return 1;
6895 + }
6896 +
6897 + $offset = empty($settings['query_offset']) ? 0 : (int) $settings['query_offset'];
6898 + $remaining = max(0, $total - $offset);
6899 +
6900 + return max(1, (int) ceil($remaining / $per_page));
6901 + }
6902 +
6903 + /**
6904 + * Returns manual media items for the current pagination page.
6905 + *
6906 + * @param array $settings Widget settings.
6907 + * @return array<int, array<string, mixed>> Paginated manual media items.
6908 + */
6909 + public function get_paginated_manual_media_items($settings)
6910 + {
6911 + $items = $this->get_manual_media_items($settings);
6912 + $per_page = (int) ($settings['query_posts_per_page'] ?? 10);
6913 +
6914 + if ($per_page <= 0) {
6915 + return $items;
6916 + }
6917 +
6918 + $paged = get_query_var('paged') ? (int) get_query_var('paged') : ((int) get_query_var('page') ?: 1);
6919 + $offset = empty($settings['query_offset']) ? 0 : (int) $settings['query_offset'];
6920 + $slice_offset = $offset + ($paged - 1) * $per_page;
6921 +
6922 + return array_slice($items, $slice_offset, $per_page);
6923 + }
6924 +
6925 + /**
6926 + * Checks whether an attachment is a video file.
6927 + *
6928 + * @param int $attachment_id Attachment post ID.
6929 + * @return bool True when the attachment mime type is video.
6930 + */
6931 + public function is_video_attachment($attachment_id)
6932 + {
6933 + $mime_type = get_post_mime_type($attachment_id);
6934 +
6935 + return is_string($mime_type) && 0 === strpos($mime_type, 'video/');
6936 + }
6937 +
6938 + /**
6939 + * Returns a video mime type based on the file extension.
6940 + *
6941 + * @param string $url Video file URL.
6942 + * @return string Video mime type.
6943 + */
6944 + public function get_video_mime_from_url($url)
6945 + {
6946 + $extension = strtolower((string) pathinfo((string) wp_parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION));
6947 + $map = [
6948 + 'mp4' => 'video/mp4',
6949 + 'webm' => 'video/webm',
6950 + 'ogg' => 'video/ogg',
6951 + 'ogv' => 'video/ogg',
6952 + ];
6953 +
6954 + return $map[$extension] ?? 'video/mp4';
6955 + }
6956 +
6957 + /**
6958 + * Returns a poster image URL for a video attachment when available.
6959 + *
6960 + * @param int $attachment_id Video attachment ID.
6961 + * @return string Poster image URL or an empty string.
6962 + */
6963 + public function get_attachment_video_poster_url($attachment_id)
6964 + {
6965 + $image_src = wp_get_attachment_image_src($attachment_id, 'large');
6966 + if (!empty($image_src[0])) {
6967 + return $image_src[0];
6968 + }
6969 +
6970 + $metadata = wp_get_attachment_metadata($attachment_id);
6971 + if (!empty($metadata['image']['file']) && !empty($metadata['file'])) {
6972 + $upload_dir = wp_upload_dir();
6973 +
6974 + return trailingslashit($upload_dir['baseurl']) . trailingslashit(dirname($metadata['file'])) . $metadata['image']['file'];
6975 + }
6976 +
6977 + return '';
6978 + }
6979 +
6980 + /**
6981 + * Builds manual media items from the repeater or legacy gallery control.
6982 + *
6983 + * @param array $settings Widget settings.
6984 + * @return array<int, array<string, mixed>> Manual media items.
6985 + */
6986 + public function get_manual_media_items($settings)
6987 + {
6988 + $items = [];
6989 +
6990 + if (!empty($settings['query_manual_media'])) {
6991 + foreach ($settings['query_manual_media'] as $index => $row) {
6992 + $item_type = $row['item_type'] ?? 'image';
6993 + $item_image = $row['item_image'] ?? [];
6994 + $item_video = $row['item_video'] ?? [];
6995 +
6996 + if ('video' === $item_type) {
6997 + if (empty($item_video['url'])) {
6998 + continue;
6999 + }
7000 + if (empty($item_image['id']) && empty($item_image['url'])) {
7001 + continue;
7002 + }
7003 + } elseif (empty($item_image['id']) && empty($item_image['url'])) {
7004 + continue;
7005 + }
7006 +
7007 + $items[] = [
7008 + 'key' => 'manual-' . $index,
7009 + 'type' => $item_type,
7010 + 'image' => $item_image,
7011 + 'video' => $item_video,
7012 + ];
7013 + }
7014 +
7015 + return $items;
7016 + }
7017 +
7018 + if (empty($settings['query_manual_attachment'])) {
7019 + return $items;
7020 + }
7021 +
7022 + foreach ($settings['query_manual_attachment'] as $index => $attachment) {
7023 + if (empty($attachment['id'])) {
7024 + continue;
7025 + }
7026 +
7027 + $items[] = [
7028 + 'key' => 'legacy-' . $index,
7029 + 'type' => 'image',
7030 + 'image' => $attachment,
7031 + 'video' => [],
7032 + ];
7033 + }
7034 +
7035 + return $items;
7036 + }
7037 +
7038 + /**
7039 + * Renders the play icon overlay for video gallery items.
7040 + *
7041 + * @param array $settings Widget settings.
7042 + * @return void
7043 + */
7044 + public function render_video_play_icon($settings)
7045 + {
7046 + echo '<span class="king-addons-grid-video-play-icon" aria-hidden="true">';
7047 + Icons_Manager::render_icon($settings['video_play_icon'], ['aria-hidden' => 'true']);
7048 + echo '</span>';
7049 + }
7050 +
7051 + /**
7052 + * Renders a hidden HTML5 video element referenced by the lightbox.
7053 + *
7054 + * @param string $video_url Video file URL.
7055 + * @param string $element_id Hidden container element ID.
7056 + * @return void
7057 + */
7058 + public function render_video_html_element($video_url, $element_id)
7059 + {
7060 + if ('' === $video_url) {
7061 + return;
7062 + }
7063 +
7064 + echo '<div class="king-addons-grid-video-html" id="' . esc_attr($element_id) . '" style="display:none;">';
7065 + echo '<video class="lg-video-object lg-html5" controls preload="none" playsinline>';
7066 + echo '<source src="' . esc_url($video_url) . '" type="' . esc_attr($this->get_video_mime_from_url($video_url)) . '">';
7067 + echo '</video>';
7068 + echo '</div>';
7069 + }
7070 +
7071 + /**
7072 + * Renders a gallery media thumbnail for image or video items.
7073 + *
7074 + * @param array $settings Widget settings.
7075 + * @param string $item_key Unique item key for lightbox video references.
7076 + * @param string $media_type Media type: image or video.
7077 + * @param array $image_data Image or cover attachment data.
7078 + * @param string $video_url Video file URL for video items.
7079 + * @return void
7080 + */
7081 + public function render_media_thumbnail($settings, $item_key, $media_type, $image_data, $video_url = '')
7082 + {
7083 + $image_id = !empty($image_data['id']) ? (int) $image_data['id'] : 0;
7084 + $is_video = ('video' === $media_type && '' !== $video_url);
7085 + $video_html_id = 'king-addons-grid-video-' . $this->get_id() . '-' . $item_key;
7086 +
7087 + if ($image_id) {
7088 + $src = Group_Control_Image_Size::get_attachment_image_src($image_id, 'layout_image_crop', $settings);
7089 + $alt = ('' === wp_get_attachment_caption($image_id)) ? get_the_title($image_id) : wp_get_attachment_caption($image_id);
7090 + $lightbox_src = $is_video ? $src : wp_get_attachment_url($image_id);
7091 + } else {
7092 + $src = $image_data['url'] ?? '';
7093 + $alt = '';
7094 + $lightbox_src = $src;
7095 + }
7096 +
7097 + if ($is_video && '' === $src && $image_id) {
7098 + $src = $this->get_attachment_video_poster_url($image_id);
7099 + }
7100 +
7101 + if ($is_video) {
7102 + $lightbox_src = '' !== $src ? $src : $video_url;
7103 + }
7104 +
7105 + $wrap_classes = 'king-addons-grid-image-wrap';
7106 + if ($is_video) {
7107 + $wrap_classes .= ' king-addons-grid-video-lightbox-item';
7108 + }
7109 +
7110 + echo '<div class="' . esc_attr($wrap_classes) . '" data-src="' . esc_url($lightbox_src) . '"';
7111 + if ($is_video) {
7112 + echo ' data-poster="' . esc_url($lightbox_src) . '"';
7113 + echo ' data-html="#' . esc_attr($video_html_id) . '"';
7114 + echo ' data-kng-video-url="' . esc_url($video_url) . '"';
7115 + }
7116 + echo '>';
7117 +
7118 + if ('' !== $src) {
7119 + echo '<img src="' . esc_url($src) . '" alt="' . esc_attr($alt) . '" class="king-addons-animation-timing-' . esc_attr($settings['image_effects_animation_timing']) . '">';
7120 + } elseif ($is_video) {
7121 + echo '<span class="king-addons-grid-video-cover-placeholder" aria-hidden="true"></span>';
7122 + }
7123 +
7124 + if ($is_video) {
7125 + $this->render_video_play_icon($settings);
7126 + }
7127 +
7128 + echo '</div>';
7129 +
7130 + if ($is_video) {
7131 + $this->render_video_html_element($video_url, $video_html_id);
7132 + }
7133 + }
7134 +
7135 + /**
7136 + * Renders one gallery article for manual media items.
7137 + *
7138 + * @param array $settings Widget settings.
7139 + * @param array $item Manual media item data.
7140 + * @return void
7141 + */
7142 + public function render_manual_grid_item($settings, $item)
7143 + {
7144 + $item_type = $item['type'] ?? 'image';
7145 + $video_url = ('video' === $item_type && !empty($item['video']['url'])) ? $item['video']['url'] : '';
7146 + $post_id = !empty($item['image']['id']) ? (int) $item['image']['id'] : 0;
7147 + $item_classes = ['king-addons-grid-item', 'elementor-clearfix'];
7148 +
7149 + if ('video' === $item_type) {
7150 + $item_classes[] = 'king-addons-grid-item-video';
7151 + }
7152 +
7153 + echo '<article class="' . esc_attr(implode(' ', $item_classes)) . '">';
7154 + echo '<div class="king-addons-grid-item-inner">';
7155 + $this->get_elements_by_location('above', $settings, $post_id);
7156 + echo '<div class="king-addons-grid-media-wrap' . esc_attr($this->get_image_effect_class($settings)) . '">';
7157 + $this->render_media_thumbnail($settings, $item['key'], $item_type, $item['image'] ?? [], $video_url);
7158 + echo '<div class="king-addons-grid-media-hover king-addons-animation-wrap">';
7159 + $this->render_media_overlay($settings, $post_id);
7160 + $this->get_elements_by_location('over', $settings, $post_id);
7161 + echo '</div></div>';
7162 + $this->get_elements_by_location('below', $settings, $post_id);
7163 + echo '</div></article>';
7164 + }
7165 +
6715 7166 public function get_main_query_args()
6716 7167 {
6717 7168 $s = $this->get_settings_for_display();
6718 7169 $author = !empty($s['query_author']) ? implode(',', $s['query_author']) : '';
6719 7170 $paged = get_query_var('paged') ? get_query_var('paged') : (get_query_var('page') ? get_query_var('page') : 1);
6720 - $offset = ($paged - 1) * $s['query_posts_per_page'] + (empty($s['query_offset']) ? 0 : $s['query_offset']);
7171 + $offset = ($paged - 1) * Core::jsNumber($s, 'query_posts_per_page', 10)
7172 + + (empty($s['query_offset']) ? 0 : Core::jsNumber($s, 'query_offset', 0));
6721 7173
6722 7174 // Remove premium-only randomize if not available
6723 7175 if (!king_addons_freemius()->can_use_premium_code__premium_only()) {
6724 7176 $s['query_randomize'] = '';
@@ -6724,13 +7176,18 @@
6724 7176 $s['query_randomize'] = '';
6725 7177 $s['order_posts'] = 'date';
6726 7178 }
6727 7179 $order_by = $s['query_randomize'] !== '' ? $s['query_randomize'] : $s['order_posts'];
6728 - if ('manual' === $s['query_selection']) $order_by = 'post__in';
7180 + if ('manual' === $s['query_selection']) {
7181 + $order_by = 'post__in';
7182 + }
6729 7183
7184 + $include_videos = !empty($s['query_include_videos']);
7185 + $post_mime_type = $include_videos ? ['image', 'video'] : 'image';
7186 +
6730 7187 $args = [
6731 7188 'post_type' => 'attachment',
6732 - 'post_mime_type' => 'image', // <-- Only images
7189 + 'post_mime_type' => $post_mime_type,
6733 7190 'post_status' => 'inherit',
6734 7191 'tax_query' => $this->get_tax_query_args(),
6735 7192 'post__not_in' => $s['query_exclude_attachment'],
6736 7193 'posts_per_page' => $s['query_posts_per_page'],
@@ -6741,17 +7198,29 @@
6741 7198 ];
6742 7199
6743 7200 if ('manual' === $s['query_selection']) {
6744 7201 $post_ids = [];
6745 - if (!empty($s['query_manual_attachment'])) {
7202 +
7203 + if (!empty($s['query_manual_media'])) {
7204 + foreach ($this->get_manual_media_items($s) as $item) {
7205 + if (!empty($item['image']['id'])) {
7206 + $post_ids[] = (int) $item['image']['id'];
7207 + }
7208 + }
7209 + } elseif (!empty($s['query_manual_attachment'])) {
6746 7210 foreach ($s['query_manual_attachment'] as $attachment) {
6747 7211 $post_ids[] = $attachment['id'];
6748 7212 }
6749 7213 }
7214 +
7215 + if (empty($post_ids)) {
7216 + $post_ids = [0];
7217 + }
7218 +
6750 7219 $orderby = ('' === $s['query_randomize']) ? 'post__in' : 'rand';
6751 7220 $args = [
6752 7221 'post_type' => 'attachment',
6753 - 'post_mime_type' => 'image', // <-- Only images
7222 + 'post_mime_type' => $post_mime_type,
6754 7223 'post_status' => 'inherit',
6755 7224 'post__in' => $post_ids,
6756 7225 'orderby' => $orderby,
6757 7226 'posts_per_page' => $s['query_posts_per_page'],
@@ -6813,18 +7282,28 @@
6813 7282
6814 7283 public function render_post_thumbnail($settings)
6815 7284 {
6816 7285 $id = get_the_ID();
6817 - $src = Group_Control_Image_Size::get_attachment_image_src($id, 'layout_image_crop', $settings);
6818 - $alt = ('' === wp_get_attachment_caption($id)) ? get_the_title() : wp_get_attachment_caption($id);
6819 - echo '<div class="king-addons-grid-image-wrap" data-src="' . esc_url(wp_get_attachment_url($id)) . '">';
6820 - echo '<img src="' . esc_url($src) . '" alt="' . wp_kses_post($alt) . '" class="king-addons-animation-timing-' . esc_html($settings['image_effects_animation_timing']) . '">';
6821 - echo '</div>';
7286 + $is_video = $this->is_video_attachment($id);
7287 + $video_url = $is_video ? (string) wp_get_attachment_url($id) : '';
7288 +
7289 + $this->render_media_thumbnail(
7290 + $settings,
7291 + 'attachment-' . $id,
7292 + $is_video ? 'video' : 'image',
7293 + ['id' => $id],
7294 + $video_url
7295 + );
6822 7296 }
6823 7297
6824 - public function render_media_overlay($s)
7298 + public function render_media_overlay($s, $post_id = 0)
6825 7299 {
6826 - echo '<div class="king-addons-grid-media-hover-bg ' . $this->get_animation_class($s, 'overlay') . '" data-url="' . esc_url(get_the_permalink(get_the_ID())) . '">';
7300 + if (!$post_id) {
7301 + $post_id = get_the_ID();
7302 + }
7303 +
7304 + $overlay_url = $post_id ? get_the_permalink($post_id) : '#';
7305 + echo '<div class="king-addons-grid-media-hover-bg ' . $this->get_animation_class($s, 'overlay') . '" data-url="' . esc_url($overlay_url) . '">';
6827 7306 if (king_addons_freemius()->can_use_premium_code__premium_only()) {
6828 7307 if ('' !== $s['overlay_image']['url']) {
6829 7308 echo '<img src="' . esc_url($s['overlay_image']['url']) . '">';
6830 7309 }
@@ -6959,9 +7438,12 @@
6959 7438 public function render_post_lightbox($s, $class, $post_id)
6960 7439 {
6961 7440 echo '<div class="' . esc_attr($class) . '"><div class="inner-block">';
6962 7441 $lightbox_source = get_the_post_thumbnail_url($post_id);
6963 - if ('audio' === get_post_format()) {
7442 +
7443 + if ($this->is_video_attachment($post_id)) {
7444 + $lightbox_source = $this->get_attachment_video_poster_url($post_id);
7445 + } elseif ('audio' === get_post_format()) {
6964 7446 if ('meta' === $s['element_lightbox_pfa_select']) {
6965 7447 $meta_value = get_post_meta($post_id, $s['element_lightbox_pfa_meta'], true);
6966 7448 if (false === strpos($meta_value, '<iframe ')) {
6967 7449 add_filter('oembed_result', $media_grid_filter = function ($html) {
@@ -6990,9 +7472,11 @@
6990 7472 }
6991 7473 if (isset($video_url)) $lightbox_source = $video_url;
6992 7474 }
6993 7475 }
6994 - if (!$lightbox_source) $lightbox_source = wp_get_attachment_url($post_id);
7476 + if (!$lightbox_source && !$this->is_video_attachment($post_id)) {
7477 + $lightbox_source = wp_get_attachment_url($post_id);
7478 + }
6995 7479 echo '<span data-src="' . esc_url($lightbox_source) . '">';
6996 7480 if ('before' === $s['element_extra_text_pos']) {
6997 7481 echo '<span class="king-addons-grid-extra-text-left">' . esc_html($s['element_extra_text']) . '</span>';
6998 7482 }
@@ -7406,9 +7890,9 @@
7406 7890 'selector' => '.king-addons-grid-image-wrap',
7407 7891 'iframeMaxWidth' => '60%',
7408 7892 'hash' => false,
7409 7893 'autoplay' => $s['lightbox_popup_autoplay'],
7410 - 'pause' => $s['lightbox_popup_pause'] * 1000,
7894 + 'pause' => Core::jsNumber($s, 'lightbox_popup_pause', 5) * 1000,
7411 7895 'progressBar' => $s['lightbox_popup_progressbar'],
7412 7896 'counter' => $s['lightbox_popup_counter'],
7413 7897 'controls' => $s['lightbox_popup_arrows'],
7414 7898 'getCaptionFromTitleOrAlt' => false,
@@ -7477,8 +7961,43 @@
7477 7961
7478 7962 protected function render()
7479 7963 {
7480 7964 $s = $this->get_settings();
7965 +
7966 + if ('manual' === $s['query_selection']) {
7967 + $manual_items = $this->get_paginated_manual_media_items($s);
7968 +
7969 + if (empty($manual_items)) {
7970 + echo '<h2>' . esc_html($s['query_not_found_text']) . '</h2>';
7971 + return;
7972 + }
7973 +
7974 + if ('slider' !== $s['layout_select']) {
7975 + $this->render_grid_filters($s);
7976 + $this->add_grid_settings($s);
7977 + $render_attribute = $this->get_render_attribute_string('grid-settings');
7978 + } else {
7979 + $this->add_slider_settings($s);
7980 + $render_attribute = $this->get_render_attribute_string('slider-settings');
7981 + }
7982 +
7983 + echo '<section class="king-addons-grid king-addons-media-grid elementor-clearfix" ' . $render_attribute . '>';
7984 + foreach ($manual_items as $item) {
7985 + $this->render_manual_grid_item($s, $item);
7986 + }
7987 + echo '</section>';
7988 +
7989 + if ('slider' === $s['layout_select']) {
7990 + echo '<div class="king-addons-grid-slider-arrow-container">';
7991 + echo '<div class="king-addons-grid-slider-prev-arrow king-addons-grid-slider-arrow" id="king-addons-grid-slider-prev-' . esc_attr($this->get_id()) . '">' . Core::getIcon($s['layout_slider_nav_icon'], '') . '</div>';
7992 + echo '<div class="king-addons-grid-slider-next-arrow king-addons-grid-slider-arrow" id="king-addons-grid-slider-next-' . esc_attr($this->get_id()) . '">' . Core::getIcon($s['layout_slider_nav_icon'], '') . '</div>';
7993 + echo '</div><div class="king-addons-grid-slider-dots"></div>';
7994 + }
7995 +
7996 + $this->render_grid_pagination($s);
7997 + return;
7998 + }
7999 +
7481 8000 $posts = new WP_Query($this->get_main_query_args());
7482 8001 if ($posts->have_posts()) {
7483 8002 if ('slider' !== $s['layout_select']) {
7484 8003 $this->render_grid_filters($s);
@@ -7490,12 +8009,19 @@
7490 8009 }
7491 8010 echo '<section class="king-addons-grid king-addons-media-grid elementor-clearfix" ' . $render_attribute . '>';
7492 8011 while ($posts->have_posts()) {
7493 8012 $posts->the_post();
7494 - // Skip non-image attachments (in case)
7495 - if (!wp_attachment_is_image(get_the_ID())) continue;
8013 + $attachment_id = get_the_ID();
7496 8014
7497 - $post_class = implode(' ', get_post_class('king-addons-grid-item elementor-clearfix', get_the_ID()));
8015 + if (!wp_attachment_is_image($attachment_id) && !$this->is_video_attachment($attachment_id)) {
8016 + continue;
8017 + }
8018 +
8019 + $post_class = implode(' ', get_post_class('king-addons-grid-item elementor-clearfix', $attachment_id));
8020 + if ($this->is_video_attachment($attachment_id)) {
8021 + $post_class .= ' king-addons-grid-item-video';
8022 + }
8023 +
7498 8024 echo '<article class="' . esc_attr($post_class) . '">';
7499 8025 echo '<div class="king-addons-grid-item-inner">';
7500 8026 $this->get_elements_by_location('above', $s, get_the_ID());
7501 8027 echo '<div class="king-addons-grid-media-wrap' . $this->get_image_effect_class($s) . ' ">';