Расширенный OOP для WordPress Часть 8: Разработка новых функций для расширяемых WordPress плагинов с помощью тест-Driven развития

В моем последнем посте в этой серии на передовых PHP объектно-ориентированного программирования для WordPress развития, я прошел через рефакторинг низкого уровня API плагина, используя тесты для руководства процессом и убедитесь, что все работает правильно. Я говорю «низкоуровневый API», потому что основное внимание было уделено внутренней, как система будет работать. Я не покрывал слишком много проводов вместе. В этой статье, вот где этот пост поднимает.

Следующим шагом было создание фабрики, которая принимает массив аргументов для REST API, чтобы добавить, и массив типов сообщений — что автоматически проводов этих фильтров.

Разработка, основанная на тестах (TDD), является практикой написания тестов для изменения базы кода перед фактическим написанием изменения. Это делает тест спецификации, которая определяет, если новая функция / ошибка исправить / все, что работает или нет. Существующие тесты также прохождения определяет, если новая функция / ошибка исправить / что собираются создать ошибки регрессии или нет.

Переход на TDD на существующей базе кода не легко. Давайте использовать этот существующий плагин, чтобы посмотреть, как это может работать.

Оценка существующих тестов

Во-первых, важно посмотреть, что делают существующие тесты. Прямо сейчас, у нас есть тесты, которые охватывают форму результатов запроса, в основном, что они представляют собой массив «lt;код»gt; WP-Posts.lt;/код.gt; Аналогичный тест гарантирует, что ответ REST API имеет правильную форму.

Это все хорошо, но ни один из них охватывают содержание тех WP_Posts . Итак, теперь мы определили, чего не хватает в нашем тестовом наборе. Теперь мы готовы написать тесты.

Начиная с мок входных данных

Я начал с создания массива того, что я хотел ввода этого класса завода. Я написал этот массив в тесте для завода.

Просмотр кода на Gist.

Теперь я собираюсь создать нефункциональную версию завода и создать тест, который проверяет ее основную функциональность. Вот наброски класса поиска, который потребляет два интерфейса и имеет функции getter:

Просмотр кода на Gist.

Это то, что моя фабрика будет создавать. Давайте начнем фабрику с метода, который принимает аргументы, чтобы добавить и типы сообщений, чтобы добавить его и испускает поиск:

Просмотр кода на Gist.

Теперь у нас есть достаточно, чтобы написать, чтобы покрыть тип возврата каждого из определенных общедоступных методов:

Просмотр кода на Gist.

Это еще не пройдет — это вызов методов мы еще не написали органов еще. Как только мы добавим тело к этим методам, у нас есть способ количественной оценки, если они уже работают. Но это опережает нас.

Во-первых, мы должны сделать поиск класса настроить все вверх. Прежде чем это произойдет, мы должны знать, что он делает. Поиск несет ответственность за склеивание системы. Поэтому он выполняет несколько задач, но до тех пор, пока он действует как контроллер, который отправляет другие системы, основываясь на логике, определенной в этих других системах, он по-прежнему несет только одну ответственность.

Перечислим те задачи, которые он должен отправить:

  • Он должен потреблять объект, реализующий qlt;code-gt;ModifySchemaContract-lt;/код-gt; интерфейс для того, чтобы изменить схему некоторых маршрутов REST API и знать, какие маршруты изменить.
  • Он должен потреблять объект реализации злт;код-gt;Modify’eryArgsContract’lt; / код -gt; интерфейс для того, чтобы изменить белый список аргументов запроса.
  • Он должен подключиться к WordPress Plugins API (крючки), чтобы сделать эти изменения.

Начнем с последнего — подключения к API-извне. Это то, что мы имеем наименьший контроль над и диктует то, что мы должны работать. Много моей озабоченности о том, как получить все права зависимых объектов — WP_Query и WP_REST_Request от ядра ушел, позволяя плагинов API поставлять данные.

Поиск нужно будет добавить крючки, которые мы хотим удалить. Я добавил интерфейс, чтобы формализовать шаблон для этого, так как он, вероятно, будет повторно использован.

Просмотр кода на Gist.

Так как моя цель, с последним набором интерфейсов было сделать filterSchema() и filterQueryArgs() методы уходят, я добавлю эти методы для поиска. Я должен быть в состоянии использовать методы этих двух интерфейсов, которые определяют, что аргументы, чтобы обеспечить на фильтре и следует ли применять фильтр, чтобы иметь одно место, которое выполняет эту задачу для каждой реализации.

Вот класс, который мог бы сделать это, за исключением ни одного из методов имеют тела:

Просмотр кода на Gist.

Но мы можем написать тесты, чтобы показать, как эти методы должны работать. В дополнение к тесту, который у меня уже есть, я добавлю этот, чтобы проверить, что свойства для классов модификаторов арг запроса и схемы арг установлены. Это охватывает эти методы и делает их безопасными для использования в других методах:

Просмотр кода на Gist.

Это не покрывает ли эти крючки работают, и если они работают правильно. Это два ключевых требования, четыре на самом деле, так как мы должны крючки. Вот тесты, чтобы доказать, что для изменения запроса arg белый список:

Просмотр кода на Gist.

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

Проектирование фабрики

Хорошо, теперь давайте начнем положить это вместе на нашей фабрике. Фабрики, где объекты собираются. Абстракция делает заводы более эффективными, так как один и тот же инструмент может создавать различные, но похожие продукты благодаря использованию общего интерфейса.

Итак, я увидел здесь возможность перенести большую часть реализации классов модификаторов арг и схемы арг к абстрактным классам, которые они наследуют, чтобы я мог повторно использовать эту логику внутри завода. Без этого, я бы использовать вырезать и вставить или, может быть, черта для повторного использования этой логики. Наследование является самым простым решением, хотя. Это имеет смысл, я хочу один или несколько классов, которые реализуют тот же интерфейс и делать в основном то же самое с различными деталями реализации. Для этого и н., что такое классное наследство.

Вот мой абстрактный запрос Arg модификатор класса:

Просмотр кода на Gist.

А вот абстрактная схема арг модификатор класса:

Просмотр кода на Gist.

Вы, наверное, заметили, что класс реализует интерфейс только. Это все, что я мог сделать многоразовые на данном этапе, так что это то, что он делает. Пустые абстрактные классы, как правило, накапливают многоразовые методы с течением времени.

Теперь, когда у нас есть эти два класса, мы можем расширить их внутри нашей фабрики. Я решил использовать анонимные классы, которые расширяют эти два класса. Это позволило мне сохранить всю заводскую логику на заводе. Анонимные классы подобны анонимным функциям, они не имеют имени и определяются по мере необходимости.

Анонимные классы могут расширять другие классы, внедрять интерфейсы и использовать черты. Они представляют свою область в специальной переменной $this и могут принимать аргументы с помощью магического __construct() метода. Так же, как классы.

Например, этот анонимный класс расширяет WP_Query и переопределяет метод запроса:

Просмотр кода на Gist.

 

Наши анонимные классы, которые будут идти в Factory::search() начале, глядя, как это:

Просмотр кода на Gist.

Оба они собираются взять $postTypesToSupport массив, который передается методу, в который они находятся в качестве зависимости конструктора. Этот конструктор не существует в классах, которые они наследуют, поэтому анонимные классы должны объявить конструктора.

Просмотр кода на Gist.

Так как этот метод передается массив аргументов, его работа заключается в цикле через и собирать их правильно внутри двух объектов, ответственных за использование фильтров WordPress, чтобы обеспечить эти данные. Вот что цикл:

Просмотр кода на Gist.

Теперь, когда форма слота, в который должны приклеиться части, более ясна, давайте начнем строить класс поиска, из которого эта фабрика создает объекты.

Просмотр кода на Gist.

Это не полная реализация, но она увеличивает на два обратных вызовов для наших крючков. В обоих случаях поиск может знать, если фильтрация должна происходить на основе, если метод, определенный на интерфейсе, который типа намекнул вернуть boolean является правдой или ложной. Он может получить массив данных для добавления на фильтры с помощью метода, который определяется на интерфейсе и типа намекнул, чтобы вернуть массив.

Это требует второго рефактора на два интерфейса я показал ранее и продолжал говорить, что мы должны вернуться. Настало время для этого второго рефактора.

Вот новый интерфейс для фильтрации аргументов запроса:

Просмотр кода на Gist.

А вот новый интерфейс для фильтрации аргументов схемы:

Просмотр кода на Gist.

Этот рефактор удаляет необходимые для этих классов на самом деле крючок в WordPress плагинов API. Это все обрабатывается в классе поиска сейчас. Кроме того, метод «lt;код»;gt;shouldFilter() lt;/код»gt; метод имеет одинаковую подпись в обоих, что мне нравится.

Поскольку интерфейсы могут наследовать другие интерфейсы, мы можем переместить этот метод в свой собственный интерфейс, который унаследуют оба этих интерфейса. Это означает, что каждый интерфейс создал только одно требование, о чем нам говорит принцип сегрегации интерфейсов. Вместо этого, я просто собираюсь сказать вам, что это неправильно, так что вы можете исправить это и положить в тянуть запрос. Напишите в блоге об этом, и я на Twitter.

Использование API-извне для фиксации зависимостей

Эта фабрика может настроить фильтрацию того, как вводы, но на самом деле не фильтр, который мы используем для изменения результатов запроса. Ранее я обсуждал, как Тоня, и я решил, что классы, которые отвечают за создание результатов, должны быть осведомлены, по крайней мере WP_Query , и, возможно WP_REST_Request , .

Для того, чтобы сделать это, мне нужна ссылка на текущий WP_REST_Request . Так как WordPress не имеет контейнера службы, чтобы запросить его от моего решения, которое вы можете видеть в этом коммите, чтобы захватить текущий запрос, чтобы он мог быть введен в контент getter с помощью фильтра rest-pre’serve.request.

Я сделала это внутри FilterWPQuery класса. Мне нужна WP_Rest_Request внутренняя часть getPosts() метода. Я добавил новый метод captureRequest, чтобы захватить запрос, положил его в статическую переменную, которую я мог бы использовать в getPosts()

Просмотр кода на Gist.

Я все еще могу проверить это с модульными тестами, заменив API Plugin с моими макетами и другие мои тесты по-прежнему действительны.

Начальная расширяемость

Моя следующая статья будет о том, чтобы эта система extensible FilterWPQuery Класс в настоящее время init() я рефакторинг его как сеттер метод с соответствующим getter. Таким getPosts() образом, действует как диспетчер последний набор contentGetter выигрывает. Я желаю что этот маршрутизатор был более абстрактным, например, по-разному реализации в тип столба. 

Вот как выглядит класс в этот момент:

Просмотр кода на Gist.

Теперь все в нашем плагине, что мы должны были бы поменять на другой реализации поиска поменяться, и у нас есть завод, чтобы управлять этим. Я буду опираться на это в следующей статье.

Весь код в этой статье и предыдущей статье был добавлен в пример плагина через этот запрос на вытягивание. Есть больше тестов, чем я обсуждал в этой статье. Опять же, этот плагин не имеет 100% охват аттестата и еще не делать то, что он должен делать. Тоня и я буду улучшать его, как мы пишем, вы приглашены присоединиться к. Я думаю, что вклад в этот плагин будет хорошим способом применить то, что вы изучаете.

Источник: torquemag.io

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

%d такие блоггеры, как: