Niedziela wieczorem, 26 lipca. Przez formularz zgłoszeniowy wpada infekcja: strona klienta przekierowuje odwiedzających na obcą domenę, w panelu wisi konto administratora, którego nikt z zespołu nie zakładał. Klasyka przejęcia. Godzinę później drugie zgłoszenie, inny klient, ten sam obraz — świeży admin, podrzucony plugin, przekierowania. W poniedziałek doszły kolejne.

Niezależne strony przejęte w ten sam sposób w ciągu kilkunastu godzin to nie zbieg okoliczności. To fala. I ma nazwę: wp2shell — łańcuch dwóch podatności w core WordPressa, który pozwala nieuwierzytelnionemu atakującemu wykonać kod na serwerze. Bez logowania, bez żadnej wtyczki, na czystej instalacji.

(wiÄ™cej…)

Kilka tygodni temu trafiÅ‚ do mnie klient z pytaniem, które sÅ‚yszÄ™ regularnie od lat: czy mogÄ™ mu zresetować hasÅ‚o bezpoÅ›rednio w bazie, bo e-mail z resetem nie dochodzi. Standardowa procedura – wchodzisz do phpMyAdmin, UPDATE wp_users SET user_pass = MD5('nowehaslo') WHERE ID = 1, gotowe. Klient siÄ™ loguje, WordPress po cichu rehashuje hasÅ‚o silniejszym algorytmem, wszyscy sÄ… szczęśliwi.

Przy okazji zajrzaÅ‚em do kolumny user_pass w jego bazie. Mieszanina $P$B... i kilku czystych MD5. Klasyczny widok na instalacji, która chodziÅ‚a przez kilka lat bez wiÄ™kszej opieki. I pomyÅ›laÅ‚em sobie – za kilka tygodni to bÄ™dzie wyglÄ…dać inaczej. Bo WordPress 6.8, wydany w kwietniu 2025, zmieniÅ‚ coÅ›, na co część z nas czekaÅ‚a od dawna.

(wiÄ™cej…)

Od wczoraj zgłaszają się do nas klienci, którzy otrzymali nieco podejrzaną wiadomość e-mal. Wiadomość ta pochodzi niby od WordPress.org i informuje o wykrytej nowej podatności oraz jej łatce. Zachęca nawet do rozwiązania problemu. Czy to może być jakieś zagrożenie?

(wiÄ™cej…)

W naszej pracy spotykamy się codziennie z wieloma problemami,z którymi muszą zmagać się właściciele jak również klienci sklepów internetowych. Czasem są one niewidoczne dla szarego kupującego, ale czasem uderzają w niego z tak dużą siłą, że nie pozostaje on obojętny.

Frustracja klienta narasta, a po osiągnięciu apogeum kupujący zazwyczaj obwinia za to sklep internetowy. Tak też było w tym przypadku, ale czy słusznie?

(wiÄ™cej…)

W ciągu ostatnich dwóch tygodni trafiło do nas kilka sklepów zainfekowanych przez podatność we wtyczce WooCommerce Dynamic Pricing and Discounts, więc warto chyba napisać o tym kilka słów.

Wtyczka WooCommerce Dynamic Pricing and Discounts pochodząca z Envato jest jedną z wielu tego typu wtyczek. Służy ona do ustalania dynamicznych rabatów i przecen dla produktów na podstawie różnych warunków. Trudno mi do końca powiedzieć, dlaczego ktoś miałby wybrać akurat tę wtyczkę, bo istnieje kilka świetnych darmowych alternatyw. Nie zmienia to jednak faktu, że wtyczka ta została kupiona prawie 20 tys. razy, więc jak na wtyczkę sklepową, jest dość popularna.

Wtyczka powstała w 2014 roku i przeglądając jej changelog, można odnieść wrażenie, że jest ciągle rozwijana, usprawniana i nie ma w niej prawie żadnych błędów. Opisy zmian są jednak bardzo lakoniczne, a to nigdy nie wróży niczego dobrego.

I tak po 7 latach istnienia wtyczki, 18 sierpnia wykryto w niej krytyczną podatność, która pozwala każdemu wykonać import ustawień. Nie wymaga to nawet zbyt wiele trudu.

(wiÄ™cej…)

13 lipca 2021 we wtyczkach WooCommerce i WooCommerce Blocks wykryte zostały krytyczne podatności. Podatność została zgłoszona w ramach programu HackerOne.

Błąd zostaÅ‚ już poprawiony i opublikowane zostaÅ‚y poprawione wersje. Tak – poprawka zostaÅ‚a opublikowana tego samego dnia. JeÅ›li wiÄ™c używasz WooCommerce, to szybka aktualizacja do wersji 5.5.1 to dobry pomysÅ‚.

(wiÄ™cej…)

Być może sÅ‚yszaÅ‚eÅ› już kiedyÅ› powiedzenie, że ludzie dzielÄ… siÄ™ na tych, którzy robiÄ… backupy i na tych, którzy zacznÄ… je robić. Gdy jednak rozmawiam z klientami, czÄ™sto sÅ‚yszÄ™, że backupów wÅ‚asnej strony nie posiadajÄ…. Jedni w ogóle o tym nie pomyÅ›leli. Inni zakÅ‚adajÄ…, że hosting robi to za nich. I owszem – wiÄ™kszość hostingów domyÅ›lnie wykonuje automatycznie kopie zapasowe, aby klienci nie musieli siÄ™ tym martwić. Jednak czy aby na pewno tak jest?

(wiÄ™cej…)

Bieżący tydzień minął nam pod znakiem czyszczenia infekcji na stronach, a szybkie wyszukanie jej oznak w Google pokazuje, że jeszcze sporo osób się z nią zmierzy. Opiszmy więc, jak ta infekcja wyglądała i jak działa.

Jak wyglÄ…da atak

Doklejenie szkodliwego kodu do pliku header.php w motywie

W pliku header.php doklejany jest następujący fragment kodu:

(wiÄ™cej…)

No i doczekaliÅ›my siÄ™ – mamy pierwszÄ… (jeÅ›li tytuÅ‚ ten należy siÄ™ komu innemu, to piszcie w komentarzach) dużą podatność z polskiej wtyczce, a „nagroda” ta wÄ™druje do Flexible Checkout Fields od WP Desku. Przyjrzyjmy siÄ™, z czego owa podatność wynikaÅ‚a, jak zostaÅ‚a wykorzystana do atakowania stron i co zrobić, jeÅ›li Twoja strona zostaÅ‚a zaatakowana…

(wiÄ™cej…)

Ten tydzień mija nam pod znakiem ratowania stron, które padły ofiarą ataku wykorzystującego podatność we wtyczce ThemeGrill Demo Importer. Przyjrzyjmy się, jak do tego całego zamieszania doszło i pomyślmy, jak można się było uchronić.

Zacznijmy od początku. ThemeGrill to firma tworząca motywy. Ich wtyczka Demo Importer miała ponad 200 tys. aktywnych instalacji, a na początku lutego WebARX znalazł w niej podatność, która pozwala zresetować bazę danych i hasło administratora każdej stronie, która z tej wtyczki korzysta.

(wiÄ™cej…)

Podobno, jeÅ›li tytuÅ‚ artykuÅ‚u zawiera pytanie, to odpowiedź na nie zazwyczaj brzmi „Nie”. W przypadku tego zagadnienia jest jednak inaczej…

Tak, cache’owanie może pogorszyć wydajność strony. Może wrÄ™cz tÄ™ stronÄ™ zabić. PrzekonaÅ‚ siÄ™ o tym wÅ‚aÅ›ciciel pewnego sklepu internetowego.

Sytuacja, jakich wiele. Klient znalazł wykonawcę, zamówił sklep i go otrzymał. Strona zbudowana została na gotowym motywie. Gdy klient chciał jakąś dodatkową funkcjonalność, wykonawca znikał na jakiś czas, testował kilka wtyczek (wszystko na stronie produkcyjnej), a następnie zostawiał tę, która sprawdzała się najlepiej. Brzmi znajomo, prawda?

(wiÄ™cej…)

Na blogu dev.WPZlecenia pojawił się wczoraj artykuł sponsorowany pokazujący, jak nauczyć WordPressa przechowywania adresów IP logujących się użytkowników. Ponieważ komentarz do niego może być długi, a będzie miał też całkiem fajną wartość merytoryczną, to postanowiłem opublikować go tutaj. Zobaczymy sobie przy okazji, jak zły kod można krok po kroku poprawić.

Przede wszystkim trudno byÅ‚oby mi zaufać hostingowi, który wsadza mnie na minÄ™ i zapomina wspomnieć o ważnych konsekwencjach. Po pierwsze, jeÅ›li chcemy sobie zapisywać adres IP, to ze wzglÄ™du na RODO musimy poinformować o tym fakcie użytkowników, wpisać to w regulamin i politykÄ™ prywatnoÅ›ci, a przede wszystkim – uzasadnić potrzebÄ™ przechowywania tej wÅ‚aÅ›nie informacji (bo nie możemy zbierać i przetwarzać danych bez uzasadnienia).

Natomiast, jeÅ›li już przebrniemy przez caÅ‚e to prawnicze zamieszanie… Fajnie byÅ‚oby robić to kodem, który ma rÄ™ce i nogi.

(wiÄ™cej…)

Od jakiegoÅ› czasu o Gutenbergu robi siÄ™ coraz gÅ‚oÅ›niej. Także na WordUpach. NajczÄ™stsze pytanie, jakie pada w kontekÅ›cie prezentacji na ten temat brzmi „A czy ja muszÄ™ go używać? Czy można go bÄ™dzie jakoÅ› wyłączyć?”

Odpowiedzi sÅ‚yszaÅ‚em już różne… Å»e siÄ™ nie da, bo Gutenberg bÄ™dzie domyÅ›lnym edytorem i zostanie na nas wymuszone jego używanie. Å»e bÄ™dÄ… (już sÄ…) wtyczki, które pozwalajÄ… go wyłączyć. Itd…

Ale czy naprawdÄ™ pozostanie przy starym edytorze jest aż tak skomplikowane? Przecież mowa o WordPressie – na pewno jest do tego jakiÅ› filtr 😉

(wiÄ™cej…)

ContactForm7 to chyba najpopularniejsza wtyczka do Å‚atwego tworzenia formularzy, które można umieÅ›cić na stronie. Nie jest ona co prawda najwygodniejsza, najÅ‚adniejsza, ani najbardziej intuicyjna, ale z pewnoÅ›ciÄ… jest szybka, bezpieczna i speÅ‚nia swojÄ… rolÄ™. A co wiÄ™cej – dziÄ™ki przemyÅ›lanemu użyciu filtrów i akcji, pozwala na Å‚atwe modyfikacje i integracje.

Zacznijmy od najprostszej i chyba najczęściej spotykanej modyfikacji, czyli:

Jak zrobić coś dodatkowego (zapisać do pliku, zachować w bazie danych, utworzyć wpis, itd.) z przesłanym formularzem?

Dzięki temu, że autor wtyczki przewidział taką możliwość, dodanie takiej integracji jest stosunkowo proste. Spójrzmy na poniższy kod, który realizuje chyba najprostszą formę takiej integracji, a jednocześnie jest świetnym startem do budowania swoich, bardziej rozbudowanych wersji:

function prefiks_process_submitted_form_data( $contact_form ) {
    $submission = WPCF7_Submission::get_instance();
    if ( $submission ) {

        // Pobierz dane przesłane w formularzu
        $submitted_name = $submission->get_posted_data('your-name');
        $submitted_email = $submission->get_posted_data('your-email');
        $submitted_subject = $submission->get_posted_data('your-subject');
        $submitted_message = $submission->get_posted_data('your-message');
        // ...

        // Zrób coś z danymi (np. zapisz je do pliku)
        file_put_contents('cf7-log.txt', 'Data: ' . date('c') . "\n", FILE_APPEND);
        file_put_contents('cf7-log.txt', "Autor: {$submitted_name} <{$submitted_email}>\n", FILE_APPEND);
        file_put_contents('cf7-log.txt', 'Temat: ' . $submitted_subject . "\n", FILE_APPEND);
        file_put_contents('cf7-log.txt', "Wiadomość:\n" . $submitted_message, FILE_APPEND);
        file_put_contents('cf7-log.txt', "\n--------------------\n", FILE_APPEND);
    }
}
add_action( 'wpcf7_before_send_mail', 'prefiks_process_submitted_form_data' );

(wiÄ™cej…)

Tym razem pytanie od znajomego otrzymane bezpoÅ›rednio. Mam jednak wrażenie, że z tym problemem spotkać można siÄ™ dość czÄ™sto, a dotyczy ono modyfikowania liczby wpisów wyÅ›wietlanych na stronie w zależnoÅ›ci od tego, na jakiej stronie aktualnie jesteÅ›my. Ale po kolei – zacznijmy od pytania:

Na stronie głównej 4 wpisy wyświetlam w sliderze, a potem resztę normalnie. Co zrobić, żeby paginacja działała poprawnie?

Podejrzewam, że przyda się kilka dodatkowych wyjaśnień. Na czym dokładnie polegał problem? Otóż na stronie listy wpisów wyświetlane było po 9 wpisów. Na stronie głównej bloga, wyświetlać miał się slider, a w nim 4 najnowsze wpisy, a poniżej 9 następnych wpisów (razem 13). Gdy przechodziliśmy na stronę drugą, to niektóre wpisy wyświetlały się ponownie.

Jak to naprawić? Prosto – musimy wytÅ‚umaczyć WordPressowi, ile wpisów gdzie chcemy wyÅ›wietlać. A możemy to zrobić tak:

function prefiks_change_posts_number_on_home( $query ) {
    if ( is_home() && $query->is_main_query() ) {
        $posts_per_page = get_query_var('posts_per_page', get_option('posts_per_page'));  // <- domyślna liczba wpisów do wyświetlenia
        $additional_posts = 4;  // <- liczba dodatkowych wpisów na pierwszej stronie

        if ( get_query_var('paged') < 2 ) {
            $query->set( 'posts_per_page', $posts_per_page + $additional_posts );
        } else {
            $query->set( 'offset', $additional_posts + ( get_query_var( 'paged' ) - 1 ) * $posts_per_page );
        }
    }
}
add_action( 'pre_get_posts', 'prefiks_change_posts_number_on_home' );

(wiÄ™cej…)

Dzisiaj na jednej z grup supoprtowych pojawiło się następujące pytanie:

Czy da się jakoś zmienić domyślne ustawienia galerii? Chciałbym mieć na start ustawione 4 kolumny oraz linkowanie do pliku, a nie strony załącznika.

No właśnie, da się? Oczywiście, że się da, a potrzebujemy w tym celu poniższych dwóch funkcji:

function prefiks_print_media_templates() {
    ?>
    <script>
        jQuery(document).ready(function() {
            _.extend(wp.media.galleryDefaults, {
                columns: '4',
                link: 'file',
            });
        });
    </script>
    <?php
}
add_action('print_media_templates', 'prefiks_print_media_templates');

function prefiks_shortcode_atts_gallery($out, $pairs, $atts) {
    if ( ! array_key_exists('columns', $atts) || ! intval( $atts['columns'] ) ) {
        $out['columns'] = 4;
    }

    if ( ! array_key_exists('link', $atts) ) {
        $out['link'] = 'file';
    }

    return $out;
}
add_filter('shortcode_atts_gallery', 'prefiks_shortcode_atts_gallery', 10, 3);

(wiÄ™cej…)

Dzisiaj na Facebookowej grupie WordPress PL pojawiło się następujące pytanie:

… potrzebujÄ™ plugin, który bez różnicy czy hasÅ‚o bÄ™dzie wpisywane z dużych czy z maÅ‚ych liter, bÄ™dzie otwieraÅ‚ dostÄ™p do danego wpisu, widziaÅ‚ ktoÅ› może coÅ› takiego? …

Na pierwszy rzut oka takie rozwiÄ…zanie może wydawać siÄ™ kiepskim pomysÅ‚em – przecież po to ustawiamy hasÅ‚o, żeby dostanie siÄ™ do wpisu nie byÅ‚o zbyt proste, a ignorujÄ…c wielkość liter, dość znacznie zmniejszamy zÅ‚ożoność hasÅ‚a. Ale… przecież ta zÅ‚ożoność nadal pozostanie caÅ‚kiem spora, a poza tym, hasÅ‚o do wpisu to nie to samo, co hasÅ‚o do panelu administracyjnego.

Jeśli więc rzeczywiście mamy z tym problem i możemy w ten sposób ułatwić życie naszych czytelników, to czemu by nie spróbować? Tym bardziej, że wcale nie będzie to nas kosztowało tak wiele wysiłku.

Wystarczy użyć poniższego kodu (tym razem musimy użyć aż dwóch funkcji):

function prefiks_uppercase_post_password_before_hashing() {
    if ( isset($_POST['post_password']) && ! empty($_POST['post_password']) ) {
        $_POST['post_password'] = mb_strtoupper($_POST['post_password']);
    }
}
add_action( 'login_form_postpass', 'prefiks_uppercase_post_password_before_hashing' );

function prefiks_uppercase_post_password_before_saving($data, $postarr) {
    if ( array_key_exists('post_password', $data) && ! empty($data['post_password']) ) {
        $data['post_password'] = mb_strtoupper($data['post_password']);
    }
    return $data;
}
add_filter( 'wp_insert_post_data', 'prefiks_uppercase_post_password_before_saving', 10, 2 );

(wiÄ™cej…)

JeÅ›li używasz WordPressa dÅ‚użej niż miesiÄ…c, to pewnie przynajmniej raz dowiedziaÅ‚eÅ› siÄ™ o jakiejÅ› aktualizacji – wtyczki, motywu, albo WordPressa. Oprogramowanie jest rozwijane, pojawiajÄ… siÄ™ nowe funkcje, wykrywane sÄ… błędy, które nastÄ™pnie sÄ… poprawiane. W ciÄ…gu ostatnich 12 miesiÄ™cy sam WordPress zmieniaÅ‚ wersjÄ™ 14 razy, choć dziÄ™ki aktualizacjom automatycznym, część z nich mogÅ‚eÅ› przeoczyć (WordPress wykonaÅ‚ je za Ciebie).

Do tego, aby aktualizować zawsze i to jak najszybciej nawołują zazwyczaj autorzy, blogi i serwisy newsowe, a także Twój WordPress, który o aktualizacjach przypomina na każdym kroku i zachęca do nich informując, że to tylko jedno kliknięcie.

JeÅ›li dodatkowo uÅ›wiadomisz sobie, że znakomita wiÄ™kszość kodu zwiÄ…zanego z WordPressem rozwijana jest jawnie – czyli każdy ma dostÄ™p do kodu poszczególnych wersji, a w wiÄ™kszoÅ›ci przypadków także do informacji o zawartych w nich poprawkach (czyli o błędach zawartych w wersjach poprzednich), to chęć jak najszybszej aktualizacji powinna być wrÄ™cz naturalna.

Tyle w teorii. A jak to wyglÄ…da w praktyce?

(wiÄ™cej…)

Wyobraźmy sobie, że tworzymy nieco bardziej rozbudowany serwis, w którym użytkownicy mogÄ… siÄ™ rejestrować. Niekoniecznie jednak chcemy, aby byli oni Å›wiadomi, że serwis bazuje na WordPressie, albo chcemy wzbogacić i uprzyjemnić ich doÅ›wiadczenie i stworzyć specjalny panel administracyjny. Tak czy inaczej nie chcemy, aby „szwÄ™dali” siÄ™ nam po panelu administracyjnym WordPressa.

Żeby nie rozmieniać się na drobne, załóżmy, że zalogowanych użytkowników, którzy mają określoną rolę (w naszym przypadku subscriber, chcemy przekierowywać na określoną stronę (naszserwis.pl/uzytkownik/). I taką właśnie funkcjonalność realizuje poniższy kod:

function prefiks_restrict_wpadmin_access() {
    if ( ! defined('DOING_AJAX') || ! DOING_AJAX ) {
        $user = wp_get_current_user();

        if ( in_array('subscriber', $user->roles) ) {
            wp_redirect( site_url( '/uzytkownik/' ) );  // <- dostosuj swoich potrzeb
            die;
        }
    }
}
add_action( 'admin_init', 'prefiks_restrict_wpadmin_access' );

(wiÄ™cej…)

Gdy korzystamy z parametru s WP_Query, WordPress wyszuka wpisów, które zawierajÄ… podane sÅ‚owa w tytule lub treÅ›ci. Zdarza siÄ™ jednak, że chcemy wyszukiwać jedynie po tytule (bo jest to w danej chwili bardziej intuicyjne – np. jeÅ›li tworzymy pole z automatycznym podpowiadaniem tytuÅ‚u wpisu).

Poniższy kod pozwoli nam osiągnąć właśnie taki efekt.

function prefiks_search_by_title_only( $search, $query ) {
    global $wpdb;

    if ( empty( $search ) ) {
        return $search;
    }
    $q = $wp_query->query_vars;
    $n = ! empty( $q['exact'] ) ? '' : '%';

    $search = $searchand = '';

    foreach ( (array) $q['search_terms'] as $term ) {
        $term = esc_sql( like_escape( $term ) );
        $search .= "{$searchand}($wpdb->posts.post_title LIKE '{$n}{$term}{$n}')";
        $searchand = ' AND ';
    }

    if ( ! empty( $search ) ) {
        $search = " AND ({$search}) ";
        if ( ! is_user_logged_in() ) {
            $search .= " AND ($wpdb->posts.post_password = '') ";
        }
    }
    return $search;
}
add_filter( 'posts_search', 'prefiks_search_by_title_only' );

(wiÄ™cej…)

Czy zdarzyło Ci się kiedyś, że na stronie z rozbudowanym drzewem kategorii, chciałeś ukryć wpisy z podkategorii w widoku archiwum danej kategorii? Z pytaniem tym spotykam się dość często, więc może warto pokazać, jak należy się za to zabrać.

Poniżej znajdziesz kod, który realizuje dokładnie takie zadanie:

function prefiks_exclude_subcategory_from_category_archive( $query ) {
    if ( !is_admin() && $query->is_main_query() && is_category() ) {
        $category_not_in = $query->get( 'category__not_in', array() );

        if ( $query->get('cat', false) ) {
            $query->set('tax_query', array( array(
                'taxonomy' => 'category',
                'operator' => 'IN',
                'terms' => $query->get('cat'),
                'include_children' => false,
            ) ));
        }
    }
}
add_filter( 'pre_get_posts', 'prefiks_exclude_subcategory_from_category_archive' );

(wiÄ™cej…)

Na pewno spotkaÅ‚eÅ› siÄ™ ze stronami lub motywami, które wyÅ›wietlajÄ…c listÄ™ wpisów, używajÄ… dla nich różnego wyglÄ…du. Na przykÅ‚ad pierwsze dwa artykuÅ‚y wyÅ›wietlane sÄ… jako duże zdjÄ™cie i tytuÅ‚, dwa nastÄ™pne jako tytuÅ‚, maÅ‚e zdjÄ™cie i zajawka, a pozostaÅ‚e – jako same tytuÅ‚y. Poniżej przykÅ‚ad takiego bloku listy artykułów z portalu gazeta.pl.

Przykład rozbitej pętli artykułów z serwisu gazeta.pl

Taki układ artykułów stosowany jest dość często i niestety równie często implementowany jest w nieprawidłowy/niewydajny sposób, co prowadzi do wielu zbędnych zapytań do bazy danych i spowolnienia działania strony. A jak zrobić to poprawnie i przy użyciu tylko jednej pętli?

(wiÄ™cej…)

Do płacenia za domeny pewnie każdy już przywykł tak samo, jak do corocznych faktur za hosting. Jestem wręcz pewien, że z bardzo dużym prawdopodobieństwem, domenę kupiłeś właśnie od swojej firmy hostingowej i nawet nie sprawdzałeś oferty konkurencji.

A szkoda, bo z mojego doÅ›wiadczenia wynika, że znakomita wiÄ™kszość osób za domenÄ™ przepÅ‚aca i to bardzo sÅ‚ono…

Czy jednak oszczÄ™dność na domenie nie bÄ™dzie wiÄ…zaÅ‚a siÄ™ z jakimiÅ› przykrymi skutkami? Wiemy przecież, że czÄ™sto nadmierne oszczÄ™dnoÅ›ci źle siÄ™ koÅ„czÄ…. Podejrzewam, że maÅ‚o kto bÄ™dzie dziÅ› próbowaÅ‚ nadmiernie oszczÄ™dzać na hostingu…

I tu mam dobrą wiadomość. Pomijając bardzo skrajne przypadki, dostawcy domen sprzedają nam dokładnie tę samą usługę o dokładnie tej samej jakości i dokładnie tych samych dodatkach.

Skąd więc tak duże różnice w cenie? Wynikają one głównie z rabatów, które dany dostawca posiada przy rejestracji domen oraz od jego marży.

Warto zatem zapoznać się z poniższym zestawieniem cen rejestracji i odnowienia domen.

(wiÄ™cej…)

Na forum i grupach WP czÄ™sto pojawia siÄ™ pytanie o to, jak sprawić, aby wpisy z wybranej kategorii nie pojawiaÅ‚y siÄ™ na stronie głównej. Jak to zrobić poprawnie? Wbrew pozorom nie jest to wcale takie trudne – realizuje to poniższy fragment kodu:

function prefiks_exclude_category_from_homepage( $query ) {
    if ( !is_admin() && $query->is_main_query() && is_home() ) {
        $category_not_in = $query->get( 'category__not_in', array() );

        if ( is_scalar($category_not_in) ) {
            $category_not_in = array( $category_not_in );
        } elseif ( !is_array($category_not_in) ) {
            $category_not_in = array();
        }

        $category_not_in[] = 3;  // <- zmień 3 na ID kategorii, którą chcesz ukryć

        $query->set( 'category__not_in', $category_not_in );
    }
}
add_filter( 'pre_get_posts', 'prefiks_exclude_category_from_homepage' );

(wiÄ™cej…)

Change consents