Własny plugin dodający widget do wtyczki Elementor
W tym artykule dowiesz się jak stworzyć plugin dodający widget do wtyczki Elementor. W poprzednich poradnikach stworzyliśmy plugin REDO JSComposer Additional dodający widget do pluginu WPBakery i teraz analogicznie stworzymy taki sam plugin dla Elementora.
Elementor jest dostosowany na potrzeby tworzenia własnych widgetów i ma dużo bardziej przyjemne środowisko programistyczne do dodawania własnych rozszerzeń. Istnieje również wiele poradników jak stworzyć własny plugin tworzący nowe funkcjonalności do pluginu elementor. W tym artykule będziemy wzorować się na poradniku znajdującym się pod tym linkiem: https://www.youtube.com/watch?v=Ko9i153o_iU&t=454s, tutaj znajdziesz kod źródłowy tego poradnika: https://github.com/alexander-young/custom-elementor-widget/.
Poza tym tworząc plugin będziemy się wzorować na wcześniej stworzonym pluginie REDO JSComposer Additional, jego strukturze i funkcjonalnościach. Opis tego pluginu i proces jego tworzenia znajdziesz w poprzednich artykułach: Własna wtyczka dodająca widget do pluginu WPBakery oraz REDO JSComposer Additional – plugin dodający widget do WPBakery.
Zaczynajmy! Tworzymy plugin dodający widget’y do Elementor
Instalujemy darmową wersję wtyczki Elementor, którą znajdziesz tutaj oraz w zbiorze wtyczek WordPress.
Poza tym będą potrzebne nam wtyczki ACF oraz CPT UI, przedstawione one zostały we wcześniejszych artykułach: Tworzymy widok (template) dla custom post w WordPress oraz Advanced Custom Fields – własne typy pól WordPress. Będziemy wykorzystywać je do wyświetlania widoków poprzez widget’y, które będą zawierały wpisy własnego typu oraz pola własne. Jeśli będziesz wykorzystywać plugin do tworzenia widoków nieopierających się o te pluginy nie musisz ich instalować (uwzględnij w kodzie zmiany, jeśli nie zamierzasz korzystać z tych wtyczek).
Jeśli mamy już zainstalowany Elementor – tworzymy folder z naszym pluginem. Postępujemy analogicznie jak przy tworzeniu pluginu REDO JSComposer Additional. Zaczynamy od stworzenia folderu w folderze plugins naszego WordPress’a. Folder nazwiemy od nazwy nowego pluginu: REDO Elementor Additional – czyli folder będzie nosił nazwę – redo-elementor-additional.
Struktura folderu będzie podobna jak w poprzednim pluginie:
- index.php – będzie zawierał informacje o naszym pluginie oraz będzie zawierał odwołanie do pliku main.php oraz inicjował klasę E_REDO – odpowiadającą za obsługę naszego pluginu,
- main.php – plik obsługujący nasz plugin i zawierający odwołanie do folderu z naszymi widgetami,
- /widgets/ – folder zawierający pliki z naszymi widgetami, w tym poradniku pokażemy jak stworzyć widget wyświetlający post’y typu projekt – plik z widget’em będzie nazywał się projekt.php.
Przechodzimy do pliku index.php. Nazywamy nasz plugin, dodajemy opis, URL, autora, podobnie jak w przypadku pluginu dla WPBakery.
Elementor wymaga do poprawnego działania nadawania przestrzeni nazw namescape, która zapobiega powielaniu nazw klas – więcej o namespaces dowiesz się tutaj: https://www.phpdevs.pl/programowanie-obiektowe/9-przestrzenie-nazw. Nazywamy naszą namescape – REDO. Następnie przechodzimy do stworzenia pętli sprawdzającej czy jest zdefiniowana ABSPATH.
Za pomocą require_once() przypisujemy nasz plik main.php. Następnie tworzymy zmienną $redo_object zawierającego inicjację klasy E_REDO z pliku main.php.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?php /** * Plugin Name: REDO Elementor Additional * Description: Custom element added to Elementor * Plugin URI: https://redo-interactive.com/ * Version: 0.0.1 * Author: REDO * Author URI: https://redo-interactive.com/ * Text Domain: redo-elementor-additional */ namespace REDO; if ( ! defined( 'ABSPATH' ) ) { die( '-1' ); } require_once('main.php'); $redo_object = new E_REDO(); |
Teraz będziemy edytować plik main.php. Nadajemy taką samą nazwę namespace i znów sprawdzamy ABSPATH.
1 2 3 | <?php namespace REDO; if (!defined('ABSPATH')) exit; |
Tworzymy klasę E_REDO – w niej będzie zawierać się logika naszego pluginu.
1 | class E_REDO { } |
W klasie należy stworzyć konstruktor klasy za pomocą funkcji __construct(). W konstruktorze podobnie jak w przypadku REDO JSComposer Additional zawieramy hook’i.
- add_action(’init’, [$this, 'check_for_install’]) – dodajemy przy inicjowaniu naszego pluginu sprawdzanie czy są zainstalowane wtyczki potrzebne do poprawnego działania naszego pluginu czyli: ACF, CPT UI, Elementor,
- add_action(’elementor/widgets/widgets_registered’, [$this, 'register_widgets’])– tutaj rejestrujemy nasz widget za pomocą funkcji register_widgets().
Tworzymy funkcję include_widgets_files() dodającą plik z naszym widgetem projekty.php.
1 2 3 4 | private function include_widgets_files() { require_once(__DIR__ . '/widgets/projekty.php'); } |
Dodajemy funkcję function register_widgets() rejestrującą nasz widget do Elementor’a. Zawieramy w niej także funkcję include_widgets_files() dołączająca nasze pliki z folderu /widgets/. Nie zapominajmy dodawać '\’, który definiuje ścieżki do klas.
1 2 3 4 5 | public function register_widgets() { $this->include_widgets_files(); \Elementor\Plugin::instance()->widgets_manager->register_widget_type(new Widgets\Projekty()); } |
Następnie definiujemy naszą funkcję check_for_install(). Jest ona analogiczna do stworzonej funkcji check_for_install() w pluginie REDO JSComposer Additional.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | public function check_for_install() { E_REDO::show_redo_warning(); return; } private function show_redo_warning() { if (!defined('ELEMENTOR_VERSION')) { $link = "https://pl.wordpress.org/plugins/elementor/"; $plugin = "Elementor Page Builder"; ?> <div class="notice notice-warning is-dismissible"> <p>Please install <a href="<?php echo $link; ?>"><?php echo $plugin; ?></a> to use REDO JSComposer Additional.</p> </div> <?php } if (!defined('CPT_VERSION')) { $link = "https://pl.wordpress.org/plugins/custom-post-type-ui/"; $plugin = "Custom Post Type UI"; ?> <div class="notice notice-warning is-dismissible"> <p>Please install <a href="<?php echo $link; ?>"><?php echo $plugin; ?></a> to use REDO JSComposer Additional.</p> </div> <?php } if (!defined('ACF_VERSION')) { $link = "https://pl.wordpress.org/plugins/advanced-custom-fields/"; $plugin = "Advanced Custom Fields"; ?> <div class="notice notice-warning is-dismissible"> <p>Please install <a href="<?php echo $link; ?>"><?php echo $plugin; ?></a> to use REDO JSComposer Additional.</p> </div> <?php } } |
Całość kodu naszego pliku main.php:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | <?php namespace REDO; if (!defined('ABSPATH')) exit; class E_REDO { public function __construct() { add_action('init', [$this, 'check_for_install']); add_action('elementor/widgets/widgets_registered', [$this, 'register_widgets']); } private function include_widgets_files() { require_once(__DIR__ . '/widgets/projekty.php'); } public function register_widgets() { $this->include_widgets_files(); \Elementor\Plugin::instance()->widgets_manager->register_widget_type(new Widgets\Projekty()); } public function check_for_install() { E_REDO::show_redo_warning(); return; } private function show_redo_warning() { if (!defined('ELEMENTOR_VERSION')) { $link = "https://pl.wordpress.org/plugins/elementor/"; $plugin = "Elementor Page Builder"; ?> <div class="notice notice-warning is-dismissible"> <p>Please install <a href="<?php echo $link; ?>"><?php echo $plugin; ?></a> to use REDO JSComposer Additional.</p> </div> <?php } if (!defined('CPT_VERSION')) { $link = "https://pl.wordpress.org/plugins/custom-post-type-ui/"; $plugin = "Custom Post Type UI"; ?> <div class="notice notice-warning is-dismissible"> <p>Please install <a href="<?php echo $link; ?>"><?php echo $plugin; ?></a> to use REDO JSComposer Additional.</p> </div> <?php } if (!defined('ACF_VERSION')) { $link = "https://pl.wordpress.org/plugins/advanced-custom-fields/"; $plugin = "Advanced Custom Fields"; ?> <div class="notice notice-warning is-dismissible"> <p>Please install <a href="<?php echo $link; ?>"><?php echo $plugin; ?></a> to use REDO JSComposer Additional.</p> </div> <?php } } } |
Przechodzimy do edycji naszego widgetu – projekty.php.
Pierwszym krokiem jest odpowiednie nazewnictwo namespace oraz dodanie klas elementora, na których będziemy bazować. Sprawdzamy także ABSPATH.
1 2 3 4 5 | <?php namespace REDO\Widgets; use Elementor\Widget_Base; use Elementor\Controls_Manager; if ( ! defined( 'ABSPATH' ) ) exit; |
Tworzymy naszą klasę Projekty dziedziczącej za pomocą extends po klasie Widget_Base.
1 | class Projekty extends Widget_Base { } |
Odpowiednio ustawiamy nasz widget za pomocą wbudowanych funkcji elementora:
- get_name() – w tej sekcji nadajemy nazwę naszego widgetu (slug),
- get_title() – nadajemy Label naszego widgetu, widoczny będzie w panelu Elementora,
- get_icon() – tutaj ustawiamy ikonę naszego widgetu – w naszym przypadku będzie to oko jak w przypadku pluginu dla WPBakery. Możemy tutaj korzystać z ikon dostępnych w FontAwesome, ponieważ Elementor jest domyślnie kompatybilny z FontAwesome.
- get_categories() – ustawiamy kategorię w, której będzie wyświetlany nasz widget, wybieramy 'ogólne’,
- _register_controls() – tutaj nadajemy opcje do personalizacji naszego widgetu, jako, że naszym celem jest jedynie wyświetlenie projektów – dodajemy tylko label informującym za co odpowiada widget.
1 2 3 4 5 6 7 8 9 10 11 12 13 | public function get_name() { return 'projekty'; } public function get_title() { return __( 'Projekty' ); } public function get_icon() { return 'fa fa-eye'; } public function get_categories(){ return ['general']; } protected function _register_controls() {} |
Wewnątrz _register_controls() używamy funkcji:
- start_controls_section() – nadaje nazwę sekcji z personalizacją widgetu,
- add_control() – dodaje nasze ustawienia personalizacji,
- end_controls_section() – zamyka sekcję.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | protected function _register_controls() { $this->start_controls_section( 'section_content', [ 'label' => 'Settings', ] ); $this->add_control( 'projekty', [ 'label' => 'Projekty', 'type' => \Elementor\Controls_Manager::HEADING, 'default' => 'Display projects' ] ); $this->end_controls_section(); } |
Następnie używamy już tylko funkcji render() do wyświetlenia naszego widoku z projektami.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | protected function render(){ $args = array( 'post_type' => 'projekt', 'posts_per_page' => -1, 'orderby' => 'date' ); $projekty = new \WP_Query($args); ?> <!-- HTML DESIGN HERE --> <div class="projekty-container"> <h2 class="projekty-container-tytul">PROJEKTY</h2> <?php while ($projekty->have_posts()) : $projekty->the_post(); ?> <div class="projekt"> <h1 class="projekt-tytul"> <a href="<?php echo get_permalink(); ?>"> <?php echo get_the_title() ?> </a> </h1> <?php echo get_the_post_thumbnail(get_the_ID(), 'medium'); ?> </div> <?php endwhile; ?> </div> <!-- HTML END DESIGN HERE --> <?php } |
Całość kodu naszego widgetu:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | <?php namespace REDO\Widgets; use Elementor\Widget_Base; use Elementor\Controls_Manager; if ( ! defined( 'ABSPATH' ) ) exit; class Projekty extends Widget_Base { public function get_name() { return 'projekty'; } public function get_title() { return __( 'Projekty' ); } public function get_icon() { return 'fa fa-eye'; } public function get_categories(){ return ['general']; } protected function _register_controls() { $this->start_controls_section( 'section_content', [ 'label' => 'Settings', ] ); $this->add_control( 'projekty', [ 'label' => 'Projekty', 'type' => \Elementor\Controls_Manager::HEADING, 'default' => 'Display projects' ] ); $this->end_controls_section(); } protected function render(){ $args = array( 'post_type' => 'projekt', 'posts_per_page' => -1, 'orderby' => 'date' ); $projekty = new \WP_Query($args); ?> <!-- HTML DESIGN HERE --> <div class="projekty-container"> <h2 class="projekty-container-tytul">PROJEKTY</h2> <?php while ($projekty->have_posts()) : $projekty->the_post(); ?> <div class="projekt"> <h1 class="projekt-tytul"> <a href="<?php echo get_permalink(); ?>"> <?php echo get_the_title() ?> </a> </h1> <?php echo get_the_post_thumbnail(get_the_ID(), 'medium'); ?> </div> <?php endwhile; ?> </div> <!-- HTML END DESIGN HERE --> <?php } } |
Gotowe! Otrzymaliśmy działający plugin do dodawania własnych widgetów w pluginie Elementor.
Podsumowanie
Tworzenie pluginów kompatybilnych z innymi pluginami takimi jak WPBakery czy Elementor wymaga znajomości środowiska danego pluginu. Na szczęście zazwyczaj wtyczki posiadają dobrą dokumentacje, z której możemy zapoznać dane środowisko. W przypadku Elementora ważne jest aby nie zapominać o namespaces i przedrostkami klas '\’. Elementor jest dostosowany do dodawania własnych widgetów i posiada wiele ułatwień dla developerów. Sprawdź dokumentację: https://docs.elementor.com/