Programando com uma API
Programando com uma APIIntegrando WP-CLI

Integrando WP-CLI

WP-CLI é uma ferramenta de linha de comando para interagir com o WordPress, que nos ajuda a automatizar tarefas. Ela nos permite instalar um novo site, criar ou atualizar posts, ativar plugins, modificar as opções e muito mais.

Os comandos do WP-CLI podem ser aninhados:

  1. Executar um comando WP-CLI que retorna o ID de algum recurso
  2. Injetar esse ID em outro comando WP-CLI, para executar uma operação nesse recurso

Por exemplo, este script encontra o ID do post com determinado slug e atualiza seus metadados:

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

Este script cria repetidamente um item de menu e define seu ID como pai de outro novo item de menu, definindo assim sua hierarquia ("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)

O Gato GraphQL pode ampliar as capacidades do WordPress na busca de dados. Dessa forma, também podemos usar o Gato GraphQL para encontrar os dados de que precisamos e injetá-los no WP-CLI.

As seguintes queries demonstrarão como fazer isso.

Executando uma query GraphQL pelo terminal

Vamos usar uma query GraphQL para encontrar usuários com o locale espanhol e executar um comando WP-CLI nesse usuário.

Primeiro limitamos o resultado a apenas 1 usuário (via 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")
  }
}

No terminal, podemos usar curl (ou uma ferramenta similar) para executar uma query contra o servidor GraphQL, passando os seguintes dados:

  • Executar o método POST
  • O tipo de conteúdo aceito é application/json
  • O corpo é um dicionário com a entrada "query" e a query GraphQL (e, se necessário, também as entradas "variables" e "operationName")
  • A string da query deve ser formatada: todos os " devem ter escape como \", e as quebras de linha devem ser substituídas por \n
  • Apontar para a URL do endpoint do Gato GraphQL (seja o endpoint único ou algum endpoint personalizado)
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/

Isso exibe a resposta diretamente no terminal:

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

Extraindo o ID da resposta GraphQL

De forma semelhante ao uso de --field=ID, --format=ids ou --porcelain no WP-CLI, precisamos encontrar uma maneira de extrair o dado específico de que precisamos da resposta GraphQL. Neste exemplo, trata-se do ID do usuário.

Atribuímos a resposta GraphQL a uma variável de ambiente (como GRAPHQL_RESPONSE) e identificamos o ID do usuário com um alias específico (como 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/)

Executando echo $GRAPHQL_RESPONSE podemos visualizar a resposta:

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

Em seguida, executamos grep com uma regex correspondente ao padrão "spanishLocaleUserID":{ID} e extraímos o ID para a variável de ambiente 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)

Agora podemos injetar o valor dessa variável no WP-CLI:

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

Tornando a query GraphQL mais legível

Ao formatar a query GraphQL para inseri-la no curl, ela se tornou difícil de ler.

Uma solução é aplicar as transformações usando comandos bash, como tr e 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/)

Adicionando realce de sintaxe à query GraphQL

Uma iteração adicional em relação à etapa anterior é colocar a query GraphQL em um arquivo .gql separado, que pode então ser editado com um editor (como o VSCode) e usar seu realce de sintaxe:

# 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")
  }
}

Em seguida, lemos o conteúdo deste arquivo usando 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/)