Page Links To - Version 2.11.0

Version Description

  • Code cleanup
Download this release

Release Info

Developer markjaquith
Plugin Icon wp plugin Page Links To
Version 2.11.0
Comparing to
See all releases

Code changes from version 2.10.4 to 2.11.0

Files changed (3) hide show
  1. lib/wp-stack-plugin.php +0 -24
  2. page-links-to.php +447 -211
  3. readme.txt +4 -1
lib/wp-stack-plugin.php DELETED
@@ -1,24 +0,0 @@
1
- <?php
2
-
3
- // Convenience methods
4
- if ( !class_exists( 'WP_Stack_Plugin' ) ) {
5
- class WP_Stack_Plugin {
6
- public function hook( $hook ) {
7
- $priority = 10;
8
- $method = $this->sanitize_method( $hook );
9
- $args = func_get_args();
10
- unset( $args[0] );
11
- foreach( (array) $args as $arg ) {
12
- if ( is_int( $arg ) )
13
- $priority = $arg;
14
- else
15
- $method = $arg;
16
- }
17
- return add_action( $hook, array( $this, $method ), $priority, 999 );
18
- }
19
-
20
- private function sanitize_method( $method ) {
21
- return str_replace( array( '.', '-' ), array( '_DOT_', '_DASH_' ), $method );
22
- }
23
- }
24
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
page-links-to.php CHANGED
@@ -1,92 +1,166 @@
1
  <?php
2
- /*
3
- Plugin Name: Page Links To
4
- Plugin URI: http://txfx.net/wordpress-plugins/page-links-to/
5
- Description: Allows you to point WordPress pages or posts to a URL of your choosing. Good for setting up navigational links to non-WP sections of your site or to off-site resources.
6
- Version: 2.10.4
7
- Author: Mark Jaquith
8
- Author URI: http://coveredweb.com/
9
- Text Domain: page-links-to
10
- Domain Path: /languages
11
- */
 
 
 
 
12
 
13
- /* Copyright 2005-2017 Mark Jaquith
 
14
 
15
- This program is free software; you can redistribute it and/or modify
16
- it under the terms of the GNU General Public License as published by
17
- the Free Software Foundation; either version 2 of the License, or
18
- (at your option) any later version.
19
 
20
- This program is distributed in the hope that it will be useful,
21
- but WITHOUT ANY WARRANTY; without even the implied warranty of
22
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
- GNU General Public License for more details.
24
 
25
- You should have received a copy of the GNU General Public License
26
- along with this program; if not, write to the Free Software
27
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28
  */
29
 
30
- // Pull in WP Stack plugin library
31
- include( dirname( __FILE__ ) . '/lib/wp-stack-plugin.php' );
32
-
33
- class CWS_PageLinksTo extends WP_Stack_Plugin {
 
 
 
 
 
34
  static $instance;
 
35
  const LINKS_CACHE_KEY = 'plt_cache__links';
36
  const TARGETS_CACHE_KEY = 'plt_cache__targets';
37
  const LINK_META_KEY = '_links_to';
38
  const TARGET_META_KEY = '_links_to_target';
39
  const VERSION_KEY = 'txfx_plt_schema_version';
 
 
 
40
  const FILE = __FILE__;
41
- const CSS_JS_VERSION = '2.10.4';
42
 
 
 
 
 
 
43
  protected $replace = true;
44
 
 
 
 
45
  function __construct() {
46
  self::$instance = $this;
47
  $this->hook( 'init' );
48
  }
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  /**
51
  * Bootstraps the upgrade process and registers all the hooks.
52
  */
53
  function init() {
54
- // Check to see if any of our data needs to be upgraded
55
  $this->maybe_upgrade();
56
 
57
- // Load translation files
58
  load_plugin_textdomain( 'page-links-to', false, basename( dirname( self::FILE ) ) . '/languages' );
59
 
60
- // Register hooks
61
  $this->register_hooks();
62
  }
63
 
64
  /**
65
- * Registers all the hooks
 
 
66
  */
67
  function register_hooks() {
68
- // Hook in to URL generation
69
  $this->hook( 'page_link', 'link', 20 );
70
  $this->hook( 'post_link', 'link', 20 );
71
  $this->hook( 'post_type_link', 'link', 20 );
72
  $this->hook( 'attachment_link', 'link', 20 );
73
 
74
- // Non-standard priority hooks
75
  $this->hook( 'do_meta_boxes', 20 );
76
  $this->hook( 'wp_enqueue_scripts' );
77
 
78
- // Non-standard callback hooks
79
- $this->hook( 'load-post.php', 'load_post' );
 
80
 
81
- // Standard hooks
82
- $this->hook( 'wp_list_pages' );
83
- $this->hook( 'template_redirect' );
84
- $this->hook( 'save_post' );
85
- $this->hook( 'edit_attachment' );
86
  $this->hook( 'wp_nav_menu_objects' );
87
- $this->hook( 'plugin_row_meta' );
 
 
 
 
 
88
 
89
- // Metadata validation grants users editing privileges for our custom fields
90
  register_meta( 'post', self::LINK_META_KEY, null, '__return_true' );
91
  register_meta( 'post', self::TARGET_META_KEY, null, '__return_true' );
92
  }
@@ -104,138 +178,173 @@ class CWS_PageLinksTo extends WP_Stack_Plugin {
104
  $total_affected = 0;
105
  foreach ( array( '', '_target', '_type' ) as $meta_key ) {
106
  $meta_key = 'links_to' . $meta_key;
107
- $affected = $wpdb->update( $wpdb->postmeta, array( 'meta_key' => '_' . $meta_key ), compact( 'meta_key' ) );
 
 
108
  if ( $affected ) {
109
  $total_affected += $affected;
110
  }
111
  }
112
- // Only flush the cache if something changed
113
  if ( $total_affected > 0 ) {
114
  wp_cache_flush();
115
  }
116
  if ( update_option( self::VERSION_KEY, 3 ) ) {
117
- $this->flush_links_cache();
118
- $this->flush_targets_cache();
119
  }
120
  }
121
  }
122
 
123
  /**
124
- * Enqueues front end scripts
125
  */
126
  function wp_enqueue_scripts() {
127
- wp_enqueue_script( 'page-links-to', $this->get_url() . 'js/new-tab.min.js', array(), self::CSS_JS_VERSION, true );
128
  }
129
 
130
  /**
131
- * Returns post ids and meta values that have a given key
132
  *
133
- * @param string $key post meta key
134
- * @return array|false objects with post_id and meta_value properties
135
  */
136
- function meta_by_key( $key ) {
137
  global $wpdb;
 
138
  return $wpdb->get_results( $wpdb->prepare( "SELECT post_id, meta_value FROM $wpdb->postmeta WHERE meta_key = %s", $key ) );
139
  }
140
 
141
  /**
142
- * Returns a single piece of post meta
143
- * @param integer $post_id a post ID
144
- * @param string $key a post meta key
145
- * @return string|false the post meta, or false, if it doesn't exist
 
146
  */
147
- function get_post_meta( $post_id, $key ) {
148
  $meta = get_post_meta( absint( $post_id ), $key, true );
 
149
  if ( '' === $meta ) {
150
  return false;
151
  }
 
152
  return $meta;
153
  }
154
 
155
  /**
156
- * Returns all links for the current site
157
  *
158
- * @return array an array of links, keyed by post ID
159
  */
160
- function get_links() {
161
- if ( false === $links = get_transient( self::LINKS_CACHE_KEY ) ) {
162
- $db_links = $this->meta_by_key( self::LINK_META_KEY );
 
 
163
  $links = array();
 
164
  if ( $db_links ) {
165
  foreach ( $db_links as $link ) {
166
  $links[ intval( $link->post_id ) ] = $link->meta_value;
167
  }
168
  }
 
169
  set_transient( self::LINKS_CACHE_KEY, $links, 10 * 60 );
170
  }
 
171
  return $links;
172
  }
173
 
174
  /**
175
- * Returns the link for the specified post ID
176
  *
177
- * @param integer $post_id a post ID
178
- * @return mixed either a URL or false
179
  */
180
- function get_link( $post_id ) {
181
- return $this->get_post_meta( $post_id, self::LINK_META_KEY );
182
  }
183
 
184
  /**
185
- * Returns all targets for the current site
186
  *
187
- * @return array an array of targets, keyed by post ID
188
  */
189
- function get_targets() {
190
- if ( false === $targets = get_transient( self::TARGETS_CACHE_KEY ) ) {
191
- $db_targets = $this->meta_by_key( self::TARGET_META_KEY );
 
 
192
  $targets = array();
 
193
  if ( $db_targets ) {
194
  foreach ( $db_targets as $target ) {
195
  $targets[ intval( $target->post_id ) ] = true;
196
  }
197
  }
 
198
  set_transient( self::TARGETS_CACHE_KEY, $targets, 10 * 60 );
199
  }
 
200
  return $targets;
201
  }
202
 
203
  /**
204
- * Returns the _blank target status for the specified post ID
205
  *
206
- * @param integer $post_id a post ID
207
- * @return bool whether it should open in a new tab
208
  */
209
- function get_target( $post_id ) {
210
- return (bool) $this->get_post_meta( $post_id, self::TARGET_META_KEY );
211
  }
212
 
213
  /**
214
- * Adds the meta box to the post or page edit screen
215
  *
216
- * @param string $page the name of the current page
217
- * @param string $context the current context
 
218
  */
219
- function do_meta_boxes( $page, $context ) {
220
- // Plugins that use custom post types can use this filter to hide the
221
- // PLT UI in their post type.
222
- $plt_post_types = apply_filters( 'page-links-to-post-types', array_keys( get_post_types( array('show_ui' => true ) ) ) );
223
-
224
- if ( in_array( $page, $plt_post_types ) && 'advanced' === $context ) {
225
- add_meta_box( 'page-links-to', _x( 'Page Links To', 'Meta box title', 'page-links-to'), array( $this, 'meta_box' ), $page, 'advanced', 'low' );
226
  }
227
  }
228
 
229
  /**
230
- * Outputs the Page Links To post screen meta box
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
  */
232
- function meta_box() {
233
  $null = null;
234
  $post = get_post( $null );
235
  echo '<p>';
236
  wp_nonce_field( 'cws_plt_' . $post->ID, '_cws_plt_nonce', false, true );
237
  echo '</p>';
238
- $url = $this->get_link( $post->ID );
239
  if ( ! $url ) {
240
  $linked = false;
241
  $url = '';
@@ -243,120 +352,154 @@ class CWS_PageLinksTo extends WP_Stack_Plugin {
243
  $linked = true;
244
  }
245
  ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
246
  <p><?php _e( 'Point this content to:', 'page-links-to' ); ?></p>
247
- <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>
248
  <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>
249
- <div style="webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin-left: 30px;" id="cws-links-to-custom-section" class="<?php echo ! $linked ? 'hide-if-js' : ''; ?>">
250
- <p><input placeholder="http://" name="cws_links_to" type="text" style="width:75%" id="cws-links-to" value="<?php echo esc_attr( $url ); ?>" /></p>
251
- <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) $this->get_target( $post->ID ) ); ?>> <?php _e( 'Open this link in a new tab', 'page-links-to' ); ?></label></p>
252
  </div>
253
- <script src="<?php echo $this->get_url() . 'js/page-links-to.min.js?v=' . self::CSS_JS_VERSION; ?>"></script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
  <?php
255
  }
256
 
257
  /**
258
- * Saves data on attachment save
259
  *
260
- * @param int $post_id
261
- * @return int the attachment post ID that was passed in
262
  */
263
  function edit_attachment( $post_id ) {
264
  return $this->save_post( $post_id );
265
  }
266
 
267
  /**
268
- * Saves data on post save
269
  *
270
- * @param int $post_id a post ID
271
- * @return int the post ID that was passed in
272
  */
273
- function save_post( $post_id ) {
274
  if ( isset( $_REQUEST['_cws_plt_nonce'] ) && wp_verify_nonce( $_REQUEST['_cws_plt_nonce'], 'cws_plt_' . $post_id ) ) {
275
  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://' ) {
276
- $url = $this->clean_url( stripslashes( $_POST['cws_links_to'] ) );
277
- $this->flush_links_if( $this->set_link( $post_id, $url ) );
278
- if ( isset( $_POST['cws_links_to_new_tab'] ) )
279
- $this->flush_targets_if( $this->set_link_new_tab( $post_id ) );
280
- else
281
- $this->flush_targets_if( $this->set_link_same_tab( $post_id ) );
 
282
  } else {
283
- $this->flush_links_if( $this->delete_link( $post_id ) );
284
  }
285
  }
 
286
  return $post_id;
287
  }
288
 
289
  /**
290
- * Cleans up a URL
291
  *
292
- * @param string $url URL
293
- * @return string cleaned up URL
294
  */
295
- function clean_url( $url ) {
296
  $url = trim( $url );
 
297
  // Starts with 'www.'. Probably a mistake. So add 'http://'.
298
  if ( 0 === strpos( $url, 'www.' ) ) {
299
  $url = 'http://' . $url;
300
  }
 
301
  return $url;
302
  }
303
 
304
  /**
305
- * Have a post point to a custom URL
306
  *
307
- * @param int $post_id post ID
308
- * @param string $url the URL to point the post to
309
- * @return bool whether anything changed
310
  */
311
- function set_link( $post_id, $url ) {
312
- return $this->flush_links_if( (bool) update_post_meta( $post_id, self::LINK_META_KEY, $url ) );
313
  }
314
 
315
  /**
316
- * Tell an custom URL post to open in a new tab
317
  *
318
- * @param int $post_id post ID
319
- * @return bool whether anything changed
320
  */
321
- function set_link_new_tab( $post_id ) {
322
- return $this->flush_targets_if( (bool) update_post_meta( $post_id, self::TARGET_META_KEY, '_blank' ) );
323
  }
324
 
325
  /**
326
- * Tell an custom URL post to open in the same tab
327
  *
328
- * @param int $post_id post ID
329
- * @return bool whether anything changed
330
  */
331
- function set_link_same_tab( $post_id ) {
332
- return $this->flush_targets_if( delete_post_meta( $post_id, self::TARGET_META_KEY ) );
333
  }
334
 
335
  /**
336
- * Discard a custom URL and point a post to its normal URL
337
  *
338
- * @param int $post_id post ID
339
- * @return bool whether the link was deleted
340
  */
341
- function delete_link( $post_id ) {
342
- $return = $this->flush_links_if( delete_post_meta( $post_id, self::LINK_META_KEY ) );
343
- $this->flush_targets_if( delete_post_meta( $post_id, self::TARGET_META_KEY ) );
344
 
345
- // Old, unused data that we can delete on the fly
346
  delete_post_meta( $post_id, '_links_to_type' );
347
 
348
  return $return;
349
  }
350
 
351
  /**
352
- * Flushes the links transient cache if the condition is true
353
  *
354
- * @param bool $condition whether to proceed with the flush
355
- * @return bool whether the flush happened
356
  */
357
- function flush_links_if( $condition ) {
358
  if ( $condition ) {
359
- $this->flush_links_cache();
360
  return true;
361
  } else {
362
  return false;
@@ -364,14 +507,14 @@ class CWS_PageLinksTo extends WP_Stack_Plugin {
364
  }
365
 
366
  /**
367
- * Flushes the targets transient cache if the condition is true
368
  *
369
- * @param bool $condition whether to proceed with the flush
370
- * @return bool whether the flush happened
371
  */
372
- function flush_targets_if( $condition ) {
373
  if ( $condition ) {
374
- $this->flush_targets_cache();
375
  return true;
376
  } else {
377
  return false;
@@ -379,43 +522,39 @@ class CWS_PageLinksTo extends WP_Stack_Plugin {
379
  }
380
 
381
  /**
382
- * Flushes the links transient cache
383
  *
384
- * @param bool $condition whether to flush the cache
385
- * @param string $type which cache to flush
386
- * @return bool whether the flush attempt occurred
387
  */
388
- function flush_links_cache() {
389
- delete_transient( self::LINKS_CACHE_KEY );
390
  }
391
 
392
  /**
393
- * Flushes the targets transient cache
394
  *
395
- * @param bool $condition whether to flush the cache
396
- * @param string $type which cache to flush
397
- * @return bool whether the flush attempt occurred
398
  */
399
- function flush_targets_cache() {
400
- delete_transient( self::TARGETS_CACHE_KEY );
401
  }
402
 
403
  /**
404
- * Filter for Post links
405
  *
406
- * @param string $link the URL for the post or page
407
- * @param int|WP_Post $post post ID or object
408
- * @return string output URL
409
  */
410
- function link( $link, $post ) {
411
  if ( $this->replace ) {
412
  $post = get_post( $post );
413
 
414
- $meta_link = $this->get_link( $post->ID );
415
 
416
  if ( $meta_link ) {
417
  $link = esc_url( $meta_link );
418
- if ( ! is_admin() && $this->get_target( $post->ID ) ) {
419
  $link .= '#new_tab';
420
  }
421
  }
@@ -439,10 +578,12 @@ class CWS_PageLinksTo extends WP_Stack_Plugin {
439
  }
440
 
441
  /**
442
- * Performs a redirect
 
 
443
  */
444
  function template_redirect() {
445
- $link = $this->get_redirect();
446
 
447
  if ( $link ) {
448
  wp_redirect( $link, 301 );
@@ -451,25 +592,25 @@ class CWS_PageLinksTo extends WP_Stack_Plugin {
451
  }
452
 
453
  /**
454
- * gets the redirection URL
455
  *
456
- * @return string|bool the redirection URL, or false
457
  */
458
- function get_redirect() {
459
  if ( ! is_singular() || ! get_queried_object_id() ) {
460
  return false;
461
  }
462
 
463
- $link = $this->get_link( get_queried_object_id() );
464
 
465
- // Convert server- and protocol-relative URLs to absolute URLs
466
- if ( "/" === $link[0] ) {
467
- // Protocol-relative
468
- if ( "/" === $link[1] ) {
469
  $link = set_url_scheme( 'http:' . $link );
470
  } else {
471
- // Host-relative
472
- $link = set_url_scheme( 'http://' . $_SERVER["HTTP_HOST"] . $link );
473
  }
474
  }
475
 
@@ -481,20 +622,22 @@ class CWS_PageLinksTo extends WP_Stack_Plugin {
481
  }
482
 
483
  /**
484
- * Filters the list of pages to alter the links and targets
485
  *
486
- * @param string $pages the wp_list_pages() HTML block from WordPress
487
- * @return string the modified HTML block
488
  */
489
  function wp_list_pages( $pages ) {
490
  $highlight = false;
491
 
492
- // We use the "fetch all" versions here, because the pages might not be queried here
493
- $links = $this->get_links();
494
- $targets = $this->get_targets();
495
  $targets_by_url = array();
496
- foreach( array_keys( $targets ) as $targeted_id )
497
- $targets_by_url[$links[$targeted_id]] = true;
 
 
498
 
499
  if ( ! $links ) {
500
  return $pages;
@@ -503,9 +646,10 @@ class CWS_PageLinksTo extends WP_Stack_Plugin {
503
  $this_url = ( is_ssl() ? 'https' : 'http' ) . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
504
 
505
  foreach ( (array) $links as $id => $page ) {
506
- if ( isset( $targets_by_url[$page] ) ) {
507
  $page .= '#new_tab';
508
  }
 
509
  if ( str_replace( 'http://www.', 'http://', $this_url ) === str_replace( 'http://www.', 'http://', $page ) || ( is_home() && str_replace( 'http://www.', 'http://', trailingslashit( get_bloginfo( 'url' ) ) ) === str_replace( 'http://www.', 'http://', trailingslashit( $page ) ) ) ) {
510
  $highlight = true;
511
  $current_page = esc_url( $page );
@@ -520,53 +664,145 @@ class CWS_PageLinksTo extends WP_Stack_Plugin {
520
  }
521
 
522
  if ( $highlight ) {
523
- $pages = preg_replace( '| class="([^"]+)current_page_item"|', ' class="$1"', $pages ); // Kill default highlighting
524
  $pages = preg_replace( '|<li class="([^"]+)"><a href="' . preg_quote( $current_page ) . '"|', '<li class="$1 current_page_item"><a href="' . $current_page . '"', $pages );
525
  }
 
526
  return $pages;
527
  }
528
 
529
  /**
530
- * Filters nav menu objects and adds target=_blank to the ones that need it
531
  *
532
- * @param array $items nav menu items
533
- * @return array modified nav menu items
534
  */
535
- function wp_nav_menu_objects( $items ) {
536
  $new_items = array();
 
537
  foreach ( $items as $item ) {
538
- if ( isset( $item->object_id ) && $this->get_target( $item->object_id ) ) {
539
  $item->target = '_blank';
540
  }
 
541
  $new_items[] = $item;
542
  }
 
543
  return $new_items;
544
  }
545
 
546
  /**
547
- * Hooks in as a post is being loaded for editing and conditionally adds a notice
 
 
548
  */
549
- function load_post() {
550
- if ( isset( $_GET['post'] ) && $this->get_link( (int) $_GET['post'] ) ) {
551
  $this->hook( 'admin_notices', 'notify_of_external_link' );
552
  }
553
  }
554
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
555
  /**
556
- * Outputs a notice that the current post item is pointed to a custom URL
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
557
  */
558
- function notify_of_external_link() {
559
- ?><div class="updated"><p><?php _e( '<strong>Note</strong>: This content is pointing to a custom URL. Use the &#8220;Page Links To&#8221; box to change this behavior.', 'page-links-to' ); ?></p></div><?php
 
 
560
  }
561
 
562
  /**
563
- * Adds a GitHub link to the plugin meta
564
  *
565
- * @param array $links the current array of links
566
- * @param string $file the current plugin being processed
567
- * @return array the modified array of links
568
  */
569
- function plugin_row_meta( $links, $file ) {
570
  if ( $file === plugin_basename( self::FILE ) ) {
571
  return array_merge(
572
  $links,
@@ -578,25 +814,25 @@ class CWS_PageLinksTo extends WP_Stack_Plugin {
578
  }
579
 
580
  /**
581
- * Returns the URL of this plugin's directory
582
  *
583
- * @return string this plugin's directory URL
584
  */
585
- public function get_url() {
586
  return plugin_dir_url( self::FILE );
587
  }
588
 
589
  /**
590
- * Returns the filesystem path of this plugin's directory
591
  *
592
- * @return string this plugin's directory filesystem path
593
  */
594
- public function get_path() {
595
  return plugin_dir_path( self::FILE );
596
  }
597
  }
598
 
599
- // Bootstrap everything
600
  new CWS_PageLinksTo;
601
 
602
  /**
@@ -606,5 +842,5 @@ new CWS_PageLinksTo;
606
  * @return string The post's original URL.
607
  */
608
  function plt_get_original_permalink( $post = null ) {
609
- return CWS_PageLinksTo::$instance->original_link( $post );
610
  }
1
  <?php
2
+ /**
3
+ * The Page Links To plugin class.
4
+ *
5
+ * @package PageLinks
6
+ *
7
+ * Plugin Name: Page Links To
8
+ * Plugin URI: http://txfx.net/wordpress-plugins/page-links-to/
9
+ * Description: Allows you to point WordPress pages or posts to a URL of your choosing. Good for setting up navigational links to non-WP sections of your site or to off-site resources.
10
+ * Version: 2.11.0
11
+ * Author: Mark Jaquith
12
+ * Author URI: https://coveredweb.com/
13
+ * Text Domain: page-links-to
14
+ * Domain Path: /languages
15
+ */
16
 
17
+ /*
18
+ Copyright 2005-2018 Mark Jaquith
19
 
20
+ This program is free software; you can redistribute it and/or modify
21
+ it under the terms of the GNU General Public License as published by
22
+ the Free Software Foundation; either version 2 of the License, or
23
+ (at your option) any later version.
24
 
25
+ This program is distributed in the hope that it will be useful,
26
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
27
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28
+ GNU General Public License for more details.
29
 
30
+ You should have received a copy of the GNU General Public License
31
+ along with this program; if not, write to the Free Software
32
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33
  */
34
 
35
+ /**
36
+ * The Page Links To class.
37
+ */
38
+ class CWS_PageLinksTo {
39
+ /**
40
+ * The class instance.
41
+ *
42
+ * @var CWS_PageLinksTo
43
+ */
44
  static $instance;
45
+
46
  const LINKS_CACHE_KEY = 'plt_cache__links';
47
  const TARGETS_CACHE_KEY = 'plt_cache__targets';
48
  const LINK_META_KEY = '_links_to';
49
  const TARGET_META_KEY = '_links_to_target';
50
  const VERSION_KEY = 'txfx_plt_schema_version';
51
+ const DISMISSED_NOTICES = 'page_links_dismissed_options';
52
+ const MESSAGE_ID = 3;
53
+ const SURVEY_URL = 'https://goo.gl/forms/8sTKH0LjPCCqBlrG2';
54
  const FILE = __FILE__;
55
+ const CSS_JS_VERSION = '2.11.0';
56
 
57
+ /**
58
+ * Whether to replace WP links with their specified URLs.
59
+ *
60
+ * @var bool
61
+ */
62
  protected $replace = true;
63
 
64
+ /**
65
+ * Class constructor. Adds init hook.
66
+ */
67
  function __construct() {
68
  self::$instance = $this;
69
  $this->hook( 'init' );
70
  }
71
 
72
+ /**
73
+ * Get the plugin instance.
74
+ *
75
+ * @return CWS_PageLinksTo The plugin class instance.
76
+ */
77
+ public static function get_instance() {
78
+ if ( ! self::$instance ) {
79
+ self::$instance = $this;
80
+ }
81
+
82
+ return self::$instance;
83
+ }
84
+
85
+ /**
86
+ * Add a WordPress hook (action/filter).
87
+ *
88
+ * @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).
89
+ */
90
+ public function hook( $hook ) {
91
+ $priority = 10;
92
+ $method = self::sanitize_method( $hook );
93
+ $args = func_get_args();
94
+ unset( $args[0] );
95
+ foreach ( (array) $args as $arg ) {
96
+ if ( is_int( $arg ) ) {
97
+ $priority = $arg;
98
+ } else {
99
+ $method = $arg;
100
+ }
101
+ }
102
+
103
+ return add_action( $hook, [ $this, $method ], $priority, 999 );
104
+ }
105
+
106
+ /**
107
+ * Sanitizes method names with bad characters.
108
+ *
109
+ * @param string $method The raw method name.
110
+ * @return string The sanitized method name.
111
+ */
112
+ private static function sanitize_method( $method ) {
113
+ return str_replace( [ '.', '-' ], [ '_DOT_', '_DASH_' ], $method );
114
+ }
115
+
116
  /**
117
  * Bootstraps the upgrade process and registers all the hooks.
118
  */
119
  function init() {
120
+ // Check to see if any of our data needs to be upgraded.
121
  $this->maybe_upgrade();
122
 
123
+ // Load translation files.
124
  load_plugin_textdomain( 'page-links-to', false, basename( dirname( self::FILE ) ) . '/languages' );
125
 
126
+ // Register hooks.
127
  $this->register_hooks();
128
  }
129
 
130
  /**
131
+ * Registers all the hooks.
132
+ *
133
+ * @return void
134
  */
135
  function register_hooks() {
136
+ // Hook in to URL generation.
137
  $this->hook( 'page_link', 'link', 20 );
138
  $this->hook( 'post_link', 'link', 20 );
139
  $this->hook( 'post_type_link', 'link', 20 );
140
  $this->hook( 'attachment_link', 'link', 20 );
141
 
142
+ // Non-standard priority hooks.
143
  $this->hook( 'do_meta_boxes', 20 );
144
  $this->hook( 'wp_enqueue_scripts' );
145
 
146
+ // Non-standard callback hooks.
147
+ $this->hook( 'load-post.php', 'load_post' );
148
+ $this->hook( 'wp_ajax_plt_dismiss_notice', 'ajax_dismiss_notice' );
149
 
150
+ // Standard hooks.
151
+ $this->hook( 'wp_list_pages' );
152
+ $this->hook( 'template_redirect' );
153
+ $this->hook( 'save_post' );
154
+ $this->hook( 'edit_attachment' );
155
  $this->hook( 'wp_nav_menu_objects' );
156
+ $this->hook( 'plugin_row_meta' );
157
+
158
+ // Notices.
159
+ if ( self::should_display_message() ) {
160
+ $this->hook( 'admin_notices', 'notify_generic' );
161
+ }
162
 
163
+ // Metadata validation grants users editing privileges for our custom fields.
164
  register_meta( 'post', self::LINK_META_KEY, null, '__return_true' );
165
  register_meta( 'post', self::TARGET_META_KEY, null, '__return_true' );
166
  }
178
  $total_affected = 0;
179
  foreach ( array( '', '_target', '_type' ) as $meta_key ) {
180
  $meta_key = 'links_to' . $meta_key;
181
+ $affected = $wpdb->update( $wpdb->postmeta, array(
182
+ 'meta_key' => '_' . $meta_key,
183
+ ), compact( 'meta_key' ) );
184
  if ( $affected ) {
185
  $total_affected += $affected;
186
  }
187
  }
188
+ // Only flush the cache if something changed.
189
  if ( $total_affected > 0 ) {
190
  wp_cache_flush();
191
  }
192
  if ( update_option( self::VERSION_KEY, 3 ) ) {
193
+ self::flush_links_cache();
194
+ self::flush_targets_cache();
195
  }
196
  }
197
  }
198
 
199
  /**
200
+ * Enqueues frontend scripts.
201
  */
202
  function wp_enqueue_scripts() {
203
+ wp_enqueue_script( 'page-links-to', self::get_url() . 'js/new-tab.min.js', array(), self::CSS_JS_VERSION, true );
204
  }
205
 
206
  /**
207
+ * Returns post ids and meta values that have a given key.
208
  *
209
+ * @param string $key post meta key.
210
+ * @return array|false objects with post_id and meta_value properties.
211
  */
212
+ public static function meta_by_key( $key ) {
213
  global $wpdb;
214
+
215
  return $wpdb->get_results( $wpdb->prepare( "SELECT post_id, meta_value FROM $wpdb->postmeta WHERE meta_key = %s", $key ) );
216
  }
217
 
218
  /**
219
+ * Returns a single piece of post meta.
220
+ *
221
+ * @param integer $post_id a post ID.
222
+ * @param string $key a post meta key.
223
+ * @return string|false the post meta, or false, if it doesn't exist.
224
  */
225
+ public static function get_post_meta( $post_id, $key ) {
226
  $meta = get_post_meta( absint( $post_id ), $key, true );
227
+
228
  if ( '' === $meta ) {
229
  return false;
230
  }
231
+
232
  return $meta;
233
  }
234
 
235
  /**
236
+ * Returns all links for the current site.
237
  *
238
+ * @return array an array of links, keyed by post ID.
239
  */
240
+ public static function get_links() {
241
+ $links = get_transient( self::LINKS_CACHE_KEY );
242
+
243
+ if ( false === $links ) {
244
+ $db_links = self::meta_by_key( self::LINK_META_KEY );
245
  $links = array();
246
+
247
  if ( $db_links ) {
248
  foreach ( $db_links as $link ) {
249
  $links[ intval( $link->post_id ) ] = $link->meta_value;
250
  }
251
  }
252
+
253
  set_transient( self::LINKS_CACHE_KEY, $links, 10 * 60 );
254
  }
255
+
256
  return $links;
257
  }
258
 
259
  /**
260
+ * Returns the link for the specified post ID.
261
  *
262
+ * @param integer $post_id a post ID.
263
+ * @return mixed either a URL or false.
264
  */
265
+ public static function get_link( $post_id ) {
266
+ return self::get_post_meta( $post_id, self::LINK_META_KEY );
267
  }
268
 
269
  /**
270
+ * Returns all targets for the current site.
271
  *
272
+ * @return array an array of targets, keyed by post ID.
273
  */
274
+ public static function get_targets() {
275
+ $targets = get_transient( self::TARGETS_CACHE_KEY );
276
+
277
+ if ( false === $targets ) {
278
+ $db_targets = self::meta_by_key( self::TARGET_META_KEY );
279
  $targets = array();
280
+
281
  if ( $db_targets ) {
282
  foreach ( $db_targets as $target ) {
283
  $targets[ intval( $target->post_id ) ] = true;
284
  }
285
  }
286
+
287
  set_transient( self::TARGETS_CACHE_KEY, $targets, 10 * 60 );
288
  }
289
+
290
  return $targets;
291
  }
292
 
293
  /**
294
+ * Returns the _blank target status for the specified post ID.
295
  *
296
+ * @param integer $post_id a post ID.
297
+ * @return bool whether it should open in a new tab.
298
  */
299
+ public static function get_target( $post_id ) {
300
+ return (bool) self::get_post_meta( $post_id, self::TARGET_META_KEY );
301
  }
302
 
303
  /**
304
+ * Adds the meta box to the post or page edit screen.
305
  *
306
+ * @param string $page the name of the current page.
307
+ * @param string $context the current context.
308
+ * @return void
309
  */
310
+ public function do_meta_boxes( $page, $context ) {
311
+ if ( self::is_supported_post_type( $page ) && 'advanced' === $context ) {
312
+ add_meta_box( 'page-links-to', _x( 'Page Links To', 'Meta box title', 'page-links-to' ), array( $this, 'meta_box' ), $page, 'advanced', 'low' );
 
 
 
 
313
  }
314
  }
315
 
316
  /**
317
+ * Determine whether a post type supports custom links.
318
+ *
319
+ * @param string $type The post type to check.
320
+ * @return bool Whether this post type supports custom links.
321
+ */
322
+ public static function is_supported_post_type( $type ) {
323
+ /*
324
+ Plugins that use custom post types can use this filter to hide the
325
+ PLT UI in their post type.
326
+ */
327
+ $hook = 'page-links-to-post-types';
328
+
329
+ $supported_post_types = (array) apply_filters( $hook, array_keys( get_post_types( array(
330
+ 'show_ui' => true,
331
+ ) ) ) );
332
+
333
+ return in_array( $type, $supported_post_types );
334
+ }
335
+
336
+ /**
337
+ * Outputs the Page Links To post screen meta box.
338
+ *
339
+ * @return void
340
  */
341
+ public static function meta_box() {
342
  $null = null;
343
  $post = get_post( $null );
344
  echo '<p>';
345
  wp_nonce_field( 'cws_plt_' . $post->ID, '_cws_plt_nonce', false, true );
346
  echo '</p>';
347
+ $url = self::get_link( $post->ID );
348
  if ( ! $url ) {
349
  $linked = false;
350
  $url = '';
352
  $linked = true;
353
  }
354
  ?>
355
+ <style>
356
+ #cws-links-to-custom-section {
357
+ webkit-box-sizing: border-box;
358
+ -moz-box-sizing: border-box;
359
+ box-sizing: border-box;
360
+ margin-left: 30px;
361
+ }
362
+
363
+ #cws-links-to {
364
+ width: 75%;
365
+ }
366
+ </style>
367
+
368
  <p><?php _e( 'Point this content to:', 'page-links-to' ); ?></p>
369
+ <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>
370
  <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>
371
+ <div id="cws-links-to-custom-section" class="<?php echo ! $linked ? 'hide-if-js' : ''; ?>">
372
+ <p><input placeholder="http://" name="cws_links_to" type="text" id="cws-links-to" value="<?php echo esc_attr( $url ); ?>" /></p>
373
+ <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>
374
  </div>
375
+
376
+ <?php if ( true ) { ?>
377
+ <style>
378
+ #cws-links-to-survey {
379
+ border: 1px solid #eee;
380
+ }
381
+
382
+ #cws-links-to-survey h3, #cws-links-to-survey p {
383
+ margin: 1em;
384
+ }
385
+ </style>
386
+ <div id="cws-links-to-survey">
387
+ <h3>New Features Coming Soon!</h3>
388
+ <p>Do you have a minute? <a target="_blank" href="<?php echo self::SURVEY_URL; ?>">Please take this quick survey</a> and help me decide what features to build next!</p>
389
+ </div>
390
+ <?php } ?>
391
+
392
+ <script src="<?php echo self::get_url() . 'js/page-links-to.min.js?v=' . self::CSS_JS_VERSION; ?>"></script>
393
  <?php
394
  }
395
 
396
  /**
397
+ * Saves data on attachment save.
398
  *
399
+ * @param int $post_id The ID of the post being saved.
400
+ * @return int the attachment post ID that was passed in.
401
  */
402
  function edit_attachment( $post_id ) {
403
  return $this->save_post( $post_id );
404
  }
405
 
406
  /**
407
+ * Saves data on post save.
408
  *
409
+ * @param int $post_id a post ID.
410
+ * @return int the post ID that was passed in.
411
  */
412
+ public static function save_post( $post_id ) {
413
  if ( isset( $_REQUEST['_cws_plt_nonce'] ) && wp_verify_nonce( $_REQUEST['_cws_plt_nonce'], 'cws_plt_' . $post_id ) ) {
414
  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://' ) {
415
+ $url = self::clean_url( stripslashes( $_POST['cws_links_to'] ) );
416
+ self::flush_links_if( self::set_link( $post_id, $url ) );
417
+ if ( isset( $_POST['cws_links_to_new_tab'] ) ) {
418
+ self::flush_targets_if( self::set_link_new_tab( $post_id ) );
419
+ } else {
420
+ self::flush_targets_if( self::set_link_same_tab( $post_id ) );
421
+ }
422
  } else {
423
+ self::flush_links_if( self::delete_link( $post_id ) );
424
  }
425
  }
426
+
427
  return $post_id;
428
  }
429
 
430
  /**
431
+ * Cleans up a URL.
432
  *
433
+ * @param string $url URL.
434
+ * @return string cleaned up URL.
435
  */
436
+ public static function clean_url( $url ) {
437
  $url = trim( $url );
438
+
439
  // Starts with 'www.'. Probably a mistake. So add 'http://'.
440
  if ( 0 === strpos( $url, 'www.' ) ) {
441
  $url = 'http://' . $url;
442
  }
443
+
444
  return $url;
445
  }
446
 
447
  /**
448
+ * Have a post point to a custom URL.
449
  *
450
+ * @param int $post_id post ID.
451
+ * @param string $url the URL to point the post to.
452
+ * @return bool whether anything changed.
453
  */
454
+ public static function set_link( $post_id, $url ) {
455
+ return self::flush_links_if( (bool) update_post_meta( $post_id, self::LINK_META_KEY, $url ) );
456
  }
457
 
458
  /**
459
+ * Tell an custom URL post to open in a new tab.
460
  *
461
+ * @param int $post_id post ID.
462
+ * @return bool whether anything changed.
463
  */
464
+ public static function set_link_new_tab( $post_id ) {
465
+ return self::flush_targets_if( (bool) update_post_meta( $post_id, self::TARGET_META_KEY, '_blank' ) );
466
  }
467
 
468
  /**
469
+ * Tell an custom URL post to open in the same tab.
470
  *
471
+ * @param int $post_id post ID.
472
+ * @return bool whether anything changed.
473
  */
474
+ public static function set_link_same_tab( $post_id ) {
475
+ return self::flush_targets_if( delete_post_meta( $post_id, self::TARGET_META_KEY ) );
476
  }
477
 
478
  /**
479
+ * Discard a custom URL and point a post to its normal URL.
480
  *
481
+ * @param int $post_id post ID.
482
+ * @return bool whether the link was deleted.
483
  */
484
+ public static function delete_link( $post_id ) {
485
+ $return = self::flush_links_if( delete_post_meta( $post_id, self::LINK_META_KEY ) );
486
+ self::flush_targets_if( delete_post_meta( $post_id, self::TARGET_META_KEY ) );
487
 
488
+ // Old, unused data that we can delete on the fly.
489
  delete_post_meta( $post_id, '_links_to_type' );
490
 
491
  return $return;
492
  }
493
 
494
  /**
495
+ * Flushes the links transient cache if the condition is true.
496
  *
497
+ * @param bool $condition whether to proceed with the flush.
498
+ * @return bool whether the flush happened.
499
  */
500
+ public static function flush_links_if( $condition ) {
501
  if ( $condition ) {
502
+ self::flush_links_cache();
503
  return true;
504
  } else {
505
  return false;
507
  }
508
 
509
  /**
510
+ * Flushes the targets transient cache if the condition is true.
511
  *
512
+ * @param bool $condition whether to proceed with the flush.
513
+ * @return bool whether the flush happened.
514
  */
515
+ public static function flush_targets_if( $condition ) {
516
  if ( $condition ) {
517
+ self::flush_targets_cache();
518
  return true;
519
  } else {
520
  return false;
522
  }
523
 
524
  /**
525
+ * Flushes the links transient cache.
526
  *
527
+ * @return bool whether the flush attempt occurred.
 
 
528
  */
529
+ public static function flush_links_cache() {
530
+ return delete_transient( self::LINKS_CACHE_KEY );
531
  }
532
 
533
  /**
534
+ * Flushes the targets transient cache.
535
  *
536
+ * @return bool whether the flush attempt occurred.
 
 
537
  */
538
+ public static function flush_targets_cache() {
539
+ return delete_transient( self::TARGETS_CACHE_KEY );
540
  }
541
 
542
  /**
543
+ * Filter for post links.
544
  *
545
+ * @param string $link the URL for the post or page.
546
+ * @param int|WP_Post $post post ID or object.
547
+ * @return string output URL.
548
  */
549
+ public function link( $link, $post ) {
550
  if ( $this->replace ) {
551
  $post = get_post( $post );
552
 
553
+ $meta_link = self::get_link( $post->ID );
554
 
555
  if ( $meta_link ) {
556
  $link = esc_url( $meta_link );
557
+ if ( ! is_admin() && self::get_target( $post->ID ) ) {
558
  $link .= '#new_tab';
559
  }
560
  }
578
  }
579
 
580
  /**
581
+ * Performs a redirect.
582
+ *
583
+ * @return void
584
  */
585
  function template_redirect() {
586
+ $link = self::get_redirect();
587
 
588
  if ( $link ) {
589
  wp_redirect( $link, 301 );
592
  }
593
 
594
  /**
595
+ * Gets the redirection URL.
596
  *
597
+ * @return string|bool the redirection URL, or false.
598
  */
599
+ public static function get_redirect() {
600
  if ( ! is_singular() || ! get_queried_object_id() ) {
601
  return false;
602
  }
603
 
604
+ $link = self::get_link( get_queried_object_id() );
605
 
606
+ // Convert server- and protocol-relative URLs to absolute URLs.
607
+ if ( '/' === $link[0] ) {
608
+ // Protocol-relative.
609
+ if ( '/' === $link[1] ) {
610
  $link = set_url_scheme( 'http:' . $link );
611
  } else {
612
+ // Host-relative.
613
+ $link = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $link );
614
  }
615
  }
616
 
622
  }
623
 
624
  /**
625
+ * Filters the list of pages to alter the links and targets.
626
  *
627
+ * @param string $pages the wp_list_pages() HTML block from WordPress.
628
+ * @return string the modified HTML block.
629
  */
630
  function wp_list_pages( $pages ) {
631
  $highlight = false;
632
 
633
+ // We use the "fetch all" versions here, because the pages might not be queried here.
634
+ $links = self::get_links();
635
+ $targets = self::get_targets();
636
  $targets_by_url = array();
637
+
638
+ foreach ( array_keys( $targets ) as $targeted_id ) {
639
+ $targets_by_url[ $links[ $targeted_id ] ] = true;
640
+ }
641
 
642
  if ( ! $links ) {
643
  return $pages;
646
  $this_url = ( is_ssl() ? 'https' : 'http' ) . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
647
 
648
  foreach ( (array) $links as $id => $page ) {
649
+ if ( isset( $targets_by_url[ $page ] ) ) {
650
  $page .= '#new_tab';
651
  }
652
+
653
  if ( str_replace( 'http://www.', 'http://', $this_url ) === str_replace( 'http://www.', 'http://', $page ) || ( is_home() && str_replace( 'http://www.', 'http://', trailingslashit( get_bloginfo( 'url' ) ) ) === str_replace( 'http://www.', 'http://', trailingslashit( $page ) ) ) ) {
654
  $highlight = true;
655
  $current_page = esc_url( $page );
664
  }
665
 
666
  if ( $highlight ) {
667
+ $pages = preg_replace( '| class="([^"]+)current_page_item"|', ' class="$1"', $pages ); // Kill default highlighting.
668
  $pages = preg_replace( '|<li class="([^"]+)"><a href="' . preg_quote( $current_page ) . '"|', '<li class="$1 current_page_item"><a href="' . $current_page . '"', $pages );
669
  }
670
+
671
  return $pages;
672
  }
673
 
674
  /**
675
+ * Filters nav menu objects and adds target=_blank to the ones that need it.
676
  *
677
+ * @param array $items nav menu items.
678
+ * @return array modified nav menu items.
679
  */
680
+ public static function wp_nav_menu_objects( $items ) {
681
  $new_items = array();
682
+
683
  foreach ( $items as $item ) {
684
+ if ( isset( $item->object_id ) && self::get_target( $item->object_id ) ) {
685
  $item->target = '_blank';
686
  }
687
+
688
  $new_items[] = $item;
689
  }
690
+
691
  return $new_items;
692
  }
693
 
694
  /**
695
+ * Hooks in as a post is being loaded for editing and conditionally adds a notice.
696
+ *
697
+ * @return void
698
  */
699
+ public function load_post() {
700
+ if ( isset( $_GET['post'] ) && self::get_link( (int) $_GET['post'] ) ) {
701
  $this->hook( 'admin_notices', 'notify_of_external_link' );
702
  }
703
  }
704
 
705
+ public static function ajax_dismiss_notice() {
706
+ if ( isset( $_GET['plt_notice'] ) ) {
707
+ self::dismiss_notice( $_GET['plt_notice'] );
708
+ }
709
+ }
710
+
711
+ /**
712
+ * Whether a message should be displayed.
713
+ *
714
+ * @return bool Whether to display the message.
715
+ */
716
+ public static function should_display_message() {
717
+ $start_time = 1529283010;
718
+ $end_time = $start_time + WEEK_IN_SECONDS;
719
+
720
+ return time() > $start_time && time() < $end_time && ! self::has_dismissed_notice( self::MESSAGE_ID ) && current_user_can( 'manage_options' );
721
+ }
722
+
723
+ /**
724
+ * Return the notices which have been dismissed.
725
+ *
726
+ * @return array The list of notice IDs that have been dismissed.
727
+ */
728
+ public function get_dismissed_notices() {
729
+ return get_option( self::DISMISSED_NOTICES, array() );
730
+ }
731
+
732
  /**
733
+ * Mark a notice as dismissed.
734
+ *
735
+ * @param int $id The notice ID to dismiss.
736
+ * @return void
737
+ */
738
+ public static function dismiss_notice( $id ) {
739
+ $notices = self::get_dismissed_notices();
740
+ $notices[] = (int) $id;
741
+
742
+ $notices = array_unique( $notices );
743
+ update_option( self::DISMISSED_NOTICES, $notices );
744
+ }
745
+
746
+ /**
747
+ * Whether anyone on this site has dismissed the given notice.
748
+ *
749
+ * @param int $id The ID of the notice.
750
+ * @return bool Whether anyone has dismissed it.
751
+ */
752
+ public static function has_dismissed_notice( $id ) {
753
+ $dismissed_notices = get_option( self::DISMISSED_NOTICES, array() );
754
+
755
+ return in_array( (int) $id, $dismissed_notices );
756
+ }
757
+
758
+ /**
759
+ * Output the generic notice.
760
+ *
761
+ * @return void
762
+ */
763
+ public static function notify_generic() {
764
+ ?>
765
+ <div id="page-links-to-notification" class="notice updated is-dismissible"><?php _e( '<h3>Page Links To</h3><p>Do you have a minute? <a target="_blank" href="' . self::SURVEY_URL . '" class="plt-dismiss">Please take this quick survey</a> and help me decide what features to build next!</p><p><a class="button plt-dismiss" target="_blank" href="' . self::SURVEY_URL . '">Take the survey</a>&nbsp;&nbsp;<small><a href="#" class="plt-dismiss">No thanks</a></small></p>', 'page-links-to' ); ?></div>
766
+ <script>
767
+ (function($){
768
+ var $plt = $('#page-links-to-notification');
769
+ $plt
770
+ .on('click', '.notice-dismiss', function(e){
771
+ $.ajax( ajaxurl, {
772
+ type: 'GET',
773
+ data: {
774
+ action: 'plt_dismiss_notice',
775
+ plt_notice: <?php echo json_encode( self::MESSAGE_ID ); ?>
776
+ }
777
+ });
778
+ })
779
+ .on('click', '.plt-dismiss', function(e){
780
+ $(this).parents('.notice').first().find('.notice-dismiss').click();
781
+ });
782
+ })(jQuery);
783
+ </script>
784
+ <?php
785
+ }
786
+
787
+ /**
788
+ * Outputs a notice that the current post item is pointed to a custom URL.
789
+ *
790
+ * @return void
791
  */
792
+ public static function notify_of_external_link() {
793
+ ?>
794
+ <div class="notice updated"><p><?php _e( '<strong>Note</strong>: This content is pointing to a custom URL. Use the &#8220;Page Links To&#8221; box to change this behavior.', 'page-links-to' ); ?></p></div>
795
+ <?php
796
  }
797
 
798
  /**
799
+ * Adds a GitHub link to the plugin meta.
800
  *
801
+ * @param array $links the current array of links.
802
+ * @param string $file the current plugin being processed.
803
+ * @return array the modified array of links.
804
  */
805
+ public static function plugin_row_meta( $links, $file ) {
806
  if ( $file === plugin_basename( self::FILE ) ) {
807
  return array_merge(
808
  $links,
814
  }
815
 
816
  /**
817
+ * Returns the URL of this plugin's directory.
818
  *
819
+ * @return string this plugin's directory URL.
820
  */
821
+ public static function get_url() {
822
  return plugin_dir_url( self::FILE );
823
  }
824
 
825
  /**
826
+ * Returns the filesystem path of this plugin's directory.
827
  *
828
+ * @return string this plugin's directory filesystem path.
829
  */
830
+ public static function get_path() {
831
  return plugin_dir_path( self::FILE );
832
  }
833
  }
834
 
835
+ // Bootstrap everything.
836
  new CWS_PageLinksTo;
837
 
838
  /**
842
  * @return string The post's original URL.
843
  */
844
  function plt_get_original_permalink( $post = null ) {
845
+ return CWS_PageLinksTo::get_instance()->original_link( $post );
846
  }
readme.txt CHANGED
@@ -5,7 +5,7 @@ Donate link: http://txfx.net/wordpress-plugins/donate
5
  Tags: page, redirect, link, external link, repoint
6
  Requires at least: 4.8
7
  Tested up to: 4.9.6
8
- Stable tag: 2.10.4
9
 
10
  Lets you make a WordPress page (or port or other content type) link to a URL of your choosing (on your site, or on another site), instead of its normal WordPress URL.
11
 
@@ -64,6 +64,9 @@ You can contribute (or report bugs) on [Github](https://github.com/markjaquith/p
64
 
65
  == Changelog ==
66
 
 
 
 
67
  = 2.10.4 =
68
  * New screenshot and assets
69
 
5
  Tags: page, redirect, link, external link, repoint
6
  Requires at least: 4.8
7
  Tested up to: 4.9.6
8
+ Stable tag: 2.11.0
9
 
10
  Lets you make a WordPress page (or port or other content type) link to a URL of your choosing (on your site, or on another site), instead of its normal WordPress URL.
11
 
64
 
65
  == Changelog ==
66
 
67
+ = 2.11.0 =
68
+ * Code cleanup
69
+
70
  = 2.10.4 =
71
  * New screenshot and assets
72