Oficjalna wtyczka dla tinypng i tinyjpg dla WordPressa

Dosłownie tydzień temu na WordUpie w Warszawie mówiłem podczas swojej prezentacji, że wtyczka WP Smush.it zgrabnie wyręcza nas z optymalizowania rozmiaru grafik, ale niestety daleko jej jeżeli chodzi o wyniki kompresji do serwisów tinyjpg i tinypng. Dzisiaj odkryłem, że wczoraj pojawiła się oficjalna wtyczka dla tych serwisów.

Oczywiście nie ma róży bez kolców – miesięczny limit to 500 obrazków – po jego przekroczeniu zapłacimy 90 centów za każde kolejne 100 skompresowanych grafik.

Sama konfiguracja jest prosta – musimy zdobyć klucz API poprzez rejestrację na stronie API, a następnie wprowadzamy go w ustawieniach mediów WordPressa. Warto też określić, które obrazki powinny być kompresowane – dzięki temu oszczędzimy trochę darmowego limitu obrazków 🙂

tinypng-plugin-configuraton

Jeżeli chcemy szybko przetworzyć stare grafiki warto skorzystać z wtyczki Regenerate Thumbnails.

P.S. Tak wiem, że istniały inne wtyczki korzystające z tego API, ale osobiście najbardziej ufam oficjalnym rozwiązaniom 🙂

Chrome na OS X i debugowanie elementów pokazywanych przy zdarzeniu onmouseenter

Debugowanie styli CSS elementów, które pokazywane są z użyciem zdarzeń obsługiwanych przez JavaScript w Chrome jest uciążliwe, ponieważ w odróżnieniu od Firefoksa Chrome przy inspekcji elementów nie wywołuje zdarzeń do nich przypisanych.

Zupełnym przypadkiem odkryłem ostatnio ciekawą metodą debugowania takich elementów:

W skrócie:

  1. Uruchamiamy narzędzia developerskie
  2. Najeżdżamy na interesujący nas element
  3. Z użyciem skrótów klawiaturowych przełączamy się na sąsiedni ekran
  4. Przesuwamy kursor w dół tak żeby po powrocie na pierwotny ekran znajdował się on nad obszarem narzędzi developerskich
  5. Powracamy na pierwotny ekran
  6. Możemy debugować wybrany element

Całość bazuje na tym, że Chrome przy zmianie ekranów nie wywołuje zdarzeń związanych z kursorem podpiętych do elementów.

Możecie przetestować tę metodę na tym prostym demo.

P.S. Jeżeli znacie inną metodę aby rozwiązać problem debugowania tego typu elementów, dajcie znać w komentarzach – może istnieje jakaś flaga dla Chrome, która wywołuje eventy przy inspekcji elementów.

P.S.2. Powyższa metoda działa też w Safari

P.S.3. Ten sam sposób można wykorzystać do robienia screenshotów tego typu elementów np. programem Skitch, pod warunkiem, że zakończymy zaznaczanie obszaru screenshota na narzędziach developerskich.

Pobieranie produktu WooCommerce na bazie jego SKU z uwzględnieniem wielojęzyczności (WPML)

Dzisiaj krótki kawałek kodu, który może się przydać osobom posiadającym wielojęzyczne sklepy oparte na WooCommerce i WPML.

Otóż typowy kod zwracający produkt z WooCommerce na bazie jego SKU wygląda następująco:

function get_product_by_sku( $sku ) {
    global $wpdb;
    $product_id = $wpdb->get_var($wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_key='_sku' AND meta_value='%s' LIMIT 1", $sku));
    if ($product_id) {
        return new WC_Product($product_id);
    }
    return null;
}

Niestety nie uwzględnia on faktu iż WPML dla każdego produktu tworzy oddzielny rekord w tabeli postów, zatem otrzymamy produkty w jednym języku. Na szczęście możemy to naprawić i to w relatywnie prosty sposób, bo wystarczy zmodyfikować zapytanie:

function get_product_by_sku($sku) {
    global $wpdb;

    $product_id = $wpdb->get_var($wpdb->prepare("SELECT pm.post_id FROM ".$wpdb->postmeta." AS pm LEFT JOIN ".$wpdb->prefix."icl_translations AS tr ON pm.post_id = tr.element_id WHERE pm.meta_key='_sku' AND pm.meta_value='%s' AND tr.language_code = '".ICL_LANGUAGE_CODE."'", $sku));

    if($product_id) {
        return new WC_Product($product_id);
    }
    return null;
}

Powyższy kod działa podobnie do poprzedniego tylko podczas zapytania pobierane są dane z tabeli icl_translations, które pozwalają określić język wpisów powiązanych ze zwracanymi ID. Oczywiście najważniejszy jest ostatni warunek, który wybiera tylko ten rekord, który powiązany jest z obecnie wykorzystywanym językiem na stronie.

Jak w prosty sposób stworzyć cache dla shortcode’ów?

Czasami zdarza się, że shortcode przed zwróceniem efektów swojego działania musi wykonać dużo czasochłonnych operacji – np. jeżeli robimy shortcode, który zwraca statusy z Twittera dla określonego zapytania. W takim wypadku powinniśmy stworzyć cache z dwóch powodów:

  • pobranie informacji o statusach z Twittera wymaga pobrania tych danych z zewnętrznego serwera co może zająć sporo czasu
  • Twitter nakłada limity zapytań do swojego API

Na szczęście stworzenie prostego mechanizmu cache dla shortcode’ów jest w WordPressie bardzo proste.

Przyjmijmy, że nasz shortcode pobiera 3 różne parametry z wartościami domyślnymi i zamieniane na zmienne o odpowiednich nazwach w poniższy sposób:

$atts = shortcode_atts(array(
'param1' => 'lorem',
'param2' => 'ipsum',
'param3' => 'dolor'
), $atts);

extract($atts);

Zatem nasz shortcode ma poniższą składnię:

[txt][shortcode param1=”x” param2=”y” param3=”z”][/txt]

Pierwsza istotna obserwacja – nasz shortcode zwróci te same rezultaty dla takich samych wartości parametrów, zatem ciąg złożony z wartości tych parametów może śmiało posłużyć za identyfikator rezultatów danego shortcode’a. Do przechowania zawartości cache wykorzystamy Transients API.

Zatem nasz mechanizm cache będzie potrzebował dwóch kluczowych fragmentów kodu – zapisu i odczytu zawartości cache.

Zacznijmy od odczytu zawartości cache, gdyż ta operacja jest wykonywana przez rozpoczęciem operacji przez nasz shortcode:

$cache = get_transient(md5('PREFIX'.serialize($atts)));

if($cache) {
    return $cache;
}

Jak wspominałem – wykorzystujemy ciąg wartości parametrów jako identyfikator, do tego sugeruję dodać też jakiś własny prefix – dzięki temu zabezpieczymy się przed sytuacją gdy wszystkie parametry będą puste. Jeżeli cache dla danej konfiguracji istnieje to po prostu funkcja zwróci od razu zawartość cache, bez wykonywania dodatkowych operacji.

Następnie cały kod wyjściowy generowany przez shortcode umieszczamy w zmiennej np. $cache_output – jeżeli dobrze tworzycie swoje shortcode’y to zapewne taką zmienną z zawartością rezultatów już posiadacie (nie używacie w shortcode’ach echo, prawda?). Na koniec działania naszego shortcode’u możemy umieścić zawartość tej zmiennej w bazie danych:

set_transient(md5('PREFIX'.serialize($atts)) , $cache_output, 10 * 60);

Jak widać dzięki stworzeniu 6 dodatkowych linijek kodu mały gotowy mechanizm cache.

Osobiscie polecam do listy parametrów takiego shortcode’a dodać też parametr cache_time – dzięki temu będzie można określić czas przechowywania cache, a ostatnia linijka związana z cache zmieni się na:

set_transient(md5('PREFIX'.serialize($atts)) , $cache_output, $cache_time * 60);

Powyższe rozwiązanie ma tą zaletę, że w wypadku shortcode’ów w których istnieje niewielkie zróżnicowanie wartości parametrów do przechowywania rezultatów nawet z kilku tysięcy wpisów, będzie potrzeba kilku-kilkunastu rekordów w bazie danych. Natomiast sugeruję ostrożność w wypadku gdy przy podobnej liczbie wpisów mamy unikalne konfiguracje shortcode’ów – wtedy istnieje ryzyko, że ilość rekordów w bazie danych będzie zbliżona do liczby wpisów.