Створення спеціального елемента керування вибором посилань CMB2 для WordPress
У цьому підручнику я розгляну, як можна створити спеціальний елемент керування для розширення функціональності CMB2 (Custom Meta Boxes 2) від WebDevStudios.
Я розробляю веб-сайти (і веб-додатки) за допомогою WordPress CMS (система керування вмістом), і коли з’явиться новий проект, ви можете гарантувати, що від мене виникне вимога розробити «Користувацькі мета-бокси», щоб користувач міг точно контролювати над вмістом і макетом сайтів.
Я детально розповім, як я створив CMB2 Control Link Picker для CMB2 (доступний у всіх хороших репозиторіях плагінів WordPress). Скріншот якого можна побачити нижче.
Елемент керування CMB2 «Вибір посилань» у дії
Засіб вибору посилань запускає вбудоване в WordPress діалогове вікно «Вставити/редагувати посилання», коли ви натискаєте кнопку «Вибрати». Це можна побачити на скріншоті нижче:
Натиснувши кнопку, ви зможете вибрати посилання (або додати власне)
Я впевнений, ви погодитесь, що такий елемент керування надзвичайно зручний, якщо ви хочете дати редакторам свого сайту можливість додавати посилання, а також шукати внутрішні посилання на WordPress, а не вирізати та вставляти посилання в посилання. поле.
Вступ / Історія
Для тих, хто не в курсі, метаполе знаходиться на екрані редактора публікації WordPress і, ймовірно, міститиме різні елементи керування формою (текстові поля, розкривні списки, прапорці тощо). Ці елементи керування дозволяють користувачам вашого веб-сайту легко змінювати спеціальний фрагмент тексту чи функції на сайті.

Приклад метабокса з різними елементами керування формою
WordPress дозволяє створювати мета-блоки за допомогою функцій (наприклад, [add_meta_box](https://developer.wordpress.org/reference/functions/add_meta_box/)), але створення мета-блоків у такий спосіб може бути тривалим процесом із великою кількістю повторень коду (особливо якщо ви хочете використовувати ті самі елементи керування формою в кількох проектах).
Чому CMB2?
Дехто з вас, можливо, чув про Advanced Custom Fields (ACF), який надає GUI (графічний інтерфейс користувача), який дозволяє створювати метабокси безпосередньо в WordPress.
На мою думку, ACF не є чудовим інструментом для будь-якого веб-рішення, яке масштабується. Плагін занадто сильно покладається на дані, які зберігаються в базі даних. Це викликає труднощі під час впровадження змін на сайт, оскільки ви не можете просто натиснути свій код і миттєво побачити зміни. Замість цього вам доведеться знову виконати роботу в різних середовищах розгортання (постановка, живе тощо). Тому нам знадобилося рішення, яке б дозволяло створювати метабокси програмно. Введіть CMB2.
Перш ніж ми прийняли CMB2, ми раніше використовували користувацькі мета-бокси HM від тих чудових людей із Human Made (які почалися як форк попередника CMB2 від WebDevStudio, «користувацькі мета-бокси»).
Нам сподобалися користувацькі мета-бокси HM, і за допомогою найпростіших фрагментів коду ми могли швидко створювати власні мета-бокси, щоб робити що завгодно!
Приклад розмітки користувацьких метабоксів HM (це розмітка для метабокса Instagram на першому знімку екрана)
Тож чому перехід на CMB2? Що ж, HM Custom Meta Boxes, на жаль, не викликав великої любові (я розмовляв з його провідним розробником, і він дуже-дуже зайнята людина), тоді як CMB2 рухався вперед із новими функціями, новими елементами керування, і він набув популярності у спільноті WordPress, де багато людей прийняли його та випустили плагіни для його розширення (включно з кількома нашими партнерськими агентствами).
Нарешті, як ви могли зрозуміти, працювати з CMB2 так само неймовірно просто, як ми звикли, оскільки обидві платформи мають спільного предка.
Підручник
Перш ніж ми почнемо, у кожного є свій власний набір ідеалів щодо того, як створити плагін WordPress, і я спробував чимало, однак підручник Тома Дж. Ноуелла про «Кореневу композицію в WordPress» повністю змінив мій спосіб роботи. Я вважаю, що його підхід чистий, простий, і це спрощує подальше обслуговування будь-якого плагіна. Якщо ви візьмете вихідний код плагіна Link Picker для CMB2, ви зможете побачити методи, яким він навчає на практиці.
Побудова форми
Щоб створити форму, яка рендерить Link Picker, перше, що нам потрібно зробити, це підключитися до cmb2_render_[control_name]дії. Оскільки я назвав цей елемент керування ‘link_picker’, ми можемо завершити хук так:
<?php
add_action( 'cmb2_render_link_picker', array( $this, 'cmb2_render_link_picker' ), 10, 5 );
`
Для тих із вас, хто не дуже розуміє add_actionгачок, він працює наступним чином:
- Перший аргумент
cmb2_render_link_picker– це ім’я хука, який ми хочемо підключити. - Другим аргументом
array( $this, 'cmb2_render_link_picker' )є функція, яку ми хочемо викликати під час виконання цього хука. Зауважте, що я загортаю це в масив із$thisпершим параметром, оскільки я викликаю функцію всередині класу. Якщо ви не працюєте з класами, ви можете просто використовувати назву функціїcmb2_render_link_picker.
3., —10це порядок, у якому ми хочемо запускати функцію (чим менше число, тим швидше вона запускається під час виклику дії). - Це
5кількість параметрів, які будуть передані функції, яку я викликаю (незабаром це стане зрозуміло).
Далі ми створюємо функцію, яка відображатиме форму:
<?php
public function cmb2_render_link_picker( $field, $value, $object_id, $object_type, $field_type_object) {
…
}
`
Я залишив «DocBlock» у коді вище, який описує, що робить кожен із параметрів, переданих у cmb2_render_link_picker()функцію.
Зверніть увагу, що моя функція починається з publicоголошення. Це знову тому, що я працюю в класі. Якщо ви не працюєте з класами, ви можете пропустити це.
Значення цього поля передається у функцію через $valueпараметр. У випадку цього поля ми будемо проходити через масив, оскільки наш елемент керування містить три окремі елементи:
- Текст
- URL
- Якщо посилання відкривається в новому вікні (чи ні)
Оскільки $valueне завжди встановлюється (наприклад, коли елемент керування відображається вперше), нам потрібно ініціалізувати його деякими значеннями за замовчуванням. Ми робимо це за допомогою наступного фрагмента коду:
<?php
$value = wp_parse_args(
$value,
array(
'text' => '',
'url' => '',
'blank' => 'false',) );
Потім ми можемо приступити до обробки форми. Ось приклад першого елемента керування введенням тексту:
<p>
<label for="<?php echo $field_type_object->_id( '_text' ); ?>'">
<?php echo esc_html( $field_type_object->_text( 'link_picker_text', 'Text') ); ?>
</label>
</p>
<?php
echo $field_type_object->input(
array(
'class' => 'cmb_text',
'name' => $field_type_object->_name( '[text]' ),
'id' => $field_type_object->_id( '_text' ),
'value' => $value['text'],) );
?>
Фу! Це виглядає трохи безладно, чи не так? Давайте розберемо це по рядках:
- Початковий тег абзацу.
- Початковий тег мітки для елемента керування, але з
forатрибутом, автоматично встановленим$field_type_object_idпараметром. Це автоматично створить ідентифікатор для елемента керування під час його відтворення. - Текст нашої мітки, створений з використанням тексту з масиву параметрів керування (або повертається до слова «Текст»).
- Закриваючий тег мітки
- Закриваючий тег абзацу.
- Запустіть оголошення PHP
- Використовуйте елемент керування введенням (частина
$field_type_objectдля створення вводу форми (типом за замовчуванням буде текст). - Запустіть масив параметрів
- Встановіть клас введення.
- Встановіть ім’я входу, знову використовуючи
$field_type_objectпомічник. - Встановіть ідентифікатор входу на той самий ідентифікатор, який було встановлено на тегу мітки.
- Отримайте значення з
$value, оскільки це масив, нам потрібен ключ «текст» для цього елемента керування. - Закрийте масив.
- Закрийте функцію введення.
- Закрийте декларацію PHP.
Розмітка поля форми URL-адреси майже така сама, лише для використання типів введення HTML5 ми можемо встановити додатковий параметр ‘type’ на ‘url’:
<?php
…
'type' => 'url',
…
Нарешті ми хочемо реалізувати спадне меню. Розмітка дуже знайома:
<?php
echo $field_type_object->select(
array(
'class' => 'cmb_dropdown',
'name' => $field_type_object->_name( '[blank]' ),
'id' => $field_type_object->_id( '_blank' ),
'options' => $blank_options,) );
Зауважте, що $field_type_objectфункція, яку ми використовуємо, призначена selectдля створення спадного списку. Також зауважте, що в рядку 6 ми маємо новий атрибут options. У нього ми передаємо рядок «параметрів». Це генерується до цього елемента керування таким чином:
<?php
$blank_options = '';
$blank_options .= '<option value="false" '. selected( $value['blank'], 'false', false) .'>Opens in same</option>';
$blank_options .= '<option value="true" '. selected( $value['blank'], 'true', false) .'>Opens in new</option>';
Тоді все, що нам потрібно зробити, це обернути його в кілька <div>, і ми отримаємо повністю відтворений контроль:
<?php
public function cmb2_render_link_picker( $field, $value, $object_id, $object_type, $field_type_object) {
$value = wp_parse_args( $value, array(
'text' => '',
'url' => '',
'blank' => 'false',) );
$blank_options = '';
$blank_options .= '<option value="false" '. selected( $value['blank'], 'false', false) .'>Opens in same</option>';
$blank_options .= '<option value="true" '. selected( $value['blank'], 'true', false) .'>Opens in new</option>';
?>
<div class="link-picker">
<div class="text">
<p>
<label for="<?php echo $field_type_object->_id( '_text' ); ?>'">
<?php echo esc_html( $field_type_object->_text( 'link_picker_text', 'Text') ); ?>
</label>
</p>
<?php
echo $field_type_object->input(
array(
'class' => 'cmb_text',
'name' => $field_type_object->_name( '[text]' ),
'id' => $field_type_object->_id( '_text' ),
'value' => $value['text'],
'desc' => '',) );
?>
</div>
<div class="url">
<p>
<label for="<?php echo $field_type_object->_id( '_url' ); ?>'">
<?php echo esc_html( $field_type_object->_text( 'link_picker_url', 'URL') ); ?>
</label>
</p>
<?php
echo $field_type_object->input(
array(
'class' => 'cmb_text_url',
'name' => $field_type_object->_name( '[url]' ),
'id' => $field_type_object->_id( '_url' ),
'value' => $value['url'],
'type' => 'url',
'desc' => '',) );
?>
</div>
<div class="blank">
<p>
<label for="<?php echo $field_type_object->_id( '_blank' ); ?>'">
<?php echo esc_html( $field_type_object->_text( 'link_picker_blank', 'Window') ); ?>
</label>
</p>
<?php
echo $field_type_object->select(
array(
'class' => 'cmb_checkbox',
'name' => $field_type_object->_name( '[blank]' ),
'id' => $field_type_object->_id( '_blank' ),
'options' => $blank_options,
'desc' => '',) );
?>
</div>
<div class="choose">
<p>
<label>Choose</label>
</p>
<button class="dashicons dashicons-admin-links js-insert-link button button-primary" title="<?php esc_html_e( 'Insert Link', 'cmb' ); ?>">
<span class="screen-reader-text"><?php esc_html_e( 'Choose Link', 'cmb' ); ?></span>
</button>
</div>
</div>
<p class="clear">
<?php echo $field_type_object->_desc();?>
</p>
<?php
}
І це все! Ми зробили свій контроль! CMB2 автоматично обробляє всі дані, які ми хочемо зберегти, тому там нічого робити.
Стилі
На знімку екрана елемента керування, який ми створюємо (у верхній частині цієї публікації), до нього застосовано кілька спеціальних стилів, тому він відображається вбудовано. Я не буду сьогодні розповідати, як стилізувати форму, але якщо вам цікаво, ви можете завантажити плагін і переглянути вихідний код.
Зробити контроль повторюваним
Для тих із вас, хто хоче отримати трохи більше знань, ви можете зробити так, щоб елемент керування працював із повторюваними областями CMB2. Для цього вам потрібно трохи відобразити масив. Для цього використовуйте код нижче:
<?php
public function cmb2_sanitize_link_picker( $check, $meta_value, $object_id, $field_args, $sanitize_object) {
if (! is_array( $meta_value) ||! $field_args['repeatable']) {
return $check;
}
foreach ($meta_value as $key => $val) {
$meta_value[ $key ] = null;
if(! empty( $val['url'])) {
$meta_value[ $key ] = array_map( 'sanitize_text_field', $val );
}
}
return $meta_value;
}
public function cmb2_types_esc_link_picker( $check, $meta_value, $field_args, $field_object) {
if (! is_array( $meta_value) ||! $field_args['repeatable']) {
return $check;
}
foreach ($meta_value as $key => $val) {
$meta_value[ $key ] = null;
if(! empty( $val['url'])) {
$meta_value[ $key ] = array_map( 'esc_attr', $val );
}
}
return $meta_value;
}
Вибір посилання
Звичайно, суть засобу вибору посилань полягає в тому, щоб інтегруватися у власну функцію вибору посилань WordPress, завдяки чому діалогове вікно «Вставити/редагувати посилання» з’являється під час натискання кнопки «Вибрати».
Щоб це сталося, ми значною мірою покладаємось на JavaScript. Зокрема, я використовую jQuery, щоб щось відбувалося.
Перш ніж я покажу вам JavaScript, який запускає діалогове вікно, ми повинні спочатку поставити в чергу власний внутрішній JavaScript WordPress, який попередньо завантажить модальні елементи та бібліотеки, від яких залежить наш код. Це виглядає приблизно так:
<?php
global $post_id;
if (isset( $post_id)) {
wp_enqueue_media( array( 'post' => $post_id) );
}
$plugin_js_url = plugins_url( 'js/plugin.js', ROOT );
wp_enqueue_script( 'wholesomecode', $plugin_js_url, array( 'jquery', 'jquery-ui-core', 'jquery-ui-draggable', 'jquery-ui-droppable', 'thickbox', 'wpdialogs' ), '1.0.0', true );
Як бачите, багато внутрішніх бібліотек WordPress покладаються на jQuery для завантаження спливаючого вікна, тому має сенс, щоб наш тригер спливаючого вікна робив те саме. Це робиться за допомогою, /js/plugin.jsякий завантажується в рядок 10 наведеного вище прикладу.
jQuery(document).ready(function($) {
var url = $('body');
var text = $('body');
var blank = $('body');
$('body').on('click', '.js-insert-link', function(event) {
event.preventDefault? event.preventDefault(): event.returnValue = false;
event.stopPropagation();
url = $(this).closest('.link-picker').find('input.cmb_text_url ');
text = $(this).closest('.link-picker').find('input.cmb_text ');
blank = $(this).closest('.link-picker').find('input.cmb_checkbox ');
wpActiveEditor = true;
wpLink.open();
wpLink.textarea = url;
return false;
});
$('body').on('click', '#wp-link-cancel, #wp-link-backdrop, #wp-link-close', function(event) {
wpLink.textarea = url;
wpLink.close();
event.preventDefault? event.preventDefault(): event.returnValue = false;
event.stopPropagation();
return false;
});
$('body').on('click', '#wp-link-submit', function(event) {
console.log(text)
var linkAtts = wpLink.getAttrs();
linkAtts.text = $('#wp-link-text').val();
url.val(linkAtts.href);
if( linkAtts.text != '') {
text.val(linkAtts.text);
}
if (linkAtts.target == '_blank') {
blank.prop('checked', true);
} else {
blank.prop('checked', false);
}
wpLink.textarea = url;
wpLink.close();
event.preventDefault? event.preventDefault(): event.returnValue = false;
event.stopPropagation();
return false;
});
});
Використовуючи класи, які ми обернули навколо наших елементів керування форми, JavaScript націлює елементи керування та надсилає вибраний результат із спливаючого вікна вибору посилань у відповідні поля керування.
Використання елемента керування
Отже, після перегляду підручника вище та, можливо, після перегляду вихідного коду модуля вибору посилань для плагіна CMB2 або просто завантаження моєї версії, можливо, тепер ви задаєтеся питанням, як використовувати цю річ із CMB2. Ну, це не може бути простіше:
<?php
function wholesomecode_create_meta_boxes() {
$prefix = '_profile_';
$cmb = new_cmb2_box(
array(
'id' => 'cta',
'title' => __( 'Call to Action', 'cmb2' ),
'object_types' => array( 'profile' ),
'context' => 'normal',
'priority' => 'low',
'show_names' => true,) );
$field1 = $cmb->add_field(
array(
'name' => __( 'Link Picker', 'cmb2' ),
'id' => $prefix. 'cta_link',
'type' => 'link_picker',) );
}
add_action( 'cmb2_admin_init', 'wholesomecode_create_meta_boxes' );