Nadawanie instancjom widżetów różnych stylistyk

Ostatnio tworząc widżety natrafiłem na problem nadawania instancjom widżetów różnych stylistyk. Jak w skrócie wyglądały moje wymagania:

  • Widżet musi posiadać kilka stylów w oddzielnych plikach CSS (dla łatwiejszego zarządzania nimi) – każdy styl powiązany jest z unikalną klasą CSS definiowaną w głównym kontenerze widżetu.
  • W zależności od konfiguracji instancji widżetów, wczytywane są tylko potrzebne pliki CSS (jeżeli w przyszłości widżet będzie posiadał 10 różnych dostępnych stylów to bez sensu byłoby wczytywać je wszystkie niezależnie od tego czego potrzebuje użytkownik)

Na czym polegał problem?

Otóż akcja dodawania styli CSS do sekcji <head> witryny (wp_enqueue_style) wykonywana jest wcześniej niż renderowanie widżetów, a co za tym idzie funkcja, która ma wybrać CSS do wczytania, nie ma dostępu do opcji w danej instancji widżetu.

Na szczęście rozwiązanie okazało się być bardzo proste:

Wystarczy wczytać parametry widżetu z tabeli opcji i sprawdzić jakie style CSS są potrzebne do wyświetlenia wszystkich instancji:

$instances = get_option('WIDGET_OPTION_NAME');
$loaded_files = array();
foreach($instances as $instance) {
    if(!in_array($instance['style'], $loaded_files)) {
       wp_register_style( 'WIDGET_PREFIX-' . $instance['style'], home_url() . '/wp-content/plugins/WIDGET_NAME/styles/'. $instance['style'] .'.css', array(), false, 'all');
        wp_enqueue_style('WIDGET_PREFIX-' . $instance['style']);
        array_push($loaded_files, $instance['style']);
    }
}

Jak widać powyższy kod wczytuje zawartość opcji widżetu (parametr style przechowuje nazwę pliku CSS do wczytania) oraz tworzy tablicę wczytanych już raz stylów CSS. Następnie sprawdzane są wszystkie instancje widżetu oraz wczytywane są brakujące pliki. Dzięki temu nie są wykonywane zbędne operacje kolejkowania już raz dodanych plików CSS.

Mała wada

Opisywane rozwiązanie ma jedną małą wadę – jeżeli niektóre instancje widżetu są wyświetlane tylko na określonych podstronach to i tak zostaną wczytane style dla wszystkich wykorzystywanych instancji. Teoretycznie można by to wszystko sprawdzić, przy czym takie sprawdzenie zależałoby od metody wykorzystywanej do wyświetlania widżetów na różnych podstronach. Dodatkowo zawsze nadmiar zapytań HTTP i kodu można zniwelować poprzez cache CSS (oczywiście zakładam tutaj scenariusz w którym użytkownik nie korzysta z wszystkich styli jak popadnie a jedynie z góra kilku wybranych).