public function more($content, $post) { $more_text = 'Read the rest →'; $max_paragraphs = 1; $showmore = false; $matches = preg_split('/<!--\\s*more\\s*-->/is', $content, 2, PREG_SPLIT_NO_EMPTY); if (count($matches) > 1) { $summary = $matches[0]; $remainder = $matches[1]; if (trim($remainder) != '') { $showmore = true; } } else { $ht = new HtmlTokenizer($content, false); $set = $ht->parse(); $stack = array(); $para = 0; $token = $set->current(); $summary = new HTMLTokenSet(false); $remainder = new HTMLTokenSet(false); $set->rewind(); for ($token = $set->current(); $set->valid(); $token = $set->next()) { if ($token['type'] == HTMLTokenizer::NODE_TYPE_ELEMENT_OPEN) { $stack[$token['name']] = $token['name']; } if ($para < $max_paragraphs) { $summary[] = $token; } if ($para >= $max_paragraphs) { $remainder[] = $token; $showmore = true; } if ($token['type'] == HTMLTokenizer::NODE_TYPE_ELEMENT_CLOSE) { if (isset($stack[$token['name']])) { while (end($stack) != $token['name']) { array_pop($stack); } array_pop($stack); } if (count($stack) == 0) { $para++; } } } } if ($post->slug == Controller::get_var('slug')) { $content = $summary . '<div id="more" class="moreanchor">' . 'Continues here →' . '</div>' . $remainder; } elseif ($showmore == true) { $content = $summary . '<p class="more"><a href="' . $post->permalink . '#more">' . $more_text . '</a></p>'; } else { $content = $summary . $remainder; } return $content; }
/** * Returns a shortened version of whatever is passed in. * @param string $value A string to shorten * @param integer $count Maximum words to display [100] * @param integer $max_paragraphs Maximum paragraphs to display [1] * @return string The string, shortened */ public static function summarize( $text, $count = 100, $max_paragraphs = 1 ) { $ellipsis = '…'; $showmore = false; $ht = new HtmlTokenizer($text, false); $set = $ht->parse(); $stack = array(); $para = 0; $token = $set->current(); $summary = new HTMLTokenSet(); $set->rewind(); $remaining_words = $count; // $bail lets the loop end naturally and close all open elements without adding new ones. $bail = false; for ( $token = $set->current(); $set->valid(); $token = $set->next() ) { if ( !$bail && $token['type'] == HTMLTokenizer::NODE_TYPE_ELEMENT_OPEN ) { $stack[] = $token; } if ( !$bail ) { switch ( $token['type'] ) { case HTMLTokenizer::NODE_TYPE_TEXT: $words = preg_split( '/(\\s+)/u', $token['value'], -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY ); // word count is doubled because spaces between words are captured as their own array elements via PREG_SPLIT_DELIM_CAPTURE $words = array_slice( $words, 0, $remaining_words * 2 ); $remaining_words -= count( $words ) / 2; $token['value'] = implode( '', $words ); if ( $remaining_words <= 0 ) { $token['value'] .= $ellipsis; $summary[] = $token; $bail = true; } else { $summary[] = $token; } break; case HTMLTokenizer::NODE_TYPE_ELEMENT_CLOSE; // don't handle this case here break; default: $summary[] = $token; break; } } if ( $token['type'] == HTMLTokenizer::NODE_TYPE_ELEMENT_CLOSE ) { do { $end = array_pop( $stack ); $end['type'] = HTMLTokenizer::NODE_TYPE_ELEMENT_CLOSE; $end['attrs'] = null; $end['value'] = null; $summary[] = $end; } while ( ( $bail || $end['name'] != $token['name'] ) && count( $stack ) > 0 ); if ( count( $stack ) == 0 ) { $para++; } if ( $bail || $para >= $max_paragraphs ) { break; } } } return (string) $summary; }