File: /home/c1190199/public_html/_alex/wp-content/plugins/cooper-plugins/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.3.5';
/**
* 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() {
if ( ! self::$instance ) {
self::$instance = new self();
}
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 mixed $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( $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;
} else {
$method = $arg;
}
}
return add_action( $hook, array( $this, $method ), $priority, 999 );
}
/**
* 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 $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 ) {
if ( $use_block_editor && self::is_supported_post_type( get_post_type( $post ) ) ) {
add_post_type_support( get_post_type( $post ), '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 $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 ) {
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 ( $affected ) {
$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() ) {
wp_enqueue_script( 'plt-block-editor', $this->get_url() . 'dist/block-editor.js', array( 'wp-edit-post', 'wp-element', 'wp-plugins' ), self::CSS_JS_VERSION, true );
wp_localize_script( 'plt-block-editor', 'pltOptions', [
'supports' => [
'newTab' => self::supports( 'new_tab' ),
],
'panelTitle' => self::get_panel_title(),
]);
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 $actions The current array of actions.
* @param WP_Post $post The current post row being processed.
* @return array The updated array of actions.
*/
public function page_row_actions( $actions, $post ) {
if ( self::get_link( $post ) ) {
$new_actions = array();
$inserted = false;
$original_html = '<a href="' . esc_attr( $this->original_link( $post->ID ) ) . '" class="plt-copy-short-url" data-clipboard-text="' . esc_attr( $this->original_link( $post->ID ) ) . '" 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 ) {
return false;
}
return $meta;
}
/**
* Returns the link for the specified post.
*
* @param WP_Post|int $post a post or post ID.
* @return mixed either a URL or false.
*/
public static function get_link( $post ) {
$post = get_post( $post );
$post_id = empty( $post ) ? null : $post->ID;
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 );
$post_id = empty( $post ) ? null : $post->ID;
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' );
}
}
/**
* Determine whether a post type supports custom links.
*
* @param string $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, array_keys( get_post_types( array(
'show_ui' => true,
) ) ) );
return in_array( $type, $supported_post_types );
}
/**
* Outputs the Page Links To post screen meta box.
*
* @return void
*/
public function meta_box() {
$null = null;
$post = get_post( $null );
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 );
}
public static function supports( $feature = '' ) {
switch( $feature ) {
case 'new_tab':
default:
return 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 ) {
if ( isset( $_REQUEST['_cws_plt_nonce'] ) && wp_verify_nonce( $_REQUEST['_cws_plt_nonce'], 'cws_plt_' . $post_id ) ) {
if ( ( ! isset( $_POST['cws_links_to_choice'] ) || 'custom' == $_POST['cws_links_to_choice'] ) && isset( $_POST['cws_links_to'] ) && strlen( $_POST['cws_links_to'] ) > 0 && $_POST['cws_links_to'] !== 'http://' ) {
$url = self::clean_url( stripslashes( $_POST['cws_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 ) {
$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 The post's original URL.
*/
function original_link( $post = null ) {
$this->replace = false;
$url = get_permalink( $post );
$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 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 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|bool 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 ) {
$link = self::absolute_url( $link );
}
return $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.
$url = set_url_scheme( 'http://' . $_SERVER['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 $_args (Unused) the arguments passed to `wp_list_pages()`.
* @param array $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;
$this_url = esc_url_raw( set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['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 = esc_url( $page_url );
$current_page_id = $page->ID;
}
}
if ( $highlight ) {
$output = preg_replace( '|<li class="([^"]+) current_page_item"|', '<li class="$1"', $output ); // Kill default highlighting.
$output = 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 $items nav menu items.
* @return array modified nav menu items.
*/
public static function wp_nav_menu_objects( $items ) {
$new_items = array();
foreach ( $items as $item ) {
if ( isset( $item->object_id ) && self::get_target( $item->object_id ) ) {
$item->target = '_blank';
}
$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'] ) && 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'] ) ) {
self::dismiss_notice( $_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' );
$post = stripslashes_deep( $_POST );
$title = $post['plt_title'];
$url = $post['plt_url'];
$slug = $post['plt_slug'];
$publish = (bool) $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 );
$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 The list of notice IDs that have been dismissed.
*/
public function get_dismissed_notices() {
return get_option( self::DISMISSED_NOTICES, array() );
}
/**
* 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 = get_option( self::DISMISSED_NOTICES, array() );
return in_array( (int) $id, $dismissed_notices );
}
/**
* 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> <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 method_exists( $current_screen, 'is_block_editor' ) && $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() {
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.
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 “%s” 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();
$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</button></div>';
}
/**
* Adds a GitHub link to the plugin meta.
*
* @param array $links the current array of links.
* @param string $file the current plugin being processed.
* @return array 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 $states The existing post states.
* @param WP_Post $post The current post object being displayed.
* @return array 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>',
);
$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 );
}
}