Jesteś designerem lub programistą i masz pomysł na ciekawy motyw WordPress, który chciałbyś następnie sprzedać? Być może masz już nawet gotowy produkt ale nie masz pomysłu jak zadbać o doświadczenie użytkownika, który powinien w łatwy sposób móc zainstalować motyw na swojej stronie wraz ze wszystkimi ustawieniami, treścią demo i pluginami. W tym tutorialu przedstawię sposób na łatwy import treści i ustawień, który stosuje we własnych produktach. Przygotowałem też darmowy motyw potomny, który zawiera cały kod omawiany w tym tutorialu i który będziesz mógł łatwo dostosować do swoich potrzeb.
Czego będziesz potrzebował
- własny motyw bazowy lub potomny, który chcesz sprzedawać
- darmowe pluginy: One Click Demo import, Widget Importer & Exporter ,Customizer Export/Import
- skonfigurowana i wypełniona treścią strona demo oparta na WordPress
W tutorialu wykorzystam przygotowany wcześniej motyw potomny Kadence Theme, który zawiera komplet omawianego w artykule kodu. Na końcu znajdziesz formularz do bezpłatnego pobrania motywu.
Co chcemy osiągnąć
Użytkownik po zainstalowaniu Twojego motywu powinien w łatwy sposób pobrać wszystkie niezbędne zasoby, dzięki którym jego strona będzie wyglądała dokładnie tak, jak widział to w wersji demo. Możemy tu wymienić następujące elementy:
- Pluginy niezbędne do działania strony (np. jeżeli wykorzystujesz wtyczkę do formularzy – powinna zostać zainstalowana zanim użytkownik zainstaluje demo
- Treść i jej struktura łącznie z menu. Mogą to być artykuły, produkty lub po prostu strony zbudowane z bloków
- Ustawienia wyglądu w Customizer (kolory, fonty)
- Widgety (coraz rzadziej używane, ale nie powinniśmy zapominać)
Oczywiście, możesz przygotować pliki exportu, napisać szczegółową instrukcję jak wykonać import wszystkich tych elementów. Nie jest to jednak najszybszy sposób, jest obarczony błędami po stronie użytkownika i kłóci się trochę z ideą produktu premium.
W tym artykulę przedstawię sposób na automatyzację całego procesu importu demo przez użytkownika przy użyciu wyłącznie darmowych rozwiązań. Zacznijmy więc od omówienia pluginów, które pozwolą na łatwe wykonanie każdego z tych kroków.
Automatyczna instalacja niezbędnych pluginów
Przede wszystkim zacznijmy od najważniejszej zasady: instalacja pluginów nie może się odbyć poza świadomością użytkownika. Pluginy nie mogą być włączone jako biblioteki do motywu. Pluginy powinny być zainstalowane tak jak każdy inny plugin w WordPress i aktualizowane. Inaczej stwarzasz zagrożenie dla bezpieczeństwa strony użytkownika.
Możemy tu wyróżnić 2 typy pluginów:
- Premium lub niedostępne w katalogu WordPress – jeżeli ich licencja na to pozwala możesz je redystrybuować ze swoim motywem
- Pluginy z katalogu WordPress – nie powinieneś ich kopiować do swojej paczki, powinny być pobrane bezpośrednio z repozytorium WordPress
Uniwersalnym rozwiązaniem dla obu tych typów jest biblioteka TGM Plugin Activation, którą możesz włączyć do swojego motywu (lub motywu potomnego). Dobrym miejscem do includowania biblioteki jest plik function.php. Konfiguracja biblioteki jest bardzo prosta i sprowadza się do przekazania w tablicy listy pluginów wymaganych i opcjonalnych.
<?php
/**
* Include the TGM_Plugin_Activation class.
*/
require_once get_stylesheet_directory() . '/libs/tgm-plugin-activation/class-tgm-plugin-activation.php';
add_action( 'tgmpa_register', 'rocksite_example_register_required_plugins' );
/**
* Register the required plugins for this theme.
*
* In this example, we register five plugins:
* - one included with the TGMPA library
* - two from an external source, one from an arbitrary source, one from a GitHub repository
* - two from the .org repo, where one demonstrates the use of the `is_callable` argument
*
* The variables passed to the `tgmpa()` function should be:
* - an array of plugin arrays;
* - optionally a configuration array.
* If you are not changing anything in the configuration array, you can remove the array and remove the
* variable from the function call: `tgmpa( $plugins );`.
* In that case, the TGMPA default settings will be used.
*
* This function is hooked into `tgmpa_register`, which is fired on the WP `init` action on priority 10.
*/
function rocksite_example_register_required_plugins() {
/*
* Array of plugin arrays. Required keys are name and slug.
* If the source is NOT from the .org repo, then source is also required.
*/
$plugins = array(
// This is an example of how to include a plugin bundled with a theme.
array(
'name' => 'Your External Plugin',
// The plugin name.
'slug' => 'your-external-plugin',
// The plugin slug (typically the folder name).
'source' => get_stylesheet_directory() . '/libs/tgm-plugin-activation/plugins/tgm-example-plugin.zip',
// The plugin source.
'required' => TRUE,
// If false, the plugin is only 'recommended' instead of required.
'version' => '',
// E.g. 1.0.0. If set, the active plugin must be this version or higher. If the plugin version is higher than the plugin version installed, the user will be notified to update the plugin.
'force_activation' => FALSE,
// If true, plugin is activated upon theme activation and cannot be deactivated until theme switch.
'force_deactivation' => FALSE,
// If true, plugin is deactivated upon theme switch, useful for theme-specific plugins.
'external_url' => '',
// If set, overrides default API URL and points to an external URL.
'is_callable' => '',
// If set, this callable will be be checked for availability to determine if a plugin is active.
),
// This is an example of how to include a plugin from a GitHub repository in your theme.
// This presumes that the plugin code is based in the root of the GitHub repository
// and not in a subdirectory ('/src') of the repository.
array(
'name' => 'One Click Demo Import',
'slug' => 'one-click-demo-import',
'required' => TRUE,
),
// This is an example of how to include a plugin from the WordPress Plugin Repository.
array(
'name' => 'Contact Form 7',
'slug' => 'contact-form-7',
'required' => FALSE,
),
);
/*
* Array of configuration settings. Amend each line as needed.
*
* TGMPA will start providing localized text strings soon. If you already have translations of our standard
* strings available, please help us make TGMPA even better by giving us access to these translations or by
* sending in a pull-request with .po file(s) with the translations.
*
* Only uncomment the strings in the config array if you want to customize the strings.
*/
$config = array(
'id' => 'rocksite-example',
// Unique ID for hashing notices for multiple instances of TGMPA.
'default_path' => '',
// Default absolute path to bundled plugins.
'menu' => 'tgmpa-install-plugins',
// Menu slug.
'parent_slug' => 'themes.php',
// Parent menu slug.
'capability' => 'edit_theme_options',
// Capability needed to view plugin install page, should be a capability associated with the parent menu used.
'has_notices' => TRUE,
// Show admin notices or not.
'dismissable' => TRUE,
// If false, a user cannot dismiss the nag message.
'dismiss_msg' => '',
// If 'dismissable' is false, this message will be output at top of nag.
'is_automatic' => FALSE,
// Automatically activate plugins after installation or not.
'message' => '',
// Message to output right before the plugins table.
);
tgmpa( $plugins, $config );
}
Pomimo tego, że jest tu trochę kodu w bardzo łatwy sposób możesz namierzyć miejsca, w których możesz zdefiniować własną listę pluginów.
Zacznijmy od części, w której dodałem do listy wymaganych plugin dostępny w repozytorium WordPress:
// This is an example of how to include a plugin from the WordPress Plugin Repository.
array(
'name' => 'Contact Form 7',
'slug' => 'contact-form-7',
'required' => true,
),
Jak widzisz, wystarczą dosłownie 3 elementy w tablicy by dodać wymagalność pluginu Contact Form 7. Możesz w ten sposób dodać każdy plugin dostępnym w repozytorium WordPress – wystarczą nazwa i slug.
Druga tablica jest bardziej rozbudowana i musisz zadbać o to, by paczka znalazła się w odpowiednim miejscu wskazanym w tablicy:
// This is an example of how to include a plugin bundled with a theme.
array(
'name' => 'Your External Plugin',
// The plugin name.
'slug' => 'your-external-plugin',
// The plugin slug (typically the folder name).
'source' => get_stylesheet_directory() . '/libs/tgm-plugin-activation/plugins/tgm-example-plugin.zip',
// The plugin source.
'required' => TRUE,
// If false, the plugin is only 'recommended' instead of required.
'version' => '',
// E.g. 1.0.0. If set, the active plugin must be this version or higher. If the plugin version is higher than the plugin version installed, the user will be notified to update the plugin.
'force_activation' => FALSE,
// If true, plugin is activated upon theme activation and cannot be deactivated until theme switch.
'force_deactivation' => FALSE,
// If true, plugin is deactivated upon theme switch, useful for theme-specific plugins.
'external_url' => '',
// If set, overrides default API URL and points to an external URL.
'is_callable' => '',
// If set, this callable will be be checked for availability to determine if a plugin is active.
),
Dochodzi tu parametr odpowiedzialny za podanie źródła, z którego pobierany jest plugin – source. W tym przypadku plik zip do instalacji umieściłem wewnątrz katalogu z motywem.
Dzięki tej konfiguracji użytkownik w swoim panelu administracyjnym zobaczy następujący komunikat:
Użytkownik klikając Begin installing plugins może rozpocząć proces instalacji wszystkich niezbędnych pluginów.
Przygotowanie plików importu z treścią.
Zanim przejdziemy do właściwej konfiguracji importu ustawień i treści musisz przygotować odpowiednie pliki exportując dane zeswojego demo. W pierwszej kolejności użyjemy dobrze znanego narzędzia czyli wbudowanego w WordPress modułu do exportu.
Zakładam w tym miejscu, że masz już finalną wersję demo swojej docelowej strony ze wszystkimi treściami i ustawieniami.
Przejdź do zakładki Tools następnie export i stwórz plik z całą treścią:
Wygenerowany zostanie plik xml który za chwilę wykorzystasz w konfiguracji importu. W moim wypadku wygenerował się testwordpress.WordPress.2022-03-11.xml. Możesz dowolnie zmienić jego nazwę.
Export ustawień Customizera
W podobny sposób możesz stworzyć plik ze wszystkimi ustawieniami customizera. Ustawienia fontów, kolorów czy nagłówków powinny w automatyczny sposób zostać przekopiowane na stronę użytkownika. W tym przypadku konieczna jest instalacja dodatkowego pluginu: Customizer Export/Import
Bezpośrednio po instalacji przejdź do zakładki: Appearance->Customize a w samym Customizer wybierz Export Import. Pojawi się panel exportu ustawień:
Po kliknięciu na przycisk export wygenerowany zostanie plik .dat. Możesz nazwać go dowolnie, w moim wypadku jest to: theme-export.dat
Export ustawień Widgetów
Jeżeli w swoim motywie używasz widgetów warto również o ich szybkie przeniesienie na stronę użytkownika podczas instalacji motywu. Do wygenerowania pliku z ustawieniami również niezbędny jest dodatkowy plugin: Widget Importer & Exporter
Po zainstalowaniu pluginu przejdź do zakładki Tools -> Widget Importer & Exporter i używając przycisku Export Widgets stwórz plik exportu:
Otrzymasz plik o rozszerzeniu .wie któremu możesz dowolnie zmienić nazwę. W moim wypadku będzie to widgets.wie
Konfiguracja Pluginu One Click Demo import
Przygotowałeś pliki z niezbędną treścią i ustawieniami. Narzędziem, które pozwoli Ci na automatyzację procesu importu będzie jeden z najpopularniejszych pluginów przeznaczonych do tego celu – One Click Demo import. Jak zapewne pamiętasz przygotowałem już mój testowy motyw do automatycznej instalacji tego pluginu poprzez dodanie go do listy wymaganych pluginów:
array(
'name' => 'One Click Demo Import',
'slug' => 'one-click-demo-import',
'required' => TRUE,
),
Następnym krokiem jest konfiguracja pluginu w Twoim motywie, tak by plugin mógł bezpośrednio po instalacji zlokalizować twoje pliki z treścią i ustawieniami.
W pliku function.php swojego motywu dodaj następujący fragment kodu:
/**
* Define your demo paths
* @return array[]
* Change params by adding your paths/url
*/
function rocksite_example_import_files() {
return [
[
'import_file_name' => 'Demo Import 1',
'categories' => [ 'Category 1', 'Category 2' ],
'import_file_url' => 'http://www.your_domain.com/ocdi/demo-content.xml',
'import_widget_file_url' => 'http://www.your_domain.com/ocdi/widgets.json',
'import_customizer_file_url' => 'http://www.your_domain.com/ocdi/customizer.dat',
'import_preview_image_url' => 'http://www.your_domain.com/ocdi/preview_import_image1.jpg',
'preview_url' => 'http://www.your_domain.com/my-demo-1',
],
[
'import_file_name' => 'Demo Import 2',
'categories' => [ 'New category', 'Old category' ],
'import_file_url' => 'http://www.your_domain.com/ocdi/demo-content2.xml',
'import_widget_file_url' => 'http://www.your_domain.com/ocdi/widgets2.json',
'import_customizer_file_url' => 'http://www.your_domain.com/ocdi/customizer2.dat',
'import_preview_image_url' => 'http://www.your_domain.com/ocdi/preview_import_image2.jpg',
'preview_url' => 'http://www.your_domain.com/my-demo-2',
],
];
}
add_filter( 'ocdi/import_files', 'rocksite_example_import_files' );
Jak widzisz w tym miejscu definiujemy url do plików z treścią i ustawieniami. W tym konkretnym przypadku dodałem dwa oddzielne demo by pokazać, że możesz dodać dowolną ilość predefiniowanych demo. Oprócz linków do plików z treścią i ustawieniami możesz dowolnie zdefiniować nazwę demo oraz podać link do obrazka z podglądem. W przykładowym kodzie są testowe ścieżki.
Jak to wszystko działa?
W moim motywie Blockfold panel do importu demo dzięki tej prostej konfiguracji wygląda tak jak poniższym screenie. Panel Import Demo Data znajduje się w zakładce Appearance:
Użytkownik klikając na wybrany obrazek rozpoczyna proces instalacji demo:
Po krótkim czasie cała treść i ustawienia zostaną zaimportowane do czystej instalacji WordPress użytkownika Twojego motywu.
Na tym etapie jednak użytkownik będzie musiał ręcznie ustawić dwa elementy:
- Zdefiniowanie strony głównej
- Przypisanie menu do odpowiednich obszarów na stronie
Wszystkie te elementy: docelowa strona główna, menu mamy już w bazie. Musimy jednak dodać kilka linii kodu, by użytkownik nie był skazany na ręczną konfigurację.
Dodajemy automatyczną konfigurację Strony głównej i Menu
Zacznijmy od strony głównej. W moim przypadku tytuł strony głównej to News Magazine. Na liście stron wyraźnie widać, że jest ustawiona jako Front Page. Chciałbym, aby w trakcie importu treści przez użytkownika ta strona automatycznie została w ten sposób ustawiona:
Tu z pomocą przychodzi bogaty zestaw filtórw i akcji dostępnych w One Click Demo Import i które możemy wykorzystać podczas konfigurowania procesu importu. Akcją/hakiem która pozwoli nam na dokonanie automatycznych ustawień po imporcie jest pt-ocdi/after_import
Poniżej przykład jak możesz ją wykorzystać:
function rocksite_example_after_import( $selected_import ) {
_e( "blockfold import files were successfully downloaded!", 'blockfold' );
// Menus to Import and assign - you can remove or add as many as you want
// Use a static front page
$home = get_page_by_title( 'News Magazine' );
$blog = get_page_by_title( 'News' );
if ( isset( $home->ID ) && $home->ID > 0 ) {
update_option( 'page_on_front', $home->ID );
update_option( 'page_for_posts', $blog->ID );
update_option( 'show_on_front', 'page' );
}
}
add_action( 'pt-ocdi/after_import', 'rocksite_example_after_import' );
Kluczowym elementem jest zastąpienie tytułów stron właściwymi dla twojego demo. W moim wypadku te strone zdefiniowane są tak:
$home = get_page_by_title( 'News Magazine' );
$blog = get_page_by_title( 'News' );
W podobny sposób możemy ustawić obszary menu. Ja w swoim motywie zdefiniowałem główne menu nadając mu nazwę Main Menu. Ponieważ tworzę motyw potomny dla motywu Kadecne obszar, w którym powinienem wyświetlić główne menu w tym motywie nazywa się Primary.
Pobierzmy więc zawartość menu o nazwie Main Menu:
$primary_menu = get_term_by('name', 'Main Menu', 'nav_menu');
I przypiszemy je do odpowiedniego obszaru:
if (is_object($primary_menu)) {
set_theme_mod('nav_menu_locations', array(
'primary' => $primary_menu->term_id,
)
);
Pamiętaj, że podobnie jak w przypadku strony głównej musisz zastąpić te nazwy właściwymi dla swojego motywu.
Całość funkcji wykonywanej bezpośrednio po imporcie treści wygląda tak:
function rocksite_example_after_import($selected_import)
{
_e("Rocksite Example import files were successfully downloaded!", 'rocksite-example');
// Menus to Import and assign - you can remove or add as many as you want
$primary_menu = get_term_by('name', 'Main Menu', 'nav_menu');
if (is_object($primary_menu)) {
set_theme_mod('nav_menu_locations', array(
'primary' => $primary_menu->term_id,
)
);
}
// Use a static front page
$home = get_page_by_title('News Magazine');
$blog = get_page_by_title('News');
if (isset($home->ID) && $home->ID > 0) {
update_option('page_on_front', $home->ID);
update_option('page_for_posts', $blog->ID);
update_option('show_on_front', 'page');
}
}
add_action('pt-ocdi/after_import', 'rocksite_example_after_import');
Dzięki kilku dodatkowym fragmentom kodu obsłużyliśmy cały proces importu łącznie z konfiguracją. Użytkownik po zakończeniu procesu importu zobaczy kompletną stronę i będzie mógł od razu przystąpić do prac związanych z personalizacją. Całość procesu instalacji i kopiowania możesz zobaczyć na filmie instruktażowym do mojego motywu Blockfold: https://www.youtube.com/watch?v=nphPSbEKWco
Całość kodu w formie motywu potomnego Kadecne Theme możesz pobrać przy użyciu poniższego formularza.