diff --git a/index.php b/index.php index 4a340be..3183f7c 100644 --- a/index.php +++ b/index.php @@ -1,3 +1,6 @@ + + /node_modules/ /vendor/ diff --git a/plugin.php b/plugin.php index 5b6ef18..0334355 100644 --- a/plugin.php +++ b/plugin.php @@ -192,15 +192,15 @@ function add_ids_to_blocks_recursive( $blocks ) { $inner_content_id_instance = new SimpleTOC_Headline_Ids(); foreach ( $blocks as &$block ) { - if ( isset( $block['blockName'] ) && in_array( $block['blockName'], $supported_blocks ) && isset( $block['innerHTML'] ) && isset( $block['innerContent'] ) && isset( $block['innerContent'][0] ) ) { + if ( isset( $block['blockName'] ) && in_array( $block['blockName'], $supported_blocks, true ) && isset( $block['innerHTML'] ) && isset( $block['innerContent'] ) && isset( $block['innerContent'][0] ) ) { $block['innerHTML'] = add_anchor_attribute( $block['innerHTML'], $inner_html_id_instance ); $block['innerContent'][0] = add_anchor_attribute( $block['innerContent'][0], $inner_content_id_instance ); - } elseif ( isset( $block['attrs']['ref'] ) ) { + } elseif ( isset( $block['attrs']['ref'] ) ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedElseif // search in reusable blocks (this is not finished because I ran out of ideas.) // $reusable_block_id = $block['attrs']['ref']; - // $reusable_block_content = parse_blocks(get_post($reusable_block_id)->post_content); + // $reusable_block_content = parse_blocks(get_post($reusable_block_id)->post_content);. } elseif ( ! empty( $block['innerBlocks'] ) ) { - // search in groups + // search in groups. $block['innerBlocks'] = add_ids_to_blocks_recursive( $block['innerBlocks'] ); } } @@ -218,14 +218,14 @@ function render_callback_simpletoc( $attributes ) { $is_backend = defined( 'REST_REQUEST' ) && REST_REQUEST && 'edit' === filter_input( INPUT_GET, 'context' ); $title_text = $attributes['title_text'] ? esc_html( trim( $attributes['title_text'] ) ) : __( 'Table of Contents', 'simpletoc' ); $alignclass = ! empty( $attributes['align'] ) ? 'align' . $attributes['align'] : ''; - $className = ! empty( $attributes['className'] ) ? strip_tags( $attributes['className'] ) : ''; + $class_name = ! empty( $attributes['className'] ) ? wp_strip_all_tags( $attributes['className'] ) : ''; $title_level = $attributes['title_level']; - $wrapper_enabled = apply_filters( 'simpletoc_wrapper_enabled', false ) || get_option( 'simpletoc_wrapper_enabled' ) == 1 || get_option( 'simpletoc_accordion_enabled' ) == 1; + $wrapper_enabled = apply_filters( 'simpletoc_wrapper_enabled', false ) || true === (bool) get_option( 'simpletoc_wrapper_enabled', false ) || true === (bool) get_option( 'simpletoc_accordion_enabled', false ); $wrapper_attrs = get_block_wrapper_attributes( array( 'class' => 'simpletoc' ) ); - $pre_html = ( ! empty( $className ) || $wrapper_enabled || $attributes['accordion'] || $attributes['wrapper'] ) ? '
' : ''; - $post_html = ( ! empty( $className ) || $wrapper_enabled || $attributes['accordion'] || $attributes['wrapper'] ) ? '
' : ''; + $pre_html = ( ! empty( $class_name ) || $wrapper_enabled || $attributes['accordion'] || $attributes['wrapper'] ) ? '
' : ''; + $post_html = ( ! empty( $class_name ) || $wrapper_enabled || $attributes['accordion'] || $attributes['wrapper'] ) ? '
' : ''; $post = get_post(); $blocks = ! is_null( $post ) && ! is_null( $post->post_content ) ? parse_blocks( $post->post_content ) : ''; @@ -288,17 +288,17 @@ function simpletoc_add_pagenumber( $blocks, $headings ) { return $headings; } - foreach ( $blocks as $block => $innerBlock ) { - // count nextpage blocks - if ( isset( $blocks[ $block ]['blockName'] ) && $blocks[ $block ]['blockName'] === 'core/nextpage' ) { + foreach ( $blocks as $block => $inner_block ) { + // count nextpage blocks. + if ( isset( $blocks[ $block ]['blockName'] ) && 'core/nextpage' === $blocks[ $block ]['blockName'] ) { ++$pages; } - if ( isset( $blocks[ $block ]['blockName'] ) && $blocks[ $block ]['blockName'] === 'core/heading' ) { + if ( isset( $blocks[ $block ]['blockName'] ) && 'core/heading' === $blocks[ $block ]['blockName'] ) { // make sure its a headline. - foreach ( $headings as $heading => &$innerHeading ) { - if ( $innerHeading == $blocks[ $block ]['innerHTML'] ) { - $innerHeading = preg_replace( '/( &$inner_heading ) { + if ( $inner_heading === $blocks[ $block ]['innerHTML'] ) { + $inner_heading = preg_replace( '/(post_content ); $arr = array_merge( filter_headings_recursive( $e_arr ), $arr ); } } else { - // search in groups - $arr = array_merge( filter_headings_recursive( $innerBlock ), $arr ); + // search in groups. + $arr = array_merge( filter_headings_recursive( $inner_block ), $arr ); } } else { - if ( isset( $blocks['blockName'] ) && ( $blocks['blockName'] === 'core/heading' ) && $innerBlock !== 'core/heading' ) { + if ( isset( $blocks['blockName'] ) && ( 'core/heading' === $blocks['blockName'] ) && 'core/heading' !== $inner_block ) { // make sure it's a headline. - if ( preg_match( '/(' . __( '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 .= '
  • '; +function open_list( &$list_to_append_to, $list_type, &$min_depth, $this_depth ) { + if ( $this_depth === $min_depth ) { + $list_to_append_to .= '
  • '; } else { for ( $min_depth; $min_depth < $this_depth; $min_depth++ ) { - $list .= "\n<" . $list_type . ">
  • \n"; + $list_to_append_to .= "\n<" . $list_type . ">
  • \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\n"; + $list_to_append_to .= "\n\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\n"; + $list_to_append_to .= "\n\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 = '

    '; + $title_text = $attributes['title_text'] ? esc_html( trim( $attributes['title_text'] ) ) : esc_html__( 'Table of Contents', 'simpletoc' ); + $accordion_start = '

    '; } - // 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"]}\n"; + $html = "<$title_tag class=\"$html_class\">{$attributes["title_text"]}\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 ''; }