' . __( 'Support', 'simpletoc' ) . '' ) );
- $links = array_merge( $links, array( '' . __( 'Donate', 'simpletoc' ) . '' ) );
- $links = array_merge( $links, array( '' . __( 'Write a review', 'simpletoc' ) . ' ⭐️⭐️⭐️⭐️⭐️' ) );
+ $links = array_merge( $links, array( '' . esc_html__( 'Support', 'simpletoc' ) . '' ) );
+ $links = array_merge( $links, array( '' . esc_html__( 'Donate', 'simpletoc' ) . '' ) );
+ $links = array_merge( $links, array( '' . esc_html__( 'Write a review', 'simpletoc' ) . ' ⭐️⭐️⭐️⭐️⭐️' ) );
}
return $links;
@@ -419,42 +419,46 @@ function simpletoc_plugin_meta( $links, $file ) {
/**
* Adds an ID attribute to all Heading tags in the provided HTML.
*
- * @param string $html The HTML content to modify
- * @param SimpleTOC_Headline_Ids $headline_class_instance The instance of the SimpleTOC_Headline_Ids class
+ * @param string $html The HTML content to modify.
+ * @param SimpleTOC_Headline_Ids $headline_class_instance The instance of the SimpleTOC_Headline_Ids class.
* @return string The modified HTML content with ID attributes added to the Heading tags
*/
function add_anchor_attribute( $html, $headline_class_instance = null ) {
- // remove non-breaking space entites from input HTML
+ // remove non-breaking space entites from input HTML.
$html_wo_nbs = str_replace( ' ', ' ', $html );
- // Thank you Nick Diego
+ // Thank you Nick Diego.
if ( ! $html_wo_nbs ) {
return $html;
}
libxml_use_internal_errors( true );
$dom = new \DOMDocument();
- @$dom->loadHTML( '' . "\n" . $html_wo_nbs, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
+ try {
+ $dom->loadHTML( '' . "\n" . $html_wo_nbs, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
+ } catch ( \Exception $e ) {
+ return $html;
+ }
// use xpath to select the Heading html tags.
$xpath = new \DOMXPath( $dom );
$tags = $xpath->evaluate( '//*[self::h1 or self::h2 or self::h3 or self::h4 or self::h5 or self::h6]' );
- // Loop through all the found tags
+ // Loop through all the found tags.
foreach ( $tags as $tag ) {
- // if tag already has an attribute "id" defined, no need for creating a new one
+ // if tag already has an attribute "id" defined, no need for creating a new one.
if ( ! empty( $tag->getAttribute( 'id' ) ) ) {
continue;
}
- // Set id attribute
- $heading_text = trim( strip_tags( $html ) );
+ // Set id attribute.
+ $heading_text = trim( wp_strip_all_tags( $html ) );
$anchor = $headline_class_instance->get_headline_anchor( $heading_text );
$tag->setAttribute( 'id', $anchor );
}
- // Save the HTML changes
- $content = $dom->saveHTML( $dom->documentElement );
+ // Save the HTML changes.
+ $content = $dom->saveHTML( $dom->documentElement ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
return $content;
}
@@ -462,8 +466,8 @@ function add_anchor_attribute( $html, $headline_class_instance = null ) {
/**
* Generates a table of contents based on the provided headings and attributes
*
- * @param array $headings An array of headings to include in the table of contents
- * @param array $attributes An array of attributes to customize the output
+ * @param array $headings An array of headings to include in the table of contents.
+ * @param array $attributes An array of attributes to customize the output.
* @return string The generated table of contents as HTML
*/
function generate_toc( $headings, $attributes ) {
@@ -485,9 +489,9 @@ function generate_toc( $headings, $attributes ) {
$this_depth = (int) $headings[ $line ][2];
$next_depth = isset( $headings[ $line + 1 ][2] ) ? (int) $headings[ $line + 1 ][2] : '';
$exclude_headline = should_exclude_headline( $headline, $attributes, $this_depth );
- $title = trim( strip_tags( $headline ) );
- $customId = extract_id( $headline );
- $link = $customId ? $customId : $headline_ids->get_headline_anchor( $title );
+ $title = trim( wp_strip_all_tags( $headline ) );
+ $custom_id = extract_id( $headline );
+ $link = $custom_id ? $custom_id : $headline_ids->get_headline_anchor( $title );
if ( ! $exclude_headline ) {
++$item_count;
open_list( $list, $list_type, $min_depth, $this_depth );
@@ -521,8 +525,8 @@ function generate_toc( $headings, $attributes ) {
$html = add_accordion_end( $html, $attributes );
$html = add_hidden_markup_end( $html, $attributes );
- // return an emtpy string if stripped result is empty
- if ( empty( trim( strip_tags( $html ) ) ) ) {
+ // return an emtpy string if stripped result is empty.
+ if ( empty( trim( wp_strip_all_tags( $html ) ) ) ) {
$html = '';
}
@@ -532,9 +536,9 @@ function generate_toc( $headings, $attributes ) {
/**
* Finds the minimum depth level of headings in the provided array and adjusts it based on the provided attributes
*
- * @param array $headings An array of headings to search through
- * @param array $attributes An array of attributes to adjust the minimum depth level
- * @return array An array containing the minimum depth level and the initial depth level
+ * @param array $headings An array of headings to search through.
+ * @param array $attributes An array of attributes to adjust the minimum depth level.
+ * @return array An array containing the minimum depth level and the initial depth level.
*/
function find_min_depth( $headings, $attributes ) {
$min_depth = 6;
@@ -556,12 +560,12 @@ function find_min_depth( $headings, $attributes ) {
}
/**
- * Determines if a given headline should be excluded based on the provided attributes
+ * Determines if a given headline should be excluded based on the provided attributes.
*
- * @param string $headline The headline to check for exclusion
- * @param array $attributes An array of attributes to use for exclusion
- * @param int $this_depth The depth level of the headline
- * @return bool True if the headline should be excluded, false otherwise
+ * @param string $headline The headline to check for exclusion.
+ * @param array $attributes An array of attributes to use for exclusion.
+ * @param int $this_depth The depth level of the headline.
+ * @return bool True if the headline should be excluded, false otherwise.
*/
function should_exclude_headline( $headline, $attributes, $this_depth ) {
$exclude_headline = false;
@@ -576,18 +580,18 @@ function should_exclude_headline( $headline, $attributes, $this_depth ) {
/**
* The open_list function appends a new list item to the global $list variable, adding necessary opening tags if needed to maintain the correct nesting of the list.
*
- * @param string &$list The global list variable to append the new list item to.
+ * @param string &$list_to_append_to The global list variable to append the new list item to.
* @param string $list_type The type of list to be created, either "ul" (unordered list) or "ol" (ordered list).
* @param int &$min_depth The minimum depth of headings that should be included in the table of contents.
* @param int $this_depth The depth of the current heading being processed.
- * @return void The function modifies the input $list variable directly.
+ * @return void The function modifies the input $list_to_append_to variable directly.
*/
-function open_list( &$list, $list_type, &$min_depth, $this_depth ) {
- if ( $this_depth == $min_depth ) {
- $list .= '
\n";
}
}
}
@@ -595,11 +599,11 @@ function open_list( &$list, $list_type, &$min_depth, $this_depth ) {
/**
* Closes an HTML list tag and updates the list string and minimum depth variable as necessary.
*
- * @param string $list A reference to the list string being built.
+ * @param string $list_to_append_to A reference to the list string being built.
* @param string $list_type The type of list tag being used (ul or ol).
* @param int $min_depth A reference to the minimum depth variable.
- * @param int $min_depth Minimum depth setting, which is a low number like 1.
- * @param int $max_depth Maximum depth setting, which is a high number like 6.
+ * @param int $min_level The minimum depth level of the headings.
+ * @param int $max_level Maximum depth setting, which is a high number like 6.
* @param int|null $next_depth The depth of the next list item, or null if this is the last item.
* @param int $line The index of the current list item.
* @param int $last_line The index of the last list item.
@@ -607,45 +611,45 @@ function open_list( &$list, $list_type, &$min_depth, $this_depth ) {
* @param int $this_depth The depth of the current list item.
* @return void
*/
-function close_list( &$list, $list_type, &$min_depth, $min_level, $max_level, $next_depth, $line, $last_line, $initial_depth, $this_depth ) {
+function close_list( &$list_to_append_to, $list_type, &$min_depth, $min_level, $max_level, $next_depth, $line, $last_line, $initial_depth, $this_depth ) {
if ( $line !== $last_line ) {
- $list .= PHP_EOL;
+ $list_to_append_to .= PHP_EOL;
if ( $next_depth < $this_depth ) {
// Next heading goes back shallower in the ToC!
if ( $next_depth >= $min_level ) {
// Next heading is within min depth bounds and WILL get ToC'd
// Close this item and step back shallower in the ToC.
for ( $min_depth; $min_depth > $next_depth; $min_depth-- ) {
- $list .= "
\n" . $list_type . ">\n";
+ $list_to_append_to .= "\n" . $list_type . ">\n";
}
- } else {
+ } else { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedElse
// SKIP CLOSING! Next heading won't be included in the ToC at all.
}
} elseif ( $next_depth === $this_depth ) {
// Next heading is exactly as deep. Not going shallower or deeper in the ToC hierarchy.
- // E.g. this is h3, next is h3
- if ( $next_depth < $min_level ) {
+ // E.g. this is h3, next is h3.
+ if ( $next_depth < $min_level ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedIf
// E.g. this is h3, next is h3, min is h2
// This heading didn't open a ToC item. Nothing to close.
} else {
// SKIP CLOSING! Next heading will open a new sub-list in the ToC.
- $list .= "\n";
+ $list_to_append_to .= "\n";
}
- } else {
+ } else { // phpcs:ignore.
// Next heading is deeper in the ToC.
- if ( $next_depth <= $max_level ) {
+ if ( $next_depth <= $max_level ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedIf
// Next deeper heading is within bounds and will open a new sub-list. Leave this one open.
- // E.g. this is h3, next is h4, min is h2, max is h5
- } else {
+ // E.g. this is h3, next is h4, min is h2, max is h5.
+ } else { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedElse
// Next heading is too deep and will be ignored. We'll close out coming up or finishing the ToC.
- // E.g. this is h3, next is h4, max is h3
+ // E.g. this is h3, next is h4, max is h3.
}
}
} else {
// This is the last line of the ToC. Close out the whole thing.
// IMPORTANT NOTE: The overall ToC list will be wrapped in a list element and closed out.
for ( $initial_depth; $initial_depth < $this_depth; $initial_depth++ ) {
- $list .= "\n" . $list_type . ">\n";
+ $list_to_append_to .= "\n" . $list_type . ">\n";
}
}
}
@@ -658,9 +662,9 @@ function close_list( &$list, $list_type, &$min_depth, $min_level, $max_level, $n
* @return string The modified HTML string with the added smooth scrolling styles.
*/
function add_smooth( $html, $attributes ) {
- // Add smooth scrolling styles, if enabled by global option or block attribute
- $isSmoothEnabled = $attributes['add_smooth'] || get_option( 'simpletoc_smooth_enabled' ) == 1;
- $html .= $isSmoothEnabled ? '' : '';
+ // Add smooth scrolling styles, if enabled by global option or block attribute.
+ $is_smooth_enabled = $attributes['add_smooth'] || true === (bool) get_option( 'simpletoc_smooth_enabled', false );
+ $html .= $is_smooth_enabled ? '' : '';
return $html;
}
@@ -685,17 +689,25 @@ function enqueue_accordion_frontend() {
);
}
-function add_hidden_markup_start( $html, $attributes, $itemcount, $alignclass ) {
- $isHiddenEnabled = $attributes['hidden'];
-
- if ( $isHiddenEnabled ) {
- $titleText = esc_html( trim( $attributes['title_text'] ) ) ?: __( 'Table of Contents', 'simpletoc' );
- $hiddenStart = '
- ' . $titleText . '';
- $html .= $hiddenStart;
+/**
+ * Adds the opening HTML tag(s) for the hidden markup element and the table of contents title, if applicable.
+ *
+ * @param string $html The HTML string to add the opening tag(s) to.
+ * @param array $attributes The attributes of the table of contents block.
+ * @param int $itemcount The number of items in the table of contents.
+ * @param string $alignclass The alignment class for the table of contents block.
+ */
+function add_hidden_markup_start( $html, $attributes, $itemcount, $alignclass ) { // phpcs:ignore.
+ $is_hidden_enabled = $attributes['hidden'];
+
+ if ( $is_hidden_enabled ) {
+ $title_text = $attributes['title_text'] ? esc_html( trim( $attributes['title_text'] ) ) : esc_html__( 'Table of Contents', 'simpletoc' );
+ $hidden_start = '
+ ' . $title_text . '';
+ $html .= $hidden_start;
}
- // If there are no items in the table of contents, return an empty string
+ // If there are no items in the table of contents, return an empty string.
if ( $itemcount < 1 ) {
return '';
}
@@ -703,10 +715,17 @@ function add_hidden_markup_start( $html, $attributes, $itemcount, $alignclass )
return $html;
}
+/**
+ * Adds the closing HTML tag(s) for the hidden markup element if the hidden markup is enabled.
+ *
+ * @param string $html The HTML string to add the closing tag(s) to.
+ * @param array $attributes The attributes of the table of contents block.
+ * @return string The modified HTML string with the closing tag(s) added.
+ */
function add_hidden_markup_end( $html, $attributes ) {
- $isHiddenEnabled = $attributes['hidden'];
+ $is_hidden_enabled = $attributes['hidden'];
- if ( $isHiddenEnabled ) {
+ if ( $is_hidden_enabled ) {
$html .= '';
}
@@ -716,41 +735,42 @@ function add_hidden_markup_end( $html, $attributes ) {
/**
* Adds the opening HTML tag(s) for the accordion element and the table of contents title, if applicable.
*
- * @param string $html The HTML string to add the opening tag(s) to
- * @param array $attributes The attributes of the table of contents block
- * @param int $itemcount The number of items in the table of contents
- * @param string $alignclass The alignment class for the table of contents block
+ * @param string $html The HTML string to add the opening tag(s) to.
+ * @param array $attributes The attributes of the table of contents block.
+ * @param int $itemcount The number of items in the table of contents.
+ * @param string $alignclass The alignment class for the table of contents block.
*/
function add_accordion_start( $html, $attributes, $itemcount, $alignclass ) {
- // Check if accordion is enabled either through the function arguments or the options
- $isAccordionEnabled = $attributes['accordion'] || get_option( 'simpletoc_accordion_enabled' ) == 1;
- $isHiddenEnabled = $attributes['hidden'];
+ // Check if accordion is enabled either through the function arguments or the options.
+ $is_accordion_enabled = $attributes['accordion'] || true === (bool) get_option( 'simpletoc_accordion_enabled', false );
+ $is_hidden_enabled = $attributes['hidden'];
- // Start and end HTML for accordion, if enabled
- $accordionStart = '';
- if ( $isAccordionEnabled ) {
+ // Start and end HTML for accordion, if enabled.
+ $accordion_start = '';
+ if ( $is_accordion_enabled ) {
enqueue_accordion_frontend();
- $titleText = esc_html( trim( $attributes['title_text'] ) ) ?: __( 'Table of Contents', 'simpletoc' );
- $accordionStart = '
';
}
- // Add the accordion start HTML to the output
- $html .= $accordionStart;
+ // Add the accordion start HTML to the output.
+ $html .= $accordion_start;
- // Add the table of contents title, if not hidden and not in accordion mode
- $showTitle = ! $attributes['no_title'] && ! $isAccordionEnabled && ! $isHiddenEnabled;
- if ( $showTitle ) {
- $titleTag = $attributes['title_level'] > 0 ? "h{$attributes['title_level']}" : 'p';
+ // Add the table of contents title, if not hidden and not in accordion mode.
+ $show_title = ! $attributes['no_title'] && ! $is_accordion_enabled && ! $is_hidden_enabled;
+ if ( $show_title ) {
+ $title_tag = $attributes['title_level'] > 0 ? "h{$attributes['title_level']}" : 'p';
+ $title_tag = wp_strip_all_tags( $title_tag );
$html_class = 'simpletoc-title';
if ( ! empty( $alignclass ) ) {
$html_class .= " $alignclass";
}
- $html = "<$titleTag class=\"$html_class\">{$attributes["title_text"]}$titleTag>\n";
+ $html = "<$title_tag class=\"$html_class\">{$attributes["title_text"]}$title_tag>\n";
}
- // If there are no items in the table of contents, return an empty string
+ // If there are no items in the table of contents, return an empty string.
if ( $itemcount < 1 ) {
return '';
}
@@ -761,15 +781,15 @@ function add_accordion_start( $html, $attributes, $itemcount, $alignclass ) {
/**
* Adds the closing HTML tag(s) for the accordion element if the accordion is enabled.
*
- * @param string $html The HTML string to add the closing tag(s) to
- * @param array $attributes The attributes of the table of contents block
+ * @param string $html The HTML string to add the closing tag(s) to.
+ * @param array $attributes The attributes of the table of contents block.
* @return string The modified HTML string with the closing tag(s) added
*/
function add_accordion_end( $html, $attributes ) {
- // Check if accordion is enabled either through the function arguments or the options
- $isAccordionEnabled = $attributes['accordion'] || get_option( 'simpletoc_accordion_enabled' ) == 1;
+ // Check if accordion is enabled either through the function arguments or the options.
+ $is_accordion_enabled = $attributes['accordion'] || true === (bool) get_option( 'simpletoc_accordion_enabled', false );
- if ( $isAccordionEnabled ) {
+ if ( $is_accordion_enabled ) {
$html .= '
';
}
@@ -779,17 +799,19 @@ function add_accordion_end( $html, $attributes ) {
/**
* Extracts the ID value from the provided heading HTML string.
*
- * @param string $headline The heading HTML string to extract the ID value from
- * @return mixed Returns the extracted ID value, or false if no ID value is found
+ * @param string $headline The heading HTML string to extract the ID value from.
+ * @return mixed Returns the extracted ID value, or false if no ID value is found.
*/
function extract_id( $headline ) {
$pattern = '/id="([^"]*)"/';
preg_match( $pattern, $headline, $matches );
- $idValue = $matches[1] ?? false;
+ $id_value = $matches[1] ?? false;
- if ( $idValue != false ) {
- return $idValue;
+ if ( false !== $id_value ) {
+ return $id_value;
}
+
+ return false;
}
/**
@@ -801,14 +823,18 @@ function extract_id( $headline ) {
function get_page_number_from_headline( $headline ) {
$dom = new \DOMDocument();
- @$dom->loadHTML( '' . "\n" . $headline, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
+ try {
+ $dom->loadHTML( '' . "\n" . $headline, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
+ } catch ( \Exception $e ) {
+ return '';
+ }
$xpath = new \DOMXPath( $dom );
$nodes = $xpath->query( '//*/@data-page' );
if ( isset( $nodes[0] ) && $nodes[0]->nodeValue > 1 ) {
- $pageNumber = $nodes[0]->nodeValue . '/';
- return esc_html( $pageNumber );
+ $page_number = $nodes[0]->nodeValue . '/';
+ return esc_html( $page_number );
} else {
return '';
}