Related Posts for WordPress - Version 1.0.0

Version Description

  • August 7, 2014 =
  • Initial version
Download this release

Release Info

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

Version 1.0.0

Files changed (40) hide show
  1. assets/css/edit-post.css +37 -0
  2. assets/css/install.css +47 -0
  3. assets/images/ajax-loader.gif +0 -0
  4. assets/images/grabber.png +0 -0
  5. assets/js/edit-post.js +108 -0
  6. assets/js/install.js +98 -0
  7. classes/class-autoloader.php +61 -0
  8. classes/class-cap-manager.php +20 -0
  9. classes/class-class-manager.php +29 -0
  10. classes/class-constants.php +21 -0
  11. classes/class-installer.php +28 -0
  12. classes/class-link-related-table.php +276 -0
  13. classes/class-manager-filter.php +68 -0
  14. classes/class-manager-hook.php +53 -0
  15. classes/class-post-link-manager.php +333 -0
  16. classes/class-related-post-manager.php +128 -0
  17. classes/class-related-word-manager.php +419 -0
  18. classes/filters/class-filter-after-post.php +113 -0
  19. classes/filters/class-filter.php +40 -0
  20. classes/hooks/class-hook-admin-scripts.php +35 -0
  21. classes/hooks/class-hook-ajax-delete-link.php +55 -0
  22. classes/hooks/class-hook-ajax-install-link-posts.php +33 -0
  23. classes/hooks/class-hook-ajax-install-save-words.php +30 -0
  24. classes/hooks/class-hook-delete-words.php +23 -0
  25. classes/hooks/class-hook-frontend-css.php +14 -0
  26. classes/hooks/class-hook-link-related-screen.php +158 -0
  27. classes/hooks/class-hook-meta-box-ajax-sort.php +50 -0
  28. classes/hooks/class-hook-meta-box.php +13 -0
  29. classes/hooks/class-hook-page-install.php +99 -0
  30. classes/hooks/class-hook-post-type.php +9 -0
  31. classes/hooks/class-hook-related-save-words.php +33 -0
  32. classes/hooks/class-hook.php +38 -0
  33. classes/meta-boxes/class-meta-box-manage.php +124 -0
  34. ignored-words/de_DE.php +7 -0
  35. ignored-words/en_US.php +7 -0
  36. ignored-words/fr_FR.php +7 -0
  37. ignored-words/it_IT.php +7 -0
  38. ignored-words/nl_NL.php +5 -0
  39. readme.txt +72 -0
  40. related-posts-for-wp.php +109 -0
assets/css/edit-post.css ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .rp4wp_table_manage.sortable tr {
2
+ cursor: move;
3
+ }
4
+
5
+ .rp4wp_table_manage td {
6
+ padding-bottom: 11px;
7
+ }
8
+
9
+ .rp4wp_table_manage.sortable td {
10
+ background-position: 98% 50%;
11
+ background-image: url('../images/grabber.png');
12
+ background-repeat: no-repeat;
13
+ }
14
+
15
+ .rp4wp_table_manage tr:nth-child(odd),
16
+ .sp_pt_links_overview tr:nth-child(odd) {
17
+ background-color: #FCFCFC;
18
+ }
19
+
20
+ .rp4wp_button_holder {
21
+ padding: 10px 0;
22
+ float: right;
23
+ }
24
+
25
+ .rp4wp_button_holder span {
26
+ margin-left: 10px;
27
+ float: left;
28
+ }
29
+
30
+ .rp4wp_save_button {
31
+ float: right;
32
+ }
33
+
34
+ .rp4wp_ajaxloader {
35
+ height: 13px;
36
+ margin-left: 10px;
37
+ }
assets/css/install.css ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .install-steps {
2
+
3
+ }
4
+
5
+ .install-steps li {
6
+ width: 33%;
7
+ padding: 10px 15px;
8
+ font-weight: bold;
9
+ color: #eee;
10
+ background: #222222;
11
+ float: left;
12
+ -moz-box-sizing: border-box;
13
+ -webkit-box-sizing: border-box;
14
+ box-sizing: border-box;
15
+ }
16
+
17
+ .install-steps li.step-bar-active {
18
+ background: #0074a2;
19
+ }
20
+
21
+ .install-steps li:first-child {
22
+ margin-left: 0;
23
+ }
24
+
25
+ .rp4wp-install-link-box {
26
+ display: inline;
27
+ padding: 15px;
28
+ border: 1px solid #0074a2;
29
+ }
30
+
31
+ .rp4wp-step .rp4wp-install-link-box label {
32
+ padding-right: 20px;
33
+ }
34
+
35
+ .rp4wp-step .rp4wp-install-link-box input {
36
+ width: 40px;
37
+ text-align: center;
38
+ }
39
+
40
+ .rp4wp-step .rp4wp-install-link-box a.rp4wp-link-now-btn {
41
+ margin-left: 20px;
42
+ margin-right: 10px;
43
+ }
44
+
45
+ .rp4wp-step-2 #progressbar {
46
+ margin-top: 30px;
47
+ }
assets/images/ajax-loader.gif ADDED
Binary file
assets/images/grabber.png ADDED
Binary file
assets/js/edit-post.js ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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(){instance.delete_child(this);});
27
+ };
28
+
29
+ this.fix_helper = function(e, ui) {
30
+ ui.children().each(function() {
31
+ jQuery(this).width(jQuery(this).width());
32
+ });
33
+ return ui;
34
+ };
35
+
36
+ this.make_sortable = function() {
37
+ var instance = this;
38
+ var sortable_table = jQuery(this.container).find('.sortable tbody');
39
+
40
+ sortable_table.sortable({
41
+ helper: instance.fix_helper,
42
+ update: function(event, ui) {
43
+
44
+ jQuery(instance.container).parent().parent().find('h3').eq(0).append(
45
+ jQuery('<img>').attr('src', jQuery('#rp4wp-dir-img').val()+'ajax-loader.gif').addClass('rp4wp_ajaxloader')
46
+ );
47
+
48
+ opts = {
49
+ url: ajaxurl,
50
+ type: 'POST',
51
+ async: true,
52
+ cache: false,
53
+ dataType: 'json',
54
+ data:{
55
+ action: 'rp4wp_related_sort',
56
+ rp4wp_items: sortable_table.sortable('toArray').toString(),
57
+ nonce: jQuery(instance.container).find('#rp4wp-ajax-nonce').val()
58
+ },
59
+ success: function(response) {
60
+ jQuery('.rp4wp_ajaxloader').remove();
61
+ return;
62
+ },
63
+ error: function(xhr,textStatus,e) {
64
+ jQuery('.rp4wp_ajaxloader').remove();
65
+ return;
66
+ }
67
+ };
68
+ jQuery.ajax(opts);
69
+ }
70
+ });
71
+
72
+ };
73
+
74
+ this.delete_child = function(tgt) {
75
+
76
+ var confirm_delete = confirm( 'Are you sure you want to delete this related post?' );
77
+ if(!confirm_delete) {
78
+ return;
79
+ }
80
+
81
+ var instance = this;
82
+
83
+ var opts = {
84
+ url: ajaxurl,
85
+ type: 'POST',
86
+ async: true,
87
+ cache: false,
88
+ dataType: 'json',
89
+ data:{
90
+ action: 'rp4wp_delete_link',
91
+ id: jQuery(tgt).closest('tr').attr('id'),
92
+ nonce: jQuery(instance.container).find('#rp4wp-ajax-nonce').val()
93
+ },
94
+ success: function(response) {
95
+ jQuery(tgt).closest('tr').fadeTo('fast', 0).slideUp(function() {
96
+ jQuery(this).remove();
97
+ });
98
+ return;
99
+ },
100
+ error: function(xhr,textStatus,e) {
101
+ return;
102
+ }
103
+ };
104
+ jQuery.ajax(opts);
105
+ };
106
+
107
+ this.init();
108
+ }
assets/js/install.js ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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.req_nr = 0;
27
+ this.action = null;
28
+
29
+ this.do_request = function () {
30
+ var instance = this;
31
+ $.post(ajaxurl, {
32
+ 'action' : this.action,
33
+ 'rel_amount': $('#rp4wp_related_posts_amount').val()
34
+ }, function (response) {
35
+
36
+ // What next?
37
+ if ('more' == response) {
38
+ // Increase the request nr
39
+ instance.req_nr++;
40
+
41
+ // Do Progressbar
42
+ instance.do_progressbar();
43
+
44
+ // Do request
45
+ instance.do_request();
46
+
47
+ } else if( 'done' == response ) {
48
+ // Done
49
+ instance.done();
50
+ }else {
51
+ alert( "Woops! Something went wrong while linking.\n\nResponse:\n\n" + response );
52
+ }
53
+
54
+ });
55
+ };
56
+
57
+ this.done = function () {
58
+
59
+ // Update progressbar
60
+ $('#progressbar').progressbar({value: 100});
61
+
62
+ // Redirect to next step
63
+ window.location = $('#rp4wp_admin_url').val() + '?page=rp4wp_install&step=' + ( this.step + 1 );
64
+ };
65
+
66
+ this.do_progressbar = function () {
67
+ $('#progressbar').progressbar({value: ((this.req_nr * this.ppr) / this.total_posts) * 100});
68
+ };
69
+
70
+ this.init = function () {
71
+
72
+ // Setup the progressbar
73
+ $('#progressbar').progressbar({value: false});
74
+
75
+ // Get the total posts
76
+ this.total_posts = $('#rp4wp_total_posts').val();
77
+
78
+ // Set the correct action
79
+ switch (this.step) {
80
+ case 1:
81
+ this.ppr = 200;
82
+ this.action = 'rp4wp_install_save_words';
83
+ break;
84
+ case 2:
85
+ this.ppr = 5;
86
+ this.action = 'rp4wp_install_link_posts';
87
+ break;
88
+ }
89
+
90
+ // Do the first request
91
+ this.do_request();
92
+ };
93
+
94
+ this.init();
95
+
96
+ }
97
+
98
+ });
classes/class-autoloader.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ }
48
+
49
+ // Append file name to clas path
50
+ $file_path .= $file_name;
51
+
52
+ // Check & load file
53
+ if ( file_exists( $file_path ) ) {
54
+ require_once( $file_path );
55
+ }
56
+
57
+ }
58
+
59
+ }
60
+
61
+ }
classes/class-cap-manager.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ class RP4WP_Cap_Manager {
6
+
7
+ /**
8
+ * Get custom post type capabilities
9
+ *
10
+ * @param $post_id
11
+ *
12
+ * @return string
13
+ */
14
+ public static function get_capability( $post_id ) {
15
+ $post_type = ( isset( $post_id ) ) ? get_post_type( $post_id ) : 'post';
16
+ $post_type_obj = get_post_type_object( $post_type );
17
+ return ( ( null != $post_type_obj) ? $post_type_obj->cap->edit_posts : 'edit_posts' );
18
+ }
19
+
20
+ }
classes/class-class-manager.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ class RP4WP_Class_Manager {
6
+
7
+ /**
8
+ * Uppercase the character after the underscore, used as callback by SP_Class_Manager::format_class_name.
9
+ *
10
+ * @param $part
11
+ *
12
+ * @return string
13
+ */
14
+ public static function capitalize_part( $part ) {
15
+ return '_' . strtoupper( substr( $part[0], 1, 1 ) );
16
+ }
17
+
18
+ /**
19
+ * Format the class name by the file name
20
+ *
21
+ * @param $file_name
22
+ *
23
+ * @return string
24
+ */
25
+ public static function format_class_name( $file_name ) {
26
+ return preg_replace_callback( "/(_[a-z])/", array( 'RP4WP_Class_Manager', 'capitalize_part' ), 'RP4WP_' . str_ireplace( '-', '_', str_ireplace( array( 'class-', '.php' ), "", $file_name ) ) );
27
+ }
28
+
29
+ }
classes/class-constants.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( !defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ abstract class RP4WP_Constants {
8
+
9
+ // const LINK_TITLE = 'rp4wp_link';
10
+ const LINK_PT = 'rp4wp_link';
11
+
12
+ // Post meta
13
+ const PM_PARENT = 'rp4wp_parent';
14
+ const PM_CHILD = 'rp4wp_child';
15
+ const PM_CACHED = 'rp4wp_cached';
16
+ const PM_AUTO_LINKED = 'rp4wp_auto_linked';
17
+
18
+ // Options
19
+ const OPTION_DO_INSTALL = 'rp4wp_do_install';
20
+
21
+ }
classes/class-installer.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class RP4WP_Installer {
4
+
5
+ /**
6
+ * Create the related cache database table
7
+ */
8
+ public function create_db_table_related() {
9
+ global $wpdb;
10
+
11
+ $sql = "CREATE TABLE IF NOT EXISTS `" . RP4WP_Related_Word_Manager::get_database_table() . "` (
12
+ `post_id` bigint(20) unsigned NOT NULL,
13
+ `word` varchar(255) CHARACTER SET utf8 NOT NULL,
14
+ `weight` float unsigned NOT NULL,
15
+ `post_type` varchar(20) CHARACTER SET utf8 NOT NULL,
16
+ PRIMARY KEY (`post_id`,`word`) );";
17
+
18
+ $wpdb->query( $sql );
19
+ }
20
+
21
+ /**
22
+ * Install method, do all the install work
23
+ */
24
+ public function install() {
25
+ $this->create_db_table_related();
26
+ }
27
+
28
+ }
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
+ }
classes/class-manager-filter.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ } // Exit if accessed directly
6
+
7
+ class RP4WP_Manager_Filter {
8
+
9
+ private $filter_dir;
10
+ private static $filters;
11
+
12
+ public function __construct( $filter_dir ) {
13
+ $this->filter_dir = $filter_dir;
14
+ }
15
+
16
+ /**
17
+ * Load on specific filter instead of all filters.
18
+ * This method should be used when the load_filters() isn't run yet, for example in the (de)activation process.
19
+ *
20
+ * @param $file_name
21
+ */
22
+ public function load_filter( $file_name ) {
23
+ $class = RP4WP_Class_Manager::format_class_name( $file_name );
24
+ if ( 'RP4WP_Filter' != $class ) {
25
+ self::$filters[$class] = new $class;
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Load and set hooks
31
+ *
32
+ * @access public
33
+ * @static
34
+ * @return void
35
+ */
36
+ public function load_filters() {
37
+
38
+ foreach ( new DirectoryIterator( $this->filter_dir ) as $file ) {
39
+ $file_name = $file->getFileName();
40
+
41
+ if ( ! $file->isDir() && ( strpos( $file->getFileName(), '.' ) !== 0 ) ) {
42
+
43
+ $class = RP4WP_Class_Manager::format_class_name( $file->getFileName() );
44
+ if ( 'RP4WP_Filter' != $class ) {
45
+ self::$filters[$class] = new $class;
46
+ }
47
+
48
+ }
49
+ }
50
+
51
+ }
52
+
53
+ /**
54
+ * Return instance of created hook
55
+ *
56
+ * @param $class_name
57
+ *
58
+ * @return Hook
59
+ */
60
+ public function get_hook_instance( $class_name ) {
61
+ if ( isset( self::$hooks[$class_name] ) ) {
62
+ return self::$hooks[$class_name];
63
+ }
64
+
65
+ return null;
66
+ }
67
+
68
+ }
classes/class-manager-hook.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ class RP4WP_Manager_Hook {
6
+
7
+ private $hook_dir;
8
+ private static $hooks;
9
+
10
+ public function __construct( $hook_dir ) {
11
+ $this->hook_dir = $hook_dir;
12
+ }
13
+
14
+ /**
15
+ * Load and set hooks
16
+ *
17
+ * @access public
18
+ * @static
19
+ * @return void
20
+ */
21
+ public function load_hooks() {
22
+
23
+ foreach ( new DirectoryIterator( $this->hook_dir ) as $file ) {
24
+ $file_name = $file->getFileName();
25
+
26
+ if ( ! $file->isDir() && ( strpos( $file->getFileName(), '.' ) !== 0 ) ) {
27
+
28
+ $class = RP4WP_Class_Manager::format_class_name( $file->getFileName() );
29
+ if ( 'RP4WP_Hook' != $class ) {
30
+ self::$hooks[$class] = new $class;
31
+ }
32
+
33
+ }
34
+
35
+ }
36
+
37
+ }
38
+
39
+ /**
40
+ * Return instance of created hook
41
+ *
42
+ * @param $class_name
43
+ *
44
+ * @return Hook
45
+ */
46
+ public function get_hook_instance( $class_name ) {
47
+ if ( isset( self::$hooks[$class_name] ) ) {
48
+ return self::$hooks[$class_name];
49
+ }
50
+ return null;
51
+ }
52
+
53
+ }
classes/class-post-link-manager.php ADDED
@@ -0,0 +1,333 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ 'post_type' => RP4WP_Constants::LINK_PT,
55
+ 'posts_per_page' => - 1,
56
+ 'orderby' => 'menu_order',
57
+ 'order' => 'ASC',
58
+ 'meta_query' => array(
59
+ array(
60
+ 'key' => RP4WP_Constants::PM_PARENT,
61
+ 'value' => $parent_id,
62
+ 'compare' => '=',
63
+ ),
64
+ )
65
+ )
66
+ );
67
+
68
+ // Reset global post variables
69
+ wp_reset_postdata();
70
+
71
+ return $link_query->found_posts;
72
+ }
73
+
74
+ /**
75
+ * Method to add a PostLink
76
+ *
77
+ * @access public
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
101
+ return $link_id;
102
+ }
103
+
104
+ /**
105
+ * Delete a link
106
+ *
107
+ * @access public
108
+ *
109
+ * @param id $link_id
110
+ *
111
+ * @return void
112
+ */
113
+ public function delete( $link_id ) {
114
+ // Action
115
+ do_action( 'rp4wp_before_link_delete', $link_id );
116
+
117
+ // Delete link
118
+ wp_delete_post( $link_id, true );
119
+
120
+ // Action
121
+ do_action( 'rp4wp_after_link_delete', $link_id );
122
+
123
+ return;
124
+ }
125
+
126
+ /**
127
+ * Get children based on parent_id.
128
+ * It's possible to add extra arguments to the WP_Query with the $extra_args argument
129
+ *
130
+ * @access public
131
+ *
132
+ * @param int $parent_id
133
+ * @param array $extra_args
134
+ *
135
+ * @return array
136
+ */
137
+ public function get_children( $parent_id, $extra_args = null ) {
138
+ global $post;
139
+
140
+ // Store current post
141
+ $o_post = $post;
142
+
143
+ // Do WP_Query
144
+ $link_args = $this->create_link_args( RP4WP_Constants::PM_PARENT, $parent_id );
145
+
146
+ /*
147
+ * Check $extra_args for `posts_per_page`.
148
+ * This is the only arg that should be added to link query instead of the child query
149
+ */
150
+ if ( isset( $extra_args['posts_per_page'] ) ) {
151
+
152
+ // Set posts_per_page to link arguments
153
+ $link_args['posts_per_page'] = $extra_args['posts_per_page'];
154
+ unset( $extra_args['posts_per_page'] );
155
+ }
156
+
157
+ /*
158
+ * Check $extra_args for `order`.
159
+ * If 'order' is set without 'orderby', we should add it to the link arguments
160
+ */
161
+ if ( isset( $extra_args['order'] ) && !isset( $extra_args['orderby'] ) ) {
162
+ $link_args['order'] = $extra_args['order'];
163
+ unset( $extra_args['order'] );
164
+ }
165
+
166
+ // Create link query
167
+ $link_query = new WP_Query( $link_args );
168
+
169
+ // Store child ids
170
+ // @todo remove the usage of get_the_id()
171
+ $child_ids = array();
172
+ while ( $link_query->have_posts() ) : $link_query->the_post();
173
+ $child_ids[get_the_id()] = get_post_meta( get_the_id(), RP4WP_Constants::PM_CHILD, true );
174
+ endwhile;
175
+
176
+ // Get children with custom args
177
+ if ( $extra_args !== null && count( $extra_args ) > 0 ) {
178
+
179
+ if ( !isset( $extra_args['orderby'] ) ) {
180
+ $this->temp_child_order = array();
181
+ foreach ( $child_ids as $child_id ) {
182
+ $this->temp_child_order[] = $child_id;
183
+ }
184
+ }
185
+
186
+ // Get child again, but this time by $extra_args
187
+ $children = array();
188
+
189
+ //Child WP_Query arguments
190
+ if ( count( $child_ids ) > 0 ) {
191
+ $child_id_values = array_values( $child_ids );
192
+ $child_post_type = get_post_type( array_shift( $child_id_values ) );
193
+ $child_args = array(
194
+ 'post_type' => $child_post_type,
195
+ 'posts_per_page' => - 1,
196
+ 'post__in' => $child_ids,
197
+ );
198
+
199
+ // Extra arguments
200
+ $child_args = array_merge_recursive( $child_args, $extra_args );
201
+
202
+ // Child Query
203
+ $child_query = new WP_Query( $child_args );
204
+
205
+ while ( $child_query->have_posts() ) : $child_query->the_post();
206
+ // Add post to correct original sort key
207
+ $children[array_search( $child_query->post->ID, $child_ids )] = $child_query->post;
208
+ endwhile;
209
+
210
+ // Fix sorting
211
+ if ( !isset( $extra_args['orderby'] ) ) {
212
+ uasort( $children, array( $this, 'sort_get_children_children' ) );
213
+ }
214
+
215
+ }
216
+ } else {
217
+ // No custom arguments found, get all objects of stored ID's
218
+ $children = array();
219
+ foreach ( $child_ids as $link_id => $child_id ) {
220
+ $children[$link_id] = get_post( $child_id );
221
+ }
222
+ }
223
+
224
+ // Reset global post variables
225
+ wp_reset_postdata();
226
+
227
+ // Restoring post
228
+ $post = $o_post;
229
+
230
+ // Return children
231
+ return $children;
232
+ }
233
+
234
+ /**
235
+ * Custom sort method to reorder children
236
+ *
237
+ * @param $a
238
+ * @param $b
239
+ *
240
+ * @return mixed
241
+ */
242
+ public function sort_get_children_children( $a, $b ) {
243
+ return array_search( $a->ID, $this->temp_child_order ) - array_search( $b->ID, $this->temp_child_order );
244
+ }
245
+
246
+ /**
247
+ * Delete all links involved in given post_id
248
+ *
249
+ * @access public
250
+ *
251
+ * @param $post_id
252
+ */
253
+ public function delete_links_related_to( $post_id ) {
254
+ $involved_query = new WP_Query( array(
255
+ 'post_type' => RP4WP_Constants::LINK_PT,
256
+ 'posts_per_page' => - 1,
257
+ 'meta_query' => array(
258
+ 'relation' => 'OR',
259
+ array(
260
+ 'key' => RP4WP_Constants::PM_PARENT,
261
+ 'value' => $post_id,
262
+ 'compare' => '=',
263
+ ),
264
+ array(
265
+ 'key' => RP4WP_Constants::PM_CHILD,
266
+ 'value' => $post_id,
267
+ 'compare' => '=',
268
+ )
269
+ )
270
+ ) );
271
+ while ( $involved_query->have_posts() ) : $involved_query->the_post();
272
+ wp_delete_post( $involved_query->post->ID, true );
273
+ endwhile;
274
+ }
275
+
276
+ /**
277
+ * Generate the children list
278
+ *
279
+ * @param $parent
280
+ * @param $link
281
+ * @param $excerpt
282
+ * @param string $header_tag
283
+ *
284
+ * @return string
285
+ */
286
+ public function generate_children_list( $parent, $link, $excerpt, $header_tag = 'b' ) {
287
+
288
+ // Make the header tag filterable
289
+ $header_tag = apply_filters( 'pc_children_list_header_tag', $header_tag );
290
+
291
+
292
+ // Get the children
293
+ $children = $this->get_children( $parent );
294
+
295
+
296
+ $return = "";
297
+
298
+ if ( count( $children ) > 0 ) {
299
+ $return .= "<div class='rp4wp-related-posts'>\n";
300
+
301
+ $return .= "<ul>\n";
302
+ foreach ( $children as $child ) {
303
+
304
+ $return .= "<li class='rp4wp-post-{$child->ID}'>";
305
+ $return .= "<{$header_tag}>";
306
+ if ( $link == 'true' ) {
307
+ $return .= "<a href='" . get_permalink( $child->ID ) . "'>";
308
+ }
309
+ $return .= $child->post_title;
310
+ if ( $link == 'true' ) {
311
+ $return .= "</a>";
312
+ }
313
+ $return .= "</{$header_tag}>";
314
+
315
+ // Excerpt
316
+ if ( $excerpt == 'true' ) {
317
+ $the_excerpt = !empty( $child->post_excerpt ) ? $child->post_excerpt : $child->post_content;
318
+ if ( $the_excerpt != '' ) {
319
+ $return .= "<p>{$the_excerpt}</p>";
320
+ }
321
+ }
322
+
323
+ $return .= "</li>\n";
324
+ }
325
+ $return .= "</ul>\n";
326
+
327
+ $return .= "</div>\n";
328
+ }
329
+
330
+ return $return;
331
+ }
332
+
333
+ }
classes/class-related-post-manager.php ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class RP4WP_Related_Post_Manager {
4
+
5
+ /**
6
+ * Get related posts by post id and post type
7
+ *
8
+ * @param $post_id
9
+ *
10
+ * @return array
11
+ */
12
+ public function get_related_posts( $post_id, $limit = - 1 ) {
13
+ global $wpdb;
14
+
15
+ $related_posts = array();
16
+
17
+ // Build SQl
18
+ $sql = "
19
+ SELECT O.`word`, P.`ID`, P.`post_title`, SUM( R.`weight` ) AS `related_weight`
20
+ FROM `" . RP4WP_Related_Word_Manager::get_database_table() . "` O
21
+ INNER JOIN `" . RP4WP_Related_Word_Manager::get_database_table() . "` R ON R.`word` = O.`word`
22
+ INNER JOIN `" . $wpdb->posts . "` P ON P.`ID` = R.`post_id`
23
+ WHERE 1=1
24
+ AND O.`post_id` = %d
25
+ AND R.`post_type` = 'post'
26
+ AND R.`post_id` != %d
27
+ AND P.`post_status` = 'publish'
28
+ GROUP BY P.`id`
29
+ ORDER BY `related_weight` DESC
30
+ ";
31
+
32
+ // Check & Add Limit
33
+ if ( - 1 != $limit ) {
34
+ $sql .= "
35
+ LIMIT 0,%d";
36
+ };
37
+
38
+ // Prepare SQL
39
+ $sql = $wpdb->prepare( $sql, $post_id, $post_id, $limit );
40
+
41
+ // Get post from related cache
42
+ $rposts = $wpdb->get_results( $sql );
43
+
44
+ if ( count( $rposts ) > 0 ) {
45
+ foreach ( $rposts as $rpost ) {
46
+ if ( !isset( $related_posts[$rpost->ID] ) ) {
47
+ $related_posts[] = $rpost;
48
+ }
49
+
50
+ }
51
+ }
52
+
53
+ return $related_posts;
54
+ }
55
+
56
+ /**
57
+ * Get non auto linked posts
58
+ *
59
+ * @param $limit
60
+ *
61
+ * @return array
62
+ */
63
+ public function get_not_auto_linked_posts( $limit ) {
64
+ return get_posts( array(
65
+ 'post_type' => 'post',
66
+ 'posts_per_page' => $limit,
67
+ 'post_status' => 'publish',
68
+ 'meta_query' => array(
69
+ array(
70
+ 'key' => RP4WP_Constants::PM_AUTO_LINKED,
71
+ 'compare' => 'NOT EXISTS',
72
+ 'value' => ''
73
+ ),
74
+ )
75
+ ) );
76
+ }
77
+
78
+ /**
79
+ * Link x related posts to post
80
+ *
81
+ * @param $post_id
82
+ * @param $amount
83
+ *
84
+ * @return boolean
85
+ */
86
+ public function link_related_post( $post_id, $amount ) {
87
+ $related_posts = $this->get_related_posts( $post_id, $amount );
88
+
89
+ if ( count( $related_posts ) > 0 ) {
90
+
91
+ $post_link_manager = new RP4WP_Post_Link_Manager();
92
+
93
+ foreach ( $related_posts as $related_post ) {
94
+ $post_link_manager->add( $post_id, $related_post->ID );
95
+ }
96
+ }
97
+
98
+ update_post_meta( $post_id, RP4WP_Constants::PM_AUTO_LINKED, 1);
99
+
100
+ return true;
101
+ }
102
+
103
+ /**
104
+ * Link x related posts to y not already linked posts
105
+ *
106
+ * @param int $rel_amount
107
+ * @param int $post_amount
108
+ *
109
+ * @return boolean
110
+ */
111
+ public function link_related_posts( $rel_amount, $post_amount = - 1 ) {
112
+ global $wpdb;
113
+
114
+ // Get uncached posts
115
+ $posts = $this->get_not_auto_linked_posts( $post_amount );
116
+
117
+ // Check & Loop
118
+ if ( count( $posts ) > 0 ) {
119
+ foreach ( $posts as $post ) {
120
+ $this->link_related_post( $post->ID, $rel_amount );
121
+ }
122
+ }
123
+
124
+ // Done
125
+ return true;
126
+ }
127
+
128
+ }
classes/class-related-word-manager.php ADDED
@@ -0,0 +1,419 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ /**
12
+ * Get the database table
13
+ *
14
+ * @return string
15
+ */
16
+ public static function get_database_table() {
17
+ global $wpdb;
18
+
19
+ return $wpdb->prefix . self::DB_TABLE;
20
+ }
21
+
22
+ /**
23
+ * Internal method that formats and outputs the $ignored_words array to screen
24
+ */
25
+ public function dedupe_and_order_ignored_words( $lang ) {
26
+ $output = '$ignored_words = array(';
27
+
28
+ $ignored_words = $this->get_ignored_words( $lang );
29
+
30
+ $temp_words = array();
31
+ foreach ( $ignored_words as $word ) {
32
+
33
+ // Only add word if it's not already added
34
+ if ( !in_array( $word, $temp_words ) ) {
35
+ if ( false !== strpos( $word, "Ã" ) ) {
36
+ continue;
37
+ }
38
+ $temp_words[] = str_ireplace( "'", "", $word );
39
+ }
40
+
41
+ }
42
+
43
+ sort( $temp_words );
44
+
45
+
46
+ foreach ( $temp_words as $word ) {
47
+ $output .= " '{$word}',";
48
+ }
49
+
50
+
51
+ $output .= ");";
52
+
53
+ echo $output;
54
+ die();
55
+ }
56
+
57
+ /**
58
+ * Get the ignored words
59
+ *
60
+ * @param string $lang
61
+ *
62
+ * @return array
63
+ */
64
+ private function get_ignored_words( $lang = '' ) {
65
+
66
+ // Set the language
67
+ if ( '' == $lang ) {
68
+ $lang = get_locale();
69
+ }
70
+
71
+ // Require the lang file
72
+ $relative_path = '/ignored-words/' . $lang . '.php';
73
+
74
+ // Validate the file path to prevent traversal attacks
75
+ if ( 0 !== validate_file( $relative_path ) ) {
76
+ return array();
77
+ }
78
+
79
+ $filename = dirname( __FILE__ ) . $relative_path;
80
+
81
+ // Check if file exists
82
+ if ( !file_exists( $filename ) ) {
83
+ return array();
84
+ }
85
+
86
+ // Require the file
87
+ $ignored_words = require( $filename );
88
+
89
+ // Check if the the $ignored_words are set
90
+ if ( is_null( $ignored_words ) || !is_array( $ignored_words ) ) {
91
+ return array();
92
+ }
93
+
94
+ // Words to ignore
95
+ return apply_filters( 'pc_ignored_words', $ignored_words );
96
+ }
97
+
98
+ /**
99
+ * Get the words from the post content
100
+ *
101
+ * @param $post
102
+ *
103
+ * @return array $words
104
+ */
105
+ private function get_content_words( $post ) {
106
+
107
+ $content = $post->post_content;
108
+
109
+ // Remove all line break
110
+ $content = trim( preg_replace( '/\s+/', ' ', $content ) );
111
+
112
+ // Array to store the linked words
113
+ $linked_words = array();
114
+
115
+ // Find all links in the content
116
+ if ( true == preg_match_all( '`<a[^>]*href="([^"]+)">[^<]*</a>`si', $content, $matches ) ) {
117
+ if ( count( $matches[1] ) > 0 ) {
118
+
119
+ // Loop
120
+ foreach ( $matches[1] as $url ) {
121
+
122
+ // Get the post Id
123
+ $link_post_id = url_to_postid( $url );
124
+
125
+ if ( 0 == $link_post_id ) {
126
+ continue;
127
+ }
128
+
129
+ // Get the post
130
+ $link_post = get_post( $link_post_id );
131
+
132
+ // Check if we found a linked post
133
+ if ( $link_post != null ) {
134
+ // Get words of title
135
+ $title_words = explode( ' ', $link_post->post_title );
136
+
137
+ // Check, Loop
138
+ if ( is_array( $title_words ) && count( $title_words ) > 0 ) {
139
+ foreach ( $title_words as $title_word ) {
140
+
141
+ $title_word_multiplied = array_fill( 0, 20, $title_word );
142
+ $linked_words = array_merge( $linked_words, $title_word_multiplied );
143
+
144
+ }
145
+ }
146
+ }
147
+
148
+ }
149
+
150
+ }
151
+ }
152
+
153
+ // Remove all html tags
154
+ $content = strip_tags( $content );
155
+
156
+ // Remove all shortcodes
157
+ $content = strip_shortcodes( $content );
158
+
159
+ // Remove the <!--more--> tag
160
+ $content = str_ireplace( '<!--more-->', '', $content );
161
+
162
+ // Remove everything but letters and numbers
163
+ // $content = preg_replace( '/[^a-z0-9]+/i', ' ', $content );
164
+
165
+ // Split string into words
166
+ $words = explode( ' ', $content );
167
+
168
+ // Add the $linked_words
169
+ $words = array_merge( $words, $linked_words );
170
+
171
+ // Return the $words
172
+ return $words;
173
+ }
174
+
175
+ /**
176
+ * Add words from an array to the "base" words array, multiplied by their weight
177
+ *
178
+ * @param array $base_words
179
+ * @param array $words
180
+ * @param int $weight
181
+ *
182
+ * @return array
183
+ */
184
+ private function add_words_from_array( array $base_words, $words, $weight = 1 ) {
185
+
186
+ if ( !is_array( $words ) ) {
187
+ return $base_words;
188
+ }
189
+
190
+ foreach ( $words as $word ) {
191
+ $word_multiplied_by_weight = array_fill( 0, $weight, $word );
192
+ $base_words = array_merge( $base_words, $word_multiplied_by_weight );
193
+ }
194
+
195
+ return $base_words;
196
+ }
197
+
198
+ /**
199
+ * Get the words of a post
200
+ *
201
+ * @param int $post_id
202
+ *
203
+ * @return array $words
204
+ */
205
+ public function get_words_of_post( $post_id ) {
206
+
207
+ $post = get_post( $post_id );
208
+
209
+ $title_weight = apply_filters( 'rp4wp_weight_title', 80 );
210
+ $tag_weight = apply_filters( 'rp4wp_weight_tag', 10 );
211
+ $cat_weight = apply_filters( 'rp4wp_weight_cat', 20 );
212
+
213
+ // Get words from content
214
+ $raw_words = $this->get_content_words( $post );
215
+
216
+ // Get words from title
217
+ $title_words = explode( ' ', $post->post_title );
218
+ $raw_words = $this->add_words_from_array( $raw_words, $title_words, $title_weight );
219
+
220
+ // Get tags and add them to list
221
+ $tags = wp_get_post_tags( $post->ID, array( 'fields' => 'names' ) );
222
+
223
+ if ( is_array( $tags ) && count( $tags ) > 0 ) {
224
+ foreach ( $tags as $tag ) {
225
+ $tag_words = explode( ' ', $tag );
226
+ $raw_words = $this->add_words_from_array( $raw_words, $tag_words, $tag_weight );
227
+ }
228
+ }
229
+
230
+ // Get categories and add them to list
231
+ $categories = wp_get_post_categories( $post->ID, array( 'fields' => 'names' ) );
232
+ if ( is_array( $categories ) && count( $categories ) > 0 ) {
233
+ foreach ( $categories as $category ) {
234
+ $cat_words = explode( ' ', $category );
235
+ $raw_words = $this->add_words_from_array( $raw_words, $cat_words, $cat_weight );
236
+ }
237
+ }
238
+
239
+ // Count words and store them in array
240
+ $words = array();
241
+
242
+ if ( is_array( $raw_words ) && count( $raw_words ) > 0 ) {
243
+
244
+ $ignored_words = $this->get_ignored_words();
245
+
246
+ foreach ( $raw_words as $word ) {
247
+
248
+ // Trim word
249
+ $word = strtolower( trim( $word ) );
250
+
251
+ // Skip empty words
252
+ if ( '' == $word ) {
253
+ continue;
254
+ }
255
+
256
+ // Only use words longer than 1 charecter
257
+ if ( strlen( $word ) < 2 ) {
258
+ continue;
259
+ }
260
+
261
+ // Skip ignored words
262
+ if ( in_array( $word, $ignored_words ) ) {
263
+ continue;
264
+ }
265
+
266
+ // Add word
267
+ if ( isset( $words[$word] ) ) {
268
+ $words[$word] += 1;
269
+ } else {
270
+ $words[$word] = 1;
271
+ }
272
+
273
+ }
274
+ }
275
+
276
+ // Sort words
277
+ arsort( $words );
278
+
279
+ // Only return words that occur more than X(3)
280
+
281
+ $new_words = array();
282
+ $total_raw_words = count( $raw_words );
283
+ $length_weight = 0.6;
284
+
285
+ foreach ( $words as $word => $amount ) {
286
+
287
+ if ( $amount < 3 ) {
288
+ break; // We can break because the array is already sorted
289
+ }
290
+
291
+ // Add word and turn amount into weight (make it relative)
292
+ $new_words[$word] = ( $amount / ( $length_weight * $total_raw_words ) );
293
+
294
+ }
295
+
296
+ // Replace $words
297
+ $words = $new_words;
298
+
299
+ // Return words
300
+ return $words;
301
+
302
+ }
303
+
304
+ /**
305
+ * Save words of given post
306
+ *
307
+ * @param $post_id
308
+ */
309
+ public function save_words_of_post( $post_id ) {
310
+ global $wpdb;
311
+
312
+ // Get words
313
+ $words = $this->get_words_of_post( $post_id );
314
+
315
+ // Check words
316
+ if ( is_array( $words ) && count( $words ) > 0 ) {
317
+
318
+ // Get post type
319
+ $post_type = get_post_type( $post_id );
320
+
321
+ // Delete all currents words of post
322
+ $this->delete_words( $post_id );
323
+
324
+ // Loop words
325
+ foreach ( $words as $word => $amount ) {
326
+
327
+ // Insert word row
328
+ $wpdb->insert(
329
+ self::get_database_table(),
330
+ array(
331
+ 'post_id' => $post_id,
332
+ 'word' => $word,
333
+ 'weight' => $amount,
334
+ 'post_type' => $post_type
335
+ ),
336
+ array(
337
+ '%d',
338
+ '%s',
339
+ '%f',
340
+ '%s',
341
+ )
342
+ );
343
+
344
+ }
345
+
346
+ }
347
+
348
+ // Update this post as cached
349
+ update_post_meta( $post_id, RP4WP_Constants::PM_CACHED, 1 );
350
+
351
+ }
352
+
353
+ /**
354
+ * Get uncached posts
355
+ *
356
+ * @param int $limit
357
+ *
358
+ * @return array
359
+ */
360
+ public function get_uncached_posts( $limit = - 1 ) {
361
+ // Get Posts without 'cached' PM
362
+ return get_posts( array(
363
+ 'post_type' => 'post',
364
+ 'posts_per_page' => $limit,
365
+ 'post_status' => 'publish',
366
+ 'meta_query' => array(
367
+ array(
368
+ 'key' => RP4WP_Constants::PM_CACHED,
369
+ 'compare' => 'NOT EXISTS',
370
+ 'value' => ''
371
+ ),
372
+ )
373
+ ) );
374
+ }
375
+
376
+ /**
377
+ * Save all words of posts
378
+ */
379
+ public function save_all_words( $limit = - 1 ) {
380
+ global $wpdb;
381
+
382
+ // Get uncached posts
383
+ $posts = $this->get_uncached_posts( $limit );
384
+
385
+ // Check & Loop
386
+ if ( count( $posts ) > 0 ) {
387
+ foreach ( $posts as $post ) {
388
+ $this->save_words_of_post( $post->ID );
389
+ }
390
+ }
391
+
392
+ // Done
393
+ return true;
394
+ }
395
+
396
+ /**
397
+ * Get the amount of words of a post
398
+ *
399
+ *
400
+ * @return int
401
+ */
402
+ public function get_word_count() {
403
+ global $wpdb;
404
+
405
+ return $wpdb->get_var( "SELECT COUNT(word) FROM `" . self::get_database_table() . "` WHERE `post_type` = 'post'" );
406
+ }
407
+
408
+ /**
409
+ * Delete words by post ID
410
+ *
411
+ * @param $post_id
412
+ */
413
+ public function delete_words( $post_id ) {
414
+ global $wpdb;
415
+
416
+ $wpdb->delete( self::get_database_table(), array( 'post_id' => $post_id ), array( '%d' ) );
417
+ }
418
+
419
+ }
classes/filters/class-filter-after-post.php ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * Generate the post list
13
+ *
14
+ * @param $slug
15
+ * @param $title
16
+ * @param $posts
17
+ *
18
+ * @return string
19
+ */
20
+ private function create_post_list( $posts, $display_excerpt, $display_image ) {
21
+
22
+ $content = "<div class='rp4wp-related-posts'>\n";
23
+
24
+ // Output the relation title
25
+ $content .= "<h3>" . __( 'Related Posts', 'related-posts-for-wp' ) . "</h3> \n";
26
+
27
+ // Open the list
28
+ $content .= "<ul>\n";
29
+
30
+ foreach ( $posts as $pc_post ) {
31
+
32
+ // Setup the postdata
33
+ setup_postdata( $pc_post );
34
+
35
+ // Output the linked post
36
+ $content .= "<li>";
37
+
38
+ if ( '1' == $display_image ) {
39
+ if ( has_post_thumbnail( $pc_post->ID ) ) {
40
+
41
+ /**
42
+ * Filter: 'pc_apdc_thumbnail_size' - Allows changing the thumbnail size of the thumbnail in de APDC section
43
+ *
44
+ * @api String $thumbnail_size The current/default thumbnail size.
45
+ */
46
+ $thumb_size = apply_filters( 'pc_apdc_thumbnail_size', 'post-thumbnail' );
47
+
48
+ $content .= "<div class='rp4wp-related-post-image'>" . PHP_EOL;
49
+ $content .= "<a href='" . get_permalink( $pc_post->ID ) . "'>";
50
+ $content .= get_the_post_thumbnail( $pc_post->ID, $thumb_size );
51
+ $content .= "</a>";
52
+ $content .= "</div>" . PHP_EOL;
53
+ }
54
+ }
55
+
56
+ $content .= "<div class='rp4wp-related-post-content'>" . PHP_EOL;
57
+ $content .= "<a href='" . get_permalink( $pc_post->ID ) . "'>" . $pc_post->post_title . "</a>";
58
+
59
+ if ( '1' == $display_excerpt ) {
60
+ $content .= "<p>" . get_the_excerpt() . "</p>";
61
+ }
62
+
63
+ $content .= "</div>" . PHP_EOL;
64
+
65
+ $content .= "</li>\n";
66
+
67
+ // Reset the postdata
68
+ wp_reset_postdata();
69
+ }
70
+
71
+ // Close the wrapper div
72
+ $content .= "</ul>\n";
73
+ $content .= "</div>\n";
74
+
75
+ return $content;
76
+
77
+ }
78
+
79
+ /**
80
+ * the_content filter that will add linked posts to the bottom of the main post content
81
+ *
82
+ * @param $content
83
+ *
84
+ * @return string
85
+ */
86
+ public function run( $content ) {
87
+ /**
88
+ * Wow, what's going on here?! Well, setup_postdata() sets a lot of variables but does not change the $post variable.
89
+ * All checks return the main queried ID but we want to check if this specific filter call is the for the 'main' content.
90
+ * The method setup_postdata() does global and set the $id variable, so we're checking that.
91
+ */
92
+ global $id;
93
+
94
+ // Only run on single
95
+ if ( !is_singular() || !is_main_query() || $id != get_queried_object_id() ) {
96
+ return $content;
97
+ }
98
+
99
+ // Post Link Manager
100
+ $pl_manager = new RP4WP_Post_Link_Manager();
101
+
102
+ // Get the linked posts
103
+ $related_posts = $pl_manager->get_children( $id );
104
+
105
+ // Count
106
+ if ( count( $related_posts ) > 0 ) {
107
+ // Create Post List
108
+ $content .= $this->create_post_list( $related_posts, true, true );
109
+ }
110
+
111
+ return $content;
112
+ }
113
+ }
classes/filters/class-filter.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * @param mixed $tag (default: null)
18
+ *
19
+ * @return void
20
+ */
21
+ public function __construct() {
22
+ $this->register();
23
+ }
24
+
25
+ /**
26
+ * Register the hook.
27
+ *
28
+ * @access public
29
+ * @return void
30
+ */
31
+ public function register() {
32
+ // Tag must be set
33
+ if ( $this->tag === null ) {
34
+ trigger_error( 'ERROR IN FILTER: NO TAG SET', E_USER_ERROR );
35
+ }
36
+
37
+ add_filter( $this->tag, array( $this, 'run' ), $this->priority, $this->args );
38
+ }
39
+
40
+ }
classes/hooks/class-hook-admin-scripts.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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.js', RP4WP::get_plugin_file() ),
20
+ array( 'jquery', 'jquery-ui-sortable' )
21
+ );
22
+
23
+ // Make PL JavaScript strings translatable
24
+ // @todo add JS translation
25
+ //wp_localize_script( 'rp4wp_edit_post_js', 'rp4wp_js', RP4WP_Javascript_Strings::get() );
26
+
27
+ // CSS
28
+ wp_enqueue_style(
29
+ 'rp4wp_edit_post_css',
30
+ plugins_url( '/assets/css/edit-post.css', RP4WP::get_plugin_file() )
31
+ );
32
+ }
33
+
34
+ }
35
+ }
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
+ }
classes/hooks/class-hook-ajax-install-link-posts.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 rel amount
13
+ $rel_amount = isset( $_POST['rel_amount'] ) ? $_POST['rel_amount'] : 5;
14
+
15
+ // Related Post Manager object
16
+ $related_post_manager = new RP4WP_Related_Post_Manager();
17
+
18
+ // Link 200 posts
19
+ if ( true === $related_post_manager->link_related_posts( $rel_amount, 5 ) ) {
20
+
21
+ // Check if we're done
22
+ if ( 0 == count( $related_post_manager->get_not_auto_linked_posts( 1 ) ) ) {
23
+ echo 'done';
24
+ } else {
25
+ echo 'more';
26
+ }
27
+
28
+ }
29
+
30
+ exit;
31
+ }
32
+
33
+ }
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
+ // Related Post Manager
13
+ $related_word_manager = new RP4WP_Related_Word_Manager();
14
+
15
+ // Save 200 words
16
+ if ( true === $related_word_manager->save_all_words( 200 ) ) {
17
+
18
+ // Check if we're done
19
+ if ( 0 == count( $related_word_manager->get_uncached_posts( 1 ) ) ) {
20
+ echo 'done';
21
+ } else {
22
+ echo 'more';
23
+ }
24
+
25
+ }
26
+
27
+ exit;
28
+ }
29
+
30
+ }
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
+ }
classes/hooks/class-hook-frontend-css.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ echo "<style type='text/css'>.rp4wp-related-posts ul {padding:0;margin:0;float:left;}.rp4wp-related-posts li{list-style:none;}.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;}.rp4wp-related-post-content{width: 65%;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;float:left;}</style>" . PHP_EOL;
12
+
13
+ }
14
+ }
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
+ }
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
+ }
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
+ }
classes/hooks/class-hook-page-install.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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, 'SRPInstallation', 'SRPInstallation', 'edit_posts', 'rp4wp_install', array( $this, 'content' ) );
13
+
14
+ add_action( 'load-' . $menu_hook, array( $this, 'enqueue_install_assets' ) );
15
+ }
16
+
17
+ public function enqueue_install_assets() {
18
+ global $wp_scripts;
19
+ wp_enqueue_style( 'rp4wp-install-css', plugins_url( '/assets/css/install.css', RP4WP::get_plugin_file() ) );
20
+ wp_enqueue_script( 'rp4wp-install-js', plugins_url( '/assets/js/install.js', RP4WP::get_plugin_file() ), array( 'jquery', 'jquery-ui-core', 'jquery-ui-progressbar' ) );
21
+ 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 );
22
+ }
23
+
24
+ /**
25
+ * The screen content
26
+ */
27
+ public function content() {
28
+
29
+ $steps = array(
30
+ 1 => 'Caching Posts',
31
+ 2 => 'Linking Posts',
32
+ 3 => 'Finished',
33
+ );
34
+
35
+ $cur_step = isset( $_GET['step'] ) ? $_GET['step'] : 1;
36
+
37
+ ?>
38
+ <div class="wrap">
39
+ <h2><?php _e( 'Related Posts for WordPress Installation', 'related-posts-for-wp' ); ?></h2>
40
+
41
+ <ul class="install-steps">
42
+ <?php
43
+
44
+ foreach ( $steps as $step => $label ) {
45
+ echo "<li id='step-bar-" . $step . "'" . ( ( $cur_step == $step ) ? " class='step-bar-active'" : "" ) . ">" . $label . "</li>" . PHP_EOL;
46
+ }
47
+ ?>
48
+ </ul>
49
+ <br class="clear" />
50
+
51
+ <h3><?php echo $steps[$cur_step]; ?></h3>
52
+
53
+ <?php
54
+ $cur_step = isset( $_GET['step'] ) ? $_GET['step'] : 1;
55
+ echo "<div class='rp4wp-step rp4wp-step-" . $cur_step . "' rel='" . $cur_step . "'>";
56
+
57
+ echo "<input type='hidden' id='rp4wp_total_posts' value='" . wp_count_posts( 'post' )->publish . "' />" . PHP_EOL;
58
+ echo "<input type='hidden' id='rp4wp_admin_url' value='" . admin_url() . "' />" . PHP_EOL;
59
+
60
+ if ( 1 == $cur_step ) {
61
+ ?>
62
+ <p>Thank you for choosing Related Posts for WordPress!<br /><br />Before you can start using Related Posts for WordPress we need to cache your current posts.<br />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.
63
+ </p>
64
+
65
+ <p style="font-weight: bold;">Do NOT close this window, wait for this process to finish and this wizard to take you to the next step.</p>
66
+
67
+ <div id="progressbar"></div>
68
+ <?php
69
+ } elseif ( 2 == $cur_step ) {
70
+ ?>
71
+ <p style="font-weight: bold;">Great! All your posts were succesfully cached!</p>
72
+ <p>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!</p>
73
+ <p>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".</p>
74
+ <p style="font-weight: bold;">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.</p>
75
+ <br class="clear" />
76
+ <p class="rp4wp-install-link-box">
77
+ <label for="rp4wp_related_posts_amount">Amount of related posts per post:</label><input class="form-input-tip" type="text" id="rp4wp_related_posts_amount" value="5" />
78
+ <a href="javascript:;" class="button button-primary button-large rp4wp-link-now-btn" id="rp4wp-link-now">Link now</a>
79
+ <a href="<?php echo admin_url(); ?>?page=rp4wp_install&step=3" class="button">Skip linking</a>
80
+ </p>
81
+ <br class="clear" />
82
+ <div id="progressbar"></div>
83
+ <?php
84
+ } elseif ( 3 == $cur_step ) {
85
+ ?>
86
+ <p>That's it, you're good to go!</p>
87
+ <p>Thanks again for using Related Posts for WordPress and if you have any questions be sure to ask them at the
88
+ <a href="http://wordpress.org/support/plugin/related-posts-for-wp">WordPress.org forums.</a></p>
89
+ <?php
90
+ }
91
+ ?>
92
+ </div>
93
+
94
+ </div>
95
+
96
+ <?php
97
+ }
98
+
99
+ }
classes/hooks/class-hook-post-type.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class RP4WP_Hook_Post_Type extends RP4WP_Hook {
4
+ protected $tag = 'init';
5
+
6
+ public function run() {
7
+ register_post_type( RP4WP_Constants::LINK_PT, array( 'public' => false, 'label' => 'Related Posts for WordPress Link' ) );
8
+ }
9
+ }
classes/hooks/class-hook-related-save-words.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ // Save Words
29
+ $related_word_manager = new RP4WP_Related_Word_Manager();
30
+ $related_word_manager->save_words_of_post( $post_id );
31
+
32
+ }
33
+ }
classes/hooks/class-hook.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ abstract class RP4WP_Hook {
6
+ protected $tag = null;
7
+ protected $priority = 10;
8
+ protected $args = 1;
9
+
10
+ /**
11
+ * Construct method. Set tag and register hook.
12
+ *
13
+ * @access public
14
+ *
15
+ * @param mixed $tag (default: null)
16
+ *
17
+ * @return void
18
+ */
19
+ public function __construct() {
20
+ $this->register();
21
+ }
22
+
23
+ /**
24
+ * Register the hook.
25
+ *
26
+ * @access public
27
+ * @return void
28
+ */
29
+ public function register() {
30
+ // Tag must be set
31
+ if ( $this->tag === null ) {
32
+ trigger_error( 'ERROR IN HOOK: NO TAG SET', E_USER_ERROR );
33
+ }
34
+
35
+ add_action( $this->tag, array( $this, 'run' ), $this->priority, $this->args );
36
+ }
37
+
38
+ }
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 this item', '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='" . __( 'Delete this item', 'related-posts-for-wp' ) . "' href='javascript:;'>";
102
+ _e( 'Delete 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
+ }
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',);
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', );
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',);
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',);
ignored-words/nl_NL.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ 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',);
readme.txt ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === Related Posts for WordPress ===
2
+ Contributors: barrykooij
3
+ Donate link: http://www.barrykooij.com/
4
+ Tags: related posts for wordpress, related posts for wp, simple related posts, easy related posts, related posts, related, relations, internal links, seo
5
+ Requires at least: 3.6
6
+ Tested up to: 3.9.2
7
+ Stable tag: 1.0.0
8
+ License: GPLv2 or later
9
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
+
11
+ Related Posts for WordPress, related posts that perform!
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 your done.
29
+
30
+ = WPML compatible =
31
+ We love love WPML, that's why we made Related Posts for WordPress fully compatible with WMPL. You can automatically and manually link related posts in their own language.
32
+
33
+
34
+ **More information**
35
+
36
+ - Other [WordPress plugins](http://profiles.wordpress.org/barrykooij/) by [Barry Kooij](http://www.barrykooij.com/)
37
+ - Contact Barry on Twitter: [@CageNL](http://twitter.com/CageNL)
38
+ - 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)
39
+
40
+
41
+ == Installation ==
42
+
43
+ = Installing the plugin =
44
+ 1. In your WordPress admin panel, go to *Plugins > New Plugin*, search for *Related Posts for WordPress* and click "Install now"
45
+ 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/`.
46
+ 1. Activate the plugin
47
+
48
+ == Frequently Asked Questions ==
49
+
50
+ = Where's the settings screen? =
51
+ Nowhere, there's no settings screen.
52
+
53
+ = Is there any way to custom CSS ? =
54
+ Not yet via the plugin, this will be added in future versions. Elements do have classes so you can style them in your own/theme CSS.
55
+
56
+ = Is there a theme function so I can output this list anywhere in my theme I want? =
57
+ Not yet, we're working on this and this will be added soon!
58
+
59
+ = Does the plugin uses it's own database table ? =
60
+ 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.
61
+
62
+ == Screenshots ==
63
+ 1. After activating Related Posts for WordPress, our wizard will automatically start. The first step is indexing and caching your posts.
64
+ 2. The second step of the wizard is linking related posts for your existing content! You can of course also skip this step.
65
+ 3. That's it! With one click you are good to go!
66
+ 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).
67
+ 5. Related posts are automatically added below your posts!
68
+
69
+ == Changelog ==
70
+
71
+ = 1.0.0 - August 7, 2014 =
72
+ * Initial version
related-posts-for-wp.php ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ Plugin Name: Related Posts for WordPress
5
+ Plugin URI: http://www.barrykooij.com/
6
+ Description: Related Posts for WordPress, related posts that perform!
7
+ Version: 1.0.0
8
+ Author: Barry Kooij
9
+ Author URI: http://www.barrykooij.com/
10
+ License: GPL v3
11
+
12
+ This program is free software: you can redistribute it and/or modify
13
+ it under the terms of the GNU General Public License as published by
14
+ the Free Software Foundation, either version 3 of the License, or
15
+ (at your option) any later version.
16
+
17
+ This program is distributed in the hope that it will be useful,
18
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
+ GNU General Public License for more details.
21
+
22
+ You should have received a copy of the GNU General Public License
23
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
24
+ */
25
+
26
+ class RP4WP {
27
+
28
+ /**
29
+ * Get the plugin file
30
+ *
31
+ * @access public
32
+ * @static
33
+ * @return String
34
+ */
35
+ public static function get_plugin_file() {
36
+ return __FILE__;
37
+ }
38
+
39
+ /**
40
+ * A static method that will setup the autoloader
41
+ */
42
+ private static function setup_autoloader() {
43
+ require_once( plugin_dir_path( self::get_plugin_file() ) . '/classes/class-autoloader.php' );
44
+ $autoloader = new RP4WP_Autoloader( plugin_dir_path( self::get_plugin_file() ) . 'classes/' );
45
+ spl_autoload_register( array( $autoloader, 'load' ) );
46
+ }
47
+
48
+ /**
49
+ * This method runs on plugin activation
50
+ */
51
+ public static function activation() {
52
+
53
+ // Setup autoloader
54
+ self::setup_autoloader();
55
+
56
+ // Run the installer
57
+ $installer = new RP4WP_Installer();
58
+ $installer->install();
59
+
60
+ // Redirect to installation wizard
61
+ add_site_option( RP4WP_Constants::OPTION_DO_INSTALL, true );
62
+ }
63
+
64
+ /**
65
+ * The constructor
66
+ */
67
+ public function __construct() {
68
+ $this->init();
69
+ }
70
+
71
+ /**
72
+ * Initialize the plugin
73
+ */
74
+ private function init() {
75
+
76
+ // Setup the autolaoder
77
+ self::setup_autoloader();
78
+
79
+ // Check if we need to run the installer
80
+ if ( get_site_option( RP4WP_Constants::OPTION_DO_INSTALL, false ) ) {
81
+
82
+ // Delete site option
83
+ delete_site_option( RP4WP_Constants::OPTION_DO_INSTALL );
84
+
85
+ // Redirect to installation wizard
86
+ wp_redirect( admin_url() . '?page=rp4wp_install', 301 );
87
+ exit;
88
+ }
89
+
90
+ // Filters
91
+ $manager_filter = new RP4WP_Manager_Filter( plugin_dir_path( __FILE__ ) . 'classes/filters/' );
92
+ $manager_filter->load_filters();
93
+
94
+ // Hooks
95
+ $manager_hook = new RP4WP_Manager_Hook( plugin_dir_path( __FILE__ ) . 'classes/hooks/' );
96
+ $manager_hook->load_hooks();
97
+ }
98
+
99
+ }
100
+
101
+ function __rp4wp_main() {
102
+ new RP4WP();
103
+ }
104
+
105
+ // Create object - Plugin init
106
+ add_action( 'plugins_loaded', '__rp4wp_main' );
107
+
108
+ // Activation hook
109
+ register_activation_hook( __FILE__, array( 'RP4WP', 'activation' ) );