Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

ERP

By: a guest on Sep 15th, 2011  |  syntax: PHP  |  size: 22.86 KB  |  views: 281  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. <?php
  2. /**
  3.  * Plugin Name: Efficient Related Posts
  4.  * Plugin URI: http://xavisys.com/wordpress-plugins/efficient-related-posts/
  5.  * Description: A related posts plugin that works quickly even with thousands of posts and tags
  6.  * Version: 0.3.8
  7.  * Author: Aaron D. Campbell
  8.  * Author URI: http://xavisys.com/
  9.  * Text Domain: efficient-related-posts
  10.  */
  11.  
  12. /**
  13.  * efficientRelatedPosts is the class that handles ALL of the plugin functionality.
  14.  * It helps us avoid name collisions
  15.  * http://codex.wordpress.org/Writing_a_Plugin#Avoiding_Function_Name_Collisions
  16.  */
  17. require_once('xavisys-plugin-framework.php');
  18. class efficientRelatedPosts extends XavisysPlugin {
  19.         /**
  20.          * @var efficientRelatedPosts - Static property to hold our singleton instance
  21.          */
  22.         static $instance = false;
  23.  
  24.         /**
  25.          * @var array Posts Processed
  26.          */
  27.         private $_processedPosts = array();
  28.  
  29.         protected function _init() {
  30.                 $this->_hook = 'efficientRelatedPosts';
  31.                 $this->_file = plugin_basename( __FILE__ );
  32.                 $this->_pageTitle = __( 'Efficient Related Posts', $this->_slug );
  33.                 $this->_menuTitle = __( 'Related Posts', $this->_slug );
  34.                 $this->_accessLevel = 'manage_options';
  35.                 $this->_optionGroup = 'erp-options';
  36.                 $this->_optionNames = array('erp');
  37.                 $this->_optionCallbacks = array();
  38.                 $this->_slug = 'efficient-related-posts';
  39.                 $this->_paypalButtonId = '9996714';
  40.  
  41.                 /**
  42.                  * Add filters and actions
  43.                  */
  44.                 add_action( 'save_post', array( $this, 'processPost' ) );
  45.                 add_action( 'admin_init', array( $this, 'processPosts' ) );
  46.                 add_action( 'permalink_structure_changed', array( $this, 'fixPermalinks' ) );
  47.                 add_shortcode('relatedPosts', array($this, 'handleShortcodes'));
  48.                 register_activation_hook( __FILE__, array( $this, 'activate' ) );
  49.                 add_filter( $this->_slug .'-opt-erp', array( $this, 'filterSettings' ) );
  50.                 add_action( 'erp-show-related-posts', array( $this, 'relatedPosts' ) );
  51.                 add_filter( 'erp-get-related-posts', array( $this, 'getRelatedPosts' ) );
  52.         }
  53.  
  54.         protected function _postSettingsInit() {
  55.                 if ( $this->_settings['erp']['auto_insert'] != 'no' ) {
  56.                         add_filter('the_content', array( $this, 'filterPostContent'), 99);
  57.                 }
  58.                 if ( $this->_settings['erp']['rss'] == 'yes' ) {
  59.                         add_filter('the_content', array( $this, 'filterPostContentRSS'), 1);
  60.                 }
  61.         }
  62.  
  63.         public function addOptionsMetaBoxes() {
  64.                 add_meta_box( $this->_slug . '-general-settings', __('General Settings', $this->_slug), array($this, 'generalSettingsMetaBox'), 'xavisys-' . $this->_slug, 'main');
  65.                 add_meta_box( $this->_slug . '-process-posts', __('Build Relations', $this->_slug), array($this, 'processPostsMetaBox'), 'xavisys-' . $this->_slug, 'main-2');
  66.                 if (get_option('erp-processedPosts')) {
  67.                         add_meta_box( $this->_slug . '-continue-processing-posts', __('Continue Processing Posts/Pages', $this->_slug), array($this, 'continueProcessingPostsMetaBox'), 'xavisys-' . $this->_slug, 'main-2');
  68.                 }
  69.         }
  70.  
  71.         public function processPostsMetaBox() {
  72.                 ?>
  73.                         <form action="" method="post">
  74.                                 <p>
  75.                                         <?php _e('Use this to build relationships for all posts.', $this->_slug); ?>
  76.                                 </p>
  77.                                 <p class="error"><?php _e('Warning, this could take a very long time (in test it took about 1 hour for 2000 posts).', $this->_slug); ?></p>
  78.                                 <?php wp_nonce_field('erp-processPosts'); ?>
  79.                                 <table class="form-table">
  80.                                         <tr valign="top">
  81.                                                 <th scope="row">
  82.                                                         <?php _e('Posts/Pages to process:', $this->_slug) ?>
  83.                                                 </th>
  84.                                                 <td>
  85.                                                         <input type="checkbox" name="erp[drafts]" value="true" id="erp-process-drafts" />
  86.                                                         <label for="erp-process-drafts"><?php _e('Process drafts', $this->_slug); ?></label><br />
  87.                                                         <input type="checkbox" name="erp[pending]" value="true" id="erp-process-pending" />
  88.                                                         <label for="erp-process-pending"><?php _e('Process pending posts', $this->_slug); ?></label><br />
  89.                                                         <input type="checkbox" name="erp[scheduled]" value="true" id="erp-process-scheduled" />
  90.                                                         <label for="erp-process-scheduled"><?php _e('Process scheduled posts', $this->_slug); ?></label>
  91.                                                 </td>
  92.                                         </tr>
  93.                                 </table>
  94.                                 <p class="submit">
  95.                                         <input type="submit" name="process_posts" value="<?php esc_attr_e('Process Posts/Pages', $this->_slug); ?>" />
  96.                                 </p>
  97.                         </form>
  98.                 <?php
  99.         }
  100.  
  101.         public function continueProcessingPostsMetaBox() {
  102.                 ?>
  103.                         <form action="" method="post">
  104.                                 <p>
  105.                                         <?php _e("The last processing didn't complete.  If you want to continue where it left off, use this:"); ?>
  106.                                 </p>
  107.                                 <?php wp_nonce_field('erp-processPosts'); ?>
  108.                                 <input type="hidden" name="erp[drafts]" value="<?php echo $_POST['erp']['drafts']; ?>" />
  109.                                 <input type="hidden" name="erp[pending]" value="<?php echo $_POST['erp']['pending']; ?>" />
  110.                                 <input type="hidden" name="erp[scheduled]" value="<?php echo $_POST['erp']['scheduled']; ?>" />
  111.                                 <input type="hidden" name="erp[continue]" value="true" />
  112.                                 <p class="submit">
  113.                                         <input type="submit" name="process_posts" value="<?php _e('Continue Processing'); ?>" />
  114.                                 </p>
  115.                         </form>
  116.                 <?php
  117.         }
  118.  
  119.         public function generalSettingsMetaBox() {
  120.                 ?>
  121.                                 <table class="form-table">
  122.                                         <tr valign="top">
  123.                                                 <th scope="row">
  124.                                                         <label for="erp_title"><?php _e("Title:", $this->_slug); ?></label>
  125.                                                 </th>
  126.                                                 <td>
  127.                                                         <input id="erp_title" name="erp[title]" type="text" class="regular-text code" value="<?php esc_attr_e($this->_settings['erp']['title']); ?>" size="40" />
  128.                                                 </td>
  129.                                         </tr>
  130.                                         <tr valign="top">
  131.                                                 <th scope="row">
  132.                                                         <label for="erp_no_rp_text"><?php _e("Display Text When No Related Posts Found:", $this->_slug); ?></label>
  133.                                                 </th>
  134.                                                 <td>
  135.                                                         <input id="erp_no_rp_text" name="erp[no_rp_text]" type="text" class="regular-text code" value="<?php esc_attr_e($this->_settings['erp']['no_rp_text']); ?>" size="40" />
  136.                                                 </td>
  137.                                         </tr>
  138.                                         <tr valign="top">
  139.                                                 <th scope="row">
  140.                                                         <label for="erp_ignore_cats"><?php _e('Ignore Categories:', $this->_slug); ?></label>
  141.                                                 </th>
  142.                                                 <td id="categorydiv" class="categorydiv">
  143.                                                         <div id="categories-all" class="tabs-panel">
  144.                                                                 <ul id="categorychecklist" class="list:category categorychecklist form-no-clear">
  145. <?php
  146.                                                         $erpWalker = new Walker_Category_Checklist_ERP();
  147.                                                         wp_category_checklist(0, 0, $this->_settings['erp']['ignore_cats'], array(), $erpWalker);
  148. ?>
  149.                                                                 </ul>
  150.                                                         </div>
  151.                                                 </td>
  152.                                         </tr>
  153.                                         <tr valign="top">
  154.                                                 <th scope="row">
  155.                                                         <label for="erp_max_relations_stored"><?php _e('Max Related Posts to Store:', $this->_slug); ?></label>
  156.                                                 </th>
  157.                                                 <td>
  158.                                                         <input id="erp_max_relations_stored" name="erp[max_relations_stored]" type="text" class="regular-text code" value="<?php esc_attr_e($this->_settings['erp']['max_relations_stored']); ?>" size="40" />
  159.                                                         <span class="setting-description"><?php _e("Max number to store.  You can't display more than this.", $this->_slug); ?></span>
  160.                                                 </td>
  161.                                         </tr>
  162.                                         <tr valign="top">
  163.                                                 <th scope="row">
  164.                                                         <label for="erp_num_to_display"><?php _e('Number of Related Posts to Display:', $this->_slug); ?></label>
  165.                                                 </th>
  166.                                                 <td>
  167.                                                         <input id="erp_num_to_display" name="erp[num_to_display]" type="text" class="regular-text code" value="<?php esc_attr_e($this->_settings['erp']['num_to_display']); ?>" size="40" />
  168.                                                         <span class="setting-description"><?php _e('The number of related posts to display if none is specified.', $this->_slug); ?></span>
  169.                                                 </td>
  170.                                         </tr>
  171.                                         <tr valign="top">
  172.                                                 <th scope="row">
  173.                                                         <?php _e("Other Setting:", $this->_slug);?>
  174.                                                 </th>
  175.                                                 <td>
  176.                                                         <input name="erp[auto_insert]" id="erp_auto_insert_no" type="radio" value="no"<?php checked('no', $this->_settings['erp']['auto_insert']) ?>>
  177.                                                         <label for="erp_auto_insert_no">
  178.                                                                 <?php _e("Do Not Auto Insert Into Posts", $this->_slug);?>
  179.                                                         </label>
  180.                                                         <br />
  181.                                                         <input name="erp[auto_insert]" id="erp_auto_insert_all" type="radio" value="all"<?php checked('all', $this->_settings['erp']['auto_insert']) ?>>
  182.                                                         <label for="erp_auto_insert_all">
  183.                                                                 <?php _e("Auto Insert Everywhere (Posts and Pages)", $this->_slug);?>
  184.                                                         </label>
  185.                                                         <br />
  186.                                                         <input name="erp[auto_insert]" id="erp_auto_insert_single-all" type="radio" value="single-all"<?php checked('single-all', $this->_settings['erp']['auto_insert']) ?>>
  187.                                                         <label for="erp_auto_insert_single-all">
  188.                                                                 <?php _e("Auto Insert Into Only Single Posts and Pages", $this->_slug);?>
  189.                                                         </label>
  190.                                                         <br />
  191.                                                         <input name="erp[auto_insert]" id="erp_auto_insert_posts" type="radio" value="posts"<?php checked('posts', $this->_settings['erp']['auto_insert']) ?>>
  192.                                                         <label for="erp_auto_insert_posts">
  193.                                                                 <?php _e("Auto Insert Into Posts", $this->_slug);?>
  194.                                                         </label>
  195.                                                         <br />
  196.                                                         <input name="erp[auto_insert]" id="erp_auto_insert_single" type="radio" value="single"<?php checked('single', $this->_settings['erp']['auto_insert']) ?>>
  197.                                                         <label for="erp_auto_insert_single">
  198.                                                                 <?php _e("Auto Insert Into Only Single Posts", $this->_slug);?>
  199.                                                         </label>
  200.                                                         <br />
  201.                                                         <br />
  202.                                                         <input name="erp[rss]" id="erp_rss" type="checkbox" value="yes"<?php checked('yes', $this->_settings['erp']['rss']) ?>>
  203.                                                         <label for="erp_rss">
  204.                                                                 <?php _e("Related Posts for RSS", $this->_slug);?>
  205.                                                         </label>
  206.                                                 </td>
  207.                                         </tr>
  208.                                 </table>
  209.                 <?php
  210.         }
  211.  
  212.         /**
  213.          * Function to instantiate our class and make it a singleton
  214.          */
  215.         public static function getInstance() {
  216.                 if ( !self::$instance ) {
  217.                         self::$instance = new self;
  218.                 }
  219.                 return self::$instance;
  220.         }
  221.  
  222.         public function processPosts() {
  223.                 if ( isset($_GET['page']) && $_GET['page'] == 'efficientRelatedPosts' && isset($_POST['process_posts']) ) {
  224.                         //ini_set('memory_limit', '256M');
  225.                         check_admin_referer( 'erp-processPosts' );
  226.                         $timestart = explode(' ', microtime() );
  227.                         $timestart = $timestart[1] + $timestart[0];
  228.  
  229.                         if ( ! isset( $_POST['erp'] ) ) {
  230.                                 $_POST['erp'] = array();
  231.                         }
  232.  
  233.                         $processed = $this->processAllPosts($_POST['erp']);
  234.  
  235.                         $timeend = explode(' ',microtime());
  236.                         $timeend = $timeend[1] + $timeend[0];
  237.                         $timetotal = $timeend-$timestart;
  238.                         $r = ( function_exists('number_format_i18n') ) ? number_format_i18n($timetotal, 1) : number_format($timetotal, 1);
  239.  
  240.                         $notice = sprintf(_n( 'Processed %d post.', 'Processed %d posts.', count($processed)), count($processed) );
  241.                         $notice .= '<br />';
  242.                         $notice .= sprintf(_n( 'Process took %s second.', 'Process took %s seconds.', $r), $r);
  243.                         $notice = str_replace( "'", "\'", "<div class='updated'><p>$notice</p></div>" );
  244.                         add_action('admin_notices', create_function( '', "echo '$notice';" ) );
  245.                 }
  246.         }
  247.  
  248.         public function filterPostContent($content) {
  249.                 // We don't want to filter if this is a feed or if settings tell us not to
  250.                 if (
  251.                                 (
  252.                                         $this->_settings['erp']['auto_insert'] == 'all' ||
  253.                                         ( $this->_settings['erp']['auto_insert'] == 'posts' && !is_page() ) ||
  254.                                         ( $this->_settings['erp']['auto_insert'] == 'single-all' && is_singular() && !is_attachment() && !is_home() ) ||
  255.                                         ( $this->_settings['erp']['auto_insert'] == 'single' && is_single() )
  256.                                 )
  257.                                 && !is_feed()
  258.                         ) {
  259.                         $content .= $this->getRelatedPosts();
  260.                 }
  261.  
  262.                 return $content;
  263.         }
  264.  
  265.         public function filterPostContentRSS($content) {
  266.                 if ( $this->_settings['erp']['rss'] == 'yes' && is_feed() ) {
  267.                         $content .= $this->getRelatedPosts();
  268.                 }
  269.  
  270.                 return $content;
  271.         }
  272.  
  273.         /**
  274.          * @param [optional]$args Array of arguments containing any of the following:
  275.          *      [num_to_display]        - Number of Posts to display
  276.          *      [no_rp_text]            - Text to display if there are no related posts
  277.          *      [title]                         - Title for related posts list, empty for none
  278.          */
  279.         public function getRelatedPosts( $args = array() ) {
  280.                 global $post;
  281.                 $output = '';
  282.  
  283.                 $settings = wp_parse_args($args, $this->_settings['erp']);
  284.  
  285.                 $relatedPosts = get_post_meta($post->ID, '_efficient_related_posts', true);
  286.  
  287.                 if ( empty($relatedPosts) || $settings['num_to_display'] == 0 ){
  288.                         /**
  289.                          * @todo The before and after setting should apply to this too
  290.                          */
  291.                         $output .= "<li>{$settings['no_rp_text']}</li>";
  292.                 } else {
  293.                         $relatedPosts = array_slice($relatedPosts, 0, $settings['num_to_display']);
  294.                         foreach ( $relatedPosts as $p ) {
  295.                                 /**
  296.                                  * Handle IDs for backwards compat
  297.                                  */
  298.                                 if ( ctype_digit($p) ) {
  299.                                         $related_post = get_post($p);
  300.                                         $p = array(
  301.                                                 'ID'                    => $related_post->ID,
  302.                                                 'post_title'            => $related_post->post_title,
  303.                                                 'permalink'             => get_permalink($related_post->ID),
  304.                                                 'post_thumbnail'        => $related_post->post_thumbnail
  305.                                         );
  306.                                 }
  307.                                 $link = "<a href='{$p['permalink']}' title='" . esc_attr(wptexturize($p['post_title']))."' class='erp-link'>".wptexturize($p['post_title']).'</a>';
  308.                                 if($p['post_thumbnail'] != ''){ $link = "<a href='{$p['permalink']}' class='erp-thumbnail'>" . $p['post_thumbnail'] . '</a>' . $link; }
  309.                                
  310.                                 /**
  311.                                  * @todo Make a before and after setting for this
  312.                                  */
  313.                                 $output .= "<li>{$link}</li>";
  314.                         }
  315.                 }
  316.  
  317.                 /**
  318.                  * @todo Make a before and after setting for this
  319.                  */
  320.                 $output = "<ul class='related_post'>{$output}</ul>";
  321.  
  322.                 if ( !empty($settings['title']) ) {
  323.                         $output = "<h3 class='related_post_title'>{$settings['title']}</h3>{$output}";
  324.                 }
  325.  
  326.                 return $output;
  327.         }
  328.  
  329.  
  330.         /**
  331.          * @param [optional]$args See efficientRelatedPosts::getRelatedPosts
  332.          */
  333.         public function relatedPosts( $args = array() ) {
  334.                 echo $this->getRelatedPosts($args);
  335.         }
  336.  
  337.         private function _getPostIDs(&$p, $key) {
  338.                 $p = absint($p['ID']);
  339.         }
  340.  
  341.         private function _findRelations($post, $processRelated = false, $postIds = null) {
  342.                 // Try to increase the time limit
  343.                 set_time_limit(60);
  344.                 global $wpdb;
  345.                 $now = current_time('mysql', 1);
  346.                 $post = get_post($post);
  347.                 $tags = wp_get_post_tags($post->ID);
  348.  
  349.                 if ( !empty($tags) ) {
  350.  
  351.                         $tagList = array();
  352.                         foreach ( $tags as $t ) {
  353.                                 $tagList[] = $t->term_id;
  354.                         }
  355.  
  356.                         $tagList = implode(',', $tagList);
  357.  
  358.                         if ( !empty($postIds) ) {
  359.                                 // Make sure each element is an integer and filter out any 0s
  360.                                 array_walk($postIds, array($this, '_getPostIDs'));
  361.                                 $postIds = array_diff(array_unique((array) $postIds), array('','0'));
  362.                         }
  363.                         if ( !empty($postIds) ) {
  364.                                 // If it's still not empty, make a SQL WHERE clause
  365.                                 $postIds = 'p.ID IN (' . implode(',', $postIds) . ') AND';
  366.                         } else {
  367.                                 // If it's empty, make sure it's a string so we don't get notices
  368.                                 $postIds = '';
  369.                         }
  370.  
  371.                         $q = <<<QUERY
  372.                         SELECT
  373.                                 p.ID,
  374.                                 p.post_title,
  375.                                 count(t_r.object_id) as matches
  376.                         FROM
  377.                                 {$wpdb->term_taxonomy} t_t,
  378.                                 {$wpdb->term_relationships} t_r,
  379.                                 {$wpdb->posts} p
  380.                         WHERE
  381.                                 {$postIds}
  382.                                 t_t.taxonomy ='post_tag' AND
  383.                                 t_t.term_taxonomy_id = t_r.term_taxonomy_id AND
  384.                                 t_r.object_id  = p.ID AND
  385.                                 (t_t.term_id IN ({$tagList})) AND
  386.                                 p.ID != {$post->ID} AND
  387.                                 p.post_status = 'publish' AND
  388.                                 p.post_date_gmt < '{$now}'
  389.                         GROUP BY
  390.                                 t_r.object_id
  391.                         ORDER BY
  392.                                 matches DESC,
  393.                                 p.post_date_gmt DESC
  394.  
  395. QUERY;
  396.                         $related_posts = $wpdb->get_results($q);
  397.                         $allRelatedPosts = array();
  398.                         $relatedPostsToStore = array();
  399.                         $threshold = '';
  400.  
  401.                         if ($related_posts) {
  402.                                 foreach ($related_posts as $related_post ){
  403.                                         $overlap = array_intersect(wp_get_post_categories($related_post->ID), $this->_settings['erp']['ignore_cats']);
  404.  
  405.                                         $allRelatedPosts[] = $related_post;
  406.  
  407.                                         if ( empty($overlap) && count($relatedPostsToStore) < $this->_settings['erp']['max_relations_stored'] ) {
  408.                                                 $threshold = $related_post->matches;
  409.                                                 //unset($related_post->matches);
  410.                                                 $related_post->permalink = get_permalink($related_post->ID);
  411.                                                 if ( function_exists('get_the_post_thumbnail') ) {
  412.                                                         $related_post->post_thumbnail = get_the_post_thumbnail($related_post->ID);
  413.                                                 }
  414.                                                 $relatedPostsToStore[] = (array)$related_post;
  415.                                         }
  416.                                 }
  417.                         }
  418.  
  419.                         if (!add_post_meta($post->ID, '_efficient_related_posts', $relatedPostsToStore, true)) {
  420.                                 update_post_meta($post->ID, '_efficient_related_posts', $relatedPostsToStore);
  421.                         }
  422.  
  423.                         /**
  424.                          * The threshold is the lowest number of matches in the related posts
  425.                          * that we store.  We use this to see if we need to process an old post.
  426.                          */
  427.                         if (!add_post_meta($post->ID, '_relation_threshold', $threshold, true)) {
  428.                                 update_post_meta($post->ID, '_relation_threshold', $threshold);
  429.                         }
  430.  
  431.                         if ($processRelated) {
  432.                                 foreach ( $allRelatedPosts as $p ) {
  433.                                         $threshold = get_post_meta($p->ID, '_relation_threshold', true);
  434.  
  435.                                         if ( empty($threshold) || $threshold <= $p->matches ) {
  436.                                                 // Get the current related posts
  437.                                                 $relatedPosts = get_post_meta($p->ID, '_efficient_related_posts', true);
  438.                                                 $relatedPosts[] = array('ID'=>$post->ID,'post_title'=>$post->post_title);
  439.                                                 // Find the relations, but limit the posts that are checked to save memory/time
  440.                                                 $this->_findRelations( $p->ID, false, $relatedPosts );
  441.                                         }
  442.                                 }
  443.                         }
  444.                 }
  445.         }
  446.  
  447.         public function processPost( $a ) {
  448.                 $a = get_post( $a );
  449.                 // Don't Process revisions
  450.                 if ( $a->post_type == 'revision' ) {
  451.                         return;
  452.                 }
  453.                 $this->_findRelations( $a, true );
  454.         }
  455.  
  456.         public function processAllPosts( $args = array() ) {
  457.                 //set_time_limit(600);
  458.                 global $wpdb;
  459.                 $defaults = array(
  460.                         'drafts'        => false,
  461.                         'pending'       => false,
  462.                         'scheduled'     => false,
  463.                         'continue'      => false
  464.                 );
  465.  
  466.                 $args = wp_parse_args((array) $args, $defaults);
  467.  
  468.                 $statuses = array('publish');
  469.  
  470.                 if ( $args['drafts'] == 'true' ) {
  471.                         $statuses[] = 'draft';
  472.                 }
  473.                 if ( $args['scheduled'] == 'true' ) {
  474.                         $statuses[] = 'future';
  475.                 }
  476.                 if ( $args['pending'] == 'true' ) {
  477.                         $statuses[] = 'pending';
  478.                 }
  479.  
  480.                 $q = "SELECT `ID` FROM `{$wpdb->posts}` WHERE `post_status` IN ('%s')";
  481.                 if ( $args['continue'] ) {
  482.                         $this->_processedPosts = get_option('erp-processedPosts');
  483.                         if ( !empty($this->_processedPosts) && is_array($this->_processedPosts) ) {
  484.                                 $q .= ' && `ID` NOT IN (' . implode(',', $this->_processedPosts) . ')';
  485.                         } else {
  486.                                 $this->_processedPosts = array();
  487.                         }
  488.                 }
  489.                 $q = sprintf( $q, implode("','", $statuses));
  490.  
  491.                 $postIDs = $wpdb->get_col( $q );
  492.  
  493.                 foreach ($postIDs as $pid) {
  494.                         $this->_findRelations( $pid );
  495.                         $this->_processedPosts[] = $pid;
  496.                         update_option('erp-processedPosts', $this->_processedPosts);
  497.                         if (memory_get_usage() >= .8 * get_memory_limit()) {
  498.                                 break;
  499.                         }
  500.                 }
  501.                 delete_option('erp-processedPosts');
  502.                 return $postIDs;
  503.         }
  504.  
  505.         public function fixPermalinks(){
  506.                 global $wpdb;
  507.  
  508.                 $query = <<<QUERY
  509.                 SELECT * FROM `{$wpdb->postmeta}` WHERE `meta_key`='_efficient_related_posts'
  510. QUERY;
  511.  
  512.                 $relatedPostMeta = $wpdb->get_results($query);
  513.  
  514.                 foreach ($relatedPostMeta as $relatedPosts) {
  515.                         $relatedPosts->meta_value = maybe_unserialize($relatedPosts->meta_value);
  516.                         foreach ($relatedPosts->meta_value as &$relatedPost) {
  517.                                 $relatedPost['permalink'] = get_permalink($relatedPost['ID']);
  518.                         }
  519.  
  520.                         $relatedPosts->meta_value = maybe_serialize( stripslashes_deep($relatedPosts->meta_value) );
  521.  
  522.                         $data  = array( 'meta_value' => $relatedPosts->meta_value);
  523.                         $where = array(
  524.                                 'meta_key'      => $relatedPosts->meta_key,
  525.                                 'post_id'       => $relatedPosts->post_id
  526.                         );
  527.  
  528.                         $wpdb->update( $wpdb->postmeta, $data, $where );
  529.                         wp_cache_delete($relatedPosts->post_id, 'post_meta');
  530.                 }
  531.         }
  532.  
  533.         public function activate() {
  534.                 $this->processAllPosts();
  535.         }
  536.  
  537.     /**
  538.          * Replace our shortCode with the list of related posts
  539.          *
  540.          * @param array $attr - array of attributes from the shortCode
  541.          * @param string $content - Content of the shortCode
  542.          * @return string - formatted XHTML replacement for the shortCode
  543.          */
  544.     public function handleShortcodes($attr, $content = '') {
  545.                 if ( !empty($content) && empty($attr['title']) ) {
  546.                         $attr['title'] = $content;
  547.                 }
  548.         $attr = shortcode_atts($this->_settings['erp'], $attr);
  549.                 return $this->getRelatedPosts($attr);
  550.         }
  551.  
  552.         public function filterSettings($settings) {
  553.                 $defaults = array(
  554.                         'title'                                 => __("Related Posts:", $this->_slug),
  555.                         'no_rp_text'                    => __("No Related Posts", $this->_slug),
  556.                         'ignore_cats'                   => array(),
  557.                         'max_relations_stored'  => 10,
  558.                         'num_to_display'                => 5,
  559.                         'auto_insert'                   => 'no',
  560.                         'rss'                                   => 'no'
  561.                 );
  562.                 $settings = wp_parse_args($settings, $defaults);
  563.  
  564.                 if ( !is_array($settings['ignore_cats']) ) {
  565.                         $settings['ignore_cats'] = preg_split('/\s*,\s*/', trim($settings['ignore_cats']), -1, PREG_SPLIT_NO_EMPTY);
  566.                 }
  567.                 $settings['max_relations_stored'] = intval($settings['max_relations_stored']);
  568.                 $settings['num_to_display'] = intval($settings['num_to_display']);
  569.  
  570.                 return $settings;
  571.         }
  572. }
  573. /**
  574.  * Our custom Walker because Walker_Category_Checklist doesn't let you use your own field name
  575.  */
  576. class Walker_Category_Checklist_ERP extends Walker {
  577.         var $tree_type = 'category';
  578.         var $db_fields = array ('parent' => 'parent', 'id' => 'term_id'); //TODO: decouple this
  579.  
  580.         function start_lvl(&$output, $depth, $args) {
  581.                 $indent = str_repeat("\t", $depth);
  582.                 $output .= "$indent<ul class='children'>\n";
  583.         }
  584.  
  585.         function end_lvl(&$output, $depth, $args) {
  586.                 $indent = str_repeat("\t", $depth);
  587.                 $output .= "$indent</ul>\n";
  588.         }
  589.  
  590.         function start_el(&$output, $category, $depth, $args) {
  591.                 extract($args);
  592.  
  593.                 $class = in_array( $category->term_id, $popular_cats ) ? ' class="popular-category"' : '';
  594.                 $output .= "\n<li id='category-$category->term_id'$class>" . '<label class="selectit"><input value="' . $category->term_id . '" type="checkbox" name="erp[ignore_cats][]" id="in-category-' . $category->term_id . '"' . (in_array( $category->term_id, $selected_cats ) ? ' checked="checked"' : "" ) . '/> ' . esc_html( apply_filters('the_category', $category->name )) . '</label>';
  595.         }
  596.  
  597.         function end_el(&$output, $category, $depth, $args) {
  598.                 $output .= "</li>\n";
  599.         }
  600. }
  601.  
  602.  
  603. /**
  604.  * Helper functions
  605.  */
  606.  
  607. /**
  608.  * @param [optional]$args See efficientRelatedPosts::getRelatedPosts
  609.  */
  610. function wp_related_posts( $args = array() ) {
  611.         _deprecated_function( __FUNCTION__, '0.3.5', '"erp-show-related-posts" action' );
  612.         // Instantiate our class
  613.         $efficientRelatedPosts = efficientRelatedPosts::getInstance();
  614.         $efficientRelatedPosts->relatedPosts($args);
  615. }
  616.  
  617. /**
  618.  * @param [optional]$args See efficientRelatedPosts::getRelatedPosts
  619.  */
  620. function wp_get_related_posts( $args = array() ) {
  621.         _deprecated_function( __FUNCTION__, '0.3.5', '"erp-get-related-posts" filter' );
  622.         // Instantiate our class
  623.         $efficientRelatedPosts = efficientRelatedPosts::getInstance();
  624.         return $efficientRelatedPosts->getRelatedPosts($args);
  625. }
  626.  
  627. if ( !function_exists('get_memory_limit') ) {
  628.         function get_memory_limit() {
  629.                 $limit = ini_get('memory_limit');
  630.                 $symbol = array('B', 'K', 'M', 'G');
  631.                 $numLimit = (int) $limit;
  632.                 $units = str_replace($numLimit, '', $limit);
  633.  
  634.                 if ( empty($units) ) {
  635.                         return $numLimit;
  636.                 } else {
  637.                         return $numLimit * pow(1024, array_search(strtoupper($units[0]), $symbol));
  638.                 }
  639.         }
  640. }
  641.  
  642. // Instantiate our class
  643. $efficientRelatedPosts = efficientRelatedPosts::getInstance();