Программирование с API
Программирование с APIДополнение WP-CLI

Дополнение WP-CLI

WP-CLI — это инструмент командной строки для взаимодействия с WordPress, помогающий автоматизировать задачи. Он позволяет устанавливать новый сайт, создавать или обновлять записи, активировать плагины, изменять настройки и многое другое.

Команды WP-CLI можно вкладывать друг в друга:

  1. Выполнить команду WP-CLI, возвращающую ID некоего ресурса
  2. Передать этот ID в другую команду WP-CLI, чтобы выполнить операцию над этим ресурсом

Например, следующий скрипт находит ID записи с определённым slug и обновляет её мета-данные:

wp post meta set $(wp post list --name="hello-world" --format=ids) _wp_page_template about.php

Этот скрипт многократно создаёт элемент меню и устанавливает его ID в качестве родителя для другого нового элемента меню, тем самым определяя их иерархию ("Most ancestor menu item" > "Parent menu item" > "Child menu item"):

wp menu item add-custom bottom-menu "Child menu item" https://bbc.com --parent-id=$(wp menu item add-post bottom-menu 1 --title="Parent menu item" --parent-id=$(wp menu item add-post bottom-menu 1 --title="Most ancestor menu item" --porcelain) --porcelain)

Gato GraphQL может расширить возможности WordPress для поиска данных. Таким образом, мы также можем использовать Gato GraphQL для поиска нужных данных и передачи их в WP-CLI.

Следующие queries продемонстрируют, как это сделать.

Выполнение GraphQL-запроса из терминала

Воспользуемся GraphQL-запросом для поиска пользователей с испанской локалью и выполнения команды WP-CLI над таким пользователем.

Сначала ограничим результат одним пользователем (через pagination: { limit: 1 }):

query {
  users(
    filter: {
      metaQuery: {
        key: "locale",
        compareBy: {
          stringValue: {
            value: "es_[A-Z]+"
            operator: REGEXP
          }
        }
      }
    },
    pagination: {
      limit: 1
    }
  ) {
    id
    name
    locale: metaValue(key: "locale")
  }
}

В терминале можно использовать curl (или аналогичный инструмент) для выполнения запроса к GraphQL-серверу, передав следующие данные:

  • Использовать метод POST
  • Принимаемый тип содержимого — application/json
  • Тело представляет собой словарь с записью "query" и GraphQL-запросом (а при необходимости также записями "variables" и "operationName")
  • Строка запроса должна быть отформатирована: все символы " необходимо экранировать как \", а переносы строк заменить на \n
  • Указать URL эндпоинта Gato GraphQL (одиночного эндпоинта или пользовательского)
curl \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"query": "query {\n  users(\n    filter: {\n      metaQuery: {\n        key: \"locale\",\n        compareBy: {\n          stringValue: {\n            value: \"es_[A-Z]+\"\n            operator: REGEXP\n          }\n        }\n      }\n    },\n    pagination: {\n      limit: 1\n    }\n  ) {\n    id\n    name\n    locale: metaValue(key: \"locale\")\n  }\n}"}' \
  https://mysite.com/graphql/

Это выводит ответ прямо в терминал:

{"data":{"users":[{"id":3,"name":"Subscriber Bennett","locale":"es_AR"}]}}

Извлечение ID из GraphQL-ответа

По аналогии с использованием --field=ID, --format=ids или --porcelain в WP-CLI, нам нужно найти способ извлечь конкретный фрагмент данных из GraphQL-ответа. В данном примере это ID пользователя.

Присвоим GraphQL-ответ переменной окружения (например, GRAPHQL_RESPONSE) и идентифицируем ID пользователя с помощью определённого псевдонима (например, spanishLocaleUserID):

GRAPHQL_RESPONSE=$(curl \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"query": "query {\n  users(\n    filter: {\n      metaQuery: {\n        key: \"locale\",\n        compareBy: {\n          stringValue: {\n            value: \"es_[A-Z]+\"\n            operator: REGEXP\n          }\n        }\n      }\n    },\n    pagination: {\n      limit: 1\n    }\n  ) {\n    spanishLocaleUserID: id\n    name\n    locale: metaValue(key: \"locale\")\n  }\n}"}' \
  https://mysite.com/graphql/)

Выполнив echo $GRAPHQL_RESPONSE, можно просмотреть ответ:

{"data":{"users":[{"spanishLocaleUserID":3,"name":"Subscriber Bennett","locale":"es_AR"}]}}

Далее выполняем grep с регулярным выражением, совпадающим с шаблоном "spanishLocaleUserID":{ID}, и извлекаем ID в переменную окружения SPANISH_LOCALE_USER_ID:

SPANISH_LOCALE_USER_ID=$(echo $GRAPHQL_RESPONSE \
  | grep -E -o '"spanishLocaleUserID\":(\d+)' \
  | cut -d':' -f2- | cut -d'"' -f2- | rev | cut -d'"' -f2- | rev)

Теперь можно передать значение этой переменной в WP-CLI:

wp user update "$(echo $SPANISH_LOCALE_USER_ID)" --locale=fr_FR

Повышение читаемости GraphQL-запроса

При форматировании GraphQL-запроса для передачи в curl он становится трудночитаемым.

Решением является применение преобразований с помощью bash-команд, таких как tr и sed:

GRAPHQL_QUERY='
  query {
    users(
      filter: {
        metaQuery: {
          key: "locale",
          compareBy: {
            stringValue: {
              value: "es_[A-Z]+"
              operator: REGEXP
            }
          }
        }
      },
      pagination: {
        limit: 1
      }
    ) {
      spanishLocaleUserID: id
      name
      locale: metaValue(key: "locale")
    }
  }
'
GRAPHQL_BODY="{\"query\": \"$(echo $GRAPHQL_QUERY | tr '\n' ' ' | sed 's/"/\\"/g')\"}"
GRAPHQL_RESPONSE=$(curl \
  -X POST \
  -H "Content-Type: application/json" \
  -d $GRAPHQL_BODY \
  https://mysite.com/graphql/)

Добавление подсветки синтаксиса к GraphQL-запросу

Следующим шагом по сравнению с предыдущим является размещение GraphQL-запроса в отдельном файле .gql, который затем можно редактировать в редакторе (например, VSCode) с использованием подсветки синтаксиса:

# This query is stored in file "find-user-with-spanish-locale.gql"
query {
  users(
    filter: {
      metaQuery: {
        key: "locale",
        compareBy: {
          stringValue: {
            value: "es_[A-Z]+"
            operator: REGEXP
          }
        }
      }
    },
    pagination: {
      limit: 1
    }
  ) {
    spanishLocaleUserID: id
    name
    locale: metaValue(key: "locale")
  }
}

Затем читаем содержимое этого файла с помощью cat:

GRAPHQL_QUERY=$(cat find-user-with-spanish-locale.gql)
GRAPHQL_BODY="{\"query\": \"$(echo $GRAPHQL_QUERY | tr '\n' ' ' | sed 's/"/\\"/g')\"}"
GRAPHQL_RESPONSE=$(curl \
  -X POST \
  -H "Content-Type: application/json" \
  -d $GRAPHQL_BODY \
  https://mysite.com/graphql/)