/** * This function extracts headings from the html formatted $content. It will pull out * only the required headings as specified in the options. For all qualifying headings, * this function populates the $find and $replace arrays (both passed by reference) * with what to search and replace with. * * Returns a HTML formatted string of list items for each qualifying heading. This * is everything between and NOT including <ul> and </ul> * * @access private * @since 1.0 * @static * * @param array $find * @param array $replace * @param string $content * * @return bool|string */ public static function extract_headings(&$find, &$replace, $content = '') { global $wp_query; $post = $wp_query->post; $matches = array(); $anchor = ''; $items = ''; $headings = get_post_meta($post->ID, '_ez-toc-heading-levels', TRUE); $exclude = get_post_meta($post->ID, '_ez-toc-exclude', TRUE); $altText = get_post_meta($post->ID, '_ez-toc-alttext', TRUE); if (!is_array($headings)) { $headings = array(); } if (empty($headings)) { $headings = ezTOC_Option::get('heading_levels', array()); } if (empty($exclude)) { $exclude = ezTOC_Option::get('exclude'); } // reset the internal collision collection as the_content may have been triggered elsewhere // eg by themes or other plugins that need to read in content such as metadata fields in // the head html tag, or to provide descriptions to twitter/facebook self::$collision_collector = array(); if (is_array($find) && is_array($replace) && $content) { // get all headings // the html spec allows for a maximum of 6 heading depths if (preg_match_all('/(<h([1-6]{1})[^>]*>).*<\\/h\\2>/msuU', $content, $matches, PREG_SET_ORDER)) { // remove undesired headings (if any) as defined by heading_levels if (count($headings) != 6) { $new_matches = array(); for ($i = 0; $i < count($matches); $i++) { if (in_array($matches[$i][2], $headings)) { $new_matches[] = $matches[$i]; } } $matches = $new_matches; } // remove specific headings if provided via the 'exclude' property if ($exclude) { $excluded_headings = explode('|', $exclude); $excluded_count = count($excluded_headings); if ($excluded_count > 0) { for ($j = 0; $j < $excluded_count; $j++) { $excluded_headings[$j] = preg_quote($excluded_headings[$j]); // escape some regular expression characters // others: http://www.php.net/manual/en/regexp.reference.meta.php $excluded_headings[$j] = str_replace(array('\\*'), array('.*'), trim($excluded_headings[$j])); } $new_matches = array(); for ($i = 0; $i < count($matches); $i++) { $found = FALSE; for ($j = 0; $j < $excluded_count; $j++) { if (@preg_match('/^' . $excluded_headings[$j] . '$/imU', strip_tags($matches[$i][0]))) { $found = TRUE; break; } } if (!$found) { $new_matches[] = $matches[$i]; } } if (count($matches) != count($new_matches)) { $matches = $new_matches; } } } // remove empty headings $new_matches = array(); for ($i = 0; $i < count($matches); $i++) { if (trim(strip_tags($matches[$i][0])) != FALSE) { $new_matches[] = $matches[$i]; } } if (count($matches) != count($new_matches)) { $matches = $new_matches; } $toc = $matches; // Replace headers with toc alt text. if ($altText) { $alt_headings = array(); $split_headings = preg_split('/\\r\\n|[\\r\\n]/', $altText); $split_headings_count = count($split_headings); if ($split_headings) { for ($k = 0; $k < $split_headings_count; $k++) { $explode_headings = explode('|', $split_headings[$k]); if (0 < strlen($explode_headings[0]) && 0 < strlen($explode_headings[1])) { $alt_headings[$explode_headings[0]] = $explode_headings[1]; } } } if (0 < count($alt_headings)) { for ($i = 0; $i < count($toc); $i++) { foreach ($alt_headings as $original_heading => $alt_heading) { $original_heading = preg_quote($original_heading); // escape some regular expression characters // others: http://www.php.net/manual/en/regexp.reference.meta.php $original_heading = str_replace(array('\\*'), array('.*'), trim($original_heading)); if (@preg_match('/^' . $original_heading . '$/imU', strip_tags($toc[$i][0]))) { //$matches[ $i ][0] = str_replace( $original_heading, $alt_heading, $matches[ $i ][0] ); $toc[$i][0] = $alt_heading; } } } } } // check minimum number of headings if (count($matches) >= ezTOC_Option::get('start')) { for ($i = 0; $i < count($matches); $i++) { // get anchor and add to find and replace arrays $anchor = isset($toc[$i][0]) ? self::url_anchor_target($toc[$i][0]) : self::url_anchor_target($matches[$i][0]); $find[] = $matches[$i][0]; $replace[] = str_replace(array($matches[$i][1], '</h' . $matches[$i][2] . '>'), array($matches[$i][1] . '<span class="ez-toc-section" id="' . $anchor . '">', '</span></h' . $matches[$i][2] . '>'), $matches[$i][0]); // assemble flat list if (!ezTOC_Option::get('show_hierarchy')) { $items .= '<li><a href="' . esc_url('#' . $anchor) . '">'; //$title = apply_filters( 'ez_toc_title', strip_tags( wp_kses_post( $toc[ $i ][0] ) ) ); $title = strip_tags(apply_filters('ez_toc_title', $toc[$i][0])); //if ( 'decimal' == ezTOC_Option::get( 'counter' ) ) { // // $items .= count( $replace ) . ' '; //} $items .= $title . '</a></li>'; } } // build a hierarchical toc? // we could have tested for $items but that var can be quite large in some cases if (ezTOC_Option::get('show_hierarchy')) { $items = self::build_hierarchy($toc); } } } } return $items; }