Znikające komentarze w WordPressie

Kategoria: Webmastering Data publikacji: 15 komentarzy

Podczas prac nad nową szatą graficzną mojego bloga napotkałem problem związany z działaniem systemu komentarzy WordPressa ujawniający się tylko w specyficznej konfiguracji. Przez wiele lat powodował on, że czytelnicy pisali ten sam komentarz kilka razy pod rząd. Gdy tylko udało mi się tę sprawę rozwiązać, aktualizacja systemu przyniosła kolejne niespodzianki.

Akt pierwszy: nie podałeś e-maila, to spadaj!

Domyślnie w systemie WordPress, w ustawieniach dyskusji, zaznaczona jest opcja „Autor komentarza musi wprowadzić swój podpis i email”, oprócz tego włączona jest ręczna moderacja. O ile to ostatnie jest dla mnie jak najbardziej zrozumiałe, to adresy e-mail moich odwiedzających naprawdę do niczego nie są mi potrzebne. Sam nie lubię podawać mojego adresu e-mail i jeśli to tylko możliwe, unikam tej konieczności.

WordPress pod wpisami wyświetla wyłącznie komentarze zatwierdzone przez moderatora — to oczywiste. Standardowo jednakże, gdy odwiedzający doda komentarz (wpisze jego treść i kliknie „wyślij”), w ciasteczkach zapisywane są jego dane (podany adres e-mail i podpis), a nowo dodany komentarz, mimo że jeszcze niezatwierdzony, pokazuje się pod wpisem wraz z adnotacją „komentarz oczekuje na akceptację moderatora”, coś w tym stylu. Dzięki takiemu zachowaniu użytkownik wie, że komentarz dotarł do miejsca docelowego, wszystko jest w porządku, ale ktoś go musi jeszcze zatwierdzić. Oczywiście niezatwierdzony komentarz pokazuje się wyłącznie użytkownikowi, który go dodał, inni czytelnicy go nie widzą do momentu akceptacji przez moderatora.

No i wszystko w porządku, ale problem pojawia się w momencie, gdy jednocześnie:

  • moderacja w komentarzach jest włączona,
  • podawanie adresu e-mail nie jest wymagane, by dodać komentarz,
  • użytkownik nie poda swojego adresu e-mail.

Wtedy, jeśli użytkownik nie poda swojego e-maila, po kliknięciu „wyślij”… nie dzieje się nic. Po prostu strona przeładowuje się bez żadnego komunikatu. Zdumiony użytkownik wpisuje treść komentarza po raz drugi, znowu dzieje się to samo, potem po raz trzeci, następnie znowu nic — irytacja sięga granic możliwości i odwiedzający rezygnuje.

Dlaczego tak się dzieje? Po nieudanych próbach znalezienia rozwiązania w Internecie, rozpocząłem przeglądanie kodu źródłowego WordPressa. Okazuje się, że system komentarzy używa adresu mailowego do zweryfikowania tożsamości użytkownika. Oznacza to, że jeśli odwiedzający bloga nie poda adresu e-mail, po kliknięciu przycisku „wyślij”, w kolejnym żądaniu HTTP, WordPress nie ma jak „skapnąć się”, że to dalej ta sama osoba, ten sam użytkownik, aby tylko dla niego wyświetlić jego własny, jeszcze niezatwierdzony komentarz z adnotacją o moderacji. Niestety WordPress nie robi w zamian kompletnie nic, aby poinformować użytkownika, że komentarz został przesłany pomyślnie.

Na moim blogu nie tyle nie trzeba, co nawet nie można podawać adresu e-mail przy dodawaniu komentarzy — usunąłem pole adresu e-mial, gdyż wasze e-maile naprawdę nie są mi potrzebne do życia. ;-) Zakasałem rękawy i po kilkudziesięciu minutach babrania się z bebechami systemu odnalazłem rozwiązanie. Oto ono:

add_filter('comments_template_query_args', function($comment_args){
	$comment_args['status'] = 'all';
	return $comment_args;
});

add_filter('comments_array', function($comments_flat){
	return array_filter($comments_flat, function($comment){
		$current_author = wp_get_current_commenter()['comment_author'];
		return ($comment->comment_approved == '1' or $comment->comment_author == $current_author);
	});
});

Powyższy kod można wrzucić do functions.php motywu (czego nie polecam) lub do własnej wtyczki systemowej (to rozwiązanie za to bardzo rekomenduję).

Powyższy kod robi dwie rzeczy:

  • sprawia, że w procesie przygotowywania listy komentarzy pod wpisem pobierane z bazy danych są nawet te komentarze, które nie są jeszcze zatwierdzone;
  • w drugiej kolejności — spośród niezatwierdzonych komentarzy odfiltrowuje (usuwa) te należące do autora innego niż aktualny.

Innymi słowy: kod powyżej sprawia, że WordPress do rozpoznania internauty (przy generowaniu listy komentarzy pod wpisem) używa nie tylko adresu e-mail, ale także podpisu.

To rozwiązanie nie jest bez wad. Złośliwy użytkownik może dodać komentarz, używając konkretnego pseudonimu, aby zobaczyć inne niezatwierdzone komentarze podpisane tym samym pseudonimem. W skali mojego bloga nie jest to jednak aż tak duży problem. Poza tym takie „obejście” i tak zawsze jest możliwe, nawet przy standardowym zachowaniu WordPressa, bowiem wystarczy w narzędziach deweloperskich zmodyfikować właściwie ciasteczko. Różnica polega tylko na tym, że adresy e-mail komentujących nie są widoczne, w przeciwieństwie do podpisów.

Szkoda tylko, że interfejs graficzny ustawień WordPressa w żaden sposób nie informuje o negatywnych skutkach właśnie takiej kombinacji ustawień.

Akt drugi: ochrona danych osobowych, od zaraz!

W pierwotnej wersji tego wpisu, która miała ukazać się wiele miesięcy temu, w tym miejscu następował już koniec. Jednakże moje plany pokrzyżowała aktualizacja WordPressa wydana w maju 2018 roku w związku z wprowadzeniem w życie nowych przepisów o ochronie danych osobowych, czyli słynnego RODO.

W aktualizacji, oznaczonej wersją 4.9.6, odrobinę zmieniono zachowanie systemu dodawania komentarzy pod wpisami. Ta „odrobina” w praktyce złamała kompatybilność wsteczną.

Jak wspomniałem wyżej, po dodaniu komentarza WordPress automatycznie tworzy ciasteczko z adresem e-mail i pseudonimem odwiedzającego, aby tylko dla niego wyświetlić już wysłany, ale jeszcze niezatwierdzony komentarz z adnotacją o moderacji. System używa również tych danych dla wygody użytkownika, uzupełniając pola formularza za niego przy pisaniu nowego komentarza.

W feralnej RODO-aktualizacji zmodyfikowano domyślny formularz dodawania komentarza do wpisu. Do dotychczasowych pól owego formularza (podpis, adres e-mail, opcjonalna strona WWW, treść komentarza, guzik „wyślij”) dodano nowy checkbox oznaczony etykietą „Zapamiętaj moje dane w tej przeglądarce podczas pisania kolejnych komentarzy”. Obecnie dopiero zaznaczenie tego (domyślnie niezaznaczonego) checkboksa powoduje zapisanie ciasteczka w przeglądarce użytkownika, a zatem również wyświetlenie informacji o tym, że jego komentarz oczekuje na akceptację.

Ujmując sprawę najprościej: jeśli użytkownik ręcznie i świadomie nie zaznaczy owego „ptaszka” przed wysłaniem komentarza, po ponownym przeładowaniu strony nie zostanie w żaden sposób poinformowany o pomyślnym zakończeniu procesu. Znowu: zdziwienie, ponowne próby dodania komentarza i ostatecznie — irytacja niczemu niewinnego użytkownika.

Jednak to nie wszystko. Domyślnie WordPress owego RODO-checkboksa nie pokazuje użytkownikowi wcale. Aby to zmienić, należy go łaskawie poprosić, zaznaczając w ustawieniach dyskusji opcję „Pokaż pole wyboru ciasteczka komentarzy” (łot de fak?!).

Nie zawsze jednak można rozwiązać problem w ten sposób. Sprawa jest zależna od używanego motywu. WordPress dostarcza gotową konstrukcję renderującą szablon formularza dodawania komentarza — mam tu na myśli funkcję comment_form(). Ze względu na jej ograniczenia, niektóre motywy graficzne w ogóle jej nie używają, a w zamian definiują swój własny kod formularza. Jako że WordPress nie ma nań wpływu, zaznaczenie wspomnianej opcji w ustawieniach dyskusji nic nie zmieni, jeśli akurat używasz takiego motywu. W takim przypadku należy checkbox (oczywiście domyślnie niezaznaczony, bo RODO) dodać ręcznie do kodu motywu, co wymaga wiedzy programistycznej. Oto kod skopiowany z rdzenia WordPressa.

<p class="comment-form-cookies-consent">
	<input id="wp-comment-cookies-consent" name="wp-comment-cookies-consent" type="checkbox" value="yes">
	<label for="wp-comment-cookies-consent">
		<?php echo __( 'Save my name, email, and website in this browser for the next time I comment.') ?>
	</label>
</p>

Niezależnie od tego, które z powyższych działań zostanie podjęte, użytkownik musi zaznaczyć durnego „ptaszka”, aby system, po zatwierdzeniu komentarza, zareagował w sposób intuicyjny.

Czy da się ten problem rozwiązać lepiej, inaczej niż zbędnymi checkboksami?

  • Można podpiąć się do jednej z akcji WordPressa uruchamianej po dodaniu komentarza, aby wyświetlić użytkownikowi zrozumiałą informację typu „komentarz został wysłany”, a potem przekierować go z powrotem do komentowanego wpisu. Na przykład tak:
    add_action('comment_post_redirect', function($location){
    	header('Refresh: 3, url=' . $location);
    	wp_die(
    		'<p>Komentarz został dodany i oczekuje na akceptację moderatora.</p>',
    		'Komentarz wysłano'
    	);
    });
  • Jeśli wolisz zignorować przepisy RODO, możesz wymusić na WordPressie tworzenie ciasteczka nawet wtedy, gdy użytkownik nie wyrazi na to wyraźnej zgody. W tym celu należy odpiąć funkcję tworzącą ciasteczko od właściwej akcji, a następnie wrzucić ją w obwolutę, w taki sposób, aby myślała, że użytkownik zgodę wyraził.
    remove_action('set_comment_cookies', 'wp_set_comment_cookies');
    add_action('set_comment_cookies', function(...$arguments){
    	$arguments[2] = true;
    	wp_set_comment_cookies(...$arguments);
    }, 10, 3);

Niezależnie od wybranego rozwiązania, powyższy kod można wrzucić do functions.php motywu lub jeszcze lepiej — do własnej wtyczki systemowej.

Aktualizacja 2023

Obecnie WordPress wyświetla użytkownikowi informację zwrotną po dodaniu komentarza nawet wtedy, gdy użytkownik nie wyrazi zgody na korzystanie z ciasteczek. Do tego celu wykorzy­stywany jest zestaw dodatkowych parametrów dokładanych do adresu strony w przekierowaniu zaraz po pomyślnym przesłaniu komentarza. Oznacza to, że opisane wyżej w tym artykule zmiany w ustawieniach i kodzie strony związane z ciasteczkami nie są potrzebne do zapewnienia użytkownikowi informacji zwrotnej po dodaniu komentarza…

…chyba, że twój blog na WordPressie nie wymaga podawania adresu e-mail do napisania komentarza. Niestety, nadal design sposobu działania mechaniki WordPressa stosuje adres e-mail jako identyfikator — gdy użytkownik nie poda adresu e-mail, nie dostanie żadnej informacji zwrotnej po przesłaniu formularza.

Poniżej zamieszczam nowy kod PHP, który integruje się z obecnie stosowanym w WordPressie podejściem, ale rozwiązuje problem braku adresu e-mail. Poniższy kod należy zastosować zamiast wszystkiego, co jest opisane wyżej w tym artykule.

add_filter('comments_array', function($comments_flat){
    $comment_id = $_GET['unapproved'] ?? null;
    $hash = $_GET['moderation-hash'] ?? null;

    if ($comment_id && $hash) {
        $comment = get_comment($comment_id);

        if (
            $comment
            && '0' == $comment->comment_approved
            && hash_equals($hash, wp_hash($comment->comment_date_gmt))
            && time() < strtotime($comment->comment_date_gmt . '+10 minutes')
        ) {
            $comments_flat[] = $comment;
        }
    }

    return $comments_flat;
});

add_filter('comment_post_redirect', function($location, $comment) {
    return add_query_arg([
        'unapproved' => $comment->comment_ID,
        'moderation-hash' => wp_hash($comment->comment_date_gmt),
    ], $location);
}, 10, 2);

Komentarze (15)

  1. stała Czytelniczka

    Nie myślałeś kiedyś Tomku przeprowadzić się na Bloggera? Ja odkąd to poczyniłam to zniknęły wszystkie moje webmasterowe problemy :) Obsługa jest tak banalnie prosta, że nie mam zamiaru już wracać do WP.

  2. Tomasz Gąsior

    Jestem programistą, lubię mieć pełną kontrolę nad kodem strony i sposobem działania witryny. Taką dowolność daje mi jedynie system CMS zainstalowany na własnym koncie hostingowym. Blogger może być dobry dla kogoś, kto się nie zna na sprawie i nie chce się znać. Ja wręcz przeciwnie — chcę w pełni decydować o moim serwisie.

  3. stała Czytelniczka

    Z tego, co widzę na Bloggerze też jest wgląd w kod i można tam nim manipulować.

  4. Monika Pałucka

    Cześć Tomku, dzięki za ten artykuł! Jestem początkującą blogerką jeśli chodzi o WP i mam problem. Googluje, ale nie znajduje odpowiedzi. Może Ty jesteś w stanie mi pomóc? Napisałam odpowiedź do mojego pierwszego komenatrza na stronie tutaj: https://panienglish.pl/2019/05/24/my-senior-moments/ i nie mam pojęcia dlaczego się on nie wyświetla? Widnieje jako zatwierdzony w kokpicie, ale go nie widać. Wiesz o co może chodzić? Ps. jestem z wykształcenia filologiem, więc jeśli chodzi o tworzenie strony (a robię to sama) jestem jak dziecko we mgle :) Please help!

  5. Tomasz Gąsior

    @Monika Pałucka
    Jak rozumiem blog należy do pani, napisała pani komentarz pod własnym postem, a potem odpowiedziała komentarzem na ten komentarz — i ten drugi komentarz będący odpowiedzią jest niewidoczny. Hmm. Nie mam pojęcia co to może być. Moje sugestie:
    — proszę wyłączyć adblock,
    — proszę wyłączyć wszystkie wtyczki w panelu WordPressa,
    — proszę zmienić motyw na jakiś domyślny (tzn. stworzony przez autorów WP: na przykład Twenty Nineteen).

  6. Monika Pałucka

    Bardzo dziękuję za odpowiedź. Tak to blog, który należy do mnie. Nie napisałam pierwszego komentarza – dodała go czytelniczka. Odpowiedziałam na niego – odpowiedź jest w komentarzach w kokpicie, ale nie wyświetla się na stronie. Próbowałam dwóch pierwszych opcji – niestety to nie podziałało. Mam ustawiony motyw domyślny „Higher Education” i nie chcę go zmieniać, bo wtedy strona straci pożądany przeze mnie wygląd. Być może coś w tym motywie trzeba ustawić, tylko nie mogę tego znaleźć. Jeśli ma pan pomysł jak mi pomóc, bardzo proszę o pomoc :) Pozdrawiam

  7. Tomasz Gąsior

    Miałem na myśli, aby zmieniła pani motyw na inny na chwilę, do celów diagnostycznych, a nie na stałe. Nie wyjaśniłem, bo takie diagnostyczne myślenie dla programisty jest normalnie, już niekoniecznie dla użytkownika końcowego. ;)

    Ponownie rzuciłem okiem na pani stronę. Jest błąd w motywie. Proszę go zgłosić autorowi. Jako workaround do momentu naprawienia błędu proszę wrzucić kod „.comment-list .children { display: initial; }” (bez cudzysłowów) do Wygląd -> Dostosuj -> Dodatkowy CSS.

  8. SpeX

    Wszystko fajnie, tylko niestety od strony komentarzy WP jest wygodny, tylko dla autora. Niestety, dla czytelnika „interakcja” zazwyczaj ogranicza się jedynie do powitalnego komentarza, bo potem nie jest powiadamiany o odpowiedzi na jego komentarz. Bo prawda można naprawić to poprzez odpowiednie wtyczki lub podmianę całych systemów komentarzy. Ale tam zawsze jest potrzebny mail jako kanał zwrotny.

  9. ToTemat

    A gdzie można znaleźć ten komunikat, lub jak go zmodyfikować aby samemu ułożyć jego treść? Chciałbym napisać go prościej ale id dokładniej, czy da się to zrobić bez wtyczki?

  10. Tomasz Gąsior

    Komunikat prawdopodobnie znajduje się w kodzie źródłowym twojego motywu. Musisz zmodyfikować kod renderujący listę komentarzy na twojej stronie, najlepiej za pomocą motywu potomnego (child theme).

  11. Ewa

    Dzień dobry,
    Też mam ten problem, ale z włączoną koniecznością podawania emaila. Zmieniam ustawienia dyskusji ale to nic nie daje, ma Pan pomysł jak z tego wybrnąć?
    Pozdrawiam

  12. Tomasz Gąsior

    Proszę spróbować zaznaczyć opcję „Pokaż pole wyboru ciasteczka w komentarzach, umożliwiając zapamiętanie autora komentarzy.”

Dodaj komentarz