Related Posts for WordPress - Version 1.7.0

Version Description

  • Major performance improvements for post link creation.
  • Fixed a shortcode bug.
  • Changed NONCE_REINSTALL constant to NONCE_INSTALL.
  • Added nonce checks.
Download this release

Release Info

Developer barrykooij
Plugin Icon 128x128 Related Posts for WordPress
Version 1.7.0
Comparing to
See all releases

Code changes from version 1.6.3 to 1.7.0

Files changed (78) hide show
  1. assets/css/settings.css +1 -1
  2. assets/css/settings.less +14 -0
  3. classes/class-autoloader.php +4 -0
  4. classes/class-constants.php +2 -1
  5. classes/class-is-installing-notice.php +1 -1
  6. classes/class-post-link-manager.php +36 -10
  7. classes/class-related-post-manager.php +77 -5
  8. classes/class-rp4wp.php +1 -1
  9. classes/filters/class-filter-plugin-links.php +1 -0
  10. classes/hooks/class-hook-ajax-install-link-posts.php +1 -1
  11. classes/hooks/class-hook-page-install.php +2 -1
  12. classes/hooks/class-hook-settings-page.php +32 -6
  13. classes/hooks/class-hook-shortcode.php +1 -1
  14. classes/{class-settings.php → settings/class-settings.php} +1 -1
  15. readme.txt +17 -1
  16. related-posts-for-wp.php +2 -2
  17. trunk/assets/css/edit-post.css +1 -0
  18. trunk/assets/css/edit-post.less +37 -0
  19. trunk/assets/css/install.css +1 -0
  20. trunk/assets/css/install.less +59 -0
  21. trunk/assets/css/settings.css +1 -0
  22. trunk/assets/css/settings.less +55 -0
  23. trunk/assets/images/ajax-loader.gif +0 -0
  24. trunk/assets/images/grabber.png +0 -0
  25. trunk/assets/js/edit-post.js +110 -0
  26. trunk/assets/js/edit-post.min.js +1 -0
  27. trunk/assets/js/install.js +118 -0
  28. trunk/assets/js/install.min.js +1 -0
  29. trunk/classes/class-autoloader.php +65 -0
  30. trunk/classes/class-cap-manager.php +23 -0
  31. trunk/classes/class-class-manager.php +31 -0
  32. trunk/classes/class-constants.php +32 -0
  33. trunk/classes/class-is-installing-notice.php +82 -0
  34. trunk/classes/class-javascript-strings.php +27 -0
  35. trunk/classes/class-link-related-table.php +276 -0
  36. trunk/classes/class-manager-filter.php +72 -0
  37. trunk/classes/class-manager-hook.php +59 -0
  38. trunk/classes/class-nag-manager.php +144 -0
  39. trunk/classes/class-post-link-manager.php +396 -0
  40. trunk/classes/class-related-post-manager.php +212 -0
  41. trunk/classes/class-related-posts-widget.php +43 -0
  42. trunk/classes/class-related-word-manager.php +431 -0
  43. trunk/classes/class-rp4wp.php +133 -0
  44. trunk/classes/filters/class-filter-after-post.php +45 -0
  45. trunk/classes/filters/class-filter-plugin-links.php +30 -0
  46. trunk/classes/filters/class-filter.php +64 -0
  47. trunk/classes/hooks/class-hook-admin-scripts.php +34 -0
  48. trunk/classes/hooks/class-hook-ajax-delete-link.php +55 -0
  49. trunk/classes/hooks/class-hook-ajax-install-link-posts.php +41 -0
  50. trunk/classes/hooks/class-hook-ajax-install-save-words.php +30 -0
  51. trunk/classes/hooks/class-hook-delete-words.php +23 -0
  52. trunk/classes/hooks/class-hook-frontend-css.php +18 -0
  53. trunk/classes/hooks/class-hook-link-related-screen.php +158 -0
  54. trunk/classes/hooks/class-hook-meta-box-ajax-sort.php +50 -0
  55. trunk/classes/hooks/class-hook-meta-box.php +13 -0
  56. trunk/classes/hooks/class-hook-page-install.php +165 -0
  57. trunk/classes/hooks/class-hook-post-type.php +13 -0
  58. trunk/classes/hooks/class-hook-related-auto-link.php +56 -0
  59. trunk/classes/hooks/class-hook-related-save-words.php +38 -0
  60. trunk/classes/hooks/class-hook-settings-page.php +129 -0
  61. trunk/classes/hooks/class-hook-shortcode.php +31 -0
  62. trunk/classes/hooks/class-hook-widget.php +13 -0
  63. trunk/classes/hooks/class-hook.php +64 -0
  64. trunk/classes/ignored-words/de_DE.php +7 -0
  65. trunk/classes/ignored-words/en_US.php +7 -0
  66. trunk/classes/ignored-words/fr_FR.php +7 -0
  67. trunk/classes/ignored-words/it_IT.php +7 -0
  68. trunk/classes/ignored-words/nl_NL.php +7 -0
  69. trunk/classes/meta-boxes/class-meta-box-manage.php +124 -0
  70. trunk/classes/settings/class-settings.php +284 -0
  71. trunk/includes/installer-functions.php +17 -0
  72. trunk/includes/template-functions.php +37 -0
  73. trunk/languages/related-posts-for-wp-nl_NL.mo +0 -0
  74. trunk/languages/related-posts-for-wp-nl_NL.po +411 -0
  75. trunk/languages/related-posts-for-wp.pot +360 -0
  76. trunk/readme.txt +180 -0
  77. trunk/related-posts-for-wp.php +56 -0
  78. trunk/uninstall.php +51 -0
assets/css/settings.css CHANGED
@@ -1 +1 @@
1
- .rp4wp-content{width:65%;float:left;box-sizing:border-box}.rp4wp-content input.rp4wp-input-text{width:100%}.rp4wp-content textarea{width:100%;height:150px}.rp4wp-content .rp4wp-description{display:block;margin:5px 0;line-height:1.4em;color:#666;font-style:italic}.rp4wp-sidebar{width:33%;margin-left:2%;padding:0 0 0 2%;border-left:1px solid #ccc;float:left;box-sizing:border-box}.rp4wp-sidebar .rp4wp-box{margin-bottom:20px}.rp4wp-sidebar .rp4wp-box .rp4wp-sidebar-header{line-height:0;border-bottom:2px solid #005592}
1
+ .rp4wp-content{width:65%;float:left;box-sizing:border-box}.rp4wp-content input.rp4wp-input-text{width:100%}.rp4wp-content textarea{width:100%;height:150px}.rp4wp-content .rp4wp-description{display:block;margin:5px 0;line-height:1.4em;color:#666;font-style:italic}.rp4wp-sidebar{width:33%;margin-left:2%;padding:0 0 0 2%;border-left:1px solid #ccc;float:left;box-sizing:border-box}.rp4wp-sidebar .rp4wp-box{margin-bottom:20px}.rp4wp-sidebar .rp4wp-box .rp4wp-sidebar-header{line-height:0;border-bottom:2px solid #005592}.rp4wp-sidebar .rp4wp-box-upgrade{background:#222;color:#ddd;padding:20px 20px 10px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.rp4wp-sidebar .rp4wp-box-upgrade h3{color:#fff;border:0;padding:0;margin:0}
assets/css/settings.less CHANGED
@@ -38,4 +38,18 @@
38
  border-bottom: 2px solid #005592;
39
  }
40
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  }
38
  border-bottom: 2px solid #005592;
39
  }
40
  }
41
+
42
+ .rp4wp-box-upgrade {
43
+ background: #222;
44
+ color: #ddd;
45
+ padding: 20px 20px 10px;
46
+ -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
47
+ }
48
+
49
+ .rp4wp-box-upgrade h3 {
50
+ color: #fff;
51
+ border: 0;
52
+ padding: 0;
53
+ margin: 0;
54
+ }
55
  }
classes/class-autoloader.php CHANGED
@@ -44,6 +44,10 @@ class RP4WP_Autoloader {
44
  $file_path .= 'filters/';
45
  } elseif ( strpos( $class_name, 'rp4wp_meta_box' ) === 0 ) {
46
  $file_path .= 'meta-boxes/';
 
 
 
 
47
  }
48
 
49
  // Append file name to clas path
44
  $file_path .= 'filters/';
45
  } elseif ( strpos( $class_name, 'rp4wp_meta_box' ) === 0 ) {
46
  $file_path .= 'meta-boxes/';
47
+ } elseif ( strpos( $class_name, 'rp4wp_settings' ) === 0 ) {
48
+ $file_path .= 'settings/';
49
+ } elseif ( strpos( $class_name, 'rp4wp_theme' ) === 0 ) {
50
+ $file_path .= 'themes/';
51
  }
52
 
53
  // Append file name to clas path
classes/class-constants.php CHANGED
@@ -10,6 +10,7 @@ abstract class RP4WP_Constants {
10
  const LINK_PT = 'rp4wp_link';
11
 
12
  // Linked meta
 
13
  const PM_PARENT = 'rp4wp_parent';
14
  const PM_CHILD = 'rp4wp_child';
15
 
@@ -26,6 +27,6 @@ abstract class RP4WP_Constants {
26
  const OPTION_ADMIN_NOTICE_KEY = 'rp4wp_hide_nag';
27
 
28
  // Nonce
29
- const NONCE_REINSTALL = 'rp4wp-reinstall-secret';
30
 
31
  }
10
  const LINK_PT = 'rp4wp_link';
11
 
12
  // Linked meta
13
+ const PM_PT_PARENT = 'rp4wp_pt_parent';
14
  const PM_PARENT = 'rp4wp_parent';
15
  const PM_CHILD = 'rp4wp_child';
16
 
27
  const OPTION_ADMIN_NOTICE_KEY = 'rp4wp_hide_nag';
28
 
29
  // Nonce
30
+ const NONCE_INSTALL = 'rp4wp-install-secret';
31
 
32
  }
classes/class-is-installing-notice.php CHANGED
@@ -42,7 +42,7 @@ if ( ! class_exists( 'RP4WP_Is_Installing_Notice' ) ) {
42
  }
43
 
44
  // Check if we are currently installing
45
- if ( get_site_option( RP4WP_Constants::OPTION_IS_INSTALLING, false ) && ( ! isset( $_GET['page'] ) || 'rp4wp_install' != $_GET['page'] ) ) {
46
  $this->display();
47
  }
48
 
42
  }
43
 
44
  // Check if we are currently installing
45
+ if ( false != get_site_option( RP4WP_Constants::OPTION_IS_INSTALLING, false ) && ( ! isset( $_GET['page'] ) || 'rp4wp_install' != $_GET['page'] ) ) {
46
  $this->display();
47
  }
48
 
classes/class-post-link-manager.php CHANGED
@@ -51,6 +51,7 @@ class RP4WP_Post_Link_Manager {
51
  private function get_link_count( $parent_id ) {
52
  $link_query = new WP_Query(
53
  array(
 
54
  'post_type' => RP4WP_Constants::LINK_PT,
55
  'posts_per_page' => - 1,
56
  'orderby' => 'menu_order',
@@ -78,23 +79,48 @@ class RP4WP_Post_Link_Manager {
78
  *
79
  * @param int $parent_id
80
  * @param int $child_id
 
81
  *
82
  * @return int ($link_id)
83
  */
84
- public function add( $parent_id, $child_id ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
  // Create post link
87
- $link_id = wp_insert_post( array(
88
- 'post_title' => 'Related Posts for WordPress Link',
89
- 'post_type' => RP4WP_Constants::LINK_PT,
90
- 'post_status' => 'publish',
91
- 'menu_order' => $this->get_link_count( $parent_id ),
92
- ) );
93
 
94
- // Create post meta
95
- add_post_meta( $link_id, RP4WP_Constants::PM_PARENT, $parent_id );
96
- add_post_meta( $link_id, RP4WP_Constants::PM_CHILD, $child_id );
97
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  do_action( 'rp4wp_after_link_add', $link_id );
99
 
100
  // Return link id
51
  private function get_link_count( $parent_id ) {
52
  $link_query = new WP_Query(
53
  array(
54
+ 'fields' => 'ids',
55
  'post_type' => RP4WP_Constants::LINK_PT,
56
  'posts_per_page' => - 1,
57
  'orderby' => 'menu_order',
79
  *
80
  * @param int $parent_id
81
  * @param int $child_id
82
+ * @param boolean $batch
83
  *
84
  * @return int ($link_id)
85
  */
86
+ public function add( $parent_id, $child_id, $batch = false ) {
87
+ global $wpdb;
88
+
89
+ // Setup the insert data
90
+ $data = array(
91
+ 'post' => "('" . current_time( 'mysql', 0 ) . "', '" . current_time( 'mysql', 1 ) . "','','Related Posts for WordPress Link','" . RP4WP_Constants::LINK_PT . "','publish')",
92
+ 'meta' => array(
93
+ "(%d, '" . RP4WP_Constants::PM_PARENT . "', '$parent_id')",
94
+ "(%d, '" . RP4WP_Constants::PM_CHILD . "', '$child_id')",
95
+ )
96
+ );
97
+
98
+ // If this is a batch insert, return data
99
+ if ( true === $batch ) {
100
+ return $data;
101
+ }
102
 
103
  // Create post link
104
+ $wpdb->query( " INSERT INTO `$wpdb->posts`
105
+ (`post_date`,`post_date_gmt`,`post_content`,`post_title`,`post_type`,`post_status`)
106
+ VALUES
107
+ {$data['post']}
108
+ " );
 
109
 
110
+ $link_id = $wpdb->insert_id;
 
 
111
 
112
+ // Create post meta
113
+ $wpdb->query(
114
+ $wpdb->prepare(
115
+ "INSERT INTO `$wpdb->postmeta`
116
+ (`post_id`,`meta_key`,`meta_value`)
117
+ VALUES
118
+ {$data['meta'][0]},
119
+ {$data['meta'][1]},
120
+ {$data['meta'][2]}
121
+ ", $link_id, $link_id, $link_id ) );
122
+
123
+ // Do action rp4wp_after_link_add
124
  do_action( 'rp4wp_after_link_add', $link_id );
125
 
126
  // Return link id
classes/class-related-post-manager.php CHANGED
@@ -35,10 +35,12 @@ class RP4WP_Related_Post_Manager {
35
  if ( - 1 != $limit ) {
36
  $sql .= "
37
  LIMIT 0,%d";
38
- };
39
-
40
- // Prepare SQL
41
- $sql = $wpdb->prepare( $sql, $post_id, $post_id, $limit );
 
 
42
 
43
  // Get post from related cache
44
  return $wpdb->get_results( $sql );
@@ -100,11 +102,38 @@ class RP4WP_Related_Post_Manager {
100
 
101
  if ( count( $related_posts ) > 0 ) {
102
 
 
 
103
  $post_link_manager = new RP4WP_Post_Link_Manager();
104
 
 
105
  foreach ( $related_posts as $related_post ) {
106
- $post_link_manager->add( $post_id, $related_post->ID );
107
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  }
109
 
110
  update_post_meta( $post_id, RP4WP_Constants::PM_POST_AUTO_LINKED, 1 );
@@ -112,6 +141,49 @@ class RP4WP_Related_Post_Manager {
112
  return true;
113
  }
114
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  /**
116
  * Link x related posts to y not already linked posts
117
  *
35
  if ( - 1 != $limit ) {
36
  $sql .= "
37
  LIMIT 0,%d";
38
+ // Prepare SQL
39
+ $sql = $wpdb->prepare( $sql, $post_id, $post_id, $limit );
40
+ } else {
41
+ // Prepare SQL
42
+ $sql = $wpdb->prepare( $sql, $post_id, $post_id );
43
+ }
44
 
45
  // Get post from related cache
46
  return $wpdb->get_results( $sql );
102
 
103
  if ( count( $related_posts ) > 0 ) {
104
 
105
+ global $wpdb;
106
+
107
  $post_link_manager = new RP4WP_Post_Link_Manager();
108
 
109
+ $batch_data = array();
110
  foreach ( $related_posts as $related_post ) {
111
+ $batch_data[] = $post_link_manager->add( $post_id, $related_post->ID, true );
112
  }
113
+
114
+ // Do batch insert
115
+ $wpdb->query( "INSERT INTO `$wpdb->posts`
116
+ (`post_date`,`post_date_gmt`,`post_content`,`post_title`,`post_type`,`post_status`)
117
+ VALUES
118
+ " . implode( ',', array_map( array( $this, 'batch_data_get_post' ), $batch_data ) ) . "
119
+ " );
120
+
121
+ // Get the first post link insert ID
122
+ $pid = $wpdb->insert_id;
123
+
124
+ // Set the correct ID's for batch meta insert
125
+ foreach ( $batch_data as $bk => $bd ) {
126
+ $batch_data[$bk]['meta'] = array_map( array( $this, 'batch_data_set_pid' ), $bd['meta'], array_fill( 0, count( $bd['meta'] ), $pid ) );
127
+ $pid ++;
128
+ }
129
+
130
+ // Insert all the meta
131
+ $wpdb->query( "INSERT INTO `$wpdb->postmeta`
132
+ (`post_id`,`meta_key`,`meta_value`)
133
+ VALUES
134
+ " . implode( ',', array_map( array( $this, 'batch_data_get_meta' ), $batch_data ) ) . "
135
+ ");
136
+
137
  }
138
 
139
  update_post_meta( $post_id, RP4WP_Constants::PM_POST_AUTO_LINKED, 1 );
141
  return true;
142
  }
143
 
144
+ /**
145
+ * Get post batch data
146
+ *
147
+ * @param $batch
148
+ *
149
+ * @since 1.0.0
150
+ * @access public
151
+ *
152
+ * @return mixed
153
+ */
154
+ public function batch_data_get_post( $batch ) {
155
+ return $batch['post'];
156
+ }
157
+
158
+ /**
159
+ * Get meta batch data
160
+ *
161
+ * @param $batch
162
+ *
163
+ * @since 1.0.0
164
+ * @access public
165
+ *
166
+ * @return string
167
+ */
168
+ public function batch_data_get_meta( $batch ) {
169
+ return implode(',',$batch['meta']);
170
+ }
171
+
172
+ /**
173
+ * Set the post ID's in batch data
174
+ *
175
+ * @param $batch
176
+ * @param $pid
177
+ *
178
+ * @since 1.0.0
179
+ * @access public
180
+ *
181
+ * @return string
182
+ */
183
+ public function batch_data_set_pid( $batch, $pid ) {
184
+ return sprintf( $batch, $pid );
185
+ }
186
+
187
  /**
188
  * Link x related posts to y not already linked posts
189
  *
classes/class-rp4wp.php CHANGED
@@ -8,7 +8,7 @@ class RP4WP {
8
 
9
  private static $instance = null;
10
 
11
- const VERSION = '1.6.3';
12
 
13
  /**
14
  * @var RP4WP_Settings
8
 
9
  private static $instance = null;
10
 
11
+ const VERSION = '1.7.0';
12
 
13
  /**
14
  * @var RP4WP_Settings
classes/filters/class-filter-plugin-links.php CHANGED
@@ -21,6 +21,7 @@ if ( ! class_exists( 'RP4WP_Filter_Plugin_Links' ) ) {
21
  */
22
  public function run( $links ) {
23
  array_unshift( $links, '<a href="' . admin_url( 'options-general.php?page=rp4wp' ) . '">' . __( 'Settings', 'related-posts-for-wp' ) . '</a>' );
 
24
 
25
  return $links;
26
  }
21
  */
22
  public function run( $links ) {
23
  array_unshift( $links, '<a href="' . admin_url( 'options-general.php?page=rp4wp' ) . '">' . __( 'Settings', 'related-posts-for-wp' ) . '</a>' );
24
+ array_unshift( $links, '<a href="https://www.relatedpostsforwp.com/?utm_source=plugin&utm_medium=link&utm_campaign=plugins-page" target="_blank" style="color:green;font-weight:bold;">' . __( 'Upgrade to Premium', 'related-posts-for-wp' ) . '</a>' );
25
 
26
  return $links;
27
  }
classes/hooks/class-hook-ajax-install-link-posts.php CHANGED
@@ -25,7 +25,7 @@ class RP4WP_Hook_Ajax_Install_Link_Posts extends RP4WP_Hook {
25
  $uncached_post_count = $related_post_manager->get_uncached_post_count();
26
 
27
  // Check if we're done
28
- if ( $uncached_post_count == 0 ) {
29
  // Save the wizard setting as the option
30
  $options = RP4WP()->settings->get_options();
31
  $options['automatic_linking_post_amount'] = $rel_amount;
25
  $uncached_post_count = $related_post_manager->get_uncached_post_count();
26
 
27
  // Check if we're done
28
+ if ( 0 == $uncached_post_count ) {
29
  // Save the wizard setting as the option
30
  $options = RP4WP()->settings->get_options();
31
  $options['automatic_linking_post_amount'] = $rel_amount;
classes/hooks/class-hook-page-install.php CHANGED
@@ -39,7 +39,7 @@ class RP4WP_Hook_Page_Install extends RP4WP_Hook {
39
  if ( isset( $_GET['reinstall'] ) ) {
40
 
41
  // Check nonce
42
- if ( ! wp_verify_nonce( ( isset( $_GET['rp4wp_nonce'] ) ? $_GET['rp4wp_nonce'] : '' ), RP4WP_Constants::NONCE_REINSTALL ) ) {
43
  wp_die( 'Woah! It looks like something else tried to run the Related Posts for WordPress installation wizard! We were able to stop them, nothing was lost. Please report this incident at <a href="http://wordpress.org/support/plugin/related-posts-for-wp" target="_blank">our forums.</a>' );
44
  }
45
 
@@ -109,6 +109,7 @@ class RP4WP_Hook_Page_Install extends RP4WP_Hook {
109
  $cur_step = isset( $_GET['step'] ) ? $_GET['step'] : 1;
110
  echo "<div class='rp4wp-step rp4wp-step-" . $cur_step . "' rel='" . $cur_step . "'>";
111
 
 
112
  echo "<input type='hidden' id='rp4wp_total_posts' value='" . wp_count_posts( 'post' )->publish . "' />" . PHP_EOL;
113
  echo "<input type='hidden' id='rp4wp_admin_url' value='" . admin_url() . "' />" . PHP_EOL;
114
 
39
  if ( isset( $_GET['reinstall'] ) ) {
40
 
41
  // Check nonce
42
+ if ( ! wp_verify_nonce( ( isset( $_GET['rp4wp_nonce'] ) ? $_GET['rp4wp_nonce'] : '' ), RP4WP_Constants::NONCE_INSTALL ) ) {
43
  wp_die( 'Woah! It looks like something else tried to run the Related Posts for WordPress installation wizard! We were able to stop them, nothing was lost. Please report this incident at <a href="http://wordpress.org/support/plugin/related-posts-for-wp" target="_blank">our forums.</a>' );
44
  }
45
 
109
  $cur_step = isset( $_GET['step'] ) ? $_GET['step'] : 1;
110
  echo "<div class='rp4wp-step rp4wp-step-" . $cur_step . "' rel='" . $cur_step . "'>";
111
 
112
+ // Hidden fields
113
  echo "<input type='hidden' id='rp4wp_total_posts' value='" . wp_count_posts( 'post' )->publish . "' />" . PHP_EOL;
114
  echo "<input type='hidden' id='rp4wp_admin_url' value='" . admin_url() . "' />" . PHP_EOL;
115
 
classes/hooks/class-hook-settings-page.php CHANGED
@@ -48,28 +48,54 @@ class RP4WP_Hook_Settings_Page extends RP4WP_Hook {
48
  </div>
49
 
50
  <p><?php _e( 'Plugin version', 'related-posts-for-wp' ); ?>: <?php echo RP4WP::VERSION; ?></p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  </div>
52
 
53
  <div class="rp4wp-box">
54
  <h3 class="rp4wp-title"><?php _e( 'More information', 'related-posts-for-wp' ); ?></h3>
55
 
56
- <p><?php printf( __( "<a href='%s'>FAQ</a>", 'related-posts-for-wp' ), 'http://wordpress.org/plugins/related-posts-for-wp/faq/' ); ?></p>
57
 
58
- <p><?php printf( __( "<a href='%s'>Change log</a>", 'related-posts-for-wp' ), 'http://wordpress.org/support/plugin/related-posts-for-wp' ); ?></p>
59
 
60
- <p><?php printf( __( "<a href='%s'>Give us a review</a>", 'related-posts-for-wp' ), 'http://wordpress.org/support/view/plugin-reviews/related-posts-for-wp' ); ?></p>
61
 
62
- <p><?php printf( __( "<a href='%s'>Release blog post</a>", 'related-posts-for-wp' ), 'http://www.barrykooij.com/related-posts-wordpress/?utm_source=plugin&utm_medium=link&utm_campaign=sidebar' ); ?></p>
63
  </div>
64
 
65
  <div class="rp4wp-box">
66
  <h3 class="rp4wp-title"><?php _e( 'About the developer', 'related-posts-for-wp' ); ?></h3>
67
 
68
- <p><?php _e( "Barry is a WordPress developer that works on WooCommerce by WooThemes and is the author of various WordPress plugins that include Post Connector, Related Posts for WordPress and What The File.", 'related-posts-for-wp' ); ?></p>
69
 
70
  <p><?php _e( "Barry likes contributing to opensource projects and visiting WordCamps and WordPress meetups. He’s the organizer of the WordPress meetup in Tilburg.", 'related-posts-for-wp' ); ?></p>
71
 
72
- <p><?php printf( __( "You can follow Barry on Twitter <a href='%s'>here</a>.", 'related-posts-for-wp' ), 'https://twitter.com/cageNL' ); ?></p>
73
  </div>
74
 
75
  </div>
48
  </div>
49
 
50
  <p><?php _e( 'Plugin version', 'related-posts-for-wp' ); ?>: <?php echo RP4WP::VERSION; ?></p>
51
+ <p><?php _e( 'Thank you for using Related Posts for WordPress!', 'related-posts-for-wp' ); ?></p>
52
+ </div>
53
+
54
+ <div class="rp4wp-box rp4wp-box-upgrade">
55
+ <h3 class="rp4wp-title"><?php _e( 'Related Posts for WordPress Premium', 'related-posts-for-wp' ); ?></h3>
56
+
57
+ <p><?php _e( "This plugin has an even better premium version, I am sure you will love it.", 'related-posts-for-wp' ); ?></p>
58
+ <p><?php _e( "Premium features include custom post type support, related post themes, custom taxonomy support and priority support.", 'related-posts-for-wp' ); ?></p>
59
+ <p><?php printf( __( "%sMore information about Related Posts for WP Premium »%s", 'related-posts-for-wp' ), '<a href="https://www.relatedpostsforwp.com/?utm_source=plugin&utm_medium=link&utm_campaign=upgrade-box" target="_blank">', '</a>' ); ?></p>
60
+ </div>
61
+
62
+ <div class="rp4wp-box">
63
+ <h3 class="rp4wp-title"><?php _e( 'Show a token of your appreciation', 'related-posts-for-wp' ); ?></h3>
64
+
65
+ <p><?php printf( __( "<a href='%s' target='_blank'>Leave a ★★★★★ plugin review on WordPress.org</a>", 'related-posts-for-wp' ), 'http://wordpress.org/support/view/plugin-reviews/related-posts-for-wp?rate=5#postform' ); ?></p>
66
+ <p><?php printf( __( "<a href='%s' target='_blank'>Tweet about Related Posts for WordPress</a>", 'related-posts-for-wp' ), 'https://twitter.com/intent/tweet?text=Showing%20my%20appreciation%20to%20%40CageNL%20for%20his%20WordPress%20plugin%3A%20Related%20Posts%20for%20WordPress%20-%20check%20it%20out!%20http%3A%2F%2Fwordpress.org%2Fplugins%2Frelated-posts-for-wp%2F' ); ?></p>
67
+ <p><?php printf( __( "Review the plugin on your blog and link to <a href='%s' target='_blank'>the plugin page</a>", 'related-posts-for-wp' ), 'https://www.relatedpostsforwp.com/?utm_source=plugin&utm_medium=link&utm_campaign=show-appreciation' ); ?></p>
68
+ <p><?php printf( __( "<a href='%s' target='_blank'>Vote 'works' on the WordPress.org plugin page</a>", 'related-posts-for-wp' ), 'http://wordpress.org/plugins/related-posts-for-wp/' ); ?></p>
69
+
70
+ </div>
71
+
72
+ <div class="rp4wp-box">
73
+ <h3 class="rp4wp-title"><?php _e( 'Looking for support?', 'related-posts-for-wp' ); ?></h3>
74
+
75
+ <p><?php printf( __( "For support please visit the <a href='%s' target='_blank'>WordPress.org forums</a>.", 'related-posts-for-wp' ), 'http://wordpress.org/support/plugin/related-posts-for-wp' ); ?></p>
76
+
77
+ <p style="color: green;font-weight: bold;"><?php printf( __( "Did you know that Related Posts for WordPress Premium clients get priority email support? %sClick here to upgrade.%s", 'related-posts-for-wp' ), '<a href="https://www.relatedpostsforwp.com/?utm_source=plugin&utm_medium=link&utm_campaign=support" target="_blank">', '</a>' ); ?></p>
78
  </div>
79
 
80
  <div class="rp4wp-box">
81
  <h3 class="rp4wp-title"><?php _e( 'More information', 'related-posts-for-wp' ); ?></h3>
82
 
83
+ <p><?php printf( __( "<a href='%s' target='_blank'>FAQ</a>", 'related-posts-for-wp' ), 'https://wordpress.org/plugins/related-posts-for-wp/faq/' ); ?></p>
84
 
85
+ <p><?php printf( __( "<a href='%s' target='_blank'>Changelog</a>", 'related-posts-for-wp' ), 'https://wordpress.org/plugins/related-posts-for-wp/changelog/' ); ?></p>
86
 
87
+ <p><?php printf( __( "<a href='%s' target='_blank'>Website</a>", 'related-posts-for-wp' ), 'https://www.relatedpostsforwp.com/?utm_source=plugin&utm_medium=link&utm_campaign=more-information' ); ?></p>
88
 
 
89
  </div>
90
 
91
  <div class="rp4wp-box">
92
  <h3 class="rp4wp-title"><?php _e( 'About the developer', 'related-posts-for-wp' ); ?></h3>
93
 
94
+ <p><?php _e( "Barry is a WordPress developer that works on WooCommerce by WooThemes and is the author of various WordPress plugins that include Related Posts for WordPress, Post Connector and What The File.", 'related-posts-for-wp' ); ?></p>
95
 
96
  <p><?php _e( "Barry likes contributing to opensource projects and visiting WordCamps and WordPress meetups. He’s the organizer of the WordPress meetup in Tilburg.", 'related-posts-for-wp' ); ?></p>
97
 
98
+ <p><?php printf( __( "<a href='%s' target='_blank'>You can follow Barry on Twitter</a>", 'related-posts-for-wp' ), 'https://twitter.com/cageNL' ); ?></p>
99
  </div>
100
 
101
  </div>
classes/hooks/class-hook-shortcode.php CHANGED
@@ -26,6 +26,6 @@ class RP4WP_Hook_Shortcode extends RP4WP_Hook {
26
  $pl_manager = new RP4WP_Post_Link_Manager();
27
 
28
  // Generate the children list
29
- echo $pl_manager->generate_children_list( $id );
30
  }
31
  }
26
  $pl_manager = new RP4WP_Post_Link_Manager();
27
 
28
  // Generate the children list
29
+ return $pl_manager->generate_children_list( $id );
30
  }
31
  }
classes/{class-settings.php → settings/class-settings.php} RENAMED
@@ -96,7 +96,7 @@ class RP4WP_Settings {
96
  'label' => __( 'Restart the wizard?', 'related-posts-for-wp' ),
97
  'description' => __( "Click this button if you want to restart the wizard. Please note that this will delete all current related post links, also those you've manually added. Of course, we will never delete your actual posts.", 'related-posts-for-wp' ),
98
  'type' => 'button_link',
99
- 'href' => admin_url( '?page=rp4wp_install&reinstall=1&rp4wp_nonce=' . wp_create_nonce( RP4WP_Constants::NONCE_REINSTALL ) ),
100
  'default' => __( 'Restart wizard', 'related-posts-for-wp' ),
101
  ),
102
  ) ),
96
  'label' => __( 'Restart the wizard?', 'related-posts-for-wp' ),
97
  'description' => __( "Click this button if you want to restart the wizard. Please note that this will delete all current related post links, also those you've manually added. Of course, we will never delete your actual posts.", 'related-posts-for-wp' ),
98
  'type' => 'button_link',
99
+ 'href' => admin_url( '?page=rp4wp_install&reinstall=1&rp4wp_nonce=' . wp_create_nonce( RP4WP_Constants::NONCE_INSTALL ) ),
100
  'default' => __( 'Restart wizard', 'related-posts-for-wp' ),
101
  ),
102
  ) ),
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: http://www.relatedpostsforwp.com/
4
  Tags: related posts for wordpress, related posts for wp, simple related posts, easy related posts, related posts, related, relations, internal links, seo, bounce rate
5
  Requires at least: 3.6
6
  Tested up to: 4.0
7
- Stable tag: 1.6.3
8
  License: GPLv3 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -18,6 +18,16 @@ Related Posts for WordPress offers you the ability to link related posts to each
18
 
19
  Our installation wizard will do all the hard work for you, simply activate the plugin, set the amount of posts that should relate and press the button. Related Posts for WordPress will do the rest. Relating posts in WordPress has never been this easy!
20
 
 
 
 
 
 
 
 
 
 
 
21
  = Related Posts for WordPress won't lag your server! =
22
  We don't think having related posts should slow down your website. That's why Related Posts for WordPress creates its own cache and does all the heavy lifting in the admin panel, keeping your website fast as it should be!
23
 
@@ -88,6 +98,12 @@ There is one custom table created for the post cache, this table will however no
88
 
89
  == Changelog ==
90
 
 
 
 
 
 
 
91
  = 1.6.3: September 18, 2014 =
92
  * Fixed an install bug.
93
 
4
  Tags: related posts for wordpress, related posts for wp, simple related posts, easy related posts, related posts, related, relations, internal links, seo, bounce rate
5
  Requires at least: 3.6
6
  Tested up to: 4.0
7
+ Stable tag: 1.7.0
8
  License: GPLv3 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
18
 
19
  Our installation wizard will do all the hard work for you, simply activate the plugin, set the amount of posts that should relate and press the button. Related Posts for WordPress will do the rest. Relating posts in WordPress has never been this easy!
20
 
21
+ > #### Related Posts for WordPress Premium
22
+ > There's an even better version of this plugin that comes with the following extra features:<br />
23
+ >
24
+ > - Custom Post Type Support<br />
25
+ > - Related Post Themes<br />
26
+ > - Custom Taxonomy Support<br />
27
+ > - Priority Email Support<br />
28
+ >
29
+ > [More information](https://www.relatedpostsforwp.com/features/?utm_source=wp-plugin-repo&utm_medium=link&utm_campaign=after-features-info-link) | [Purchase >>](https://www.relatedpostsforwp.com/checkout/?utm_source=wp-plugin-repo&utm_medium=link&utm_campaign=after-features-purchase-link)
30
+
31
  = Related Posts for WordPress won't lag your server! =
32
  We don't think having related posts should slow down your website. That's why Related Posts for WordPress creates its own cache and does all the heavy lifting in the admin panel, keeping your website fast as it should be!
33
 
98
 
99
  == Changelog ==
100
 
101
+ = 1.7.0 =
102
+ * Major performance improvements for post link creation.
103
+ * Fixed a shortcode bug.
104
+ * Changed NONCE_REINSTALL constant to NONCE_INSTALL.
105
+ * Added nonce checks.
106
+
107
  = 1.6.3: September 18, 2014 =
108
  * Fixed an install bug.
109
 
related-posts-for-wp.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Related Posts for WordPress
4
  Plugin URI: http://www.relatedpostsforwp.com/
5
  Description: Related Posts for WordPress, the best way to display related posts in WordPress.
6
- Version: 1.6.3
7
  Author: Barry Kooij
8
  Author URI: http://www.barrykooij.com/
9
  License: GPL v3
@@ -53,4 +53,4 @@ if( is_admin() && ( false === defined( 'DOING_AJAX' ) || false === DOING_AJAX )
53
 
54
  // Activation hook
55
  register_activation_hook( __FILE__, 'rp4wp_activate_plugin' );
56
- }
3
  Plugin Name: Related Posts for WordPress
4
  Plugin URI: http://www.relatedpostsforwp.com/
5
  Description: Related Posts for WordPress, the best way to display related posts in WordPress.
6
+ Version: 1.7.0
7
  Author: Barry Kooij
8
  Author URI: http://www.barrykooij.com/
9
  License: GPL v3
53
 
54
  // Activation hook
55
  register_activation_hook( __FILE__, 'rp4wp_activate_plugin' );
56
+ }
trunk/assets/css/edit-post.css ADDED
@@ -0,0 +1 @@
 
1
+ .rp4wp_table_manage.sortable tr{cursor:move}.rp4wp_table_manage.sortable tr td{background-position:98% 50%;background-image:url(../images/grabber.png);background-repeat:no-repeat}.rp4wp_table_manage td{padding-bottom:11px}.rp4wp_table_manage tr:nth-child(odd){background-color:#FCFCFC}.rp4wp_button_holder{padding:10px 0;float:right}.rp4wp_button_holder span{margin-left:10px;float:left}.rp4wp_save_button{float:right}.rp4wp_ajaxloader{height:13px;margin-left:10px}
trunk/assets/css/edit-post.less ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .rp4wp_table_manage {
2
+ &.sortable tr {
3
+ cursor: move;
4
+ td {
5
+ background-position: 98% 50%;
6
+ background-image: url('../images/grabber.png');
7
+ background-repeat: no-repeat;
8
+ }
9
+ }
10
+
11
+ td {
12
+ padding-bottom: 11px;
13
+ }
14
+
15
+ tr:nth-child(odd) {
16
+ background-color: #FCFCFC;
17
+ }
18
+ }
19
+
20
+ .rp4wp_button_holder {
21
+ padding: 10px 0;
22
+ float: right;
23
+
24
+ span {
25
+ margin-left: 10px;
26
+ float: left;
27
+ }
28
+ }
29
+
30
+ .rp4wp_save_button {
31
+ float: right;
32
+ }
33
+
34
+ .rp4wp_ajaxloader {
35
+ height: 13px;
36
+ margin-left: 10px;
37
+ }
trunk/assets/css/install.css ADDED
@@ -0,0 +1 @@
 
1
+ .install-steps li{width:33%;padding:10px 15px;font-weight:700;color:#eee;background:#222;float:left;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.install-steps li.step-bar-active{background:#0074a2}.install-steps li:first-child{margin-left:0}.rp4wp-step #progressbar span{line-height:28px;display:block;text-align:right;padding-right:10px;color:#3B3B3B}.rp4wp-step .rp4wp-install-link-box label{padding-right:20px}.rp4wp-step .rp4wp-install-link-box input{width:40px;text-align:center}.rp4wp-step .rp4wp-install-link-box a.rp4wp-link-now-btn{margin-left:20px;margin-right:10px}.rp4wp-install-link-box{display:inline;padding:15px;border:1px solid #0074a2}.rp4wp-step-2 #progressbar{margin-top:30px}
trunk/assets/css/install.less ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .install-steps {
2
+ li {
3
+ width: 33%;
4
+ padding: 10px 15px;
5
+ font-weight: bold;
6
+ color: #eee;
7
+ background: #222222;
8
+ float: left;
9
+ -moz-box-sizing: border-box;
10
+ -webkit-box-sizing: border-box;
11
+ box-sizing: border-box;
12
+
13
+ &.step-bar-active {
14
+ background: #0074a2;
15
+ }
16
+
17
+ &:first-child {
18
+ margin-left: 0;
19
+ }
20
+ }
21
+ }
22
+
23
+ .rp4wp-step {
24
+
25
+ #progressbar {
26
+ span {
27
+ line-height: 28px;
28
+ display: block;
29
+ text-align: right;
30
+ padding-right: 10px;
31
+ color: #3B3B3B;
32
+ }
33
+ }
34
+
35
+ .rp4wp-install-link-box {
36
+ label {
37
+ padding-right: 20px;
38
+ }
39
+ input {
40
+ width: 40px;
41
+ text-align: center;
42
+ }
43
+ a.rp4wp-link-now-btn {
44
+ margin-left: 20px;
45
+ margin-right: 10px;
46
+ }
47
+ }
48
+
49
+ }
50
+
51
+ .rp4wp-install-link-box {
52
+ display: inline;
53
+ padding: 15px;
54
+ border: 1px solid #0074a2;
55
+ }
56
+
57
+ .rp4wp-step-2 #progressbar {
58
+ margin-top: 30px;
59
+ }
trunk/assets/css/settings.css ADDED
@@ -0,0 +1 @@
 
1
+ .rp4wp-content{width:65%;float:left;box-sizing:border-box}.rp4wp-content input.rp4wp-input-text{width:100%}.rp4wp-content textarea{width:100%;height:150px}.rp4wp-content .rp4wp-description{display:block;margin:5px 0;line-height:1.4em;color:#666;font-style:italic}.rp4wp-sidebar{width:33%;margin-left:2%;padding:0 0 0 2%;border-left:1px solid #ccc;float:left;box-sizing:border-box}.rp4wp-sidebar .rp4wp-box{margin-bottom:20px}.rp4wp-sidebar .rp4wp-box .rp4wp-sidebar-header{line-height:0;border-bottom:2px solid #005592}.rp4wp-sidebar .rp4wp-box-upgrade{background:#222;color:#ddd;padding:20px 20px 10px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.rp4wp-sidebar .rp4wp-box-upgrade h3{color:#fff;border:0;padding:0;margin:0}
trunk/assets/css/settings.less ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .rp4wp-content {
2
+ width: 65%;
3
+ float: left;
4
+ box-sizing: border-box;
5
+
6
+ input.rp4wp-input-text {
7
+ width: 100%;
8
+ }
9
+
10
+ textarea {
11
+ width: 100%;
12
+ height: 150px;
13
+ }
14
+
15
+ .rp4wp-description {
16
+ display: block;
17
+ margin: 5px 0;
18
+ line-height: 1.4em;
19
+ color: #666;
20
+ font-style: italic;
21
+ }
22
+
23
+ }
24
+
25
+ .rp4wp-sidebar {
26
+ width: 33%;
27
+ margin-left: 2%;
28
+ padding: 0 0 0 2%;
29
+ border-left: 1px solid #ccc;
30
+ float: left;
31
+ box-sizing: border-box;
32
+
33
+ .rp4wp-box {
34
+ margin-bottom: 20px;
35
+
36
+ .rp4wp-sidebar-header {
37
+ line-height: 0;
38
+ border-bottom: 2px solid #005592;
39
+ }
40
+ }
41
+
42
+ .rp4wp-box-upgrade {
43
+ background: #222;
44
+ color: #ddd;
45
+ padding: 20px 20px 10px;
46
+ -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
47
+ }
48
+
49
+ .rp4wp-box-upgrade h3 {
50
+ color: #fff;
51
+ border: 0;
52
+ padding: 0;
53
+ margin: 0;
54
+ }
55
+ }
trunk/assets/images/ajax-loader.gif ADDED
Binary file
trunk/assets/images/grabber.png ADDED
Binary file
trunk/assets/js/edit-post.js ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Used on the post screen
3
+ */
4
+ jQuery(function ($) {
5
+ $.each($('.rp4wp_mb_manage'), function (k, v) {
6
+ new RP4WP_Related_Manager(v);
7
+ });
8
+ });
9
+
10
+ /**
11
+ * Used on the post screen
12
+ *
13
+ * @param tgt
14
+ * @constructor
15
+ */
16
+ function RP4WP_Related_Manager(tgt) {
17
+ this.container = tgt;
18
+
19
+ this.init = function () {
20
+ this.bind();
21
+ this.make_sortable();
22
+ };
23
+
24
+ this.bind = function () {
25
+ var instance = this;
26
+ jQuery(this.container).find('.rp4wp_table_manage .trash a').bind('click', function () {
27
+ instance.delete_child(this);
28
+ });
29
+ };
30
+
31
+ this.fix_helper = function (e, ui) {
32
+ ui.children().each(function () {
33
+ jQuery(this).width(jQuery(this).width());
34
+ });
35
+ return ui;
36
+ };
37
+
38
+ this.make_sortable = function () {
39
+ var instance = this;
40
+ var sortable_table = jQuery(this.container).find('.sortable tbody');
41
+
42
+ sortable_table.sortable({
43
+ helper: instance.fix_helper,
44
+ update: function (event, ui) {
45
+
46
+ jQuery(instance.container).parent().parent().find('h3').eq(0).append(
47
+ jQuery('<img>').attr('src', jQuery('#rp4wp-dir-img').val() + 'ajax-loader.gif').addClass('rp4wp_ajaxloader')
48
+ );
49
+
50
+ opts = {
51
+ url : ajaxurl,
52
+ type : 'POST',
53
+ async : true,
54
+ cache : false,
55
+ dataType: 'json',
56
+ data : {
57
+ action : 'rp4wp_related_sort',
58
+ rp4wp_items: sortable_table.sortable('toArray').toString(),
59
+ nonce : jQuery(instance.container).find('#rp4wp-ajax-nonce').val()
60
+ },
61
+ success : function (response) {
62
+ jQuery('.rp4wp_ajaxloader').remove();
63
+ return;
64
+ },
65
+ error : function (xhr, textStatus, e) {
66
+ jQuery('.rp4wp_ajaxloader').remove();
67
+ return;
68
+ }
69
+ };
70
+ jQuery.ajax(opts);
71
+ }
72
+ });
73
+
74
+ };
75
+
76
+ this.delete_child = function (tgt) {
77
+
78
+ var confirm_delete = confirm(rp4wp_js.confirm_delete_related_post);
79
+ if (!confirm_delete) {
80
+ return;
81
+ }
82
+
83
+ var instance = this;
84
+
85
+ var opts = {
86
+ url : ajaxurl,
87
+ type : 'POST',
88
+ async : true,
89
+ cache : false,
90
+ dataType: 'json',
91
+ data : {
92
+ action: 'rp4wp_delete_link',
93
+ id : jQuery(tgt).closest('tr').attr('id'),
94
+ nonce : jQuery(instance.container).find('#rp4wp-ajax-nonce').val()
95
+ },
96
+ success : function (response) {
97
+ jQuery(tgt).closest('tr').fadeTo('fast', 0).slideUp(function () {
98
+ jQuery(this).remove();
99
+ });
100
+ return;
101
+ },
102
+ error : function (xhr, textStatus, e) {
103
+ return;
104
+ }
105
+ };
106
+ jQuery.ajax(opts);
107
+ };
108
+
109
+ this.init();
110
+ }
trunk/assets/js/edit-post.min.js ADDED
@@ -0,0 +1 @@
 
1
+ function RP4WP_Related_Manager(a){this.container=a,this.init=function(){this.bind(),this.make_sortable()},this.bind=function(){var a=this;jQuery(this.container).find(".rp4wp_table_manage .trash a").bind("click",function(){a.delete_child(this)})},this.fix_helper=function(a,b){return b.children().each(function(){jQuery(this).width(jQuery(this).width())}),b},this.make_sortable=function(){var a=this,b=jQuery(this.container).find(".sortable tbody");b.sortable({helper:a.fix_helper,update:function(){jQuery(a.container).parent().parent().find("h3").eq(0).append(jQuery("<img>").attr("src",jQuery("#rp4wp-dir-img").val()+"ajax-loader.gif").addClass("rp4wp_ajaxloader")),opts={url:ajaxurl,type:"POST",async:!0,cache:!1,dataType:"json",data:{action:"rp4wp_related_sort",rp4wp_items:b.sortable("toArray").toString(),nonce:jQuery(a.container).find("#rp4wp-ajax-nonce").val()},success:function(){jQuery(".rp4wp_ajaxloader").remove()},error:function(){jQuery(".rp4wp_ajaxloader").remove()}},jQuery.ajax(opts)}})},this.delete_child=function(a){var b=confirm(rp4wp_js.confirm_delete_related_post);if(b){var c=this,d={url:ajaxurl,type:"POST",async:!0,cache:!1,dataType:"json",data:{action:"rp4wp_delete_link",id:jQuery(a).closest("tr").attr("id"),nonce:jQuery(c.container).find("#rp4wp-ajax-nonce").val()},success:function(){jQuery(a).closest("tr").fadeTo("fast",0).slideUp(function(){jQuery(this).remove()})},error:function(){}};jQuery.ajax(d)}},this.init()}jQuery(function(a){a.each(a(".rp4wp_mb_manage"),function(a,b){new RP4WP_Related_Manager(b)})});
trunk/assets/js/install.js ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function ($) {
2
+
3
+ // Determine steps
4
+ var step = $('.rp4wp-step').attr('rel');
5
+
6
+ // Checks steps
7
+ if (1 == step) {
8
+
9
+ // Install the cache
10
+ rp4wp_install_wizard(1);
11
+
12
+ } else if (2 == step) {
13
+
14
+ // Link the posts
15
+ $('#rp4wp-link-now').click(function () {
16
+ rp4wp_install_wizard(2);
17
+ });
18
+
19
+ }
20
+
21
+ function rp4wp_install_wizard(step) {
22
+
23
+ this.step = step;
24
+ this.total_posts = 0;
25
+ this.ppr = null;
26
+ this.action = null;
27
+ this.percentage_object = null;
28
+
29
+ this.do_request = function () {
30
+ var instance = this;
31
+ $.post(ajaxurl, {
32
+ 'action' : this.action,
33
+ 'ppr' : this.ppr,
34
+ 'rel_amount': $('#rp4wp_related_posts_amount').val()
35
+ }, function (response) {
36
+
37
+ // The RegExp
38
+ var response_regex = new RegExp("^[0-9]+$");
39
+
40
+ // Trim that string o/
41
+ response = response.trim();
42
+
43
+ // Test it
44
+ if (response_regex.test(response)) {
45
+
46
+ var posts_left = parseInt(response);
47
+
48
+ // Do Progressbar
49
+ instance.do_progressbar(posts_left);
50
+
51
+ if (posts_left > 0) {
52
+ // Do request
53
+ instance.do_request();
54
+ } else {
55
+ // Done
56
+ instance.done();
57
+ }
58
+
59
+ } else {
60
+ alert("Woops! Something went wrong while linking.\n\nResponse:\n\n" + response);
61
+ }
62
+
63
+ });
64
+ };
65
+
66
+ this.done = function () {
67
+
68
+ // Update progressbar
69
+ $('#progressbar').progressbar({value: 100});
70
+
71
+ // Redirect to next step
72
+ window.location = $('#rp4wp_admin_url').val() + '?page=rp4wp_install&step=' + ( this.step + 1 );
73
+ };
74
+
75
+ this.do_progressbar = function (posts_left) {
76
+ var progress = Math.round(( ( this.total_posts - posts_left ) / this.total_posts ) * 100);
77
+ if (progress > 0) {
78
+ this.percentage_object.html(progress + '%');
79
+ $('#progressbar').progressbar({value: progress});
80
+ }
81
+ };
82
+
83
+ this.init = function () {
84
+
85
+ // Setup the progressbar
86
+ $('#progressbar').progressbar({value: false});
87
+
88
+ // Create the span
89
+ this.percentage_object = jQuery('<span>');
90
+ $('#progressbar').find('div:first').append(this.percentage_object);
91
+
92
+ // Set the current progress
93
+ this.do_progressbar($('#rp4wp_uncached_posts').val());
94
+
95
+ // Get the total posts
96
+ this.total_posts = $('#rp4wp_total_posts').val();
97
+
98
+ // Set the correct action
99
+ switch (this.step) {
100
+ case 1:
101
+ this.ppr = 25;
102
+ this.action = 'rp4wp_install_save_words';
103
+ break;
104
+ case 2:
105
+ this.ppr = 5;
106
+ this.action = 'rp4wp_install_link_posts';
107
+ break;
108
+ }
109
+
110
+ // Do the first request
111
+ this.do_request();
112
+ };
113
+
114
+ this.init();
115
+
116
+ }
117
+
118
+ });
trunk/assets/js/install.min.js ADDED
@@ -0,0 +1 @@
 
1
+ jQuery(document).ready(function(a){function b(b){this.step=b,this.total_posts=0,this.ppr=null,this.action=null,this.percentage_object=null,this.do_request=function(){var b=this;a.post(ajaxurl,{action:this.action,ppr:this.ppr,rel_amount:a("#rp4wp_related_posts_amount").val()},function(a){var c=new RegExp("^[0-9]+$");if(a=a.trim(),c.test(a)){var d=parseInt(a);b.do_progressbar(d),d>0?b.do_request():b.done()}else alert("Woops! Something went wrong while linking.\n\nResponse:\n\n"+a)})},this.done=function(){a("#progressbar").progressbar({value:100}),window.location=a("#rp4wp_admin_url").val()+"?page=rp4wp_install&step="+(this.step+1)},this.do_progressbar=function(b){var c=Math.round((this.total_posts-b)/this.total_posts*100);c>0&&(this.percentage_object.html(c+"%"),a("#progressbar").progressbar({value:c}))},this.init=function(){switch(a("#progressbar").progressbar({value:!1}),this.percentage_object=jQuery("<span>"),a("#progressbar").find("div:first").append(this.percentage_object),this.do_progressbar(a("#rp4wp_uncached_posts").val()),this.total_posts=a("#rp4wp_total_posts").val(),this.step){case 1:this.ppr=25,this.action="rp4wp_install_save_words";break;case 2:this.ppr=5,this.action="rp4wp_install_link_posts"}this.do_request()},this.init()}var c=a(".rp4wp-step").attr("rel");1==c?b(1):2==c&&a("#rp4wp-link-now").click(function(){b(2)})});
trunk/classes/class-autoloader.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Autoloader {
8
+
9
+ private $path;
10
+
11
+ /**
12
+ * The Constructor, sets the path of the class directory.
13
+ *
14
+ * @param $path
15
+ */
16
+ public function __construct( $path ) {
17
+ $this->path = $path;
18
+ }
19
+
20
+
21
+ /**
22
+ * Autoloader load method. Load the class.
23
+ *
24
+ * @param $class_name
25
+ */
26
+ public function load( $class_name ) {
27
+
28
+ // Only autoload WooCommerce Sales Report Email classes
29
+ if ( 0 === strpos( $class_name, 'RP4WP_' ) ) {
30
+
31
+ // String to lower
32
+ $class_name = strtolower( $class_name );
33
+
34
+ // Format file name
35
+ $file_name = 'class-' . str_ireplace( '_', '-', str_ireplace( 'RP4WP_', '', $class_name ) ) . '.php';
36
+
37
+ // Setup the file path
38
+ $file_path = $this->path;
39
+
40
+ // Check if we need to extend the class path
41
+ if ( strpos( $class_name, 'rp4wp_hook' ) === 0 ) {
42
+ $file_path .= 'hooks/';
43
+ } elseif ( strpos( $class_name, 'rp4wp_filter' ) === 0 ) {
44
+ $file_path .= 'filters/';
45
+ } elseif ( strpos( $class_name, 'rp4wp_meta_box' ) === 0 ) {
46
+ $file_path .= 'meta-boxes/';
47
+ } elseif ( strpos( $class_name, 'rp4wp_settings' ) === 0 ) {
48
+ $file_path .= 'settings/';
49
+ } elseif ( strpos( $class_name, 'rp4wp_theme' ) === 0 ) {
50
+ $file_path .= 'themes/';
51
+ }
52
+
53
+ // Append file name to clas path
54
+ $file_path .= $file_name;
55
+
56
+ // Check & load file
57
+ if ( file_exists( $file_path ) ) {
58
+ require_once( $file_path );
59
+ }
60
+
61
+ }
62
+
63
+ }
64
+
65
+ }
trunk/classes/class-cap-manager.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Cap_Manager {
8
+
9
+ /**
10
+ * Get custom post type capabilities
11
+ *
12
+ * @param $post_id
13
+ *
14
+ * @return string
15
+ */
16
+ public static function get_capability( $post_id ) {
17
+ $post_type = ( isset( $post_id ) ) ? get_post_type( $post_id ) : 'post';
18
+ $post_type_obj = get_post_type_object( $post_type );
19
+
20
+ return ( ( null != $post_type_obj ) ? $post_type_obj->cap->edit_posts : 'edit_posts' );
21
+ }
22
+
23
+ }
trunk/classes/class-class-manager.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Class_Manager {
8
+
9
+ /**
10
+ * Uppercase the character after the underscore, used as callback by SP_Class_Manager::format_class_name.
11
+ *
12
+ * @param $part
13
+ *
14
+ * @return string
15
+ */
16
+ public static function capitalize_part( $part ) {
17
+ return '_' . strtoupper( substr( $part[0], 1, 1 ) );
18
+ }
19
+
20
+ /**
21
+ * Format the class name by the file name
22
+ *
23
+ * @param $file_name
24
+ *
25
+ * @return string
26
+ */
27
+ public static function format_class_name( $file_name ) {
28
+ return preg_replace_callback( "/(_[a-z])/", array( 'RP4WP_Class_Manager', 'capitalize_part' ), 'RP4WP_' . str_ireplace( '-', '_', str_ireplace( array( 'class-', '.php' ), "", $file_name ) ) );
29
+ }
30
+
31
+ }
trunk/classes/class-constants.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ abstract class RP4WP_Constants {
8
+
9
+ // Link title
10
+ const LINK_PT = 'rp4wp_link';
11
+
12
+ // Linked meta
13
+ const PM_PT_PARENT = 'rp4wp_pt_parent';
14
+ const PM_PARENT = 'rp4wp_parent';
15
+ const PM_CHILD = 'rp4wp_child';
16
+
17
+ // Post meta
18
+ const PM_CACHED = 'rp4wp_cached'; // Posts that words are saved of
19
+ const PM_POST_AUTO_LINKED = 'rp4wp_auto_linked'; // Posts that have automatically linked posts
20
+
21
+ // Options
22
+ const OPTION_DO_INSTALL = 'rp4wp_do_install';
23
+ const OPTION_IS_INSTALLING = 'rp4wp_is_installing';
24
+
25
+ // Nag options
26
+ const OPTION_INSTALL_DATE = 'rp4wp_install_date';
27
+ const OPTION_ADMIN_NOTICE_KEY = 'rp4wp_hide_nag';
28
+
29
+ // Nonce
30
+ const NONCE_INSTALL = 'rp4wp-install-secret';
31
+
32
+ }
trunk/classes/class-is-installing-notice.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+
8
+ if ( ! class_exists( 'RP4WP_Is_Installing_Notice' ) ) {
9
+
10
+ /**
11
+ * Class RP4WP_Is_Installing_Notice
12
+ *
13
+ * @since 1.4.0
14
+ */
15
+ class RP4WP_Is_Installing_Notice {
16
+
17
+ /**
18
+ * Get the admin query string
19
+ *
20
+ * @since 1.4.0
21
+ * @access public
22
+ *
23
+ * @return mixed
24
+ */
25
+ private function get_admin_query_string_array() {
26
+ parse_str( $_SERVER['QUERY_STRING'], $params );
27
+
28
+ return $params;
29
+ }
30
+
31
+ /**
32
+ * Check if we need to do anything related to this notice
33
+ * @since 1.4.0
34
+ * @access public
35
+ *
36
+ */
37
+ public function check() {
38
+
39
+ // Check if we need to dismiss the notice
40
+ if ( isset( $_GET['rp4wp_hide_is_installing'] ) ) {
41
+ delete_site_option( RP4WP_Constants::OPTION_IS_INSTALLING );
42
+ }
43
+
44
+ // Check if we are currently installing
45
+ if ( false != get_site_option( RP4WP_Constants::OPTION_IS_INSTALLING, false ) && ( ! isset( $_GET['page'] ) || 'rp4wp_install' != $_GET['page'] ) ) {
46
+ $this->display();
47
+ }
48
+
49
+ }
50
+
51
+ /**
52
+ * Display the admin notice
53
+ *
54
+ * @since 1.4.0
55
+ * @access private
56
+ *
57
+ */
58
+ private function display() {
59
+ add_action( 'admin_notices', array( $this, 'content' ) );
60
+ }
61
+
62
+ /**
63
+ * The admin notice content
64
+ *
65
+ * @since 1.4.0
66
+ * @access public
67
+ */
68
+ public function content() {
69
+ $query_params = $this->get_admin_query_string_array();
70
+ $install_query_string = '?' . http_build_query( array_merge( $query_params, array( 'page' => 'rp4wp_install' ) ) );
71
+ $dismiss_query_string = '?' . http_build_query( array_merge( $query_params, array( 'rp4wp_hide_is_installing' => 1 ) ) );
72
+
73
+ echo '<div class="error"><p>';
74
+ printf( __( "Woah! Looks like we weren't able to finish your Related Posts for WordPress installation wizard!" ), '<b>', '</b>' );
75
+ echo "<br /><br />";
76
+ printf( __( "%sResume the installation wizard%s or %sdismiss this notice%s" ), '<a href="' . $install_query_string . '">', '</a>', '<a href="' . $dismiss_query_string . '">', '</a>' );
77
+ echo "</p></div>";
78
+ }
79
+
80
+ }
81
+
82
+ }
trunk/classes/class-javascript-strings.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ if ( ! class_exists( 'RP4WP_Javascript_Strings' ) ) {
8
+ class RP4WP_Javascript_Strings {
9
+
10
+ private static $value = null;
11
+
12
+ private static function fill() {
13
+ self::$value = array(
14
+ 'confirm_delete_related_post' => __( 'Are you sure you want to delete this related post?', 'related-posts-for-wp' ),
15
+ );
16
+ }
17
+
18
+ public static function get() {
19
+ if ( self::$value === null ) {
20
+ self::fill();
21
+ }
22
+
23
+ return self::$value;
24
+ }
25
+
26
+ }
27
+ }
trunk/classes/class-link-related-table.php ADDED
@@ -0,0 +1,276 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ if ( ! class_exists( 'WP_List_Table' ) ) {
8
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
9
+ }
10
+
11
+ class RP4WP_Link_Related_Table extends WP_List_Table {
12
+
13
+ private $post_type;
14
+ private $data;
15
+ private $search;
16
+
17
+ private $enable_related = false;
18
+ private $is_related = false;
19
+
20
+ public function __construct() {
21
+ parent::__construct();
22
+ add_filter( 'views_' . $this->screen->id, array( $this, 'add_page_views' ) );
23
+ }
24
+
25
+ /**
26
+ * Get the current view
27
+ *
28
+ * @return string
29
+ */
30
+ private function get_current_view() {
31
+ return ( isset ( $_GET['rp4wp_view'] ) ? $_GET['rp4wp_view'] : 'related' );
32
+ }
33
+
34
+ /**
35
+ * Add page views
36
+ *
37
+ * @param array $views
38
+ *
39
+ * @return array
40
+ */
41
+ public function add_page_views() {
42
+
43
+ // Get current
44
+ $current = $this->get_current_view();
45
+
46
+ $views_arr = array(
47
+ 'related' => __( 'Related Posts', 'related-posts-for-wp' ),
48
+ 'all' => __( 'All Posts', 'related-posts-for-wp' ),
49
+ );
50
+
51
+ $new_views = array();
52
+
53
+ foreach ( $views_arr as $key => $val ) {
54
+ $new_views[$key] = "<a href='" . add_query_arg( array(
55
+ 'rp4wp_view' => $key,
56
+ 'paged' => 1
57
+ ) ) . "'" . ( ( $current == $key ) ? " class='current'" : "" ) . ">{$val}</a>";
58
+ }
59
+
60
+ return $new_views;
61
+ }
62
+
63
+ /**
64
+ * Set the search string
65
+ *
66
+ * @param $search
67
+ */
68
+ public function set_search( $search ) {
69
+
70
+ // Can't search through related posts
71
+ if ( $this->get_current_view() != 'related' ) {
72
+ $this->search = $search;
73
+ }
74
+
75
+ }
76
+
77
+ /**
78
+ * Display the search box.
79
+ *
80
+ * @param string $text The search button text
81
+ * @param string $input_id The search input id
82
+ */
83
+ public function search_box( $text, $input_id ) {
84
+ if ( $this->get_current_view() != 'related' ) {
85
+ parent::search_box( $text, $input_id );
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Get the columns
91
+ *
92
+ * @return array
93
+ */
94
+ public function get_columns() {
95
+ $columns = array(
96
+ 'cb' => '<input type="checkbox" />',
97
+ 'title' => __( 'Title', 'related-posts-for-wp' ),
98
+ );
99
+
100
+ return $columns;
101
+ }
102
+
103
+ /**
104
+ * Prepare the items
105
+ */
106
+ public function prepare_items() {
107
+
108
+ // Get current view
109
+ $view = $this->get_current_view();
110
+
111
+ // Check if we're in the related view
112
+ if ( 'related' == $view ) {
113
+ $this->is_related = true;
114
+ }
115
+
116
+ // Set table properties
117
+ $columns = $this->get_columns();
118
+ $hidden = array();
119
+ $sortable = $this->get_sortable_columns();
120
+ $this->_column_headers = array( $columns, $hidden, $sortable );
121
+
122
+ // Vies
123
+ $this->views();
124
+
125
+ // Set search
126
+ if ( $this->search !== null ) {
127
+ add_filter( 'posts_where', array( $this, 'filter_posts_where' ) );
128
+ }
129
+
130
+ // Get Data
131
+ $this->data = array();
132
+
133
+ // Get posts
134
+ if ( 'all' == $view ) {
135
+ $posts = get_posts( array(
136
+ 'post_type' => 'post',
137
+ 'posts_per_page' => '-1',
138
+ 'suppress_filters' => false
139
+ ) );
140
+ } else {
141
+ $rpm = new RP4WP_Related_Post_Manager();
142
+ $parent = $_GET['rp4wp_parent'];
143
+ $posts = $rpm->get_related_posts( $parent );
144
+ }
145
+
146
+ // Format data for table
147
+ if ( count( $posts ) > 0 ) {
148
+ foreach ( $posts as $post ) {
149
+ $this->data[] = array( 'ID' => $post->ID, 'title' => $post->post_title );
150
+ }
151
+ }
152
+
153
+ // Remove search filter
154
+ remove_filter( 'posts_where', array( $this, 'filter_posts_where' ) );
155
+
156
+ // Sort
157
+ if ( ! $this->is_related ) {
158
+ if ( count( $this->data ) > 0 ) {
159
+ usort( $this->data, array( $this, 'custom_reorder' ) );
160
+ }
161
+ }
162
+
163
+ // Set items
164
+ $this->items = $this->data;
165
+ }
166
+
167
+ /**
168
+ * Get the sortable columns
169
+ *
170
+ * @return array
171
+ */
172
+ public function get_sortable_columns() {
173
+ $sortable_columns = array();
174
+ if ( ! $this->is_related ) {
175
+ $sortable_columns['title'] = array( 'title', false );
176
+ }
177
+
178
+ return $sortable_columns;
179
+ }
180
+
181
+ /**
182
+ * Method to do the custom reorder
183
+ *
184
+ * @param $a
185
+ * @param $b
186
+ *
187
+ * @return int
188
+ */
189
+ public function custom_reorder( $a, $b ) {
190
+ // If no sort, default to title
191
+ $orderby = ( ! empty( $_GET['orderby'] ) ) ? $_GET['orderby'] : 'title';
192
+ // If no order, default to asc
193
+ $order = ( ! empty( $_GET['order'] ) ) ? $_GET['order'] : 'asc';
194
+ // Determine sort order
195
+ $result = strcmp( $a[$orderby], $b[$orderby] );
196
+
197
+ // Send final sort direction to usort
198
+ return ( $order === 'asc' ) ? $result : - $result;
199
+ }
200
+
201
+ /**
202
+ * Checkbox column
203
+ *
204
+ * @param $item
205
+ *
206
+ * @return string
207
+ */
208
+ public function column_cb( $item ) {
209
+ return sprintf(
210
+ '<input type="checkbox" name="rp4wp_bulk[]" value="%s" />', $item['ID']
211
+ );
212
+ }
213
+
214
+ /**
215
+ * Title column
216
+ *
217
+ * @param $item
218
+ *
219
+ * @return string
220
+ */
221
+ public function column_title( $item ) {
222
+ $actions = array(
223
+ 'link' => sprintf(
224
+ '<a href="?page=%s&amp;rp4wp_parent=%s&amp;rp4wp_create_link=%s">' . __( 'Link Post', 'related-posts-for-wp' ) . '</a>',
225
+ $_REQUEST['page'],
226
+ $_GET['rp4wp_parent'],
227
+ $item['ID']
228
+ ),
229
+ );
230
+
231
+ return sprintf( '%1$s %2$s', $item['title'], $this->row_actions( $actions ) );
232
+ }
233
+
234
+ /**
235
+ * Default column
236
+ *
237
+ * @param $item
238
+ * @param $column_name
239
+ *
240
+ * @return mixed
241
+ */
242
+ public function column_default( $item, $column_name ) {
243
+ switch ( $column_name ) {
244
+ case 'title':
245
+ return $item[$column_name];
246
+ }
247
+ }
248
+
249
+ /**
250
+ * Get the bulk actions
251
+ *
252
+ * @return array
253
+ */
254
+ public function get_bulk_actions() {
255
+ $actions = array(
256
+ 'link' => __( 'Link Posts', 'related-posts-for-wp' )
257
+ );
258
+
259
+ return $actions;
260
+ }
261
+
262
+ /**
263
+ * Filter on the post where
264
+ *
265
+ * @param $where
266
+ *
267
+ * @return string
268
+ */
269
+ public function filter_posts_where( $where ) {
270
+ global $wpdb;
271
+ $where .= $wpdb->prepare( " AND {$wpdb->prefix}posts.post_title LIKE '%%%s%%' ", $this->search );
272
+
273
+ return $where;
274
+ }
275
+
276
+ }
trunk/classes/class-manager-filter.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ if ( ! class_exists( 'RP4WP_Manager_Filter' ) ) {
8
+
9
+ class RP4WP_Manager_Filter {
10
+
11
+ private $filter_dir;
12
+ private static $filters;
13
+
14
+ public function __construct( $filter_dir ) {
15
+ $this->filter_dir = $filter_dir;
16
+ }
17
+
18
+ /**
19
+ * Load on specific filter instead of all filters.
20
+ * This method should be used when the load_filters() isn't run yet, for example in the (de)activation process.
21
+ *
22
+ * @param $file_name
23
+ */
24
+ public function load_filter( $file_name ) {
25
+ $class = RP4WP_Class_Manager::format_class_name( $file_name );
26
+ if ( 'RP4WP_Filter' != $class ) {
27
+ self::$filters[$class] = new $class;
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Load and set hooks
33
+ *
34
+ * @access public
35
+ * @static
36
+ * @return void
37
+ */
38
+ public function load_filters() {
39
+
40
+ foreach ( new DirectoryIterator( $this->filter_dir ) as $file ) {
41
+
42
+ if ( ! $file->isDir() && ( strpos( $file->getFileName(), '.' ) !== 0 ) ) {
43
+
44
+ $class = RP4WP_Class_Manager::format_class_name( $file->getFileName() );
45
+ if ( 'RP4WP_Filter' != $class ) {
46
+ self::$filters[$class] = new $class;
47
+ }
48
+
49
+ }
50
+ }
51
+
52
+ }
53
+
54
+ /**
55
+ * Return instance of created hook
56
+ *
57
+ * @param $class_name
58
+ *
59
+ * @return RP4WP_Filter
60
+ */
61
+ public static function get_filter_object( $class_name ) {
62
+ if ( isset( self::$filters[$class_name] ) ) {
63
+ return self::$filters[$class_name];
64
+ }
65
+
66
+ return null;
67
+ }
68
+
69
+ }
70
+
71
+ }
72
+
trunk/classes/class-manager-hook.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ if ( ! class_exists( 'RP4WP_Manager_Hook' ) ) {
8
+
9
+ class RP4WP_Manager_Hook {
10
+
11
+ private $hook_dir;
12
+ private static $hooks;
13
+
14
+ public function __construct( $hook_dir ) {
15
+ $this->hook_dir = $hook_dir;
16
+ }
17
+
18
+ /**
19
+ * Load and set hooks
20
+ *
21
+ * @access public
22
+ * @static
23
+ * @return void
24
+ */
25
+ public function load_hooks() {
26
+
27
+ foreach ( new DirectoryIterator( $this->hook_dir ) as $file ) {
28
+
29
+ if ( ! $file->isDir() && ( strpos( $file->getFileName(), '.' ) !== 0 ) ) {
30
+
31
+ $class = RP4WP_Class_Manager::format_class_name( $file->getFileName() );
32
+ if ( 'RP4WP_Hook' != $class ) {
33
+ self::$hooks[$class] = new $class;
34
+ }
35
+
36
+ }
37
+
38
+ }
39
+
40
+ }
41
+
42
+ /**
43
+ * Return instance of created hook
44
+ *
45
+ * @param $class_name
46
+ *
47
+ * @return RP4WP_Hook
48
+ */
49
+ public static function get_hook_object( $class_name ) {
50
+ if ( isset( self::$hooks[$class_name] ) ) {
51
+ return self::$hooks[$class_name];
52
+ }
53
+
54
+ return null;
55
+ }
56
+
57
+ }
58
+
59
+ }
trunk/classes/class-nag-manager.php ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ if ( ! class_exists( 'RP4WP_Nag_Manager' ) ) {
8
+ class RP4WP_Nag_Manager {
9
+
10
+ /**
11
+ * Get the admin query string
12
+ *
13
+ * @since 1.3.0
14
+ * @access public
15
+ *
16
+ * @return mixed
17
+ */
18
+ private function get_admin_query_string_array() {
19
+ parse_str( $_SERVER['QUERY_STRING'], $params );
20
+
21
+ return $params;
22
+ }
23
+
24
+ /**
25
+ * Insert the install date
26
+ *
27
+ * @since 1.3.0
28
+ * @access public
29
+ *
30
+ * @return string
31
+ */
32
+ private function insert_install_date() {
33
+ $datetime_now = new DateTime();
34
+ $date_string = $datetime_now->format( 'Y-m-d' );
35
+ add_site_option( RP4WP_Constants::OPTION_INSTALL_DATE, $date_string, '', 'no' );
36
+
37
+ return $date_string;
38
+ }
39
+
40
+ /**
41
+ * get the install date
42
+ *
43
+ * @since 1.3.0
44
+ * @access private
45
+ *
46
+ * @return DateTime
47
+ */
48
+ private function get_install_date() {
49
+ $date_string = get_site_option( RP4WP_Constants::OPTION_INSTALL_DATE, '' );
50
+ if ( $date_string == '' ) {
51
+ // There is no install date, plugin was installed before version 1.2.0. Add it now.
52
+ $date_string = $this->insert_install_date();
53
+ }
54
+
55
+ return new DateTime( $date_string );
56
+ }
57
+
58
+ /**
59
+ * Setup the nag manager
60
+ *
61
+ * @since 1.3.0
62
+ * @access public
63
+ *
64
+ * @return bool
65
+ */
66
+ public function setup() {
67
+
68
+ // Check user rights
69
+ if ( current_user_can( 'install_plugins' ) ) {
70
+
71
+ // Get current user
72
+ $current_user = wp_get_current_user();
73
+
74
+ // Get user meta
75
+ $hide_notice = get_user_meta( $current_user->ID, RP4WP_Constants::OPTION_ADMIN_NOTICE_KEY, true );
76
+
77
+ // Check if the notice is already dismissed
78
+ if ( '' == $hide_notice ) {
79
+ // Get installation date
80
+ $datetime_install = $this->get_install_date();
81
+ $datetime_past = new DateTime( '-10 days' );
82
+
83
+ if ( $datetime_past >= $datetime_install ) {
84
+ // 10 or more days ago, show admin notice
85
+ add_action( 'admin_notices', array( $this, 'display_admin_notice' ) );
86
+ }
87
+ }
88
+
89
+ // Catch the hide notice
90
+ $this->catch_hide_notice();
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Display the admin notice
96
+ *
97
+ * @since 1.3.0
98
+ * @access public
99
+ */
100
+ public function display_admin_notice() {
101
+ $query_params = $this->get_admin_query_string_array();
102
+ $query_string = '?' . http_build_query( array_merge( $query_params, array( RP4WP_Constants::OPTION_ADMIN_NOTICE_KEY => '1' ) ) );
103
+
104
+ echo '<div class="updated"><p>';
105
+ printf( __( "You've been using %sRelated Posts for WordPress%s for some time now, could you please give it a review at wordpress.org?", 'related-posts-for-wp' ), '<b>', '</b>' );
106
+ echo "<br /><br />";
107
+ printf( __( "%sYes, take me there!%s - %sI've already done this!%s", 'related-posts-for-wp' ), '<a href="http://wordpress.org/support/view/plugin-reviews/related-posts-for-wp" target="_blank">', '</a>', '<a href="' . $query_string . '">', '</a>' );
108
+ echo "</p></div>";
109
+ }
110
+
111
+ /**
112
+ * Catch the hide notice click
113
+ *
114
+ * @since 1.0.0
115
+ * @access public
116
+ */
117
+ public function catch_hide_notice() {
118
+ if ( isset( $_GET[RP4WP_Constants::OPTION_ADMIN_NOTICE_KEY] ) && current_user_can( 'install_plugins' ) ) {
119
+ // Add user meta
120
+ global $current_user;
121
+ add_user_meta( $current_user->ID, RP4WP_Constants::OPTION_ADMIN_NOTICE_KEY, '1', true );
122
+
123
+ // Build redirect URL
124
+ $query_params = $this->get_admin_query_string_array();
125
+ unset( $query_params[RP4WP_Constants::OPTION_ADMIN_NOTICE_KEY] );
126
+ $query_string = http_build_query( $query_params );
127
+ if ( $query_string != '' ) {
128
+ $query_string = '?' . $query_string;
129
+ }
130
+
131
+ $redirect_url = 'http';
132
+ if ( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] == 'on' ) {
133
+ $redirect_url .= 's';
134
+ }
135
+ $redirect_url .= '://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . $query_string;
136
+
137
+ // Redirect
138
+ wp_redirect( $redirect_url );
139
+ exit;
140
+ }
141
+ }
142
+
143
+ }
144
+ }
trunk/classes/class-post-link-manager.php ADDED
@@ -0,0 +1,396 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Post_Link_Manager {
8
+
9
+ private $temp_child_order;
10
+
11
+ public function __construct() {
12
+ }
13
+
14
+ /**
15
+ * Create query arguments used to fetch links
16
+ *
17
+ * @access private
18
+ *
19
+ * @param int $post_id
20
+ * @param string $meta_key
21
+ *
22
+ * @return array
23
+ */
24
+ private function create_link_args( $meta_key, $post_id ) {
25
+ $args = array(
26
+ 'post_type' => RP4WP_Constants::LINK_PT,
27
+ 'posts_per_page' => - 1,
28
+ 'orderby' => 'menu_order',
29
+ 'order' => 'ASC',
30
+ 'meta_query' => array(
31
+ array(
32
+ 'key' => $meta_key,
33
+ 'value' => $post_id,
34
+ 'compare' => '=',
35
+ )
36
+ )
37
+ );
38
+
39
+ return $args;
40
+ }
41
+
42
+ /**
43
+ * Get amount of links based on post type link id and (post) parent id
44
+ *
45
+ * @access private
46
+ *
47
+ * @param int $parent_id
48
+ *
49
+ * @return int
50
+ */
51
+ private function get_link_count( $parent_id ) {
52
+ $link_query = new WP_Query(
53
+ array(
54
+ 'fields' => 'ids',
55
+ 'post_type' => RP4WP_Constants::LINK_PT,
56
+ 'posts_per_page' => - 1,
57
+ 'orderby' => 'menu_order',
58
+ 'order' => 'ASC',
59
+ 'meta_query' => array(
60
+ array(
61
+ 'key' => RP4WP_Constants::PM_PARENT,
62
+ 'value' => $parent_id,
63
+ 'compare' => '=',
64
+ ),
65
+ )
66
+ )
67
+ );
68
+
69
+ // Reset global post variables
70
+ wp_reset_postdata();
71
+
72
+ return $link_query->found_posts;
73
+ }
74
+
75
+ /**
76
+ * Method to add a PostLink
77
+ *
78
+ * @access public
79
+ *
80
+ * @param int $parent_id
81
+ * @param int $child_id
82
+ * @param boolean $batch
83
+ *
84
+ * @return int ($link_id)
85
+ */
86
+ public function add( $parent_id, $child_id, $batch = false ) {
87
+ global $wpdb;
88
+
89
+ // Setup the insert data
90
+ $data = array(
91
+ 'post' => "('" . current_time( 'mysql', 0 ) . "', '" . current_time( 'mysql', 1 ) . "','','Related Posts for WordPress Link','" . RP4WP_Constants::LINK_PT . "','publish')",
92
+ 'meta' => array(
93
+ "(%d, '" . RP4WP_Constants::PM_PARENT . "', '$parent_id')",
94
+ "(%d, '" . RP4WP_Constants::PM_CHILD . "', '$child_id')",
95
+ )
96
+ );
97
+
98
+ // If this is a batch insert, return data
99
+ if ( true === $batch ) {
100
+ return $data;
101
+ }
102
+
103
+ // Create post link
104
+ $wpdb->query( " INSERT INTO `$wpdb->posts`
105
+ (`post_date`,`post_date_gmt`,`post_content`,`post_title`,`post_type`,`post_status`)
106
+ VALUES
107
+ {$data['post']}
108
+ " );
109
+
110
+ $link_id = $wpdb->insert_id;
111
+
112
+ // Create post meta
113
+ $wpdb->query(
114
+ $wpdb->prepare(
115
+ "INSERT INTO `$wpdb->postmeta`
116
+ (`post_id`,`meta_key`,`meta_value`)
117
+ VALUES
118
+ {$data['meta'][0]},
119
+ {$data['meta'][1]},
120
+ {$data['meta'][2]}
121
+ ", $link_id, $link_id, $link_id ) );
122
+
123
+ // Do action rp4wp_after_link_add
124
+ do_action( 'rp4wp_after_link_add', $link_id );
125
+
126
+ // Return link id
127
+ return $link_id;
128
+ }
129
+
130
+ /**
131
+ * Delete a link
132
+ *
133
+ * @access public
134
+ *
135
+ * @param id $link_id
136
+ *
137
+ * @return void
138
+ */
139
+ public function delete( $link_id ) {
140
+ // Action
141
+ do_action( 'rp4wp_before_link_delete', $link_id );
142
+
143
+ // Delete link
144
+ wp_delete_post( $link_id, true );
145
+
146
+ // Action
147
+ do_action( 'rp4wp_after_link_delete', $link_id );
148
+
149
+ return;
150
+ }
151
+
152
+ /**
153
+ * Get children based on parent_id.
154
+ * It's possible to add extra arguments to the WP_Query with the $extra_args argument
155
+ *
156
+ * @access public
157
+ *
158
+ * @param int $parent_id
159
+ * @param array $extra_args
160
+ *
161
+ * @return array
162
+ */
163
+ public function get_children( $parent_id, $extra_args = null ) {
164
+ global $post;
165
+
166
+ // Store current post
167
+ $o_post = $post;
168
+
169
+ // Do WP_Query
170
+ $link_args = $this->create_link_args( RP4WP_Constants::PM_PARENT, $parent_id );
171
+
172
+ /*
173
+ * Check $extra_args for `posts_per_page`.
174
+ * This is the only arg that should be added to link query instead of the child query
175
+ */
176
+ if ( isset( $extra_args['posts_per_page'] ) ) {
177
+
178
+ // Set posts_per_page to link arguments
179
+ $link_args['posts_per_page'] = $extra_args['posts_per_page'];
180
+ unset( $extra_args['posts_per_page'] );
181
+ }
182
+
183
+ /*
184
+ * Check $extra_args for `order`.
185
+ * If 'order' is set without 'orderby', we should add it to the link arguments
186
+ */
187
+ if ( isset( $extra_args['order'] ) && ! isset( $extra_args['orderby'] ) ) {
188
+ $link_args['order'] = $extra_args['order'];
189
+ unset( $extra_args['order'] );
190
+ }
191
+
192
+ // Create link query
193
+ $link_query = new WP_Query( $link_args );
194
+
195
+ // Store child ids
196
+ // @todo remove the usage of get_the_id()
197
+ $child_ids = array();
198
+ while ( $link_query->have_posts() ) : $link_query->the_post();
199
+ $child_ids[get_the_id()] = get_post_meta( get_the_id(), RP4WP_Constants::PM_CHILD, true );
200
+ endwhile;
201
+
202
+ // Get children with custom args
203
+ if ( $extra_args !== null && count( $extra_args ) > 0 ) {
204
+
205
+ if ( ! isset( $extra_args['orderby'] ) ) {
206
+ $this->temp_child_order = array();
207
+ foreach ( $child_ids as $child_id ) {
208
+ $this->temp_child_order[] = $child_id;
209
+ }
210
+ }
211
+
212
+ // Get child again, but this time by $extra_args
213
+ $children = array();
214
+
215
+ //Child WP_Query arguments
216
+ if ( count( $child_ids ) > 0 ) {
217
+ $child_id_values = array_values( $child_ids );
218
+ $child_post_type = get_post_type( array_shift( $child_id_values ) );
219
+ $child_args = array(
220
+ 'post_type' => $child_post_type,
221
+ 'posts_per_page' => - 1,
222
+ 'post__in' => $child_ids,
223
+ );
224
+
225
+ // Extra arguments
226
+ $child_args = array_merge_recursive( $child_args, $extra_args );
227
+
228
+ // Child Query
229
+ $child_query = new WP_Query( $child_args );
230
+
231
+ while ( $child_query->have_posts() ) : $child_query->the_post();
232
+ // Add post to correct original sort key
233
+ $children[array_search( $child_query->post->ID, $child_ids )] = $child_query->post;
234
+ endwhile;
235
+
236
+ // Fix sorting
237
+ if ( ! isset( $extra_args['orderby'] ) ) {
238
+ uasort( $children, array( $this, 'sort_get_children_children' ) );
239
+ }
240
+
241
+ }
242
+ } else {
243
+ // No custom arguments found, get all objects of stored ID's
244
+ $children = array();
245
+ foreach ( $child_ids as $link_id => $child_id ) {
246
+ $children[$link_id] = get_post( $child_id );
247
+ }
248
+ }
249
+
250
+ // Reset global post variables
251
+ wp_reset_postdata();
252
+
253
+ // Restoring post
254
+ $post = $o_post;
255
+
256
+ // Return children
257
+ return $children;
258
+ }
259
+
260
+ /**
261
+ * Custom sort method to reorder children
262
+ *
263
+ * @param $a
264
+ * @param $b
265
+ *
266
+ * @return mixed
267
+ */
268
+ public function sort_get_children_children( $a, $b ) {
269
+ return array_search( $a->ID, $this->temp_child_order ) - array_search( $b->ID, $this->temp_child_order );
270
+ }
271
+
272
+ /**
273
+ * Delete all links involved in given post_id
274
+ *
275
+ * @access public
276
+ *
277
+ * @param $post_id
278
+ */
279
+ public function delete_links_related_to( $post_id ) {
280
+ $involved_query = new WP_Query( array(
281
+ 'post_type' => RP4WP_Constants::LINK_PT,
282
+ 'posts_per_page' => - 1,
283
+ 'meta_query' => array(
284
+ 'relation' => 'OR',
285
+ array(
286
+ 'key' => RP4WP_Constants::PM_PARENT,
287
+ 'value' => $post_id,
288
+ 'compare' => '=',
289
+ ),
290
+ array(
291
+ 'key' => RP4WP_Constants::PM_CHILD,
292
+ 'value' => $post_id,
293
+ 'compare' => '=',
294
+ )
295
+ )
296
+ ) );
297
+ while ( $involved_query->have_posts() ) : $involved_query->the_post();
298
+ wp_delete_post( $involved_query->post->ID, true );
299
+ endwhile;
300
+ }
301
+
302
+ /**
303
+ * Generate the children list
304
+ *
305
+ * @param $id
306
+ *
307
+ * @since 1.0.0
308
+ * @access public
309
+ *
310
+ * @return string
311
+ */
312
+ public function generate_children_list( $id ) {
313
+
314
+ // The content
315
+ $content = '';
316
+
317
+ // Get the children
318
+ $related_posts = $this->get_children( $id );
319
+
320
+ // Count
321
+ if ( count( $related_posts ) > 0 ) {
322
+
323
+ // The rp4wp block
324
+ $content .= "<div class='rp4wp-related-posts'>\n";
325
+
326
+ // Get the heading text
327
+ $heading_text = RP4WP::get()->settings->get_option( 'heading_text' );
328
+
329
+ // Check if there is a heading text
330
+ if ( '' != $heading_text ) {
331
+
332
+ // Add heading text plus heading elements
333
+ $heading_text = '<h3>' . $heading_text . '</h3>' . PHP_EOL;
334
+ }
335
+
336
+ // Filter complete heading
337
+ $content .= apply_filters( 'rp4wp_heading', $heading_text );
338
+
339
+ // Open the list
340
+ $content .= "<ul>\n";
341
+
342
+
343
+ foreach ( $related_posts as $rp4wp_post ) {
344
+
345
+ // Setup the postdata
346
+ setup_postdata( $rp4wp_post );
347
+
348
+ // Output the linked post
349
+ $content .= "<li>";
350
+
351
+ if ( 1 == RP4WP::get()->settings->get_option( 'display_image' ) ) {
352
+ if ( has_post_thumbnail( $rp4wp_post->ID ) ) {
353
+
354
+ /**
355
+ * Filter: 'rp4wp_apdc_thumbnail_size' - Allows changing the thumbnail size of the thumbnail in de APDC section
356
+ *
357
+ * @api String $thumbnail_size The current/default thumbnail size.
358
+ */
359
+ $thumb_size = apply_filters( 'rp4wp_thumbnail_size', 'thumbnail' );
360
+
361
+ $content .= "<div class='rp4wp-related-post-image'>" . PHP_EOL;
362
+ $content .= "<a href='" . get_permalink( $rp4wp_post->ID ) . "'>";
363
+ $content .= get_the_post_thumbnail( $rp4wp_post->ID, $thumb_size );
364
+ $content .= "</a>";
365
+ $content .= "</div>" . PHP_EOL;
366
+ }
367
+ }
368
+
369
+ $content .= "<div class='rp4wp-related-post-content'>" . PHP_EOL;
370
+ $content .= "<a href='" . get_permalink( $rp4wp_post->ID ) . "'>" . $rp4wp_post->post_title . "</a>";
371
+
372
+ $excerpt_length = RP4WP::get()->settings->get_option( 'excerpt_length' );
373
+ if ( $excerpt_length > 0 ) {
374
+ $excerpt = ( ( '' != $rp4wp_post->post_excerpt ) ? $rp4wp_post->post_excerpt : wp_trim_words( $rp4wp_post->post_content, $excerpt_length ) );
375
+ $content .= "<p>" . $excerpt . "</p>";
376
+ }
377
+
378
+ $content .= "</div>" . PHP_EOL;
379
+
380
+ $content .= "</li>\n";
381
+
382
+ // Reset the postdata
383
+ wp_reset_postdata();
384
+ }
385
+
386
+ // Close the wrapper div
387
+ $content .= "</ul>\n";
388
+ $content .= "</div>\n";
389
+
390
+ }
391
+
392
+ return $content;
393
+
394
+ }
395
+
396
+ }
trunk/classes/class-related-post-manager.php ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Related_Post_Manager {
8
+
9
+ /**
10
+ * Get related posts by post id and post type
11
+ *
12
+ * @param $post_id
13
+ *
14
+ * @return array
15
+ */
16
+ public function get_related_posts( $post_id, $limit = - 1 ) {
17
+ global $wpdb;
18
+
19
+ // Build SQl
20
+ $sql = "
21
+ SELECT O.`word`, P.`ID`, P.`post_title`, SUM( R.`weight` ) AS `related_weight`
22
+ FROM `" . RP4WP_Related_Word_Manager::get_database_table() . "` O
23
+ INNER JOIN `" . RP4WP_Related_Word_Manager::get_database_table() . "` R ON R.`word` = O.`word`
24
+ INNER JOIN `" . $wpdb->posts . "` P ON P.`ID` = R.`post_id`
25
+ WHERE 1=1
26
+ AND O.`post_id` = %d
27
+ AND R.`post_type` = 'post'
28
+ AND R.`post_id` != %d
29
+ AND P.`post_status` = 'publish'
30
+ GROUP BY P.`id`
31
+ ORDER BY `related_weight` DESC
32
+ ";
33
+
34
+ // Check & Add Limit
35
+ if ( - 1 != $limit ) {
36
+ $sql .= "
37
+ LIMIT 0,%d";
38
+ // Prepare SQL
39
+ $sql = $wpdb->prepare( $sql, $post_id, $post_id, $limit );
40
+ } else {
41
+ // Prepare SQL
42
+ $sql = $wpdb->prepare( $sql, $post_id, $post_id );
43
+ }
44
+
45
+ // Get post from related cache
46
+ return $wpdb->get_results( $sql );
47
+ }
48
+
49
+ /**
50
+ * Get non auto linked posts
51
+ *
52
+ * @param $limit
53
+ *
54
+ * @return array
55
+ */
56
+ public function get_not_auto_linked_posts_ids( $limit ) {
57
+ return get_posts( array(
58
+ 'fields' => 'ids',
59
+ 'post_type' => 'post',
60
+ 'posts_per_page' => $limit,
61
+ 'post_status' => 'publish',
62
+ 'meta_query' => array(
63
+ array(
64
+ 'key' => RP4WP_Constants::PM_POST_AUTO_LINKED,
65
+ 'compare' => 'NOT EXISTS',
66
+ 'value' => ''
67
+ ),
68
+ )
69
+ ) );
70
+ }
71
+
72
+ /**
73
+ * Get the uncached post count
74
+ *
75
+ * @since 1.6.0
76
+ * @access public
77
+ *
78
+ * @return mixed
79
+ */
80
+ public function get_uncached_post_count() {
81
+ global $wpdb;
82
+
83
+ $post_count = $wpdb->get_var( "SELECT COUNT(P.ID) FROM " . $wpdb->posts . " P LEFT JOIN wp_postmeta PM ON (P.ID = PM.post_id AND PM.meta_key = '" . RP4WP_Constants::PM_POST_AUTO_LINKED . "') WHERE 1=1 AND P.post_type = 'post' AND P.post_status = 'publish' AND PM.post_id IS NULL GROUP BY P.post_status" );
84
+
85
+ if ( ! is_numeric( $post_count ) ) {
86
+ $post_count = 0;
87
+ }
88
+
89
+ return $post_count;
90
+ }
91
+
92
+ /**
93
+ * Link x related posts to post
94
+ *
95
+ * @param $post_id
96
+ * @param $amount
97
+ *
98
+ * @return boolean
99
+ */
100
+ public function link_related_post( $post_id, $amount ) {
101
+ $related_posts = $this->get_related_posts( $post_id, $amount );
102
+
103
+ if ( count( $related_posts ) > 0 ) {
104
+
105
+ global $wpdb;
106
+
107
+ $post_link_manager = new RP4WP_Post_Link_Manager();
108
+
109
+ $batch_data = array();
110
+ foreach ( $related_posts as $related_post ) {
111
+ $batch_data[] = $post_link_manager->add( $post_id, $related_post->ID, true );
112
+ }
113
+
114
+ // Do batch insert
115
+ $wpdb->query( "INSERT INTO `$wpdb->posts`
116
+ (`post_date`,`post_date_gmt`,`post_content`,`post_title`,`post_type`,`post_status`)
117
+ VALUES
118
+ " . implode( ',', array_map( array( $this, 'batch_data_get_post' ), $batch_data ) ) . "
119
+ " );
120
+
121
+ // Get the first post link insert ID
122
+ $pid = $wpdb->insert_id;
123
+
124
+ // Set the correct ID's for batch meta insert
125
+ foreach ( $batch_data as $bk => $bd ) {
126
+ $batch_data[$bk]['meta'] = array_map( array( $this, 'batch_data_set_pid' ), $bd['meta'], array_fill( 0, count( $bd['meta'] ), $pid ) );
127
+ $pid ++;
128
+ }
129
+
130
+ // Insert all the meta
131
+ $wpdb->query( "INSERT INTO `$wpdb->postmeta`
132
+ (`post_id`,`meta_key`,`meta_value`)
133
+ VALUES
134
+ " . implode( ',', array_map( array( $this, 'batch_data_get_meta' ), $batch_data ) ) . "
135
+ ");
136
+
137
+ }
138
+
139
+ update_post_meta( $post_id, RP4WP_Constants::PM_POST_AUTO_LINKED, 1 );
140
+
141
+ return true;
142
+ }
143
+
144
+ /**
145
+ * Get post batch data
146
+ *
147
+ * @param $batch
148
+ *
149
+ * @since 1.0.0
150
+ * @access public
151
+ *
152
+ * @return mixed
153
+ */
154
+ public function batch_data_get_post( $batch ) {
155
+ return $batch['post'];
156
+ }
157
+
158
+ /**
159
+ * Get meta batch data
160
+ *
161
+ * @param $batch
162
+ *
163
+ * @since 1.0.0
164
+ * @access public
165
+ *
166
+ * @return string
167
+ */
168
+ public function batch_data_get_meta( $batch ) {
169
+ return implode(',',$batch['meta']);
170
+ }
171
+
172
+ /**
173
+ * Set the post ID's in batch data
174
+ *
175
+ * @param $batch
176
+ * @param $pid
177
+ *
178
+ * @since 1.0.0
179
+ * @access public
180
+ *
181
+ * @return string
182
+ */
183
+ public function batch_data_set_pid( $batch, $pid ) {
184
+ return sprintf( $batch, $pid );
185
+ }
186
+
187
+ /**
188
+ * Link x related posts to y not already linked posts
189
+ *
190
+ * @param int $rel_amount
191
+ * @param int $post_amount
192
+ *
193
+ * @return boolean
194
+ */
195
+ public function link_related_posts( $rel_amount, $post_amount = - 1 ) {
196
+ global $wpdb;
197
+
198
+ // Get uncached posts
199
+ $post_ids = $this->get_not_auto_linked_posts_ids( $post_amount );
200
+
201
+ // Check & Loop
202
+ if ( count( $post_ids ) > 0 ) {
203
+ foreach ( $post_ids as $post_id ) {
204
+ $this->link_related_post( $post_id, $rel_amount );
205
+ }
206
+ }
207
+
208
+ // Done
209
+ return true;
210
+ }
211
+
212
+ }
trunk/classes/class-related-posts-widget.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Related_Posts_Widget extends WP_Widget {
8
+
9
+ public function __construct() {
10
+ // Parent construct
11
+ parent::__construct(
12
+ 'rp4wp_related_posts_widget',
13
+ __( 'Related Posts for WordPress', 'related-posts-for-wp' ),
14
+ array( 'description' => __( 'Display related posts.', 'related-posts-for-wp' ) )
15
+ );
16
+ }
17
+
18
+ public function widget( $args, $instance ) {
19
+
20
+ // Get the current ID
21
+ $id = get_the_ID();
22
+
23
+ // Not on frontpage please
24
+ if ( is_front_page() && false === is_page() ) {
25
+ return;
26
+ }
27
+
28
+ // Post Link Manager
29
+ $pl_manager = new RP4WP_Post_Link_Manager();
30
+
31
+ // Get content
32
+ $widget_content = $pl_manager->generate_children_list( $id );
33
+
34
+ // Only display if there's content
35
+ if ( '' != $widget_content ) {
36
+ // Output the widget
37
+ echo $args['before_widget'];
38
+ echo $widget_content;
39
+ echo $args['after_widget'];
40
+ }
41
+
42
+ }
43
+ }
trunk/classes/class-related-word-manager.php ADDED
@@ -0,0 +1,431 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Related_Word_Manager {
8
+
9
+ const DB_TABLE = 'rp4wp_cache';
10
+
11
+ private $ignored_words = null;
12
+
13
+ /**
14
+ * Get the database table
15
+ *
16
+ * @return string
17
+ */
18
+ public static function get_database_table() {
19
+ global $wpdb;
20
+
21
+ return $wpdb->prefix . self::DB_TABLE;
22
+ }
23
+
24
+ /**
25
+ * Internal method that formats and outputs the $ignored_words array to screen
26
+ */
27
+ public function dedupe_and_order_ignored_words( $lang ) {
28
+ $output = '$ignored_words = array(';
29
+
30
+ $ignored_words = $this->get_ignored_words( $lang );
31
+
32
+ $temp_words = array();
33
+ foreach ( $ignored_words as $word ) {
34
+
35
+ // Only add word if it's not already added
36
+ if ( ! in_array( $word, $temp_words ) ) {
37
+ if ( false !== strpos( $word, "Ã" ) ) {
38
+ continue;
39
+ }
40
+ $temp_words[] = str_ireplace( "'", "", $word );
41
+ }
42
+
43
+ }
44
+
45
+ sort( $temp_words );
46
+
47
+
48
+ foreach ( $temp_words as $word ) {
49
+ $output .= " '{$word}',";
50
+ }
51
+
52
+
53
+ $output .= ");";
54
+
55
+ echo $output;
56
+ die();
57
+ }
58
+
59
+ /**
60
+ * Get the ignored words
61
+ *
62
+ * @param string $lang
63
+ *
64
+ * @return array
65
+ */
66
+ private function get_ignored_words( $lang = '' ) {
67
+
68
+ if ( null == $this->ignored_words ) {
69
+ // Set the language
70
+ if ( '' == $lang ) {
71
+ $lang = get_locale();
72
+ }
73
+
74
+ // Require the lang file
75
+ $relative_path = '/ignored-words/' . $lang . '.php';
76
+
77
+ // Validate the file path to prevent traversal attacks
78
+ if ( 0 !== validate_file( $relative_path ) ) {
79
+ return array();
80
+ }
81
+
82
+ $filename = dirname( __FILE__ ) . $relative_path;
83
+
84
+ // Check if file exists
85
+ if ( ! file_exists( $filename ) ) {
86
+ return array();
87
+ }
88
+
89
+ // Require the file
90
+ $ignored_words = require( $filename );
91
+
92
+ // Check if the the $ignored_words are set
93
+ if ( is_null( $ignored_words ) || ! is_array( $ignored_words ) ) {
94
+ return array();
95
+ }
96
+
97
+ // Words to ignore
98
+ $this->ignored_words = apply_filters( 'rp4wp_ignored_words', $ignored_words );
99
+ }
100
+
101
+ return $this->ignored_words;
102
+ }
103
+
104
+ /**
105
+ * Get the words from the post content
106
+ *
107
+ * @param $post
108
+ *
109
+ * @return array $words
110
+ */
111
+ private function get_content_words( $post ) {
112
+
113
+ $content = $post->post_content;
114
+
115
+ // Remove all line break
116
+ $content = trim( preg_replace( '/\s+/', ' ', $content ) );
117
+
118
+ // Array to store the linked words
119
+ $linked_words = array();
120
+
121
+ // Find all links in the content
122
+ if ( true == preg_match_all( '`<a[^>]*href="([^"]+)">[^<]*</a>`si', $content, $matches ) ) {
123
+ if ( count( $matches[1] ) > 0 ) {
124
+
125
+ // Loop
126
+ foreach ( $matches[1] as $url ) {
127
+
128
+ // Get the post Id
129
+ $link_post_id = url_to_postid( $url );
130
+
131
+ if ( 0 == $link_post_id ) {
132
+ continue;
133
+ }
134
+
135
+ // Get the post
136
+ $link_post = get_post( $link_post_id );
137
+
138
+ // Check if we found a linked post
139
+ if ( $link_post != null ) {
140
+ // Get words of title
141
+ $title_words = explode( ' ', $link_post->post_title );
142
+
143
+ // Check, Loop
144
+ if ( is_array( $title_words ) && count( $title_words ) > 0 ) {
145
+ $linked_words = $this->add_words_from_array( $linked_words, $title_words, 20 );
146
+ }
147
+ }
148
+
149
+ }
150
+
151
+ }
152
+ }
153
+
154
+ // Remove all html tags
155
+ $content = strip_tags( $content );
156
+
157
+ // Remove all shortcodes
158
+ $content = strip_shortcodes( $content );
159
+
160
+ // Remove the <!--more--> tag
161
+ $content = str_ireplace( '<!--more-->', '', $content );
162
+
163
+ // Remove everything but letters and numbers
164
+ // $content = preg_replace( '/[^a-z0-9]+/i', ' ', $content );
165
+
166
+ // Split string into words
167
+ $words = explode( ' ', $content );
168
+
169
+ foreach ( $words as $word_key => $word_val ) {
170
+ $words[$word_key] = iconv( "utf-8", "us-ascii//TRANSLIT", $word_val );
171
+ }
172
+
173
+ // Add the $linked_words
174
+ $words = array_merge( $words, $linked_words );
175
+
176
+ // Return the $words
177
+ return $words;
178
+ }
179
+
180
+ /**
181
+ * Add words from an array to the "base" words array, multiplied by their weight
182
+ *
183
+ * @param array $base_words
184
+ * @param array $words
185
+ * @param int $weight
186
+ *
187
+ * @return array
188
+ */
189
+ private function add_words_from_array( array $base_words, $words, $weight = 1 ) {
190
+
191
+ if ( ! is_array( $words ) ) {
192
+ return $base_words;
193
+ }
194
+
195
+ foreach ( $words as $word ) {
196
+ $word_multiplied_by_weight = array_fill( 0, $weight, iconv( "utf-8", "us-ascii//TRANSLIT", $word ) );
197
+ $base_words = array_merge( $base_words, $word_multiplied_by_weight );
198
+ }
199
+
200
+ return $base_words;
201
+ }
202
+
203
+ /**
204
+ * Get the words of a post
205
+ *
206
+ * @param int $post_id
207
+ *
208
+ * @return array $words
209
+ */
210
+ public function get_words_of_post( $post_id ) {
211
+
212
+ setlocale( LC_CTYPE, 'en_US.UTF8' );
213
+
214
+ $post = get_post( $post_id );
215
+
216
+ $title_weight = apply_filters( 'rp4wp_weight_title', 80 );
217
+ $tag_weight = apply_filters( 'rp4wp_weight_tag', 10 );
218
+ $cat_weight = apply_filters( 'rp4wp_weight_cat', 20 );
219
+
220
+ // Get raw words
221
+ $raw_words = $this->get_content_words( $post );
222
+
223
+ // Get words from title
224
+ $title_words = explode( ' ', $post->post_title );
225
+ $raw_words = $this->add_words_from_array( $raw_words, $title_words, $title_weight );
226
+
227
+ // Get tags and add them to list
228
+ $tags = wp_get_post_tags( $post->ID, array( 'fields' => 'names' ) );
229
+
230
+ if ( is_array( $tags ) && count( $tags ) > 0 ) {
231
+ foreach ( $tags as $tag ) {
232
+ $tag_words = explode( ' ', $tag );
233
+ $raw_words = $this->add_words_from_array( $raw_words, $tag_words, $tag_weight );
234
+ }
235
+ }
236
+
237
+ // Get categories and add them to list
238
+ $categories = wp_get_post_categories( $post->ID, array( 'fields' => 'names' ) );
239
+ if ( is_array( $categories ) && count( $categories ) > 0 ) {
240
+ foreach ( $categories as $category ) {
241
+ $cat_words = explode( ' ', $category );
242
+ $raw_words = $this->add_words_from_array( $raw_words, $cat_words, $cat_weight );
243
+ }
244
+ }
245
+
246
+ // Count words and store them in array
247
+ $words = array();
248
+
249
+ if ( is_array( $raw_words ) && count( $raw_words ) > 0 ) {
250
+
251
+ $ignored_words = $this->get_ignored_words();
252
+
253
+ foreach ( $raw_words as $word ) {
254
+
255
+ // Trim word
256
+ $word = strtolower( trim( $word ) );
257
+
258
+ // Only use words longer than 1 charecter
259
+ if ( strlen( $word ) < 2 ) {
260
+ continue;
261
+ }
262
+
263
+ // Skip ignored words
264
+ if ( in_array( $word, $ignored_words ) ) {
265
+ continue;
266
+ }
267
+
268
+ // Add word
269
+ if ( isset( $words[$word] ) ) {
270
+ $words[$word] += 1;
271
+ } else {
272
+ $words[$word] = 1;
273
+ }
274
+
275
+ }
276
+ }
277
+
278
+ $new_words = array();
279
+ $total_raw_words = count( $raw_words );
280
+ $length_weight = 0.6;
281
+
282
+ foreach ( $words as $word => $amount ) {
283
+
284
+ if ( $amount < 3 ) {
285
+ continue; // Don't add words that occur less than 3 times
286
+ }
287
+
288
+ // Add word and turn amount into weight (make it relative)
289
+ $new_words[$word] = ( $amount / ( $length_weight * $total_raw_words ) );
290
+
291
+ }
292
+
293
+ return $new_words;
294
+ }
295
+
296
+ /**
297
+ * Save words of given post
298
+ *
299
+ * @param $post_id
300
+ */
301
+ public function save_words_of_post( $post_id ) {
302
+ global $wpdb;
303
+
304
+ // Get words
305
+ $words = $this->get_words_of_post( $post_id );
306
+
307
+ // Check words
308
+ if ( is_array( $words ) && count( $words ) > 0 ) {
309
+
310
+ // Delete all currents words of post
311
+ $this->delete_words( $post_id );
312
+
313
+ // Loop words
314
+ foreach ( $words as $word => $amount ) {
315
+
316
+ // Insert word row
317
+ $wpdb->insert(
318
+ self::get_database_table(),
319
+ array(
320
+ 'post_id' => $post_id,
321
+ 'word' => $word,
322
+ 'weight' => $amount,
323
+ 'post_type' => 'post'
324
+ ),
325
+ array(
326
+ '%d',
327
+ '%s',
328
+ '%f',
329
+ '%s',
330
+ )
331
+ );
332
+
333
+ }
334
+
335
+ }
336
+
337
+ // Update this post as cached
338
+ update_post_meta( $post_id, RP4WP_Constants::PM_CACHED, 1 );
339
+
340
+ }
341
+
342
+ /**
343
+ * Get uncached posts
344
+ *
345
+ * @param int $limit
346
+ *
347
+ * @return array
348
+ */
349
+ public function get_uncached_post_ids( $limit = - 1 ) {
350
+
351
+ // Get Posts without 'cached' PM
352
+ return get_posts( array(
353
+ 'fields' => 'ids',
354
+ 'post_type' => 'post',
355
+ 'posts_per_page' => $limit,
356
+ 'post_status' => 'publish',
357
+ 'meta_query' => array(
358
+ array(
359
+ 'key' => RP4WP_Constants::PM_CACHED,
360
+ 'compare' => 'NOT EXISTS',
361
+ 'value' => ''
362
+ ),
363
+ )
364
+ ) );
365
+
366
+ }
367
+
368
+ /**
369
+ * Get the uncached post count
370
+ *
371
+ * @since 1.6.0
372
+ * @access public
373
+ *
374
+ * @return mixed
375
+ */
376
+ public function get_uncached_post_count() {
377
+ global $wpdb;
378
+
379
+ $post_count = $wpdb->get_var( "SELECT COUNT(P.ID) FROM " . $wpdb->posts . " P LEFT JOIN wp_postmeta PM ON (P.ID = PM.post_id AND PM.meta_key = '" . RP4WP_Constants::PM_CACHED . "') WHERE 1=1 AND P.post_type = 'post' AND P.post_status = 'publish' AND PM.post_id IS NULL GROUP BY P.post_status" );
380
+
381
+ if ( ! is_numeric( $post_count ) ) {
382
+ $post_count = 0;
383
+ }
384
+
385
+ return $post_count;
386
+ }
387
+
388
+ /**
389
+ * Save all words of posts
390
+ */
391
+ public function save_all_words( $limit = - 1 ) {
392
+ global $wpdb;
393
+
394
+ // Get uncached posts
395
+ $post_ids = $this->get_uncached_post_ids( $limit );
396
+
397
+ // Check & Loop
398
+ if ( count( $post_ids ) > 0 ) {
399
+ foreach ( $post_ids as $post_id ) {
400
+ $this->save_words_of_post( $post_id );
401
+ }
402
+ }
403
+
404
+ // Done
405
+ return true;
406
+ }
407
+
408
+ /**
409
+ * Get the amount of words of a post
410
+ *
411
+ *
412
+ * @return int
413
+ */
414
+ public function get_word_count() {
415
+ global $wpdb;
416
+
417
+ return $wpdb->get_var( "SELECT COUNT(word) FROM `" . self::get_database_table() . "` WHERE `post_type` = 'post'" );
418
+ }
419
+
420
+ /**
421
+ * Delete words by post ID
422
+ *
423
+ * @param $post_id
424
+ */
425
+ public function delete_words( $post_id ) {
426
+ global $wpdb;
427
+
428
+ $wpdb->delete( self::get_database_table(), array( 'post_id' => $post_id ), array( '%d' ) );
429
+ }
430
+
431
+ }
trunk/classes/class-rp4wp.php ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP {
8
+
9
+ private static $instance = null;
10
+
11
+ const VERSION = '1.7.0';
12
+
13
+ /**
14
+ * @var RP4WP_Settings
15
+ */
16
+ public $settings = null;
17
+
18
+ /**
19
+ * Singleton get method
20
+ *
21
+ * @since 1.0.0
22
+ * @access public
23
+ *
24
+ * @return RP4WP
25
+ */
26
+ public static function get() {
27
+ if ( null == self::$instance ) {
28
+ self::$instance = new self();
29
+ }
30
+
31
+ return self::$instance;
32
+ }
33
+
34
+ /**
35
+ * Get the plugin file
36
+ *
37
+ * @access public
38
+ * @static
39
+ * @return String
40
+ */
41
+ public static function get_plugin_file() {
42
+ return RP4WP_PLUGIN_FILE;
43
+ }
44
+
45
+ /**
46
+ * A static method that will setup the autoloader
47
+ */
48
+ private static function setup_autoloader() {
49
+ require_once( plugin_dir_path( self::get_plugin_file() ) . '/classes/class-autoloader.php' );
50
+ $autoloader = new RP4WP_Autoloader( plugin_dir_path( self::get_plugin_file() ) . 'classes/' );
51
+ spl_autoload_register( array( $autoloader, 'load' ) );
52
+ }
53
+
54
+ /**
55
+ * The constructor
56
+ */
57
+ private function __construct() {
58
+ $this->init();
59
+ }
60
+
61
+ /**
62
+ * Initialize the plugin
63
+ */
64
+ private function init() {
65
+
66
+ // Setup the autoloader
67
+ self::setup_autoloader();
68
+
69
+ // Load plugin text domain
70
+ load_plugin_textdomain( 'related-posts-for-wp', false, dirname( plugin_basename( RP4WP_PLUGIN_FILE ) ) . '/languages/' );
71
+
72
+ // Check if we need to run the installer
73
+ if ( is_admin() && get_site_option( RP4WP_Constants::OPTION_DO_INSTALL, false ) ) {
74
+
75
+ // Delete do install site option
76
+ delete_site_option( RP4WP_Constants::OPTION_DO_INSTALL );
77
+
78
+ // Redirect to installation wizard
79
+ wp_redirect( admin_url() . '?page=rp4wp_install', 307 );
80
+ exit;
81
+ }
82
+
83
+ if ( is_admin() ) {
84
+ // Check if we need to display an 'is installing' notice
85
+ $is_installing_notice = new RP4WP_Is_Installing_Notice();
86
+ $is_installing_notice->check();
87
+ }
88
+
89
+ // Setup settings
90
+ add_action( 'init', array( $this, 'setup_settings' ) );
91
+
92
+ // Filters
93
+ $manager_filter = new RP4WP_Manager_Filter( plugin_dir_path( RP4WP_PLUGIN_FILE ) . 'classes/filters/' );
94
+ $manager_filter->load_filters();
95
+
96
+ // Hooks
97
+ $manager_hook = new RP4WP_Manager_Hook( plugin_dir_path( RP4WP_PLUGIN_FILE ) . 'classes/hooks/' );
98
+ $manager_hook->load_hooks();
99
+
100
+ // Include template functions
101
+ if ( ! is_admin() ) {
102
+ require_once( plugin_dir_path( self::get_plugin_file() ) . '/includes/template-functions.php' );
103
+ }
104
+
105
+ // Setup the nag
106
+ if ( is_admin() ) {
107
+ $nag_manager = new RP4WP_Nag_Manager();
108
+ $nag_manager->setup();
109
+ }
110
+
111
+ }
112
+
113
+ /**
114
+ * Setup the settings
115
+ *
116
+ * @since 1.6.2
117
+ * @access public
118
+ */
119
+ public function setup_settings() {
120
+ $this->settings = new RP4WP_Settings();
121
+ }
122
+
123
+ }
124
+
125
+ /**
126
+ * @since 1.0.0
127
+ * @access public
128
+ *
129
+ * @return RP4WP
130
+ */
131
+ function RP4WP() {
132
+ return RP4WP::get();
133
+ }
trunk/classes/filters/class-filter-after-post.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Filter_After_Post extends RP4WP_Filter {
8
+ protected $tag = 'the_content';
9
+ protected $priority = 99;
10
+
11
+ /**
12
+ * the_content filter that will add linked posts to the bottom of the main post content
13
+ *
14
+ * @param $content
15
+ *
16
+ * @return string
17
+ */
18
+ public function run( $content ) {
19
+ /**
20
+ * Wow, what's going on here?! Well, setup_postdata() sets a lot of variables but does not change the $post variable.
21
+ * All checks return the main queried ID but we want to check if this specific filter call is the for the 'main' content.
22
+ * The method setup_postdata() does global and set the $id variable, so we're checking that.
23
+ */
24
+ global $id;
25
+
26
+ // Only run on single
27
+ if ( ! is_singular() || ! is_main_query() || $id != get_queried_object_id() ) {
28
+ return $content;
29
+ }
30
+
31
+ // Allow disabling content filter
32
+ if ( false === apply_filters( 'rp4wp_append_content', true ) ) {
33
+ return $content;
34
+ }
35
+
36
+ // Post Link Manager
37
+ $pl_manager = new RP4WP_Post_Link_Manager();
38
+
39
+ // Generate the content
40
+ $content .= $pl_manager->generate_children_list( $id );
41
+
42
+ // Return content
43
+ return $content;
44
+ }
45
+ }
trunk/classes/filters/class-filter-plugin-links.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ if ( ! class_exists( 'RP4WP_Filter_Plugin_Links' ) ) {
8
+
9
+ class RP4WP_Filter_Plugin_Links extends RP4WP_Filter {
10
+ protected $tag = 'plugin_action_links_related-posts-for-wp/related-posts-for-wp.php';
11
+
12
+ /**
13
+ * Add custom plugin links
14
+ *
15
+ * @param array $links
16
+ *
17
+ * @since 1.4.0
18
+ * @access public
19
+ *
20
+ * @return array
21
+ */
22
+ public function run( $links ) {
23
+ array_unshift( $links, '<a href="' . admin_url( 'options-general.php?page=rp4wp' ) . '">' . __( 'Settings', 'related-posts-for-wp' ) . '</a>' );
24
+ array_unshift( $links, '<a href="https://www.relatedpostsforwp.com/?utm_source=plugin&utm_medium=link&utm_campaign=plugins-page" target="_blank" style="color:green;font-weight:bold;">' . __( 'Upgrade to Premium', 'related-posts-for-wp' ) . '</a>' );
25
+
26
+ return $links;
27
+ }
28
+ }
29
+
30
+ }
trunk/classes/filters/class-filter.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ abstract class RP4WP_Filter {
8
+ protected $tag = null;
9
+ protected $priority = 10;
10
+ protected $args = 1;
11
+
12
+ /**
13
+ * Construct method. Set tag and register hook.
14
+ *
15
+ * @access public
16
+ */
17
+ public function __construct() {
18
+ $this->register();
19
+ }
20
+
21
+ /**
22
+ * Register the hook.
23
+ *
24
+ * @access public
25
+ * @return void
26
+ */
27
+ public function register() {
28
+ // Tag must be set
29
+ if ( $this->tag === null ) {
30
+ trigger_error( 'ERROR IN FILTER: NO TAG SET', E_USER_ERROR );
31
+ }
32
+
33
+ add_filter( $this->tag, array( $this, 'run' ), $this->priority, $this->args );
34
+ }
35
+
36
+ /**
37
+ * Get the args
38
+ *
39
+ * @return int
40
+ */
41
+ public function get_args() {
42
+ return $this->args;
43
+ }
44
+
45
+ /**
46
+ * Get the priority
47
+ *
48
+ * @return int
49
+ */
50
+ public function get_priority() {
51
+ return $this->priority;
52
+ }
53
+
54
+ /**
55
+ * Get the tag
56
+ *
57
+ * @return string
58
+ */
59
+ public function get_tag() {
60
+ return $this->tag;
61
+ }
62
+
63
+
64
+ }
trunk/classes/hooks/class-hook-admin-scripts.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Hook_Admin_Scripts extends RP4WP_Hook {
8
+ protected $tag = 'admin_enqueue_scripts';
9
+
10
+ public function run() {
11
+ global $pagenow;
12
+
13
+ // Post screen
14
+ if ( $pagenow == 'post.php' || $pagenow == 'post-new.php' ) {
15
+
16
+ // Load PL JS
17
+ wp_enqueue_script(
18
+ 'rp4wp_edit_post_js',
19
+ plugins_url( '/assets/js/edit-post' . ( ( ! SCRIPT_DEBUG ) ? '.min' : '' ) . '.js', RP4WP::get_plugin_file() ),
20
+ array( 'jquery', 'jquery-ui-sortable' )
21
+ );
22
+
23
+ // Make JavaScript strings translatable
24
+ wp_localize_script( 'rp4wp_edit_post_js', 'rp4wp_js', RP4WP_Javascript_Strings::get() );
25
+
26
+ // CSS
27
+ wp_enqueue_style(
28
+ 'rp4wp_edit_post_css',
29
+ plugins_url( '/assets/css/edit-post.css', RP4WP::get_plugin_file() )
30
+ );
31
+ }
32
+
33
+ }
34
+ }
trunk/classes/hooks/class-hook-ajax-delete-link.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Hook_Ajax_Delete_Link extends RP4WP_Hook {
8
+ protected $tag = 'wp_ajax_rp4wp_delete_link';
9
+
10
+ /**
11
+ * Hook into admin AJAX to delete a link
12
+ *
13
+ * @access public
14
+ * @return void
15
+ */
16
+ public function run() {
17
+
18
+ // id,
19
+ if ( ! isset( $_POST['id'] ) ) {
20
+ exit;
21
+ }
22
+
23
+ // Post id into $post_id
24
+ $post_id = $_POST['id'];
25
+
26
+ // Check nonce
27
+ check_ajax_referer( 'rp4wp-ajax-nonce-omgrandomword', 'nonce' );
28
+
29
+ // Check if user is allowed to do this
30
+ if ( ! current_user_can( 'edit_posts' ) ) {
31
+ return;
32
+ }
33
+
34
+ // Load post
35
+ $target_post = get_post( $post_id );
36
+
37
+ // Only delete post type we control
38
+ if ( $target_post->post_type != RP4WP_Constants::LINK_PT ) {
39
+ return;
40
+ }
41
+
42
+ // Delete link
43
+ $post_link_manager = new RP4WP_Post_Link_Manager();
44
+ $post_link_manager->delete( $target_post->ID );
45
+
46
+ // Generate JSON response
47
+ $response = json_encode( array( 'success' => true ) );
48
+ header( 'Content-Type: application/json' );
49
+ echo $response;
50
+
51
+ // Bye
52
+ exit();
53
+ }
54
+
55
+ }
trunk/classes/hooks/class-hook-ajax-install-link-posts.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Hook_Ajax_Install_Link_Posts extends RP4WP_Hook {
8
+ protected $tag = 'wp_ajax_rp4wp_install_link_posts';
9
+
10
+ public function run() {
11
+
12
+ // Get the PPR
13
+ $ppr = isset( $_POST['ppr'] ) ? $_POST['ppr'] : 5;
14
+
15
+ // Get the rel amount
16
+ $rel_amount = isset( $_POST['rel_amount'] ) ? $_POST['rel_amount'] : 3;
17
+
18
+ // Related Post Manager object
19
+ $related_post_manager = new RP4WP_Related_Post_Manager();
20
+
21
+ // Link posts
22
+ $related_post_manager->link_related_posts( $rel_amount, $ppr );
23
+
24
+ // Get uncached post count
25
+ $uncached_post_count = $related_post_manager->get_uncached_post_count();
26
+
27
+ // Check if we're done
28
+ if ( 0 == $uncached_post_count ) {
29
+ // Save the wizard setting as the option
30
+ $options = RP4WP()->settings->get_options();
31
+ $options['automatic_linking_post_amount'] = $rel_amount;
32
+ update_option( 'rp4wp', $options );
33
+ }
34
+
35
+ // Echo the uncached posts
36
+ echo $uncached_post_count;
37
+
38
+ exit;
39
+ }
40
+
41
+ }
trunk/classes/hooks/class-hook-ajax-install-save-words.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Hook_Ajax_Install_Save_Words extends RP4WP_Hook {
8
+ protected $tag = 'wp_ajax_rp4wp_install_save_words';
9
+
10
+ public function run() {
11
+
12
+ // Get the PPR
13
+ $ppr = isset( $_POST['ppr'] ) ? $_POST['ppr'] : 25;
14
+
15
+ // Related Post Manager
16
+ $related_word_manager = new RP4WP_Related_Word_Manager();
17
+
18
+ // Save words
19
+ $related_word_manager->save_all_words( $ppr );
20
+
21
+ // Get uncached post count
22
+ $uncached_post_count = $related_word_manager->get_uncached_post_count();
23
+
24
+ // Echo the uncached posts
25
+ echo $uncached_post_count;
26
+
27
+ exit;
28
+ }
29
+
30
+ }
trunk/classes/hooks/class-hook-delete-words.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Hook_Delete_Words extends RP4WP_Hook {
8
+ protected $tag = 'delete_post';
9
+ protected $args = 1;
10
+
11
+ public function run( $post_id ) {
12
+
13
+ // Check if the current user can delete posts
14
+ if ( ! current_user_can( 'delete_posts' ) ) {
15
+ return;
16
+ }
17
+
18
+ // Related Post Manager
19
+ $related_word_manager = new RP4WP_Related_Word_Manager();
20
+ $related_word_manager->delete_words( $post_id );
21
+
22
+ }
23
+ }
trunk/classes/hooks/class-hook-frontend-css.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Hook_Frontend_Css extends RP4WP_Hook {
8
+ protected $tag = 'wp_head';
9
+
10
+ public function run() {
11
+ if ( is_single() ) {
12
+ $css = trim( RP4WP::get()->settings->get_option( 'css' ) );
13
+ if ( '' != $css ) {
14
+ echo "<style type='text/css'>" . $css . "</style>" . PHP_EOL;
15
+ }
16
+ }
17
+ }
18
+ }
trunk/classes/hooks/class-hook-link-related-screen.php ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Hook_Link_Related_Screen extends RP4WP_Hook {
8
+ protected $tag = 'admin_menu';
9
+
10
+ public function run() {
11
+ $this->check_if_allowed();
12
+
13
+ $this->handle_create_link();
14
+ $this->handle_bulk_link();
15
+
16
+ // Add Page
17
+ add_submenu_page( null, 'Link_Related_Screen', 'Link_Related_Screen', 'edit_posts', 'rp4wp_link_related', array( $this, 'content' ) );
18
+ }
19
+
20
+ /**
21
+ * Check if the current user is allowed to create related posts
22
+ */
23
+ private function check_if_allowed() {
24
+ if ( ! current_user_can( 'edit_posts' ) ) {
25
+ wp_die( 'There was a problem loading this page, you may not have the necessary permissions.' );
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Handle the create link action
31
+ */
32
+ private function handle_create_link() {
33
+
34
+ // Check if link is chosen
35
+ if ( isset( $_GET['rp4wp_create_link'] ) && isset( $_GET['rp4wp_parent'] ) ) {
36
+
37
+ // Check if user is allowed to do this
38
+ if ( ! current_user_can( 'edit_posts' ) ) {
39
+ return;
40
+ }
41
+
42
+ // Get parent
43
+ $parent = $_GET['rp4wp_parent'];
44
+
45
+ // Create link
46
+ $post_link_manager = new RP4WP_Post_Link_Manager();
47
+
48
+ // Create link
49
+ $post_link_manager->add( $parent, $_GET['rp4wp_create_link'] );
50
+
51
+ // Send back
52
+ $redirect_url = get_admin_url() . "post.php?post={$parent}&action=edit";
53
+
54
+ // WPML check
55
+ if ( isset( $_GET['lang'] ) ) {
56
+ $redirect_url .= "&amp;lang=" . $_GET['lang'];
57
+ }
58
+
59
+ wp_redirect( $redirect_url );
60
+ exit;
61
+ }
62
+
63
+ }
64
+
65
+ /**
66
+ * Handle the bulk creation of links
67
+ */
68
+ private function handle_bulk_link() {
69
+
70
+ if ( isset( $_POST['rp4wp_bulk'] ) && isset( $_GET['rp4wp_parent'] ) ) {
71
+
72
+ // Get parent
73
+ $parent = $_GET['rp4wp_parent'];
74
+
75
+ // Check if user is allowed to do this
76
+ if ( ! current_user_can( 'edit_posts' ) ) {
77
+ return;
78
+ }
79
+
80
+ // Post Link Manager
81
+ $post_link_manager = new RP4WP_Post_Link_Manager();
82
+
83
+ if ( count( $_POST['rp4wp_bulk'] ) > 0 ) {
84
+ foreach ( $_POST['rp4wp_bulk'] as $bulk_post ) {
85
+
86
+ // Create link
87
+ $post_link_manager->add( $parent, $bulk_post );
88
+
89
+ }
90
+ }
91
+
92
+ // Send back
93
+ $redirect_url = get_admin_url() . "post.php?post={$parent}&action=edit";
94
+
95
+ // WPML check
96
+ if ( isset( $_GET['lang'] ) ) {
97
+ $redirect_url .= "&amp;lang=" . $_GET['lang'];
98
+ }
99
+
100
+ wp_redirect( $redirect_url );
101
+ exit;
102
+
103
+ }
104
+
105
+ }
106
+
107
+ /**
108
+ * The screen content
109
+ */
110
+ public function content() {
111
+
112
+ if ( ! isset( $_GET['rp4wp_parent'] ) ) {
113
+ wp_die( "Can't load page, no parent set. Please contact support and provide them this message" );
114
+ }
115
+
116
+ // Parent
117
+ $parent = $_GET['rp4wp_parent'];
118
+
119
+ // Setup cancel URL
120
+ $cancel_url = get_admin_url() . "post.php?post={$parent}&action=edit";
121
+
122
+ // Catch search string
123
+ $search = null;
124
+ if ( isset( $_POST['s'] ) && $_POST['s'] != '' ) {
125
+ $search = $_POST['s'];
126
+ }
127
+
128
+ ?>
129
+ <div class="wrap">
130
+ <h2>
131
+ <?php _e( 'Posts', 'related-posts-for-wp' ); ?>
132
+ <a href="<?php echo $cancel_url; ?>" class="add-new-h2"><?php _e( 'Cancel linking', 'related-posts-for-wp' ); ?></a>
133
+ </h2>
134
+
135
+ <form id="sp-list-table-form" method="post">
136
+ <input type="hidden" name="page" value="<?php echo $_REQUEST['page'] ?>" />
137
+ <?php
138
+ // Create the link table
139
+ $list_table = new RP4WP_Link_Related_Table();
140
+
141
+ // Set the search
142
+ $list_table->set_search( $search );
143
+
144
+ // Load the items
145
+ $list_table->prepare_items();
146
+
147
+ // Add the search box
148
+ $list_table->search_box( __( 'Search', 'related-posts-for-wp' ), 'sp-search' );
149
+
150
+ // Display the table
151
+ $list_table->display();
152
+ ?>
153
+ </form>
154
+ </div>
155
+
156
+ <?php
157
+ }
158
+ }
trunk/classes/hooks/class-hook-meta-box-ajax-sort.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Hook_Meta_Box_AJAX_Sort extends RP4WP_Hook {
8
+ protected $tag = 'wp_ajax_rp4wp_related_sort';
9
+
10
+ public function run() {
11
+ global $wpdb;
12
+
13
+ // Check nonce
14
+ check_ajax_referer( 'rp4wp-ajax-nonce-omgrandomword', 'nonce' );
15
+
16
+ // Check if user is allowed to do this
17
+ if ( ! current_user_can( 'edit_posts' ) ) {
18
+ return;
19
+ }
20
+
21
+ // Check if the items are set
22
+ if ( ! isset( $_POST['rp4wp_items'] ) ) {
23
+ return;
24
+ }
25
+
26
+ // Boom
27
+ $items = explode( ',', $_POST['rp4wp_items'] );
28
+
29
+ // Check if there are items posted
30
+ if ( count( $items ) == 0 ) {
31
+ return;
32
+ }
33
+
34
+ // Change order
35
+ $counter = 0;
36
+ foreach ( $items as $item_id ) {
37
+ $wpdb->update( $wpdb->posts, array( 'menu_order' => $counter ), array( 'ID' => $item_id ) );
38
+ $counter ++;
39
+ }
40
+
41
+ // Generate JSON response
42
+ $response = json_encode( array( 'success' => true ) );
43
+ header( 'Content-Type: application/json' );
44
+ echo $response;
45
+
46
+ // Bye
47
+ exit();
48
+ }
49
+
50
+ }
trunk/classes/hooks/class-hook-meta-box.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Hook_Meta_Box extends RP4WP_Hook {
8
+ protected $tag = 'admin_init';
9
+
10
+ public function run() {
11
+ new RP4WP_Meta_Box_Manage();
12
+ }
13
+ }
trunk/classes/hooks/class-hook-page-install.php ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Hook_Page_Install extends RP4WP_Hook {
8
+ protected $tag = 'admin_menu';
9
+
10
+ public function run() {
11
+
12
+ $menu_hook = add_submenu_page( null, 'RP4WPINSTALL', 'RP4WPINSTALL', 'edit_posts', 'rp4wp_install', array( $this, 'content' ) );
13
+
14
+ add_action( 'load-' . $menu_hook, array( $this, 'enqueue_install_assets' ) );
15
+ }
16
+
17
+ /**
18
+ * Enqueue install assets
19
+ *
20
+ * @since 1.0.0
21
+ * @access public
22
+ */
23
+ public function enqueue_install_assets() {
24
+ global $wp_scripts;
25
+ wp_enqueue_style( 'rp4wp-install-css', plugins_url( '/assets/css/install.css', RP4WP::get_plugin_file() ) );
26
+ wp_enqueue_script( 'rp4wp-install-js', plugins_url( '/assets/js/install' . ( ( ! SCRIPT_DEBUG ) ? '.min' : '' ) . '.js', RP4WP::get_plugin_file() ), array( 'jquery', 'jquery-ui-core', 'jquery-ui-progressbar' ) );
27
+ wp_enqueue_style( 'jquery-ui-smoothness', "http://ajax.googleapis.com/ajax/libs/jqueryui/" . $wp_scripts->query( 'jquery-ui-core' )->ver . "/themes/smoothness/jquery-ui.css", false, null );
28
+ }
29
+
30
+ /**
31
+ * The screen content
32
+ *
33
+ * @since 1.0.0
34
+ * @access public
35
+ */
36
+ public function content() {
37
+
38
+ // Do we have a reinstall?
39
+ if ( isset( $_GET['reinstall'] ) ) {
40
+
41
+ // Check nonce
42
+ if ( ! wp_verify_nonce( ( isset( $_GET['rp4wp_nonce'] ) ? $_GET['rp4wp_nonce'] : '' ), RP4WP_Constants::NONCE_INSTALL ) ) {
43
+ wp_die( 'Woah! It looks like something else tried to run the Related Posts for WordPress installation wizard! We were able to stop them, nothing was lost. Please report this incident at <a href="http://wordpress.org/support/plugin/related-posts-for-wp" target="_blank">our forums.</a>' );
44
+ }
45
+
46
+ global $wpdb;
47
+
48
+ // Get ID's of related post link posts
49
+ $link_ids = get_posts(
50
+ array(
51
+ 'post_type' => RP4WP_Constants::LINK_PT,
52
+ 'fields' => 'ids',
53
+ 'posts_per_page' => - 1
54
+ )
55
+ );
56
+
57
+ // Only run queries if we have ID's
58
+ if ( count( $link_ids ) > 0 ) {
59
+ // Delete all link posts
60
+ $wpdb->query( "DELETE FROM $wpdb->posts WHERE `ID` IN (" . implode( ",", $link_ids ) . ");" );
61
+
62
+ // Delete all link post meta
63
+ $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE `post_id` IN (" . implode( ",", $link_ids ) . ");" );
64
+ }
65
+
66
+ // Remove the post meta we attached to posts
67
+ $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE `meta_key` = 'rp4wp_auto_linked' OR `meta_key` = 'rp4wp_cached' " );
68
+
69
+ // Empty word cache
70
+ $wpdb->query( "DELETE FROM " . RP4WP_Related_Word_Manager::get_database_table() . " WHERE 1=1" );
71
+ }
72
+
73
+ // The steps
74
+ $steps = array(
75
+ 1 => __( 'Caching Posts', 'related-posts-for-wp' ),
76
+ 2 => __( 'Linking Posts', 'related-posts-for-wp' ),
77
+ 3 => __( 'Finished', 'related-posts-for-wp' ),
78
+ );
79
+
80
+ // What's the current step?
81
+ $cur_step = isset( $_GET['step'] ) ? $_GET['step'] : 1;
82
+
83
+ // Check installer resume options
84
+ if ( 1 == $cur_step ) {
85
+ // Add is installing site option
86
+ add_site_option( RP4WP_Constants::OPTION_IS_INSTALLING, true );
87
+ } elseif ( 3 == $cur_step ) {
88
+ // Installer is done, remove the option
89
+ delete_site_option( RP4WP_Constants::OPTION_IS_INSTALLING );
90
+ }
91
+
92
+ ?>
93
+ <div class="wrap">
94
+ <h2>Related Posts for WordPress <?php _e( 'Installation', 'related-posts-for-wp' ); ?></h2>
95
+
96
+ <ul class="install-steps">
97
+ <?php
98
+
99
+ foreach ( $steps as $step => $label ) {
100
+ echo "<li id='step-bar-" . $step . "'" . ( ( $cur_step == $step ) ? " class='step-bar-active'" : "" ) . "><span>" . $step . '. ' . $label . "</span></li>" . PHP_EOL;
101
+ }
102
+ ?>
103
+ </ul>
104
+ <br class="clear" />
105
+
106
+ <h3><?php echo $steps[$cur_step]; ?></h3>
107
+
108
+ <?php
109
+ $cur_step = isset( $_GET['step'] ) ? $_GET['step'] : 1;
110
+ echo "<div class='rp4wp-step rp4wp-step-" . $cur_step . "' rel='" . $cur_step . "'>";
111
+
112
+ // Hidden fields
113
+ echo "<input type='hidden' id='rp4wp_total_posts' value='" . wp_count_posts( 'post' )->publish . "' />" . PHP_EOL;
114
+ echo "<input type='hidden' id='rp4wp_admin_url' value='" . admin_url() . "' />" . PHP_EOL;
115
+
116
+ if ( 1 == $cur_step ) {
117
+
118
+ // Echo current uncached posts
119
+ $related_word_manager = new RP4WP_Related_Word_Manager();
120
+ echo "<input type='hidden' id='rp4wp_uncached_posts' value='" . $related_word_manager->get_uncached_post_count() . "' />" . PHP_EOL;
121
+
122
+ ?>
123
+ <p><?php _e( 'Thank you for choosing Related Posts for WordPress!', 'related-posts-for-wp' ); ?></p>
124
+ <p><?php _e( 'Before you can start using Related Posts for WordPress we need to cache your current posts.', 'related-posts-for-wp' ); ?></p>
125
+ <p><?php _e( "This is a one time process which might take some time now, depending on the amount of posts you have, but will ensure your website's performance when using the plugin.", 'related-posts-for-wp' ); ?></p>
126
+
127
+ <p style="font-weight: bold;"><?php _e( 'Do NOT close this window, wait for this process to finish and this wizard to take you to the next step.', 'related-posts-for-wp' ); ?></p>
128
+
129
+ <div id="progressbar"></div>
130
+ <?php
131
+ } elseif ( 2 == $cur_step ) {
132
+
133
+ // Echo current uncached posts
134
+ $related_post_manager = new RP4WP_Related_Post_Manager();
135
+ echo "<input type='hidden' id='rp4wp_uncached_posts' value='" . $related_post_manager->get_uncached_post_count() . "' />" . PHP_EOL;
136
+
137
+ ?>
138
+ <p style="font-weight: bold;"><?php _e( 'Great! All your posts were successfully cached!', 'related-posts-for-wp' ); ?></p>
139
+ <p><?php _e( "You can let me link your posts, based on what I think is related, to each other. And don't worry, if I made a mistake at one of your posts you can easily correct this by editing it manually!", 'related-posts-for-wp' ); ?></p>
140
+ <p><?php _e( 'Want me to start linking posts to each other? Fill in the amount of related posts each post should have and click on the "Link now" button. Rather link your posts manually? Click "Skip linking".', 'related-posts-for-wp' ); ?></p>
141
+ <p style="font-weight: bold;"><?php _e( 'Do NOT close this window if you click the "Link now" button, wait for this process to finish and this wizard to take you to the next step.', 'related-posts-for-wp' ); ?></p>
142
+ <br class="clear" />
143
+ <p class="rp4wp-install-link-box">
144
+ <label for="rp4wp_related_posts_amount"><?php _e( 'Amount of related posts per post:', 'related-posts-for-wp' ); ?></label><input class="form-input-tip" type="text" id="rp4wp_related_posts_amount" value="<?php echo RP4WP()->settings->get_option( 'automatic_linking_post_amount' ); ?>" />
145
+ <a href="javascript:;" class="button button-primary button-large rp4wp-link-now-btn" id="rp4wp-link-now"><?php _e( 'Link now', 'related-posts-for-wp' ); ?></a>
146
+ <a href="<?php echo admin_url(); ?>?page=rp4wp_install&step=3" class="button"><?php _e( 'Skip linking', 'related-posts-for-wp' ); ?></a>
147
+ </p>
148
+ <br class="clear" />
149
+ <div id="progressbar"></div>
150
+ <?php
151
+ } elseif ( 3 == $cur_step ) {
152
+ ?>
153
+ <p><?php _e( "That's it, you're good to go!", 'related-posts-for-wp' ); ?></p>
154
+ <p><?php printf( __( 'Thanks again for using Related Posts for WordPress and if you have any questions be sure to ask them at the %sWordPress.org forums.%s', 'related-posts-for-wp' ), '<a href="http://wordpress.org/support/plugin/related-posts-for-wp" target="_blank">', '</a>' ); ?></p>
155
+ <?php
156
+ }
157
+ ?>
158
+ </div>
159
+
160
+ </div>
161
+
162
+ <?php
163
+ }
164
+
165
+ }
trunk/classes/hooks/class-hook-post-type.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Hook_Post_Type extends RP4WP_Hook {
8
+ protected $tag = 'init';
9
+
10
+ public function run() {
11
+ register_post_type( RP4WP_Constants::LINK_PT, array( 'public' => false, 'label' => 'Related Posts for WordPress Link' ) );
12
+ }
13
+ }
trunk/classes/hooks/class-hook-related-auto-link.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Hook_Related_Auto_Link extends RP4WP_Hook {
8
+ protected $tag = 'save_post';
9
+ protected $args = 2;
10
+ protected $priority = 11;
11
+
12
+ public function run( $post_id, $post ) {
13
+
14
+ // verify this is not an auto save routine.
15
+ if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
16
+ return;
17
+ }
18
+
19
+ // Only count on post type 'post'
20
+ if ( 'post' != $post->post_type ) {
21
+ return;
22
+ }
23
+
24
+ // Check permission
25
+ if ( ! current_user_can( 'edit_post', $post_id ) ) {
26
+ return;
27
+ }
28
+
29
+ // Post status must be publish
30
+ if ( 'publish' != $post->post_status ) {
31
+ return;
32
+ }
33
+
34
+ // Is automatic linking enabled?
35
+ if ( 1 != RP4WP::get()->settings->get_option( 'automatic_linking' ) ) {
36
+ return;
37
+ }
38
+
39
+ // Check if the current post is already auto linked
40
+ if ( 1 != get_post_meta( $post_id, RP4WP_Constants::PM_POST_AUTO_LINKED, true ) ) {
41
+
42
+ // Get automatic linking post amount
43
+ $automatic_linking_post_amount = RP4WP::get()->settings->get_option( 'automatic_linking_post_amount' );
44
+
45
+ // Related Posts Manager
46
+ $related_post_manager = new RP4WP_Related_Post_Manager();
47
+
48
+ // Link related posts
49
+ $related_post_manager->link_related_post( $post_id, $automatic_linking_post_amount );
50
+
51
+ // Set the auto linked meta
52
+ update_post_meta( $post_id, RP4WP_Constants::PM_POST_AUTO_LINKED, 1 );
53
+ }
54
+
55
+ }
56
+ }
trunk/classes/hooks/class-hook-related-save-words.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Hook_Related_Save_Words extends RP4WP_Hook {
8
+ protected $tag = 'save_post';
9
+ protected $args = 2;
10
+
11
+ public function run( $post_id, $post ) {
12
+
13
+ // verify this is not an auto save routine.
14
+ if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
15
+ return;
16
+ }
17
+
18
+ // Only count on post type 'post'
19
+ if ( 'post' != $post->post_type ) {
20
+ return;
21
+ }
22
+
23
+ // Check permission
24
+ if ( ! current_user_can( 'edit_post', $post_id ) ) {
25
+ return;
26
+ }
27
+
28
+ // Post status must be publish
29
+ if ( 'publish' != $post->post_status ) {
30
+ return;
31
+ }
32
+
33
+ // Save Words
34
+ $related_word_manager = new RP4WP_Related_Word_Manager();
35
+ $related_word_manager->save_words_of_post( $post_id );
36
+
37
+ }
38
+ }
trunk/classes/hooks/class-hook-settings-page.php ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Hook_Settings_Page extends RP4WP_Hook {
8
+ protected $tag = 'admin_menu';
9
+
10
+ /**
11
+ * Hook callback, add the sub menu page
12
+ *
13
+ * @since 1.1.0
14
+ * @access public
15
+ */
16
+ public function run() {
17
+ $menu_hook = add_submenu_page( 'options-general.php', __( 'Related Posts', 'related-posts-for-wp' ), __( 'Related Posts', 'related-posts-for-wp' ), 'manage_options', 'rp4wp', array(
18
+ $this,
19
+ 'screen'
20
+ ) );
21
+
22
+ add_action( 'load-' . $menu_hook, array( $this, 'enqueue_assets' ) );
23
+ }
24
+
25
+ /**
26
+ * Enqueue settings page assets
27
+ *
28
+ * @since 1.0.0
29
+ * @access public
30
+ */
31
+ public function enqueue_assets() {
32
+ wp_enqueue_style( 'rp4wp-settings-css', plugins_url( '/assets/css/settings.css', RP4WP::get_plugin_file() ) );
33
+ }
34
+
35
+ /**
36
+ * The sidebar
37
+ *
38
+ * @since 1.0.0
39
+ * @access private
40
+ */
41
+ private function sidebar() {
42
+ ?>
43
+ <div class="rp4wp-sidebar">
44
+
45
+ <div class="rp4wp-box">
46
+ <div class="rp4wp-sidebar-header">
47
+ <h3>Related Posts for WordPress</h3>
48
+ </div>
49
+
50
+ <p><?php _e( 'Plugin version', 'related-posts-for-wp' ); ?>: <?php echo RP4WP::VERSION; ?></p>
51
+ <p><?php _e( 'Thank you for using Related Posts for WordPress!', 'related-posts-for-wp' ); ?></p>
52
+ </div>
53
+
54
+ <div class="rp4wp-box rp4wp-box-upgrade">
55
+ <h3 class="rp4wp-title"><?php _e( 'Related Posts for WordPress Premium', 'related-posts-for-wp' ); ?></h3>
56
+
57
+ <p><?php _e( "This plugin has an even better premium version, I am sure you will love it.", 'related-posts-for-wp' ); ?></p>
58
+ <p><?php _e( "Premium features include custom post type support, related post themes, custom taxonomy support and priority support.", 'related-posts-for-wp' ); ?></p>
59
+ <p><?php printf( __( "%sMore information about Related Posts for WP Premium »%s", 'related-posts-for-wp' ), '<a href="https://www.relatedpostsforwp.com/?utm_source=plugin&utm_medium=link&utm_campaign=upgrade-box" target="_blank">', '</a>' ); ?></p>
60
+ </div>
61
+
62
+ <div class="rp4wp-box">
63
+ <h3 class="rp4wp-title"><?php _e( 'Show a token of your appreciation', 'related-posts-for-wp' ); ?></h3>
64
+
65
+ <p><?php printf( __( "<a href='%s' target='_blank'>Leave a ★★★★★ plugin review on WordPress.org</a>", 'related-posts-for-wp' ), 'http://wordpress.org/support/view/plugin-reviews/related-posts-for-wp?rate=5#postform' ); ?></p>
66
+ <p><?php printf( __( "<a href='%s' target='_blank'>Tweet about Related Posts for WordPress</a>", 'related-posts-for-wp' ), 'https://twitter.com/intent/tweet?text=Showing%20my%20appreciation%20to%20%40CageNL%20for%20his%20WordPress%20plugin%3A%20Related%20Posts%20for%20WordPress%20-%20check%20it%20out!%20http%3A%2F%2Fwordpress.org%2Fplugins%2Frelated-posts-for-wp%2F' ); ?></p>
67
+ <p><?php printf( __( "Review the plugin on your blog and link to <a href='%s' target='_blank'>the plugin page</a>", 'related-posts-for-wp' ), 'https://www.relatedpostsforwp.com/?utm_source=plugin&utm_medium=link&utm_campaign=show-appreciation' ); ?></p>
68
+ <p><?php printf( __( "<a href='%s' target='_blank'>Vote 'works' on the WordPress.org plugin page</a>", 'related-posts-for-wp' ), 'http://wordpress.org/plugins/related-posts-for-wp/' ); ?></p>
69
+
70
+ </div>
71
+
72
+ <div class="rp4wp-box">
73
+ <h3 class="rp4wp-title"><?php _e( 'Looking for support?', 'related-posts-for-wp' ); ?></h3>
74
+
75
+ <p><?php printf( __( "For support please visit the <a href='%s' target='_blank'>WordPress.org forums</a>.", 'related-posts-for-wp' ), 'http://wordpress.org/support/plugin/related-posts-for-wp' ); ?></p>
76
+
77
+ <p style="color: green;font-weight: bold;"><?php printf( __( "Did you know that Related Posts for WordPress Premium clients get priority email support? %sClick here to upgrade.%s", 'related-posts-for-wp' ), '<a href="https://www.relatedpostsforwp.com/?utm_source=plugin&utm_medium=link&utm_campaign=support" target="_blank">', '</a>' ); ?></p>
78
+ </div>
79
+
80
+ <div class="rp4wp-box">
81
+ <h3 class="rp4wp-title"><?php _e( 'More information', 'related-posts-for-wp' ); ?></h3>
82
+
83
+ <p><?php printf( __( "<a href='%s' target='_blank'>FAQ</a>", 'related-posts-for-wp' ), 'https://wordpress.org/plugins/related-posts-for-wp/faq/' ); ?></p>
84
+
85
+ <p><?php printf( __( "<a href='%s' target='_blank'>Changelog</a>", 'related-posts-for-wp' ), 'https://wordpress.org/plugins/related-posts-for-wp/changelog/' ); ?></p>
86
+
87
+ <p><?php printf( __( "<a href='%s' target='_blank'>Website</a>", 'related-posts-for-wp' ), 'https://www.relatedpostsforwp.com/?utm_source=plugin&utm_medium=link&utm_campaign=more-information' ); ?></p>
88
+
89
+ </div>
90
+
91
+ <div class="rp4wp-box">
92
+ <h3 class="rp4wp-title"><?php _e( 'About the developer', 'related-posts-for-wp' ); ?></h3>
93
+
94
+ <p><?php _e( "Barry is a WordPress developer that works on WooCommerce by WooThemes and is the author of various WordPress plugins that include Related Posts for WordPress, Post Connector and What The File.", 'related-posts-for-wp' ); ?></p>
95
+
96
+ <p><?php _e( "Barry likes contributing to opensource projects and visiting WordCamps and WordPress meetups. He’s the organizer of the WordPress meetup in Tilburg.", 'related-posts-for-wp' ); ?></p>
97
+
98
+ <p><?php printf( __( "<a href='%s' target='_blank'>You can follow Barry on Twitter</a>", 'related-posts-for-wp' ), 'https://twitter.com/cageNL' ); ?></p>
99
+ </div>
100
+
101
+ </div>
102
+ <?php
103
+ }
104
+
105
+ /**
106
+ * Settings screen output
107
+ *
108
+ * @since 1.1.0
109
+ * @access public
110
+ */
111
+ public function screen() {
112
+ ?>
113
+ <div class="wrap">
114
+ <h2>Related Posts for WordPress</h2>
115
+
116
+ <div class="rp4wp-content">
117
+ <form method="post" action="options.php">
118
+ <?php settings_fields( 'rp4wp' ); //pass slug name of page, also referred
119
+ //to in Settings API as option group name
120
+ do_settings_sections( 'rp4wp' ); //pass slug name of page
121
+ submit_button();
122
+ ?>
123
+ </form>
124
+ </div>
125
+ <?php $this->sidebar(); ?>
126
+ </div>
127
+ <?php
128
+ }
129
+ }
trunk/classes/hooks/class-hook-shortcode.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Hook_Shortcode extends RP4WP_Hook {
8
+ protected $tag = 'init';
9
+
10
+ public function run() {
11
+ add_shortcode( 'rp4wp', array( $this, 'output' ) );
12
+ }
13
+
14
+ /**
15
+ * Output the shortcode
16
+ *
17
+ * @since 1.3.0
18
+ * @access public
19
+ *
20
+ */
21
+ public function output() {
22
+ // Get the current ID
23
+ $id = get_the_ID();
24
+
25
+ // Post Link Manager
26
+ $pl_manager = new RP4WP_Post_Link_Manager();
27
+
28
+ // Generate the children list
29
+ return $pl_manager->generate_children_list( $id );
30
+ }
31
+ }
trunk/classes/hooks/class-hook-widget.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Hook_Widget extends RP4WP_Hook {
8
+ protected $tag = 'widgets_init';
9
+
10
+ public function run() {
11
+ register_widget( 'RP4WP_Related_Posts_Widget' );
12
+ }
13
+ }
trunk/classes/hooks/class-hook.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ abstract class RP4WP_Hook {
8
+ protected $tag = null;
9
+ protected $priority = 10;
10
+ protected $args = 1;
11
+
12
+ /**
13
+ * Construct method. Set tag and register hook.
14
+ *
15
+ * @access public
16
+ */
17
+ public function __construct() {
18
+ $this->register();
19
+ }
20
+
21
+ /**
22
+ * Register the hook.
23
+ *
24
+ * @access public
25
+ * @return void
26
+ */
27
+ public function register() {
28
+ // Tag must be set
29
+ if ( $this->tag === null ) {
30
+ trigger_error( 'ERROR IN HOOK: NO TAG SET', E_USER_ERROR );
31
+ }
32
+
33
+ add_action( $this->tag, array( $this, 'run' ), $this->priority, $this->args );
34
+ }
35
+
36
+ /**
37
+ * Get args
38
+ *
39
+ * @return int
40
+ */
41
+ public function get_args() {
42
+ return $this->args;
43
+ }
44
+
45
+ /**
46
+ * Get priority
47
+ *
48
+ * @return int
49
+ */
50
+ public function get_priority() {
51
+ return $this->priority;
52
+ }
53
+
54
+ /**
55
+ * Get tag
56
+ *
57
+ * @return string
58
+ */
59
+ public function get_tag() {
60
+ return $this->tag;
61
+ }
62
+
63
+
64
+ }
trunk/classes/ignored-words/de_DE.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ return array( '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jahr', 'Jahre', 'Jahren', 'Millionen', 'Prozent', 'Uhr', 'ab', 'aber', 'alle', 'als', 'am', 'an', 'auch', 'auf', 'aus', 'bei', 'beim', 'bereits', 'bis', 'da', 'damit', 'dann', 'das', 'dass', 'dem', 'den', 'der', 'des', 'die', 'diese', 'diesem', 'dieser', 'doch', 'drei', 'durch', 'ein', 'eine', 'einem', 'einen', 'einer', 'eines', 'er', 'ersten', 'es', 'etwa', 'für', 'gegen', 'gibt', 'habe', 'haben', 'hat', 'hatte', 'ich', 'ihr', 'ihre', 'ihrer', 'im', 'immer', 'in', 'ist', 'jetzt', 'kann', 'keine', 'man', 'mehr', 'mit', 'muss', 'nach', 'neue', 'neuen', 'nicht', 'noch', 'nun', 'nur', 'oder', 'ohne', 'sagte', 'schon', 'sei', 'sein', 'seine', 'seinen', 'seiner', 'seit', 'selbst', 'sich', 'sie', 'sind', 'so', 'soll', 'sondern', 'um', 'und', 'unter', 'vom', 'von', 'vor', 'war', 'waren', 'was', 'wenn', 'werden', 'wie', 'wieder', 'will', 'wir', 'wird', 'worden', 'wurde', 'wurden', 'zu', 'zum', 'zur', 'zwei', 'zwischen', );
trunk/classes/ignored-words/en_US.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ return array( '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'I', 'a', 'about', 'after', 'all', 'almost', 'along', 'also', 'amp', 'an', 'and', 'another', 'any', 'are', 'area', 'around', 'as', 'at', 'available', 'back', 'be', 'because', 'been', 'being', 'best', 'better', 'big', 'bit', 'both', 'but', 'by', 'c', 'came', 'can', 'capable', 'control', 'could', 'course', 'd', 'dan', 'day', 'decided', 'did', 'didn', 'different', 'div', 'do', 'does', 'doesn', 'don', 'down', 'drive', 'e', 'each', 'easily', 'easy', 'edition', 'end', 'enough', 'even', 'every', 'example', 'few', 'find', 'first', 'for', 'found', 'from', 'get', 'go', 'going', 'good', 'got', 'gt', 'had', 'hard', 'has', 'have', 'he', 'her', 'here', 'how', 'i', 'if', 'in', 'into', 'is', 'isn', 'it', 'just', 'know', 'last', 'li', 'like', 'little', 'll', 'long', 'look', 'lot', 'lt', 'm', 'made', 'make', 'many', 'mb', 'me', 'might', 'mm', 'more', 'most', 'much', 'my', 'name', 'nbsp', 'need', 'new', 'no', 'not', 'now', 'number', 'of', 'off', 'old', 'on', 'one', 'only', 'or', 'original', 'other', 'our', 'out', 'over', 'part', 'place', 'point', 'pretty', 'probably', 'problem', 'put', 'quite', 'quot', 'r', 're', 'really', 'results', 'right', 's', 'same', 'saw', 'see', 'set', 'several', 'she', 'sherree', 'should', 'since', 'size', 'small', 'so', 'some', 'something', 'special', 'still', 'stuff', 'such', 'sure', 'system', 't', 'take', 'than', 'that', 'the', 'their', 'them', 'then', 'there', 'these', 'they', 'thing', 'things', 'think', 'this', 'those', 'though', 'through', 'time', 'to', 'today', 'together', 'too', 'took', 'two', 'up', 'us', 'use', 'used', 'using', 've', 'very', 'want', 'was', 'way', 'we', 'well', 'went', 'were', 'what', 'when', 'where', 'which', 'while', 'white', 'who', 'will', 'with', 'would', 'yes', 'you', 'your', );
trunk/classes/ignored-words/fr_FR.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ return array( '', 'a', 'abandonner', 'abattre', 'abord', 'aborder', 'abri', 'absence', 'absolu', 'absolument', 'accent', 'accepter', 'accompagner', 'accomplir', 'accord', 'accorder', 'accrocher', 'accueillir', 'accuser', 'acheter', 'achever', 'acte', 'action', 'admettre', 'adresser', 'affaire', 'affirmer', 'afin', 'agent', 'agir', 'agiter', 'ah', 'ai', 'aide', 'aider', 'aile', 'ailleurs', 'aimer', 'ainsi', 'air', 'ajouter', 'aller', 'allumer', 'alors', 'amener', 'ami', 'amour', 'amuser', 'an', 'ancien', 'anglais', 'angoisse', 'animal', 'animer', 'annoncer', 'apercevoir', 'apparence', 'appartement', 'appartenir', 'appel', 'appeler', 'apporter', 'apprendre', 'approcher', 'approuver', 'appuyer', 'arbre', 'argent', 'arme', 'armer', 'arracher', 'arriver', 'art', 'article', 'as', 'aspect', 'asseoir', 'assez', 'assister', 'assurer', 'attacher', 'attaquer', 'atteindre', 'attendre', 'attente', 'attention', 'attirer', 'attitude', 'au', 'aucun', 'aujourdhui', 'auparavant', 'auquel', 'aussi', 'autant', 'auteur', 'autour', 'autre', 'autrefois', 'autrement', 'autres', 'aux', 'auxquelles', 'auxquels', 'avance', 'avancer', 'avant', 'avec', 'avenir', 'aventure', 'avis', 'avoir', 'avouer', 'baisser', 'banc', 'bande', 'barbe', 'bas', 'bataille', 'battre', 'beau', 'beaucoup', 'beaux', 'besoin', 'bien', 'billet', 'blanc', 'bleu', 'blond', 'boire', 'bois', 'bon', 'bonheur', 'bons', 'bord', 'bouche', 'bout', 'branche', 'bras', 'briller', 'briser', 'bruit', 'brusquement', 'bureau', 'but', 'cabinet', 'cacher', 'calme', 'calmer', 'camarade', 'campagne', 'capable', 'car', 'caresser', 'carte', 'cas', 'casser', 'cause', 'causer', 'ce', 'ceci', 'cela', 'celui', 'cent', 'centre', 'cependant', 'cercle', 'certain', 'certainement', 'certes', 'cerveau', 'ces', 'cesse', 'cesser', 'cet', 'cette', 'chacun', 'chair', 'chaise', 'chaleur', 'chambre', 'champ', 'chance', 'changement', 'changer', 'chant', 'chanter', 'chaque', 'charge', 'charger', 'chasse', 'chasser', 'chat', 'chaud', 'chef', 'chemin', 'chemise', 'cher', 'chercher', 'cheval', 'cheveu', 'chez', 'chien', 'chiffre', 'choisir', 'choix', 'chose', 'chute', 'ci', 'ciel', 'cinq', 'cinquante', 'circonstance', 'clair', 'claire', 'classe', 'clef', 'coin', 'colline', 'colon', 'combat', 'combien', 'commander', 'comme', 'commencement', 'commencer', 'comment', 'commun', 'compagnie', 'compagnon', 'complet', 'composer', 'comprendre', 'compte', 'compter', 'conclure', 'condamner', 'condition', 'conduire', 'confiance', 'confier', 'confondre', 'connaissance', 'conscience', 'conseil', 'consentir', 'construire', 'consulter', 'contenir', 'content', 'contenter', 'continuer', 'contraire', 'contre', 'convenir', 'conversation', 'corde', 'corps', 'cou', 'couche', 'coucher', 'couler', 'couleur', 'coup', 'couper', 'cour', 'courage', 'courant', 'courir', 'cours', 'course', 'court', 'couvrir', 'craindre', 'crainte', 'creuser', 'cri', 'crier', 'crise', 'croire', 'croiser', 'croix', 'cruel', 'cuisine', 'curieux', 'dame', 'danger', 'dangereux', 'dans', 'danser', 'davantage', 'de', 'debout', 'dedans', 'dehors', 'demain', 'demande', 'demander', 'demeurer', 'demi', 'dent', 'depuis', 'dernier', 'des', 'descendre', 'desquelles', 'desquels', 'dessiner', 'dessous', 'dessus', 'deux', 'devant', 'devenir', 'deviner', 'devoir', 'dieu', 'difficile', 'digne', 'dimanche', 'dire', 'direction', 'diriger', 'discours', 'discussion', 'discuter', 'disposer', 'distance', 'distinguer', 'divers', 'dix', 'docteur', 'doigt', 'dominer', 'donc', 'donner', 'dont', 'dormir', 'dos', 'double', 'doucement', 'douceur', 'douleur', 'doute', 'douter', 'doux', 'douze', 'drame', 'dresser', 'droit', 'droite', 'du', 'dun', 'dune', 'duquel', 'dur', 'durant', 'durer', 'eau', 'eaux', 'effacer', 'effet', 'effort', 'eh', 'elle', 'elles', 'embrasser', 'emmener', 'emparer', 'empire', 'employer', 'emporter', 'en', 'encore', 'endormir', 'endroit', 'enfance', 'enfant', 'enfermer', 'enfin', 'enfoncer', 'engager', 'enlever', 'ennemi', 'ensemble', 'ensuite', 'entendre', 'entier', 'entourer', 'entre', 'entrer', 'entretenir', 'envelopper', 'envie', 'environ', 'envoyer', 'erreur', 'escalier', 'espace', 'espoir', 'esprit', 'essayer', 'essuyer', 'est', 'et', 'etc', 'euh', 'eux', 'examiner', 'exemple', 'exiger', 'existence', 'exister', 'explication', 'expliquer', 'exposer', 'expression', 'exprimer', 'extraordinaire', 'face', 'facile', 'faible', 'faim', 'faire', 'fais', 'fait', 'falloir', 'famille', 'fatigue', 'fatiguer', 'faute', 'fauteuil', 'faux', 'faveur', 'femme', 'fer', 'ferme', 'fermer', 'feu', 'feuille', 'fier', 'figure', 'figurer', 'fil', 'fille', 'fils', 'fin', 'fine', 'finir', 'fixe', 'fixer', 'flamme', 'fleur', 'flot', 'foi', 'fois', 'folie', 'fonction', 'fond', 'fonder', 'force', 'forcer', 'forme', 'former', 'fort', 'fortune', 'fou', 'foule', 'frais', 'franc', 'franchir', 'frapper', 'froid', 'front', 'fruit', 'fuir', 'fumer', 'gagner', 'garde', 'garder', 'gauche', 'genou', 'genre', 'gens', 'geste', 'glace', 'glisser', 'gloire', 'goutte', 'gouvernement', 'grain', 'grand', 'grandir', 'grave', 'gris', 'gros', 'groupe', 'guerre', 'guider', 'habiller', 'habitant', 'habiter', 'habitude', 'haine', 'hasard', 'haut', 'haute', 'hauteur', 'hein', 'herbe', 'heure', 'heureux', 'heurter', 'hier', 'histoire', 'hiver', 'homme', 'honneur', 'honte', 'horizon', 'hormis', 'hors', 'huit', 'humain', 'humide', 'ignorer', 'il', 'illusion', 'ils', 'image', 'imaginer', 'immense', 'immobile', 'importance', 'important', 'importer', 'imposer', 'impossible', 'impression', 'incapable', 'inconnu', 'indiquer', 'inspirer', 'installer', 'instant', 'instinct', 'instrument', 'intelligence', 'intention', 'interroger', 'interrompre', 'inutile', 'inventer', 'inviter', 'jamais', 'jambe', 'jardin', 'jaune', 'je', 'jeter', 'jeu', 'jeune', 'jeunesse', 'joie', 'joindre', 'joli', 'joue', 'jouer', 'jour', 'journal', 'juge', 'juger', 'juif', 'jusquau', 'jusquaux', 'jusque', 'juste', 'justice', 'la', 'laquelle', 'large', 'larme', 'le', 'lendemain', 'lentement', 'lequel', 'les', 'lesquelles', 'lesquels', 'lettre', 'leur', 'leurs', 'lever', 'libre', 'lien', 'lier', 'lieu', 'ligne', 'lire', 'lisser', 'lit', 'livre', 'livrer', 'loi', 'loin', 'long', 'longtemps', 'lors', 'lorsque', 'loup', 'lourd', 'lueur', 'lui', 'lun', 'lune', 'lutte', 'lutter', 'ma', 'machine', 'madame', 'magnifique', 'main', 'maintenant', 'maintenir', 'mais', 'maison', 'mal', 'malade', 'maladie', 'malheur', 'manche', 'manger', 'manier', 'manquer', 'marchand', 'marche', 'marcher', 'mari', 'mariage', 'marier', 'marquer', 'masse', 'matin', 'mauvais', 'me', 'meilleur', 'meilleure', 'meilleures', 'meilleurs', 'membre', 'menacer', 'mener', 'mensonge', 'mentir', 'mer', 'mes', 'mesure', 'mettre', 'midi', 'mien', 'miens', 'mieux', 'milieu', 'militaire', 'mille', 'million', 'mince', 'mine', 'ministre', 'minute', 'miser', 'mode', 'moi', 'moindre', 'moins', 'mois', 'moment', 'mon', 'monde', 'monsieur', 'montagne', 'monter', 'montrer', 'morceau', 'mort', 'mot', 'mourir', 'mouvement', 'moyen', 'muet', 'mur', 'musique', 'naissance', 'nation', 'nature', 'naturel', 'naturellement', 'ne', 'nerveux', 'neuf', 'nez', 'ni', 'noir', 'noire', 'nom', 'nombre', 'nombreux', 'nommer', 'non', 'nord', 'nos', 'note', 'notre', 'nourrir', 'nous', 'nouveau', 'noyer', 'nu', 'nuage', 'nuit', 'nul', 'objet', 'obliger', 'observer', 'obtenir', 'occasion', 'occuper', 'odeur', 'oeil', 'officier', 'offrir', 'oh', 'oiseau', 'ombre', 'on', 'oncle', 'or', 'ordre', 'oreille', 'oser', 'ou', 'oublier', 'ouh', 'oui', 'ouvert', 'ouvrage', 'ouvrir', 'page', 'pain', 'paix', 'palais', 'papa', 'papier', 'paquet', 'par', 'parce', 'parcourir', 'pareil', 'parent', 'parer', 'parfait', 'parfaitement', 'parfois', 'parler', 'parmi', 'parole', 'part', 'partager', 'parti', 'particulier', 'partie', 'partir', 'partout', 'parvenir', 'pas', 'passage', 'passer', 'passion', 'patron', 'pauvre', 'payer', 'pays', 'paysage', 'paysan', 'peau', 'peine', 'pencher', 'pendant', 'pendre', 'penser', 'perdre', 'perdu', 'permettre', 'personnage', 'personne', 'perte', 'peser', 'petit', 'peu', 'peuple', 'peur', 'phrase', 'pied', 'pierre', 'piquer', 'pire', 'pires', 'place', 'placer', 'plaindre', 'plaine', 'plaire', 'plaisir', 'plan', 'planche', 'plante', 'plein', 'pleurer', 'plier', 'plonger', 'pluie', 'plus', 'plusieurs', 'poche', 'poids', 'point', 'pointe', 'poitrine', 'police', 'politique', 'pont', 'port', 'porte', 'porter', 'portier', 'poser', 'position', 'possible', 'poste', 'pour', 'pourquoi', 'poursuivre', 'pourtant', 'pousser', 'pouvoir', 'premier', 'prendre', 'presque', 'presser', 'preuve', 'prier', 'prince', 'principe', 'printemps', 'prison', 'prix', 'probablement', 'prochain', 'produire', 'professeur', 'profiter', 'profond', 'projet', 'promener', 'promettre', 'prononcer', 'propos', 'proposer', 'propre', 'prouver', 'public', 'puis', 'puisque', 'puissance', 'puissant', 'pur', 'quand', 'quant', 'quarante', 'quart', 'quartier', 'quatre', 'que', 'quel', 'quelle', 'quelles', 'quelque', 'quelquun', 'quels', 'question', 'queue', 'qui', 'quinze', 'quitter', 'quoi', 'quoique', 'race', 'raconter', 'rage', 'raison', 'ramasser', 'ramener', 'rang', 'rapide', 'rapidement', 'rappeler', 'rapport', 'rapporter', 'rare', 'rassurer', 'rayon', 'recevoir', 'recherche', 'recommencer', 'recueillir', 'reculer', 'redevenir', 'refuser', 'regard', 'regarder', 'regretter', 'rejeter', 'rejoindre', 'relation', 'relever', 'religion', 'remarquer', 'remercier', 'remettre', 'remonter', 'remplacer', 'remplir', 'rencontre', 'rencontrer', 'rendre', 'renoncer', 'rentrer', 'renverser', 'repas', 'reposer', 'repousser', 'reprendre', 'reproche', 'respect', 'respecter', 'respirer', 'ressembler', 'reste', 'rester', 'retenir', 'retirer', 'retomber', 'retour', 'retourner', 'retrouver', 'revenir', 'revoir', 'riche', 'rideau', 'rien', 'rire', 'risquer', 'robe', 'roche', 'rocher', 'roi', 'roman', 'rompre', 'rond', 'rose', 'rouge', 'rouler', 'route', 'rue', 'ruine', 'sa', 'sable', 'sac', 'saint', 'saisir', 'saison', 'salle', 'saluer', 'salut', 'sang', 'sans', 'satisfaire', 'sauf', 'sauter', 'sauvage', 'sauver', 'savoir', 'science', 'se', 'sec', 'second', 'seconde', 'secours', 'secret', 'seigneur', 'sein', 'selon', 'semaine', 'semblable', 'sembler', 'semer', 'sens', 'sentier', 'sentiment', 'sentir', 'sept', 'serrer', 'service', 'servir', 'ses', 'seuil', 'seul', 'seulement', 'si', 'sien', 'siens', 'signe', 'signer', 'signifier', 'silence', 'silencieux', 'simple', 'simplement', 'situation', 'six', 'social', 'soi', 'soin', 'soir', 'soit', 'sol', 'soldat', 'soleil', 'solitude', 'sombre', 'somme', 'sommeil', 'sommet', 'son', 'songer', 'sonner', 'sorte', 'sortir', 'sou', 'souci', 'soudain', 'souffler', 'souffrance', 'souffrir', 'souhaiter', 'soulever', 'soumettre', 'source', 'sourd', 'sourire', 'sous', 'soutenir', 'souvenir', 'souvent', 'spectacle', 'subir', 'sueur', 'suffire', 'suite', 'suivant', 'suivre', 'sujet', 'supporter', 'supposer', 'sur', 'surprendre', 'surtout', 'surveiller', 'ta', 'table', 'tache', 'taille', 'taire', 'tandis', 'tant', 'tapis', 'tard', 'te', 'tel', 'telle', 'tellement', 'telles', 'tels', 'temps', 'tendre', 'tenir', 'tenter', 'terme', 'terminer', 'terrain', 'terre', 'terreur', 'terrible', 'tes', 'tien', 'tiens', 'tirer', 'titre', 'toi', 'toile', 'toit', 'tombe', 'tomber', 'ton', 'toucher', 'toujours', 'tour', 'tourner', 'tous', 'tout', 'toute', 'trace', 'tracer', 'train', 'trait', 'traiter', 'tranquille', 'transformer', 'travail', 'travailler', 'travers', 'traverser', 'trembler', 'trente', 'triste', 'trois', 'tromper', 'trop', 'trou', 'troubler', 'trouver', 'tu', 'tuer', 'type', 'un', 'une', 'unique', 'usage', 'user', 'va', 'vague', 'vaincre', 'vais', 'valeur', 'valoir', 'vas', 'vaste', 'veille', 'veiller', 'vendre', 'venir', 'vent', 'ventre', 'verre', 'vers', 'verser', 'vert', 'victime', 'vide', 'vie', 'vieil', 'vieillard', 'viens', 'vient', 'vieux', 'vif', 'village', 'ville', 'vin', 'vingt', 'violence', 'violent', 'visage', 'visible', 'vision', 'visite', 'visiter', 'vite', 'vivant', 'vivre', 'voici', 'voie', 'voile', 'voir', 'voisin', 'voiture', 'voix', 'vol', 'voler', 'vos', 'votre', 'vouloir', 'vous', 'voyage', 'voyager', 'vrai', 'vraiment', 'vue', );
trunk/classes/ignored-words/it_IT.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ return array( '', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'a', 'abbastanza', 'accanto', 'accordo', 'addirittura', 'addosso', 'adesso', 'affatto', 'ah', 'allora', 'almeno', 'anche', 'ancora', 'anzi', 'apesso', 'appena', 'appunto', 'assai', 'attorno', 'avanti', 'bene', 'certamente', 'che', 'chi', 'ci', 'circa', 'coloro', 'come', 'completamente', 'comunque', 'contro', 'cui', 'davvero', 'dentro', 'di', 'dietro', 'dinanzi', 'domani', 'dopo', 'dove', 'dunque', 'durante', 'e', 'eccetera', 'ecco', 'egli', 'eh', 'entro', 'eppure', 'essa', 'esso', 'finalmente', 'fino', 'forse', 'fra', 'fuori', 'grazie', 'ieri', 'il', 'in', 'indietro', 'infatti', 'infine', 'inoltre', 'insieme', 'insomma', 'intanto', 'intorno', 'invece', 'io', 'lei', 'li', 'loro', 'lui', 'lungo', 'ma', 'magari', 'male', 'meno', 'mentre', 'mi', 'naturalmente', 'ne', 'neanche', 'nemmeno', 'neppure', 'niente', 'no', 'noi', 'non', 'nulla', 'o', 'oggi', 'ognuno', 'oh', 'oltre', 'oppure', 'ora', 'oramai', 'peccato', 'perfino', 'piuttosto', 'presso', 'presto', 'prima', 'probabilmente', 'pure', 'qua', 'qualcosa', 'qualcuno', 'quasi', 'qui', 'quindi', 'se', 'secondo', 'senza', 'sino', 'soltanto', 'sopra', 'soprattutto', 'sotto', 'stamattina', 'stasera', 'su', 'subito', 'tardi', 'tra', 'tu', 'tuttavia', 'un', 'uno', 'veramente', 'verso', 'vi', 'voi', );
trunk/classes/ignored-words/nl_NL.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ return array( '', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'aleen', 'alle', 'alleen', 'als', 'ander', 'andere', 'anders', 'begrijpen', 'beiden', 'ben', 'bent', 'beschikbaar', 'beslissen', 'beste', 'beter', 'bijna', 'c', 'controleren', 'cursus', 'd', 'daarna', 'dag', 'dan', 'dat', 'de', 'deden', 'deed', 'deel', 'denk', 'denken', 'deze', 'dezelfde', 'die', 'ding', 'dingen', 'dit', 'doe', 'doen', 'doet', 'door', 'doordat', 'doorheen', 'e', 'editie', 'een', 'eerder', 'eerste', 'einde', 'elke', 'enig', 'enige', 'enkele', 'er', 'erg', 'even', 'ga', 'gaan', 'gebruik', 'gebruiken', 'gebruikt', 'gebruikte', 'gemaakt', 'gemakkelijk', 'genoeg', 'gevonden', 'geweest', 'gezegde', 'goed', 'groot', 'haar', 'had', 'hard', 'heb', 'hebben', 'heeft', 'heel', 'hem', 'hen', 'het', 'hier', 'hij', 'hoe', 'hun', 'iets', 'in', 'is', 'ja', 'jaar', 'je', 'jij', 'jou', 'jouw', 'kan', 'kijk', 'kijken', 'klein', 'kleine', 'klopt', 'kom', 'komen', 'konden', 'krijg', 'krijgen', 'kunnen', 'laatste', 'lang', 'langs', 'later', 'leuk', 'links', 'maak', 'maakte', 'maar', 'maat', 'mag', 'maken', 'makkie', 'man', 'manier', 'meer', 'mensen', 'menu', 'met', 'mij', 'mijn', 'min', 'minder', 'misschien', 'moeilijk', 'moet', 'moeten', 'mogen', 'mooi', 'na', 'naam', 'naar', 'nam', 'natuurlijk', 'nbsp', 'nee', 'neem', 'nemen', 'niet', 'nieuw', 'nodig', 'nog', 'nou', 'nu', 'nummer', 'of', 'omdat', 'onder', 'ondertussen', 'ongeveer', 'ons', 'ook', 'op', 'originineel', 'oud', 'over', 'persoon', 'plaats', 'plek', 'plus', 'probleem', 're', 'rechts', 'rijden', 's', 'samen', 'since', 'slecht', 'snap', 'sommige', 'speciaal', 'stil', 'systeem', 't', 'terug', 'terwijl', 'tijd', 'twee', 'uh', 'uit', 'uitkomst', 'van', 'vandaag', 'veel', 'verschillend', 'verschillende', 'versie', 'vind', 'vinden', 'vindt', 'voor', 'voorbeeld', 'vrouw', 'waar', 'waarschijnlijk', 'wanneer', 'want', 'was', 'wat', 'weinig', 'wel', 'welke', 'wellicht', 'werd', 'werden', 'werkelijk', 'weten', 'wie', 'wij', 'wil', 'wit', 'word', 'wordt', 'zag', 'zeer', 'zeg', 'zeggen', 'zegt', 'zei', 'zelfde', 'zie', 'zien', 'zij', 'zijn', 'zo', 'zoals', 'zou', 'zouden', 'zulke', 'zwart', );
trunk/classes/meta-boxes/class-meta-box-manage.php ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Meta_Box_Manage {
8
+
9
+ public function __construct() {
10
+
11
+ // Check if we're in the admin/backend
12
+ if ( ! is_admin() ) {
13
+ return;
14
+ }
15
+
16
+ // Add meta boxes
17
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
18
+
19
+ }
20
+
21
+ /**
22
+ * Add metabox to dashboard
23
+ *
24
+ * @access public
25
+ * @return void
26
+ */
27
+ public function add_meta_box() {
28
+
29
+ // Add meta box to parent
30
+ add_meta_box(
31
+ 'rp4wp_metabox_related_posts',
32
+ __( 'Related Posts', 'related-posts-for-wp' ),
33
+ array( $this, 'callback' ),
34
+ 'post',
35
+ 'normal',
36
+ 'core'
37
+ );
38
+
39
+ }
40
+
41
+ /**
42
+ * Metabox content
43
+ *
44
+ * @access public
45
+ * @return void
46
+ */
47
+ public function callback( $post ) {
48
+ echo "<div class='rp4wp_mb_manage'>\n";
49
+
50
+ // Add nonce
51
+ echo "<input type='hidden' name='rp4wp-ajax-nonce' id='rp4wp-ajax-nonce' value='" . wp_create_nonce( 'rp4wp-ajax-nonce-omgrandomword' ) . "' />\n";
52
+
53
+ // Output plugin URL in hidden val
54
+ echo "<input type='hidden' name='rp4wp-dir-img' id='rp4wp-dir-img' value='" . plugins_url( '/assets/images/', RP4WP::get_plugin_file() ) . "' />\n";
55
+
56
+ // Create a Post Link Manager object
57
+ $post_link_manager = new RP4WP_Post_Link_Manager();
58
+
59
+ // Get the children
60
+ $children = $post_link_manager->get_children( $post->ID );
61
+
62
+ echo "<div class='rp4wp_button_holder'>\n";
63
+
64
+
65
+ // Build the related post link
66
+ $url = get_admin_url() . "admin.php?page=rp4wp_link_related&amp;rp4wp_parent=" . $post->ID;
67
+
68
+ // WPML check
69
+ if ( isset( $_GET['lang'] ) ) {
70
+ $url .= "&amp;lang=" . $_GET['lang'];
71
+ }
72
+
73
+ echo "<span id='view-post-btn'>";
74
+ echo "<a href='" . $url . "' class='button button-primary'>";
75
+ _e( 'Add Related Posts', 'related-posts-for-wp' );
76
+ echo "</a>";
77
+ echo "</span>\n";
78
+
79
+
80
+ echo "</div>\n";
81
+
82
+ if ( count( $children ) > 0 ) {
83
+
84
+ // Managet table
85
+ echo "<table class='wp-list-table widefat fixed pages rp4wp_table_manage sortable'>\n";
86
+
87
+ echo "<tbody>\n";
88
+ $i = 0;
89
+ foreach ( $children as $link_id => $child ) {
90
+ $child_id = $child->ID;
91
+
92
+ $edit_url = get_admin_url() . "post.php?post={$child_id}&amp;action=edit&amp;rp4wp_parent={$post->ID}";
93
+
94
+ echo "<tr id='{$link_id}'>\n";
95
+ echo "<td>";
96
+ echo "<strong><a href='{$edit_url}' class='row-title' title='{$child->post_title}'>{$child->post_title}</a></strong>\n";
97
+ echo "<div class='row-actions'>\n";
98
+ echo "<span class='edit'><a href='{$edit_url}' title='" . __( 'Edit Post', 'related-posts-for-wp' ) . "'>";
99
+ _e( 'Edit Post', 'related-posts-for-wp' );
100
+ echo "</a> | </span>";
101
+ echo "<span class='trash'><a class='submitdelete' title='" . __( 'Unlink Related Post', 'related-posts-for-wp' ) . "' href='javascript:;'>";
102
+ _e( 'Unlink Related Post', 'related-posts-for-wp' );
103
+ echo "</a></span>";
104
+ echo "</div>\n";
105
+ echo "</td>\n";
106
+ echo "</tr>\n";
107
+ $i ++;
108
+ }
109
+ echo "</tbody>\n";
110
+ echo "</table>\n";
111
+
112
+ } else {
113
+
114
+ echo '<br/>';
115
+ _e( 'No related posts found.', 'related-posts-for-wp' );
116
+ }
117
+
118
+ // Reset Post Data
119
+ wp_reset_postdata();
120
+
121
+ echo "</div>\n";
122
+ }
123
+
124
+ }
trunk/classes/settings/class-settings.php ADDED
@@ -0,0 +1,284 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ /**
8
+ * Class RP4WP_Settings
9
+ *
10
+ * @todo Make class for each input type with own sanitize method.
11
+ */
12
+ class RP4WP_Settings {
13
+
14
+ const PREFIX = 'rp4wp_';
15
+
16
+ const PAGE = 'rp4wp';
17
+
18
+ private $sections;
19
+ private $defaults;
20
+
21
+ /**
22
+ * Constructor
23
+ */
24
+ public function __construct() {
25
+
26
+ // CSS default
27
+ $css_default_lines = array();
28
+ $css_default_lines[] = '.rp4wp-related-posts ul{width:100%;padding:0;margin:0;float:left;}';
29
+ $css_default_lines[] = '.rp4wp-related-posts ul>li{list-style:none;padding:0;margin:0;padding-bottom:20px;clear:both;}';
30
+ $css_default_lines[] = '.rp4wp-related-posts ul>li>p{margin:0;padding:0;}';
31
+ $css_default_lines[] = '.rp4wp-related-post-image{width:35%;padding-right:25px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;float:left;}';
32
+
33
+ // The fields
34
+ $this->sections = array(
35
+ self::PREFIX . 'automatic_linking' => array(
36
+ 'id' => 'automatic_linking',
37
+ 'label' => __( 'Automatic post linking', 'related-posts-for-wp' ),
38
+ 'description' => __( 'The following options affect how related posts are automatically linked.', 'related-posts-for-wp' ),
39
+ 'fields' => array(
40
+ array(
41
+ 'id' => 'automatic_linking',
42
+ 'label' => __( 'Enable', 'related-posts-for-wp' ),
43
+ 'description' => __( 'Checking this will enable automatically linking posts to new posts', 'related-posts-for-wp' ),
44
+ 'type' => 'checkbox',
45
+ 'default' => 1,
46
+ ),
47
+ array(
48
+ 'id' => 'automatic_linking_post_amount',
49
+ 'label' => __( 'Amount of Posts', 'related-posts-for-wp' ),
50
+ 'description' => __( 'The amount of automatically linked post', 'related-posts-for-wp' ),
51
+ 'type' => 'text',
52
+ 'default' => '3',
53
+ )
54
+ ) ),
55
+ self::PREFIX . 'css' => array(
56
+ 'id' => 'css',
57
+ 'label' => __( 'Frontend Settings', 'related-posts-for-wp' ),
58
+ 'description' => __( 'The following options affect how related posts are displayed on the frontend.', 'related-posts-for-wp' ),
59
+ 'fields' => array(
60
+ array(
61
+ 'id' => 'heading_text',
62
+ 'label' => __( 'Heading text', 'related-posts-for-wp' ),
63
+ 'description' => __( 'The text that is displayed above the related posts. To disable, leave field empty.', 'related-posts-for-wp' ),
64
+ 'type' => 'text',
65
+ 'default' => __( 'Related Posts', 'related-posts-for-wp' ),
66
+ ),
67
+ array(
68
+ 'id' => 'excerpt_length',
69
+ 'label' => __( 'Excerpt length', 'related-posts-for-wp' ),
70
+ 'description' => __( 'The amount of words to be displayed below the title on website. To disable, set value to 0.', 'related-posts-for-wp' ),
71
+ 'type' => 'text',
72
+ 'default' => '15',
73
+ ),
74
+ array(
75
+ 'id' => 'display_image',
76
+ 'label' => __( 'Display Image', 'related-posts-for-wp' ),
77
+ 'description' => __( 'Checking this will enable displaying featured images of related posts.', 'related-posts-for-wp' ),
78
+ 'type' => 'checkbox',
79
+ 'default' => 0,
80
+ ),
81
+ array(
82
+ 'id' => 'css',
83
+ 'label' => __( 'CSS', 'related-posts-for-wp' ),
84
+ 'description' => __( 'Warning! This is an advanced feature! An error here will break frontend display. To disable, leave field empty.', 'related-posts-for-wp' ),
85
+ 'type' => 'textarea',
86
+ 'default' => implode( PHP_EOL, $css_default_lines ),
87
+ )
88
+ ) ),
89
+ self::PREFIX . 'restart_wizard' => array(
90
+ 'id' => 'restart_wizard',
91
+ 'label' => __( 'Restart wizard', 'related-posts-for-wp' ),
92
+ 'description' => __( "Remove the cache and all existing related post links and restart the wizard.", 'related-posts-for-wp' ),
93
+ 'fields' => array(
94
+ array(
95
+ 'id' => 'restart_wizard_button',
96
+ 'label' => __( 'Restart the wizard?', 'related-posts-for-wp' ),
97
+ 'description' => __( "Click this button if you want to restart the wizard. Please note that this will delete all current related post links, also those you've manually added. Of course, we will never delete your actual posts.", 'related-posts-for-wp' ),
98
+ 'type' => 'button_link',
99
+ 'href' => admin_url( '?page=rp4wp_install&reinstall=1&rp4wp_nonce=' . wp_create_nonce( RP4WP_Constants::NONCE_INSTALL ) ),
100
+ 'default' => __( 'Restart wizard', 'related-posts-for-wp' ),
101
+ ),
102
+ ) ),
103
+ self::PREFIX . 'misc' => array(
104
+ 'id' => 'misc',
105
+ 'label' => __( 'Miscellaneous Settings', 'related-posts-for-wp' ),
106
+ 'description' => __( "A shelter for options that just don't fit in.", 'related-posts-for-wp' ),
107
+ 'fields' => array(
108
+ array(
109
+ 'id' => 'clean_on_uninstall',
110
+ 'label' => __( 'Remove Data on Uninstall?', 'related-posts-for-wp' ),
111
+ 'description' => __( 'Check this box if you would like to completely remove all of its data when the plugin is deleted.', 'related-posts-for-wp' ),
112
+ 'type' => 'checkbox',
113
+ 'default' => 0,
114
+ ),
115
+ ) ),
116
+ );
117
+
118
+ // Set defaults
119
+ foreach ( $this->sections as $section ) {
120
+ foreach ( $section['fields'] as $field ) {
121
+ $this->defaults[$field['id']] = $field['default'];
122
+ }
123
+ }
124
+
125
+ // Setup settings
126
+ add_action( 'admin_init', array( $this, 'setup' ) );
127
+
128
+ }
129
+
130
+ /**
131
+ * Setup the settings
132
+ *
133
+ * @since 1.1.0
134
+ * @access public
135
+ */
136
+ public function setup() {
137
+ if ( count( $this->sections ) > 0 ) {
138
+ foreach ( $this->sections as $section ) {
139
+
140
+ // Add the section
141
+ add_settings_section(
142
+ self::PREFIX . $section['id'],
143
+ $section['label'],
144
+ array( $this, 'section_intro' ),
145
+ self::PAGE
146
+ );
147
+
148
+ // Check & Loop
149
+ if ( count( $section['fields'] ) > 0 ) {
150
+ foreach ( $section['fields'] as $field ) {
151
+
152
+ // Add section
153
+ add_settings_field(
154
+ self::PREFIX . $field['id'],
155
+ $field['label'],
156
+ array( $this, 'do_field' ),
157
+ self::PAGE,
158
+ self::PREFIX . $section['id'],
159
+ $field
160
+ );
161
+
162
+ }
163
+ }
164
+
165
+ }
166
+
167
+
168
+ // Register section setting
169
+ register_setting( self::PAGE, self::PAGE, array( $this, 'sanitize_option' ) );
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Method that is called when adding a section
175
+ *
176
+ * @param $section
177
+ *
178
+ * @since 1.1.0
179
+ * @access public
180
+ */
181
+ public function section_intro( $section ) {
182
+ echo '<p>' . $this->sections[$section['id']]['description'] . '</p>' . PHP_EOL;
183
+ }
184
+
185
+ /**
186
+ * Method that outputs the correct field
187
+ *
188
+ * @param $field
189
+ *
190
+ * @since 1.1.0
191
+ * @access public
192
+ */
193
+ public function do_field( $field ) {
194
+
195
+ // For now we just do a simple switch here, make this more OOP in future version
196
+ switch ( $field['type'] ) {
197
+ case 'checkbox':
198
+ echo '<input type="checkbox" name="' . self::PAGE . '[' . $field['id'] . ']' . '" id="' . $field['id'] . '" value="1" ' . checked( 1, $this->get_option( $field['id'] ), false ) . ' />';
199
+ break;
200
+ case 'text':
201
+ echo '<input type="text" name="' . self::PAGE . '[' . $field['id'] . ']' . '" id="' . $field['id'] . '" value="' . $this->get_option( $field['id'] ) . '" class="rp4wp-input-text" />';
202
+ break;
203
+ case 'textarea':
204
+ echo '<textarea name="' . self::PAGE . '[' . $field['id'] . ']' . '" id="' . $field['id'] . '">' . $this->get_option( $field['id'] ) . '</textarea>';
205
+ break;
206
+ case 'button_link':
207
+ echo '<a href="' . $field['href'] . '" class="button">' . $field['default'] . '</a>';
208
+ break;
209
+ }
210
+
211
+ // Description
212
+ if ( isset( $field['description'] ) && '' != $field['description'] ) {
213
+ echo '<label class="rp4wp-description" for="' . $field['id'] . '">' . $field['description'] . '</label>';
214
+ }
215
+
216
+ // End of line
217
+ echo PHP_EOL;
218
+
219
+ }
220
+
221
+ /**
222
+ * Sanitize the option value
223
+ *
224
+ * @param array $post_data
225
+ *
226
+ * @since 1.1.0
227
+ * @access public
228
+ *
229
+ * @return array
230
+ */
231
+ public function sanitize_option( $post_data ) {
232
+
233
+ // Unset automatic_linking if not set in post
234
+ if ( ! isset( $post_data['automatic_linking'] ) ) {
235
+ $post_data['automatic_linking'] = 0;
236
+ }
237
+
238
+ // Unset display_image if not set in post
239
+ if ( ! isset( $post_data['display_image'] ) ) {
240
+ $post_data['display_image'] = 0;
241
+ }
242
+
243
+ // automatic_linking must be an integer
244
+ $post_data['automatic_linking'] = intval( $post_data['automatic_linking'] );
245
+
246
+ // automatic_linking_post_amount must be an integer
247
+ $post_data['automatic_linking_post_amount'] = intval( $post_data['automatic_linking_post_amount'] );
248
+
249
+ // Excerpt length must be an integer
250
+ $post_data['excerpt_length'] = intval( $post_data['excerpt_length'] );
251
+
252
+ return $post_data;
253
+
254
+ }
255
+
256
+ /**
257
+ * Get the plugin options
258
+ *
259
+ * @since 1.1.0
260
+ * @access public
261
+ *
262
+ * @return mixed|void
263
+ */
264
+ public function get_options() {
265
+ return apply_filters( 'rp4wp_options', wp_parse_args( get_option( self::PAGE, array() ), $this->defaults ) );
266
+ }
267
+
268
+ /**
269
+ * Return a single option
270
+ *
271
+ * @param $option
272
+ *
273
+ * @since 1.0.0
274
+ * @access public
275
+ *
276
+ * @return mixed|bool
277
+ */
278
+ public function get_option( $option ) {
279
+ $options = $this->get_options();
280
+
281
+ return isset( $options[$option] ) ? $options[$option] : false;
282
+ }
283
+
284
+ }
trunk/includes/installer-functions.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ function rp4wp_activate_plugin() {
4
+ global $wpdb;
5
+
6
+ $sql = "CREATE TABLE IF NOT EXISTS `" . $wpdb->prefix . "rp4wp_cache` (
7
+ `post_id` bigint(20) unsigned NOT NULL,
8
+ `word` varchar(255) CHARACTER SET utf8 NOT NULL,
9
+ `weight` float unsigned NOT NULL,
10
+ `post_type` varchar(20) CHARACTER SET utf8 NOT NULL,
11
+ PRIMARY KEY (`post_id`,`word`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;";
12
+
13
+ $wpdb->query( $sql );
14
+
15
+ // Redirect to installation wizard
16
+ add_site_option( 'rp4wp_do_install', true );
17
+ }
trunk/includes/template-functions.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( !function_exists( 'rp4wp_children' ) ) {
4
+ /**
5
+ * Generate the Related Posts for WordPress children list
6
+ *
7
+ * @param bool $id
8
+ * @param bool $output
9
+ *
10
+ * @since 1.0.0
11
+ * @access public
12
+ *
13
+ * @return string
14
+ */
15
+ function rp4wp_children( $id = false, $output = true ) {
16
+
17
+ // Get the current ID if ID not set
18
+ if ( false === $id ) {
19
+ $id = get_the_ID();
20
+ }
21
+
22
+ // Post Link Manager
23
+ $pl_manager = new RP4WP_Post_Link_Manager();
24
+
25
+ // Generate the children list
26
+ $content = $pl_manager->generate_children_list( $id );
27
+
28
+ // Output or return the content
29
+ if ( $output ) {
30
+ echo $content;
31
+ } else {
32
+ return $content;
33
+ }
34
+
35
+ }
36
+ }
37
+
trunk/languages/related-posts-for-wp-nl_NL.mo ADDED
Binary file
trunk/languages/related-posts-for-wp-nl_NL.po ADDED
@@ -0,0 +1,411 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Related Posts for WordPress\n"
4
+ "POT-Creation-Date: 2014-08-23 15:29+0100\n"
5
+ "PO-Revision-Date: 2014-08-23 15:30+0100\n"
6
+ "Last-Translator: Barry Kooij <barry@cageworks.nl>\n"
7
+ "Language-Team: Cageworks <barry@cageworks.nl>\n"
8
+ "Language: en\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Generator: Poedit 1.6.8\n"
13
+ "X-Poedit-Basepath: .\n"
14
+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
15
+ "X-Poedit-SourceCharset: UTF-8\n"
16
+ "X-Poedit-KeywordsList: _e;__;_x\n"
17
+ "X-Poedit-SearchPath-0: ../.\n"
18
+
19
+ #: .././classes/class-javascript-strings.php:14
20
+ msgid "Are you sure you want to delete this related post?"
21
+ msgstr "Weet je zeker dat je dit gerelateerde bericht wilt verwijderen?"
22
+
23
+ #: .././classes/class-link-related-table.php:47
24
+ #: .././classes/hooks/class-hook-settings-page.php:17
25
+ #: .././classes/meta-boxes/class-meta-box-manage.php:32
26
+ msgid "Related Posts"
27
+ msgstr "Gerelateerde Berichten"
28
+
29
+ #: .././classes/class-link-related-table.php:48
30
+ msgid "All Posts"
31
+ msgstr "Alle Berichten"
32
+
33
+ #: .././classes/class-link-related-table.php:97
34
+ msgid "Title"
35
+ msgstr "Titel"
36
+
37
+ #: .././classes/class-link-related-table.php:224
38
+ msgid "Link Post"
39
+ msgstr "Link Bericht"
40
+
41
+ #: .././classes/class-link-related-table.php:256
42
+ msgid "Link Posts"
43
+ msgstr "Link Berichten"
44
+
45
+ #: .././classes/class-nag-manager.php:105
46
+ #, php-format
47
+ msgid ""
48
+ "You've been using %sRelated Posts for WordPress%s for some time now, could "
49
+ "you please give it a review at wordpress.org?"
50
+ msgstr ""
51
+ "Je gebruikt %sRelated Posts for WordPress%s nu al best een tijdje, zou je "
52
+ "ons alsjeblieft een review willen geven op wordpress.org?"
53
+
54
+ #: .././classes/class-nag-manager.php:107
55
+ #, php-format
56
+ msgid "%sYes, take me there!%s - %sI've already done this!%s"
57
+ msgstr "%sJa, ga er heen!%s - %sIk heb dit al gedaan!%s"
58
+
59
+ #: .././classes/class-settings.php:37
60
+ msgid "Automatic post linking"
61
+ msgstr "Automatisch linken van berichten"
62
+
63
+ #: .././classes/class-settings.php:38
64
+ msgid ""
65
+ "The following options affect how related posts are automatically linked."
66
+ msgstr ""
67
+ "Deze opties beïnvloeden hoe gerelateerde berichten automatisch gelinkt "
68
+ "worden."
69
+
70
+ #: .././classes/class-settings.php:42
71
+ msgid "Enable"
72
+ msgstr "Activeren"
73
+
74
+ #: .././classes/class-settings.php:43
75
+ msgid "Checking this will enable automatically linking posts to new posts"
76
+ msgstr ""
77
+ "Door dit aan te vinken zullen berichten automatisch gekoppeld worden aan "
78
+ "nieuwe berichten"
79
+
80
+ #: .././classes/class-settings.php:49
81
+ msgid "Amount of Posts"
82
+ msgstr "Aantal berichten"
83
+
84
+ #: .././classes/class-settings.php:50
85
+ msgid "The amount of automatically linked post"
86
+ msgstr "Het aantal automatisch gelinkte berichten"
87
+
88
+ #: .././classes/class-settings.php:57
89
+ msgid "Frontend Settings"
90
+ msgstr "Frontend Instellingen"
91
+
92
+ #: .././classes/class-settings.php:58
93
+ msgid ""
94
+ "The following options affect how related posts are displayed on the frontend."
95
+ msgstr ""
96
+ "Deze opties beïnvloeden hoe gerelateerde berichten getoond worden op uw "
97
+ "website."
98
+
99
+ #: .././classes/class-settings.php:62
100
+ msgid "Heading text"
101
+ msgstr "Titel tekst"
102
+
103
+ #: .././classes/class-settings.php:63
104
+ msgid ""
105
+ "The text that is displayed above the related posts. To disable, leave field "
106
+ "empty."
107
+ msgstr ""
108
+ "De tekst welke boven de gerelateerde berichten getoond wordt. Laat dit veld "
109
+ "leeg om het uit te schakelen."
110
+
111
+ #: .././classes/class-settings.php:69
112
+ msgid "Excerpt length"
113
+ msgstr "Samenvatting lengte"
114
+
115
+ #: .././classes/class-settings.php:70
116
+ msgid ""
117
+ "The amount of words to be displayed below the title on website. To disable, "
118
+ "set value to 0."
119
+ msgstr ""
120
+ "Het aantal woorden dat getoond wordt onder de titel. Vul 0 in om het uit te "
121
+ "schakelen."
122
+
123
+ #: .././classes/class-settings.php:76
124
+ msgid "Display Image"
125
+ msgstr "Toon afbeelding"
126
+
127
+ #: .././classes/class-settings.php:77
128
+ msgid "Checking this will enable displaying featured images of related posts."
129
+ msgstr ""
130
+ "Door dit aan te vinken zullen afbeeldingen van berichten getoond worden."
131
+
132
+ #: .././classes/class-settings.php:83
133
+ msgid "CSS"
134
+ msgstr "CSS"
135
+
136
+ #: .././classes/class-settings.php:84
137
+ msgid ""
138
+ "Warning! This is an advanced feature! An error here will break frontend "
139
+ "display. To disable, leave field empty."
140
+ msgstr ""
141
+ "Waarschuwing! Dit is een geavanceerde functie! Een fout hier kan uw website "
142
+ "incorrect laten tonen. Laat dit veld leeg om deze functie uit te schakelen."
143
+
144
+ #: .././classes/class-settings.php:91
145
+ msgid "Miscellaneous Settings"
146
+ msgstr "Diversen Instellingen"
147
+
148
+ #: .././classes/class-settings.php:92
149
+ msgid "A shelter for options that just don't fit in."
150
+ msgstr "Een opvang voor opties die nergens bijhoren."
151
+
152
+ #: .././classes/class-settings.php:96
153
+ msgid "Remove Data on Uninstall?"
154
+ msgstr "Verwijder gegevens bij deïnstallatie?"
155
+
156
+ #: .././classes/class-settings.php:97
157
+ msgid ""
158
+ "Check this box if you would like to completely remove all of its data when "
159
+ "the plugin is deleted."
160
+ msgstr ""
161
+ "Door dit aan te vinken zullen alle plugin gegevens verwijderd worden waneer "
162
+ "u de plugin verwijderd."
163
+
164
+ #: .././classes/hooks/class-hook-link-related-screen.php:131
165
+ msgid "Posts"
166
+ msgstr "Berichten"
167
+
168
+ #: .././classes/hooks/class-hook-link-related-screen.php:132
169
+ msgid "Cancel linking"
170
+ msgstr "Annuleer linken"
171
+
172
+ #: .././classes/hooks/class-hook-link-related-screen.php:148
173
+ msgid "Search"
174
+ msgstr "Zoeken"
175
+
176
+ #: .././classes/hooks/class-hook-page-install.php:39
177
+ msgid "Caching Posts"
178
+ msgstr "Cachen van berichten"
179
+
180
+ #: .././classes/hooks/class-hook-page-install.php:40
181
+ msgid "Linking Posts"
182
+ msgstr "Linken van berichten"
183
+
184
+ #: .././classes/hooks/class-hook-page-install.php:41
185
+ msgid "Finished"
186
+ msgstr "Klaar"
187
+
188
+ #: .././classes/hooks/class-hook-page-install.php:48
189
+ msgid "Installation"
190
+ msgstr "Installatie"
191
+
192
+ #: .././classes/hooks/class-hook-page-install.php:71
193
+ msgid "Thank you for choosing Related Posts for WordPress!"
194
+ msgstr "Bedankt voor het kiezen voor Related Posts for WordPress!"
195
+
196
+ #: .././classes/hooks/class-hook-page-install.php:72
197
+ msgid ""
198
+ "Before you can start using Related Posts for WordPress we need to cache your "
199
+ "current posts."
200
+ msgstr ""
201
+ "Voordat je Related Posts for WordPress kan gebruiken moeten we eerst je "
202
+ "huidige berichten cachen."
203
+
204
+ #: .././classes/hooks/class-hook-page-install.php:73
205
+ msgid ""
206
+ "This is a one time process which might take some time now, depending on the "
207
+ "amount of posts you have, but will ensure your website's performance when "
208
+ "using the plugin."
209
+ msgstr ""
210
+ "Dit is een eenmalig proces wat, afhankelijk van het aantal berichten dat je "
211
+ "hebt, nu even kan duren maar wat er voor zorgt dat de prestatie van je "
212
+ "website hoog blijft."
213
+
214
+ #: .././classes/hooks/class-hook-page-install.php:75
215
+ msgid ""
216
+ "Do NOT close this window, wait for this process to finish and this wizard to "
217
+ "take you to the next step."
218
+ msgstr ""
219
+ "Sluit dit venster NIET, wacht tot het proces klaar is en de wizard je naar "
220
+ "de volgende stap stuurt."
221
+
222
+ #: .././classes/hooks/class-hook-page-install.php:81
223
+ msgid "Great! All your posts were successfully cached!"
224
+ msgstr "Perfect! Al je berichten zijn succesvol gecached."
225
+
226
+ #: .././classes/hooks/class-hook-page-install.php:82
227
+ msgid ""
228
+ "You can let me link your posts, based on what I think is related, to each "
229
+ "other. And don't worry, if I made a mistake at one of your posts you can "
230
+ "easily correct this by editing it manually!"
231
+ msgstr ""
232
+ "Je kan mij, op basis van wat ik denk dat gerelateerd is, je berichten aan "
233
+ "elkaar laten koppelen. Maak je geen zorgen, als ik een fout gemaakt hebt kan "
234
+ "je deze gemakkelijk later corrigeren!"
235
+
236
+ #: .././classes/hooks/class-hook-page-install.php:83
237
+ msgid ""
238
+ "Want me to start linking posts to each other? Fill in the amount of related "
239
+ "posts each post should have and click on the \"Link now\" button. Rather "
240
+ "link your posts manually? Click \"Skip linking\"."
241
+ msgstr ""
242
+ "Wil je dat ik begin met het linken van gerelateerde berichten? Vul het "
243
+ "aantal gerelateerde berichten in dat ieder bericht moet krijgen en klik op "
244
+ "\"Nu linken\". Liever je berichten handmatig linken? Klik op \"Sla linken "
245
+ "over\"."
246
+
247
+ #: .././classes/hooks/class-hook-page-install.php:84
248
+ msgid ""
249
+ "Do NOT close this window if you click the \"Link now\" button, wait for this "
250
+ "process to finish and this wizard to take you to the next step."
251
+ msgstr ""
252
+ "Sluit dit venster NIET wanneer je \"Nu linken\" hebt gekozen, wacht tot het "
253
+ "proces klaar is en de wizard je naar de volgende stap stuurt."
254
+
255
+ #: .././classes/hooks/class-hook-page-install.php:87
256
+ msgid "Amount of related posts per post:"
257
+ msgstr "Aantal gerelateerde berichten per bericht:"
258
+
259
+ #: .././classes/hooks/class-hook-page-install.php:88
260
+ msgid "Link now"
261
+ msgstr "Nu linken"
262
+
263
+ #: .././classes/hooks/class-hook-page-install.php:89
264
+ msgid "Skip linking"
265
+ msgstr "Sla linken over"
266
+
267
+ #: .././classes/hooks/class-hook-page-install.php:96
268
+ msgid "That's it, you're good to go!"
269
+ msgstr ""
270
+ "Super, de wizard is klaar en je hebt nu gerelateerde berichten op je website!"
271
+
272
+ #: .././classes/hooks/class-hook-page-install.php:97
273
+ #, php-format
274
+ msgid ""
275
+ "Thanks again for using Related Posts for WordPress and if you have any "
276
+ "questions be sure to ask them at the %sWordPress.org forums.%s"
277
+ msgstr ""
278
+ "Nogmaals bedankt voor het kiezen voor Related Posts for WordPress en als je "
279
+ "nog vragen hebt kan je deze stellen op %shet WordPress.org forum%s."
280
+
281
+ #: .././classes/hooks/class-hook-settings-page.php:50
282
+ msgid "Plugin version"
283
+ msgstr "Plugin versie"
284
+
285
+ #: .././classes/hooks/class-hook-settings-page.php:54
286
+ msgid "More information"
287
+ msgstr "Meer informatie"
288
+
289
+ #: .././classes/hooks/class-hook-settings-page.php:56
290
+ #, php-format
291
+ msgid "<a href='%s'>FAQ</a>"
292
+ msgstr "<a href='%s'>FAQ</a>"
293
+
294
+ #: .././classes/hooks/class-hook-settings-page.php:58
295
+ #, php-format
296
+ msgid "<a href='%s'>Change log</a>"
297
+ msgstr "<a href='%s'>Change log</a>"
298
+
299
+ #: .././classes/hooks/class-hook-settings-page.php:60
300
+ #, php-format
301
+ msgid "<a href='%s'>Give us a review</a>"
302
+ msgstr "<a href='%s'>Geef ons een review</a>"
303
+
304
+ #: .././classes/hooks/class-hook-settings-page.php:62
305
+ #, php-format
306
+ msgid "<a href='%s'>Release blog post</a>"
307
+ msgstr "<a href='%s'>Release blog bericht</a>"
308
+
309
+ #: .././classes/hooks/class-hook-settings-page.php:66
310
+ msgid "About the developer"
311
+ msgstr "Over de ontwikkelaar"
312
+
313
+ #: .././classes/hooks/class-hook-settings-page.php:68
314
+ msgid ""
315
+ "Barry is a WordPress developer that works on WooCommerce by WooThemes and is "
316
+ "the author of various WordPress plugins that include Post Connector, Related "
317
+ "Posts for WordPress and What The File."
318
+ msgstr ""
319
+ "Barry is een WordPress ontwikkelaar werkzaam bij WooThemes waar hij werkt "
320
+ "aan WooCommerce. Ook is hij de schrijver van verschillende WordPress plugins "
321
+ "zoals Post Connector, Related Posts for WordPress en What The File."
322
+
323
+ #: .././classes/hooks/class-hook-settings-page.php:70
324
+ msgid ""
325
+ "Barry likes contributing to opensource projects and visiting WordCamps and "
326
+ "WordPress meetups. He’s the organizer of the WordPress meetup in Tilburg."
327
+ msgstr ""
328
+ "Barry houd van het bijdragen aan opensource projecten en het bezoeken van "
329
+ "WordCamps en WordPress meetups. Hij is de organisator van de WordPress "
330
+ "meetup in Tilburg."
331
+
332
+ #: .././classes/hooks/class-hook-settings-page.php:72
333
+ #, php-format
334
+ msgid "You can follow Barry on Twitter <a href='%s'>here</a>."
335
+ msgstr "<a href='%s'>Volg Barry op Twitter</a>."
336
+
337
+ #: .././classes/meta-boxes/class-meta-box-manage.php:75
338
+ msgid "Add Related Posts"
339
+ msgstr "Voeg gerelateerde posts toe"
340
+
341
+ #: .././classes/meta-boxes/class-meta-box-manage.php:98
342
+ msgid "Edit this item"
343
+ msgstr "Bewerk dit item"
344
+
345
+ #: .././classes/meta-boxes/class-meta-box-manage.php:99
346
+ msgid "Edit Post"
347
+ msgstr "Bewerk Bericht"
348
+
349
+ #: .././classes/meta-boxes/class-meta-box-manage.php:101
350
+ msgid "Delete this item"
351
+ msgstr "Verwijder dit item"
352
+
353
+ #: .././classes/meta-boxes/class-meta-box-manage.php:102
354
+ msgid "Delete Post"
355
+ msgstr "Verwijder Bericht"
356
+
357
+ #: .././classes/meta-boxes/class-meta-box-manage.php:115
358
+ msgid "No related posts found."
359
+ msgstr "Geen gerelateerde berichten gevonden."
360
+
361
+ #: .././node_modules/grunt-checktextdomain/test/expected/incorrect-domain-autocorrect.php:3
362
+ #: .././node_modules/grunt-checktextdomain/test/expected/incorrect-domain-autocorrect.php:5
363
+ #: .././node_modules/grunt-checktextdomain/test/expected/variable-domain-autocorrect.php:4
364
+ #: .././node_modules/grunt-checktextdomain/test/expected/variable-domain-autocorrect.php:6
365
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/correct-domain.php:3
366
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/correct-domain.php:5
367
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain-autocorrect.php:3
368
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain-autocorrect.php:5
369
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain.php:3
370
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain.php:5
371
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/missing-domain.php:3
372
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/missing-domain.php:5
373
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/variable-domain-autocorrect.php:4
374
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/variable-domain-autocorrect.php:6
375
+ msgid "Hello World"
376
+ msgstr "Hallo Wereld"
377
+
378
+ #: .././node_modules/grunt-checktextdomain/test/expected/incorrect-domain-autocorrect.php:4
379
+ #: .././node_modules/grunt-checktextdomain/test/expected/variable-domain-autocorrect.php:5
380
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/correct-domain.php:4
381
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain-autocorrect.php:4
382
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain.php:4
383
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/missing-domain.php:4
384
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/variable-domain-autocorrect.php:5
385
+ msgid "Post"
386
+ msgstr "Bericht"
387
+
388
+ #: .././node_modules/grunt-wp-i18n/test/fixtures/basic-theme/exclude/file.php:3
389
+ #: .././node_modules/grunt-wp-i18n/test/fixtures/plugin-include/plugin-include.php:6
390
+ msgid "Exclude"
391
+ msgstr "Uitsluiten"
392
+
393
+ #: .././node_modules/grunt-wp-i18n/test/fixtures/plugin-include/include/file.php:2
394
+ msgid "Include"
395
+ msgstr "Insluiten"
396
+
397
+ #: .././node_modules/grunt-wp-i18n/test/fixtures/text-domains/add-domain.php:2
398
+ #: .././node_modules/grunt-wp-i18n/test/fixtures/text-domains/update-domains.php:2
399
+ #: .././node_modules/grunt-wp-i18n/test/fixtures/text-domains/update-domains.php:3
400
+ msgid "String"
401
+ msgstr "String"
402
+
403
+ #~ msgid "This section contains automatic post link related settings."
404
+ #~ msgstr ""
405
+ #~ "Dit gedeelte bevat instellingen van de automatisch gelinkte berichten."
406
+
407
+ #~ msgid "This section contains frontend related settings."
408
+ #~ msgstr "Dit gedeelte bevat frontend gerelateerde instellingen."
409
+
410
+ #~ msgid "Related Posts for WordPress Installation"
411
+ #~ msgstr "Related Posts for WordPress installatie"
trunk/languages/related-posts-for-wp.pot ADDED
@@ -0,0 +1,360 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Related Posts for WordPress\n"
4
+ "POT-Creation-Date: 2014-08-23 15:29+0100\n"
5
+ "PO-Revision-Date: 2014-08-23 15:29+0100\n"
6
+ "Last-Translator: Barry Kooij <barry@cageworks.nl>\n"
7
+ "Language-Team: Cageworks <barry@cageworks.nl>\n"
8
+ "Language: en\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Generator: Poedit 1.6.8\n"
13
+ "X-Poedit-Basepath: .\n"
14
+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
15
+ "X-Poedit-SourceCharset: UTF-8\n"
16
+ "X-Poedit-KeywordsList: _e;__;_x\n"
17
+ "X-Poedit-SearchPath-0: ../.\n"
18
+ "X-Poedit-SearchPathExcluded-0: ../node_modules/.\n"
19
+
20
+ #: .././classes/class-javascript-strings.php:14
21
+ msgid "Are you sure you want to delete this related post?"
22
+ msgstr ""
23
+
24
+ #: .././classes/class-link-related-table.php:47
25
+ #: .././classes/hooks/class-hook-settings-page.php:17
26
+ #: .././classes/meta-boxes/class-meta-box-manage.php:32
27
+ msgid "Related Posts"
28
+ msgstr ""
29
+
30
+ #: .././classes/class-link-related-table.php:48
31
+ msgid "All Posts"
32
+ msgstr ""
33
+
34
+ #: .././classes/class-link-related-table.php:97
35
+ msgid "Title"
36
+ msgstr ""
37
+
38
+ #: .././classes/class-link-related-table.php:224
39
+ msgid "Link Post"
40
+ msgstr ""
41
+
42
+ #: .././classes/class-link-related-table.php:256
43
+ msgid "Link Posts"
44
+ msgstr ""
45
+
46
+ #: .././classes/class-nag-manager.php:105
47
+ #, php-format
48
+ msgid ""
49
+ "You've been using %sRelated Posts for WordPress%s for some time now, could "
50
+ "you please give it a review at wordpress.org?"
51
+ msgstr ""
52
+
53
+ #: .././classes/class-nag-manager.php:107
54
+ #, php-format
55
+ msgid "%sYes, take me there!%s - %sI've already done this!%s"
56
+ msgstr ""
57
+
58
+ #: .././classes/class-settings.php:37
59
+ msgid "Automatic post linking"
60
+ msgstr ""
61
+
62
+ #: .././classes/class-settings.php:38
63
+ msgid ""
64
+ "The following options affect how related posts are automatically linked."
65
+ msgstr ""
66
+
67
+ #: .././classes/class-settings.php:42
68
+ msgid "Enable"
69
+ msgstr ""
70
+
71
+ #: .././classes/class-settings.php:43
72
+ msgid "Checking this will enable automatically linking posts to new posts"
73
+ msgstr ""
74
+
75
+ #: .././classes/class-settings.php:49
76
+ msgid "Amount of Posts"
77
+ msgstr ""
78
+
79
+ #: .././classes/class-settings.php:50
80
+ msgid "The amount of automatically linked post"
81
+ msgstr ""
82
+
83
+ #: .././classes/class-settings.php:57
84
+ msgid "Frontend Settings"
85
+ msgstr ""
86
+
87
+ #: .././classes/class-settings.php:58
88
+ msgid ""
89
+ "The following options affect how related posts are displayed on the frontend."
90
+ msgstr ""
91
+
92
+ #: .././classes/class-settings.php:62
93
+ msgid "Heading text"
94
+ msgstr ""
95
+
96
+ #: .././classes/class-settings.php:63
97
+ msgid ""
98
+ "The text that is displayed above the related posts. To disable, leave field "
99
+ "empty."
100
+ msgstr ""
101
+
102
+ #: .././classes/class-settings.php:69
103
+ msgid "Excerpt length"
104
+ msgstr ""
105
+
106
+ #: .././classes/class-settings.php:70
107
+ msgid ""
108
+ "The amount of words to be displayed below the title on website. To disable, "
109
+ "set value to 0."
110
+ msgstr ""
111
+
112
+ #: .././classes/class-settings.php:76
113
+ msgid "Display Image"
114
+ msgstr ""
115
+
116
+ #: .././classes/class-settings.php:77
117
+ msgid "Checking this will enable displaying featured images of related posts."
118
+ msgstr ""
119
+
120
+ #: .././classes/class-settings.php:83
121
+ msgid "CSS"
122
+ msgstr ""
123
+
124
+ #: .././classes/class-settings.php:84
125
+ msgid ""
126
+ "Warning! This is an advanced feature! An error here will break frontend "
127
+ "display. To disable, leave field empty."
128
+ msgstr ""
129
+
130
+ #: .././classes/class-settings.php:91
131
+ msgid "Miscellaneous Settings"
132
+ msgstr ""
133
+
134
+ #: .././classes/class-settings.php:92
135
+ msgid "A shelter for options that just don't fit in."
136
+ msgstr ""
137
+
138
+ #: .././classes/class-settings.php:96
139
+ msgid "Remove Data on Uninstall?"
140
+ msgstr ""
141
+
142
+ #: .././classes/class-settings.php:97
143
+ msgid ""
144
+ "Check this box if you would like to completely remove all of its data when "
145
+ "the plugin is deleted."
146
+ msgstr ""
147
+
148
+ #: .././classes/hooks/class-hook-link-related-screen.php:131
149
+ msgid "Posts"
150
+ msgstr ""
151
+
152
+ #: .././classes/hooks/class-hook-link-related-screen.php:132
153
+ msgid "Cancel linking"
154
+ msgstr ""
155
+
156
+ #: .././classes/hooks/class-hook-link-related-screen.php:148
157
+ msgid "Search"
158
+ msgstr ""
159
+
160
+ #: .././classes/hooks/class-hook-page-install.php:39
161
+ msgid "Caching Posts"
162
+ msgstr ""
163
+
164
+ #: .././classes/hooks/class-hook-page-install.php:40
165
+ msgid "Linking Posts"
166
+ msgstr ""
167
+
168
+ #: .././classes/hooks/class-hook-page-install.php:41
169
+ msgid "Finished"
170
+ msgstr ""
171
+
172
+ #: .././classes/hooks/class-hook-page-install.php:48
173
+ msgid "Installation"
174
+ msgstr ""
175
+
176
+ #: .././classes/hooks/class-hook-page-install.php:71
177
+ msgid "Thank you for choosing Related Posts for WordPress!"
178
+ msgstr ""
179
+
180
+ #: .././classes/hooks/class-hook-page-install.php:72
181
+ msgid ""
182
+ "Before you can start using Related Posts for WordPress we need to cache your "
183
+ "current posts."
184
+ msgstr ""
185
+
186
+ #: .././classes/hooks/class-hook-page-install.php:73
187
+ msgid ""
188
+ "This is a one time process which might take some time now, depending on the "
189
+ "amount of posts you have, but will ensure your website's performance when "
190
+ "using the plugin."
191
+ msgstr ""
192
+
193
+ #: .././classes/hooks/class-hook-page-install.php:75
194
+ msgid ""
195
+ "Do NOT close this window, wait for this process to finish and this wizard to "
196
+ "take you to the next step."
197
+ msgstr ""
198
+
199
+ #: .././classes/hooks/class-hook-page-install.php:81
200
+ msgid "Great! All your posts were successfully cached!"
201
+ msgstr ""
202
+
203
+ #: .././classes/hooks/class-hook-page-install.php:82
204
+ msgid ""
205
+ "You can let me link your posts, based on what I think is related, to each "
206
+ "other. And don't worry, if I made a mistake at one of your posts you can "
207
+ "easily correct this by editing it manually!"
208
+ msgstr ""
209
+
210
+ #: .././classes/hooks/class-hook-page-install.php:83
211
+ msgid ""
212
+ "Want me to start linking posts to each other? Fill in the amount of related "
213
+ "posts each post should have and click on the \"Link now\" button. Rather "
214
+ "link your posts manually? Click \"Skip linking\"."
215
+ msgstr ""
216
+
217
+ #: .././classes/hooks/class-hook-page-install.php:84
218
+ msgid ""
219
+ "Do NOT close this window if you click the \"Link now\" button, wait for this "
220
+ "process to finish and this wizard to take you to the next step."
221
+ msgstr ""
222
+
223
+ #: .././classes/hooks/class-hook-page-install.php:87
224
+ msgid "Amount of related posts per post:"
225
+ msgstr ""
226
+
227
+ #: .././classes/hooks/class-hook-page-install.php:88
228
+ msgid "Link now"
229
+ msgstr ""
230
+
231
+ #: .././classes/hooks/class-hook-page-install.php:89
232
+ msgid "Skip linking"
233
+ msgstr ""
234
+
235
+ #: .././classes/hooks/class-hook-page-install.php:96
236
+ msgid "That's it, you're good to go!"
237
+ msgstr ""
238
+
239
+ #: .././classes/hooks/class-hook-page-install.php:97
240
+ #, php-format
241
+ msgid ""
242
+ "Thanks again for using Related Posts for WordPress and if you have any "
243
+ "questions be sure to ask them at the %sWordPress.org forums.%s"
244
+ msgstr ""
245
+
246
+ #: .././classes/hooks/class-hook-settings-page.php:50
247
+ msgid "Plugin version"
248
+ msgstr ""
249
+
250
+ #: .././classes/hooks/class-hook-settings-page.php:54
251
+ msgid "More information"
252
+ msgstr ""
253
+
254
+ #: .././classes/hooks/class-hook-settings-page.php:56
255
+ #, php-format
256
+ msgid "<a href='%s'>FAQ</a>"
257
+ msgstr ""
258
+
259
+ #: .././classes/hooks/class-hook-settings-page.php:58
260
+ #, php-format
261
+ msgid "<a href='%s'>Change log</a>"
262
+ msgstr ""
263
+
264
+ #: .././classes/hooks/class-hook-settings-page.php:60
265
+ #, php-format
266
+ msgid "<a href='%s'>Give us a review</a>"
267
+ msgstr ""
268
+
269
+ #: .././classes/hooks/class-hook-settings-page.php:62
270
+ #, php-format
271
+ msgid "<a href='%s'>Release blog post</a>"
272
+ msgstr ""
273
+
274
+ #: .././classes/hooks/class-hook-settings-page.php:66
275
+ msgid "About the developer"
276
+ msgstr ""
277
+
278
+ #: .././classes/hooks/class-hook-settings-page.php:68
279
+ msgid ""
280
+ "Barry is a WordPress developer that works on WooCommerce by WooThemes and is "
281
+ "the author of various WordPress plugins that include Post Connector, Related "
282
+ "Posts for WordPress and What The File."
283
+ msgstr ""
284
+
285
+ #: .././classes/hooks/class-hook-settings-page.php:70
286
+ msgid ""
287
+ "Barry likes contributing to opensource projects and visiting WordCamps and "
288
+ "WordPress meetups. He’s the organizer of the WordPress meetup in Tilburg."
289
+ msgstr ""
290
+
291
+ #: .././classes/hooks/class-hook-settings-page.php:72
292
+ #, php-format
293
+ msgid "You can follow Barry on Twitter <a href='%s'>here</a>."
294
+ msgstr ""
295
+
296
+ #: .././classes/meta-boxes/class-meta-box-manage.php:75
297
+ msgid "Add Related Posts"
298
+ msgstr ""
299
+
300
+ #: .././classes/meta-boxes/class-meta-box-manage.php:98
301
+ msgid "Edit this item"
302
+ msgstr ""
303
+
304
+ #: .././classes/meta-boxes/class-meta-box-manage.php:99
305
+ msgid "Edit Post"
306
+ msgstr ""
307
+
308
+ #: .././classes/meta-boxes/class-meta-box-manage.php:101
309
+ msgid "Delete this item"
310
+ msgstr ""
311
+
312
+ #: .././classes/meta-boxes/class-meta-box-manage.php:102
313
+ msgid "Delete Post"
314
+ msgstr ""
315
+
316
+ #: .././classes/meta-boxes/class-meta-box-manage.php:115
317
+ msgid "No related posts found."
318
+ msgstr ""
319
+
320
+ #: .././node_modules/grunt-checktextdomain/test/expected/incorrect-domain-autocorrect.php:3
321
+ #: .././node_modules/grunt-checktextdomain/test/expected/incorrect-domain-autocorrect.php:5
322
+ #: .././node_modules/grunt-checktextdomain/test/expected/variable-domain-autocorrect.php:4
323
+ #: .././node_modules/grunt-checktextdomain/test/expected/variable-domain-autocorrect.php:6
324
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/correct-domain.php:3
325
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/correct-domain.php:5
326
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain-autocorrect.php:3
327
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain-autocorrect.php:5
328
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain.php:3
329
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain.php:5
330
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/missing-domain.php:3
331
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/missing-domain.php:5
332
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/variable-domain-autocorrect.php:4
333
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/variable-domain-autocorrect.php:6
334
+ msgid "Hello World"
335
+ msgstr ""
336
+
337
+ #: .././node_modules/grunt-checktextdomain/test/expected/incorrect-domain-autocorrect.php:4
338
+ #: .././node_modules/grunt-checktextdomain/test/expected/variable-domain-autocorrect.php:5
339
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/correct-domain.php:4
340
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain-autocorrect.php:4
341
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain.php:4
342
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/missing-domain.php:4
343
+ #: .././node_modules/grunt-checktextdomain/test/fixtures/variable-domain-autocorrect.php:5
344
+ msgid "Post"
345
+ msgstr ""
346
+
347
+ #: .././node_modules/grunt-wp-i18n/test/fixtures/basic-theme/exclude/file.php:3
348
+ #: .././node_modules/grunt-wp-i18n/test/fixtures/plugin-include/plugin-include.php:6
349
+ msgid "Exclude"
350
+ msgstr ""
351
+
352
+ #: .././node_modules/grunt-wp-i18n/test/fixtures/plugin-include/include/file.php:2
353
+ msgid "Include"
354
+ msgstr ""
355
+
356
+ #: .././node_modules/grunt-wp-i18n/test/fixtures/text-domains/add-domain.php:2
357
+ #: .././node_modules/grunt-wp-i18n/test/fixtures/text-domains/update-domains.php:2
358
+ #: .././node_modules/grunt-wp-i18n/test/fixtures/text-domains/update-domains.php:3
359
+ msgid "String"
360
+ msgstr ""
trunk/readme.txt ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === Related Posts for WordPress ===
2
+ Contributors: barrykooij
3
+ Donate link: http://www.relatedpostsforwp.com/
4
+ Tags: related posts for wordpress, related posts for wp, simple related posts, easy related posts, related posts, related, relations, internal links, seo, bounce rate
5
+ Requires at least: 3.6
6
+ Tested up to: 4.0
7
+ Stable tag: 1.7.0
8
+ License: GPLv3 or later
9
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
+
11
+ Display related posts without slowing down your website! Link all your existing content with only 1 click, get related posts for all your posts today!
12
+
13
+ == Description ==
14
+
15
+ = Related Posts for WordPress =
16
+
17
+ Related Posts for WordPress offers you the ability to link related posts to each other with just 1 click!
18
+
19
+ Our installation wizard will do all the hard work for you, simply activate the plugin, set the amount of posts that should relate and press the button. Related Posts for WordPress will do the rest. Relating posts in WordPress has never been this easy!
20
+
21
+ = Related Posts for WordPress won't lag your server! =
22
+ We don't think having related posts should slow down your website. That's why Related Posts for WordPress creates its own cache and does all the heavy lifting in the admin panel, keeping your website fast as it should be!
23
+
24
+ = Automatically link posts to each other =
25
+ After installing the plugin you will be taking to a wizard that will analyze your posts and link them to each other based on what we think is related. This means you can install Related Posts for WordPress on your website that has thousands of posts and create related connections on the fly, without any manual work!
26
+
27
+ = Manually add, edit or remove =
28
+ Everyone makes mistakes, so do we. That's why you can easily modify all automatically created related posts. Simply navigate to the post that has incorrect related posts attached to it, edit it and you're done.
29
+
30
+ = WPML compatible =
31
+ Related Posts for WordPress is fully compatible with WPML. You can automatically add manually link related posts in their own language.
32
+
33
+ = Shortcode =
34
+ Related Posts for WordPress has a shortcode allowing you to display related posts on any position within your content.
35
+
36
+ = Widget =
37
+ Related Posts for Wordpress has a widget allowing you to display related posts in any sidebar you'd like.
38
+
39
+ **More information**
40
+
41
+ - Visit the [Related Posts for WordPress website](http://www.relatedpostsforwp.com/?utm_source=wp-plugin-repo&utm_medium=link&utm_campaign=more-information)
42
+ - Other [WordPress plugins](http://profiles.wordpress.org/barrykooij/) by [Barry Kooij](http://www.barrykooij.com/)
43
+ - Contact Barry on Twitter: [@CageNL](http://twitter.com/CageNL)
44
+ - If you're a dev, follow or contribute to the [Related Posts for WordPress plugin on GitHub](https://github.com/barrykooij/related-posts-for-wp)
45
+
46
+
47
+ == Installation ==
48
+
49
+ = Installing the plugin =
50
+ 1. In your WordPress admin panel, go to *Plugins > New Plugin*, search for *Related Posts for WordPress* and click "Install now"
51
+ 1. Alternatively, download the plugin and upload the contents of `related-posts-for-wp.zip` to your plugins directory, which usually is `/wp-content/plugins/`.
52
+ 1. Activate the plugin
53
+
54
+ == Frequently Asked Questions ==
55
+
56
+ Please see the [FAQ section at our website.](http://www.relatedpostsforwp.com/faq/?utm_source=wp-plugin-repo&utm_medium=link&utm_campaign=faq)
57
+
58
+ = Where's the settings screen? =
59
+ Settings > Related Posts.
60
+
61
+ = Can the displaying of excerpt be disabled? =
62
+ Yes, set the excerpt length to 0 in the Related Posts for WordPress settings screen.
63
+
64
+ = Is there any way to custom CSS ? =
65
+ Yes, it's in the Related Posts for WordPress settings screen.
66
+
67
+ = Can the automatically outputted CSS be disabled? =
68
+ Yes, clear the CSS field in the Related Posts for WordPress settings screen.
69
+
70
+ = Is there a theme function so I can output this list anywhere in my theme I want? =
71
+ Not yet, we're working on this and this will be added soon!
72
+
73
+ = Is there a shortcode? =
74
+ Yes, use [rp4wp]
75
+
76
+ = Is there a widget? =
77
+ Yes there is!
78
+
79
+ = Does Related Posts for WordPress uses it's own database table ? =
80
+ There is one custom table created for the post cache, this table will however not be used at the frontend of your website. Related Posts are fetched with normal WP_Query objects.
81
+
82
+ == Screenshots ==
83
+ 1. After activating Related Posts for WordPress, our wizard will automatically start. The first step is indexing and caching your posts.
84
+ 2. The second step of the wizard is linking related posts for your existing content! You can of course also skip this step.
85
+ 3. That's it! With one click you are good to go!
86
+ 4. A new meta box is added to your post edit screens allowing you to link related posts, we will sort them on what we think is related (where top is most related).
87
+ 5. Related posts are automatically added below your posts!
88
+
89
+ == Changelog ==
90
+
91
+ = 1.7.0 =
92
+ * Major performance improvements for post link creation.
93
+ * Fixed a shortcode bug.
94
+ * Changed NONCE_REINSTALL constant to NONCE_INSTALL.
95
+ * Added nonce checks.
96
+
97
+ = 1.6.3: September 18, 2014 =
98
+ * Fixed an install bug.
99
+
100
+ = 1.6.2: September 17, 2014 =
101
+ * Fixed a WSOD caused by wp_created_nonce being called before init hook.
102
+ * Changed the way the plugin is bootstrapped.
103
+
104
+ = 1.6.1: September 13, 2014 =
105
+ * Fixed a bug that caused the manual post link table to be empty.
106
+ * Added checks to only do certain checks in admin.
107
+
108
+ = 1.6.0: September 12, 2014 =
109
+ * We're now replacing 'special' characters with their 'normal' equivalent.
110
+ * Save the wizard settings to options to improve defaults.
111
+ * Added a percentage to the progressbar to improve progress clarity.
112
+ * The wizard progress is now updated when returned to wizard.
113
+ * Various caching tweaks.
114
+ * Added utf8 charset to cache database table in installer.
115
+
116
+ = 1.5.0: September 5, 2014 =
117
+ * Added Related Posts widget.
118
+ * Changed 'Delete Post' label to 'Unlink Related Post'.
119
+ * Lowered amount of posts cached per request to increase feedback in wizard.
120
+ * Various small wizard tweaks.
121
+ * Added nonce check to wizard restart procedure.
122
+ * Fixed a plugin activation redirect bug.
123
+
124
+ = 1.4.1: August 29, 2014 =
125
+ * Added filter 'rp4wp_append_content' to allow disabling of related post append to content.
126
+ * Fixed various hook and filter class bugs.
127
+
128
+ = 1.4.0: August 24, 2014 =
129
+ * Created the possibility to restart the installation wizard. See settings page for this option.
130
+ * Added notice that allows resuming installation wizard that will be displayed if the installation wizard crashed.
131
+ * Only load frontend CSS on singles.
132
+ * Fixed a default image size bug, props [Robert Neu](https://github.com/robneu).
133
+ * Small default CSS tweaks, props [Jackie D'Elia](https://github.com/savvyjackie).
134
+ * Complete plugin is now translatable.
135
+ * Updated Dutch translation.
136
+ * Default values are now in site language, if available.
137
+ * Uninstall script now also deletes the caching table.
138
+ * Added 'settings' link to plugins links.
139
+
140
+ = 1.3.2: August 22, 2014 =
141
+ * Fixed a bug where ignored words where not properly loaded.
142
+
143
+ = 1.3.1: August 21, 2014 =
144
+ * Added an uninstall procedure, see settings panel.
145
+ * Added plugin icons (yay).
146
+
147
+ = 1.3.0 : August 18, 2014 =
148
+ * Added 'rp4wp_children' template function.
149
+ * Added shortcode [rp4wp]
150
+ * Added pot translation template file.
151
+ * Added Dutch translation.
152
+ * Added review request admin notice.
153
+
154
+ = 1.2.2 : August 16, 2014 =
155
+ * Solved a conflict with the NextGen plugin (apply_filters recursion on same filter kills underlying call).
156
+ * Excerpt length is now set in words instead of characters.
157
+ * Small default CSS tweaks.
158
+
159
+ = 1.2.1 : August 14, 2014 =
160
+ * Fixed a small CSS default rule.
161
+
162
+ = 1.2.0 : August 14, 2014 =
163
+ * Related Posts heading text is now a setting.
164
+ * Amount of words in excerpt is now a setting.
165
+ * Displaying images of related posts is now a setting.
166
+ * Frontend CSS is now editable via settings.
167
+ * Added 'rp4wp_heading' filter, allows filtering of complete related posts block heading.
168
+
169
+ = 1.1.0 : August 11, 2014 =
170
+ * Added settings screen.
171
+ * Added to option to automatically link related posts on new posts, enabled by default.
172
+ * Added 'rp4wp_ignored_words' filter.
173
+ * Added 'rp4wp_thumbnail_size' filter.
174
+ * Added missing ABSPATH checks.
175
+
176
+ = 1.0.0 : August 7, 2014 =
177
+ * Initial version
178
+
179
+ == Upgrade Notice ==
180
+ This version is safe to upgrade. If all of your related posts are linked automatically, we do recommend rerunning the wizard for better results.
trunk/related-posts-for-wp.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: Related Posts for WordPress
4
+ Plugin URI: http://www.relatedpostsforwp.com/
5
+ Description: Related Posts for WordPress, the best way to display related posts in WordPress.
6
+ Version: 1.7.0
7
+ Author: Barry Kooij
8
+ Author URI: http://www.barrykooij.com/
9
+ License: GPL v3
10
+
11
+ This program is free software: you can redistribute it and/or modify
12
+ it under the terms of the GNU General Public License as published by
13
+ the Free Software Foundation, either version 3 of the License, or
14
+ (at your option) any later version.
15
+
16
+ This program is distributed in the hope that it will be useful,
17
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ GNU General Public License for more details.
20
+
21
+ You should have received a copy of the GNU General Public License
22
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
23
+ */
24
+
25
+
26
+ if ( ! defined( 'ABSPATH' ) ) {
27
+ exit;
28
+ } // Exit if accessed directly
29
+
30
+ function rp4wp_load_plugin() {
31
+
32
+ if ( defined( 'RP4WP_PLUGIN_FILE' ) ) {
33
+ return false;
34
+ }
35
+
36
+ // Define
37
+ define( 'RP4WP_PLUGIN_FILE', __FILE__ );
38
+
39
+ // Load main plugin file
40
+ require_once plugin_dir_path( RP4WP_PLUGIN_FILE ) . 'classes/class-rp4wp.php';
41
+ RP4WP();
42
+
43
+ }
44
+
45
+ // Create object - Plugin init
46
+ add_action( 'plugins_loaded', 'rp4wp_load_plugin', 20 );
47
+
48
+ //
49
+ if( is_admin() && ( false === defined( 'DOING_AJAX' ) || false === DOING_AJAX ) ) {
50
+
51
+ // Load installer functions
52
+ require_once plugin_dir_path( __FILE__ ) . 'includes/installer-functions.php';
53
+
54
+ // Activation hook
55
+ register_activation_hook( __FILE__, 'rp4wp_activate_plugin' );
56
+ }
trunk/uninstall.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // What is happening?
4
+ if ( ! defined( 'ABSPATH' ) || ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
5
+ exit();
6
+ }
7
+
8
+ // Should we clean?
9
+ $options = get_option( 'rp4wp', array() );
10
+ if ( isset( $options['clean_on_uninstall'] ) && 1 == $options['clean_on_uninstall'] ) {
11
+
12
+ global $wpdb;
13
+
14
+ /**
15
+ * Once upon a time I was relating posts
16
+ * But now I'm only cleaning them up
17
+ * There's nothing I can do
18
+ * A total eclipse of the heart
19
+ */
20
+
21
+ // Get ID's of post links
22
+ $link_ids = get_posts(
23
+ array(
24
+ 'post_type' => 'rp4wp_link',
25
+ 'fields' => 'ids',
26
+ 'posts_per_page' => - 1
27
+ )
28
+ );
29
+
30
+ if ( count( $link_ids ) > 0 ) {
31
+ // Delete all link posts
32
+ $wpdb->query( "DELETE FROM $wpdb->posts WHERE `ID` IN (" . implode( ",", $link_ids ) . ");" );
33
+
34
+ // Delete all link post meta
35
+ $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE `post_id` IN (" . implode( ",", $link_ids ) . ");" );
36
+ }
37
+
38
+
39
+ // Delete the options
40
+ delete_option( 'rp4wp' );
41
+ delete_option( 'rp4wp_do_install' );
42
+ delete_option( 'rp4wp_install_date' );
43
+ delete_option( 'rp4wp_hide_nag' );
44
+
45
+ // Remove the post meta we attached to posts
46
+ $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE `meta_key` = 'rp4wp_auto_linked' OR `meta_key` = 'rp4wp_cached' " );
47
+
48
+ // Drop the word cache table
49
+ $wpdb->query( "DROP TABLE {$wpdb->prefix}rp4wp_cache ;" );
50
+
51
+ }