WordPress - motywy, wtyczki, informacje, programowanie

Shortcode

Oprogramowanie własnego shortcode w motywie WordPressa

Stosunkowo łatwo jest dodać do motywu w Wordpressie własne shortcody. W tym poradniku pokażemy jak to zrobić. Przy okazji nauczysz się łatwo tworzyć lekkie i ładnie wyglądające pezyciski w czystym HTML i CSS bez dodatkowej grafiki.

Jeśli nie korzystałeś dotąd z  shortcodów i chciałbyś się dowiedziec o nich więcej – do czego służą, i jak się ich używa – zapraszamy do tekstu Co to są shortcodes i jak ich używać? Shortcode „gallery”.

Funkcja obsługująca shortcode

Zacznijmy od czegoś bardzo prostego. Załóżmy, że chcesz dodać prosty shortcode [email], który w miejscu wstawienia wygeneruje tekst z aktualnym adresem email twojej firmy. Dzięki temu jeśli adres ulegnie kiedyś zmianie wystarczy, że zmienisz go w funkcji obsługującej shortcode i zostanie zamieniony na wszystkich stronach twojego serwisu.

Najpierw musimy napisać funkcję obsługującą nasz shortcode. Funkcja taka będzie wywoływana zawsze ilekroć WordPress napotka [email] podczas wyświetlania notki.

function email_sc_func ( $atts ){
    return "sekretariat@example.com";
}

Funkcję dodamy do pliku functions.php. Jeśli nie chcemy modyfikować oryginalnego pliku naszego motywu, powinniśmy utworzyć motyw potomny (child theme). Jest to rozwiązanie zdecydowanie zalecane, pozwalające uniknąć problemów później, gdy motyw którego używamy zostanie zaktualizowany do nowej wersji. O tym jak tworzyć child themes i dlaczego warto ich używać możecie przeczytać w artykule Motywy potomne (child themes) – bezpieczne modyfikacje motywu.

Teraz musimy poinformować WordPressa kiedy ma tę funkcję wywoływać, a więc skojarzyć  ją z naszym shortcodem. Służy do tego funkcja add_shortcode:

add_shortcode('email', 'email_sc_func');

Dodajemy ją poniżej, również w pliku functions.php. Pierwszy parametr to nazwa naszego shortcodu, taka, jakiej będziemy używali wstawiając go do notki, a drugi to nazwa funkcji, która ma go obsługiwać, czyli tej, którą napisaliśmy powyżej.

Atrybuty shortcodu

Do funkcji przekazywane są też za pomocą tablicy asocjacyjnej atts wszystkie atrybuty podane przy wywołaniu shortcodu.

Załóżmy, że chcemy mieć możliwość podania jednego z kilku adresów email, których używamy w firmie,  w zależności od tego, jakiego tematu dotyczy notka. Mamy do dyspozycji adresy: do biura obsługi, serwisu, biura handlowego, albo, jeśli temat nie jest określony, mamy ogólny adres do sekretariatu. Nasza funkcja obsługująca shortcode mogłaby wyglądać następująco:

function email_sc_func ( $atts ){
    $address = 'sekretariat@example.com';
    if ($atts['temat'] == 'handel') {
        $address = 'dzial_handlowy@example.com';
    } elseif ($atts['temat'] == 'reklamacje') {
        $address = 'biuro_obslugi@example.com';
    } elseif ($atts['temat'] == 'naprawa') {
        $address = 'serwis@example.com';
    }
    return $address;
}

Teraz możemy napisać:

[email temat=handel]
[email temat=reklamacje]
[email temat=naprawa]

lub zwyczajnie

[email]

i do notki zostanie wstawiony adres odpowiedniego działu lub sekretariatu firmy.

Nasza funkcja jest stosunkowo prosta, obsługuje tylko jeden atrybut i ma prostą logikę. Bardziej zaawansowane shortcody mogą korzystać z wielu atrybutów, które mają jakieś wartości domyślne. Dlatego zwykle w funkcjach obsługujących shortcody używamy funkcji shortcode_atts.

shortcode_atts( $pairs , $atts );

Przyjmuje ona dwa parametry:

  • $pairs  to tablica dozwolonych atrybutów dla danego shortcodu z wartościami domyślnymi
  • $atts to lista atrybutów jakie dostaliśmy na wejściu do funkcjo obsługującej shortcode

Funkcja shortcode_atts zwraca tablicę atrybutów wg następującej logiki:

  • jeśli atrybutu nie było w tablicy $pairs jest usuwany
  • jeśli atrybut występuje w tablicy $pairs a nie ma go w $atts to zwracana jest wartość z $pairs czyli wartość domyślna
  • jeśli atrybut występuje zarówno w $pairs jak i w $atts, zwracana jest wartość z $atts

Dodajmy zatem do naszego shortcodu jeszcze jeden atrybut o nazwie styl. Jeśli podamy styl=text (wartość domyślna) otrzymamy sam adres email, a jeśli podamy styl=html otrzymamy adres email zlinkowany przy pomocy mailto: tak, że użytkownik będzie mógł kliknąć w adres aby otworzyć klienta poczty.

function email_sc_func ( $atts ) {
    $atts = shortcode_atts(array(
                             'temat' => 'ogolne',
                             'styl'  => 'text'
                          ), $atts);
    $temat = $atts['temat'];
    $styl  = $atts['styl'];
    if ($temat == 'handel') {
        $address = 'dzial_handlowy@example.com';
    } elseif ($temat == 'reklamacje') {
        $address = 'biuro_obslugi@example.com';
    } elseif ($temat == 'naprawa') {
        $address = 'serwis@example.com';
    } elseif ($temat == 'ogolne') {
        $address = 'sekretariat@example.com';
    }
    if ($styl == 'html')
    {
        $address = '<a href="mailto:' . $address .
                   '">'. $address .'</a>';
    }
    return $address;
}

W liniach 6 i 7 podstawiamy wartości z tablicy $atts do zmiennych. Nie musimy tego robić, ale przy dłuższych funkcjach zwiększa to czytelność kodu. W wielu przykładach i w kodzie WordPressa zamiast takiej serii podstawień jest używana funkcja extract(), która powołuje lokalne zmienne na podstawie tablicy hashującej. Zamiast:

    $atts = shortcode_atts(array(
                             'temat' => 'ogolne',
                             'styl'  => 'text'
                          ), $atts);
    $temat = $atts['temat'];
    $styl  = $atts['styl'];

moglibyśmy napisać krócej:

    extract(shortcode_atts(array(
                             'temat' => 'ogolne',
                             'styl'  => 'text'
                          ), $atts));

i efekt byłyby ten sam, zostałyby powołane zmienne $temat i $styl. Na pozór to wiele skraca i upraszcza, zwłaszcza jeśli atrybutów jest dużo, ale to bardzo nieeleganckie rozwiązanie. Zmienne pojawiają się nie wiadomo skąd, nie są jawnie zainicjowane, jeśli używamy sensownego środowiska developerskiego, na przykład phpStorm, będziemy mieć masę ostrzeżeń o użyciu niezainicjowanych zmiennych, przez co przegapimy niejeden faktyczny błąd. Funkcja extract to relikt po PHP 4.0 i stanowczo odradzam jej użycie.

Pełna postać funkcji

Jeśli chcemy, aby klikalny był nie adres email, ale na przykład tekst „napisz do nas” musimy tak przerobić nasz  shortcode, aby mógł obejmować treść, czyli aby mozna go było użyć w następujący sposób:

[email temat=handel mode=html]Napisz do nas[/email]

W tym celu musimy użyć bardziej pełnej implementacji funkcji obsługującej. Jej pełna postać jest następująca:

function my_shortcode_handler( $atts, $content=null, $code="" )

Parametr $atts już znamy. W parametrze $content, który jak widać domyślnie jest pusty do funkcji obsługującej przekazywana jest treść obejmowana przez shortcode czyli w naszym przypadku będzie to „Napisz do nas”. Parametr $code używany jest w wypadku gdy chcemy aby jedna funkcja obsługiwała więcej shortcodów, ale prawdopodobnie wskutek błędu w WordPressie jego użycie jest pogmatwane. Generalnie rozsądne jest pisanie oddzielnej funkcji dla każdego shortcodu. Jeśli koniecznie chcecie jednak obsługiwać wiele shortcodów jedną funkcją możecie doczytać jak używać parametru $code w dokumentacji na wordpress.org. Aby nie komplikować tego przewodnika, my pominiemy ten element.

Po zmianach nasza funkcja wygląda następująco (zmienione linie wyróżniono)

function email_sc_func ( $atts, $content = '' ) {
    $atts = shortcode_atts(array(
                             'temat' => 'ogolne',
                             'styl' => 'text'
                          ), $atts);
    $temat = $atts['temat'];
    $styl  = $atts['styl'];
    if ($temat == 'handel') {
        $address = 'dzial_handlowy@example.com';
    } elseif ($temat == 'reklamacje') {
        $address = 'biuro_obslugi@example.com';
    } elseif ($temat == 'naprawa') {
        $address = 'serwis@example.com';
    } elseif ($temat == 'ogolne') {
        $address = 'sekretariat@example.com';
    }
    if ($styl == 'html')
    {
       $address = '<a href="mailto:' . $address . '">'.
           ($content ? $content : $address) .'</a>';
    }
    return $address;
}

Użyteczny przykład: przyciski w tekście

Przykład z emailem może być przydatny dla niektórych użytkowników, ale teraz, kiedy potrafimy już oprogramować własny shortcode, zrobimy coś użytecznego właściwie dla wszystkich.

Często chcielibyśmy umieścić w artykule elegancki przycisk, który może prowadzić do jakiejś zewnętrznej strony, do formularza rejestracyjnego  lub formularza do logowania, albo eksponować możliwość pobrania jakiegoś pliku. Najwygodniej zrealizować to własnie przy pomocy odpowiedniego shortcode.

Zacznijmy od napisania funkcji obsługującej shortcode [button]. Będzie ona akceptować cztery atrybuty:

  • size – rozmiar przycisku. Jeśli pominiemy ten parametr przycisk będzie normalny, ale możemy tez podać wartości small oraz big
  • color – barwa przycisku- możliwe wartości to red, orange, green, blue, pink, black. Domyślna wartość to blue
  • link – adres URL do którego ma linkować przycisk
  • window – jeśli podamy jakakolwiek wartość tego atrybutu, link zostanie otwarty w nowym oknie
function button_sc_func($atts, $content = null) {

    $atts = shortcode_atts(array('size' => '',
                                 'color' => 'blue',
                                 'link' => '#',
                                 'window' => ''), $atts);
    $size   = $atts['size'];
    $color  = $atts['color'];
    $link   = $atts['link'];
    $window = $atts['window'];
    $color_output = '';
    $class = '';
    if (  $color == "red"   OR $color == "orange" OR
          $color == "green" OR $color == "blue" OR
          $color == "pink"  OR $color == "black") {
        $class = $color;
    } else {
        $color_output = ' style="background:'.$color.
                        ';border-color:'.$color.'"';
    }
    $class_output = $class . ($size ? ' '.$size : '');
    if ( $window )
        $window = 'target="_blank" ';
        $output = '<a class="ex-button ' . $class_output .
            '" href="' . $link . '">'. $content . '</a>';
    return $output;
}

Musimy teraz zarejestrować funkcję dla shortcode

add_shortcode( 'button', 'button_sc_func' );

Nasza funkcja wymaga arkusza styli, aby przyciski wyglądały elegancko, a część funkcjonalności (kolory, rozmiar) są w ogóle zrealizowane przez odpowiednie klasy CSS.

a.ex-button {
    font-family: arial, helvetica, sans-serif;
    display: inline-block;
    line-height: 1em;
    padding: 6px 13px;
    margin:0 .6em 1.5em 0;
    border: 1px solid #4080b0;
    border-bottom-color: #bbbbbb;
    color: white !important;
    text-align: center;
    text-decoration: none;
    border-radius: 15px;
    background-color: #2280d8;
    box-shadow: inset 0 1px 0 hsla(0,100%,100%,.3),
                inset 0 0 2px hsla(0,100%,100%,.3),
                0 1px 2px hsla(0, 0%, 0%, .29);
}

a.ex-button.small { padding:4px 11px; font-size:0.9em;}
a.ex-button.big   { padding:7px 16px; font-size:1.4em;}

a.ex-button:hover  { text-decoration: none; opacity:0.85; }
a.ex-button:active { border-color: #225599;
                     box-shadow: inset 0 0 7px hsla(0,0%,0%,.3),
                                 0 1px 0 hsla(0, 100%, 100%, 1);
}

a.ex-button.red     { border-color: #af4040;
                      background-color: #d72323; }
a.ex-button.orange  { border-color: #af7440;
                      background-color: #d76b23; }
a.ex-button.green   { border-color: #478f00;
                      background-color: #5da11e; }
a.ex-button.blue    { border-color: #234dd6;
                      background-color: #2356d7; }
a.ex-button.pink    { border-color: #d623cb;
                      background-color: #d723d5; }
a.ex-button.black   { border-color: #111111;
                      background-color: #222222; }

Zapiszemy arkusz styli w kartotece motywu (albo naszego child theme), w podkartotece /css/, jako shortcode-button.css. Musimy teraz sprawić, żeby był on wczytywany gdy ładowane są strony naszego bloga. Moglibyśmy ręcznie wyedytywać plik odpowiedzialny za wyświetlenie nagłówka stron – zapewne header.php – ale bardziej elegancko jest dodać akcję w pliku functions.php. Ta metoda jest znacznie wygodniejsza jeśli używamy motywu dziedziczącego i zalecana przez twórców WordPressa.

Wystarczy, że napiszemy prostą funkcję z wykorzystaniem wp_enqueue_style(). Wykorzystamy ją w najprostszy sposób, ale pozwala ona też na budowanie zależności między arkuszami styli lub skryptami .JS (ładowanie jakiegoś pod warunkiem, że został załadowany inny), wersjonowanie skryptów i styli. W złożonych motywach i wtyczkach pozwala tez łatwo uniknąć wielokrotnego ich ładowania.

function my_enqueue_scripts() {
    wp_enqueue_style( 'shortcode-button',
		get_template_directory_uri().'/css/shortcode-button.css');
}

i dodamy ją jako akcję dla haka 'wp_enqueue_style'.

add_action( 'wp_enqueue_scripts', 'my_enqueue_scripts' );

I już, nasze przyciski są gotowe do użycia:

[ex_button color=red link=”javascript:alert(‚Kliknąłeś przycisk czerwony!’)”]Przycisk czerwony[/ex_button]
Przycisk czerwony

[ex_button color=orange link=”javascript:alert(‚Kliknąłeś przycisk pomarańczowy!’)”]Przycisk pomarańczowy[/ex_button]
Przycisk pomarańczowy

[ex_button color=green link=”javascript:alert(‚Kliknąłeś przycisk zielony!’)”]Przycisk zielony[/ex_button]
Przycisk zielony

[ex_button color=blue link=”javascript:alert(‚Kliknąłeś przycisk niebieski!’)”]Przycisk niebieski[/ex_button]
Przycisk niebieski

[ex_button color=pink link=”javascript:alert(‚Kliknąłeś przycisk różowy!’)”]Przycisk różowy[/ex_button]
Przycisk różowy

[ex_button color=black link=”javascript:alert(‚Kliknąłeś przycisk czarny!’)”]Przycisk czarny[/ex_button]
Przycisk czarny

[ex_button link=”javascript:alert(‚Kliknąłeś przycisk w kolorze domyślnym!’)”]Przycisk domyślny[/ex_button]
Przycisk domyślny

[ex_button size=small link=”javascript:alert(‚Kliknąłeś przycisk mały!’)”]Przycisk mały[/ex_button]
Przycisk mały

[ex_button size=big link=”javascript:alert(‚Kliknąłeś przycisk duży!’)”]Przycisk duży[/ex_button]
Przycisk duży

Komentarzy: 2

  1. Pingback: S | Tworzenie witryn interntowych

  2. Hej, a istnieje możliwość by do shortcodów przekazywać jakiś tekst który będzie potem użyty w funkcji? chciałbym zrobić shortcode jako przycisk do płatności, i by przekazalo mi do tego przycisku dane które wprowadzi gościu w formularzu