RSS
RSS

Jak nadpisać funkcję zdefiniowaną we wtyczce WordPressa?


Kategorie: Administracja, Tworzenie stron, WordPress, Wszystkie

3

WordPress posiada mechanizmy zwane filtrami i hakami, których można używać do zmiany sposobu działania funkcji zdefiniowanych np. we wtyczkach.

Nie zawsze jednak jest możliwe użycie tego mechanizmu - często autor wtyczki po prostu go nie przewidział lub należałoby wycofać jedną funkcję, by móc zarejestrować swoją z zagnieżdżeniem wielu innych funkcji tylko po to, by zmienić 1 linię kodu w jakiejś zagrzebanej funkcji pomocniczej. To jest skomplikowane i powoduje, że przy pierwszej lepszej aktualizacji i tak wtyczka nie będzie działać poprawnie, skoro znaczną część jej kodu zapisujemy na stałe np. w pliku functions.php motywu.

Nadpisywanie funkcji powinno zaś być możliwie odporne na przyszłe aktualizacje wtyczki.

Na szczęście da się to zrobić.

Co musi mieć wtyczka?

Wtyczka powinna mieć przed deklaracją każdej funkcji określenie:

if(!function_exists('NAZWA_FUNKCJI')){
function NAZWA_FUNKCJI(){
//ciało funkcji
}
}

Bez tego określenia w zasadzie wtyczka nie powinna wcale się włączyć i powinna powodować Fatal Error, jako że wtyczki w WordPressie najpierw ładowane są w sandboxie i w praktyce nawet jeśli w kodzie funkcja o danej nazwie nie została jeszcze zdefiniowana, to przez to, jak działa WordPress, będzie ona ładowana dwukrotnie (a przynajmniej tak czytałem). Z tego względu również funkcja nadpisująca oryginalną musi sprawdzać, czy nie została już zdefiniowana.

Zaprzeczone function_exists musi więc być obecne przed zarówno oryginalną definicją funkcji w kodzie wtyczki, jak i w definicji funkcji, która ma być użyta zamiast tej oryginalnej.

Jeśli w oryginalnym kodzie wtyczki tej formuły nie ma, można poprosić autora o aktualizację. Jeśli tego nie zrobi, pozostaje tylko nadpisanie oryginalnych plików wtyczki, które będzie każdorazowo wymazywane przy jej aktualizacji. W takiej sytuacji mimo wszystko warto rozważyć stosowanie metody podanej w ciągu dalszym artykułu, by swój kod trzymać w jednym miejscu, a w kodzie wtyczki dodawać przy każdej jej aktualizacji tylko if(!function_exists()){} dookoła funkcji oryginalnej.

Nadpisywanie funkcji wtyczki

Pierwszym, co przychodzi na myśl, jest zdefiniowanie własnego kodu funkcji o takiej samej nazwie w pliku functions.php motywu. To działa dla motywów potomnych, pozwalając na nadpisanie ich funkcji własnymi.

Nie działa to natomiast dla funkcji zdefiniowanych we wtyczkach, ponieważ wtyczki ładowane są przed ładowaniem plików motywu, w tym functions.php.

Niestety nie działa także zamieszczenie nowej deklaracji funkcji w ramach wtyczki Code Snippets, w której można zamieszczać fragmenty kodu PHP administrowalne z poziomu panelu WordPressa. Winna jest zapewne kolejność ładowania wtyczek i gdyby ją zmienić (co jest trochę złożone lub wymaga wtyczki Plugin Organizer), to by mogło zadziałać.

Modyfikowanie kolejności ładowania wtyczek nie wydaje się jednak dobrym pomysłem, do tego kod staje się zależny od 2 dodatkowych wtyczek.

Rozwiązanie problemu

Zgodnie ze schematem ładowania elementów systemu WordPress, przed załadowaniem kodów wtyczek można swój kod zamieścić tylko w dwóch miejscach - pliku wp-config.php, co wydaje się bardzo złym pomysłem (jest to plik konfiguracyjny, a nie przeznaczony na własny kod) oraz we wtyczkach niezbędnych (must-use plugins).

To drugie rozwiązanie jest odpowiednie. Wtyczki Must Use są ładowane przed normalnymi wtyczkami, nie da się ich wyłączyć ani automatycznie aktualizować. Wyświetlane są w sekcji Wtyczki panelu administracyjnego WordPressa, w podsekcji "Wymuszane". Aby wyłączyć i jednocześnie usunąć taką wtyczkę, trzeba usunąć jej plik z serwera.

Aby stworzyć wtyczkę Must Use, należy w katalogu wp-content utworzyć katalog o nazwie mu-plugins. Do niego należy wgrać swój plik PHP o dowolnej nazwie. Chociaż nie musi on mieć nagłówka typowej wtyczki WordPressa, dobrze jest go wprowadzić, by orientować się, do czego wtyczka służy.

Przykładowy kod pliku PHP:

<?php
/**
* Plugin Name: Nadpisywanie funkcji wtyczki Googlayers Hotel
* Plugin URI: https://sukcesstrony.pl
* Description: Nadpisuje określenie, które dni tygodnia są weekendowe, co jest zdefiniowane w jednej z funkcji wtyczki Goodlayers Hotel
* Version: 1.0.0
* Author: SukcesStrony.pl
* Author URI: https://sukcesstrony.pl
*/

if(!function_exists('NAZWA_FUNKCJI')){
function NAZWA_FUNKCJI(){
//ciało funkcji
}
}

Nazwa funkcji musi przy tym oczywiście być taka sama, jak nazwa funkcji oryginalnej, którą nadpisujemy.

Po wgraniu pliku na serwer wtyczka zadziała automatycznie.

Komentarze

Czyli w skrócie, iż z względu iż zazwyczaj nie da się nadpisać funkcji w pluginach.

Robisz swój plugin, który jest wcześniej inicjowali i nie pozwalasz pluginowi nadpisać swoją funkcję.

Czy coś pomieszałem?

Robimy swój plugin, ale specjalnego typu, który jest ładowany przed pluginem właściwym (tym, którego funkcję chcemy nadpisać). Plugin właściwy już nie definiuje swojej wersji funkcji, tylko używa tej, którą nasz plugin specjalnego typu zdefiniował.

Czyli dobrze to zrozumiałem.

Komentuj

Subscribe without commenting