Crear TOC personalizado - Ejecutar shortcode en sidebar

  • Autor Autor samuelsuteras
  • Fecha de inicio Fecha de inicio

samuelsuteras

Épsilon
Verificación en dos pasos activada
Verificado por Whatsapp
Verificado por Binance
Buenos dias chicos,

Necesito hacer una tabla de contenido personalizada, es por esto que no estoy usando los plugins ya bastante conocids para una TOC.

El problema que tengo es que mi clase se ejecuta de manera normal dentro del contenido de cada post, sin embargo quiero ejecutar el shortcode en el sidebar pero este no lo hace, algun dios del php me podria ayudar?

Dejo codigo.


Insertar CODE, HTML o PHP:
<?php class TableOfContents {

    /**
     * Counts the occurence of header elements in Wordpress content
     *
     * @param type $content
     * @return null|boolean|array
     */
    static function hasToc($tiers, $content) {

        $pattern = '/<h[2-' . $tiers . ']*[^>]*>(.*?)<\/h([2-' . $tiers . '])>/';
        $return = array();
        if (empty($content))
            return null;

        if (!preg_match_all($pattern, $content, $return)) {
            return false;
        }
        return $return;
    }

    /**
     * Generates a table of content only when singular pages are being viewed
     *
     * @param type $tiers
     * @param type $text
     */
    static function generateTableOfContents($tiers, $content, $draw = TRUE, $return = array()) {

        if (!is_singular())
            return $content;

        // numbers on or off?
        $num_on = false;

        $content = $toc . $content;
        $searches = array();
        $replaces = array();
        $return = (is_array($return) && !empty($return) ) ? $return : TableOfContents::hasToc($tiers, $content);

        if ($draw && !empty($return)):
            if($num_on){
                $toc = '<div class="toc nonumbers">';
            }else{
                $toc = '<div class="toc">';
            }

            $toc .= "<span>Tabla de contenidos</span>";
            $toc .= "<ul class=\"parent start\">";
            $tags = reset($return);
            $titles = $return[1];
            $levels = end($return);
            $_level = 2;
            $chapters = array('0','0','0','0','0','0');

            $count = 0;
            foreach ($tags as $i => $htag) {
                $count++;
                $attributes = array();
                $href = $count;

                $newId = 'id="' . $href . '"';
                $newhtag = '><span style="position: absolute; margin-top: -60px;" ' .$newId. '></span>';
                $htagr = str_replace('>' . $titles[$i], "\t" . $newhtag  . $titles[$i], $htag);
                $searches[] = $htag;
                $replaces[] = $htagr;


                if ((int)$levels[$i] === (int)$_level):
                    if($num_on){
                        $chapters[$_level-1] = ((int)$chapters[$_level-1]+1);
                        $chapter = implode('.', array_slice($chapters, 1, ($levels[$i]-1)  ) );
                        $toc .= '<li><span>' . strval($chapter) . '</span> <a href="#' . $href . '">' . $titles[$i] . '</a></li>';
                    }else{
                        $titles[$i] = preg_replace('/\s+/', '-', $titles[$i]);
                        $titles[$i] = strtolower($titles[$i]);
                        $toc .= '<li><a href="#' . $titles[$i]. '">' . $titles[$i] . '</a></li>';
                    }

                endif;

                if ($levels[$i] > $_level) {
                    $_steps = ((int) $levels[$i] - (int) $_level);

                    for ($j = 0; $j < $_steps; $j++):
                        $toc .= '<ul class="continue">';
                        $chapters[$levels[$i]-1+$j] = (int)$chapters[$levels[$i]-1+$j]+1;
                        $_level++;
                    endfor;
                    $chapter = implode('.', array_slice($chapters, 1, ($levels[$i]-1)  ) );

                    if($num_on){
                        $toc .= '<li><span>' . strval($chapter) . '</span> <a href="#' . $titles[$i] . '">' . $titles[$i] . '</a></li>';
                    }else{
                        $toc .= '<li><a href="#' . $titles[$i] . '">' . $titles[$i] . '</a></li>';
                    }

                }

                if ($levels[$i] < $_level) {

                    $_steps = ((int) $_level - (int) $levels[$i]);
                    $chapters[$levels[$i]-1] = (int)$chapters[$levels[$i]-1]+1;
                    $_olevel = $_level;
                    for ($j = 0; $j < $_steps; $j++):
                        $chapters[$levels[$i]+$j] = 0;
                        $toc .= '</ul>';
                        $_level--;
                    endfor;

                    $chapters[$_olevel-1] = 0;
                    $chapter = implode('.', array_slice($chapters, 1, ($levels[$i]-1)  ) );

                    if($num_on){
                        $toc .= '<li><span>' . strval($chapter) . '</span> <a href="#' . $href . '">' . $titles[$i] . '</a></li>';
                    }else{
                        $toc .= '<li><a href="#' . $href . '">' . $titles[$i] . '</a></li>';
                    }

                }
            }
            $toc .= '</ul>';
            $toc .= '</div><div class="clear"></div>';
            $content = str_replace($searches, $replaces, $content);
            $content = str_replace( '[toc]', $toc, $content );
        endif;

        return $content;
    }

    /**
     * Appends the table of content to the $content
     * AKA. Executes our filter
     *
     * @param type $content
     * @return type
     */
    static function writeToc($content) {
        // Change the number of the parameter to show more headings in the table
        $content = TableOfContents::generateTableOfContents(2, $content, TRUE);
        return $content;
    }

}
add_filter('the_content', array('TableOfContents', 'writeTOC'));
 
@samuelsuteras no veo donde registras el shortcode ??
No lo estoy registrando.

La clase funciona con el filtro the_content, ya que he probado a registrar el shortcode pero no me funciona :/

No se como hacer para que se muestra tanto en el post como en el sidebar
 
No lo estoy registrando.

La clase funciona con el filtro the_content, ya que he probado a registrar el shortcode pero no me funciona :/

No se como hacer para que se muestra tanto en el post como en el sidebar
Por lo que veo solo estas cambiando [toc] por el contenido html en el the_content, tienes que agregar tu shortcode.

Prueba eliminado el add_filter('the_content', array('TableOfContents', 'writeTOC')); y los
$content = str_replace( '[toc]', $toc, $content ); ya que el shortcode, esta registrado.

Solo retorna el html.

PHP:
function toc_add_shortcode(){
    add_shortcode('[toc]', array('TableOfContents', 'writeTOC'));
}

add_action('init', 'toc_add_shortcode');
 
No me funciona :/

No entiendo el porqué, por eso fue que busco la alternativa de reemplazar el texto toc con el output
 
Cree la clase en un archivo .php para hacer la prueba, luego llamo la clase en el functions con esto:

require_once( __DIR__ . '/toc.php'); //Path of file
Ok y en el sidebar como llamas el shortcode?
 
adjunto foto de como sale
 

Adjuntos

  • Captura de pantalla 2022-02-21 a las 16.04.46.webp
    44 KB · Visitas: 10
Bueno bro, es que add_filter('the_content', array('TableOfContents', 'writeTOC')); trabaja filtrando el contenido del post,
y el sidebar no es un post.
Lo raro es que incluso si lo paso a shortcode tampoco funciona, pero con el filtro si lo hace. Alguna idea de como hacerlo funcionar con el sidebar?
 
Lo raro es que incluso si lo paso a shortcode tampoco funciona, pero con el filtro si lo hace. Alguna idea de como hacerlo funcionar con el sidebar?
Tienes que probar registrando el shortcode y pasandole el contenido del post actual.

Algo asi bro.

PHP:
/* $content = str_replace( '[toc]', $toc, $content ); */

PHP:
static function writeToc($content) {
      
    global $post;
    $content = $post->post_content;
      
    $content = TableOfContents::generateTableOfContents(2, $content, TRUE);
    return $content;
      
}

PHP:
function toc_add_shortcode(){
    add_shortcode('[toc]', array('TableOfContents', 'writeTOC'));
}

add_action('init', 'toc_add_shortcode');

/* add_filter('the_content', array('TableOfContents', 'writeTOC')); */
 


Gracias por la ayuda bro, pero sigue sin funcionar me está volviendo loco esto.

No entiendo porque solo lo funciona con el filtro de the_content
 
Gracias por la ayuda bro, pero sigue sin funcionar me está volviendo loco esto.

No entiendo porque solo lo funciona con el filtro de the_content
Después de 1 hora de busqueda en google, encontré alguien que lo hizo

Por si a alguno le sirve para hacer su propia tabla de contenido a gusto lo dejo por aqui.