PageRenderTime 49ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/simple-tags/inc/class.client.related_posts.php

https://bitbucket.org/Wallynm/iptb
PHP | 414 lines | 296 code | 52 blank | 66 comment | 71 complexity | 795f1cdeab22617bde383ca503f6ae8c MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-1.0, GPL-2.0, GPL-3.0
  1. <?php
  2. class SimpleTags_Client_RelatedPosts extends SimpleTags_Client {
  3. /**
  4. * Constructor
  5. *
  6. * @return void
  7. * @author Amaury Balmer
  8. */
  9. function SimpleTags_Client_RelatedPosts() {
  10. // Get options
  11. $options = get_option( STAGS_OPTIONS_NAME );
  12. // Add related posts in post ( all / feedonly / blogonly / homeonly / singularonly / singleonly / pageonly /no )
  13. if ( (isset($options['rp_embedded']) && $options['rp_embedded'] != 'no') || (isset($options['rp_feed']) && $options['rp_feed'] == 1) ) {
  14. add_filter('the_content', array(&$this, 'inlineRelatedPosts'), 999993);
  15. }
  16. }
  17. /**
  18. * Auto add related posts to post content
  19. *
  20. * @param string $content
  21. * @return string
  22. */
  23. function inlineRelatedPosts( $content = '' ) {
  24. // Get options
  25. $options = get_option( STAGS_OPTIONS_NAME );
  26. $marker = false;
  27. if ( is_feed() ) {
  28. if ( $options['rp_feed'] == '1' ) {
  29. $marker = true;
  30. }
  31. } elseif ( isset($options['rp_embedded']) ) {
  32. switch ( $options['rp_embedded'] ) {
  33. case 'blogonly' :
  34. $marker = ( is_feed() ) ? false : true;
  35. break;
  36. case 'homeonly' :
  37. $marker = ( is_home() ) ? true : false;
  38. break;
  39. case 'singularonly' :
  40. $marker = ( is_singular() ) ? true : false;
  41. break;
  42. case 'singleonly' :
  43. $marker = ( is_single() ) ? true : false;
  44. break;
  45. case 'pageonly' :
  46. $marker = ( is_page() ) ? true : false;
  47. break;
  48. case 'all' :
  49. $marker = true;
  50. break;
  51. case 'no' :
  52. default:
  53. $marker = false;
  54. break;
  55. }
  56. }
  57. if ( $marker === true ) {
  58. return ( $content . $this->relatedPosts( '', false ) );
  59. }
  60. return $content;
  61. }
  62. /**
  63. * Generate related posts
  64. *
  65. * @param string $user_args
  66. * @return string|array
  67. */
  68. function relatedPosts( $user_args = '', $copyright = true ) {
  69. global $wpdb;
  70. // Get options
  71. $options = get_option( STAGS_OPTIONS_NAME );
  72. $defaults = array(
  73. 'taxonomy' => 'post_tag',
  74. 'post_type' => 'post',
  75. 'number' => 5,
  76. 'order' => 'count-desc',
  77. 'format' => 'list',
  78. 'separator' => '',
  79. 'include_page' => 'true',
  80. 'exclude_posts' => '',
  81. 'exclude_terms' => '',
  82. 'post_id' => 0,
  83. 'excerpt_wrap' => 55,
  84. 'limit_days' => 0,
  85. 'min_shared' => 1,
  86. 'title' => __('<h4>Related posts</h4>', 'simpletags'),
  87. 'nopoststext' => __('No related posts.', 'simpletags'),
  88. 'dateformat' => get_option('date_format'),
  89. 'xformat' => __('<a href="%post_permalink%" title="%post_title% (%post_date%)">%post_title%</a> (%post_comment%)', 'simpletags')
  90. );
  91. // Get values in DB
  92. $defaults['number'] = $options['rp_limit_qty'];
  93. $defaults['order'] = $options['rp_order'];
  94. $defaults['nopoststext'] = $options['rp_notagstext'];
  95. $defaults['title'] = $options['rp_title'];
  96. $defaults['xformat'] = $options['rp_xformat'];
  97. $defaults['taxonomy'] = $options['rp_taxonomy'];
  98. if( empty($user_args) ) {
  99. $user_args = $options['rp_adv_usage'];
  100. }
  101. // Replace old markers by new
  102. $markers = array('%date%' => '%post_date%', '%permalink%' => '%post_permalink%', '%title%' => '%post_title%', '%commentcount%' => '%post_comment%', '%tagcount%' => '%post_tagcount%', '%postid%' => '%post_id%');
  103. if ( !is_array($user_args) )
  104. $user_args = strtr($user_args, $markers);
  105. $args = wp_parse_args( $user_args, $defaults );
  106. extract($args);
  107. // If empty use default xformat !
  108. if ( empty($xformat) ) {
  109. $xformat = $defaults['xformat'];
  110. }
  111. // Clean memory
  112. $args = array();
  113. $defaults = array();
  114. // Get current post data
  115. $object_id = (int) $post_id;
  116. if ( $object_id == 0 ) {
  117. global $post;
  118. $object_id = (int) $post->ID;
  119. if ( $object_id == 0 ) {
  120. return false;
  121. }
  122. }
  123. // Get cache if exist
  124. $results = false;
  125. // Generate key cache
  126. $key = md5(maybe_serialize($user_args).'-'.$object_id);
  127. if ( $cache = wp_cache_get( 'related_posts'.$taxonomy, 'simpletags' ) ) {
  128. if ( isset( $cache[$key] ) ) {
  129. $results = $cache[$key];
  130. }
  131. }
  132. // If cache not exist, get datas and set cache
  133. if ( $results === false || $results === null ) {
  134. // Get get tags
  135. $current_terms = get_the_terms( (int) $object_id, $taxonomy );
  136. if ( $current_terms == false || is_wp_error($current_terms) ) {
  137. return $this->outputContent( 'st-related-posts', $format, $title, $nopoststext, $copyright );
  138. }
  139. // Number - Limit
  140. $number = (int) $number;
  141. if ( $number == 0 ) {
  142. $number = 5;
  143. } elseif( $number > 50 ) {
  144. $number = 50;
  145. }
  146. $limit_sql = 'LIMIT 0, '.$number;
  147. unset($number);
  148. // Order tags before output (count-asc/count-desc/date-asc/date-desc/name-asc/name-desc/random)
  149. $order_by = '';
  150. $order = strtolower($order);
  151. switch ( $order ) {
  152. case 'count-asc':
  153. $order_by = 'counter ASC, p.post_title DESC';
  154. break;
  155. case 'random':
  156. $order_by = 'RAND()';
  157. break;
  158. case 'date-asc':
  159. $order_by = 'p.post_date ASC';
  160. break;
  161. case 'date-desc':
  162. $order_by = 'p.post_date DESC';
  163. break;
  164. case 'name-asc':
  165. $order_by = 'p.post_title ASC';
  166. break;
  167. case 'name-desc':
  168. $order_by = 'p.post_title DESC';
  169. break;
  170. default: // count-desc
  171. $order_by = 'counter DESC, p.post_title DESC';
  172. break;
  173. }
  174. // Limit days - 86400 seconds = 1 day
  175. $limit_days = (int) $limit_days;
  176. $limit_days_sql = '';
  177. if ( $limit_days != 0 ) {
  178. $limit_days_sql = 'AND p.post_date > "' .date( 'Y-m-d H:i:s', time() - $limit_days * 86400 ). '"';
  179. }
  180. unset($limit_days);
  181. // Make array post type
  182. if ( is_string($post_type) ) {
  183. $post_type = explode(',', $post_type);
  184. }
  185. // Include_page
  186. $include_page = strtolower($include_page);
  187. if ( $include_page == 'true' ) {
  188. $post_type[] = 'page';
  189. }
  190. unset($include_page);
  191. // Build post type SQL
  192. $restrict_sql = "AND p.post_type IN ('".implode("', '", $post_type)."')";
  193. // Restrict posts
  194. $exclude_posts_sql = '';
  195. if ( $exclude_posts != '' ) {
  196. $exclude_posts = (array) explode(',', $exclude_posts);
  197. $exclude_posts = array_unique($exclude_posts);
  198. $exclude_posts_sql = "AND p.ID NOT IN (";
  199. foreach ( $exclude_posts as $value ) {
  200. $value = (int) $value;
  201. if( $value > 0 && $value != $object_id ) {
  202. $exclude_posts_sql .= '"'.$value.'", ';
  203. }
  204. }
  205. $exclude_posts_sql .= '"'.$object_id.'")';
  206. } else {
  207. $exclude_posts_sql = "AND p.ID <> {$object_id}";
  208. }
  209. unset($exclude_posts);
  210. // Restricts tags
  211. $terms_to_exclude = array();
  212. if ( $exclude_terms != '' ) {
  213. $exclude_terms = (array) explode(',', $exclude_terms);
  214. $exclude_terms = array_unique($exclude_terms);
  215. foreach ( $exclude_terms as $value ) {
  216. $terms_to_exclude[] = trim($value);
  217. }
  218. }
  219. unset($exclude_terms);
  220. // SQL Terms list
  221. $term_list = array();
  222. foreach ( (array) $current_terms as $term ) {
  223. if ( !in_array($term->name, $terms_to_exclude) ) {
  224. $term_list[] = '"'.(int) $term->term_id.'"';
  225. }
  226. }
  227. $term_list = implode(', ', $term_list);
  228. // Build SQL terms subqueries array
  229. $include_terms_sql = array();
  230. if ( !empty($term_list) ) {
  231. $include_terms_sql[$taxonomy] = $term_list;
  232. }
  233. // Group Concat check if post_relatedtags is used by xformat...
  234. $select_gp_concat = '';
  235. if ( strpos($xformat,'%post_relatedtags%') || $min_shared > 1 ) {
  236. $select_gp_concat = ', GROUP_CONCAT(tt.term_id) as terms_id';
  237. }
  238. // Check if post_excerpt is used by xformat...
  239. $select_excerpt = '';
  240. if ( strpos( $xformat, '%post_excerpt%' ) ) {
  241. $select_excerpt = ', p.post_content, p.post_excerpt, p.post_password';
  242. }
  243. // If empty return no posts text
  244. if ( empty($include_terms_sql) ) {
  245. return $this->outputContent( 'st-related-posts', $format, $title, $nopoststext, $copyright );
  246. }
  247. // Posts: title, comments_count, date, permalink, post_id, counter
  248. $results = $wpdb->get_results("
  249. SELECT p.post_title, p.comment_count, p.post_date, p.ID, COUNT(tr.object_id) AS counter {$select_excerpt} {$select_gp_concat}
  250. FROM {$wpdb->posts} AS p
  251. INNER JOIN {$wpdb->term_relationships} AS tr ON (p.ID = tr.object_id)
  252. INNER JOIN {$wpdb->term_taxonomy} AS tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id)
  253. WHERE 1 = 1
  254. AND (tt.taxonomy = '{$taxonomy}' AND tt.term_id IN ({$term_list}))
  255. {$exclude_posts_sql}
  256. AND p.post_status = 'publish'
  257. AND p.post_date_gmt < '".current_time('mysql')."'
  258. {$limit_days_sql}
  259. {$restrict_sql}
  260. GROUP BY tr.object_id
  261. ORDER BY {$order_by}
  262. {$limit_sql}");
  263. $cache[$key] = $results;
  264. wp_cache_set('related_posts'.$taxonomy, $cache, 'simpletags');
  265. }
  266. if ( $format == 'object' || $format == 'array' ) {
  267. return $results;
  268. } elseif ( $results === false || empty($results) ) {
  269. return $this->outputContent( 'st-related-posts', $format, $title, $nopoststext, $copyright );
  270. }
  271. if ( empty($dateformat) ) {
  272. $dateformat = get_option('date_format');
  273. }
  274. $output = array();
  275. // Replace placeholders
  276. foreach ( (array) $results as $result ) {
  277. if ( ( $min_shared > 1 && ( count(explode(',', $result->terms_id)) < $min_shared ) ) || !is_object($result) ) {
  278. continue;
  279. }
  280. $element_loop = $xformat;
  281. $post_title = apply_filters( 'the_title', $result->post_title );
  282. $element_loop = str_replace('%post_date%', mysql2date($dateformat, $result->post_date), $element_loop);
  283. $element_loop = str_replace('%post_permalink%', get_permalink($result->ID), $element_loop);
  284. $element_loop = str_replace('%post_title%', $post_title, $element_loop);
  285. $element_loop = str_replace('%post_title_attribute%', esc_html(strip_tags($post_title)), $element_loop);
  286. $element_loop = str_replace('%post_comment%', (int) $result->comment_count, $element_loop);
  287. $element_loop = str_replace('%post_tagcount%', (int) $result->counter, $element_loop);
  288. $element_loop = str_replace('%post_id%', $result->ID, $element_loop);
  289. if ( isset($result->terms_id) )
  290. $element_loop = str_replace('%post_relatedtags%', $this->getTagsFromID($result->terms_id, $taxonomy), $element_loop);
  291. if ( isset($result->post_excerpt) || isset($result->post_content) )
  292. $element_loop = str_replace('%post_excerpt%', $this->getExcerptPost( $result->post_excerpt, $result->post_content, $result->post_password, $excerpt_wrap ), $element_loop);
  293. $output[] = $element_loop;
  294. }
  295. // Clean memory
  296. $results = array();
  297. unset($results, $result);
  298. return $this->outputContent( 'st-related-posts', $format, $title, $output, $copyright, $separator );
  299. }
  300. /**
  301. * Build excerpt from post data with specific lenght
  302. *
  303. * @param string $excerpt
  304. * @param string $content
  305. * @param string $password
  306. * @param integer $excerpt_length
  307. * @return string
  308. * @author Amaury Balmer
  309. */
  310. function getExcerptPost( $excerpt = '', $content = '', $password = '', $excerpt_length = 55 ) {
  311. if ( !empty($password) ) { // if there's a password
  312. if ( $_COOKIE['wp-postpass_'.COOKIEHASH] != $password ) { // and it doesn't match the cookie
  313. return __('There is no excerpt because this is a protected post.', 'simpletags');
  314. }
  315. }
  316. if ( !empty($excerpt) ) {
  317. return apply_filters('get_the_excerpt', $excerpt);
  318. } else { // Fake excerpt
  319. $content = str_replace(']]>', ']]&gt;', $content);
  320. $content = strip_tags($content);
  321. $excerpt_length = (int) $excerpt_length;
  322. if ( $excerpt_length == 0 ) {
  323. $excerpt_length = 55;
  324. }
  325. $words = explode(' ', $content, $excerpt_length + 1);
  326. if ( count($words) > $excerpt_length ) {
  327. array_pop($words);
  328. array_push($words, '[...]');
  329. $content = implode(' ', $words);
  330. }
  331. return $content;
  332. }
  333. }
  334. /**
  335. * Get and format tags from list ID (SQL Group Concat)
  336. *
  337. * @param string $terms
  338. * @return string
  339. * @author Amaury Balmer
  340. */
  341. function getTagsFromID( $terms = '', $taxonomy = 'post_tag' ) {
  342. if ( empty($terms) ) {
  343. return '';
  344. }
  345. // Get tags since Term ID.
  346. $terms = (array) get_terms( $taxonomy, 'include='.$terms );
  347. if ( empty($terms) ) {
  348. return '';
  349. }
  350. // HTML Rel (tag)
  351. $rel = $this->buildRel();
  352. $output = array();
  353. foreach ( (array) $terms as $term ) {
  354. $link = get_term_link($term->term_id, $term->taxonomy);
  355. if ( empty($link) || is_wp_error($link) )
  356. continue;
  357. $output[] = '<a href="'.$link.'" title="'.esc_attr(sprintf( _n('%d topic', '%d topics', (int) $term->count, 'simpletags'), $term->count )).'" '.$rel.'>'.esc_html($term->name).'</a>';
  358. }
  359. return implode(', ', $output);
  360. }
  361. }
  362. ?>