path = plugins_url('', __FILE__);
$this->exclude_post_types = array('attachment', 'revision', 'nav_menu_item', 'safecss');
// get options
$defaults = array(// default options
'heading_text' => 'Contents',
'start' => 3,
'show_heading_text' => true,
'auto_insert_post_types' => array('page', 'post'),
'heading_levels' => array('1', '2', '3', '4', '5', '6'),
'show_hierarchy' => true,
'number_list_items' => true,
);
$options = get_option(EXTENDED_TOC_ID, $defaults);
$this->options = wp_parse_args($options, $defaults);
add_action('plugins_loaded', array(&$this, 'plugins_loaded'));
if (is_admin()) {
//Additional links on the plugin page
add_filter('plugin_row_meta', array(&$this, 'register_plugin_links'), 10, 2);
add_action('admin_init', array(&$this, 'admin_init'));
add_action('admin_menu', array(&$this, 'admin_menu'));
} else {
/** Add the content filter and enqueue css * */
add_filter('the_content', array(&$this, 'the_content'), 100);
add_action('wp_enqueue_scripts', array(&$this, 'wp_enqueue_scripts'));
add_shortcode('extoc', array(&$this, 'shortcode_extoc'));
add_shortcode('noextoc', array(&$this, 'shortcode_noextoc'));
}
}
public function __destruct() {
}
public function register_plugin_links($links, $file) {
if ($file == plugin_basename(__FILE__)) {
$links[] = '' . __('Donate', EXTENDED_TOC_ID) . '';
}
return $links;
}
public function admin_init() {
wp_register_style(EXTENDED_TOC_ID, $this->path . '/admin-style.css', array(), EXTENDED_TOC_VERSION);
wp_enqueue_style(EXTENDED_TOC_ID);
}
public function admin_menu() {
// Create menu tab
$page = add_submenu_page('plugins.php', EXTENDED_TOC_NAME, EXTENDED_TOC_NAME, 'manage_options', EXTENDED_TOC_ID, array(&$this, 'admin_options'));
}
private function save_admin_options() {
global $post_id;
// security check
if (!wp_verify_nonce(@$_POST[EXTENDED_TOC_ID], plugin_basename(__FILE__)))
return false;
// require an administrator level to save
if (!current_user_can('manage_options', $post_id))
return false;
$this->options = array_merge(
$this->options,
array(
'heading_text' => stripslashes(trim($_POST['heading_text'])),
'auto_insert_post_types' => @(array) $_POST['auto_insert_post_types'],
'start' => intval($_POST['start']),
'show_heading_text' => (isset($_POST['show_heading_text']) && $_POST['show_heading_text']) ? true : false,
'show_hierarchy' => (isset($_POST['show_hierarchy']) && $_POST['show_hierarchy']) ? true : false,
'number_list_items' => (isset($_POST['number_list_items']) && $_POST['number_list_items']) ? true : false,
'heading_levels' => @(array) $_POST['heading_levels'],
)
);
// update_option will return false if no changes were made
update_option(EXTENDED_TOC_ID, $this->options);
return true;
}
public function admin_options() {
if (isset($_GET['update'])) {
if ($this->save_admin_options())
$msg = '
' . __('Options saved.', EXTENDED_TOC_ID) . '
';
else
$msg = '' . __('Save failed.', EXTENDED_TOC_ID) . '
';
}
?>
displayMainContent();
} else {
$this->displayHelpContent();
}
?>
path . '/style.css', array(), 'POWER_TOC_VERSION');
wp_enqueue_style(EXTENDED_TOC_ID);
}
public function plugins_loaded() {
load_plugin_textdomain(EXTENDED_TOC_ID, false, dirname(plugin_basename(__FILE__)) . '/locale/');
}
public function shortcode_extoc($atts) {
extract(shortcode_atts(array(
'start' => $this->options["start"],
'headers' => $this->options["heading_levels"],
'title' => $this->options["heading_text"],
), $atts));
if (!is_array($headers))
$headers = preg_split('/[\s*,]+/i', $headers);
if ($start)
$this->options['start'] = $start;
if ($headers)
$this->options['heading_levels'] = $headers;
if ($title)
$this->options['heading_text'] = $title;
if (isset($atts[0]['notitle']))
$this->options['show_heading_text'] = false;
if (!is_search() && !is_archive() && !is_feed() && !is_front_page())
return '[extoc]';
else
return;
}
public function shortcode_noextoc($atts) {
return;
}
public function the_content($content) {
global $post;
// Reset the counter
$this->counter = array();
if (is_search() || is_archive() || is_front_page() || is_feed())
return $content;
/** Extract the content, and extract the part content if was used * */
$this->content = $content; // The original content (subpage) that is displayed
$this->extract_full_post_content();
$toc_content = "";
if ($this->options['show_heading_text'] == true)
$toc_content .= "
" . $this->options["heading_text"] . "
";
$toc_content .= "
";
$toc_content .= $this->extract_toc();
$toc_content .= "
";
if ($this->totalHeadings >= $this->options['start'])
return $this->insert_toc_at_markup_position($toc_content); // $toc_content . $this->content;
else {
$content = preg_replace("/\[extoc\]|\[noextoc\]/", "", $this->content);
return $content;
}
}
/** returns the content for display added by the ToC */
private function insert_toc_at_markup_position($toc_content) {
// clean content without markups for returning
$content = $this->content;
$content = preg_replace("/\[noextoc\]/", "", $content); // preg_replace("/\[extoc\]|\[noextoc\]/", "", $content);
// [noextoc] has priority. If this is found, return the original
if (strpos($this->content, '[noextoc]') !== false)
return $content;
// try to find the markup for the ToC
$pos = strpos($this->content, '[extoc]');
// we didn't find any markup...
if ($pos === false) {
global $post;
// There was no markup, so insert at top or return original if this type does not need a ToC
if (!in_array(get_post_type($post), $this->options['auto_insert_post_types']))
return $content;
else
return $toc_content . $content;
}
// In this case, the markup was found in the content
if (is_numeric($pos) && $pos >= 0) {
return str_replace('[extoc]', $toc_content, $content); // substr($content, 0, $pos) . $toc_content . substr($content, $pos);
}
// Absolute backup, return the content. This point should actually never be reached
return $content;
}
/** Extract the full unshortened content from the post * */
private function extract_full_post_content() {
global $post;
$this->fullcontent = $post->post_content;
$this->ID = $post->ID;
}
private function extract_toc() {
/** check within the full content how many pages exists */
$this->extract_pages();
$headers = "";
// Reset all settings
$this->minLevel = null;
// private $path;
// private $content = "";
// private $fullcontent = "";
// private $pages = array();
// private $ID = 0;
// private $counter = array();
// private $totalHeadings = 0;
// private $minLevel = null;
/** Extract headings from every pages */
for ($pagenum = 1; $pagenum <= count($this->pages); $pagenum++) {
$headers .= $this->extract_headings($pagenum);
}
return $headers;
}
private function extract_pages() {
/** Split the content by "nextpage"-tags if some exists */
$this->pages = preg_split("//msuU", $this->fullcontent);
}
private function extract_headings($pagenum) {
/** find all header tags within the page * */
preg_match_all('/(]*>).*<\/h\2>/msuU', $this->pages[$pagenum - 1], $matches, PREG_SET_ORDER);
if (count($matches) == 0) {
return null;
}
/** Check the headings that are desired */
if (count($this->options['heading_levels']) != 6) {
$new_matches = array();
for ($i = 0; $i < count($matches); $i++) {
if (in_array($matches[$i][2], $this->options['heading_levels']))
$new_matches[] = $matches[$i];
}
$matches = $new_matches;
}
$items = "";
/** Take first h-level as baseline */
if ($this->minLevel == null)
$this->minLevel = $matches[0][2]; // lowest level e.g. h3
$currentLevel = $this->minLevel; // $minLevel;
$this->counter[$currentLevel] = 0;
for ($i = 0; $i < count($matches); $i++) {
/** get anchor and add to find and replace arrays * */
$anchor = $this->url_encode_anchor($matches[$i][0]);
$find = $matches[$i][0];
$replace = str_replace(
array(
$matches[$i][1], // start of heading
'' // end of heading
),
array(
$matches[$i][1] . '',
''
),
$matches[$i][0]
);
$this->content = str_replace($find, $replace, $this->content);
/** Check if header lower current header, then add level and update current header */
if ($matches[$i][2] > $currentLevel && $this->options['show_hierarchy'] == true) {
$currentLevel = $matches[$i][2];
$this->counter[$currentLevel] += 1;
} else if ($matches[$i][2] < $currentLevel && $matches[$i][2] >= $this->minLevel && $this->options['show_hierarchy'] == true) {
$currentLevel = $matches[$i][2];
$this->counter[$currentLevel] += 1;
} else {
$this->counter[$currentLevel] += 1;
}
/** build html */
$items .= '';
$this->totalHeadings++;
}
return $items;
}
private function url_encode_anchor($anchor) {
$return = false;
if (!empty($anchor)) {
/** Remove tags */
$return = trim(strip_tags($anchor));
/** remove & */
$return = str_replace('&', '', $return);
/** remove all unknown chars * */
$return = preg_replace("/[^0-9a-zA-Z \-_]+/", "", $return);
/** Remove backspace etc */
$return = preg_replace("/[\s]+/", "-", $return);
/** If we now start or end with a - or _ remove it */
$return = preg_replace("/^[-_]/", "", $return);
$return = preg_replace("/[-_]$/", "", $return);
}
return $return;
}
}
}
/** Initialise the class */
$tocPlugin = new ExToC();
?>