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