Reklama sponsora

Woocommerce – plik użytkownika



Jakiś czas temu pracowałem na sklepem z foto obrazami gdzie użytkownik kupując obraz musiał wysłać zdjęcie jakie miało zostać wydrukowane. Wprawdzie projekt realizowałem na autorskim CMSie gdzie było to całkiem proste ponieważ mogłem edytować kod źródłowy CMSa. Podobny efekt można jednak otrzymać wczepiając się w Woocomerce. Postawiłem sobie świeży czysty WordPress na localhost, zainstalowałem woocommerce i możemy przejść do działania krok po kroku.

Woocommerce – Dodawanie pola w produkcie

Startujemy z całkowicie czystego WordPressa i Woocommerce więc nie ma za bardzo gdzie dodać kodu. Mamy co najmniej dwa wyjścia możemy zrobić motyw potomny i tam się wczepić w odpowiednie miejsca w pliku functions.php oraz skopiować odpowiednie pliki z woocommerce i wstawić je do naszego motywu potomnego co umożliwi nam bardziej bezpośrednią edycję widoków. Jest też druga opcja nieco trudniejsza czyli stworzenie wtyczki i tą drogą pójdziemy.

Podczas instalacji Woocommerce zaznaczyłem instalację motywu Motyw Storefront co powinno wiele uprościć i pominąć konieczność ingerencji w motyw.

Utworzymy sobie teraz wtyczkę o nazwie „user_product_custom_file”, zupełnie zgodnie z pierwszą częścią kursu „Własna wtyczka”. I tak wygląda nasz plik startowy:

Plik startowy

Najprościej pewnie będzie się podpiąć w miejscu przed buttonem dodawania do koszyka. Tak się składa że jest hook, który spełnia tę rolę czyli akcja „woocommerce_before_add_to_cart_button”. Jak znajduję tego typu zaczepy?

Po pierwsze wchodzę na stronę produktu i patrzę w źródle strony czy jest w formularzu jakiś charakterystyczny fragment kodu. W tym przypadku szczególnie zainteresowała mnie klasa buttona „single_add_to_cart_button”.

Jak znaleźć indywidualny element

Następnym krokiem jest wyszukanie nazwy tej klasy w Woocommerce. Po prostu przeszukuję folder wtyczki pod tym kątem tej nazwy.

Jak wyszukać nazwę klasy

Teraz jak już mamy odpowiedni zaczep dodajemy za jego pomocą pole z możliwością dodania pliku. W tym celu do głównego pliku wtyczki dodajemy kod taki jak ten:


add_action('woocommerce_before_add_to_cart_button','add_field_to_basket_form');
function add_field_to_basket_form(){
?>
<input type="file" name="user_file" value="" required="true"/> Plik użytkownika
<?php
}

Oczywiście w miejscu inputa na plik możemy dodać dowolne opakowania oraz klasy.

W efekcie otrzymamy najzwyklejszy input na plik tuż nad przyciskiem dodawania do koszyka.

woocomerce - pole na plik użytkownika

Przesyłanie pliku na serwer

Gdy już mamy możliwość załączenia pliku w formularzu produktu należałoby jakoś zapisać ten plik na serwerze. W tym miejscu zaprezentują najbardziej okrojoną opcję, w której po prostu zapisujemy plik na serwerze i podpinamy pod item w koszyku. W prawdziwym życiu trzeba dodać jeszcze dodatkowe zabezpieczenia w momencie uploadu pliku oraz rejestr plików. Jak zabezpieczyć się przed uploadem niepowołanych plików można bardzo łatwo odszukać, ale na czym polega rejestr plików?

Co pominęliśmy

Należy wziąć pod uwagę fakt że często użytkownicy dodają coś do koszyka po czym opuszczają stronę, dlatego też trzeba by w momencie uploadu pliku zapisać tę informację do bazy oraz ustawić datę ważności np na 24 godziny. Następnie wypadałoby napisać funkcję która po wygaśnięciu usuwa plik z serwera oraz wpis z bazy (prawdopodobnie ludzie nie kupują dłużej niż 24 godziny, żeby być dokładniejszym można sprawdzić czas przechowywania koszyka i dostosować ten czas dając jakiś zapas) w momencie złożenia zamówienia można by zmienić daty wygaśnięcia na jakiś bliżej nie określony termin albo po prostu oflagować żeby tych plików nie usuwać.

Ogólnie zabezpieczenia to temat na dłuższy artykuł albo i książkę, dlatego po prostu zapiszmy już ten plik.

Najprostszy upload

Tym razem szukamy miejsca gdzie odbieramy informację o dodaniu produktu do koszyka. Najprostszy upload pliku wygląda następująco:


add_filter( 'woocommerce_add_cart_item_data', 'user_file_to_cart_item', 10, 3 );
function user_file_to_cart_item( $cart_item_data, $product_id, $variation_id ) {
$dirPath = __DIR__.'/uploads/';
$target_file = $dirPath . basename($_FILES["user_file"]["name"]);
$uploadOk = 1;

if (!move_uploaded_file($_FILES["user_file"]["tmp_name"], $target_file)) {
$uploadOk = 0;
}

$fileToSave = [
'originalName' => $_FILES["user_file"]["name"]
];

if ( empty( $uploadOk ) ) {
return $cart_item_data;
}

$cart_item_data['fileToSave'] = $fileToSave;

return $cart_item_data;
}

W powyższym przykładzie wczepiamy się w filter „woocommerce_add_cart_item_data” gdzie wewnątrz naszej funkcji najpierw definiujemy ścieżkę gdzie mają się zapisywać pliki. W tym przypadku utworzyliśmy folder uploads w folderze naszej wtyczki.

Dalej określamy ścieżkę pliku. Ustawiamy zmienną $uploadOk na true, dalej powinny być wszelkie walidacje pliku co pominęliśmy.

Dalej po prostu wysyłamy plik na serwer.

Zmienna $fileToSave przechowuje informacje o pliku który wgrywamy. Słusznym rozwiązaniem byłoby dodatkowe zakodowanie nazwy pliku w celu utrudnienia dostępu do niego, wówczas w tablicy przechowywalibyśmy nazwę oryginalną i zakodowaną, powyżej można by też dodać wpis do bazy o takim pliku i tutaj dodać id rejestru plików. Jeśli upload się nie powiódł po prostu zwracamy dane jeśli się powiódł zapisujemy informację do itemu koszyka.

Wyświetlenie informacji w koszyku

Jesteśmy na etapie gdy dodaliśmy produkt do koszyka, wgraliśmy plik użytkownika i dopisaliśmy informację do itemu w koszyku. Może warto by wyświetlić link do pliku koszyku użytkownika, aby ten mógł sobie sprawdzić czy wysłał odpowiedni plik. Opcja szczególnie się przyda gdy w jakiś sposób manipulujemy nad plikiem, wówczas tutaj można by dodać odnośnik do wyniku.

Wykorzystamy sobie w tym celu woocommerce_get_item_data


add_filter( 'woocommerce_get_item_data', 'display_file_in_cart', 10, 2 );
function display_file_in_cart( $item_data, $cart_item ) {
if ( empty( $cart_item['fileToSave'] ) ) {
return $item_data;
}

$linkHtml = '<a href="'.plugin_dir_url('').'user_product_custom_file/uploads/'.$cart_item['fileToSave']['originalName'].'" target="_blank">Zobacz plik</a>';
$item_data[] = array(
'key' => __( 'Plik', 'userFile' ),
'value' => $linkHtml ,
'display' => '',
);

return $item_data;
}

Teraz tutaj przy każdym itemie sprawdzamy czy ma zapisaną informację o pliku. Jeśli nie ma to od razu wypluwamy item a jeśli ma to dodajemy to do informacji itemu i na koniec zwracamy item zaktualizowany o informację o pliku w efekcie otrzymujemy link do pliku otwierany w nowej kracie.

file in basket woocommerce

 

Zapis informacji o pliku do zamówienia

Nadszedł czas na zamówienie, tutaj trzeba się wpiąć w taki sposób aby informacja o załączonym w koszyku pliku do produktu zapisała się również do bazy aby później w kokpicie tę informację można było wyciągnąć. W tym celu wykorzystamy sobie akcję woocommerce_checkout_create_order_line_item.


add_action( 'woocommerce_checkout_create_order_line_item', 'save_user_file_to_order_items', 10, 4 );
function save_user_file_to_order_items( $item, $cart_item_key, $values, $order ) {
if ( empty( $values['fileToSave'] ) ) {
return;
}
$item->add_meta_data( __( 'userFile', 'userFile' ), $values['fileToSave'] );
}

Podczepiwszy się pod odpowiednią akcję otrzymujemy obiekt $item czyli pozycję w koszyku oraz wartości jakie wcześniej do niej przypisaliśmy w tablicy $values. Jeśli zapisaliśmy informacje o pliku w „fileToSave” to teraz możemy zapisać meta data do danego itemu za pomocą metody add_meta_data jak w przykładzie powyżej. Takich informacji możemy zapisać wiele tylko trzeba pamiętać żeby przypisać odpowiednie nazwy dla pól.

Wyciąganie informacji dodatkowych

Skoro mamy już zapis meta itemu, to teraz przydałoby się te informacje jakoś wyciągnąć w zamówieniu. W tym celu wykorzystamy akcję woocommerce_before_order_itemmeta dzięki temu wyciągana informacja powinna się pojawić pod linkowaną nazwą produktu a nad innymi meta. Warto zauważyć że WordPress ładnie parsuje obiekt w postaci tablicy a później możemy go wygodnie wyciągnąć z bazy.


add_action('woocommerce_before_order_itemmeta','display_user_file_in_order');
function display_user_file_in_order($item_id) {
$userFile = wc_get_order_item_meta($item_id, 'userFile');
if(!empty($userFile)){
$linkHtml = '<a href="'.plugin_dir_url('').'user_product_custom_file/uploads/'.$userFile['originalName'].'" target="_blank">Zobacz plik</a>';
?>
<p><?= $linkHtml;?></p>
<?php
}
}

Tutaj chyba nie ma za wiele do tłumaczenia, po prostu na początku funkcji wyciągamy wcześniej zapisaną tablicę, następnie sprawdzamy czy wartość nie jest pusta i tworzymy link do naszego pliku.

Podsumowanie

Powyżej przedstawione rozwiązanie daje niesamowite możliwości. Nie musimy w końcu ograniczać się tylko do pliku, w podobny sposób możemy przypisać do itemu koszyka – zamówienia dowolne informacje a więc dzieli nas tylko krok od utworzenia ciekawego kreatora produktów gdzie z odrobiną umiejętności w javascript możemy sobie zapisać różne parametry typu rozmiary kolory itd.

Żeby nie trzeba się było męczyć niepotrzebnie z kopiowaniem kody dołączam plik z wtyczką:

POBIERZ WTYCZKĘ USER_PRODUCT_CUSTOM_FILE

 


Dodaj komentarz

Twój adres email nie zostanie opublikowany. Wymagane pola są oznaczone *