/**
  * the_content filter that will add linked posts to the bottom of the main post content
  *
  * @param $content
  *
  * @return string
  */
 public function run($content)
 {
     /**
      * Wow, what's going on here?! Well, setup_postdata() sets a lot of variables but does not change the $post variable.
      * All checks return the main queried ID but we want to check if this specific filter call is the for the 'main' content.
      * The method setup_postdata() does global and set the $id variable, so we're checking that.
      */
     global $id;
     // Only run on single
     if (!is_singular() || !is_main_query() || $id != get_queried_object_id()) {
         return $content;
     }
     // Allow disabling content filter
     if (false === apply_filters('rp4wp_append_content', true)) {
         return $content;
     }
     // The Post Type
     $post_type = get_post_type($id);
     // The Post Type Manager
     $pt_manager = new RP4WP_Post_Type_Manager();
     // Check if this Post Type is installed
     if ($pt_manager->is_post_type_installed($post_type) && isset(RP4WP()->settings['general_' . $post_type])) {
         // Related Post Manager
         $related_post_manager = new RP4WP_Related_Post_Manager();
         // The Output
         $output = $related_post_manager->generate_related_posts_list($id);
         // Add output if there is any
         if ('' != $output) {
             $content .= $output;
         }
     }
     // Return the content
     return $content;
 }
 public function run($new_status, $old_status, $post)
 {
     // verify this is not an auto save routine.
     if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
         return;
     }
     // Only count on post type 'post'
     if ('post' != $post->post_type) {
         return;
     }
     // Post status must be publish
     if ('publish' != $new_status) {
         return;
     }
     // Is automatic linking enabled?
     if (1 != RP4WP::get()->settings->get_option('automatic_linking')) {
         return;
     }
     // Check if the current post is already auto linked
     if (1 != get_post_meta($post->ID, RP4WP_Constants::PM_POST_AUTO_LINKED, true)) {
         // Get automatic linking post amount
         $automatic_linking_post_amount = RP4WP::get()->settings->get_option('automatic_linking_post_amount');
         // Related Posts Manager
         $related_post_manager = new RP4WP_Related_Post_Manager();
         // Link related posts
         $related_post_manager->link_related_post($post->ID, $automatic_linking_post_amount);
         // Set the auto linked meta
         update_post_meta($post->ID, RP4WP_Constants::PM_POST_AUTO_LINKED, 1);
     }
 }
 /**
  * Hook into admin AJAX to delete a link
  *
  * @access public
  * @return void
  */
 public function run()
 {
     // Check nonce
     check_ajax_referer(RP4WP_Constants::NONCE_AJAX, 'nonce');
     try {
         // Parent
         if (!isset($_POST['parent'])) {
             throw new Exception('Parent not set');
         }
         // Parent and post types
         $parent = sanitize_text_field($_POST['parent']);
         // Check if user is allowed to do this
         if (!current_user_can('edit_posts')) {
             return;
         }
         // Related post manager
         $related_post_manager = new RP4WP_Related_Post_Manager();
         // Remove linked related posts
         $related_post_manager->remove_linked_posts($parent);
         // Let's go0oo
         $redirect = true;
         // Success response
         $response = array('result' => 'success', 'redirect' => $redirect);
     } catch (Exception $e) {
         // Failure response
         $response = array('result' => 'failure', 'redirect' => false, 'error' => $e->getMessage());
     }
     // Send response
     wp_send_json($response);
 }
 public function run()
 {
     // Check nonce
     check_ajax_referer(RP4WP_Constants::NONCE_AJAX, 'nonce');
     // Get the PPR
     $ppr = isset($_POST['ppr']) ? $_POST['ppr'] : 5;
     // Get the rel amount
     $rel_amount = isset($_POST['rel_amount']) ? $_POST['rel_amount'] : 3;
     // Related Post Manager object
     $related_post_manager = new RP4WP_Related_Post_Manager();
     // Link posts
     $related_post_manager->link_related_posts($rel_amount, $ppr);
     // Get uncached post count
     $unlinked_post_count = $related_post_manager->get_unlinked_post_count();
     // Check if we're done
     if (0 == $unlinked_post_count) {
         // Save the wizard setting as the option
         $options = RP4WP()->settings->get_options();
         $options['automatic_linking_post_amount'] = $rel_amount;
         update_option('rp4wp', $options);
     }
     // Echo the uncached posts
     echo $unlinked_post_count;
     exit;
 }
 public function run()
 {
     // Check nonce
     check_ajax_referer(RP4WP_Constants::NONCE_AJAX, 'nonce');
     // Get the PPR
     $ppr = isset($_POST['ppr']) ? $_POST['ppr'] : 5;
     // Get the Post Type
     $post_type = isset($_POST['pt']) ? $_POST['pt'] : null;
     // Check if Post Type is set
     if (null == $post_type) {
         echo 'No Post Type set!';
     }
     // the rel amount
     $rel_amount = 3;
     if (isset(RP4WP::get()->settings['general_' . $post_type])) {
         // set the correct options from step 3
         $rel_amount = RP4WP::get()->settings['general_' . $post_type]->get_option('automatic_linking_post_amount');
     }
     // Related Post Manager object
     $related_post_manager = new RP4WP_Related_Post_Manager();
     // Link posts
     $related_post_manager->link_related_posts($rel_amount, $post_type, $ppr);
     // Get unlinked post count
     $unlinked_post_count = $related_post_manager->get_unlinked_post_count($post_type);
     // Echo the uncached posts
     echo $unlinked_post_count;
     exit;
 }
 /**
  * Hook into admin AJAX to delete a link
  *
  * @todo write method
  *
  * @access public
  * @return void
  */
 public function run()
 {
     // Check nonce
     check_ajax_referer(RP4WP_Constants::NONCE_AJAX, 'nonce');
     try {
         // Parent
         if (!isset($_POST['parent'])) {
             throw new Exception('Parent not set');
         }
         // Parent and post types
         $parent = sanitize_text_field($_POST['parent']);
         // Check if user is allowed to do this
         if (!current_user_can('edit_posts')) {
             return;
         }
         // Related post manager
         $related_post_manager = new RP4WP_Related_Post_Manager();
         // Remove linked related posts
         $related_post_manager->remove_linked_posts($parent);
         // Add the post types
         $ptm = new RP4WP_Post_Type_Manager();
         // get children of parent
         $children = $ptm->get_installed_post_type($parent);
         // Related word manager
         $word_manager = new RP4WP_Related_Word_Manager();
         // always delete parent words
         $word_manager->delete_words_by_post_type($parent);
         // check if there are children
         if (count($children) > 0) {
             // loop
             foreach ($children as $child) {
                 // delete children words
                 $word_manager->delete_words_by_post_type($child);
             }
         }
         // Redirect to setup reinstall
         $redirect = true;
         // Success response
         $response = array('result' => 'success', 'redirect' => $redirect);
     } catch (Exception $e) {
         // Failure response
         $response = array('result' => 'failure', 'redirect' => false, 'error' => $e->getMessage());
     }
     // Send response
     wp_send_json($response);
 }
 public function run($new_status, $old_status, $post)
 {
     // verify this is not an auto save routine.
     if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
         return;
     }
     // Post status must be publish
     if ('publish' != $new_status) {
         return;
     }
     // Check if this post type is installed
     $pt_manager = new RP4WP_Post_Type_Manager();
     if (!$pt_manager->is_post_type_installed($post->post_type)) {
         return;
     }
     // Is automatic linking enabled?
     if (1 != RP4WP::get()->settings['general_' . $post->post_type]->get_option('automatic_linking')) {
         return;
     }
     // Check if the current post is already auto linked
     if (1 != get_post_meta($post->ID, RP4WP_Constants::PM_POST_AUTO_LINKED, true)) {
         // Post Link Manager
         $pl_manager = new RP4WP_Post_Link_Manager();
         // Get automatic linking post amount
         $automatic_linking_post_amount = RP4WP::get()->settings['general_' . $post->post_type]->get_option('automatic_linking_post_amount');
         // Count already linked posts
         $already_linked_posts = $pl_manager->get_children_count($post->ID);
         // Subtract already linked post count from posts to link amount
         if (count($already_linked_posts) > 0) {
             $automatic_linking_post_amount = $automatic_linking_post_amount - $already_linked_posts;
         }
         // Related Posts Manager
         $related_post_manager = new RP4WP_Related_Post_Manager();
         // Link related posts
         $related_post_manager->link_related_post($post->ID, $post->post_type, $automatic_linking_post_amount);
         // Set the auto linked meta
         update_post_meta($post->ID, RP4WP_Constants::PM_POST_AUTO_LINKED, 1);
     }
 }
 /**
  * Generate the Related Posts for WordPress children list
  *
  * @param bool $id
  * @param bool $output
  * @param string $template
  * @param int $limit
  *
  * @since  1.0.0
  * @access public
  *
  * @return string
  */
 function rp4wp_children($id = false, $output = true, $template = 'related-posts-default.php', $limit = -1)
 {
     // Get the current ID if ID not set
     if (false === $id) {
         $id = get_the_ID();
     }
     // Get the post type
     $post_type = get_post_type($id);
     // Check if this Post Type is installed
     $pt_manager = new RP4WP_Post_Type_Manager();
     if ($pt_manager->is_post_type_installed($post_type) && isset(RP4WP()->settings['general_' . $post_type])) {
         // related Post Manager
         $related_post_manager = new RP4WP_Related_Post_Manager();
         // the Output
         $content = $related_post_manager->generate_related_posts_list($id, $template, $limit);
         // Output or return the content
         if ($output) {
             echo $content;
         } else {
             return $content;
         }
     }
 }
    /**
     * The screen content
     *
     * @since  1.0.0
     * @access public
     */
    public function content()
    {
        // Do we have a reinstall?
        if (isset($_GET['reinstall'])) {
            // Check nonce
            if (!wp_verify_nonce(isset($_GET['rp4wp_nonce']) ? $_GET['rp4wp_nonce'] : '', RP4WP_Constants::NONCE_REINSTALL)) {
                wp_die('Woah! It looks like something else tried to run the Related Posts for WordPress installation wizard! We were able to stop them, nothing was lost. Please report this incident at <a href="http://wordpress.org/support/plugin/related-posts-for-wp" target="_blank">our forums.</a>');
            }
            global $wpdb;
            // Get ID's of related post link posts
            $link_ids = get_posts(array('post_type' => RP4WP_Constants::LINK_PT, 'fields' => 'ids', 'posts_per_page' => -1));
            // Only run queries if we have ID's
            if (count($link_ids) > 0) {
                // Delete all link posts
                $wpdb->query("DELETE FROM {$wpdb->posts} WHERE `ID` IN (" . implode(",", $link_ids) . ");");
                // Delete all link post meta
                $wpdb->query("DELETE FROM {$wpdb->postmeta} WHERE `post_id` IN (" . implode(",", $link_ids) . ");");
            }
            // Remove the post meta we attached to posts
            $wpdb->query("DELETE FROM {$wpdb->postmeta} WHERE `meta_key` = 'rp4wp_auto_linked' OR `meta_key` = 'rp4wp_cached' ");
            // Empty word cache
            $wpdb->query("DELETE FROM " . RP4WP_Related_Word_Manager::get_database_table() . " WHERE 1=1");
        }
        // The steps
        $steps = array(1 => __('Caching Posts', 'related-posts-for-wp'), 2 => __('Linking Posts', 'related-posts-for-wp'), 3 => __('Finished', 'related-posts-for-wp'));
        // What's the current step?
        $cur_step = isset($_GET['step']) ? $_GET['step'] : 1;
        // Check installer resume options
        if (1 == $cur_step) {
            // Add is installing site option
            add_site_option(RP4WP_Constants::OPTION_IS_INSTALLING, true);
        } elseif (3 == $cur_step) {
            // Installer is done, remove the option
            delete_site_option(RP4WP_Constants::OPTION_IS_INSTALLING);
        }
        ?>
		<div class="wrap">
			<h2>Related Posts for WordPress <?php 
        _e('Installation', 'related-posts-for-wp');
        ?>
</h2>

			<ul class="install-steps">
				<?php 
        foreach ($steps as $step => $label) {
            echo "<li id='step-bar-" . $step . "'" . ($cur_step == $step ? " class='step-bar-active'" : "") . "><span>" . $step . '. ' . $label . "</span></li>" . PHP_EOL;
        }
        ?>
			</ul>
			<br class="clear" />

			<h3><?php 
        echo $steps[$cur_step];
        ?>
</h3>

			<?php 
        $cur_step = isset($_GET['step']) ? $_GET['step'] : 1;
        echo "<div class='rp4wp-step rp4wp-step-" . $cur_step . "' rel='" . $cur_step . "'>";
        echo "<input type='hidden' id='rp4wp_total_posts' value='" . wp_count_posts('post')->publish . "' />" . PHP_EOL;
        echo "<input type='hidden' id='rp4wp_admin_url' value='" . admin_url() . "' />" . PHP_EOL;
        if (1 == $cur_step) {
            // Echo current uncached posts
            $related_word_manager = new RP4WP_Related_Word_Manager();
            echo "<input type='hidden' id='rp4wp_uncached_posts' value='" . $related_word_manager->get_uncached_post_count() . "' />" . PHP_EOL;
            ?>
				<p><?php 
            _e('Thank you for choosing Related Posts for WordPress!', 'related-posts-for-wp');
            ?>
</p>
				<p><?php 
            _e('Before you can start using Related Posts for WordPress we need to cache your current posts.', 'related-posts-for-wp');
            ?>
</p>
				<p><?php 
            _e("This is a one time process which might take some time now, depending on the amount of posts you have, but will ensure your website's performance when using the plugin.", 'related-posts-for-wp');
            ?>
</p>

				<p style="font-weight: bold;"><?php 
            _e('Do NOT close this window, wait for this process to finish and this wizard to take you to the next step.', 'related-posts-for-wp');
            ?>
</p>

				<div id="progressbar"></div>
			<?php 
        } elseif (2 == $cur_step) {
            // Echo current uncached posts
            $related_post_manager = new RP4WP_Related_Post_Manager();
            echo "<input type='hidden' id='rp4wp_uncached_posts' value='" . $related_post_manager->get_uncached_post_count() . "' />" . PHP_EOL;
            ?>
				<p style="font-weight: bold;"><?php 
            _e('Great! All your posts were successfully cached!', 'related-posts-for-wp');
            ?>
</p>
				<p><?php 
            _e("You can let me link your posts, based on what I think is related, to each other. And don't worry, if I made a mistake at one of your posts you can easily correct this by editing it manually!", 'related-posts-for-wp');
            ?>
</p>
				<p><?php 
            _e('Want me to start linking posts to each other? Fill in the amount of related posts each post should have and click on the "Link now" button. Rather link your posts manually? Click "Skip linking".', 'related-posts-for-wp');
            ?>
</p>
				<p style="font-weight: bold;"><?php 
            _e('Do NOT close this window if you click the "Link now" button, wait for this process to finish and this wizard to take you to the next step.', 'related-posts-for-wp');
            ?>
</p>
				<br class="clear" />
				<p class="rp4wp-install-link-box">
					<label for="rp4wp_related_posts_amount"><?php 
            _e('Amount of related posts per post:', 'related-posts-for-wp');
            ?>
</label><input class="form-input-tip" type="text" id="rp4wp_related_posts_amount" value="<?php 
            echo RP4WP()->settings->get_option('automatic_linking_post_amount');
            ?>
" />
					<a href="javascript:;" class="button button-primary button-large rp4wp-link-now-btn" id="rp4wp-link-now"><?php 
            _e('Link now', 'related-posts-for-wp');
            ?>
</a>
					<a href="<?php 
            echo admin_url();
            ?>
?page=rp4wp_install&step=3" class="button"><?php 
            _e('Skip linking', 'related-posts-for-wp');
            ?>
</a>
				</p>
				<br class="clear" />
				<div id="progressbar"></div>
			<?php 
        } elseif (3 == $cur_step) {
            ?>
				<p><?php 
            _e("That's it, you're good to go!", 'related-posts-for-wp');
            ?>
</p>
				<p><?php 
            printf(__('Thanks again for using Related Posts for WordPress and if you have any questions be sure to ask them at the %sWordPress.org forums.%s', 'related-posts-for-wp'), '<a href="http://wordpress.org/support/plugin/related-posts-for-wp" target="_blank">', '</a>');
            ?>
</p>
			<?php 
        }
        ?>
		</div>

		</div>

	<?php 
    }
 /**
  * Prepare the items
  */
 public function prepare_items()
 {
     // Get current view
     $view = $this->get_current_view();
     // Check if we're in the related view
     if ('related' == $view) {
         $this->is_related = true;
     }
     // Set table properties
     $columns = $this->get_columns();
     $hidden = array();
     $sortable = $this->get_sortable_columns();
     $this->_column_headers = array($columns, $hidden, $sortable);
     // pagination and sorting
     $screen = get_current_screen();
     $per_page = absint(get_user_meta(get_current_user_id(), $screen->get_option('per_page', 'option'), true));
     $per_page = $per_page > 0 ? $per_page : 20;
     $paged = absint(isset($_GET['paged']) ? $_GET['paged'] : 1);
     $orderby = isset($_GET['orderby']) ? $_GET['orderby'] : 'title';
     $order = isset($_GET['order']) ? $_GET['order'] : 'asc';
     // views
     $this->views();
     // Set search
     if (null !== $this->search) {
         add_filter('posts_where', array($this, 'filter_posts_where'));
     }
     // Get Data
     $this->data = array();
     // Get posts
     if ('all' == $view) {
         // Post Type Manager
         $pt_manager = new RP4WP_Post_Type_Manager();
         // Get linked posts
         $linked_post_types = $pt_manager->get_installed_post_type($this->post_type);
         // posts
         $posts = array();
         // the posts query
         $post_query = new WP_Query(array('post_type' => $linked_post_types, 'posts_per_page' => $per_page, 'paged' => $paged, 'suppress_filters' => false, 'orderby' => $orderby, 'order' => $order, 'post_status' => apply_filters('rp4wp_manual_link_post_statuses', array('publish', 'private'))));
         // Format data for table
         if ($post_query->have_posts()) {
             while ($post_query->have_posts()) {
                 $posts[] = $post_query->next_post();
             }
         }
     } else {
         $rpm = new RP4WP_Related_Post_Manager();
         $parent = intval($_GET['rp4wp_parent']);
         $posts = $rpm->get_related_posts($parent, $this->post_type, 25);
     }
     // Format data for table
     if (count($posts) > 0) {
         foreach ($posts as $post) {
             // Related results only contain ID to keep query fast. Rather have an extra query per post on manual linking than a much heavier query for all linking.
             if (!isset($post->post_title)) {
                 $post = get_post($post->ID);
             }
             $this->data[] = array('ID' => $post->ID, 'title' => $post->post_title, 'post_type' => $post->post_type);
         }
     }
     // Remove search filter
     remove_filter('posts_where', array($this, 'filter_posts_where'));
     // Pagination only for all view
     if ('all' == $view) {
         $this->set_pagination_args(array('total_items' => $post_query->found_posts, 'per_page' => $per_page));
     }
     // Set items
     $this->items = $this->data;
 }
    /**
     * The screen content
     *
     * @since  1.0.0
     * @access public
     */
    public function content()
    {
        // Check nonce
        $installer_nonce = isset($_GET['rp4wp_nonce']) ? $_GET['rp4wp_nonce'] : '';
        if (!wp_verify_nonce($installer_nonce, RP4WP_Constants::NONCE_INSTALL)) {
            wp_die('Woah! It looks like something else tried to run the Related Posts for WordPress installation wizard! We were able to stop them, nothing was lost. Please report this incident at <a href="http://wordpress.org/support/plugin/related-posts-for-wp" target="_blank">our forums.</a>');
        }
        // The steps
        $steps = array(1 => __('Welcome', 'related-posts-for-wp'), 2 => __('Caching Posts', 'related-posts-for-wp'), 3 => __('Linking Posts', 'related-posts-for-wp'), 4 => __('Finished', 'related-posts-for-wp'));
        // What's the current step?
        $cur_step = intval(isset($_GET['step']) ? $_GET['step'] : 1);
        // Set the post type in var
        $post_type = esc_html(isset($_GET['pt']) ? $_GET['pt'] : '');
        // Check if the post type is set
        if ($cur_step > 1 && empty($post_type)) {
            wp_die(sprintf(__('Missing post type parameter, please report this incident via %sour website%s.', 'related-posts-for-wp'), '<a href="https://www.relatedpostsforwp.com/support/" target="_blank">', '</a>'));
        }
        // Try to create the cache table if we're in step 1 and this is a multisite
        if (1 == $cur_step && is_multisite()) {
            require_once plugin_dir_path(RP4WP_PLUGIN_FILE) . 'includes/installer-functions.php';
            rp4wp_premium_create_db_table();
        }
        // Check installer resume options
        if (2 == $cur_step) {
            // Add is installing site option
            add_option(RP4WP_Constants::OPTION_IS_INSTALLING, $post_type);
            // Get current linked post type
            $linked_pt_cur = absint(isset($_GET['cur']) ? $_GET['cur'] : 0);
            // Get the available post types
            $ptm = new RP4WP_Post_Type_Manager();
            $linked_pt_count = count($ptm->get_installed_post_type($post_type));
        } elseif (4 == $cur_step) {
            // Installer is done, remove the option
            delete_option(RP4WP_Constants::OPTION_IS_INSTALLING);
        }
        ?>
		<div class="wrap">
			<h2>Related Posts for WordPress <?php 
        _e('Installation', 'related-posts-for-wp');
        ?>
</h2>

			<ul class="install-steps">
				<?php 
        foreach ($steps as $step => $label) {
            echo "<li id='step-bar-" . $step . "'" . ($cur_step == $step ? " class='step-bar-active'" : "") . "><span>" . $step . '. ' . $label . "</span></li>" . PHP_EOL;
        }
        ?>
			</ul>
			<br class="clear" />

			<h3><?php 
        echo $steps[$cur_step];
        ?>
</h3>

			<?php 
        echo "<div class='rp4wp-step rp4wp-step-" . $cur_step . "' rel='" . $cur_step . "'>";
        // Hidden fields
        echo "<input type='hidden' id='rp4wp_admin_url' value='" . admin_url() . "' />" . PHP_EOL;
        // Echo the post type & total posts when post type is set
        if (!empty($post_type)) {
            echo "<input type='hidden' id='rp4wp_post_type' value='" . $post_type . "' />" . PHP_EOL;
            echo "<input type='hidden' id='rp4wp_total_posts' value='" . wp_count_posts($post_type)->publish . "' />" . PHP_EOL;
        }
        // Echo the amount of linked post types
        if (isset($linked_pt_count)) {
            echo "<input type='hidden' id='linked_pt_count' value='" . $linked_pt_count . "' />" . PHP_EOL;
        }
        // Echo the current linked post type
        if (isset($linked_pt_cur)) {
            echo "<input type='hidden' id='linked_pt_cur' value='" . $linked_pt_cur . "' />" . PHP_EOL;
        }
        // Echo the nonce
        if (!empty($installer_nonce)) {
            echo "<input type='hidden' id='rp4wp_nonce' value='" . $installer_nonce . "' />" . PHP_EOL;
        }
        // AJAX nonce
        echo '<input type="hidden" name="rp4wp-ajax-nonce" id="rp4wp-ajax-nonce" value="' . wp_create_nonce(RP4WP_Constants::NONCE_AJAX) . '" />';
        switch ($cur_step) {
            case 1:
                ?>
				<p><?php 
                _e('Thank you for choosing Related Posts for WordPress!', 'related-posts-for-wp');
                ?>
</p>
				<p><?php 
                _e("Below you'll find your post types available for installation, by installing a post type we'll set up a cache and offer you the ability to automatic link (custom) posts. To install a post type, simply click the 'Install Post Type' button.", 'related-posts-for-wp');
                ?>
</p>
				<h3>Post Types</h3>
				<?php 
                // Get the available post types
                $ptm = new RP4WP_Post_Type_Manager();
                // Get installed post types
                $installed_post_types = $ptm->get_installed_post_types();
                // Available post types
                $available_post_types = $ptm->get_available_post_types();
                echo '<input type="hidden" id="rp4wp-availabe_post_types" value="' . implode(',', array_keys($available_post_types)) . '" />';
                echo '<table cellpadding="0" cellspacing="0" border="0" class="rp4wp-table-pt-overview">' . PHP_EOL;
                echo "<tr>" . PHP_EOL;
                echo "<th>" . __('Post Type', 'related-posts-for-wp') . "</th>" . PHP_EOL;
                echo "<th>" . __('Related to Post Types', 'related-posts-for-wp') . "</th>" . PHP_EOL;
                echo "<th>&nbsp;</th>" . PHP_EOL;
                echo "</tr>" . PHP_EOL;
                // Da loop
                if (count($available_post_types) > 0) {
                    foreach ($available_post_types as $pt_key => $pt_label) {
                        $is_active = false;
                        if (isset($installed_post_types[$pt_key]) && count($installed_post_types[$pt_key]) > 0) {
                            $is_active = true;
                        }
                        echo '<tr rel="' . $pt_key . '" ' . (!$is_active ? 'class="inactive"' : '') . '>';
                        echo '<td class="rp4wp-parent">' . $pt_label . '</td>' . PHP_EOL;
                        echo '<td class="rp4wp-children">';
                        echo '<ul>' . PHP_EOL;
                        if ($is_active) {
                            foreach ($installed_post_types[$pt_key] as $linked_pt) {
                                echo '<li id="' . $linked_pt . '"><span>' . $available_post_types[$linked_pt] . '</span></li>' . PHP_EOL;
                            }
                        }
                        echo '</ul>' . PHP_EOL;
                        echo '</td>' . PHP_EOL;
                        echo '<td class="rp4wp-button">';
                        echo '<div class="rp4wp-buttons-wrap">' . PHP_EOL;
                        echo '<a href="javascript:;" class="button button-primary rp4wp-btn-edit rp4wp-has-tip" title="' . __('Edit this post type', 'related-posts-for-wp') . '" rel="edit"></a>';
                        echo '</div>' . PHP_EOL;
                        echo '</td>' . PHP_EOL;
                        echo '</tr>';
                    }
                }
                echo '</table>' . PHP_EOL;
                break;
            case 2:
                // Echo current uncached posts
                $related_word_manager = new RP4WP_Related_Word_Manager();
                // amount of posts needs caching
                $posts_todo = $related_word_manager->get_uncached_post_count($post_type);
                echo "<input type='hidden' id='rp4wp_posts_todo' value='" . $posts_todo . "' />" . PHP_EOL;
                ?>
				<p><?php 
                _e('Thank you for choosing Related Posts for WordPress!', 'related-posts-for-wp');
                ?>
</p>
				<p><?php 
                _e('Before you can start using Related Posts for WordPress we need to cache your current posts.', 'related-posts-for-wp');
                ?>
</p>
				<p><?php 
                _e("This is a one time process which might take some time now, depending on the amount of posts you have, but will ensure your website's performance when using the plugin.", 'related-posts-for-wp');
                ?>
</p>

				<p style="font-weight: bold;"><?php 
                _e('Do NOT close this window, wait for this process to finish and this wizard to take you to the next step.', 'related-posts-for-wp');
                ?>
</p>

				<div id="progress-container">
					<div id="progressbar"></div>
					<p>Todo: <span id="progress-todo"><?php 
                echo $posts_todo;
                ?>
</span></p>
					<p>Done: <span id="progress-done">0</span></p>
				</div>

				<?php 
                break;
            case 3:
                // Echo current unlinked posts
                $related_post_manager = new RP4WP_Related_Post_Manager();
                // amount of posts need linking
                $posts_todo = $related_post_manager->get_unlinked_post_count($post_type);
                echo "<input type='hidden' id='rp4wp_posts_todo' value='" . $posts_todo . "' />" . PHP_EOL;
                // Get the automatic linking post amount
                $alpa = 3;
                if (isset(RP4WP()->settings['general_' . $post_type])) {
                    $alpa = RP4WP()->settings['general_' . $post_type]->get_option('automatic_linking_post_amount');
                }
                // get the post age
                // Get the automatic linking post amount
                $max_post_age = 0;
                if (isset(RP4WP()->settings['general_' . $post_type])) {
                    $max_post_age = RP4WP()->settings['general_' . $post_type]->get_option('max_post_age');
                }
                ?>
				<p style="font-weight: bold;"><?php 
                _e('Great! All your posts were successfully cached!', 'related-posts-for-wp');
                ?>
</p>
				<p><?php 
                _e("You can let me link your posts, based on what I think is related, to each other. And don't worry, if I made a mistake at one of your posts you can easily correct this by editing it manually!", 'related-posts-for-wp');
                ?>
</p>
				<p><?php 
                _e('Want me to start linking posts to each other? Fill in the amount of related posts each post should have and click on the "Link now" button. Rather link your posts manually? Click "Skip linking".', 'related-posts-for-wp');
                ?>
</p>
				<p style="font-weight: bold;"><?php 
                _e('Do NOT close this window if you click the "Link now" button, wait for this process to finish and this wizard to take you to the next step.', 'related-posts-for-wp');
                ?>
</p>
				<br class="clear"/>

				<div class="rp4wp-install-link-box">
					<table cellpadding="0" cellspacing="0" border="0">
						<tr>
							<td><label for="rp4wp_related_posts_amount"><?php 
                _e('Amount of related posts:', 'related-posts-for-wp');
                ?>
</label></td>
							<td><input class="form-input-tip" type="text" id="rp4wp_related_posts_amount" value="<?php 
                echo $alpa;
                ?>
" /></td>
							<td class="rp4pw-install-step3-table-desc"><?php 
                printf(__('The amount of related items per %s', 'related-posts-for-wp'), $post_type);
                ?>
</td>
						</tr>


						<tr>
							<td><label for="rp4wp_related_posts_age"><?php 
                _e('Maximum Post Age:', 'related-posts-for-wp');
                ?>
</label></td>
							<td><input class="form-input-tip" type="text" id="rp4wp_related_posts_age" value="<?php 
                echo $max_post_age;
                ?>
"/></td>
							<td class="rp4pw-install-step3-table-desc"><?php 
                printf(__('The maximum age in days of %s that will be linked. (0 = unlimited)', 'related-posts-for-wp'), $post_type);
                ?>
</td>
						</tr>

						<tr>
							<td>&nbsp;</td>
							<td colspan="2" class="rp4pw-install-step3-table-buttons">
								<a href="javascript:;" class="button button-primary button-large rp4wp-link-now-btn" id="rp4wp-link-now"><?php 
                _e('Link now', 'related-posts-for-wp');
                ?>
</a>
								<a href="<?php 
                echo admin_url(sprintf('?page=rp4wp_install&step=4&pt=%s&&rp4wp_nonce=%s', $post_type, wp_create_nonce(RP4WP_Constants::NONCE_INSTALL)));
                ?>
" class="button"><?php 
                _e('Skip linking', 'related-posts-for-wp');
                ?>
</a>
							</td>
						</tr>

					</table>
				</div>

				<br class="clear"/>

				<div id="progress-container">
					<div id="progressbar"></div>
					<p>Todo: <span id="progress-todo"><?php 
                echo $posts_todo;
                ?>
</span></p>
					<p>Done: <span id="progress-done">0</span></p>
				</div>
				<?php 
                break;
            case 4:
                ?>
				<p><?php 
                _e("That's it, you're good to go!", 'related-posts-for-wp');
                ?>
</p>
				<p><?php 
                printf(__('Thanks again for using Related Posts for WordPress and if you have any questions be sure to ask them at the %sWordPress.org forums.%s', 'related-posts-for-wp'), '<a href="http://wordpress.org/support/plugin/related-posts-for-wp" target="_blank">', '</a>');
                ?>
</p>
				<p>
					<a href="<?php 
                echo admin_url(sprintf('?page=rp4wp_install&rp4wp_nonce=%s', wp_create_nonce(RP4WP_Constants::NONCE_INSTALL)));
                ?>
"
					   class="button button-primary"><?php 
                _e('Click here to return to step 1', 'related-posts-for-wp');
                ?>
</a>
				</p>
				<p>
					<?php 
                $local_settings = (array) RP4WP()->settings;
                $first_setting = array_shift($local_settings);
                echo '<a href="' . admin_url('options-general.php?page=' . $first_setting->get_page()) . '" class="button button-primary">' . __('Click here to go to the settings page', 'related-posts-for-wp') . '</a>';
                ?>
				</p>
			<?php 
        }
        ?>
		</div>

		</div>

	<?php 
    }
 /**
  * Install a post type. This includes caching and linking post types.
  *
  * ## OPTIONS
  *
  * <post_type>
  * : The post type where related posts are linked to
  *
  * <linked_post_types>
  * : The post types (comma separated) which are linked to the first argument
  *
  * <rel_amount>
  * : The amount of related posts per post
  *
  * [<max_post_age>]
  * : The maximum age of a related post in days
  *
  * ## EXAMPLE
  *
  *     wp rp4wp remove_related post
  *
  * @synopsis <post_type> <linked_post_types> <rel_amount> [<max_post_age>]
  */
 public function install($args, $assoc_args)
 {
     // args
     $post_type = trim($args[0]);
     $linked_post_types = explode(',', trim($args[1]));
     $rel_amount = intval($args[2]);
     $max_post_age = intval(isset($args[3]) ? $args[3] : 0);
     // we need at least one linked post type to continue
     if (count($linked_post_types) > 0) {
         /**
          * SETTINGS
          */
         // set the linked post types
         $ptm = new RP4WP_Post_Type_Manager();
         $ptm->add_post_type($post_type, $linked_post_types);
         // set the post type options
         if (isset(RP4WP::get()->settings['general_' . $post_type])) {
             $options = RP4WP::get()->settings['general_' . $post_type]->get_options();
             $options['automatic_linking_post_amount'] = $rel_amount;
             $options['max_post_age'] = $max_post_age;
             update_option('rp4wp_general_' . $post_type, $options);
         }
         /**
          * CACHE POSTS
          */
         WP_CLI::line('Caching Words');
         // related word manage
         $related_word_manager = new RP4WP_Related_Word_Manager();
         // cache words of parent post type
         $related_word_manager->save_all_words($post_type);
         // cache words of linked post types
         foreach ($linked_post_types as $linked_post_type) {
             $related_word_manager->save_all_words($linked_post_type);
         }
         /**
          * LINK POSTS
          */
         WP_CLI::line('Linking Posts');
         $related_post_manager = new RP4WP_Related_Post_Manager();
         $related_post_manager->link_related_posts($rel_amount, $post_type);
         // output success
         WP_CLI::success(sprintf('Successfully installed %s', $post_type));
     }
 }
 /**
  * Hook into admin AJAX to delete a link
  *
  * @access public
  * @return void
  */
 public function run()
 {
     // Check nonce
     check_ajax_referer(RP4WP_Constants::NONCE_AJAX, 'nonce');
     try {
         // Parent
         if (!isset($_POST['parent'])) {
             throw new Exception('Parent not set');
         }
         // Parent and post types
         $parent = sanitize_text_field($_POST['parent']);
         $post_types = array_map('sanitize_text_field', isset($_POST['post_types']) ? $_POST['post_types'] : array());
         // Check if user is allowed to do this
         if (!current_user_can('edit_posts')) {
             return;
         }
         // Related post manager
         $related_post_manager = new RP4WP_Related_Post_Manager();
         // Remove linked related posts
         $related_post_manager->remove_linked_posts($parent);
         // Add the post types
         $ptm = new RP4WP_Post_Type_Manager();
         // Check if we're adding or removing
         if (count($post_types) > 0) {
             // Add the post type
             $ptm->add_post_type($parent, $post_types);
             // Let's go0oo
             $redirect = true;
         } else {
             // get children of parent
             $children = $ptm->get_installed_post_type($parent);
             // Remove post type
             $ptm->remove_post_type($parent);
             // Related word manager
             $word_manager = new RP4WP_Related_Word_Manager();
             // check if parent is used as child in any other relations
             if (false === $ptm->is_post_type_used($parent)) {
                 // delete word cache of parent
                 $word_manager->delete_words_by_post_type($parent);
             }
             // check if there are children
             if (count($children) > 0) {
                 // loop
                 foreach ($children as $child) {
                     // check if this child post type is used in any other relation
                     if (false === $ptm->is_post_type_used($child)) {
                         // delete words
                         $word_manager->delete_words_by_post_type($child);
                     }
                 }
             }
             // No redirect needed
             $redirect = false;
         }
         // Success response
         $response = array('result' => 'success', 'redirect' => $redirect);
     } catch (Exception $e) {
         // Failure response
         $response = array('result' => 'failure', 'redirect' => false, 'error' => $e->getMessage());
     }
     // Send response
     wp_send_json($response);
 }
 /**
  * Prepare the items
  */
 public function prepare_items()
 {
     // Get current view
     $view = $this->get_current_view();
     // Check if we're in the related view
     if ('related' == $view) {
         $this->is_related = true;
     }
     // Set table properties
     $columns = $this->get_columns();
     $hidden = array();
     $sortable = $this->get_sortable_columns();
     $this->_column_headers = array($columns, $hidden, $sortable);
     // Vies
     $this->views();
     // Set search
     if ($this->search !== null) {
         add_filter('posts_where', array($this, 'filter_posts_where'));
     }
     // Get Data
     $this->data = array();
     // Get posts
     if ('all' == $view) {
         $posts = get_posts(array('post_type' => 'post', 'posts_per_page' => '-1', 'suppress_filters' => false));
     } else {
         $rpm = new RP4WP_Related_Post_Manager();
         $parent = $_GET['rp4wp_parent'];
         $posts = $rpm->get_related_posts($parent);
     }
     // Format data for table
     if (count($posts) > 0) {
         foreach ($posts as $post) {
             $this->data[] = array('ID' => $post->ID, 'title' => $post->post_title);
         }
     }
     // Remove search filter
     remove_filter('posts_where', array($this, 'filter_posts_where'));
     // Sort
     if (!$this->is_related) {
         if (count($this->data) > 0) {
             usort($this->data, array($this, 'custom_reorder'));
         }
     }
     // Set items
     $this->items = $this->data;
 }
 /**
  * Dev test flow
  *
  * ## OPTIONS
  *
  * ## EXAMPLES
  *
  *     wp rp4wp-dev test
  */
 public function test($args, $assoc_args)
 {
     $limit = 274;
     //		$limit = 10;
     WP_CLI::line('Start rp4wp-dev test');
     WP_CLI::line('---------------------');
     // args
     $post_type = 'post';
     $linked_post_types = array('post');
     $rel_amount = 3;
     $max_post_age = 0;
     /**
      * UNINSTALL
      */
     // Add the post types
     $ptm = new RP4WP_Post_Type_Manager();
     // Remove post type
     $ptm->remove_post_type($post_type);
     // Related post manager
     $related_post_manager = new RP4WP_Related_Post_Manager();
     // Remove linked related posts
     $related_post_manager->remove_linked_posts($post_type);
     // delete words
     $word_manager = new RP4WP_Related_Word_Manager();
     $word_manager->delete_words_by_post_type($post_type);
     /**
      * SETTINGS
      */
     // set the linked post types
     $ptm->add_post_type($post_type, $linked_post_types);
     // set the post type options
     if (isset(RP4WP::get()->settings['general_' . $post_type])) {
         $options = RP4WP::get()->settings['general_' . $post_type]->get_options();
         $options['automatic_linking_post_amount'] = $rel_amount;
         $options['max_post_age'] = $max_post_age;
         update_option('rp4wp_general_' . $post_type, $options);
     }
     /**
      * CACHE POSTS
      */
     WP_CLI::line('Start building word cache');
     // related word manage
     $related_word_manager = new RP4WP_Related_Word_Manager();
     $start = time();
     // cache words of parent post type
     $related_word_manager->save_all_words($post_type, $limit);
     // cache words of linked post types
     foreach ($linked_post_types as $linked_post_type) {
         $related_word_manager->save_all_words($linked_post_type, $limit);
     }
     $runtime = time() - $start;
     $avg = $runtime / $limit;
     WP_CLI::line(sprintf('Words cached - Runtime: %d - Average: %f', $runtime, $avg));
     $start = time();
     /**
      * LINK POSTS
      */
     WP_CLI::line('Start linking posts');
     $related_post_manager->link_related_posts($rel_amount, $post_type, $limit);
     $runtime = time() - $start;
     $avg = $runtime / $limit;
     WP_CLI::line(sprintf('Posts linked - Runtime: %d - Average: %f', $runtime, $avg));
     // output success
     WP_CLI::success(sprintf('Successfully installed %s', $post_type));
 }