galleries
1 week ago
providers
4 months ago
settings
4 months ago
class-fast-image.php
2 years ago
class-folders.php
1 week ago
class-frontend.php
1 week ago
class-galleries.php
4 months ago
class-multilang.php
2 years ago
class-remote-library-api.php
1 week ago
class-remote-library.php
1 week ago
class-settings-api.php
1 month ago
class-settings-data.php
5 months ago
class-settings-pages.php
4 months ago
class-settings.php
4 months ago
class-tour.php
5 months ago
class-welcome.php
4 months ago
class-widgets.php
2 years ago
functions.php
3 years ago
class-galleries.php
1858 lines
| 1 | <?php |
| 2 | // exit if accessed directly |
| 3 | if ( ! defined( 'ABSPATH' ) ) |
| 4 | exit; |
| 5 | |
| 6 | // Include gallery traits |
| 7 | require_once( RESPONSIVE_LIGHTBOX_PATH . 'includes/galleries/trait-gallery-duplicate.php' ); |
| 8 | require_once( RESPONSIVE_LIGHTBOX_PATH . 'includes/galleries/trait-gallery-preview.php' ); |
| 9 | require_once( RESPONSIVE_LIGHTBOX_PATH . 'includes/galleries/trait-gallery-sanitize.php' ); |
| 10 | require_once( RESPONSIVE_LIGHTBOX_PATH . 'includes/galleries/trait-gallery-ajax.php' ); |
| 11 | require_once( RESPONSIVE_LIGHTBOX_PATH . 'includes/galleries/trait-gallery-image-methods.php' ); |
| 12 | |
| 13 | /** |
| 14 | * Responsive Lightbox Galleries class. |
| 15 | * |
| 16 | * @class Responsive_Lightbox_Galleries |
| 17 | */ |
| 18 | class Responsive_Lightbox_Galleries { |
| 19 | |
| 20 | use Responsive_Lightbox_Gallery_Duplicate; |
| 21 | use Responsive_Lightbox_Gallery_Preview; |
| 22 | use Responsive_Lightbox_Gallery_Sanitize; |
| 23 | use Responsive_Lightbox_Gallery_Ajax; |
| 24 | use Responsive_Lightbox_Galleries_Image_Methods; |
| 25 | |
| 26 | public $fields; |
| 27 | private $tabs; |
| 28 | private $sizes; |
| 29 | private $gallery_args; |
| 30 | private $menu_item; |
| 31 | private $revision_id; |
| 32 | private $allowed_select_html = [ |
| 33 | 'select' => [ |
| 34 | 'name' => true, |
| 35 | 'id' => true, |
| 36 | 'class' => true, |
| 37 | 'required' => true, |
| 38 | 'tabindex' => true, |
| 39 | 'aria-describedby' => true |
| 40 | ], |
| 41 | 'option' => [ |
| 42 | 'value' => true, |
| 43 | 'class' => true, |
| 44 | 'selected' => true |
| 45 | ] |
| 46 | ]; |
| 47 | |
| 48 | |
| 49 | /** |
| 50 | * Class constructor. |
| 51 | * |
| 52 | * @param bool $read_only Whether is it read only mode |
| 53 | * @return void |
| 54 | */ |
| 55 | public function __construct( $read_only = false ) { |
| 56 | // set instance |
| 57 | Responsive_Lightbox()->galleries = $this; |
| 58 | |
| 59 | if ( $read_only ) |
| 60 | return; |
| 61 | |
| 62 | // Initialize gallery settings API - all tabs managed by adapter |
| 63 | include_once( RESPONSIVE_LIGHTBOX_PATH . 'includes/galleries/class-gallery-api.php' ); |
| 64 | Responsive_Lightbox()->gallery_api = new Responsive_Lightbox_Gallery_API(); |
| 65 | |
| 66 | // actions |
| 67 | add_action( 'init', array( $this, 'init' ), 11 ); |
| 68 | add_action( 'admin_init', array( $this, 'init_admin' ) ); |
| 69 | add_action( 'current_screen', array( $this, 'clear_metaboxes' ) ); |
| 70 | add_action( 'edit_form_after_title', array( $this, 'after_title_nav_menu' ) ); |
| 71 | add_action( 'admin_footer', array( $this, 'modal_gallery_template' ) ); |
| 72 | add_action( 'customize_controls_print_footer_scripts', array( $this, 'modal_gallery_template' ) ); |
| 73 | add_action( 'media_buttons', array( $this, 'add_gallery_button' ) ); |
| 74 | add_action( 'add_meta_boxes_rl_gallery', array( $this, 'add_meta_boxes' ) ); |
| 75 | add_action( 'save_post_rl_gallery', array( $this, 'save_post' ), 10, 3 ); |
| 76 | add_action( 'manage_rl_gallery_posts_custom_column', array( $this, 'gallery_columns_content' ), 10, 2 ); |
| 77 | add_action( 'admin_action_duplicate_gallery', array( $this, 'duplicate_gallery' ) ); |
| 78 | add_action( 'wp_ajax_rl-get-menu-content', array( $this, 'get_menu_content' ) ); |
| 79 | add_action( 'wp_ajax_rl-get-preview-content', array( $this, 'get_gallery_preview_content' ) ); |
| 80 | add_action( 'wp_ajax_rl-post-get-galleries', array( $this, 'post_get_galleries' ) ); |
| 81 | add_action( 'wp_ajax_rl-post-gallery-preview', array( $this, 'post_gallery_preview' ) ); |
| 82 | add_action( 'wp_ajax_rl-get-gallery-page-content', array( $this, 'get_gallery_page' ) ); |
| 83 | add_action( 'wp_ajax_nopriv_rl-get-gallery-page-content', array( $this, 'get_gallery_page' ) ); |
| 84 | add_action( '_wp_put_post_revision', array( $this, 'save_revision' ) ); |
| 85 | add_action( 'delete_attachment', array( $this, 'delete_attachment' ) ); |
| 86 | add_action( 'shutdown', array( $this, 'shutdown_preview' ) ); |
| 87 | add_action( 'wp_loaded', array( $this, 'maybe_change_lightbox' ), 1 ); |
| 88 | |
| 89 | // filters |
| 90 | add_filter( 'manage_rl_gallery_posts_columns', array( $this, 'gallery_columns' ) ); |
| 91 | add_filter( 'admin_post_thumbnail_html', array( $this, 'admin_post_thumbnail_html' ), 10, 3 ); |
| 92 | add_filter( 'post_thumbnail_html', array( $this, 'post_thumbnail_html' ), 10, 5 ); |
| 93 | add_filter( 'preview_post_link', array( $this, 'preview_post_link' ) ); |
| 94 | add_filter( 'post_row_actions', array( $this, 'post_row_actions_duplicate' ), 10, 2 ); |
| 95 | |
| 96 | if ( ! empty( $_POST['rl_active_tab'] ) ) |
| 97 | add_filter( 'redirect_post_location', array( $this, 'add_active_tab' ) ); |
| 98 | } |
| 99 | |
| 100 | /** |
| 101 | * Get class data. |
| 102 | * |
| 103 | * @param string $attr |
| 104 | * @return mixed |
| 105 | */ |
| 106 | public function get_data( $attr ) { |
| 107 | return property_exists( $this, $attr ) ? $this->{$attr} : null; |
| 108 | } |
| 109 | |
| 110 | /** |
| 111 | * Get default gallery single image template. |
| 112 | * |
| 113 | * @param array $args Template arguments |
| 114 | * @return string |
| 115 | */ |
| 116 | public function get_media_item_template( $args = [] ) { |
| 117 | $args = array_merge( |
| 118 | array( |
| 119 | 'draggable' => false, |
| 120 | 'editable' => false, |
| 121 | 'removable' => false, |
| 122 | 'changeable' => false |
| 123 | ), |
| 124 | $args |
| 125 | ); |
| 126 | |
| 127 | return ' |
| 128 | <li class="rl-gallery-image__MEDIA_STATUS__" data-attachment_id="__MEDIA_ID__" data-type="__MEDIA_TYPE__"' . ( $args['draggable'] ? ' style="cursor: move;"' : '' ) . '> |
| 129 | <div class="rl-gallery-inner"> |
| 130 | <div class="centered"> |
| 131 | __MEDIA_DATA__ |
| 132 | </div> |
| 133 | </div> |
| 134 | <div class="rl-gallery-actions">' . |
| 135 | ( $args['changeable'] ? '<a href="#" class="rl-gallery-image-status dashicons dashicons-marker" title="' . esc_attr__( 'Status', 'responsive-lightbox' ) . '"></a>' : '' ) . |
| 136 | ( $args['editable'] ? '<a href="#" class="rl-gallery-image-edit dashicons dashicons-edit" title="' . esc_attr__( 'Edit image', 'responsive-lightbox' ) . '"></a>' : '' ) . |
| 137 | ( $args['removable'] ? '<a href="#" class="rl-gallery-image-remove dashicons dashicons-no" title="' . esc_attr__( 'Remove image', 'responsive-lightbox' ) . '"></a>' : '' ) . ' |
| 138 | </div> |
| 139 | </li>'; |
| 140 | } |
| 141 | |
| 142 | /** |
| 143 | * Get default gallery embed template. |
| 144 | * |
| 145 | * @param bool $js |
| 146 | * @return string |
| 147 | */ |
| 148 | public function get_media_embed_template( $js = false ) { |
| 149 | $html = ''; |
| 150 | |
| 151 | if ( $js ) |
| 152 | $html .= '<div data-id="__EMBED_ID__" style="display: none;">'; |
| 153 | |
| 154 | $html .= ' |
| 155 | <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][url]" data-type="url" value="__EMBED_URL__"> |
| 156 | <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][width]" data-type="width" value="__EMBED_WIDTH__"> |
| 157 | <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][height]" data-type="height" value="__EMBED_HEIGHT__"> |
| 158 | <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][thumbnail_url]" data-type="thumbnail_url" value="__EMBED_THUMBNAIL_URL__"> |
| 159 | <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][thumbnail_width]" data-type="thumbnail_width" value="__EMBED_THUMBNAIL_WIDTH__"> |
| 160 | <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][thumbnail_height]" data-type="thumbnail_height" value="__EMBED_THUMBNAIL_HEIGHT__"> |
| 161 | <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][title]" data-type="title" value="__EMBED_TITLE__"> |
| 162 | <textarea class="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][caption]" data-type="caption">__EMBED_DESCRIPTION__</textarea> |
| 163 | <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][date]" data-type="date" value="__EMBED_DATE__">'; |
| 164 | |
| 165 | if ( $js ) |
| 166 | $html .= '</div>'; |
| 167 | |
| 168 | return $html; |
| 169 | } |
| 170 | |
| 171 | /** |
| 172 | * Set the current menu item for image source resolution. |
| 173 | * |
| 174 | * Used by gallery adapter to set menu_item before calling get_gallery_images(). |
| 175 | * |
| 176 | * @param string $menu_item Menu item key. |
| 177 | * @return void |
| 178 | */ |
| 179 | public function set_menu_item( $menu_item ) { |
| 180 | $this->menu_item = sanitize_key( $menu_item ); |
| 181 | } |
| 182 | |
| 183 | /** |
| 184 | * Get default gallery exclude input template. |
| 185 | * |
| 186 | * @param string $tab_id |
| 187 | * @param string $menu_item |
| 188 | * @param string $field_name |
| 189 | * @param mixed $excluded_value |
| 190 | * @return string |
| 191 | */ |
| 192 | public function get_media_exclude_input_template( $tab_id = '', $menu_item = '', $field_name = '', $excluded_value = '' ) { |
| 193 | $template = '<input type="hidden" class="rl-gallery-exclude" name="rl_gallery[__MEDIA_TAB_ID__][__MEDIA_MENU_ITEM__][__MEDIA_FIELD_NAME__][exclude][]" value="__MEDIA_FIELD_VALUE__" />'; |
| 194 | |
| 195 | if ( $tab_id === '' && $menu_item === '' && $field_name === '' && $excluded_value === '' ) |
| 196 | return str_replace( '__MEDIA_FIELD_VALUE__', '', $template ); |
| 197 | |
| 198 | return str_replace( |
| 199 | [ |
| 200 | '__MEDIA_TAB_ID__', |
| 201 | '__MEDIA_MENU_ITEM__', |
| 202 | '__MEDIA_FIELD_NAME__', |
| 203 | '__MEDIA_FIELD_VALUE__' |
| 204 | ], |
| 205 | [ |
| 206 | esc_attr( $tab_id ), |
| 207 | esc_attr( $menu_item ), |
| 208 | esc_attr( $field_name ), |
| 209 | empty( $excluded_value ) ? '' : esc_attr( $excluded_value ) |
| 210 | ], |
| 211 | $template |
| 212 | ); |
| 213 | } |
| 214 | |
| 215 | /** |
| 216 | * Load needed data. |
| 217 | * |
| 218 | * @return void |
| 219 | */ |
| 220 | public function init() { |
| 221 | // register shortcode |
| 222 | add_shortcode( 'rl_gallery', array( $this, 'gallery_shortcode' ) ); |
| 223 | |
| 224 | // get main instance |
| 225 | $rl = Responsive_Lightbox(); |
| 226 | |
| 227 | // set lightbox script for infinite scroll pages |
| 228 | if ( isset( $_GET['rl_gallery_no'], $_GET['rl_page'], $_GET['rl_lightbox_script'] ) ) |
| 229 | $rl->set_lightbox_script( sanitize_key( $_GET['rl_lightbox_script'] ) ); |
| 230 | |
| 231 | $config_menu_items = apply_filters( 'rl_gallery_types', $rl->get_data( 'gallery_types' ) ); |
| 232 | $config_menu_items['default'] = __( 'Global', 'responsive-lightbox' ); |
| 233 | |
| 234 | // set tabs |
| 235 | $this->tabs = apply_filters( |
| 236 | 'rl_gallery_tabs', |
| 237 | array( |
| 238 | 'images' => array( |
| 239 | 'label' => __( 'Images', 'responsive-lightbox' ), |
| 240 | 'description' => __( 'The settings below adjust the contents of the gallery.', 'responsive-lightbox' ), |
| 241 | 'menu_items' => array( |
| 242 | 'media' => __( 'Media Library', 'responsive-lightbox' ), |
| 243 | 'featured' => __( 'Featured Content', 'responsive-lightbox' ) |
| 244 | ) |
| 245 | ), |
| 246 | 'config' => array( |
| 247 | 'label' => __( 'Config', 'responsive-lightbox' ), |
| 248 | 'description' => __( 'The settings below allow you to select a gallery type and adjust the gallery options.', 'responsive-lightbox' ), |
| 249 | 'menu_items' => $config_menu_items |
| 250 | ), |
| 251 | 'design' => array( |
| 252 | 'label' => __( 'Design', 'responsive-lightbox' ), |
| 253 | 'description' => __( 'The settings below adjust the gallery design options.', 'responsive-lightbox' ) |
| 254 | ), |
| 255 | 'paging' => array( |
| 256 | 'label' => __( 'Paging', 'responsive-lightbox' ), |
| 257 | 'description' => __( 'The settings below adjust the gallery pagination options.', 'responsive-lightbox' ) |
| 258 | ), |
| 259 | 'lightbox' => array( |
| 260 | 'label' => __( 'Lightbox', 'responsive-lightbox' ), |
| 261 | 'description' => __( 'The settings below adjust the lightbox options.', 'responsive-lightbox' ), |
| 262 | ), |
| 263 | 'misc' => array( |
| 264 | 'label' => __( 'Misc', 'responsive-lightbox' ), |
| 265 | 'description' => __( 'The settings below adjust miscellaneous options.', 'responsive-lightbox' ), |
| 266 | ) |
| 267 | ) |
| 268 | ); |
| 269 | |
| 270 | // add folders if active |
| 271 | if ( $rl->options['folders']['active'] ) |
| 272 | $this->tabs['images']['menu_items']['folders'] = __( 'Media Folder', 'responsive-lightbox' ); |
| 273 | |
| 274 | // add remote library if active |
| 275 | $this->tabs['images']['menu_items']['remote_library'] = __( 'Remote Library', 'responsive-lightbox' ); |
| 276 | |
| 277 | // use sizes as keys and values |
| 278 | $this->sizes = $this->get_image_sizes(); |
| 279 | $sizes = array_combine( array_keys( $this->sizes ), array_keys( $this->sizes ) ); |
| 280 | |
| 281 | // add default, custom and full image size |
| 282 | $sizes['full'] = __( 'Full size', 'responsive-lightbox' ); |
| 283 | $sizes['global'] = __( 'Global', 'responsive-lightbox' ); |
| 284 | $sizes['rl_custom_size'] = __( 'Custom size', 'responsive-lightbox' ); |
| 285 | |
| 286 | // positions |
| 287 | $positions = array( |
| 288 | 'none' => __( 'None', 'responsive-lightbox' ), |
| 289 | 'top' => __( 'Top', 'responsive-lightbox' ), |
| 290 | 'bottom' => __( 'Bottom', 'responsive-lightbox' ) |
| 291 | ); |
| 292 | |
| 293 | // merge titles |
| 294 | $merged_titles = array( 'global' => __( 'Global', 'responsive-lightbox' ) ) + $rl->settings->get_data( 'image_titles' ); |
| 295 | |
| 296 | // set fields |
| 297 | $this->fields = array( |
| 298 | 'images' => [], |
| 299 | // Field definitions for config, design, paging, lightbox, misc are populated from adapter classes below. |
| 300 | // This ensures single source of truth and eliminates duplication while maintaining get_data('fields') contract. |
| 301 | 'config' => [], |
| 302 | 'design' => [], |
| 303 | 'paging' => [], |
| 304 | 'lightbox' => [], |
| 305 | 'misc' => [] |
| 306 | ); |
| 307 | |
| 308 | // Populate adapter-owned tabs from their classes (single source of truth - v2.7.1+) |
| 309 | // This eliminates field duplication while maintaining get_data('fields') public contract |
| 310 | // for core frontend and gallery add-ons that access design/lightbox/misc fields. |
| 311 | if ( isset( $rl->gallery_api ) ) { |
| 312 | foreach ( [ 'images', 'config', 'design', 'paging', 'lightbox', 'misc' ] as $adapter_tab ) { |
| 313 | if ( $rl->gallery_api->is_managed_tab( $adapter_tab ) ) { |
| 314 | $tab_data = $rl->gallery_api->get_tab_definition( $adapter_tab ); |
| 315 | if ( ! empty( $tab_data ) ) { |
| 316 | $this->fields[$adapter_tab] = $tab_data; |
| 317 | } |
| 318 | } |
| 319 | } |
| 320 | } |
| 321 | } |
| 322 | |
| 323 | /** |
| 324 | * Add a gallery shortcode. |
| 325 | * |
| 326 | * @param array $args Shortcode arguments |
| 327 | * @return string |
| 328 | */ |
| 329 | public function gallery_shortcode( $args ) { |
| 330 | // enable only for frontend previews |
| 331 | if ( ! is_admin() && is_preview() ) |
| 332 | add_filter( 'get_post_metadata', array( $this, 'filter_preview_metadata' ), 10, 4 ); |
| 333 | |
| 334 | // prepare defaults |
| 335 | $defaults = [ 'id' => 0 ]; |
| 336 | |
| 337 | // merge defaults with arguments |
| 338 | $args = array_merge( $defaults, $args ); |
| 339 | |
| 340 | // parse id |
| 341 | $args['id'] = (int) $args['id']; |
| 342 | |
| 343 | // is it gallery? |
| 344 | if ( get_post_type( $args['id'] ) !== 'rl_gallery' ) |
| 345 | return ''; |
| 346 | |
| 347 | // private gallery? |
| 348 | if ( get_post_status( $args['id'] ) === 'private' && ! current_user_can( 'read_private_posts' ) ) |
| 349 | return ''; |
| 350 | |
| 351 | $images_args = [ 'exclude' => true ]; |
| 352 | |
| 353 | if ( isset( $args['preview'] ) ) |
| 354 | $images_args['preview'] = (bool) $args['preview']; |
| 355 | elseif( isset( $_GET['rl_gallery_revision_id'], $_GET['preview'] ) && $_GET['preview'] === 'true' ) |
| 356 | $images_args['preview'] = true; |
| 357 | else |
| 358 | $images_args['preview'] = false; |
| 359 | |
| 360 | // get images |
| 361 | $images = $this->get_gallery_images( $args['id'], $images_args ); |
| 362 | |
| 363 | if ( ! $images ) |
| 364 | return ''; |
| 365 | |
| 366 | $attachments = []; |
| 367 | |
| 368 | // build config |
| 369 | foreach ( $images as $image ) { |
| 370 | if ( ! empty( $image['id'] ) ) |
| 371 | $attachments[] = $image['id']; |
| 372 | } |
| 373 | |
| 374 | // get config data |
| 375 | $config = get_post_meta( $args['id'], '_rl_config', true ); |
| 376 | if ( ! is_array( $config ) ) |
| 377 | $config = []; |
| 378 | |
| 379 | // get main instance |
| 380 | $rl = Responsive_Lightbox(); |
| 381 | |
| 382 | // available gallery types |
| 383 | $gallery_types = apply_filters( 'rl_gallery_types', $rl->get_data( 'gallery_types' ) ); |
| 384 | if ( ! is_array( $gallery_types ) ) |
| 385 | $gallery_types = []; |
| 386 | |
| 387 | // prepare gallery shortcode parameters |
| 388 | $fields = []; |
| 389 | $gallery_type = ''; |
| 390 | $menu_item = ! empty( $config['menu_item'] ) ? $config['menu_item'] : 'default'; |
| 391 | if ( ! empty( $menu_item ) && $menu_item !== 'default' && ! array_key_exists( $menu_item, $gallery_types ) ) |
| 392 | $menu_item = 'default'; |
| 393 | |
| 394 | // valid menu item? |
| 395 | if ( ! empty( $menu_item ) ) { |
| 396 | // assign data from db |
| 397 | $data = isset( $config[$menu_item] ) && is_array( $config[$menu_item] ) ? $config[$menu_item] : []; |
| 398 | |
| 399 | foreach ( $rl->frontend->get_default_gallery_fields() as $field_name => $field_args ) { |
| 400 | // replace default values |
| 401 | if ( array_key_exists( $field_name, $data ) ) |
| 402 | $fields[$field_name] = $data[$field_name]; |
| 403 | } |
| 404 | |
| 405 | // is it default gallery type? |
| 406 | if ( $menu_item === 'default' ) { |
| 407 | // set new gallery type |
| 408 | $gallery_type = $rl->options['settings']['builder_gallery']; |
| 409 | |
| 410 | // fallback to a valid gallery type |
| 411 | if ( empty( $gallery_type ) || ! array_key_exists( $gallery_type, $gallery_types ) ) |
| 412 | $gallery_type = $rl->defaults['settings']['builder_gallery']; |
| 413 | |
| 414 | // assign gallery settings |
| 415 | $gallery_fields = $rl->settings->get_setting_fields( $gallery_type . '_gallery' ); |
| 416 | // assign gallery defaults |
| 417 | if ( array_key_exists( $gallery_type . '_gallery', $rl->options ) ) |
| 418 | $gallery_defaults = $rl->options[$gallery_type . '_gallery']; |
| 419 | } else { |
| 420 | $gallery_type = $menu_item; |
| 421 | |
| 422 | // fallback to a valid gallery type |
| 423 | if ( empty( $gallery_type ) || ! array_key_exists( $gallery_type, $gallery_types ) ) |
| 424 | $gallery_type = $rl->options['settings']['builder_gallery']; |
| 425 | |
| 426 | // assign gallery settings |
| 427 | $gallery_fields = $rl->settings->get_setting_fields( $menu_item . '_gallery' ); |
| 428 | // assign gallery defaults |
| 429 | if ( array_key_exists( $menu_item . '_gallery', $rl->defaults ) ) |
| 430 | $gallery_defaults = $rl->defaults[$menu_item . '_gallery']; |
| 431 | } |
| 432 | |
| 433 | if ( ! isset( $gallery_defaults ) && ! empty( $gallery_type ) && array_key_exists( $gallery_type . '_gallery', $rl->defaults ) ) |
| 434 | $gallery_defaults = $rl->defaults[$gallery_type . '_gallery']; |
| 435 | |
| 436 | if ( ! isset( $gallery_fields ) && ! empty( $gallery_type ) ) |
| 437 | $gallery_fields = $rl->settings->get_setting_fields( $gallery_type . '_gallery' ); |
| 438 | |
| 439 | if ( isset( $gallery_fields, $gallery_defaults ) ) { |
| 440 | // run through all fields |
| 441 | foreach ( $gallery_fields as $field_name => $field_args ) { |
| 442 | if ( $field_args['type'] === 'multiple' ) { |
| 443 | foreach ( $field_args['fields'] as $subfield_name => $subfield_args ) { |
| 444 | // field exists in db? |
| 445 | if ( array_key_exists( $subfield_name, $data ) ) |
| 446 | $fields[$subfield_name] = $data[$subfield_name]; |
| 447 | elseif ( isset( $rl->options[$gallery_type . '_gallery'][ $subfield_name ] ) ) |
| 448 | $fields[$subfield_name] = $rl->options[$gallery_type . '_gallery'][ $subfield_name ]; |
| 449 | else |
| 450 | $fields[$subfield_name] = $gallery_defaults[$subfield_name]; |
| 451 | } |
| 452 | } else { |
| 453 | // field exists in db? |
| 454 | if ( array_key_exists( $field_name, $data ) ) |
| 455 | $fields[$field_name] = $data[$field_name]; |
| 456 | elseif ( isset( $rl->options[$gallery_type . '_gallery'][ $field_name ] ) ) |
| 457 | $fields[$field_name] = $rl->options[$gallery_type . '_gallery'][ $field_name ]; |
| 458 | else |
| 459 | $fields[$field_name] = $gallery_defaults[$field_name]; |
| 460 | } |
| 461 | } |
| 462 | } |
| 463 | // add gallery type |
| 464 | if ( ! empty( $gallery_type ) && array_key_exists( $gallery_type, $gallery_types ) ) |
| 465 | $fields['type'] = $gallery_type; |
| 466 | } |
| 467 | |
| 468 | // ensure gallery type is present and valid |
| 469 | if ( empty( $fields['type'] ) || ! array_key_exists( $fields['type'], $gallery_types ) ) { |
| 470 | $fallback_type = $rl->options['settings']['builder_gallery']; |
| 471 | if ( empty( $fallback_type ) || ! array_key_exists( $fallback_type, $gallery_types ) ) |
| 472 | $fallback_type = $rl->defaults['settings']['builder_gallery']; |
| 473 | |
| 474 | if ( ! empty( $fallback_type ) && array_key_exists( $fallback_type, $gallery_types ) ) |
| 475 | $fields['type'] = $fallback_type; |
| 476 | } |
| 477 | |
| 478 | $shortcode = ''; |
| 479 | |
| 480 | foreach ( $fields as $arg => $value ) { |
| 481 | if ( is_array( $value ) ) |
| 482 | $shortcode .= ' ' . esc_attr( $arg ) . '="' . esc_attr( (string) implode( ',', $value ) ) . '"'; |
| 483 | else |
| 484 | $shortcode .= ' ' . esc_attr( $arg ) . '="' . esc_attr( (string) $value ) . '"'; |
| 485 | } |
| 486 | |
| 487 | // get design data |
| 488 | $design = get_post_meta( $args['id'], '_rl_design', true ); |
| 489 | $design = is_array( $design ) ? $design : []; |
| 490 | |
| 491 | if ( ! empty( $design['menu_item'] ) && isset( $design[$design['menu_item']] ) && is_array( $design[$design['menu_item']] ) ) { |
| 492 | $design_data = $design[$design['menu_item']]; |
| 493 | |
| 494 | // remove show_title to avoid shortcode attribute duplication |
| 495 | if ( isset( $design_data['show_title'] ) ) { |
| 496 | if ( ! isset( $design_data['design_show_title'] ) ) |
| 497 | $design_data['design_show_title'] = $design_data['show_title']; |
| 498 | |
| 499 | unset( $design_data['show_title'] ); |
| 500 | } |
| 501 | |
| 502 | // remove show_caption to avoid shortcode attribute duplication |
| 503 | if ( isset( $design_data['show_caption'] ) ) { |
| 504 | if ( ! isset( $design_data['design_show_caption'] ) ) |
| 505 | $design_data['design_show_caption'] = $design_data['show_caption']; |
| 506 | |
| 507 | unset( $design_data['show_caption'] ); |
| 508 | } |
| 509 | |
| 510 | foreach ( $design_data as $arg => $value ) { |
| 511 | $shortcode .= ' ' . esc_attr( $arg ) . '="' . esc_attr( (string) $value ) . '"'; |
| 512 | } |
| 513 | } |
| 514 | |
| 515 | // get lightbox data |
| 516 | $lightbox = get_post_meta( $args['id'], '_rl_lightbox', true ); |
| 517 | $lightbox = is_array( $lightbox ) ? $lightbox : []; |
| 518 | |
| 519 | if ( ! empty( $lightbox['menu_item'] ) && isset( $lightbox[$lightbox['menu_item']] ) && is_array( $lightbox[$lightbox['menu_item']] ) ) { |
| 520 | foreach ( $lightbox[$lightbox['menu_item']] as $arg => $value ) { |
| 521 | $shortcode .= ' ' . esc_attr( $arg ) . '="' . esc_attr( (string) $value ) . '"'; |
| 522 | } |
| 523 | } |
| 524 | |
| 525 | $forced_gallery_no = 0; |
| 526 | |
| 527 | // check forced gallery number |
| 528 | if ( isset( $args['gallery_no'] ) ) { |
| 529 | $args['gallery_no'] = (int) $args['gallery_no']; |
| 530 | |
| 531 | if ( $args['gallery_no'] > 0 ) |
| 532 | $forced_gallery_no = $args['gallery_no']; |
| 533 | } |
| 534 | |
| 535 | // get content |
| 536 | $content = do_shortcode( '[gallery rl_gallery_id="' . esc_attr( $args['id'] ) .'"' . ( $forced_gallery_no > 0 ? ' rl_gallery_no="' . (int) $forced_gallery_no .'"' : '' ) . ' include="' . ( empty( $attachments ) ? '' : esc_attr( implode( ',', $attachments ) ) ) . '"' . $shortcode . ']' ); |
| 537 | |
| 538 | // make sure every filter is available in frontend ajax |
| 539 | if ( wp_doing_ajax() ) |
| 540 | $content = $rl->frontend->add_lightbox( $content ); |
| 541 | |
| 542 | return $content; |
| 543 | } |
| 544 | |
| 545 | /** |
| 546 | * Add a gallery button. |
| 547 | * |
| 548 | * @param string $editor_id Editor ID |
| 549 | * @return void |
| 550 | */ |
| 551 | public function add_gallery_button( $editor_id ) { |
| 552 | if ( get_post_type() === 'rl_gallery' ) |
| 553 | return; |
| 554 | |
| 555 | $this->enqueue_gallery_scripts_styles(); |
| 556 | |
| 557 | echo '<button type="button" id="rl-insert-modal-gallery-button" class="button" data-editor="' . esc_attr( $editor_id ) . '"><span class="wp-media-buttons-icon dashicons dashicons-format-gallery"></span> ' . esc_html__( 'Add Gallery', 'responsive-lightbox' ) . '</button>'; |
| 558 | } |
| 559 | |
| 560 | /** |
| 561 | * Enqueue scripts and styles needed for gallery modal. |
| 562 | * |
| 563 | * @global string $pagenow |
| 564 | * |
| 565 | * @return void |
| 566 | */ |
| 567 | public function enqueue_gallery_scripts_styles() { |
| 568 | global $pagenow; |
| 569 | |
| 570 | // count how many times function was executed |
| 571 | static $run = 0; |
| 572 | |
| 573 | // allow this only once |
| 574 | if ( $run > 0 ) |
| 575 | return; |
| 576 | |
| 577 | $run++; |
| 578 | |
| 579 | // get main instance |
| 580 | $rl = Responsive_Lightbox(); |
| 581 | |
| 582 | wp_enqueue_script( 'responsive-lightbox-admin-gallery', RESPONSIVE_LIGHTBOX_URL . '/js/admin-gallery.js', array( 'jquery', 'underscore' ), $rl->defaults['version'], false ); |
| 583 | |
| 584 | // prepare script data |
| 585 | $script_data = [ |
| 586 | 'nonce' => wp_create_nonce( 'rl-gallery-post' ), |
| 587 | 'post_id' => get_the_ID(), |
| 588 | 'page' => esc_url( $pagenow ) |
| 589 | ]; |
| 590 | |
| 591 | wp_add_inline_script( 'responsive-lightbox-admin-gallery', 'var rlArgsGallery = ' . wp_json_encode( $script_data ) . ";\n", 'before' ); |
| 592 | |
| 593 | wp_enqueue_style( 'responsive-lightbox-admin-gallery', RESPONSIVE_LIGHTBOX_URL . '/css/admin-gallery.css', [], $rl->defaults['version'] ); |
| 594 | } |
| 595 | |
| 596 | /** |
| 597 | * Modal gallery HTML template. |
| 598 | * |
| 599 | * @global string $wp_version |
| 600 | * @global string $pagenow |
| 601 | * |
| 602 | * @return void |
| 603 | */ |
| 604 | public function modal_gallery_template() { |
| 605 | global $wp_version; |
| 606 | global $pagenow; |
| 607 | |
| 608 | // display only for post edit pages |
| 609 | if ( ! ( ( ( $pagenow === 'post.php' || $pagenow === 'post-new.php' ) && get_post_type() !== 'rl_gallery' ) || ( version_compare( $wp_version, '5.8', '>=' ) && ( $pagenow === 'widgets.php' || $pagenow === 'customize.php' ) ) ) ) |
| 610 | return; |
| 611 | |
| 612 | // get main instance |
| 613 | $rl = Responsive_Lightbox(); |
| 614 | |
| 615 | $categories = ''; |
| 616 | |
| 617 | // builder categories? |
| 618 | if ( $rl->options['builder']['categories'] ) { |
| 619 | $terms = get_terms( |
| 620 | array( |
| 621 | 'taxonomy' => 'rl_category', |
| 622 | 'orderby' => 'name', |
| 623 | 'order' => 'ASC', |
| 624 | 'hide_empty' => false, |
| 625 | 'fields' => 'id=>name' |
| 626 | ) |
| 627 | ); |
| 628 | |
| 629 | // get categories dropdown |
| 630 | $categories = wp_dropdown_categories( |
| 631 | array( |
| 632 | 'orderby' => 'name', |
| 633 | 'order' => 'asc', |
| 634 | 'show_option_none' => empty( $terms ) ? __( 'All categories', 'responsive-lightbox' ) : '', |
| 635 | 'show_option_all' => __( 'All categories', 'responsive-lightbox' ), |
| 636 | 'show_count' => false, |
| 637 | 'hide_empty' => false, |
| 638 | 'option_none_value' => 0, |
| 639 | 'hierarchical' => true, |
| 640 | 'selected' => 0, |
| 641 | 'taxonomy' => 'rl_category', |
| 642 | 'hide_if_empty' => false, |
| 643 | 'echo' => false, |
| 644 | 'id' => 'rl-media-attachment-categories', |
| 645 | 'class' => 'attachment-filters', |
| 646 | 'name' => '' |
| 647 | ) |
| 648 | ); |
| 649 | } |
| 650 | |
| 651 | echo ' |
| 652 | <div id="rl-modal-gallery" style="display: none;"> |
| 653 | <div class="media-modal wp-core-ui"> |
| 654 | <button type="button" class="media-modal-close"><span class="media-modal-icon"><span class="screen-reader-text">' . esc_html__( 'Close', 'responsive-lightbox' ) . '</span></span></button> |
| 655 | <div class="media-modal-content"> |
| 656 | <div class="media-frame mode-select wp-core-ui hide-menu hide-router"> |
| 657 | <div class="media-frame-title"> |
| 658 | <h1 class="wrap">' . esc_html__( 'Insert Gallery', 'responsive-lightbox' ) . ' <a class="rl-reload-galleries page-title-action" href="#">' . esc_html__( 'Reload', 'responsive-lightbox' ). '</a><span class="rl-gallery-reload-spinner spinner"></span></h1> |
| 659 | </div> |
| 660 | <div class="media-frame-content" data-columns="0"> |
| 661 | <div class="attachments-browser"> |
| 662 | <div class="uploader-inline rl-no-galleries" style="display: none;"> |
| 663 | <div class="uploader-inline-content has-upload-message"> |
| 664 | <h2 class="upload-message">' . esc_html__( 'No items found.', 'responsive-lightbox' ) . '</h2> |
| 665 | <div class="upload-ui"> |
| 666 | <h2 class="upload-instructions">' . esc_html__( 'No galleries? Create them first or try another search phrase.', 'responsive-lightbox' ) . '</h2> |
| 667 | </div> |
| 668 | </div> |
| 669 | </div> |
| 670 | <div class="media-toolbar">' . ( $rl->options['builder']['categories'] ? ' |
| 671 | <div class="media-toolbar-secondary"><label for="rl-media-attachment-categories" class="screen-reader-text">' . esc_html__( 'Filter by category', 'responsive-lightbox' ) . '</label>' . ( $categories !== '' ? wp_kses( $categories, $this->allowed_select_html ) : '' ) . '</div>' : '' ) . ' |
| 672 | <div class="media-toolbar-primary search-form"> |
| 673 | <label for="rl-media-search-input" class="screen-reader-text">' . esc_html__( 'Search galleries', 'responsive-lightbox' ) . '</label><input type="search" placeholder="' . esc_attr__( 'Search galleries', 'responsive-lightbox' ) . '" id="rl-media-search-input" class="search"> |
| 674 | </div> |
| 675 | </div> |
| 676 | <ul class="attachments rl-galleries-list ui-sortable ui-sortable-disabled"> |
| 677 | </ul> |
| 678 | <div class="media-sidebar visible"> |
| 679 | <h2>' . esc_html__( 'Select A Gallery', 'responsive-lightbox' ) . '</h2> |
| 680 | <p>' . esc_html__( 'To select a gallery simply click on one of the boxes to the left.', 'responsive-lightbox' ) . '</p> |
| 681 | <p>' . esc_html__( 'To insert your gallery into the editor, click on the "Insert Gallery" button below.', 'responsive-lightbox' ) . '</p> |
| 682 | </div> |
| 683 | </div> |
| 684 | </div> |
| 685 | <div class="media-frame-toolbar"> |
| 686 | <div class="media-toolbar"> |
| 687 | <div class="media-toolbar-secondary"> |
| 688 | <div class="media-selection empty"> |
| 689 | <div class="selection-info"> |
| 690 | <span class="rl-gallery-count count">' . esc_html( sprintf( _n( '%s image', '%s images', 0, 'responsive-lightbox' ), 0 ) ) . '</span> |
| 691 | <a href="" class="button-link rl-edit-gallery-link">' . esc_html__( 'Edit gallery', 'responsive-lightbox' ) . '</a> |
| 692 | </div> |
| 693 | <div class="selection-view"> |
| 694 | <span class="rl-gallery-images-spinner spinner" style="display: none;"></span> |
| 695 | <ul class="attachments rl-attachments-list"> |
| 696 | </ul> |
| 697 | </div> |
| 698 | </div> |
| 699 | </div> |
| 700 | <div class="media-toolbar-primary search-form"> |
| 701 | <button style="display: none;" type="button" class="button media-button button-primary button-large rl-media-button-insert-gallery" disabled="disabled">' . esc_html__( 'Insert gallery into post', 'responsive-lightbox') . '</button> |
| 702 | <button style="display: none;" type="button" class="button media-button button-primary button-large rl-media-button-select-gallery" disabled="disabled">' . esc_html__( 'Select gallery', 'responsive-lightbox') . '</button> |
| 703 | <button type="button" class="button media-button button-secondary button-large rl-media-button-cancel-gallery">' . esc_html__( 'Cancel', 'responsive-lightbox') . '</button> |
| 704 | </div> |
| 705 | </div> |
| 706 | </div> |
| 707 | </div> |
| 708 | </div> |
| 709 | </div> |
| 710 | <div class="media-modal-backdrop"></div> |
| 711 | </div>'; |
| 712 | } |
| 713 | |
| 714 | /** |
| 715 | * Add menu tabs after the post title. |
| 716 | * |
| 717 | * @global array $wp_meta_boxes |
| 718 | * |
| 719 | * @param object $post Post object |
| 720 | * @return void |
| 721 | */ |
| 722 | public function after_title_nav_menu( $post ) { |
| 723 | if ( $post->post_type !== 'rl_gallery' ) |
| 724 | return; |
| 725 | |
| 726 | global $wp_meta_boxes; |
| 727 | |
| 728 | // check active tab |
| 729 | $active_tab = isset( $_GET['rl_active_tab'] ) ? sanitize_key( $_GET['rl_active_tab'] ) : ''; |
| 730 | $active_tab = ! empty( $active_tab ) && array_key_exists( $active_tab, $this->tabs ) ? $active_tab : 'images'; |
| 731 | |
| 732 | echo ' |
| 733 | <div class="rl-settings-wrapper"> |
| 734 | <h2 class="nav-tab-wrapper">'; |
| 735 | |
| 736 | foreach ( $this->tabs as $key => $data ) { |
| 737 | echo ' |
| 738 | <a id="rl-gallery-tab-' . esc_attr( $key ) . '" class="rl-gallery-tab nav-tab' . ( $key === $active_tab ? ' nav-tab-active' : '' ) . '" href="#' . esc_attr( $key ) . '">' . esc_html( $data['label'] ) . '</a>'; |
| 739 | } |
| 740 | |
| 741 | echo ' |
| 742 | </h2>'; |
| 743 | |
| 744 | do_meta_boxes( $post->post_type, 'responsive_lightbox_metaboxes', $post ); |
| 745 | |
| 746 | echo ' |
| 747 | </div>'; |
| 748 | |
| 749 | unset( $wp_meta_boxes[$post->post_type]['responsive_lightbox_metaboxes'] ); |
| 750 | } |
| 751 | |
| 752 | /** |
| 753 | * Add class to hide metabox. |
| 754 | * |
| 755 | * @param array $classes |
| 756 | * @return array |
| 757 | */ |
| 758 | public function hide_metabox( $classes ) { |
| 759 | $classes[] = 'rl-metabox-content'; |
| 760 | $classes[] = 'rl-hide-metabox'; |
| 761 | |
| 762 | return $classes; |
| 763 | } |
| 764 | |
| 765 | /** |
| 766 | * Add class to display the metabox. |
| 767 | * |
| 768 | * @param array $classes |
| 769 | * @return array |
| 770 | */ |
| 771 | function display_metabox( $classes ) { |
| 772 | $classes[] = 'rl-metabox-content'; |
| 773 | $classes[] = 'rl-display-metabox'; |
| 774 | |
| 775 | return $classes; |
| 776 | } |
| 777 | |
| 778 | /** |
| 779 | * Add settings wrapper class to the metabox. |
| 780 | * |
| 781 | * @param array $classes |
| 782 | * @return array |
| 783 | */ |
| 784 | public function add_settings_wrapper_class( $classes ) { |
| 785 | if ( ! in_array( 'rl-settings', $classes, true ) ) |
| 786 | $classes[] = 'rl-settings'; |
| 787 | |
| 788 | return $classes; |
| 789 | } |
| 790 | |
| 791 | /** |
| 792 | * Add active tab to post redirect destination URL. |
| 793 | * |
| 794 | * @param string $location Destination URL |
| 795 | * @return string |
| 796 | */ |
| 797 | function add_active_tab( $location ) { |
| 798 | // check active tab |
| 799 | $active_tab = isset( $_POST['rl_active_tab'] ) ? sanitize_key( $_POST['rl_active_tab'] ) : ''; |
| 800 | |
| 801 | return add_query_arg( 'rl_active_tab', ! empty( $active_tab ) && array_key_exists( $active_tab, $this->tabs ) ? $active_tab : 'images', $location ); |
| 802 | } |
| 803 | |
| 804 | /** |
| 805 | * Add metaboxes. |
| 806 | * |
| 807 | * @return void |
| 808 | */ |
| 809 | public function add_meta_boxes() { |
| 810 | // side metaboxes |
| 811 | add_meta_box( 'responsive-gallery-shortcode', esc_html__( 'Gallery Code', 'responsive-lightbox' ), array( $this, 'shortcode_metabox' ), 'rl_gallery', 'side', 'core' ); |
| 812 | } |
| 813 | |
| 814 | /** |
| 815 | * Get number of gallery images. |
| 816 | * |
| 817 | * @param int $gallery_id |
| 818 | * @return int |
| 819 | */ |
| 820 | public function get_gallery_images_number( $gallery_id ) { |
| 821 | return count( $this->get_gallery_images( $gallery_id, [ 'count_images' => true, 'preview' => false, 'exclude' => true ] ) ); |
| 822 | } |
| 823 | |
| 824 | /** |
| 825 | * Sync gallery image counts when an attachment is deleted. |
| 826 | * |
| 827 | * @param int $attachment_id |
| 828 | * @return void |
| 829 | */ |
| 830 | public function delete_attachment( $attachment_id ) { |
| 831 | $attachment_id = (int) $attachment_id; |
| 832 | if ( $attachment_id <= 0 ) |
| 833 | return; |
| 834 | |
| 835 | $galleries = get_posts( [ |
| 836 | 'post_type' => 'rl_gallery', |
| 837 | 'post_status' => [ 'publish', 'private', 'draft', 'pending', 'future' ], |
| 838 | 'fields' => 'ids', |
| 839 | 'nopaging' => true, |
| 840 | 'meta_query' => [ |
| 841 | [ |
| 842 | 'key' => '_rl_images', |
| 843 | 'value' => (string) $attachment_id, |
| 844 | 'compare' => 'LIKE' |
| 845 | ] |
| 846 | ] |
| 847 | ] ); |
| 848 | |
| 849 | if ( empty( $galleries ) ) |
| 850 | return; |
| 851 | |
| 852 | foreach ( $galleries as $gallery_id ) { |
| 853 | update_post_meta( $gallery_id, '_rl_images_count', $this->get_gallery_images_number( $gallery_id ) ); |
| 854 | } |
| 855 | } |
| 856 | |
| 857 | /** |
| 858 | * Load featured content query args. |
| 859 | * |
| 860 | * @global string $pagenow |
| 861 | * |
| 862 | * @return void |
| 863 | */ |
| 864 | public function init_admin() { |
| 865 | global $pagenow; |
| 866 | |
| 867 | // check values |
| 868 | $post = isset( $_GET['post'] ) ? (int) $_GET['post'] : 0; |
| 869 | $post_id = isset( $_POST['post_ID'] ) ? (int) $_POST['post_ID'] : 0; |
| 870 | $action = isset( $_POST['action'] ) ? sanitize_key( $_POST['action'] ) : ''; |
| 871 | $post_type = isset( $_POST['post_type'] ) ? sanitize_key( $_POST['post_type'] ) : ''; |
| 872 | |
| 873 | // prepare query arguments if needed |
| 874 | if ( ( $pagenow === 'post.php' && ( ( $post && get_post_type( $post ) === 'rl_gallery' ) || ( $post_id && get_post_type( $post_id ) === 'rl_gallery' ) ) ) || ( in_array( $pagenow, array( 'edit.php', 'post-new.php'), true ) && $post_type === 'rl_gallery' ) || ( $pagenow === 'admin-ajax.php' && $action && in_array( $action, array( 'rl-get-preview-content', 'rl-post-gallery-preview', 'rl-get-menu-content' ), true ) ) ) |
| 875 | $this->fields['images']['featured'] = $this->prepare_featured_fields( $this->fields['images']['featured'] ); |
| 876 | |
| 877 | // add default thumbnail image if needed |
| 878 | if ( Responsive_Lightbox()->options['builder']['gallery_builder'] && $pagenow === 'edit.php' && $post_type && $post_type === 'rl_gallery' ) |
| 879 | $this->maybe_generate_thumbnail(); |
| 880 | } |
| 881 | |
| 882 | /** |
| 883 | * Generate post thumbnail replacement. |
| 884 | * |
| 885 | * @return int |
| 886 | */ |
| 887 | public function maybe_generate_thumbnail() { |
| 888 | // get old attachment |
| 889 | $thumbnail_id = get_posts( |
| 890 | array( |
| 891 | 'name' => 'responsive-lightbox-thumbnail', |
| 892 | 'post_type' => 'attachment', |
| 893 | 'post_status' => 'inherit', |
| 894 | 'numberposts' => 1, |
| 895 | 'fields' => 'ids' |
| 896 | ) |
| 897 | ); |
| 898 | |
| 899 | // no attachment? |
| 900 | if ( empty( $thumbnail_id ) ) { |
| 901 | // get new attachment |
| 902 | $thumbnail_id = get_posts( |
| 903 | array( |
| 904 | 'name' => 'responsive-lightbox-thumbnail', |
| 905 | 'post_type' => 'attachment', |
| 906 | 'post_status' => 'pending', |
| 907 | 'numberposts' => 1, |
| 908 | 'fields' => 'ids' |
| 909 | ) |
| 910 | ); |
| 911 | |
| 912 | // no attachment? |
| 913 | if ( empty( $thumbnail_id ) ) { |
| 914 | // get upload directory data |
| 915 | $wp_upload_dir = wp_upload_dir(); |
| 916 | |
| 917 | // get file path |
| 918 | $filepath = str_replace( '\\', '/', RESPONSIVE_LIGHTBOX_PATH . 'images/responsive-lightbox-thumbnail.png' ); |
| 919 | |
| 920 | // get file name |
| 921 | $filename = basename( $filepath ); |
| 922 | |
| 923 | // new filepath in upload dir |
| 924 | $new_filepath = $wp_upload_dir['path'] . '/' . $filename; |
| 925 | |
| 926 | // copty file to upload dir |
| 927 | copy( $filepath, $new_filepath ); |
| 928 | |
| 929 | // get type of file |
| 930 | $filetype = wp_check_filetype( $filename ); |
| 931 | |
| 932 | // force pending status for the attachment |
| 933 | add_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) ); |
| 934 | |
| 935 | // insert attachment |
| 936 | $thumbnail_id = wp_insert_attachment( |
| 937 | array( |
| 938 | 'guid' => $wp_upload_dir['url'] . '/' . $filename, |
| 939 | 'post_mime_type' => $filetype['type'], |
| 940 | 'post_title' => preg_replace( '/\.[^.]+$/', '', $filename ), |
| 941 | 'post_content' => '', |
| 942 | 'post_parent' => 0, |
| 943 | 'post_status' => 'inherit' |
| 944 | ), |
| 945 | $new_filepath, |
| 946 | 0 |
| 947 | ); |
| 948 | |
| 949 | remove_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) ); |
| 950 | |
| 951 | // success? |
| 952 | if ( $thumbnail_id ) { |
| 953 | // make sure that this file is included |
| 954 | require_once( ABSPATH . 'wp-admin/includes/image.php' ); |
| 955 | |
| 956 | // update database with generated metadata for the attachment |
| 957 | wp_update_attachment_metadata( $thumbnail_id, wp_generate_attachment_metadata( $thumbnail_id, $new_filepath ) ); |
| 958 | } |
| 959 | } else |
| 960 | $thumbnail_id = $thumbnail_id[0]; |
| 961 | } else { |
| 962 | // force pending status for the attachment |
| 963 | add_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) ); |
| 964 | |
| 965 | $thumbnail_id = wp_update_post( |
| 966 | array( |
| 967 | 'ID' => $thumbnail_id[0], |
| 968 | 'post_status' => 'pending' |
| 969 | ) |
| 970 | ); |
| 971 | |
| 972 | remove_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) ); |
| 973 | } |
| 974 | |
| 975 | return (int) $thumbnail_id; |
| 976 | } |
| 977 | |
| 978 | /** |
| 979 | * Get video thumbnail replacement. |
| 980 | * |
| 981 | * @param int $post_id |
| 982 | * @return int |
| 983 | */ |
| 984 | public function get_video_thumbnail_id( $post_id ) { |
| 985 | $thumbnail_id = 0; |
| 986 | |
| 987 | // try to get video thumbnail |
| 988 | $attachment_id = (int) get_post_thumbnail_id( $post_id ); |
| 989 | |
| 990 | // real attachment? |
| 991 | if ( wp_attachment_is_image( $attachment_id ) ) |
| 992 | $thumbnail_id = $attachment_id; |
| 993 | |
| 994 | // try to get default video poster image |
| 995 | if ( ! $thumbnail_id ) { |
| 996 | $thumbnail_id = get_posts( |
| 997 | array( |
| 998 | 'name' => 'responsive-lightbox-video-thumbnail', |
| 999 | 'post_type' => 'attachment', |
| 1000 | 'post_status' => 'inherit', |
| 1001 | 'numberposts' => 1, |
| 1002 | 'fields' => 'ids' |
| 1003 | ) |
| 1004 | ); |
| 1005 | } |
| 1006 | |
| 1007 | // no attachment? |
| 1008 | if ( ! $thumbnail_id ) { |
| 1009 | // get new attachment |
| 1010 | $thumbnail_id = get_posts( |
| 1011 | array( |
| 1012 | 'name' => 'responsive-lightbox-video-thumbnail', |
| 1013 | 'post_type' => 'attachment', |
| 1014 | 'post_status' => 'pending', |
| 1015 | 'numberposts' => 1, |
| 1016 | 'fields' => 'ids' |
| 1017 | ) |
| 1018 | ); |
| 1019 | |
| 1020 | // no attachment? |
| 1021 | if ( ! $thumbnail_id ) { |
| 1022 | // get upload directory data |
| 1023 | $wp_upload_dir = wp_upload_dir(); |
| 1024 | |
| 1025 | // get file path |
| 1026 | $filepath = str_replace( '\\', '/', RESPONSIVE_LIGHTBOX_PATH . 'images/responsive-lightbox-video-thumbnail.png' ); |
| 1027 | |
| 1028 | // get file name |
| 1029 | $filename = basename( $filepath ); |
| 1030 | |
| 1031 | // new filepath in upload dir |
| 1032 | $new_filepath = $wp_upload_dir['path'] . '/' . $filename; |
| 1033 | |
| 1034 | // copty file to upload dir |
| 1035 | copy( $filepath, $new_filepath ); |
| 1036 | |
| 1037 | // get type of file |
| 1038 | $filetype = wp_check_filetype( $filename ); |
| 1039 | |
| 1040 | // force pending status for the attachment |
| 1041 | add_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) ); |
| 1042 | |
| 1043 | // insert attachment |
| 1044 | $thumbnail_id = wp_insert_attachment( |
| 1045 | array( |
| 1046 | 'guid' => $wp_upload_dir['url'] . '/' . $filename, |
| 1047 | 'post_mime_type' => $filetype['type'], |
| 1048 | 'post_title' => preg_replace( '/\.[^.]+$/', '', $filename ), |
| 1049 | 'post_content' => '', |
| 1050 | 'post_parent' => 0, |
| 1051 | 'post_status' => 'inherit' |
| 1052 | ), |
| 1053 | $new_filepath, |
| 1054 | 0 |
| 1055 | ); |
| 1056 | |
| 1057 | remove_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) ); |
| 1058 | |
| 1059 | // success? |
| 1060 | if ( $thumbnail_id ) { |
| 1061 | // make sure that this file is included |
| 1062 | require_once( ABSPATH . 'wp-admin/includes/image.php' ); |
| 1063 | |
| 1064 | // update database with generated metadata for the attachment |
| 1065 | wp_update_attachment_metadata( $thumbnail_id, wp_generate_attachment_metadata( $thumbnail_id, $new_filepath ) ); |
| 1066 | } |
| 1067 | } else |
| 1068 | $thumbnail_id = $thumbnail_id[0]; |
| 1069 | } |
| 1070 | |
| 1071 | return (int) $thumbnail_id; |
| 1072 | } |
| 1073 | |
| 1074 | /** |
| 1075 | * Change status of new attachment thumbnail replacement. |
| 1076 | * |
| 1077 | * @param array $data |
| 1078 | * @return array |
| 1079 | */ |
| 1080 | function set_attachment_post_status( $data ) { |
| 1081 | $data['post_status'] = 'pending'; |
| 1082 | |
| 1083 | return $data; |
| 1084 | } |
| 1085 | |
| 1086 | /** |
| 1087 | * Prepare featured content fields. |
| 1088 | * |
| 1089 | * @param array $fields |
| 1090 | * @return array |
| 1091 | */ |
| 1092 | public function prepare_featured_fields( $fields ) { |
| 1093 | foreach ( array( 'post_type', 'post_status', 'post_format', 'post_term', 'post_author', 'page_parent', 'page_template' ) as $option ) { |
| 1094 | $fields[$option]['options'] = $this->prepare_query_args( $option ); |
| 1095 | } |
| 1096 | |
| 1097 | return $fields; |
| 1098 | } |
| 1099 | |
| 1100 | /** |
| 1101 | * Prepare values option list. |
| 1102 | * |
| 1103 | * @param string $type |
| 1104 | * @return array |
| 1105 | */ |
| 1106 | public function prepare_query_args( $type = '' ) { |
| 1107 | $html = ''; |
| 1108 | |
| 1109 | switch( $type ) { |
| 1110 | case 'post_type': |
| 1111 | $data = $this->get_post_types(); |
| 1112 | break; |
| 1113 | |
| 1114 | case 'post_status': |
| 1115 | $data = $this->get_post_statuses(); |
| 1116 | break; |
| 1117 | |
| 1118 | case 'post_format': |
| 1119 | $data = $this->get_post_formats(); |
| 1120 | break; |
| 1121 | |
| 1122 | case 'post_term': |
| 1123 | $taxonomies = $this->get_taxonomies(); |
| 1124 | $new_terms = []; |
| 1125 | |
| 1126 | if ( ! empty( $taxonomies ) ) { |
| 1127 | foreach ( $taxonomies as $tax_id => $label ) { |
| 1128 | $terms = get_terms( |
| 1129 | array( |
| 1130 | 'taxonomy' => $tax_id, |
| 1131 | 'orderby' => 'name', |
| 1132 | 'order' => 'ASC', |
| 1133 | 'hide_empty' => false, |
| 1134 | 'fields' => 'id=>name' |
| 1135 | ) |
| 1136 | ); |
| 1137 | |
| 1138 | if ( ! empty( $terms ) ) |
| 1139 | $new_terms[$tax_id] = array( |
| 1140 | 'label' => $label, |
| 1141 | 'terms' => $terms |
| 1142 | ); |
| 1143 | } |
| 1144 | } |
| 1145 | |
| 1146 | $data = $new_terms; |
| 1147 | break; |
| 1148 | |
| 1149 | case 'post_author': |
| 1150 | $data = $this->get_users(); |
| 1151 | break; |
| 1152 | |
| 1153 | case 'page_parent': |
| 1154 | $parents = []; |
| 1155 | $hierarchical = get_post_types( |
| 1156 | array( |
| 1157 | 'public' => true, |
| 1158 | 'hierarchical' => true |
| 1159 | ), |
| 1160 | 'objects', |
| 1161 | 'and' |
| 1162 | ); |
| 1163 | |
| 1164 | if ( ! empty( $hierarchical ) ) { |
| 1165 | foreach ( $hierarchical as $post_type => $object ) { |
| 1166 | // get top level hierarchical posts |
| 1167 | $query = new WP_Query( |
| 1168 | array( |
| 1169 | 'post_type' => $post_type, |
| 1170 | 'post_status' => 'publish', |
| 1171 | 'nopaging' => true, |
| 1172 | 'posts_per_page' => -1, |
| 1173 | 'orderby' => 'title', |
| 1174 | 'order' => 'ASC', |
| 1175 | 'suppress_filters' => false, |
| 1176 | 'no_found_rows' => true, |
| 1177 | 'cache_results' => false, |
| 1178 | 'post_parent' => 0 |
| 1179 | ) |
| 1180 | ); |
| 1181 | |
| 1182 | if ( ! empty( $query->posts ) ) { |
| 1183 | foreach ( $query->posts as $post ) { |
| 1184 | $parents[$post->ID] = trim( $post->post_title ) === '' ? __( 'Untitled' ) : $post->post_title; |
| 1185 | } |
| 1186 | } |
| 1187 | } |
| 1188 | } |
| 1189 | |
| 1190 | $data = $parents; |
| 1191 | break; |
| 1192 | |
| 1193 | case 'page_template': |
| 1194 | $data = $this->get_page_templates(); |
| 1195 | break; |
| 1196 | |
| 1197 | default: |
| 1198 | $data = []; |
| 1199 | } |
| 1200 | |
| 1201 | return apply_filters( 'rl_galleries_prepare_query_args', $data, $type ); |
| 1202 | } |
| 1203 | |
| 1204 | /** |
| 1205 | * Get public post types. |
| 1206 | * |
| 1207 | * @param bool $simple Which data should be returned |
| 1208 | * @param bool $skip Which post types should be skipped |
| 1209 | * @return array |
| 1210 | */ |
| 1211 | public function get_post_types( $simple = false, $skip = [ 'attachment', 'rl_gallery' ] ) { |
| 1212 | $post_types = get_post_types( |
| 1213 | array( |
| 1214 | 'public' => true |
| 1215 | ), |
| 1216 | 'objects', |
| 1217 | 'and' |
| 1218 | ); |
| 1219 | |
| 1220 | $data = []; |
| 1221 | |
| 1222 | if ( ! empty( $post_types ) ) { |
| 1223 | foreach ( $post_types as $post_type => $cpt ) { |
| 1224 | // skip unwanted post types |
| 1225 | if ( in_array( $post_type, $skip, true ) ) |
| 1226 | continue; |
| 1227 | |
| 1228 | if ( $simple ) |
| 1229 | $data[] = $post_type; |
| 1230 | else |
| 1231 | $data[$post_type] = $cpt->labels->singular_name; |
| 1232 | } |
| 1233 | } |
| 1234 | |
| 1235 | if ( ! $simple ) |
| 1236 | asort( $data ); |
| 1237 | |
| 1238 | return $data; |
| 1239 | } |
| 1240 | |
| 1241 | /** |
| 1242 | * Get post statuses. |
| 1243 | * |
| 1244 | * @return array |
| 1245 | */ |
| 1246 | public function get_post_statuses() { |
| 1247 | $post_statuses = get_post_stati(); |
| 1248 | |
| 1249 | asort( $post_statuses ); |
| 1250 | |
| 1251 | // remove inherit post status |
| 1252 | if ( isset( $post_statuses['inherit'] ) ) |
| 1253 | unset( $post_statuses['inherit'] ); |
| 1254 | |
| 1255 | return $post_statuses; |
| 1256 | } |
| 1257 | |
| 1258 | /** |
| 1259 | * Get post formats. |
| 1260 | * |
| 1261 | * @return array |
| 1262 | */ |
| 1263 | public function get_post_formats() { |
| 1264 | $post_formats = array( |
| 1265 | 'aside' => __( 'Aside' ), |
| 1266 | 'audio' => __( 'Audio' ), |
| 1267 | 'chat' => __( 'Chat' ), |
| 1268 | 'gallery' => __( 'Gallery' ), |
| 1269 | 'link' => __( 'Link' ), |
| 1270 | 'photo' => __( 'Photo' ), |
| 1271 | 'quote' => __( 'Quote' ), |
| 1272 | 'standard' => __( 'Standard' ), |
| 1273 | 'status' => __( 'Status' ), |
| 1274 | 'video' => __( 'Video' ) |
| 1275 | ); |
| 1276 | |
| 1277 | asort( $post_formats ); |
| 1278 | |
| 1279 | return $post_formats; |
| 1280 | } |
| 1281 | |
| 1282 | /** |
| 1283 | * Get taxonomies. |
| 1284 | * |
| 1285 | * @return array |
| 1286 | */ |
| 1287 | public function get_taxonomies() { |
| 1288 | $taxonomies = get_taxonomies( |
| 1289 | array( |
| 1290 | 'public' => true |
| 1291 | ), |
| 1292 | 'objects', |
| 1293 | 'and' |
| 1294 | ); |
| 1295 | |
| 1296 | // remove post format |
| 1297 | if ( array_key_exists( 'post_format', $taxonomies ) ) |
| 1298 | unset( $taxonomies['post_format'] ); |
| 1299 | |
| 1300 | // get main instance |
| 1301 | $rl = Responsive_Lightbox(); |
| 1302 | |
| 1303 | // remove gallery categories |
| 1304 | if ( $rl->options['builder']['categories'] && array_key_exists( 'rl_category', $taxonomies ) ) |
| 1305 | unset( $taxonomies['rl_category'] ); |
| 1306 | |
| 1307 | // remove gallery tags |
| 1308 | if ( $rl->options['builder']['tags'] && array_key_exists( 'rl_tag', $taxonomies ) ) |
| 1309 | unset( $taxonomies['rl_tag'] ); |
| 1310 | |
| 1311 | if ( $rl->options['folders']['active'] ) { |
| 1312 | // remove active folders taxonomy from gallery source selector |
| 1313 | $active_taxonomy = $rl->folders->get_active_taxonomy(); |
| 1314 | unset( $taxonomies[$active_taxonomy] ); |
| 1315 | |
| 1316 | // remove media folders tags |
| 1317 | if ( $rl->options['folders']['media_tags'] ) |
| 1318 | unset( $taxonomies['rl_media_tag'] ); |
| 1319 | } |
| 1320 | |
| 1321 | $data = []; |
| 1322 | |
| 1323 | if ( ! empty( $taxonomies ) ) { |
| 1324 | foreach ( $taxonomies as $tax_id => $taxonomy ) { |
| 1325 | $data[$tax_id] = $taxonomy->labels->singular_name; |
| 1326 | } |
| 1327 | } |
| 1328 | |
| 1329 | // sort taxonomies |
| 1330 | asort( $data ); |
| 1331 | |
| 1332 | return $data; |
| 1333 | } |
| 1334 | |
| 1335 | /** |
| 1336 | * Get users. |
| 1337 | * |
| 1338 | * @return array |
| 1339 | */ |
| 1340 | public function get_users() { |
| 1341 | $users = get_users( |
| 1342 | array( |
| 1343 | 'fields' => array( 'ID', 'user_login' ) |
| 1344 | ) |
| 1345 | ); |
| 1346 | |
| 1347 | $data = []; |
| 1348 | |
| 1349 | if ( ! empty( $users ) ) { |
| 1350 | foreach ( $users as $user ) { |
| 1351 | $data[(int) $user->ID] = $user->user_login; |
| 1352 | } |
| 1353 | } |
| 1354 | |
| 1355 | asort( $data ); |
| 1356 | |
| 1357 | return $data; |
| 1358 | } |
| 1359 | |
| 1360 | /** |
| 1361 | * Get page templates. |
| 1362 | * |
| 1363 | * @return array |
| 1364 | */ |
| 1365 | public function get_page_templates() { |
| 1366 | $data = []; |
| 1367 | $page_templates = wp_get_theme()->get_page_templates(); |
| 1368 | |
| 1369 | if ( ! empty( $page_templates ) ) |
| 1370 | asort( $page_templates ); |
| 1371 | |
| 1372 | $data = array_merge( array( 'default' => apply_filters( 'default_page_template_title', __( 'Default Template' ) ) ), $page_templates ); |
| 1373 | |
| 1374 | return $data; |
| 1375 | } |
| 1376 | |
| 1377 | /** |
| 1378 | * Fix possible misplaced or hidden metaboxes do to old 'after_title' metabox and possibility to move internal metaboxes. |
| 1379 | * |
| 1380 | * @return void |
| 1381 | */ |
| 1382 | public function clear_metaboxes( $screen ) { |
| 1383 | global $pagenow; |
| 1384 | |
| 1385 | if ( ! ( ( $pagenow === 'post.php' || $pagenow === 'post-new.php' ) && ! empty( $screen->post_type ) && $screen->post_type === 'rl_gallery' && empty( $_POST['rl_gallery'] ) ) ) |
| 1386 | return; |
| 1387 | |
| 1388 | // get user id |
| 1389 | $user_id = get_current_user_id(); |
| 1390 | |
| 1391 | // get rl metaboxes |
| 1392 | $order = get_user_meta( $user_id, 'meta-box-order_rl_gallery', true ); |
| 1393 | |
| 1394 | // any metabox order? fix possible misplaced metaboxes |
| 1395 | if ( is_array( $order ) && ! empty( $order ) ) { |
| 1396 | // save metaboxes |
| 1397 | $_order = $order; |
| 1398 | |
| 1399 | // default rl metaboxes |
| 1400 | $rl_boxes = [ 'responsive-gallery-images', 'responsive-gallery-config', 'responsive-gallery-design', 'responsive-gallery-paging', 'responsive-gallery-lightbox', 'responsive-gallery-misc' ]; |
| 1401 | |
| 1402 | foreach ( $_order as $group => $metaboxes ) { |
| 1403 | if ( $group === 'after_title' ) { |
| 1404 | // remove deprecated after_title metabox |
| 1405 | unset( $order['after_title'] ); |
| 1406 | } elseif ( $metaboxes !== '' ) { |
| 1407 | $boxes = explode( ',', $metaboxes ); |
| 1408 | $new_boxes = []; |
| 1409 | |
| 1410 | foreach ( $boxes as $box ) { |
| 1411 | if ( ! in_array( $box, $rl_boxes, true ) ) |
| 1412 | $new_boxes[] = $box; |
| 1413 | } |
| 1414 | |
| 1415 | if ( ! empty( $new_boxes ) ) |
| 1416 | $order[$group] = implode( ',', $new_boxes ); |
| 1417 | else |
| 1418 | $order[$group] = ''; |
| 1419 | } |
| 1420 | } |
| 1421 | |
| 1422 | // remove default metaboxes storage |
| 1423 | if ( array_key_exists( 'responsive_lightbox_metaboxes', $order ) ) |
| 1424 | unset( $order['responsive_lightbox_metaboxes'] ); |
| 1425 | |
| 1426 | // update usermeta to prevent issues with rl metaboxes |
| 1427 | if ( $order !== $_order ) |
| 1428 | update_user_meta( $user_id, 'meta-box-order_rl_gallery', $order ); |
| 1429 | } |
| 1430 | } |
| 1431 | |
| 1432 | /** |
| 1433 | * Save gallery metadata. |
| 1434 | * |
| 1435 | * @param int $post_id |
| 1436 | * @param object $post |
| 1437 | * @param bool $update Whether existing post is being updated or not |
| 1438 | * @return void |
| 1439 | */ |
| 1440 | public function save_post( $post_id, $post, $update ) { |
| 1441 | // check action |
| 1442 | $action = isset( $_GET['action'] ) ? sanitize_key( $_GET['action'] ) : ''; |
| 1443 | |
| 1444 | if ( wp_is_post_revision( $post_id ) || ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || ! $update || in_array( $post->post_status, array( 'trash', 'auto-draft' ), true ) || ( $action === 'untrash' ) || empty( $_POST['rl_gallery'] ) ) |
| 1445 | return; |
| 1446 | |
| 1447 | // save gallery |
| 1448 | $this->save_gallery( wp_unslash( $_POST ), $post_id ); |
| 1449 | } |
| 1450 | |
| 1451 | /** |
| 1452 | * Save gallery preview metadata. |
| 1453 | * |
| 1454 | * @param array $post_data Gallery data |
| 1455 | * @param int $post_id |
| 1456 | * @param bool $preview Whether is it preview |
| 1457 | * @return void |
| 1458 | */ |
| 1459 | public function save_gallery( $post_data, $post_id, $preview = false ) { |
| 1460 | // get gallery data |
| 1461 | $data = $post_data['rl_gallery']; |
| 1462 | |
| 1463 | // prepare sanitized data |
| 1464 | $safedata = []; |
| 1465 | |
| 1466 | // get main instance |
| 1467 | $rl = Responsive_Lightbox(); |
| 1468 | |
| 1469 | // sanitize all fields - iterate from $this->tabs (authoritative registry) to prevent silent skipping |
| 1470 | foreach ( array_keys( $this->tabs ) as $tab_id ) { |
| 1471 | // Retrieve menu_items from $this->fields for this tab (may be empty for adapter-only tabs) |
| 1472 | $menu_items = isset( $this->fields[$tab_id] ) ? $this->fields[$tab_id] : []; |
| 1473 | |
| 1474 | // Determine menu item for this tab |
| 1475 | $tab_menu_items = isset( $this->tabs[$tab_id]['menu_items'] ) && is_array( $this->tabs[$tab_id]['menu_items'] ) ? $this->tabs[$tab_id]['menu_items'] : []; |
| 1476 | $posted_menu_item = isset( $data[$tab_id], $data[$tab_id]['menu_item'] ) ? sanitize_key( $data[$tab_id]['menu_item'] ) : ''; |
| 1477 | |
| 1478 | // Resolve menu item safely for tabs with and without menu navigation. |
| 1479 | if ( $posted_menu_item !== '' ) { |
| 1480 | if ( ! empty( $tab_menu_items ) && array_key_exists( $posted_menu_item, $tab_menu_items ) ) |
| 1481 | $menu_item = $posted_menu_item; |
| 1482 | elseif ( array_key_exists( $posted_menu_item, $menu_items ) ) |
| 1483 | $menu_item = $posted_menu_item; |
| 1484 | else { |
| 1485 | if ( empty( $menu_items ) ) |
| 1486 | continue; |
| 1487 | $menu_item = array_key_exists( 'options', $menu_items ) ? 'options' : key( $menu_items ); |
| 1488 | } |
| 1489 | } else { |
| 1490 | if ( empty( $menu_items ) ) |
| 1491 | continue; |
| 1492 | $menu_item = array_key_exists( 'options', $menu_items ) ? 'options' : key( $menu_items ); |
| 1493 | } |
| 1494 | |
| 1495 | // Resolve fields from adapter (single source for managed tabs) |
| 1496 | $items = []; |
| 1497 | if ( isset( $rl->gallery_api ) && $rl->gallery_api->is_managed_tab( $tab_id ) ) { |
| 1498 | $items = $rl->gallery_api->get_tab_fields_for_save( $tab_id, $menu_item ); |
| 1499 | } |
| 1500 | |
| 1501 | // Defensive fallback for images tab only (not fully adapter-owned for field definitions) |
| 1502 | if ( $tab_id === 'images' && empty( $items ) && isset( $menu_items[$menu_item] ) && is_array( $menu_items[$menu_item] ) ) { |
| 1503 | $items = $menu_items[$menu_item]; |
| 1504 | } |
| 1505 | |
| 1506 | if ( empty( $items ) || ! is_array( $items ) ) |
| 1507 | continue; |
| 1508 | |
| 1509 | // IMAGES TAB: Minimal defensive guards (sanitizer handles data structure) |
| 1510 | if ( $tab_id === 'images' ) { |
| 1511 | // Ensure folder field has valid structure for folders menu item |
| 1512 | if ( $menu_item === 'folders' && isset( $data[$tab_id][$menu_item]['folder'] ) ) { |
| 1513 | $folder = $data[$tab_id][$menu_item]['folder']; |
| 1514 | if ( ! is_array( $folder ) ) { |
| 1515 | $data[$tab_id][$menu_item]['folder'] = [ 'id' => 0, 'children' => false ]; |
| 1516 | } else { |
| 1517 | if ( ! isset( $folder['id'] ) ) { |
| 1518 | $data[$tab_id][$menu_item]['folder']['id'] = 0; |
| 1519 | } |
| 1520 | if ( ! isset( $folder['children'] ) ) { |
| 1521 | $data[$tab_id][$menu_item]['folder']['children'] = false; |
| 1522 | } |
| 1523 | } |
| 1524 | } |
| 1525 | // Note: attachments['ids'] is CSV string, sanitizer handles it at line 1997 |
| 1526 | } |
| 1527 | |
| 1528 | // sanitize fields |
| 1529 | $safedata = $this->sanitize_fields( $items, $data, $tab_id, $menu_item ); |
| 1530 | |
| 1531 | // tab validation hook (adapter-managed tabs) |
| 1532 | if ( isset( $rl->gallery_api ) && $rl->gallery_api->is_managed_tab( $tab_id ) ) { |
| 1533 | if ( isset( $safedata[$tab_id][$menu_item] ) && is_array( $safedata[$tab_id][$menu_item] ) ) { |
| 1534 | $safedata[$tab_id][$menu_item] = $rl->gallery_api->validate_tab_data( |
| 1535 | $tab_id, |
| 1536 | $menu_item, |
| 1537 | $safedata[$tab_id][$menu_item], |
| 1538 | $post_id |
| 1539 | ); |
| 1540 | } |
| 1541 | } |
| 1542 | |
| 1543 | // add menu item |
| 1544 | $safedata[$tab_id]['menu_item'] = $menu_item; |
| 1545 | |
| 1546 | // preview? |
| 1547 | if ( $preview ) |
| 1548 | update_metadata( 'post', $post_id, '_rl_' . $tab_id, $safedata[$tab_id] ); |
| 1549 | else |
| 1550 | update_post_meta( $post_id, '_rl_' . $tab_id, $safedata[$tab_id] ); |
| 1551 | } |
| 1552 | |
| 1553 | $has_featured_image_payload = isset( $post_data['rl_gallery_featured_image'] ); |
| 1554 | |
| 1555 | // Preserve existing featured-image metadata for partial updates (e.g. Quick Edit). |
| 1556 | if ( ! $has_featured_image_payload ) { |
| 1557 | $featured_image_type = get_post_meta( $post_id, '_rl_featured_image_type', true ); |
| 1558 | $featured_image = get_post_meta( $post_id, '_rl_featured_image', true ); |
| 1559 | $thumbnail_id = (int) get_post_meta( $post_id, '_thumbnail_id', true ); |
| 1560 | |
| 1561 | if ( ! in_array( $featured_image_type, [ 'id', 'url', 'image' ], true ) ) |
| 1562 | $featured_image_type = 'image'; |
| 1563 | } else { |
| 1564 | $featured_image_type = ! empty( $post_data['rl_gallery_featured_image'] ) && in_array( $post_data['rl_gallery_featured_image'], array( 'id', 'url', 'image' ), true ) ? $post_data['rl_gallery_featured_image'] : 'id'; |
| 1565 | |
| 1566 | switch ( $featured_image_type ) { |
| 1567 | // custom url |
| 1568 | case 'url': |
| 1569 | $thumbnail_id = $this->maybe_generate_thumbnail(); |
| 1570 | $frontend = function_exists( 'Responsive_Lightbox' ) ? Responsive_Lightbox()->frontend : null; |
| 1571 | $custom_url = isset( $post_data['_rl_thumbnail_url'] ) ? $post_data['_rl_thumbnail_url'] : ''; |
| 1572 | if ( $frontend && method_exists( $frontend, 'sanitize_remote_image_url' ) ) |
| 1573 | $featured_image = $frontend->sanitize_remote_image_url( $custom_url ); |
| 1574 | else |
| 1575 | $featured_image = ''; |
| 1576 | |
| 1577 | if ( $featured_image === '' ) |
| 1578 | $featured_image_type = 'image'; |
| 1579 | break; |
| 1580 | |
| 1581 | // first image |
| 1582 | case 'image': |
| 1583 | $thumbnail_id = $this->maybe_generate_thumbnail(); |
| 1584 | $featured_image = ''; |
| 1585 | break; |
| 1586 | |
| 1587 | // attachment id |
| 1588 | case 'id': |
| 1589 | default: |
| 1590 | $featured_image = $thumbnail_id = isset( $post_data['_thumbnail_id'] ) ? (int) $post_data['_thumbnail_id'] : 0; |
| 1591 | } |
| 1592 | } |
| 1593 | |
| 1594 | // preview? |
| 1595 | if ( $preview ) { |
| 1596 | update_metadata( 'post', $post_id, '_rl_featured_image_type', $featured_image_type ); |
| 1597 | update_metadata( 'post', $post_id, '_rl_featured_image', $featured_image ); |
| 1598 | update_metadata( 'post', $post_id, '_thumbnail_id', $thumbnail_id ); |
| 1599 | } else { |
| 1600 | // update featured image |
| 1601 | update_post_meta( $post_id, '_rl_featured_image_type', $featured_image_type ); |
| 1602 | update_post_meta( $post_id, '_rl_featured_image', $featured_image ); |
| 1603 | update_post_meta( $post_id, '_thumbnail_id', $thumbnail_id ); |
| 1604 | |
| 1605 | // save number of images |
| 1606 | update_post_meta( $post_id, '_rl_images_count', $this->get_gallery_images_number( $post_id ) ); |
| 1607 | } |
| 1608 | |
| 1609 | // update post excerpt |
| 1610 | if ( isset( $safedata['misc']['options']['gallery_description'] ) ) { |
| 1611 | remove_action( 'save_post_rl_gallery', [ $this, 'save_post' ], 10, 3 ); |
| 1612 | |
| 1613 | $postdata = [ |
| 1614 | 'ID' => $post_id, |
| 1615 | 'post_excerpt' => sanitize_textarea_field( $safedata['misc']['options']['gallery_description'] ) |
| 1616 | ]; |
| 1617 | |
| 1618 | wp_update_post( $postdata ); |
| 1619 | |
| 1620 | add_action( 'save_post_rl_gallery', [ $this, 'save_post' ], 10, 3 ); |
| 1621 | } |
| 1622 | } |
| 1623 | |
| 1624 | /** |
| 1625 | * Display shortcode metabox. |
| 1626 | * |
| 1627 | * @param object $post |
| 1628 | * @return void |
| 1629 | */ |
| 1630 | public function shortcode_metabox( $post ) { |
| 1631 | echo ' |
| 1632 | <p>' . esc_html__( 'You can place this gallery anywhere into your posts, pages, custom post types or widgets by using the shortcode below', 'responsive-lightbox' ) . ':</p> |
| 1633 | <code class="rl-shortcode" data-number="0">[rl_gallery id="' . (int) $post->ID . '"]</code> |
| 1634 | <p>' . esc_html__( 'You can also place this gallery into your template files by using the template tag below', 'responsive-lightbox' ) . ':</p> |
| 1635 | <code class="rl-shortcode" data-number="1">if ( function_exists( \'rl_gallery\' ) ) { rl_gallery( \'' . (int) $post->ID . '\' ); }</code>'; |
| 1636 | } |
| 1637 | |
| 1638 | /** |
| 1639 | * Add new gallery listing columns. |
| 1640 | * |
| 1641 | * @param array $columns |
| 1642 | * @return array |
| 1643 | */ |
| 1644 | public function gallery_columns( $columns ) { |
| 1645 | // find title position |
| 1646 | $offset = array_search( 'title', array_keys( $columns ) ); |
| 1647 | |
| 1648 | // put image column before title |
| 1649 | $columns = array_merge( |
| 1650 | array_slice( $columns, 0, $offset ), |
| 1651 | array( |
| 1652 | 'image' => esc_html__( 'Gallery', 'responsive-lightbox' ) |
| 1653 | ), |
| 1654 | array_slice( $columns, $offset ) |
| 1655 | ); |
| 1656 | |
| 1657 | // put new columns after title |
| 1658 | $columns = array_merge( |
| 1659 | array_slice( $columns, 0, $offset + 2 ), |
| 1660 | array( |
| 1661 | 'shortcode' => esc_html__( 'Shortcode', 'responsive-lightbox' ), |
| 1662 | 'type' => esc_html__( 'Type', 'responsive-lightbox' ), |
| 1663 | 'source' => esc_html__( 'Source', 'responsive-lightbox' ) |
| 1664 | ), |
| 1665 | array_slice( $columns, $offset + 2 ) |
| 1666 | ); |
| 1667 | |
| 1668 | return $columns; |
| 1669 | } |
| 1670 | |
| 1671 | /** |
| 1672 | * Add new gallery listing columns content. |
| 1673 | * |
| 1674 | * @global string $pagenow |
| 1675 | * |
| 1676 | * @param string $column_name |
| 1677 | * @param int $post_id |
| 1678 | * @return void |
| 1679 | */ |
| 1680 | public function gallery_columns_content( $column_name, $post_id ) { |
| 1681 | switch ( $column_name ) { |
| 1682 | case 'image': |
| 1683 | // get image data, based on gallery source type |
| 1684 | $image = $this->get_featured_image( $post_id, 'thumbnail' ); |
| 1685 | $images_count = (int) get_post_meta( $post_id, '_rl_images_count', true ); |
| 1686 | |
| 1687 | // display count |
| 1688 | if ( ! empty( $image ) ) |
| 1689 | echo '<span class="media-icon image-icon">' . wp_kses_post( $image ) . '</span><span>' . esc_html( sprintf( _n( '%s element', '%s elements', $images_count, 'responsive-lightbox' ), $images_count ) ) . '</span>'; |
| 1690 | else |
| 1691 | echo '<span class="media-icon image-icon">' . wp_get_attachment_image( 0, array( 60, 60 ), true, array( 'alt' => '' ) ) . '</span>'; |
| 1692 | break; |
| 1693 | |
| 1694 | case 'shortcode': |
| 1695 | echo '<code>[rl_gallery id="' . (int) $post_id . '"]</code>'; |
| 1696 | break; |
| 1697 | |
| 1698 | case 'type': |
| 1699 | $config = get_post_meta( $post_id, '_rl_config', true ); |
| 1700 | |
| 1701 | if ( is_array( $config ) && ! empty( $config['menu_item'] ) && array_key_exists( $config['menu_item'], $this->tabs['config']['menu_items'] ) ) { |
| 1702 | echo esc_html( $this->tabs['config']['menu_items'][$config['menu_item']] ); |
| 1703 | |
| 1704 | if ( $config['menu_item'] === 'default' ) |
| 1705 | echo esc_html( ' (' . $this->tabs['config']['menu_items'][Responsive_Lightbox()->options['settings']['builder_gallery']] . ')' ); |
| 1706 | } else |
| 1707 | echo '-'; |
| 1708 | break; |
| 1709 | |
| 1710 | case 'source': |
| 1711 | $images = get_post_meta( $post_id, '_rl_images', true ); |
| 1712 | |
| 1713 | if ( is_array( $images ) && ! empty( $images['menu_item'] ) && array_key_exists( $images['menu_item'], $this->tabs['images']['menu_items'] ) ) |
| 1714 | echo esc_html( $this->tabs['images']['menu_items'][$images['menu_item']] ); |
| 1715 | else |
| 1716 | echo '-'; |
| 1717 | break; |
| 1718 | } |
| 1719 | } |
| 1720 | |
| 1721 | /** |
| 1722 | * Get size information for all currently-registered image sizes. |
| 1723 | * |
| 1724 | * @global array $_wp_additional_image_sizes |
| 1725 | * |
| 1726 | * @return array |
| 1727 | */ |
| 1728 | public function get_image_sizes() { |
| 1729 | global $_wp_additional_image_sizes; |
| 1730 | |
| 1731 | $sizes = []; |
| 1732 | |
| 1733 | foreach ( get_intermediate_image_sizes() as $_size ) { |
| 1734 | if ( in_array( $_size, [ 'thumbnail', 'medium', 'medium_large', 'large' ] ) ) { |
| 1735 | $sizes[$_size]['width'] = get_option( "{$_size}_size_w" ); |
| 1736 | $sizes[$_size]['height'] = get_option( "{$_size}_size_h" ); |
| 1737 | $sizes[$_size]['crop'] = (bool) get_option( "{$_size}_crop" ); |
| 1738 | } elseif ( isset( $_wp_additional_image_sizes[$_size] ) ) { |
| 1739 | $sizes[$_size] = [ |
| 1740 | 'width' => $_wp_additional_image_sizes[$_size]['width'], |
| 1741 | 'height' => $_wp_additional_image_sizes[$_size]['height'], |
| 1742 | 'crop' => $_wp_additional_image_sizes[$_size]['crop'], |
| 1743 | ]; |
| 1744 | } |
| 1745 | } |
| 1746 | |
| 1747 | return $sizes; |
| 1748 | } |
| 1749 | |
| 1750 | /** |
| 1751 | * Get size information for a specific image size. |
| 1752 | * |
| 1753 | * @param string $size The image size for which to retrieve data. |
| 1754 | * @return false|array |
| 1755 | */ |
| 1756 | public function get_image_size( $size ) { |
| 1757 | if ( isset( $this->sizes[$size] ) ) |
| 1758 | return $this->sizes[$size]; |
| 1759 | else |
| 1760 | return false; |
| 1761 | } |
| 1762 | |
| 1763 | /** |
| 1764 | * Filter the admin post thumbnail HTML markup. |
| 1765 | * |
| 1766 | * @param string $content |
| 1767 | * @param int $post_id |
| 1768 | * @param int $thumbnail_id |
| 1769 | * @return string |
| 1770 | */ |
| 1771 | public function admin_post_thumbnail_html( $content, $post_id, $thumbnail_id ) { |
| 1772 | if ( get_post_type( $post_id ) === 'rl_gallery' ) { |
| 1773 | $value = get_post_meta( $post_id, '_rl_featured_image', true ); |
| 1774 | $frontend = function_exists( 'Responsive_Lightbox' ) ? Responsive_Lightbox()->frontend : null; |
| 1775 | if ( $frontend && method_exists( $frontend, 'sanitize_remote_image_url' ) ) |
| 1776 | $value = $frontend->sanitize_remote_image_url( $value ); |
| 1777 | $type = get_post_meta( $post_id, '_rl_featured_image_type', true ); |
| 1778 | $type = ! empty( $type ) && in_array( $type, array( 'image', 'id', 'url' ) ) ? $type : 'image'; |
| 1779 | |
| 1780 | // force media library image |
| 1781 | if ( wp_doing_ajax() ) |
| 1782 | $type = 'id'; |
| 1783 | // post featured image is post thumbnail replacement? |
| 1784 | elseif ( $this->maybe_generate_thumbnail() === (int) $thumbnail_id ) { |
| 1785 | remove_filter( 'admin_post_thumbnail_html', array( $this, 'admin_post_thumbnail_html' ), 10 ); |
| 1786 | |
| 1787 | $content = _wp_post_thumbnail_html( 0, $post_id ); |
| 1788 | } |
| 1789 | |
| 1790 | $content = ' |
| 1791 | <div class="rl-gallery-featured-image-options"> |
| 1792 | <p class="howto">' . esc_html__( 'Select gallery featured image source:', 'responsive-lightbox' ) . '</p> |
| 1793 | <label for="rl-gallery-featured-image"><input id="rl-gallery-featured-image" type="radio" name="rl_gallery_featured_image" value="image" ' . checked( $type, 'image', false ) . ' />' . esc_html__( 'First gallery image', 'responsive-lightbox' ) . '</label><br /> |
| 1794 | <label for="rl-gallery-featured-id"><input id="rl-gallery-featured-id" type="radio" name="rl_gallery_featured_image" value="id" ' . checked( $type, 'id', false ) . ' />' . esc_html__( 'Media Library', 'responsive-lightbox' ) . '</label><br /> |
| 1795 | <label for="rl-gallery-featured-url"><input id="rl-gallery-featured-url" type="radio" name="rl_gallery_featured_image" value="url" ' . checked( $type, 'url', false ) . ' />' . esc_html__( 'Custom URL', 'responsive-lightbox' ) . '</label> |
| 1796 | </div> |
| 1797 | <div class="rl-gallery-featured-image-select"> |
| 1798 | <div class="rl-gallery-featured-image-select-id"' . ( $type === 'id' ? '' : ' style="display: none;"' ) . '>' . $content . '</div> |
| 1799 | <div class="rl-gallery-featured-image-select-url"' . ( $type === 'url' ? '' : ' style="display: none;"' ) . '> |
| 1800 | <p><input id="_rl_thumbnail_url" class="large-text" name="_rl_thumbnail_url" value="' . ( $type === 'url' ? esc_url( $value ) : '' ) . '" type="text" /></p> |
| 1801 | <p class="howto">' . esc_html__( 'Custom featured image URL', 'responsive-lightbox' ) . '</p> |
| 1802 | </div> |
| 1803 | <div class="rl-gallery-featured-image-select-image"' . ( $type === 'image' ? '' : ' style="display: none;"' ) . '><p class="howto">' . esc_html__( 'Dynamically generated first gallery image', 'responsive-lightbox' ) . '</p></div> |
| 1804 | </div> |
| 1805 | '; |
| 1806 | } |
| 1807 | |
| 1808 | return $content; |
| 1809 | } |
| 1810 | |
| 1811 | /** |
| 1812 | * Modify the resulting HTML so that the feature image is set as a background property. |
| 1813 | * |
| 1814 | * @param string $html The HTML image tag. |
| 1815 | * @param int $post_id The post whose featured image is to be printed. |
| 1816 | * @param int $post_thumbnail_id The post thumbnail ID. |
| 1817 | * @param array|string $size The size of the featured image. |
| 1818 | * @param array $attr Additional attributes. |
| 1819 | * @return string |
| 1820 | */ |
| 1821 | public function post_thumbnail_html( $html, $post_id = 0, $post_thumbnail_id = 0, $size = false, $attr = [] ) { |
| 1822 | if ( get_post_type( $post_id ) === 'rl_gallery' ) { |
| 1823 | // get featured image type |
| 1824 | $image_type = get_post_meta( $post_id, '_rl_featured_image_type', true ); |
| 1825 | |
| 1826 | // break if featured image type is media library |
| 1827 | if ( ! $image_type || $image_type == 'id' ) |
| 1828 | return $html; |
| 1829 | |
| 1830 | // get image source |
| 1831 | $image_src = $this->get_gallery_image_src( $this->get_featured_image_src( $post_id ) ); |
| 1832 | |
| 1833 | // no image? |
| 1834 | if ( empty( $image_src ) ) |
| 1835 | return $html; |
| 1836 | |
| 1837 | // add featured image as background in style tag |
| 1838 | $style = 'style="background:url( ' . esc_url( $image_src['url'] ) . ' ) no-repeat center center;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size: cover;"'; |
| 1839 | |
| 1840 | $html = str_replace( 'src=', $style . ' src=', $html ); |
| 1841 | |
| 1842 | // fix the alt tag (if possible) |
| 1843 | $alt = $image_src['alt']; |
| 1844 | |
| 1845 | if ( isset( $attr['alt'] ) ) |
| 1846 | $alt = $attr['alt']; |
| 1847 | |
| 1848 | if ( $alt ) { |
| 1849 | $html = str_replace( '/(alt=\'[^\']+\'\|alt="[^"]+")/', '', $html ); |
| 1850 | $html = str_replace( 'src=', ' alt="' . esc_attr( $alt ) . '" src=', $html ); |
| 1851 | } |
| 1852 | } |
| 1853 | |
| 1854 | return $html; |
| 1855 | } |
| 1856 | } |
| 1857 | |
| 1858 |