Elementor – jak stworzyć wÅ‚asny plugin dodajÄ…cy custom post
W tym poradniku stworzymy widget do naszego plugin, który dodawaÅ‚by custom post, okreÅ›lany w widget’cie oraz pola, które również wybieralibyÅ›my z poziomu Elementor. W poprzednim poradniku: WÅ‚asny plugin dodajÄ…cy widget do wtyczki Elementor stworzyliÅ›my plugin, dodajÄ…cy wÅ‚asne widget’y do wtyczki Elementor. BÄ™dzie to takie samo rozwiÄ…zanie jak w artykule REDO JSComposer Additional – plugin dodajÄ…cy widget do WPBakery tylko zamiast wtyczki WPBakery docelowÄ… wtyczkÄ… bÄ™dzie Elementor.
Zacznijmy pracÄ™ nad naszym pluginem dla Elementora dodajÄ…cego custom post
Tworzymy kolejny widget w folderze widgets i nazywamy go customPostRedo.php, który będzie przechowywał klasę CustomPostRedo.
Musimy wrócić do folderu głównego naszego pluginu i edytować plik main.php. Musimy wskazać Å›cieżkÄ™ do naszego widgetu i jego klasy w klasie głównej E_REDO. Å»eby to zrobić dopisujemy analogicznie jak przy widgetcie projekty.php – Å›cieżkÄ™ w require_once() oraz dodajemy Å›cieżkÄ™ do klasy CustomPostRedo w funkcji register_widgets().
1 2 3 4 5 6 7 8 9 10 11 12 | private function include_widgets_files() { require_once(__DIR__ . '/widgets/projekty.php'); require_once(__DIR__ . '/widgets/customPostRedo.php'); } public function register_widgets() { $this->include_widgets_files(); \Elementor\Plugin::instance()->widgets_manager->register_widget_type(new Widgets\Projekty()); \Elementor\Plugin::instance()->widgets_manager->register_widget_type(new Widgets\CustomPostRedo()); } |
Edycja pliku customPostRedo.php naszego pluginu
Gotowe. Przechodzimy do edycji naszego pliku customPostRedo.php. Nadajemy odpowiedniÄ… nazwÄ™ dla namespace oraz dodajemy Å›cieżki do odpowiednich klas, których bÄ™dziemy używać w naszym kodzie. Dodajemy sprawdzenie czy jest zdefiniowana staÅ‚a ABSPATH i nastÄ™pnie definiujemy nazwÄ™, naszej klasy CustomPostRedo dziedziczÄ…cej po klasie Widget_Base – klasa wtyczki Elementor.
1 2 3 4 5 6 7 | namespace REDO\Widgets; use Elementor\Widget_Base; use Elementor\Controls_Manager; use REDO\E_REDO; if (!defined('ABSPATH')) exit; class CustomPostRedo extends Widget_Base { } |
Rejestracja widget’u w pluginie Elementor
Przechodzimy do tworzenia klasy obsÅ‚ugujÄ…cej nasz widget – CustomPostRedo. Definiujemy kilka funkcji wbudowanych Elementora, nazywajÄ…cego nasz widget.
1 2 3 4 5 6 7 8 9 10 11 12 | public function get_name(){ return 'customPostRedo'; } public function get_title(){ return __('Custom Post REDO'); } public function get_icon() { return 'fa fa-eye'; } public function get_categories(){ return ['general']; } |
Przechodzimy do głównej funkcji _register_controls(), która pobierać bÄ™dzie jaki typ custom post’a chcemy wyÅ›wietlić oraz jakie pola posta chcemy otrzymać w widoku. Å»eby to otrzymać potrzebujemy pobrać do widgetu Elementora listÄ™ custom postów oraz ich pól a także pól wÅ‚asnych. BÄ™dziemy tutaj bazować na wbudowanej opcji get_option(’cptui_post_types’) oraz stworzonej w pliku main.php funkcji prepareCustomFields(). Pobranie listy typów postów jest analogiczne do tego jak tworzyliÅ›my to w artykule: REDO JSComposer Additional – dodawanie wÅ‚asnych widget’ów do WPBakery – część druga – tam wytÅ‚umaczone sÄ… funkcje oraz listy na których bÄ™dziemy pracować.
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 | protected function _register_controls() { $customPostList = get_option('cptui_post_types'); $_custom_posts = array(); $_custom_posts_params = array(); if ($customPostList) { foreach ($customPostList as $postList) { $_custom_posts_params[$postList["name"]] = $postList["label"]; $_custom_posts[$postList["name"]]["type"] = $postList["name"]; $_custom_posts[$postList["name"]]["label"] = $postList["label"]; $supportsArray = array_flip($postList["supports"]); foreach ($supportsArray as $key => $value) { $supportsArray[$key] = $key; } $_custom_posts[$postList["name"]]["supports"] = $supportsArray; } } $fields = E_REDO::prepareCustomFields(); $customFieldsList = array(); if ($fields) { foreach ($fields as $field) { $customFieldsList[$field["type"]]["customFields"] = $field["fields"]; } } } |
Mamy już przygotowaną listę z typami postów i ich pól. Tworzymy sekcję w naszym widgetcie i nadajemy odpowiedni label informujący o tym że będzie to sekcja do wyboru typu posta.
1 2 3 4 5 6 | $this->start_controls_section( 'custom-post', [ 'label' => 'Custom Post Type', 'Choose Post Type which you want to display', ] ); |
Wyświetlanie typów custom post w Elementor
Teraz możemy wyÅ›wietlić możliwe typy postów do wyboru. Trzeba pamiÄ™tać aby każda nazwa parametru byÅ‚a indywidualna i niepowtarzalna. JeÅ›li nazwy jakichkolwiek parametrów bÄ™dÄ… siÄ™ powtarzać – nasz widget nie zadziaÅ‚a. Ważne jest aby odpowiednio nazwać nasz parametr, aby później można byÅ‚o operować na nich (zgodna musi być identyfikacja każdego parametru, żebyÅ›my wiedzieli za co on odpowiada). Å»eby wyÅ›wietlić typy postów posÅ‚ugujemy siÄ™ listÄ… $_custom_posts_params dla, której w pÄ™tli foreach dodajemy osobny radio-button, za pomocÄ… funkcji elementor add_control(). Definiujemy nazwÄ™ parametru – ’post-type’.$key – do tablicy przekaże nam – ’post-type-typ custom posta’ – co bÄ™dzie zawsze indywidualnÄ… nazwÄ… dla każdego typu posta. W typie posta korzystamy z typu CHOOSE dziedziczonego z klasy Controls_Manager – typ ten jest jednoznaczny z radio-button. W tablicy options dodajemy wartość $key z naszej listy.
1 2 3 4 5 6 7 8 9 10 11 12 13 | foreach ($_custom_posts_params as $key => $value) { $this->add_control( 'post_type-'.$key, [ 'label' => $value, 'type' => \Elementor\Controls_Manager::CHOOSE, 'default' => '', 'options' => [ $key => __($key), ], ] ); } |
Teraz należy zamknąć sekcję dla typu custom postów.
1 | $this->end_controls_section(); |
Kolejne sekcje naszego widgetu bÄ™dÄ… tworzone w pÄ™tli foreach dla wartoÅ›ci tablicy $_custom_posts przechowujÄ…cej typ posta oraz dla każdego typu posta typy pól możliwych do wyÅ›wietlenia. WewnÄ…trz pÄ™tli definiujemy sekcjÄ™ dla każdego typu posta, przechowujÄ…cÄ… typy pól. Typy pól bÄ™dziemy przechowyweać w liÅ›cie $custom_params dla której za pomocÄ… pÄ™tli foreach przypisujemy odpowiednie radio-button’y w stworzonej sekcji.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | $this->start_controls_section( $key .'-fields', [ 'label' => $value["label"] . ' Fields', 'Chose additional fields', ] ); $custom_params = $value["supports"]; foreach ($custom_params as $pkey => $pvalue) { $this->add_control( 'post_field-'.$key .'-' . $pvalue, [ 'label' => $pvalue, 'type' => \Elementor\Controls_Manager::CHOOSE, 'default' => '', 'options' => [ $pkey => __($pvalue), ], ] ); } $this->end_controls_section(); |
W tej samej pÄ™tli dla list $_custom_posts tworzymy kolejne sekcje dla pól wÅ‚asnych – indywidualnie dla każdego typu posta.
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 | foreach ($customFieldsList as $fkey => $fvalue) { if ($fkey == $value["type"]) { $customList = $fvalue["customFields"]; foreach ($customList as $ck => $cv) { $customList[$ck] = $ck; } $this->start_controls_section( $key . 'custom-fields', [ 'label' => $value["label"] . ' Custom Fields', 'Chose additional fields', ] ); foreach ($customList as $ckey) { $this->add_control( 'customfield-'. $key . '-' . $ckey, [ 'label' => $ckey, 'type' => \Elementor\Controls_Manager::CHOOSE, 'default' => '', 'options' => [ $ckey => __($ckey), ], ] ); } $this->end_controls_section(); } } |
Całość kodu funkcji _register_controls() :
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 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | protected function _register_controls() { $customPostList = get_option('cptui_post_types'); $_custom_posts = array(); $_custom_posts_params = array(); if ($customPostList) { foreach ($customPostList as $postList) { $_custom_posts_params[$postList["name"]] = $postList["label"]; $_custom_posts[$postList["name"]]["type"] = $postList["name"]; $_custom_posts[$postList["name"]]["label"] = $postList["label"]; $supportsArray = array_flip($postList["supports"]); foreach ($supportsArray as $key => $value) { $supportsArray[$key] = $key; } $_custom_posts[$postList["name"]]["supports"] = $supportsArray; } } $fields = E_REDO::prepareCustomFields(); $customFieldsList = array(); if ($fields) { foreach ($fields as $field) { $customFieldsList[$field["type"]]["customFields"] = $field["fields"]; } } $this->start_controls_section( 'custom-post', [ 'label' => 'Custom Post Type', 'Choose Post Type which you want to display', ] ); foreach ($_custom_posts_params as $key => $value) { $this->add_control( 'post_type-'.$key, [ 'label' => $value, 'type' => \Elementor\Controls_Manager::CHOOSE, 'default' => '', 'options' => [ $key => __($key), ], ] ); } $this->end_controls_section(); foreach ($_custom_posts as $key => $value) { $this->start_controls_section( $key .'-fields', [ 'label' => $value["label"] . ' Fields', 'Chose additional fields', ] ); $custom_params = $value["supports"]; foreach ($custom_params as $pkey => $pvalue) { $this->add_control( 'post_field-'.$key .'-' . $pvalue, [ 'label' => $pvalue, 'type' => \Elementor\Controls_Manager::CHOOSE, 'default' => '', 'options' => [ $pkey => __($pvalue), ], ] ); } $this->end_controls_section(); foreach ($customFieldsList as $fkey => $fvalue) { if ($fkey == $value["type"]) { $customList = $fvalue["customFields"]; foreach ($customList as $ck => $cv) { $customList[$ck] = $ck; } $this->start_controls_section( $key . 'custom-fields', [ 'label' => $value["label"] . ' Custom Fields', 'Chose additional fields', ] ); foreach ($customList as $ckey) { $this->add_control( 'customfield-'. $key . '-' . $ckey, [ 'label' => $ckey, 'type' => \Elementor\Controls_Manager::CHOOSE, 'default' => '', 'options' => [ $ckey => __($ckey), ], ] ); } $this->end_controls_section(); } } } } |
Otrzymaliśmy widok w elementorze zawierający wszystkie sekcje przechowujące odpowiednie wartości:
Teraz chcielibyÅ›my aby wybrane w widgecie wartoÅ›ci wyÅ›wietlić w widoku. WyÅ›wietlanie bÄ™dzie bardzo podobne jak w przypadku widgetu dla WPBakery. RóżnicÄ… bÄ™dzie operowanie nie na tablicy $atts jak w przypadku WPBakery a na tablicy $settings, którÄ… uzupeÅ‚niamy za pomocÄ… funkcji get_settings_for_display() – funkcji Elementora, zwracajÄ…cej parametry widgetu oraz ich wartoÅ›ci. Widok przekazywany bÄ™dzie w funkcji render().
1 2 3 | protected function render() { $settings = $this->get_settings_for_display(); } |
Pobieramy listÄ™ typów postów wybranych w widgetcie. Tworzymy pustÄ… tablicÄ™ $postTypes do której przekażemy typy postów. Za pomocÄ… pÄ™tli foreach przeszukujemy tablicÄ™ $settings. JeÅ›li klucz tablicy bÄ™dzie zawieraÅ‚ w części nazwy parametru ’post_type-’ i wartość dla danego klucza nie bÄ™dzie pusta – przekazujemy wartość do tablicy $postTypes.
1 2 3 4 5 6 7 | foreach($settings as $key => $value) { if (strpos($key, 'post_type-') !== false) { if(!empty($value)) { $postTypes[$value] = $value; } } } |
Tworzenie widoku końcowego listy custom post w Elementor
Pobraliśmy już listę typów postów pobranych z widgetu. Teraz przechodzimy do wyświetlenia dla nich widoku. Pierwszym krokiem jest sprawdzenie czy tablica $postTypes zawiera typy postów. Jeśli nie jest pusta dla każdego typu postu w tablicy wyświetlamy container oraz nazwę typu posta.
1 2 3 4 5 6 | <?php if (!empty($postTypes)) : ?> <?php foreach ($postTypes as $postType) : ?> <div class="post-type-container <?php echo $postType ?>"> <h2><?php echo $postType ?></h2> </div> <?php endforeach; endif; ?> |
Dla każdego typu posta pobieramy listÄ™ postów. W tablicy $args podajemy dla jakiego typu posta chcemy pobrać listÄ™ oraz ilość postów. W tablicy $query wykonujemy zapytanie WP_Query na tablicy $args. ListÄ™ postów zawartÄ… w $query przekazujemy do tablicy $postList, która bÄ™dzie przechowywać pobrane post’y.
1 2 3 4 5 6 7 | $args = array( 'post_type' => $postType, 'posts_per_page' => -1, 'orderby' => 'date' ); $query = new \WP_Query($args); $postList = ($query->posts); |
Teraz sprawdzamy czy $postList nie jest pusta. Jeśli nie to wyswietlamy dla każdego posta container oraz jego tytuł.
1 2 3 4 5 | if (!empty($postList)) : ?> <?php foreach ($postList as $myPost) : ?> <div class="post-container <?php echo $postType ?>"> <h2><?php echo $myPost->post_title; ?></h2> </div><?php endforeach; endif; |
Teraz należy przeszukać tablicÄ™ $settings i wyÅ›wietlić wybrane pola. Podobnie jak w przypadku typów postów za pomocÄ… funkcji strpos() sprawdzamy czy klucz zawiera w nazwie ’post-field’ lub ’customfield’ i odpowiednio wyÅ›wietlamy te pola. WyÅ›wietlanie przebiega analogicznie jak w przypadku WPBakery – odsyÅ‚am do tego artykuÅ‚u – link, jeÅ›li nie rozumiesz poniższego kodu.
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 | foreach($settings as $key => $value) { if (strpos($key, 'post_field-'.$postType) !== false) { if(!empty($value)) { ?> <div class="'post-field '<?php echo $postType . ' ' . $value ?>"> <?php if($value=="thumbnail") { echo get_the_post_thumbnail($myPost->ID, 'medium'); } else { echo get_post_field("post_".$value, $myPost->ID); }?> </div> <?php } } if (strpos($key, 'customfield-'.$postType) !== false) { ?> <div class="'post-field '<?php echo $postType . ' ' . $value ?>"> <?php $customField = get_field($value,$myPost->ID); if(is_array($customField)) { $size = 'thumbnail'; echo '<img src="' . esc_url( $customField['sizes'][$size] ) . '"/>'; } else { echo $customField; } ?> </div> <?php } |
Gotowe! Nasz plugin posiada widget dodajÄ…cy custom post w pluginie Elementor
Całość kodu pliku customPostRedo.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 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | <?php namespace REDO\Widgets; use Elementor\Widget_Base; use Elementor\Controls_Manager; use REDO\E_REDO; if (!defined('ABSPATH')) exit; class CustomPostRedo extends Widget_Base { public function get_name() { return 'customPostRedo'; } public function get_title() { return __('Custom Post REDO'); } public function get_icon() { return 'fa fa-eye'; } public function get_categories() { return ['general']; } protected function _register_controls() { $customPostList = get_option('cptui_post_types'); $_custom_posts = array(); $_custom_posts_params = array(); if ($customPostList) { foreach ($customPostList as $postList) { $_custom_posts_params[$postList["name"]] = $postList["label"]; $_custom_posts[$postList["name"]]["type"] = $postList["name"]; $_custom_posts[$postList["name"]]["label"] = $postList["label"]; $supportsArray = array_flip($postList["supports"]); foreach ($supportsArray as $key => $value) { $supportsArray[$key] = $key; } $_custom_posts[$postList["name"]]["supports"] = $supportsArray; } } $fields = E_REDO::prepareCustomFields(); $customFieldsList = array(); if ($fields) { foreach ($fields as $field) { $customFieldsList[$field["type"]]["customFields"] = $field["fields"]; } } $this->start_controls_section( 'custom-post', [ 'label' => 'Custom Post Type', 'Choose Post Type which you want to display', ] ); foreach ($_custom_posts_params as $key => $value) { $this->add_control( 'post_type-'.$key, [ 'label' => $value, 'type' => \Elementor\Controls_Manager::CHOOSE, 'default' => '', 'options' => [ $key => __($key), ], ] ); } $this->end_controls_section(); foreach ($_custom_posts as $key => $value) { $this->start_controls_section( $key .'-fields', [ 'label' => $value["label"] . ' Fields', 'Chose additional fields', ] ); $custom_params = $value["supports"]; foreach ($custom_params as $pkey => $pvalue) { $this->add_control( 'post_field-'.$key .'-' . $pvalue, [ 'label' => $pvalue, 'type' => \Elementor\Controls_Manager::CHOOSE, 'default' => '', 'options' => [ $pkey => __($pvalue), ], ] ); } $this->end_controls_section(); foreach ($customFieldsList as $fkey => $fvalue) { if ($fkey == $value["type"]) { $customList = $fvalue["customFields"]; foreach ($customList as $ck => $cv) { $customList[$ck] = $ck; } $this->start_controls_section( $key . 'custom-fields', [ 'label' => $value["label"] . ' Custom Fields', 'Chose additional fields', ] ); foreach ($customList as $ckey) { $this->add_control( 'customfield-'. $key . '-' . $ckey, [ 'label' => $ckey, 'type' => \Elementor\Controls_Manager::CHOOSE, 'default' => '', 'options' => [ $ckey => __($ckey), ], ] ); |