PageRenderTime 48ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://bitbucket.org/Wallynm/iptb
PHP | 217 lines | 137 code | 34 blank | 46 comment | 36 complexity | 64ca0bade349efdea22b7a32743b2f1a MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-1.0, GPL-2.0, GPL-3.0
  1. <?php
  2. class SimpleTags_Client_Autolinks extends SimpleTags_Client {
  3. var $posts = array();
  4. var $link_tags = array();
  5. /**
  6. * Constructor
  7. *
  8. * @return void
  9. * @author Amaury Balmer
  10. */
  11. function SimpleTags_Client_Autolinks() {
  12. $options = get_option( STAGS_OPTIONS_NAME );
  13. if ( !isset($options['auto_link_priority']) || (int) $options['auto_link_priority'] == 0 )
  14. $options['auto_link_priority'] = 12;
  15. // Auto link tags
  16. add_filter( 'the_posts', array(&$this, 'getPostIds') );
  17. add_filter( 'the_content', array(&$this, 'autoLinkTags'), $options['auto_link_priority'] );
  18. }
  19. /**
  20. * Stock posts ID as soon as possible
  21. *
  22. * @param array $posts
  23. * @return array
  24. */
  25. function getPostIds( $posts = array() ) {
  26. if ( !empty($posts) && is_array($posts) ) {
  27. foreach( (array) $posts as $post) {
  28. $this->posts[] = (int) $post->ID;
  29. }
  30. $this->posts = array_unique( $this->posts );
  31. }
  32. return $posts;
  33. }
  34. /**
  35. * Get tags from current post views
  36. *
  37. * @return boolean
  38. */
  39. function getTagsFromCurrentPosts() {
  40. global $wpdb;
  41. if ( is_array($this->posts) && count($this->posts) > 0 ) {
  42. // Generate SQL from post id
  43. $postlist = implode( "', '", $this->posts );
  44. // Generate key cache
  45. $key = md5(maybe_serialize($postlist));
  46. // Get cache if exist
  47. if ( $cache = wp_cache_get( 'generate_keywords', 'simpletags' ) ) {
  48. if ( isset( $cache[$key] ) ) {
  49. return $cache[$key];
  50. }
  51. }
  52. // If cache not exist, get datas and set cache
  53. $results = $wpdb->get_results("
  54. SELECT t.name AS name, t.term_id AS term_id, tt.count AS count
  55. FROM {$wpdb->term_relationships} AS tr
  56. INNER JOIN {$wpdb->term_taxonomy} AS tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id)
  57. INNER JOIN {$wpdb->terms} AS t ON (tt.term_id = t.term_id)
  58. WHERE tt.taxonomy = 'post_tag'
  59. AND ( tr.object_id IN ('{$postlist}') )
  60. GROUP BY t.term_id
  61. ORDER BY tt.count DESC");
  62. $cache[$key] = $results;
  63. wp_cache_set('generate_keywords', $cache, 'simpletags');
  64. return $results;
  65. }
  66. return array();
  67. }
  68. /**
  69. * Get links for each tag for auto link feature
  70. *
  71. */
  72. function prepareAutoLinkTags() {
  73. // Get options
  74. $options = get_option( STAGS_OPTIONS_NAME );
  75. $auto_link_min = (int) $options['auto_link_min'];
  76. if ( $auto_link_min == 0 ) {
  77. $auto_link_min = 1;
  78. }
  79. foreach ( (array) $this->getTagsFromCurrentPosts() as $term ) {
  80. if ( $term->count >= $auto_link_min ) {
  81. $this->link_tags[$term->name] = esc_url(get_tag_link( $term->term_id ));
  82. }
  83. }
  84. return true;
  85. }
  86. /**
  87. * Replace text by link to tag
  88. *
  89. * @param string $content
  90. * @return string
  91. */
  92. function autoLinkTags( $content = '' ) {
  93. global $post;
  94. // user preference for this post ?
  95. $meta_value = get_post_meta( $post->ID, '_exclude_autolinks', true );
  96. if ( !empty($meta_value) )
  97. return $content;
  98. // Get currents tags if no exists
  99. $this->prepareAutoLinkTags();
  100. // Shuffle array
  101. $this->randomArray($this->link_tags);
  102. // HTML Rel (tag/no-follow)
  103. $rel = $this->buildRel();
  104. // Get options
  105. $options = get_option( STAGS_OPTIONS_NAME );
  106. // only continue if the database actually returned any links
  107. if ( isset($this->link_tags) && is_array($this->link_tags) && count($this->link_tags) > 0 ) {
  108. // Case option ?
  109. $case = ( $options['auto_link_case'] == 1 ) ? 'i' : '';
  110. $strpos_fnc = $options['auto_link_case'] ? 'stripos' : 'strpos';
  111. // Prepare exclude terms array
  112. $excludes_terms = explode( ',', $options['auto_link_exclude'] );
  113. if ( $excludes_terms == false ) {
  114. $excludes_terms = array();
  115. } else {
  116. $excludes_terms = array_filter($excludes_terms, '_delete_empty_element');
  117. $excludes_terms = array_unique($excludes_terms);
  118. }
  119. $z = 0;
  120. foreach ( (array) $this->link_tags as $term_name => $term_link ) {
  121. // Exclude terms ? next...
  122. if ( in_array( $term_name, (array) $excludes_terms ) ) {
  123. continue;
  124. }
  125. // Make a first test with PHP function, economize CPU with regexp
  126. if ( $strpos_fnc( $content, $term_name ) === false ) {
  127. continue;
  128. }
  129. $must_tokenize = true; // will perform basic tokenization
  130. $tokens = null; // two kinds of tokens: markup and text
  131. $j = 0;
  132. $filtered = ''; // will filter text token by token
  133. $match = '/(\PL|\A)(' . preg_quote($term_name, "/") . ')(\PL|\Z)/u'.$case;
  134. $substitute = '$1<a href="'.$term_link.'" class="st_tag internal_tag" '.$rel.' title="'. esc_attr( sprintf( __('Posts tagged with %s', 'simpletags'), $term_name ) )."\">$2</a>$3";
  135. //$match = "/\b" . preg_quote($term_name, "/") . "\b/".$case;
  136. //$substitute = '<a href="'.$term_link.'" class="st_tag internal_tag" '.$rel.' title="'. esc_attr( sprintf( __('Posts tagged with %s', 'simpletags'), $term_name ) )."\">$0</a>";
  137. // for efficiency only tokenize if forced to do so
  138. if ( $must_tokenize ) {
  139. // this regexp is taken from PHP Markdown by Michel Fortin: http://www.michelf.com/projects/php-markdown/
  140. $comment = '(?s:<!(?:--.*?--\s*)+>)|';
  141. $processing_instruction = '(?s:<\?.*?\?>)|';
  142. $tag = '(?:<[/!$]?[-a-zA-Z0-9:]+\b(?>[^"\'>]+|"[^"]*"|\'[^\']*\')*>)';
  143. $markup = $comment . $processing_instruction . $tag;
  144. $flags = PREG_SPLIT_DELIM_CAPTURE;
  145. $tokens = preg_split("{($markup)}", $content, -1, $flags);
  146. $must_tokenize = false;
  147. }
  148. // there should always be at least one token, but check just in case
  149. $anchor_level = 0;
  150. if ( isset($tokens) && is_array($tokens) && count($tokens) > 0 ) {
  151. $i = 0;
  152. foreach ($tokens as $token) {
  153. if (++$i % 2 && $token != '') { // this token is (non-markup) text
  154. if ($anchor_level == 0) { // linkify if not inside anchor tags
  155. if ( preg_match($match, $token) ) { // use preg_match for compatibility with PHP 4
  156. $j++;
  157. if ( $j <= $options['auto_link_max_by_tag'] ) {// Limit replacement at 1 by default, or options value !
  158. $token = preg_replace($match, $substitute, $token); // only PHP 5 supports calling preg_replace with 5 arguments
  159. }
  160. $must_tokenize = true; // re-tokenize next time around
  161. }
  162. }
  163. } else { // this token is markup
  164. if ( preg_match("#<\s*a\s+[^>]*>#i", $token) ) { // found <a ...>
  165. $anchor_level++;
  166. } elseif ( preg_match("#<\s*/\s*a\s*>#i", $token) ) { // found </a>
  167. $anchor_level--;
  168. }
  169. }
  170. $filtered .= $token; // this token has now been filtered
  171. }
  172. $content = $filtered; // filtering completed for this link
  173. }
  174. $z++;
  175. if ( $z > (int) $options['auto_link_max_by_post'] )
  176. break;
  177. }
  178. }
  179. return $content;
  180. }
  181. }
  182. ?>