<?php
/**
 * Common admin class.
 *
 * @since 1.0.0
 *
 * @package Envira_Gallery
 * @author  Envira Gallery Team
 */

// Exit if accessed directly.

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use Envira\Admin\Envira_Permissions;

/**
 * Common Helper Class
 *
 * @since 1.0.0
 */
class Envira_Gallery_Common_Admin {

	/**
	 * Holds the class object.
	 *
	 * @since 1.0.0
	 *
	 * @var object
	 */
	public static $instance;

	/**
	 * Path to the file.
	 *
	 * @since 1.0.0
	 *
	 * @var string
	 */
	public $file = __FILE__;

	/**
	 * Holds the base class object.
	 *
	 * @since 1.0.0
	 *
	 * @var object
	 */
	public $base;

	/**
	 * Holds the metabox class object.
	 *
	 * @since 1.3.1
	 *
	 * @var object
	 */
	public $metabox;

	/**
	 * Primary class constructor.
	 *
	 * @since 1.0.0
	 */
	public function __construct() {

		// Load the base class object.
		$this->base = Envira_Gallery_Lite::get_instance();

		add_action( 'admin_init', [ $this, 'add_capabilities' ] );

		// Handle any necessary DB upgrades.
		add_action( 'admin_init', [ $this, 'db_upgrade' ] );

		// Add new section in WordPress media settings page.
		add_action( 'admin_init', [ $this, 'envira_gallery_media_settings_add_new_section' ] );

		// Load admin assets.
		add_action( 'admin_enqueue_scripts', [ $this, 'admin_styles' ], 10, 1 );
		add_action( 'admin_enqueue_scripts', [ $this, 'admin_scripts' ], 10, 1 );

		// Delete any gallery association on attachment deletion. Also delete any extra cropped images.
		add_action( 'delete_attachment', [ $this, 'delete_gallery_association' ] );
		add_action( 'delete_attachment', [ $this, 'delete_cropped_image' ] );

		// Ensure gallery display is correct when trashing/untrashing galleries.
		add_action( 'wp_trash_post', [ $this, 'trash_gallery' ] );
		add_action( 'untrash_post', [ $this, 'untrash_gallery' ] );

		// Delete attachments, if setting enabled, when a gallery is permanently deleted.
		add_action( 'before_delete_post', [ $this, 'delete_gallery' ] );

		add_filter( 'admin_footer_text', [ $this, 'admin_footer' ], 1, 2 );
		add_action( 'in_admin_footer', [ $this, 'footer_template' ] );
		add_action( 'admin_footer', [ $this, 'notifications_template' ] );
		add_action( 'admin_menu', [ $this, 'add_upgrade_menu_item' ], 99 );
		add_action( 'admin_menu', [ $this, 'add_cdn_menu_item' ], 11 );
		add_action( 'admin_head', [ $this, 'admin_inline_styles' ] );
		add_action( 'admin_footer', [ $this, 'admin_sidebar_target' ] );
	}

	/**
	 * Set capabilities for Envira Gallery Lite.
	 *
	 * @return void
	 */
	public function add_capabilities() {

		( new \Envira\Admin\Envira_Capabilities() )->add_capabilities();
	}

	/**
	 * Add inline styles
	 *
	 * @since 1.8.7
	 *
	 * @return void
	 */
	public function admin_inline_styles() {
		echo '<style>
			.envira-sidebar-upgrade-pro {
				background-color: #37993B;
			}
			.envira-sidebar-upgrade-pro a {
				color: #fff !important;
			}
			.cdn_new_badge {
				color:#f18200;
				vertical-align:super;
				font-size:9px;
				margin-left:3px;
			}
		</style>';
	}

	/**
	 * Sidebar Target Blank
	 *
	 * @since 1.8.7
	 *
	 * @return void
	 */
	public function admin_sidebar_target() {
		?>
		<script type="text/javascript">
		jQuery(document).ready(function($) {
			$('li.envira-sidebar-upgrade-pro a').attr('target','_blank');
			$('li.cdn-menu-item-target-blank a').attr('target','_blank');
		});
		</script>
		<?php
	}

	/**
	 * Add lite-specific upgrade to pro menu item.
	 *
	 * @return void
	 */
	public function add_upgrade_menu_item() {

		global $submenu;

		add_submenu_page(
			'edit.php?post_type=envira',
			esc_html__( 'Upgrade to Pro', 'envira-gallery-lite' ),
			esc_html__( 'Upgrade to Pro', 'envira-gallery-lite' ),
			apply_filters( 'envira_gallery_menu_cap', 'manage_options' ),
			esc_url( $this->get_upgrade_link( 'http://enviragallery.com/lite/', 'adminsidebar', 'unlockprosidebar' ) )
		);

		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		$upgrade_link_position = key(
			array_filter(
				$submenu['edit.php?post_type=envira'],
				static function ( $item ) {
					return strpos( $item[2], 'http://enviragallery.com/lite/' ) !== false;
				}
			)
		);

		// phpcs:disable WordPress.WP.GlobalVariablesOverride.Prohibited
		if ( isset( $submenu['edit.php?post_type=envira'][ $upgrade_link_position ][4] ) ) {
			$submenu['edit.php?post_type=envira'][ $upgrade_link_position ][4] .= ' envira-sidebar-upgrade-pro';
		} else {
			$submenu['edit.php?post_type=envira'][ $upgrade_link_position ][] = 'envira-sidebar-upgrade-pro';
		}
		// phpcs:enable WordPress.WP.GlobalVariablesOverride.Prohibited
	}

	/**
	 * Add CDN menu item.
	 *
	 * @return void
	 */
	public function add_cdn_menu_item() {
		global $submenu;
		$utm = '?utm_source=envira-gallery-lite&utm_medium=lite-plugin&utm_campaign=admin-menu&utm_content=' . ENVIRA_LITE_VERSION;
		// Only add if the submenu exists.
		if ( isset( $submenu['edit.php?post_type=envira'] ) ) {
			$submenu['edit.php?post_type=envira'][] = [
				// Use HTML in the menu title, but be aware some WP versions may not render it.
				'Envira CDN <span class="cdn_new_badge">NEW</span>',
				'manage_options',
				'https://enviragallery.com/cdn/' . $utm,
				// Add a custom class to target with JS for opening in new tab
				'cdn-menu-item-target-blank',
			];
		}
	}

	/**
	 * Load footer template
	 *
	 * @since 1.8.7
	 */
	public function footer_template() {
		global $current_screen;
		if ( ! empty( $current_screen->id ) && strpos( $current_screen->id, 'envira' ) !== false ) {
			// If here, we're on an Envira Gallery, so output the footer.
			$this->base->load_admin_partial(
				'footer'
			);
		}
	}
	/**
	 * Helper Method to load footer template
	 *
	 * @since 1.8.7
	 */
	public function notifications_template() {
		global $current_screen;
		if ( ! empty( $current_screen->id ) && strpos( $current_screen->id, 'envira' ) !== false ) {
			// If here, we're on an Envira Gallery, so output the footer.
			$this->base->load_admin_partial(
				'notifications'
			);
		}
	}

	/**
	 * When user is on a Envira related admin page, display footer text
	 * that graciously asks them to rate us.
	 *
	 * @since
	 * @param string $text Footer text.
	 * @return string
	 */
	public function admin_footer( $text ) {
		global $current_screen;
		if ( ! empty( $current_screen->id ) && strpos( $current_screen->id, 'envira' ) !== false ) {
			$url = 'https://wordpress.org/support/plugin/envira-gallery-lite/reviews/?filter=5#new-post';
			/* translators: %s: url */
			$text = sprintf( __( 'Please rate <strong>Envira Gallery</strong> <a href="%1$s" target="_blank">&#9733;&#9733;&#9733;&#9733;&#9733;</a> on <a href="%2$s" target="_blank">WordPress.org</a> to help us spread the word. Thank you from the Envira Gallery team!', 'envira-gallery-lite' ), $url, $url );
		}
		return $text;
	}


	/**
	 * Handles any necessary DB upgrades for Envira.
	 *
	 * @since 1.0.0
	 */
	public function db_upgrade() {

		// Upgrade to allow captions (v1.1.6).
		$captions = get_option( 'envira_gallery_116' );
		if ( ! $captions ) {
			$galleries = Envira_Gallery_Lite::get_instance()->_get_galleries();
			if ( $galleries ) {
				foreach ( $galleries as $gallery ) {
					foreach ( (array) $gallery['gallery'] as $id => $item ) {
						$gallery['gallery'][ $id ]['caption'] = ! empty( $item['title'] ) ? $item['title'] : '';
						update_post_meta( $gallery['id'], '_eg_gallery_data', $gallery );
						Envira_Gallery_Common::get_instance()->flush_gallery_caches( $gallery['id'], $gallery['config']['slug'] );
					}
				}
			}

			update_option( 'envira_gallery_116', true );
		}

		// 1.2.1: Convert all non-Envira Post Type galleries into Envira CPT galleries.
		$cpt_galleries = get_option( 'envira_gallery_121' );
		if ( ! $cpt_galleries ) {
			// Get Post Types, excluding our own
			// We don't use post_status => 'any', as this doesn't include CPTs where exclude_from_search = true.
			$post_types         = get_post_types(
				[
					'public' => true,
				]
			);
			$excluded_posttypes = [ 'envira', 'envira_album', 'attachment' ];
			foreach ( $post_types as $key => $post_type ) {
				if ( in_array( $post_type, $excluded_posttypes, true ) ) {
					unset( $post_types[ $key ] );
				}
			}

			// Get all Posts that have _eg_gallery_data set.
			$in_post_galleries = new WP_Query(
				[
					'post_type'      => $post_types,
					'post_status'    => 'any',
					'posts_per_page' => -1,
					'meta_query'     => array( // @codingStandardsIgnoreLine - Possible slow query
						[
							'key'     => '_eg_gallery_data',
							'compare' => 'EXISTS',
						],
					),
				]
			);

			// Check if any Posts with galleries exist.
			if ( count( $in_post_galleries->posts ) > 0 ) {
				$migrated_galleries = 0;

				// Iterate through Posts with Galleries.
				foreach ( $in_post_galleries->posts as $post ) {
					// Check if this is an Envira or Envira Album CPT.
					// If so, skip it.
					if ( 'envira' === $post->post_type || 'envira_album' === $post->post_type ) {
						continue;
					}

					// Get metadata.
					$data = get_post_meta( $post->ID, '_eg_gallery_data', true );
					$in   = get_post_meta( $post->ID, '_eg_in_gallery', true );

					// Check if there is at least one image in the gallery.
					// Some Posts save Envira config data but don't have images - we don't want to migrate those,
					// as we would end up with blank Envira CPT galleries.
					if ( ! isset( $data['gallery'] ) || ! is_array( $data['gallery'] ) ) {
						continue;
					}

					// If here, we need to create a new Envira CPT.
					$cpt_args = [
						'post_title'  => ( ! empty( $data['config']['title'] ) ? $data['config']['title'] : $post->post_title ),
						'post_status' => $post->post_status,
						'post_type'   => 'envira',
						'post_author' => $post->post_author,
					];
					if ( ! empty( $data['config']['slug'] ) ) {
						$cpt_args['post_name'] = $data['config']['slug'];
					}
					$envira_gallery_id = wp_insert_post( $cpt_args );

					// Check gallery creation was successful.
					if ( is_wp_error( $envira_gallery_id ) ) {
						// @TODO how to handle errors?
						continue;
					}

					// Get Envira Gallery Post.
					$envira_post = get_post( $envira_gallery_id );

					// Map the title and slug of the post object to the custom fields if no value exists yet.
					$data['config']['title'] = trim( wp_strip_all_tags( $envira_post->post_title ) );
					$data['config']['slug']  = sanitize_text_field( $envira_post->post_name );

					// Store post metadata.
					update_post_meta( $envira_gallery_id, '_eg_gallery_data', $data );
					update_post_meta( $envira_gallery_id, '_eg_in_gallery', $in );
					update_post_meta( $envira_gallery_id, '_eg_gallery_old', $post->ID );
					if ( ! empty( $data['config']['slug'] ) ) {
						update_post_meta( $envira_gallery_id, '_eg_gallery_old_slug', $data['config']['slug'] );
					}

					// Remove post metadata from the original Post.
					delete_post_meta( $post->ID, '_eg_gallery_data' );
					delete_post_meta( $post->ID, '_eg_in_gallery' );

					// Search for the envira shortcode in the Post content, and change its ID to the new Envira Gallery ID.
					if ( has_shortcode( $post->post_content, 'envira-gallery' ) ) {
						$pattern = get_shortcode_regex();
						if ( preg_match_all( '/' . $pattern . '/s', $post->post_content, $matches ) ) {
							foreach ( $matches[2] as $key => $shortcode ) {
								if ( 'envira-gallery' === $shortcode ) {
									// Found an envira-gallery shortcode.
									// Change the ID.
									$original_shortcode    = $matches[0][ $key ];
									$replacement_shortcode = str_replace( 'id="' . $post->ID . '"', 'id="' . $envira_gallery_id . '"', $original_shortcode );
									$post->post_content    = str_replace( $original_shortcode, $replacement_shortcode, $post->post_content );
									wp_update_post( $post );
								}
							}
						}
					}

					// Store a relationship between the gallery and this Post.
					update_post_meta( $post->ID, '_eg_gallery_id', $envira_gallery_id );

					// Increment the counter.
					++$migrated_galleries;
				}

				// Display a one time admin notice so the user knows their in-page galleries were migrated.
				if ( $migrated_galleries > 0 ) {
					add_action( 'admin_notices', [ $this, 'notice_galleries_migrated' ] );
				}
			}

			// Force the tags addon to convert any tags to the new CPT system for any galleries that have been converted to Envira post type.
			delete_option( 'envira_tags_taxonomy_migrated' );

			// Mark upgrade as complete.
			update_option( 'envira_gallery_121', true );
		}
	}
	/**
	 * Displays a notice on screen when a user upgrades from Lite to Pro or Lite to Lite 1.5.x,
	 * telling them that their in-page galleries have been migrated.
	 *
	 * @since 1.5.0
	 */
	public function notice_galleries_migrated() {

		?>
		<div class="notice updated">
			<p><strong><?php esc_html_e( 'Envira Gallery', 'envira-gallery-lite' ); ?>:&nbsp;</strong><?php esc_html_e( 'Your existing in-page Galleries can now be found by clicking on Envira Gallery in the WordPress Admin menu.', 'envira-gallery-lite' ); ?></p>
		</div>
		<?php
	}

	/**
	 * Loads styles for all Envira-based Administration Screens.
	 *
	 * @since 1.3.1
	 *
	 * @param string $hook Page Hook.
	 * @return void Return early if not on the proper screen.
	 */
	public function admin_styles( $hook ) {

		// Get current screen.
		$screen = get_current_screen();

		// Bail if we're not on the Envira Post Type screen.
		if ( 'envira' !== $screen->post_type ) {
			return;
		}

		// Load necessary admin styles.
		wp_register_style( $this->base->plugin_slug . '-admin-style', plugins_url( 'assets/css/admin.css', $this->base->file ), [], $this->base->version );
		wp_enqueue_style( $this->base->plugin_slug . '-admin-style' );

		if ( 'envira_page_envira-gallery-settings' === $hook && isset( $_GET['post_type'] ) && 'envira' === $_GET['post_type'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended

			wp_enqueue_style( 'envira-gallery-settings-style-css', plugins_url( 'assets/css/settings.css', $this->base->file ), false, $this->base->version );
			wp_enqueue_style( 'envira-choice-css', plugins_url( 'assets/css/choices.css', $this->base->file ), false, $this->base->version );

		}

		// Fire a hook to load in custom admin styles.
		do_action( 'envira_gallery_admin_styles' );
	}

	/**
	 * Loads scripts for all Envira-based Administration Screens.
	 *
	 * @since 1.3.5
	 *
	 * @param string $hook Page Hook.
	 * @return void Return early if not on the proper screen.
	 */
	public function admin_scripts( $hook ) {

		// Get current screen.
		$screen = get_current_screen();

		// Bail if we're not on the Envira Post Type screen.
		if ( 'envira' !== $screen->post_type ) {
			return;
		}

		wp_enqueue_script( 'clipboard' );

		wp_register_script( $this->base->plugin_slug . '-tabs-script', plugins_url( 'assets/js/min/tabs-min.js', $this->base->file ), [ 'jquery' ], $this->base->version, true );
		wp_enqueue_script( $this->base->plugin_slug . '-tabs-script' );

		// Load necessary admin scripts.
		wp_register_script( $this->base->plugin_slug . '-admin-script', plugins_url( 'assets/js/min/admin-min.js', $this->base->file ), [ 'jquery', 'clipboard' ], $this->base->version, false );

		if ( 'envira_page_envira-gallery-settings' === $hook ) {
			wp_register_script( $this->base->plugin_slug . '-permissions-check', plugins_url( 'assets/js/min/envira-permissions-min.js', $this->base->file ), [], $this->base->version, false );
			wp_register_script( $this->base->plugin_slug . '-permissions-modal-js', plugins_url( 'assets/js/lib/a11y-dialog.min.js', $this->base->file ), [], $this->base->version, false );

			$permissions = new Envira_Permissions();
			$permissions->envira_permissions_localize();
			wp_enqueue_script( $this->base->plugin_slug . '-choice-js', plugins_url( 'assets/js/lib/choices.min.js', $this->base->file ), [ 'jquery' ], $this->base->version, false );

			// For permisson modal.
			wp_enqueue_script( $this->base->plugin_slug . '-permissions-modal-js' );
			wp_enqueue_script( $this->base->plugin_slug . '-permissions-check' );

		}

		wp_enqueue_script( $this->base->plugin_slug . '-admin-script' );
		wp_localize_script(
			$this->base->plugin_slug . '-admin-script',
			'envira_gallery_admin',
			[
				'ajax'                       => admin_url( 'admin-ajax.php' ),
				'dismiss_notification_nonce' => wp_create_nonce( 'envira_dismiss_notification' ),
				'dismiss_notice_nonce'       => wp_create_nonce( 'envira-gallery-dismiss-notice' ),
				'dismiss_topbar_nonce'       => wp_create_nonce( 'envira-gallery-dismiss-topbar' ),
				'connect_nonce'              => wp_create_nonce( 'envira_gallery_connect' ),
				'oops'                       => esc_html__( 'Oops!', 'envira-gallery-lite' ),
				'ok'                         => esc_html__( 'OK', 'envira-gallery-lite' ),
				'almost_done'                => esc_html__( 'Almost Done', 'envira-gallery-lite' ),
				'server_error'               => esc_html__( 'Unfortunately there was a server connection error.', 'envira-gallery-lite' ),
				'plugin_activate_btn'        => esc_html__( 'Activate', 'envira-gallery-lite' ),
				'unlock_url'                 => esc_url( $this->get_upgrade_link( 'https://enviragallery.com/pricing', 'listgallery', 'unlock' ) ),
				'unlock_title'               => esc_html__( 'Unlock All Features', 'envira-gallery-lite' ),
				'unlock_text'                => esc_html__( 'Upgrade to Pro to get access to Albums, Protected Images,  Video Galleries, and more!', 'envira-gallery-lite' ),
				'unlock_btn'                 => esc_html__( 'Unlock Gallery Features ' ),
			]
		);

		// Load gallery convert script.
		wp_register_script( $this->base->plugin_slug . '-convert-gallery-script', plugins_url( 'assets/js/min/gallery-convert-min.js', $this->base->file ), [ 'jquery' ], $this->base->version, false );

		wp_enqueue_script( $this->base->plugin_slug . '-convert-gallery-script' );

		wp_localize_script(
			$this->base->plugin_slug . '-convert-gallery-script',
			'envira_gallery_convert',
			[
				'bulk_convert_rest_url'      => rest_url( 'envira-convert/v1/bulk-convert' ),
				'process_item_rest_url'      => rest_url( 'envira-convert/v1/process-gallery' ),
				'gallery_convert_rest_nonce' => wp_create_nonce( 'wp_rest' ),
				'bulk_confirmation_alert'    => __( 'Are you sure you want to convert? This action cannot be reversed.', 'envira-gallery-lite' ),
				'bulk_conversion_started'    => __( 'Gallery conversion in progress... Please do not close this window or refresh the page until the process is complete.', 'envira-gallery-lite' ),
				'found_posts_text'           => __( 'posts found containing WordPress galleries.', 'envira-gallery-lite' ),
				'conversion_completed'       => __( 'Gallery conversion completed.', 'envira-gallery-lite' ),
				'failed_conversion_logs'     => __( 'Failed Conversion Logs:', 'envira-gallery-lite' ),
				'post_id_text'               => __( 'Post ID', 'envira-gallery-lite' ),
				'edit_post_text'             => __( 'Edit Post', 'envira-gallery-lite' ),
			]
		);

		// Fire a hook to load in custom admin scripts.
		do_action( 'envira_gallery_admin_scripts' );
	}

	/**
	 * Deletes the Envira gallery association for the image being deleted.
	 *
	 * @since 1.0.0
	 *
	 * @param int $attach_id The attachment ID being deleted.
	 */
	public function delete_gallery_association( $attach_id ) {

		$has_gallery = get_post_meta( $attach_id, '_eg_has_gallery', true );

		// Only proceed if the image is attached to any Envira galleries.
		if ( ! empty( $has_gallery ) ) {
			foreach ( (array) $has_gallery as $post_id ) {
				// Remove the in_gallery association.
				$in_gallery = get_post_meta( $post_id, '_eg_in_gallery', true );
				if ( ! empty( $in_gallery ) ) {
					$key = array_search( $attach_id, (array) $in_gallery, true );
					if ( false !== $key ) {
						unset( $in_gallery[ $key ] );
					}
				}

				update_post_meta( $post_id, '_eg_in_gallery', $in_gallery );

				// Remove the image from the gallery altogether.
				$gallery_data = get_post_meta( $post_id, '_eg_gallery_data', true );
				if ( ! empty( $gallery_data['gallery'] ) ) {
					unset( $gallery_data['gallery'][ $attach_id ] );
				}

				// Update the post meta for the gallery.
				update_post_meta( $post_id, '_eg_gallery_data', $gallery_data );

				// Flush necessary gallery caches.
				Envira_Gallery_Common::get_instance()->flush_gallery_caches( $post_id, ( ! empty( $gallery_data['config']['slug'] ) ? $gallery_data['config']['slug'] : '' ) );
			}
		}
	}

	/**
	 * Removes any extra cropped images when an attachment is deleted.
	 *
	 * @since 1.0.0
	 *
	 * @param int $post_id The post ID.
	 * @return void        Return early if the appropriate metadata cannot be retrieved.
	 */
	public function delete_cropped_image( $post_id ) {

		// Get attachment image metadata.
		$metadata = wp_get_attachment_metadata( $post_id );

		// Return if no metadata is found.
		if ( ! $metadata ) {
			return;
		}

		// Return if we don't have the proper metadata.
		if ( ! isset( $metadata['file'] ) || ! isset( $metadata['image_meta']['resized_images'] ) ) {
			return;
		}

		// Grab the necessary info to removed the cropped images.
		$wp_upload_dir  = wp_upload_dir();
		$pathinfo       = pathinfo( $metadata['file'] );
		$resized_images = $metadata['image_meta']['resized_images'];

		// Loop through and deleted and resized/cropped images.
		foreach ( $resized_images as $dims ) {
			// Get the resized images filename and delete the image.
			$file = $wp_upload_dir['basedir'] . '/' . $pathinfo['dirname'] . '/' . $pathinfo['filename'] . '-' . $dims . '.' . $pathinfo['extension'];

			// Delete the resized image.
			if ( file_exists( $file ) ) {
				@unlink( $file ); // @codingStandardsIgnoreLine
			}
		}
	}

	/**
	 * Trash a gallery when the gallery post type is trashed.
	 *
	 * @since 1.0.0
	 *
	 * @param boolean $id   The post ID being trashed.
	 * @return void Return early if no gallery is found.
	 */
	public function trash_gallery( $id ) {

		$gallery = get_post( $id );

		// Flush necessary gallery caches to ensure trashed galleries are not showing.
		Envira_Gallery_Common::get_instance()->flush_gallery_caches( $id );

		// Return early if not an Envira gallery.
		if ( 'envira' !== $gallery->post_type ) {
			return;
		}

		// Check some gallery data exists.
		$gallery_data = get_post_meta( $id, '_eg_gallery_data', true );
		if ( empty( $gallery_data ) ) {
			return;
		}

		// Set the gallery status to inactive.
		$gallery_data['status'] = 'inactive';
		update_post_meta( $id, '_eg_gallery_data', $gallery_data );

		// Allow other addons to run routines when a Gallery is trashed.
		do_action( 'envira_gallery_trash', $id, $gallery_data );
	}

	/**
	 * Untrash a gallery when the gallery post type is untrashed.
	 *
	 * @since 1.0.0
	 *
	 * @param boolean $id   The post ID being untrashed.
	 * @return void Return early if no gallery is found.
	 */
	public function untrash_gallery( $id ) {

		$gallery = get_post( $id );

		// Flush necessary gallery caches to ensure untrashed galleries are showing.
		Envira_Gallery_Common::get_instance()->flush_gallery_caches( $id );

		// Return early if not an Envira gallery.
		if ( 'envira' !== $gallery->post_type ) {
			return;
		}

		// Set the gallery status to inactive.
		$gallery_data = get_post_meta( $id, '_eg_gallery_data', true );
		if ( empty( $gallery_data ) ) {
			return;
		}

		if ( isset( $gallery_data['status'] ) ) {
			unset( $gallery_data['status'] );
		}

		update_post_meta( $id, '_eg_gallery_data', $gallery_data );

		// Allow other addons to run routines when a Gallery is untrashed.
		do_action( 'envira_gallery_untrash', $id, $gallery_data );
	}

	/**
	 * Fired when a gallery is about to be permanently deleted from Trash
	 *
	 * Checks if the media_delete setting is enabled, and if so safely deletes
	 * media that isn't being used elsewhere on the site
	 *
	 * @since 1.3.6.1
	 *
	 * @param boolean $id Post ID.
	 * @return void
	 */
	public function delete_gallery( $id ) {

		// Check if the media_delete setting is enabled.
		$media_delete = false;
		if ( '1' !== $media_delete ) {
			return;
		}

		// Get post.
		$gallery = get_post( $id );

		// Flush necessary gallery caches to ensure untrashed galleries are showing.
		Envira_Gallery_Common::get_instance()->flush_gallery_caches( $id );

		// Return early if not an Envira gallery.
		if ( 'envira' !== $gallery->post_type ) {
			return;
		}

		// Get attached media.
		$media = get_attached_media( 'image', $id );
		if ( ! is_array( $media ) || 0 === count( $media ) ) {
			return;
		}

		// Iterate through media, deleting.
		foreach ( $media as $image ) {
			wp_delete_attachment( $image->ID );
		}
	}

	/**
	 * Called whenever an upgrade button / link is displayed in Lite, this function will
	 * check if there's a shareasale ID specified.
	 *
	 * There are three ways to specify an ID, ordered by highest to lowest priority
	 * - add_filter( 'envira_gallery_shareasale_id', function() { return 1234; } );
	 * - define( 'ENVIRA_GALLERY_SHAREASALE_ID', 1234 );
	 * - get_option( 'envira_gallery_shareasale_id' ); (with the option being in the wp_options table)
	 *
	 * Additionally, you can completely override the final URL using:
	 * - add_filter( 'envira_gallery_shareasale_entire_redirect_url', function( $url, $original_url, $medium, $button, $append, $shareasale_id ) { return 'your-custom-url'; } );
	 *
	 * utm_source = liteplugin
	 * utm_medium = page
	 * utm_campaign = what button was clicked, etc.
	 *
	 * If an ID is present, returns the ShareASale link with the affiliate ID, and tells
	 * ShareASale to then redirect to enviragallery.com/lite
	 *
	 * If no ID is present, just returns the enviragallery.com/lite URL with UTM tracking.
	 *
	 * @param string $url Url for upgrade.
	 * @param string $medium utm_medium.
	 * @param string $button utm_campaign.
	 * @param string $append append to the end of the url.
	 *
	 * @since 1.5.0
	 */
	public function get_upgrade_link( $url = false, $medium = 'default', $button = 'default', $append = false ) {

		// Check if there's a constant.
		$shareasale_id = '';
		if ( defined( 'ENVIRA_GALLERY_SHAREASALE_ID' ) ) {
			$shareasale_id = ENVIRA_GALLERY_SHAREASALE_ID;
		}

		// If there's no constant, check if there's an option.
		if ( empty( $shareasale_id ) ) {
			$shareasale_id = get_option( 'envira_gallery_shareasale_id', '' );
		}

		// Whether we have an ID or not, filter the ID.
		$shareasale_id = apply_filters( 'envira_gallery_shareasale_id', $shareasale_id );

		// Build the URL first, then allow it to be completely overridden
		$final_url = '';

		// If at this point we still don't have an ID, we really don't have one!
		// Just return the standard upgrade URL.
		if ( empty( $shareasale_id ) ) {
			if ( false === filter_var( $url, FILTER_VALIDATE_URL ) ) {
				// prevent a possible typo.
				$url = false;
			}
			$url       = ( false !== $url ) ? trailingslashit( esc_url( $url ) ) : 'https://enviragallery.com/lite/';
			$final_url = $url . '?utm_source=liteplugin&utm_medium=' . $medium . '&utm_campaign=' . $button . $append;
		} else {
			// If here, we have a ShareASale ID
			// Build ShareASale URL with redirect.
			$final_url = 'http://www.shareasale.com/r.cfm?u=' . $shareasale_id . '&b=566240&m=51693&afftrack=&urllink=enviragallery%2Ecom%2Flite%2F';
		}

		// Allow complete URL override via new filter
		$final_url = apply_filters( 'envira_gallery_shareasale_entire_redirect_url', $final_url, $url, $medium, $button, $append, $shareasale_id );

		return $final_url;
	}

	/**
	 * Callback for the Envira Gallery Media Settings section.
	 *
	 * @return void
	 */
	public function envira_gallery_media_settings_add_new_section() {
		// Register a new section in the "Media" settings page.
		add_settings_section(
			'envira_gallery_convert_section',
			__( 'Envira Gallery', 'envira-gallery-lite' ),
			[ $this, 'envira_gallery_convert_section_callback' ],
			'media'
		);
	}

	/**
	 * Callback for the Envira Gallery content section.
	 *
	 * @return void
	 */
	public function envira_gallery_convert_section_callback() {
		?>
		<p><?php esc_html_e( 'Convert all of your existing WP Galleries to Envira Galleries. Take advantage of advanced options like drag and drop features, themes, lightboxes, and much more.', 'envira-gallery-lite' ); ?></p>
		<?php
			$convert_button = __( 'Convert to Envira Gallery', 'envira-gallery-lite' );
		?>
		<p><a href="<?php echo esc_url( admin_url( 'edit.php?post_type=envira&page=envira-gallery-settings#!envira-tab-convert_to_envira' ) ); ?>" title="<?php echo esc_attr( $convert_button ); ?>" class="button button-secondary envira-media-settings-convert-btn"><?php echo esc_attr( $convert_button ); ?></a></p>
		<?php
	}

	/**
	 * Renders the post types dropdown.
	 *
	 * @return void
	 */
	public function envira_render_post_types_dropdown() {
		// Exclusions for keywords, exact names, and labels.
		$exclusions = [
			'keywords'    => [ 'envira', 'ngg', 'nextgen', 'photocrati', 'gallery', 'elementor' ],
			'exact_names' => [ 'e-landing-page' ],
			'labels'      => [ 'NextGEN', 'Gallery' ],
		];

		// Retrieve all custom post types.
		$post_types = get_post_types( [ '_builtin' => false ], 'objects' );

		// Filter post types based on exclusions.
		$filtered_post_types = array_filter(
			$post_types,
			function ( $post_type ) use ( $exclusions ) {
				// Exclude based on keywords in the post type name.
				foreach ( $exclusions['keywords'] as $keyword ) {
					if ( strpos( $post_type->name, $keyword ) !== false ) {
						return false;
					}
				}

				// Exclude based on exact post type names.
				if ( in_array( $post_type->name, $exclusions['exact_names'], true ) ) {
					return false;
				}

				// Exclude based on labels.
				foreach ( $exclusions['labels'] as $label ) {
					if ( strpos( $post_type->label, $label ) !== false ) {
						return false;
					}
				}

				return true; // Include post type if it passes all checks.
			}
		);

		// Allow users to modify the post types list.
		$filtered_post_types = apply_filters( 'envira_convert_post_types', $filtered_post_types );
		?>
		<div class="envira-posttype-dropdown-section">
			<select name="envira_convert_post_types_dropdown" id="envira_convert_post_types_dropdown">
				<option value=""><?php esc_html_e( 'Select Post Type for Conversion', 'envira-gallery-lite' ); ?></option>
				<option value="post"><?php esc_html_e( 'Posts', 'envira-gallery-lite' ); ?></option>
				<option value="page"><?php esc_html_e( 'Pages', 'envira-gallery-lite' ); ?></option>
				<?php
				foreach ( $filtered_post_types as $post_type ) {
					?>
					<option value="<?php echo esc_html( $post_type->name ); ?>">
						<?php echo esc_html( $post_type->label ); ?>
					</option>
					<?php
				}
				?>
			</select>
			<br/>
			<span class="envira-posttype-dropdown-error"><?php esc_html_e( 'Please select a post type for conversion.', 'envira-gallery-lite' ); ?></span>
		</div>
		<?php
	}

	/**
	 * Returns the singleton instance of the class.
	 *
	 * @since 1.0.0
	 *
	 * @return object The Envira_Gallery_Common_Admin object.
	 */
	public static function get_instance() {

		if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Envira_Gallery_Common_Admin ) ) {
			self::$instance = new Envira_Gallery_Common_Admin();
		}

		return self::$instance;
	}
}

// Load the common admin class.
$envira_gallery_common_admin = Envira_Gallery_Common_Admin::get_instance();
