403Webshell
Server IP : 195.130.67.5  /  Your IP : 216.73.217.154
Web Server : Microsoft-IIS/10.0
System : Windows NT WEBSERVER1 10.0 build 17763 (Windows Server 2016) i586
User : IUSR ( 0)
PHP Version : 7.4.19
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : OFF  |  Perl : OFF  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /inetpub/wwwroot/cdc/wp-content/plugins/page-links-to/classes/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /inetpub/wwwroot/cdc/wp-content/plugins/page-links-to/classes/plugin.php
<?php
/**
 * The Page Links To plugin.
 *
 * @package PageLinksTo
 */

defined( 'WPINC' ) or die;

/**
 * The Page Links To class.
 */
class CWS_PageLinksTo {
	/**
	 * The class instance.
	 *
	 * @var CWS_PageLinksTo
	 */
	static $instance;

	/**
	 * The main plugin file path.
	 *
	 * @var string
	 */
	private $file;

	const LINK_META_KEY = '_links_to';
	const TARGET_META_KEY = '_links_to_target';
	const VERSION_KEY = 'txfx_plt_schema_version';
	const DISMISSED_NOTICES = 'page_links_dismissed_options';
	const MESSAGE_ID = 4;
	const NEWSLETTER_URL = 'https://pages.convertkit.com/8eb23c1339/1ce4614706';
	const CSS_JS_VERSION = '3.4.1';
	const ALWAYS_SUPPORTED_POST_TYPES = array( 'page' );
	const OMITTED_POST_TYPES = array( 'wp_block', 'wp-help' );

	/**
	 * Whether to replace WP links with their specified URLs.
	 *
	 * @var bool
	 */
	protected $replace = true;

	/**
	 * Class constructor. Adds init hook.
	 *
	 * @param string $file The main plugin file path.
	 */
	function __construct( $file ) {
		self::$instance = $this;
		self::$instance->file = $file;
		$this->hook( 'init' );
	}

	/**
	 * Get the plugin instance.
	 *
	 * @return CWS_PageLinksTo The plugin class instance.
	 */
	public static function get_instance() {
		return self::$instance;
	}


	/**
	 * Returns the main plugin file path.
	 *
	 * @return string The main plugin file path.
	 */
	public function get_file() {
		return $this->file;
	}

	/**
	 * Add a WordPress hook (action/filter).
	 *
	 * @param string $hook first parameter is the name of the hook. If second or third parameters are included, they will be used as a priority (if an integer) or as a class method callback name (if a string).
	 * @return true Will always return true.
	 */
	public function hook( string $hook ) {
		$args = func_get_args();
		$priority = 10;
		$method = self::sanitize_method( $hook );
		unset( $args[0] );
		foreach ( (array) $args as $arg ) {
			if ( is_int( $arg ) ) {
				$priority = $arg;
			} elseif ( is_string( $arg ) ) {
				$method = $arg;
			}
		}

		return add_action( $hook, array( $this, $method ), $priority, 999 ); // @phpstan-ignore argument.type
	}

	/**
	 * Sanitizes method names with bad characters.
	 *
	 * @param string $method The raw method name.
	 * @return string The sanitized method name.
	 */
	private static function sanitize_method( $method ) {
		return str_replace( array( '.', '-' ), array( '_DOT_', '_DASH_' ), $method );
	}

	/**
	 * Includes a file (relative to the plugin base path)
	 * and optionally globalizes a named array passed in.
	 *
	 * @param string              $file The file to include.
	 * @param array<string,mixed> $data A named array of data to globalize.
	 * @return void
	 */
	public function include_file( $file, $data = array() ) {
		extract( $data, EXTR_SKIP );
		include( $this->get_path() . $file );
	}

	/**
	 * Bootstraps the upgrade process and registers all the hooks.
	 *
	 * @return void
	 */
	public function init() {
		// Check to see if any of our data needs to be upgraded.
		$this->maybe_upgrade();

		// Load translation files.
		load_plugin_textdomain( 'page-links-to', false, basename( dirname( $this->file ) ) . '/languages' );

		// Init hook.
		do_action( 'page_links_to_init', $this );

		// Register hooks.
		$this->register_hooks();
	}

	/**
	 * Registers all the hooks.
	 *
	 * @return void
	 */
	function register_hooks() {
		// Hook in to URL generation.
		$this->hook( 'page_link', 'link', 20 );
		$this->hook( 'post_link', 'link', 20 );
		$this->hook( 'post_type_link', 'link', 20 );
		$this->hook( 'attachment_link', 'link', 20 );

		// Non-standard priority hooks.
		$this->hook( 'do_meta_boxes', 20 );
		$this->hook( 'admin_bar_menu', 999 );
		$this->hook( 'wp_ajax_sample-permalink', 'disable_replacements', -999 );

		// Non-standard callback hooks.
		$this->hook( 'load-post.php', 'load_post' );
		$this->hook( 'wp_ajax_plt_dismiss_notice', 'ajax_dismiss_notice' );
		$this->hook( 'wp_ajax_plt_quick_add', 'ajax_quick_add' );

		// Standard hooks.
		$this->hook( 'wp_list_pages' );
		$this->hook( 'template_redirect' );
		$this->hook( 'save_post' );
		$this->hook( 'wp_enqueue_scripts' );
		$this->hook( 'edit_attachment' );
		$this->hook( 'wp_nav_menu_objects' );
		$this->hook( 'plugin_row_meta' );
		$this->hook( 'display_post_states' );
		$this->hook( 'admin_footer' );
		$this->hook( 'admin_enqueue_scripts' );
		$this->hook( 'enqueue_block_editor_assets' );
		$this->hook( 'admin_menu' );

		$this->hook( 'rest_api_init' );

		// Gutenberg.
		$this->hook( 'use_block_editor_for_post', 99999 );

		// Page row actions.
		$this->hook( 'page_row_actions' );
		$this->hook( 'post_row_actions', 'page_row_actions' );

		$this->hook( 'init', 'register_meta_keys', 9999 );
		$this->hook( 'rest_api_init', 'register_meta_keys', 9999 );

		// Notices.
		if ( self::should_display_message() ) {
			$this->hook( 'admin_notices', 'notify_generic' );
		}
	}

	/**
	 * Checks if the specified post is going to use the block editor, and adds custom-fields support.
	 * 
	 * We have to do this because PLT requires custom-fields support to update post meta in the block editor.
	 * So if you add a custom post type without 'custom-fields' support, you'll get an error.
	 * We check that this post is going to use the block editor, and that its post type supports the block editor,
	 * and only then do we add 'custom-fields' support for the post type.
	 *
	 * @param boolean $use_block_editor Whether they are going to use the block editor for this post.
	 * @param WP_Post $post The post they are editing.
	 * @return boolean We return the original value of their decision.
	 */
	public function use_block_editor_for_post( $use_block_editor, $post ) {
		$post_type = get_post_type( $post );

		if ( $post_type && $use_block_editor && self::is_supported_post_type( $post_type ) ) {
			add_post_type_support( $post_type, 'custom-fields' );
		}

		return $use_block_editor;
	}

	/**
	 * Adds custom-fields support to PLT-supporting post types during REST API initialization.
	 *
	 * @return void
	 */
	function rest_api_init() {
		$post_type_names = array_keys( get_post_types() );

		foreach ( $post_type_names as $type ) {
			if ( self::is_supported_post_type( $type ) ) {
				add_post_type_support( $type, 'custom-fields' );
			}
		}
	}

	/**
	 * Registers the PLT post meta keys for supported post types.
	 *
	 * @return void
	 */
	public function register_meta_keys() {
		$post_type_names = array_keys( get_post_types() );

		foreach ( $post_type_names as $type ) {
			if ( self::is_supported_post_type( $type ) ) {
				$this->register_meta( self::LINK_META_KEY, $type );
				$this->register_meta( self::TARGET_META_KEY, $type );
				do_action( 'page_links_to_register_meta_for_post_type', $type );
			}
		}
	}

	/**
	 * Registers a post meta key for a given post type.
	 *
	 * @param string $key The key name.
	 * @param string $post_type The post type.
	 * @return boolean Whether the meta key was registered.
	 */
	public function register_meta( $key, $post_type ) {
		return register_meta(
			'post',
			$key,
			array(
				'object_subtype' => $post_type,
				'type' => 'string',
				'single' => true,
				'show_in_rest' => true,
				'auth_callback' => array( $this, 'rest_auth' ),
			)
		);
	}

	/**
	 * Determines REST API authentication.
	 *
	 * @param bool          $allowed Whether it is allowed.
	 * @param string        $meta_key The meta key being checked.
	 * @param int           $post_id The post ID being checked.
	 * @param int           $user_id The user ID being checked.
	 * @param string        $cap The current capability.
	 * @param array<string> $caps All capabilities.
	 * @return bool Whether the user can do it.
	 */
	public function rest_auth( $allowed, $meta_key, $post_id, $user_id, $cap, $caps ) {
		return user_can( $user_id, 'edit_post', $post_id );
	}

	/**
	 * Performs an upgrade for older versions
	 *
	 * * Version 3: Underscores the keys so they only show in the plugin's UI.
	 *
	 * @return void
	 */
	function maybe_upgrade() {
		// In earlier versions, the meta keys were stored without a leading underscore.
		// Since then, underscore has been codified as the standard for "something manages this" post meta.
		if ( ! get_option( self::VERSION_KEY ) || get_option( self::VERSION_KEY ) < 3 ) {
			/** @var \wpdb $wpdb */
			global $wpdb;
			$total_affected = 0;
			foreach ( array( '', '_target', '_type' ) as $meta_key ) {
				$meta_key = 'links_to' . $meta_key;
				$affected = $wpdb->update( $wpdb->postmeta, array(
					'meta_key' => '_' . $meta_key,
				), compact( 'meta_key' ) );
				if ( is_int( $affected ) && $affected > 0 ) {
					$total_affected += $affected;
				}
			}

			// Update the database version.
			update_option( self::VERSION_KEY, 3 );

			// Only flush the cache if something changed.
			if ( $total_affected > 0 ) {
				wp_cache_flush();
			}
		}
	}

	/**
	 * Disables replacements.
	 *
	 * @return void
	 */
	public function disable_replacements() {
		$this->replace = false;
	}

	/**
	 * Enqueues frontend scripts.
	 *
	 * @return void
	 */
	public function wp_enqueue_scripts() {
		if ( self::supports( 'new_tab' ) ) {
			wp_enqueue_script( 'page-links-to', $this->get_url() . 'dist/new-tab.js', array(), self::CSS_JS_VERSION, true );
		}
	}

	/**
	 * Enqueues backend scripts.
	 *
	 * @return void
	 */
	public function admin_enqueue_scripts() {
		if ( !is_customize_preview() && current_user_can( 'edit_posts' ) ) {
			wp_register_script( 'plt-clipboard', $this->get_url() . 'dist/clipboard.min.js', array(), self::CSS_JS_VERSION, true );
			wp_enqueue_script( 'plt-quick-add', $this->get_url() . 'dist/quick-add.js', array( 'plt-clipboard', 'jquery-ui-dialog' ), self::CSS_JS_VERSION, true );
			wp_enqueue_style( 'plt-quick-add', $this->get_url() . 'dist/quick-add.css', array( 'wp-jquery-ui-dialog' ), self::CSS_JS_VERSION );
		}
	}

	/**
	 * Enqueues block editor scripts.
	 *
	 * @return void
	 */
	public function enqueue_block_editor_assets() {
		// Gutenberg.
		if ( self::is_block_editor() && self::is_supported_post_type() ) {
			/** @var array{dependencies: array<string>, version: string} $asset_file */
			$asset_file = include $this->get_path() . 'dist/block-editor.asset.php';
			wp_enqueue_script( 'plt-block-editor', $this->get_url() . 'dist/block-editor.js', $asset_file['dependencies'], self::CSS_JS_VERSION, true );
			wp_set_script_translations( 'plt-block-editor', 'page-links-to', $this->get_path() . 'languages' );
			wp_localize_script( 'plt-block-editor', 'pltOptions', [
				'supports' => [
					'newTab' => self::supports( 'new_tab' ),
				],
				'panelTitle' => self::get_panel_title(),
				'supportedPostTypes' => (array) apply_filters( 'page-links-to-post-types', self::get_default_post_types() ),
			]);
			do_action( 'page_links_to_enqueue_block_editor_assets' );
		}
	}

	/**
	 * Adds our items to the admin bar.
	 *
	 * @param WP_Admin_Bar $bar The admin bar object.
	 * @return void
	 */
	public function admin_bar_menu( $bar ) {
		if ( is_admin() ) {
			$bar->add_node( array(
				'id' => 'new-page-link',
				'title' => __( 'Page Link', 'page-links-to' ),
				'parent' => 'new-content',
				'href' => '#new-page-link',
			));
		}
	}

	/**
	 * Filters the page row actions.
	 *
	 * @param array<string,string> $actions The current array of actions.
	 * @param WP_Post              $post The current post row being processed.
	 * @return array<string,string> The updated array of actions.
	 */
	public function page_row_actions( $actions, $post ) {
		if ( self::get_link( $post ) ) {
			$new_actions = array();
			$inserted = false;
			$original_url = (string) $this->original_link( $post->ID );
			$original_html = '<a href="' . esc_attr( $original_url ) . '" class="plt-copy-short-url" data-clipboard-text="' . esc_attr( $original_url ) . '" data-original-text="' . __( 'Copy Short URL', 'page-links-to' ) . '">' . __( 'Copy Short URL', 'page-links-to' ) . '</a>';
			$original_key = 'plt_original';

			foreach ( $actions as $key => $html ) {
				$new_actions[ $key ] = $html;

				if ( 'view' === $key ) {
					$inserted = true;
					$new_actions[ $original_key ] = $original_html;
				}
			}

			if ( ! $inserted ) {
				$new_actions[ $original_key ] = $original_html;
			}

			$actions = $new_actions;
		}

		return $actions;
	}

	/**
	 * Adds the Add Page Link menu item.
	 *
	 * @return void
	 */
	public function admin_menu() {
		add_submenu_page( 'edit.php?post_type=page', '', __( 'Add Page Link', 'page-links-pro' ), 'edit_pages', 'plt-add-page-link', '__return_empty_string' );
	}

	/**
	 * Adds the quick-add HTML to the admin footer.
	 *
	 * @return void
	 */
	public function admin_footer() {
		if ( current_user_can( 'edit_pages' ) ) {
			$this->include_file( 'templates/quick-add.php' );
		}
	}

	/**
	 * Returns a single piece of post meta.
	 *
	 * @param  int    $post_id a post ID.
	 * @param  string $key a post meta key.
	 * @return string|false the post meta, or false, if it doesn't exist.
	 */
	public static function get_post_meta( $post_id, $key ) {
		$meta = get_post_meta( absint( $post_id ), $key, true );

		if ( '' === $meta || ! is_string( $meta ) ) {
			return false;
		}

		return $meta;
	}

	/**
	 * Returns the link for the specified post.
	 *
	 * @param  WP_Post|int $post a post or post ID.
	 * @return string|false either a URL or false.
	 */
	public static function get_link( $post ) {
		$post = get_post( $post );

		if ( ! $post ) {
			return false;
		}

		return self::get_post_meta( $post->ID, self::LINK_META_KEY );
	}

	/**
	 * Returns the _blank target status for the specified post.
	 *
	 * @param  WP_Post|int $post a post or post ID.
	 * @return bool whether it should open in a new tab.
	 */
	public static function get_target( $post ) {
		$post = get_post( $post );

		if ( ! $post ) {
			return false;
		}

		return (bool) self::get_post_meta( $post->ID, self::TARGET_META_KEY );
	}

	/**
	 * Adds the meta box to the post or page edit screen.
	 *
	 * @param string $page the name of the current page.
	 * @param string $context the current context.
	 * @return void
	 */
	public function do_meta_boxes( $page, $context ) {
		if ( ! self::is_block_editor() && self::is_supported_post_type( $page ) && 'advanced' === $context ) {
			add_meta_box( 'page-links-to', self::get_panel_title(), array( $this, 'meta_box' ), $page, 'advanced', 'low' );
		}
	}

	/**
	 * Get the default post types that support custom links.
	 *
	 * Returns post types that have a UI, except for post types omitted manually,
	 * plus the 'page' post type.
	 *
	 * @return array<string> List of post type names.
	 */
	public static function get_default_post_types() {
		$post_types = array_keys( get_post_types( array(
			'show_ui'            => true,
		) ) );

		$post_types = array_values( array_diff( $post_types, self::OMITTED_POST_TYPES ) );

		foreach ( self::ALWAYS_SUPPORTED_POST_TYPES as $post_type ) {
			if ( ! in_array( $post_type, $post_types, true ) ) {
				$post_types[] = $post_type;
			}
		}

		return $post_types;
	}

	/**
	 * Determine whether a post type supports custom links.
	 *
	 * @param string|object|null $type The post type to check.
	 * @return bool Whether this post type supports custom links.
	 */
	public static function is_supported_post_type( $type = null ) {
		if ( is_null( $type ) ) {
			$type = get_post_type();
		}

		if ( is_object( $type ) ) {
			if ( isset( $type->id ) ) {
				$type = $type->id;
			}
		}

		/*
			Plugins that use custom post types can use this filter to hide the
			PLT UI in their post type.
		*/
		$hook = 'page-links-to-post-types';

		$supported_post_types = (array) apply_filters( $hook, self::get_default_post_types() );

		return in_array( $type, $supported_post_types );
	}

	/**
	 * Outputs the Page Links To post screen meta box.
	 *
	 * @return void
	 */
	public function meta_box() {
		$post = get_post();

		if ( ! $post ) {
			return;
		}

		echo '<p>';
		wp_nonce_field( 'cws_plt_' . $post->ID, '_cws_plt_nonce', false, true );
		echo '</p>';
		$url = self::get_link( $post->ID );
		if ( ! $url ) {
			$linked = false;
			$url = '';
		} else {
			$linked = true;
		}
		?>
		<p><?php _e( 'Point this content to:', 'page-links-to' ); ?></p>
		<p><label><input type="radio" id="cws-links-to-choose-wp" name="cws_links_to_choice" value="wp" <?php checked( ! $linked ); ?> /> <?php _e( 'Its normal WordPress URL', 'page-links-to' ); ?></label></p>
		<p><label><input type="radio" id="cws-links-to-choose-custom" name="cws_links_to_choice" value="custom" <?php checked( $linked ); ?> /> <?php _e( 'A custom URL', 'page-links-to' ); ?></label></p>
		<div id="cws-links-to-custom-section" class="<?php echo ! $linked ? 'hide-if-js' : ''; ?>">
			<p><input placeholder="http://" name="cws_links_to" type="text" id="cws-links-to" value="<?php echo esc_attr( $url ); ?>" /></p>
			<?php if ( $this->supports('new_tab') ) { ?>
				<p><label for="cws-links-to-new-tab"><input type="checkbox" name="cws_links_to_new_tab" id="cws-links-to-new-tab" value="_blank" <?php checked( (bool) self::get_target( $post->ID ) ); ?>> <?php _e( 'Open this link in a new tab', 'page-links-to' ); ?></label></p>
			<?php } ?>
			<?php do_action( 'page_links_to_meta_box_bottom' ); ?>
		</div>

		<script src="<?php echo esc_url( $this->get_url() ) . 'dist/meta-box.js?v=' . self::CSS_JS_VERSION; ?>"></script>
		<?php
	}

	/**
	 * Saves data on attachment save.
	 *
	 * @param  int $post_id The ID of the post being saved.
	 * @return int the attachment post ID that was passed in.
	 */
	function edit_attachment( $post_id ) {
		return $this->save_post( $post_id );
	}

	/**
	 * Checks whether a given feature is supported.
	 *
	 * @param string $feature The feature to check.
	 * @return bool Whether the feature is supported.
	 */
	public static function supports( $feature = '' ) {
		switch( $feature ) {
			case 'new_tab':
			default:
				return (bool) apply_filters( 'page_links_to_supports_' . $feature, true );
		}
	}

	/**
	 * Saves data on post save.
	 *
	 * @param int $post_id a post ID.
	 * @return int the post ID that was passed in.
	 */
	public static function save_post( $post_id ) {
		$nonce = isset( $_REQUEST['_cws_plt_nonce'] ) && is_string( $_REQUEST['_cws_plt_nonce'] ) ? $_REQUEST['_cws_plt_nonce'] : '';
		if ( $nonce && wp_verify_nonce( $nonce, 'cws_plt_' . $post_id ) ) {
			$links_to = isset( $_POST['cws_links_to'] ) && is_string( $_POST['cws_links_to'] ) ? $_POST['cws_links_to'] : '';
			$choice   = isset( $_POST['cws_links_to_choice'] ) && is_string( $_POST['cws_links_to_choice'] ) ? $_POST['cws_links_to_choice'] : '';
			if ( ( '' === $choice || 'custom' === $choice ) && strlen( $links_to ) > 0 && $links_to !== 'http://' ) {
				$url = self::clean_url( stripslashes( $links_to ) );
				self::set_link( $post_id, $url );
				if ( isset( $_POST['cws_links_to_new_tab'] ) && self::supports( 'new_tab' ) ) {
					self::set_link_new_tab( $post_id );
				} else {
					self::set_link_same_tab( $post_id );
				}
			} else {
				self::delete_link( $post_id );
			}
		}

		return $post_id;
	}

	/**
	 * Cleans up a URL.
	 *
	 * @param string $url URL.
	 * @return string cleaned up URL.
	 */
	public static function clean_url( $url ) {
		$url = trim( $url );

		// Starts with 'www.'. Probably a mistake. So add 'http://'.
		if ( 0 === strpos( $url, 'www.' ) ) {
			$url = 'http://' . $url;
		}

		return $url;
	}

	/**
	 * Have a post point to a custom URL.
	 *
	 * @param int    $post_id post ID.
	 * @param string $url the URL to point the post to.
	 * @return bool whether anything changed.
	 */
	public static function set_link( $post_id, $url ) {
		do_action( 'page_links_to_set_link', $post_id, $url );
		return (bool) update_post_meta( $post_id, self::LINK_META_KEY, $url );
	}

	/**
	 * Tell an custom URL post to open in a new tab.
	 *
	 * @param int $post_id post ID.
	 * @return bool whether anything changed.
	 */
	public static function set_link_new_tab( $post_id ) {
		return (bool) update_post_meta( $post_id, self::TARGET_META_KEY, '_blank' );
	}

	/**
	 * Tell an custom URL post to open in the same tab.
	 *
	 * @param int $post_id post ID.
	 * @return bool whether anything changed.
	 */
	public static function set_link_same_tab( $post_id ) {
		return delete_post_meta( $post_id, self::TARGET_META_KEY );
	}

	/**
	 * Discard a custom URL and point a post to its normal URL.
	 *
	 * @param int $post_id post ID.
	 * @return bool whether the link was deleted.
	 */
	public static function delete_link( $post_id ) {
		$return = delete_post_meta( $post_id, self::LINK_META_KEY );
		delete_post_meta( $post_id, self::TARGET_META_KEY );

		// Old, unused data that we can delete on the fly.
		delete_post_meta( $post_id, '_links_to_type' );

		do_action( 'page_links_to_delete_link', $post_id );

		return $return;
	}

	/**
	 * Filter for post links.
	 *
	 * @param string      $link the URL for the post or page.
	 * @param int|WP_Post $post post ID or object.
	 * @return string output URL.
	 */
	public function link( $link, $post ) {
		if ( $this->replace ) {
			$post = get_post( $post );

			if (! $post instanceof \WP_Post) {
				return $link;
			}

			$meta_link = self::get_link( $post->ID );

			if ( $meta_link ) {
				/** @var string $link */
				$link = apply_filters( 'page_links_to_link', $meta_link, $post, $link );
				$link = esc_url( $link );
				if ( self::supports( 'new_tab' ) && ! is_admin() && !  (defined( 'REST_REQUEST' ) && REST_REQUEST ) && self::get_target( $post->ID ) ) {
					$link .= '#new_tab';
				}
			}
		}

		return $link;
	}

	/**
	 * Returns the original URL of the post.
	 *
	 * @param null|int|WP_Post $post The post to fetch.
	 * @return string|false The post's original URL, or false on failure.
	 */
	function original_link( $post = null ) {
		$this->replace = false;
		$url = get_permalink( $post ?? 0 );
		$this->replace = true;

		return $url;
	}

	/**
	 * Whether the request has a flag that should halt the redirect.
	 *
	 * @return bool
	 */
	function has_non_redirect_flag() {
		return (
			isset( $_GET['customize_theme'] ) ||
			isset( $_GET['elementor-preview'] )
		);
	}

	/**
	 * Performs a redirect.
	 *
	 * @return void
	 */
	function template_redirect() {
		$link = self::get_redirect();

		if ( $link && !self::has_non_redirect_flag() ) {
			do_action( 'page_links_to_redirect_url', get_queried_object_id(), $link );
			wp_redirect( $link, 301 );
			exit;
		}
	}

	/**
	 * Retrieves all posts that have a specified custom URL.
	 *
	 * @param string $url The URL to check.
	 * @return array<int|WP_Post> Array of post objects.
	 */
	public static function get_custom_url_posts( $url ) {
		$result = new WP_Query(array(
			'post_type' => 'any',
			'meta_key' => self::LINK_META_KEY,
			'meta_value' => $url,
			'posts_per_page' => -1,
			'post_status' => 'any',
		));

		return $result->posts;
	}

	/**
	 * Retrieves all posts that have a custom URL.
	 *
	 * @return array<int|WP_Post> Array of post objects.
	 */
	public static function get_all_custom_url_posts() {
		$result = new WP_Query(array(
			'post_type' => 'any',
			'meta_key' => self::LINK_META_KEY,
			'posts_per_page' => -1,
			'post_status' => 'any',
		));

		return $result->posts;
	}

	/**
	 * Gets the redirection URL.
	 *
	 * @return string|false the redirection URL, or false.
	 */
	public static function get_redirect() {
		if ( ! is_singular() || ! get_queried_object_id() ) {
			return false;
		}
		$link = self::get_link( get_queried_object_id() );

		if ( ! $link ) {
			return false;
		}

		return self::absolute_url( $link );
	}

	/**
	 * Makes a relative URL into an absolute one.
	 *
	 * @param string $url The relative URL.
	 * @return string The absolute URL.
	 */
	public static function absolute_url( $url ) {
		// Convert server- and protocol-relative URLs to absolute URLs.
		if ( '/' === $url[0] ) {
			// Protocol-relative.
			if ( '/' === $url[1] ) {
				$url = set_url_scheme( 'http:' . $url );
			} else {
				// Host-relative.
				$host = isset( $_SERVER['HTTP_HOST'] ) && is_string( $_SERVER['HTTP_HOST'] ) ? $_SERVER['HTTP_HOST'] : '';
				$url = set_url_scheme( 'http://' . $host . $url );
			}
		}

		if ( 'mailto' !== parse_url( $url, PHP_URL_SCHEME ) ) {
			$url = str_replace( '@', '%40', $url );
		}

		return $url;
	}

	/**
	 * Filters the list of pages to alter the links and targets.
	 *
	 * @param string          $output the wp_list_pages() HTML block from WordPress.
	 * @param array<mixed>    $_args (Unused) the arguments passed to `wp_list_pages()`.
	 * @param array<WP_Post>  $pages Array of WP_Post objects.
	 * @return string the modified HTML block.
	 */
	function wp_list_pages( $output, $_args = array(), $pages = array() ) {
		if ( empty( $pages ) ) {
			return $output;
		}

		$highlight = false;
		$current_page_id = 0;

		$host = isset( $_SERVER['HTTP_HOST'] ) && is_string( $_SERVER['HTTP_HOST'] ) ? $_SERVER['HTTP_HOST'] : '';
		$request_uri = isset( $_SERVER['REQUEST_URI'] ) && is_string( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : '';
		$this_url = esc_url_raw( set_url_scheme( 'http://' . $host . $request_uri ) );

		foreach ( (array) $pages as $page ) {
			$page_url = self::get_link( $page->ID );

			if ( $page_url && $this_url === $page_url ) {
				$highlight = true;
				$current_page_id = $page->ID;
			}
		}

		if ( $highlight ) {
			$output = (string) preg_replace( '|<li class="([^"]+) current_page_item"|', '<li class="$1"', $output ); // Kill default highlighting.
			$output = (string) preg_replace( '|<li class="(page_item page-item-' . $current_page_id . ')"|', '<li class="$1 current_page_item"', $output );
		}

		return $output;
	}

	/**
	 * Filters nav menu objects and adds target=_blank to the ones that need it.
	 *
	 * @param  array<\WP_Post>|mixed $items nav menu items.
	 * @return array<\WP_Post>|mixed modified nav menu items.
	 */
	public static function wp_nav_menu_objects( $items ) {
		if ( ! is_array( $items ) ) {
			return $items;
		}

		$new_items = array();

		foreach ( $items as $item ) {
			if ( is_object( $item ) && isset( $item->object_id ) && is_numeric( $item->object_id ) && self::get_target( (int) $item->object_id ) ) {
				$item->target = '_blank'; // @phpstan-ignore property.notFound
			}

			$new_items[] = $item;
		}

		return $new_items;
	}

	/**
	 * Hooks in as a post is being loaded for editing and conditionally adds a notice.
	 *
	 * @return void
	 */
	public function load_post() {
		if ( isset( $_GET['post'] ) && is_numeric( $_GET['post'] ) && self::get_link( (int) $_GET['post'] ) ) {
			$this->hook( 'edit_form_after_title' );
			$this->hook( 'admin_notices', 'notify_of_external_link' );
			$this->replace = false;
		}
	}

	/**
	 * Ajax handler for dismissing a notice.
	 *
	 * @return void
	 */
	public static function ajax_dismiss_notice() {
		if ( isset( $_GET['plt_notice'] ) && is_numeric( $_GET['plt_notice'] ) ) {
			self::dismiss_notice( (int) $_GET['plt_notice'] );
		}
	}

	/**
	 * Ajad handler for creating a page link.
	 *
	 * @return void
	 */
	public function ajax_quick_add() {
		if ( current_user_can( 'edit_pages' ) ) {
			check_ajax_referer( 'plt-quick-add', 'plt_nonce' );

			$title   = isset( $_POST['plt_title'] ) && is_string( $_POST['plt_title'] ) ? stripslashes( $_POST['plt_title'] ) : '';
			$url     = isset( $_POST['plt_url'] ) && is_string( $_POST['plt_url'] ) ? stripslashes( $_POST['plt_url'] ) : '';
			$slug    = isset( $_POST['plt_slug'] ) && is_string( $_POST['plt_slug'] ) ? stripslashes( $_POST['plt_slug'] ) : '';
			$publish = ! empty( $_POST['plt_publish'] ) && current_user_can( 'publish_pages' );

			$post_id = wp_insert_post(array(
				'post_type' => 'page',
				'post_status' => $publish ? 'publish' : 'draft',
				'post_title' => $title,
				'post_name' => $slug,
			));

			$this->set_link( $post_id, $url );

			$post = get_post( $post_id );

			if ( ! $post ) {
				return;
			}

			$message = $publish ? __( 'New page link published!', 'page-links-to' ) : __( 'Page link draft saved!', 'page-links-to' );

			wp_send_json_success( array(
				'id'      => $post->ID,
				'title'   => $post->post_title,
				'wpUrl'   => $this->original_link( $post->ID ),
				'url'     => self::get_link( $post->ID ),
				'slug'    => $post->post_name,
				'status'  => $post->post_status,
				'message' => $message,
			));
		}
	}

	/**
	 * Whether a message should be displayed.
	 *
	 * @return bool Whether to display the message.
	 */
	public static function should_display_message() {
		return false;
	}

	/**
	 * Return the notices which have been dismissed.
	 *
	 * @return array<int> The list of notice IDs that have been dismissed.
	 */
	public static function get_dismissed_notices() {
		$notices = get_option( self::DISMISSED_NOTICES, array() );

		if ( ! is_array( $notices ) ) {
			return array();
		}

		return array_map( static function ( $notice ): int {
			return is_numeric( $notice ) ? (int) $notice : 0;
		}, $notices );
	}

	/**
	 * Mark a notice as dismissed.
	 *
	 * @param int $id The notice ID to dismiss.
	 * @return void
	 */
	public static function dismiss_notice( $id ) {
		$notices = self::get_dismissed_notices();
		$notices[] = (int) $id;

		$notices = array_unique( $notices );
		update_option( self::DISMISSED_NOTICES, $notices );
	}

	/**
	 * Whether anyone on this site has dismissed the given notice.
	 *
	 * @param int $id The ID of the notice.
	 * @return bool Whether anyone has dismissed it.
	 */
	public static function has_dismissed_notice( $id ) {
		$dismissed_notices = self::get_dismissed_notices();

		return in_array( (int) $id, $dismissed_notices, true );
	}

	/**
	 * Output the generic notice.
	 *
	 * @return void
	 */
	public static function notify_generic() {
		if ( self::is_block_editor() ) {
			// Nothing right now.
		} else {
			?>
			<div id="page-links-to-notification" class="notice updated is-dismissible"><h3><?php _e( 'Page Links To', 'page-links-to' ); ?></h3>
				<p><a class="button plt-dismiss" target="_blank" href="<?php echo esc_url( self::NEWSLETTER_URL ); ?>"><?php _e( 'Give Me Updates', 'page-links-to' ); ?></a>&nbsp;&nbsp;<small><a href="javascript:void(0)" class="plt-dismiss"><?php _e( 'No thanks', 'page-links-to' ); ?></a></small></p>
			</div>
			<script>
				(function($){
					var $plt = $('#page-links-to-notification');
					$plt
						.on('click', '.notice-dismiss', function(e){
							$.ajax( ajaxurl, {
								type: 'GET',
								data: {
									action: 'plt_dismiss_notice',
									plt_notice: <?php echo json_encode( self::MESSAGE_ID ); ?>
								}
							});
						})
						.on('click', '.plt-dismiss', function(e){
							e.preventDefault();
							$(this).parents('.notice').first().find('.notice-dismiss').click();
						});
				})(jQuery);
			</script>
			<?php
		}
	}

	/**
	 * Whether the user is using the block editor (Gutenberg).
	 *
	 * @return bool
	 */
	public static function is_block_editor() {
		$current_screen = get_current_screen();
		return $current_screen instanceof \WP_Screen && $current_screen->is_block_editor();
	}

	/**
	 * Create a block editor notification.
	 *
	 * @param string $text The notification.
	 * @param string $type The type of notification.
	 * @return void
	 */
	public static function block_editor_notification( $text, $type = 'info' ) {
		if ( ! in_array( $type, array( 'error', 'warning', 'info' ) ) ) {
			return;
		}

		$type = ucfirst( $type );
		$method = "create{$type}Notice";
		?>
			<script>
				document.addEventListener('DOMContentLoaded', function() {
					if (wp.data !== undefined) {
						wp.data.dispatch('core/notices').<?php echo $method; ?>(<?php echo json_encode( $text ); ?>, {isDismissible: true, id: 'page-links-to-notice'});
					}
				});
			</script>
		<?php
	}

	/**
	 * Returns the panel title.
	 *
	 * @return string The panel title.
	 */
	public static function get_panel_title() {
		/** @var string */
		return apply_filters( 'page_links_to_panel_title', _x( 'Page Links To', 'Meta box title', 'page-links-to' ) );
	}

	/**
	 * Outputs a notice that the current post item is pointed to a custom URL.
	 *
	 * @return void
	 */
	public static function notify_of_external_link() {
		if ( self::is_block_editor() ) {
			// Disabled, currently, because these notifications can block the title, which is annoying.
			// @phpstan-ignore-next-line booleanAnd.leftAlwaysFalse
			false && self::block_editor_notification( 'Note: This content is pointing to a custom URL. Use the “Page Links To” area in the sidebar to control this.', 'info' );
		} else {
			?>
				<div class="notice updated"><p><?php printf( __( '<strong>Note</strong>: This content is pointing to a custom URL. Use the &#8220;%s&#8221; box to change this behavior.', 'page-links-to' ), self::get_panel_title() ); ?></p></div>
			<?php
		}
	}

	/**
	 * Inserts an Edit link after the title.
	 *
	 * @return void
	 */
	public function edit_form_after_title() {
		$this->replace = true;
		$post = get_post();

		if ( ! $post ) {
			return;
		}

		$link = self::get_link( $post );

		if ( ! $link ) {
			return;
		}

		echo '<div class="plt-links-to"><strong>' . __( 'Links to:', 'page-links-to' ) . '</strong> <a href="' . esc_url( $link ) . '">' . esc_html( $link ) . '</a> <button type="button" class="edit-slug button button-small hide-if-no-js">' . __( 'Edit', 'page-links-to' ) . '</button></div>';
	}

	/**
	 * Adds a GitHub link to the plugin meta.
	 *
	 * @param array<string> $links the current array of links.
	 * @param string        $file the current plugin being processed.
	 * @return array<string> the modified array of links.
	 */
	public function plugin_row_meta( $links, $file ) {
		if ( $file === plugin_basename( $this->file ) ) {
			return array_merge(
				$links,
				array( '<a href="https://github.com/markjaquith/page-links-to" target="_blank">GitHub</a>' )
			);
		} else {
			return $links;
		}
	}

	/**
	 * Filter the post states to indicate which ones are linked using this plugin.
	 *
	 * @param array<string,string> $states The existing post states.
	 * @param WP_Post              $post The current post object being displayed.
	 * @return array<string,string> The modified post states array.
	 */
	public function display_post_states( $states, $post ) {
		$link = self::get_link( $post );

		if ( $link ) {
			$link = $this->absolute_url( $link );
			$output = '';
			$output_parts = array(
				'custom' => '<a title="' . __( 'Linked URL', 'page-links-to' ) . '" href="' . esc_url( $link ) . '" class="plt-post-state-link"><span class="dashicons dashicons-admin-links"></span><span class="url"> ' . esc_url( $link ) . '</span></a>',
			);
			/** @var array<string,string> $output_parts */
			$output_parts = apply_filters( 'page_links_to_post_state_parts', $output_parts, $post, $link );
			$output .= '<span class="plt-post-info">' . implode( $output_parts ) . '</span>';
			$states['plt'] = $output;
		}

		return $states;
	}

	/**
	 * Returns the URL of this plugin's directory.
	 *
	 * @return string this plugin's directory URL.
	 */
	public function get_url() {
		return plugin_dir_url( $this->file );
	}

	/**
	 * Returns the filesystem path of this plugin's directory.
	 *
	 * @return string this plugin's directory filesystem path.
	 */
	public function get_path() {
		return plugin_dir_path( $this->file );
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit