Bootstrap i the_​posts_​navigation [wordpress]

Szuka­łem rozwią­za­nia jak zaimple­men­to­wać znacz­ni­ki i klasy Bootstra­pa w nawiga­cji po stronach posta w WordPres­sie. Znala­złem przeróż­ne, głównie skompli­ko­wa­ne filtry lub klasy i posta­no­wi­łem że sam coś napiszę. Domyśl­nie WP wyświe­tla napis 'Starsze posty' i 'Nowsze posty', albo to co podamy w argumen­tach funkcji. Można dodać klasy, ale tak czy inaczej dosta­nie­my taką surową formę:

<div class="nav-links">
   <div class="nav-previous">
      <a href="https://akademia.gaum.prostykod.pl/page/3/?s=zarz%C4%85dzanie" >Starsze wpisy</a>
   </div>
   <div class="nav-next">
      <a href="https://akademia.gaum.prostykod.pl/?s=zarz%C4%85dzanie" >Nowsze wpisy</a>
   </div>
</div>

Mi zależy na czymś takim jak na zdjęciu:

Zupeł­nie inna struk­tu­ra kodu. Posta­no­wi­łem zatem wykorzy­stać orygi­nal­ną funkcję get_​the_​posts_​navigation() do stworze­nia podob­nej, ale tworzą­cej kod wg Bootstra­pa i z dodat­ko­wą obsłu­gą numerów stron.

function sb5_get_the_posts_navigation( $args = array() ) { 
    global $paged, $wp_query;

    $max_page = $wp_query->max_num_pages;
    $nextpage = (int) $paged + 1;

    if ($max_page < 2) return '';

    $args = wp_parse_args(
        $args,
        array(
            'prev_text'          => __( 'Older posts' ),
            'next_text'          => __( 'Newer posts' ),
            'screen_reader_text' => __( 'Posts navigation' ),
            'aria_label'         => __( 'Posts' ),
            'class'              => 'page-link',
            'numbers'              => false
        )
    );

    $navigation = ''; 
    
    // Don't print empty markup if there's only one page.
    if ( $max_page > 1 ) { 
        
        $navigation = '<nav aria-label="' . $args["aria_label"] . '">
                         <ul class="pagination justify-content-center">';        
        // Make sure the nav element has an aria-label attribute: fallback to the screen reader text.
        if ( ! empty( $args['screen_reader_text'] ) && empty( $args['aria_label'] ) ) {
            $args['aria_label'] = $args['screen_reader_text'];
        }


        if ( ! is_single() && ( $nextpage <= $max_page ) ) { 
            $next_link = '<a href="' . next_posts( $max_page, false ) . '" class="' . $args["class"] . '">' . preg_replace( '/&([^#])(?![a-z]{1,8};)/i', '&#038;$1', $args["next_text"] ) . '</a>';
        }
        if ( ! is_single() && $paged > 1 ) { 
            $prev_link = '<a href="' . previous_posts( false ) . '" class="' . $args["class"] . '">' . preg_replace( '/&([^#])(?![a-z]{1,8};)/i', '&#038;$1', $args["prev_text"] ) . '</a>';
        }


        if ( isset($prev_link) ) {
            $navigation .= '<li class="page-item">' . $prev_link . '</li>';
        }
        else
        {
            $navigation .= '<li class="page-item disabled">
                                <a class="' . $args["class"] . '">' . $args["prev_text"] . '</a>
                            </li>';
        }

        if ($args["numbers"] && $max_page > 2 && $max_page < 7)
        {

            for ($i=1; $i<=$max_page; $i++)
            {
                if ($paged != $i)
                {
                    $navigation .=  '<li class="page-item"><a class="'. $args["class"] . '" href="' .get_pagenum_link($i). '">' . $i . '</a></li>';
                }
                else
                {
                    $navigation .=  '<li class="page-item active"><span class="page-link">' . $i . '</span></li>';
                }
            }
        }
        else if ($args["numbers"] && $max_page >= 7)
        {

            if ($paged >= 3)
                $navigation .=  '<li class="page-item"><a class="' . $args["class"] . '" href="' .get_pagenum_link(1). '">1</a></li>';

            if ($paged >= 4)
            {
                $navigation .=  '<li class="page-item "><span class="page-link">...</span></li>';            
            }

            $last_step = 2;
            if ($paged == 1) $last_step = 3;

            $first_step = 1;
            if ($paged == $max_page) $first_step = 2;



            if ($paged >= 1)
                for ($i = $paged-$first_step; $i<$paged+$last_step; $i++)
                {
                    if ($i <= 0 || ($i == $max_page && $i!=$paged) || $i > $max_page) continue;
                    if ($paged != $i)
                    {
                        $navigation .=  '<li class="page-item"><a class="' . $args["class"] . '" href="' .get_pagenum_link($i). '">' .$i. '</a></li>';
                    }
                    else
                    {
                        $navigation .=  '<li class="page-item active"><span class="page-link">' . $i . '</span></li>';
                    }   
                }

            if (($max_page - $paged) >= 3)
            {
                $navigation .=  '<li class="page-item "><span class="page-link">...</span></li>';            
            }            

            if ($paged < $max_page)
                $navigation .=  '<li class="page-item"><a class="' . $args["class"] . '" href="' .get_pagenum_link($max_page). '">' . $max_page . '</a></li>';
        }


        if ( isset($next_link) ) {
            $navigation .= '<li class="page-item">' . $next_link . '</li>';
        }
        else
        {
            $navigation .= '<li class="page-item disabled">
                                <a class="' . $args["class"] . '">' . $args["next_text"] . '</a>
                            </li>';
        }

        $navigation .= '</ul></nav>';
    }

    return $navigation;
}

Omówienie kodu

W odróż­nie­niu od orygi­na­łu, moja funkcja jest bardziej samodziel­na, ale do tego potrze­bu­je dostęp do dwóch zmien­nych global­nych: $paged – numer aktual­nej strony, i $wp_​query – obiekt zawie­ra­ją­cy wynik zapyta­nia do bazy WP.

$max_​page

Dzięki dostę­po­wi do $wp_​query wiemy ile jest wszyst­kich stron i możemy zadecy­do­wać, czy wyświe­tle­nie linków jest sensow­ne i jaką formę powin­no przybrać. Wartość $wp_query->max_page przypi­su­je­my do $max_​page i w linii nr 7 spraw­dza­my czy stron jest więcej niż jedna. Jeżeli nie, to kończy­my funkcję zwraca­jąc pusty ciąg. Żaden znacz­nik nie zosta­nie wyświetlony.

$nextpage

Warto od razu wiedzieć jaki numer będzie miała następ­na strona. Choćby po to, by spraw­dzić, czy nie wycho­dzi poza zakres, czyli jest większy niż $max_​page.

$args

Od linii nr 9 zaczy­na się spraw­dza­nie przypi­sa­nych paramen­tów. Dzięki funkcji wp_​parse_​args() jeste­śmy w stanie dopisać domyśl­ne warto­ści dla niepoda­nych warto­ści tabli­cy $args. Dla przykła­du nie trzeba podawać warto­ści dla nazwy linków. System podsta­wi warto­ści domyśl­ne. W odróż­nie­niu od orygi­na­łu zmody­fi­ko­wa­na zosta­ła wartość dla klucza 'class', na bootstra­po­we 'page-link'. Od siebie dodałem 'numbers', czyli boolow­ski parametr decydu­ją­cy, czy mają być wyświe­tlo­ne linki z numera­mi stron. Domyśl­nie nie będą wyświetlane.

$navigation

Zmien­na przecho­wu­ją­ca kod HTML odpowie­dzial­ny za nawiga­cję z parame­tra­mi Bootstra­pa. Jeżeli wartość $max_​page jest większa niż 1 system rozpocz­nie przypi­sy­wa­nie kodu do $naviga­tion. W liniach 26, 27 oraz 120 mamy obudo­wę dla paginacji.

$next_​link i $prev_​link

Od 34 do 39 linii mamy kod odpowie­dzial­ny za wygene­ro­wa­nie kodu HTML dla znacz­ni­ka A, czyli linku "wstecz" i "do przodu". Dla popraw­ne­go wygene­ro­wa­nia linku dla następ­nej strony musimy spraw­dzić czy wyświe­tla­na strona nie jest stroną pojedyn­cze­go posta oraz czy numer następ­nej strony nie jest większy niż $max_​page. W tym celu korzy­sta­my z funkcji is_​single() i porów­na­nia $nextpa­ge <= $max_​page. Jeżeli warun­ki są spełnio­ne, tworzy­my zmien­ną $next_​link i przypi­su­je­my kod HTML.

W linii 35 zwróć uwagę na funkcję next_​posts(). Jej wynikiem jest link url do następ­nej strony. Ma dwa argumen­ty: $max_​page$echo. Drugi odpowia­da za wyświe­tla­nie warto­ści linku. Jeżeli wpisze­my 'false', to funkcja wyświe­tli wartość zamiast przypi­sać ją do ciągu $next_​link. W linii 38 jest podob­na funkcja previous_​posts(), odpowie­dzial­na za adres url do poprzed­niej strony. Różni się tym, że ma tylko argument $echo.

Między linia­mi 42 i 50 system spraw­dza czy zmien­na $prev_​link istnie­je. Jeżeli tak, to do $naviga­tion przypi­sa­na wartość $prev_​link obudo­wa­na kodem linii listy punkto­wa­nej '<li>'. Jeżeli nie istnie­je $prev_​link, to do $naviga­tion przypi­sy­wa­ny jest kod HTML z wygaszo­nym, nieak­tyw­nym linkiem.

Podob­nie jest w liniach 110 – 118. Tam spraw­dza­my czy istnie­je $next_​link.

$args["numbers"]

Jeżeli chcemy wyświe­tlić linki z numera­mi stron, co jest bardzo pomoc­ne przy większej ilości stron, to wystar­czy przypi­sać wartość 'true' do parame­tru $args["numbers"]. Za to rozwią­za­nie odpowia­da najdłuż­sza część kodu – od linii 52 do 107.

Za wyświe­tle­nie linku do strony o konkret­nym numerze odpowia­da funkcja get_​pagenum_​link().

Numera­cja ma sens jeżeli stron jest więcej niż dwie. W mojej funkcji zasto­so­wa­łem ograni­cze­nie, które spraw­dza ile jest stron i jeżeli jest mniej niż 7, to wyświe­tla wszyst­kie linki. Jeżeli jest inaczej, to wyświe­tla pierw­szą i ostat­nia stroną oraz aktual­ną, poprzed­nią i następ­ną. Zapobie­ga to wynatu­rze­niom przy bardzo dużej ilości stron. Pomyśl jak wyglą­da­ła­by pagina­cja dla stu stron?

W pierw­szym przypad­ku zadanie jest proste. Dzięki pętli for dodaje­my kolej­ne linki do $naviga­tion. W linii 59 spraw­dza­my czy wartość pętli odpowia­da numero­wi strony. Jeżeli nie, to dodaje­my zwykły link. Jeżeli tak, to musimy dodać klasę 'active' do pozycji listy '<li>'. Trudniej się robi, gdy stron jest minimum 7.

Krok po kroku

  • Zaczy­na­my od spraw­dze­nia czy numer aktual­nej strony to co najmniej 3. Jeżeli tak, to wyświe­tla­my link dla pierw­szej strony. Jeżeli strona ma numer mniej­szy od 3, to link do strony 1 zosta­nie dodany w poniż­szej pętli 'for'.
  • Dalej czy strona jest większa czy równa 4. Jeżeli tak, to musimy dodać trzykro­pek czyli przeryw­nik, który odizo­lu­je link do strony 1 od pozostałych.
  • Tworzy­my dwie nowe warto­ści: $last_​step = 2 i $first_​step = 1. Jeżeli jeste­śmy na pierw­szej stronie, to $last_​step zwięk­sza wartość do 3, a jeżeli na ostat­niej to rośnie wartość $first_​step do 2. Warto­ści te są pomoc­ne przy logice odpowie­dzial­nej za wyświe­tla­nie linków do pierw­szej lub ostat­niej strony w pętli 'for'.
  • W linii 87 jest kluczo­wa pętla 'for' dla linków numerycz­nych. Wartość począt­ko­wa obliczo­na jest na różni­cę między numerem strony i $first_​step. Wartość końco­wa to suma numeru strony i $last_​step.
  • Dodat­ko­we zabez­pie­cze­nie jest poniżej. Jeżeli wartość pętli to 0 lub mniej albo numer strony jest równy $max_​page i jedno­cze­śnie numer strony nie jest warto­ścią pętli albo wartość pętli jest większa od $max_​page, to krok pętli jest pomija­ny. Wystar­czy, że jeden z trzech warun­ków jest spełniony.
  • Następ­nie pozosta­je spraw­dzić czy wartość pętli jest równa numero­wi strony. Wtedy przypi­su­je­my nieak­tyw­ny link, a jeżeli nie, to zwykły.
  • Na koniec system spraw­dza czy numer strony jest mniej­szy od $max_​page i jeżeli to prawda, to wyświe­tla link do ostat­niej strony.

Podsumowanie

I na tym koniec. Funkcję można rozbu­do­wać od większą liczbę numerów stron lub dodat­ko­we kroki dla bardzo dużej ilości stron. Jeżeli mamy np. 30 stron, to przej­ście z pierw­szej strony do 15 teraz trochę potrwa.

Dodaj komentarz

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.