Списки доступных виджетов в WordPress

  • 13.05.15
  • 23:30
  • 478
  • 0

Одна из тем имеет сайдбары, оформление любого виджета или типа виджетов в которых задаётся на соотв. экране настройки. Интерфейс экрана должен содержать выпадающие списки виджетов и их типов.

Задача: составить списки виджетов и типов виджетов. При этом

  1. список всех зарегистрированных виджетов требуется в виде хеша $id_base => $name;
  2. список всех размещённых на сайдбарах виджетов должен быть сгруппирован по сайдбарам:
    Текст пунктов списка имеет вид "{$name} ({$title})", пустой заголовок не приводится; значения пунктов — идентификаторы виджетов.

Первая задача решается обработкой массива $wp_widget_factory->widgets, содержащего экземпляры всех зарегистрированных классов виджетов:

Обработка массива возложена на функцию wp_list_pluck($arr, $field_val, $field_key): здесь она выбирает из элементов массива — объектов — значения полей 'id_base' и 'name', а затем помещает их в выходной массив как пару "ключ => значение". Массив с объектами следует первым аргументом, имя поля значений — вторым, имя поля ключей — третьим.

Причина такого вида списка в том, что при обработке вывода виджета имя его класса обработчикам хуков не передаётся, но передаётся либо идентификатор, из которого можно извлечь $id_base, либо само $id_base.

Вторая задача требует определить все размещённые в сайдбарах виджеты и для каждого получить настройки — в них хранится опциональный заголовок. Задача сводится к формированию вложенного хеша вида $sidebar_id => array($widget_id => $text).

Информация о виджетах находится в глобальном массиве $wp_registered_widgets , ключами которого являются идентификаторы виджетов — имеют вид "{$id_base}-{$number}". Массив также содержит «потерянные», неактивные и «несуществующие» виджеты.

Последние отражают существование классов, не имеющих ни одного виджета. Отличаются номером -1 (минус один) и идентификатором "{$id_base}-1" (номера реальных виджетов начинаются с 2). Регистрируются с пустыми настройками. Нужны для экрана «Внешний вид > Виджеты».

Номер виджета лежит в $wp_registered_widgets[$widget_id]['params'][0]['number'], также может быть выделен из идентификатора выражением '/^.*-(\d+)$/'.

Для сортировки по сайдбарам необходимы список зарегистрированных сайдбаров и списки соответствующих им виджетов. Информация о сайдбарах хранится в глобальном массиве $wp_registered_sidebars вида $sidebar_id => array( /* параметры сайдбара*/ ).

Хеш соответствия виджетов сайдбарам даётся вызовом wp_get_sidebars_widgets(): в ключах находятся идентификаторы сайдбаров, в значениях — массивы идентификаторов виджетов. В результат также входят «потерянные» и неактивные виджеты:

Группы wp_inactive_widgets и orphaned_widgets_* сайдбарами не являются и в $wp_registered_sidebars не содержатся, что удобно для фильтрации.

Формирование хеша $sidebar_id => array($widget_id => '') — без текста для пунктов списка — выглядит так:

Для формирования строки $text нужны имя виджета и заголовок. Человекочитаемое имя находится в поле $name класса виджета, заголовок — в настройках. Массив с настройками всех виджетов одного типа даётся методом get_settings() их класса:

Результат имеет вид $number => $instance, где $number — номер виджета, $instance — его настройки. Заголовок берётся из $instance['title'].

Имя класса 'ClassName' не известно. Для удобного его определения можно заранее построить хеш вида $id_base => 'ClassName':

Примечание: сам WordPress использует массив $wp_widget_factory->widgets только при инициализации виджетов. При этом все необходимые им функции раскладываются по глобальным массивам, поэтому имена классов ему не требуются и средств для их определения по, например, идентификатору виджета не имеется.

При построении выпадающего списка значение $id_base виджета определяется из его идентификатора:

Примечание: Это же самое действие выполняет функция _get_widget_id_base($widget_id), но она, как видно из первого знака подчёркивания, является «приватной» и к использованию не рекомендуется. Поэтому в неё следует разве что заглядывать от версии к версии на предмет к.-л. изменений в устройстве идентификатора виджета.

Формирование строк "{$name} ({$title})" для элементов списка выглядит так:

Выдать построенный массив в виде выпадающего списка <select> можно, напр., так:

Результат выглядит так (функция и выдача списка находятся в разных файлах, всё лишнее вырезано):

Так выглядят пара вариантов выдаваемого списка:

  • Ресурс с четыремя однотипными сайдбарами в футере:
  • Ресурс с правым сайдбаром и сайдбарами в футере:

P. S. Класс виджета из его идентификатора можно получить и другим способом: функционал $wp_registered_widgets[$id]['callback'] для всех «нормальных» виджетов конструируется как array($this, 'display_callback') в методе _get_display_callback() класса WP_Widget. Поэтому для них такие варианты будут идентичны:

Две проблемы связаны со вторым вариантом:

  • технически возможны «ненормальные» виджеты, реализованные ручным использованием функции wp_register_sidebar_widget($id, $name, $output_callback, $options), которая от существования класса никак не зависит. Такие виджеты приведут второй вариант в нерабочее состояние;
  • от значения $wp_registered_widgets[$id]['callback'] требуется только способность его к выполнению — вызов is_callable(...) должен возвращать истину. Поэтому ничего не мешает разработчикам изменить вид функционала на строку с именем функции, анонимную функцию, метод к.-л. другого класса, вызывающий метод класса виджета и т. д.

По этим соображениям первый вариант — более громоздкий и с дополнительным массивом — кажется более надёжным.

Оставить комментарий

Добавить комментарий