content = $content; $this->keywords = array(); $ids = get_posts( array( 'numberposts' => -1, 'post_type' => 'affiliate_keyword', 'meta_key' => 'enabled', 'meta_value' => 'yes', 'suppress_filters' => false, 'fields' => 'ids' ) ); foreach( $ids as $id ) { $url = get_post_meta( $id, 'url', true ); if ( !empty( $url ) ) { if ( $keyword = get_post( $id ) ) { $search = $keyword->post_title; $match_case = get_post_meta( $id, 'match_case', true ) == 'yes'; $boundary = get_post_meta( $id, 'boundary', true ); $boundary = empty( $boundary ) || $boundary == 'yes'; $nofollow = get_post_meta( $id, 'nofollow', true ) == 'yes'; if ( $match_case ) { $case = ''; } else { $case = 'i'; } $this->keywords[] = array( 'url' => $url, 'search' => $search, 'case' => $case, 'rel' => $nofollow ? 'nofollow' : '', 'boundary' => $boundary ); unset( $keyword ); } } } } /** * Transforms the content using keyword replacement. * * @return string */ public function get_content() { $charset = get_bloginfo( 'charset' ); $d = new DOMDocument( '1.0', $charset ); // Important to have the right encoding. Either like below or using // sprintf( '', $charset ); $prefix = sprintf( '
', $charset ); $suffix = '
'; if ( !empty( $this->keywords ) ) { foreach( $this->keywords as $keyword ) { // we need to reconstruct the document after each replacement round @$d->loadHTML( $prefix . $this->content . $suffix ); if ( $keyword['case'] == 'i' ? stripos( $this->content, $keyword['search'] ) : strpos( $this->content, $keyword['search'] ) ) { $this->current_keyword = $keyword; $this->traverse( $d ); $output = $d->saveHTML(); $open = mb_stripos( $output, $prefix ); $close = mb_stripos( $output, $suffix ); $output = mb_substr( $output, $open + strlen( $prefix ), $close - $open - strlen( $prefix ) ); $this->content = html_entity_decode( $output, ENT_QUOTES, $charset ); } } } return $this->content; } /** * Node traversal and content replacement. * * @param DOMNode $DOMNode */ private function traverse( $DOMNode ) { if( $DOMNode->hasChildNodes() ){ foreach ( $DOMNode->childNodes as $DOMElement ) { $nodeName = $DOMNode->nodeName; $nodeType = $DOMNode->nodeType; if ( $nodeType == XML_ELEMENT_NODE && $nodeName == 'a' ) { // skip links so that we don't place a link inside a link } else { $this->traverse( $DOMElement ); } } } else { $nodeName = $DOMNode->nodeName; $nodeType = $DOMNode->nodeType; if ( $nodeType == XML_TEXT_NODE ) { if ( !empty( $this->current_keyword ) ) { $boundary = $this->current_keyword['boundary'] ? '\b' : ''; $DOMNode->nodeValue = mb_ereg_replace( $boundary . $this->current_keyword['search'] . $boundary, sprintf( '\\0', esc_attr( $this->current_keyword['url'] ), !empty( $this->current_keyword['rel'] ) ? ' rel="' . esc_attr( $this->current_keyword['rel'] ) . '" ' : '' ), $DOMNode->nodeValue, "msr" . $this->current_keyword['case'] ); } } } } }