Open sergey-s-betke opened 10 years ago
add_meta_box
добавляет не элемент управления, а секцию (по сути) с группой элементов управления. Поэтому и иерархию классовых обёрток в WPF следует выстраивать по аналогии с секциями страниц настроек:
Элементы управления уже должны быть связаны с собственно метаданными, которые (как и в случае с опциями) мы описываем отдельно от их представления в интерфейсе.
meta_box
)На первый взгляд кажется, что вполне есть шанс использовать элементы управления страниц настроек! Но в этом случае придётся изменить пространство имён для них (что крайне нехорошо из соображений совместимости).
Опции объединены в группы, одна группа отображается на одной странице настроек. И при регистрации опций важно их регистрировать в группе, определённой той страницей настроек, на которую мы хотим настройку разместить.
Аналогичная ситуация должна быть и для meta. Один meta_box будет обрабатывать одну группу meta при сохранении изменений. И, по сути, регистрация meta должна осуществляться также в "группе", предусмотренной для конкретного meta_box...
Для метаданных безболезненно можно и нужно использовать register_meta
. Она вообще не влияет на интерфейс, но регистрирует санитизатор, который используется перед изменением значений метаданных.
Кроме того, указанная функция так же регистрирует и верификатор полномочий на изменение метаданных. Однако, нашёл лишь использование при проверке полномочий add_post_meta
, посему этот верификатор пока не вижу большого смысла использовать. Но проверять его через фильтр
$allowed = apply_filters( "auth_{$meta_type}_meta_{$meta_key}", false, $meta_key, $post->ID, $user_id, $cap, $caps );
всё-таки следует.
Аналогичная (как и для опций) проблема с десериализацией. Так же целесообразно реализовать два разных класса - с сериализацией всего, и с поведением по умолчанию (сериализация только объектов и массивов).
Естественно, как и с опциями, потребуется в этом случае читать и писать метаданные через объект плагина (чтобы поддержать возможность оборачивания значения перед сохранением в БД).
Убрал из кода генерацию nonce и проверку - в форме в целом уже присутствуют nonce, и их проверка уже будет выполнена до наших действий, поэтому не вижу смысла повторно проверять факт вызова именно через консоль администратора.
Вопрос об использовании общих элементов управления на в секциях страниц настроек и в meta_box. Чтение аттрибутов изменяемой величины и её значения осуществляется во всех view уже сейчас через методы собственно элемента управления, то есть здесь инкапсуляция обеспечена уже сейчас.
Теперь важно заставить сам элемент управления работать как с секциями страниц настроек, так и с meta_box. Пытаться вставлять секции в meta_box излишне, как мне кажется.
Таким образом от элементов управления будет полностью изолирован слой непосредственного взаимодействия с изменяемыми величинами.
Есть один подводный камень. Сейчас я перенёс функционал setting из option в элемент управления. В том числе - валидаторы, санитизаторы и прочее. При описанном же выше подходе элементы управления больше не должны содержать функционала setting, этот функционал должен быть реализован за пределами элемента управления.
Но и не в классах, инкапсулирующих изменяемые величины - эта задача уже решена была (#48).
Функционал setting должен быть реализован в рамках страницы настроек. А санитизаторы / валидаторы куда? Опять вернуть их в опции / meta?
Функционал setting в секции страницы настроек реализуем следующим образом: опрашиваем все элементы управления, запрашиваем у них изменяемые величины, и под них регистрируем settings.
Похожим образом будем действовать и в meta_box: будет опрашивать все элементы управления, получать от них идентификаторы изменяемых величин (или непосредственно через класс элемента управления будем его читать изменяемые величины - это возможно, и может быть полезным), и таким образом формируем циклы обработки / сохранения meta.
Остаётся вопрос по санитизаторам / верификаторам изменяемых величин. Оставить их по-прежнему принадлежностью элемента управления? Или вернуть их в дескрипторы опций / мета? Возвращать не очень хотелось бы - во front end не требуются санитизаторы / верификаторы, поэтому не следует грузить и их код с точки зрения производительности. Вводить же ещё одни сущности - собственно санитизаторы / валидаторы - точно не стоит. Тогда без вариантов - оставляем валидаторы принадлежностью элементов управления. Кстати, в дальнейшем подобным симбиоз можно развить и в client side validation, или хотя бы в client side ajax validation. Так что - оставим санитизаторы / валидаторы принадлежностью элементов управления.
Но функционал setting выносим в страницы настроек. Необязательно в секции - можно и в страницы, никто не мешает нам реализовать этот функционал и в базовом классе страниц настроек, что позволит использовать свои секции и на чужих страницах.
Итак, план действий:
В итоге мы получим возможность использовать одни и те же элементы управления и на страницах настроек, и в meta_box.
P.S. Можно подумать в дальнейшем о том, чтобы элемент управления мог выбирать свой шаблон (view) с учётом того, где он используется.
[x] добавить в интерфейс элементов управления метод:
public
function bind_action_handlers_and_filters();
Давно напрашивается... Для этих целей целесообразно выделить отдельный интерфейс - IPluggable
.
Пока не потяну секции и в meta_box, хотя они сейчас исполняют крайне ограниченный функционал, и всё взаимодействие с settings API из них убрано в settings page. Так что вполне можно в дальнейшем переименовать секции и использовать их так же и в meta_box. Пока не будем этого делать, но в дальнейшем - почему бы и нет?
В meta_box следует предоставить возможность вставить страницу справки. Пока не вижу в этом проблем, но тогда так же целесообразно изменить пространство имён для страниц справки.
Теперь опишем интерфейсы и базовую реализацию коллекции элементов управления (и не только) - компонентов интерфейса. У нас есть базовый класс - базовый компонент страницы настроек.
Для начала нужен базовый интерфейс компонента интерфейса, и интерфейс коллекции компонентов интерфейса. А затем:
Справку уже могу успешно добавить.
К сожалению, определить при генерации meta_box
действительное его местоположение (context
) не представляется возможным штатными средствами. Кроме того, и при перетаскивании meta_box
перезагружать страницу не будет. Поэтому разметка не должна зависеть от context
. Поэтому от табличной разметки придётся отказаться.
Пришло время реализовать интерфейс контроллера метаданных. И в отличии от опций, крайне важно сохранять только необходимые метаданные, удаляя и не создавая те, в которых нет потребности.
Например, если мы для страницы укажем - "использовать общие параметры кэширования", тогда нет смысла создавать метаданные, их отсутствие даст нам необходимую информацию.
А при изменении значения на значение по умолчанию мы должны удалять метаданные.
Учитывая тот факт, что отдельно метаданные мы нигде не определяем, мы не сможем определить "значение по умолчанию". Посему под ним стоит понимать null
, как минимум.
С целью сокращения времени выборки метаданных - может, стоит их сохранять одним метаданным (составным) для одного метабокса? Ограничения на длину строкового представления в базе данных нет...
Хотелось бы предоставить возможность указать уже в коде плагина, какой способ хранения мы изберём в итоге.
Самый красивый вариант - поступить аналогично опциям, редактирование реализовать исключительно через объект плагина. А уже конкретными компонентами, реализующими интерфейс взаимодействия с метаданными, будет определяться механизм их хранения - в составном одном объекте или во множестве простых объектов. Такой подход предоставит в перспективе и возможность удаления метаданных, созданных плагином, при удалении плагина.
Изложенный выше подход кажется наиболее правильным. Тогда иерархия классов приблизительно следующая:
WPF\Data\Meta\Post\Base
- базовый класс для инкапсуляции операций с метаданными. Не сериализует простые типы, работает с простыми (не составными) метаданнымиWPF\Data\Meta\Post\Complex
- принимает в качестве параметра и идентификатор собственно метаданных (составного значения), и идентификатор элемента. Для каждого элемента - отдельный экземпляр (компонент плагина). К идентификатору сам дописывает _
.С составными метаданными не всё так однозначно. Вопрос: какой из компонентов в будущем может отвечать за удаление метаданных при удалении плагина? Компонентов то плагина, ссылающихся на один составной тип метаданных, может быть несколько, и будет несколько.
Есть выход из положения! Комплексные метаданные не самостоятельно будут обращаться к meta API, а через плагин - к обёртке метаданных уже простого типа, который и будет непосредственно взаимодействовать с meta API, а также отвечать за удаление метаданных при удалении плагина.
Таким путём и пойдём.
Необходим механизм уведомления о допущенных ошибках при указании значений метаданных по аналогии с add_settings_error
, но такого API WorpPress не предлагает. Однако, в WPF у меня уже есть подобный компонент - ToDo
, динамический компонент.
Сообщения об ошибках при сохранении метаданных (#53) уже вполне могу генерировать.
Валидаторы уже сейчас работают и корректно генерируют сообщения об ошибках.
Имею первую редакцию, успешно валидирующую и сохраняющую метаданные страниц.
В том числе - и с сериализацией метаданные прекрасно обрабатываются. И значения по умолчанию для них можно использовать в моей реализации. И удаляться они могут при удалении плагина, при этом по умолчанию - удаляться и будут для всех страниц.
Возможно, стоит изменить обёртку для сериализации опций и метаданных с массива на какой-либо конкретный класс, так как для составных метаданных я планирую использовать именно массив, что привёт к конфликту. Да и для опций то же решение потенциально опасное по тем же причинам.
Следует добавить поддержку "скрытых" метаданных #55.
Возвращаюсь к вопросу удаления метаданных, точнее - хранения лишь значений, отличных от значения по умолчанию.
http://codex.wordpress.org/Function_Reference/register_meta