Programowanie z API
Programowanie z APIIntegracja z WP-CLI

Integracja z WP-CLI

WP-CLI to narzędzie wiersza poleceń do interakcji z WordPress, które pomaga automatyzować zadania. Pozwala nam instalować nową stronę, tworzyć lub aktualizować posty, aktywować wtyczki, modyfikować opcje i wiele więcej.

Polecenia WP-CLI można zagnieżdżać:

  1. Wykonanie polecenia WP-CLI, które zwraca ID pewnego zasobu
  2. Wstrzyknięcie tego ID do innego polecenia WP-CLI w celu wykonania operacji na tym zasobie

Na przykład ten skrypt znajduje ID posta o określonym slugu i aktualizuje jego metadane:

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

Ten skrypt wielokrotnie tworzy element menu i ustawia jego ID jako nadrzędny dla kolejnego nowego elementu menu, definiując w ten sposób ich hierarchię ("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 może rozszerzyć możliwości WordPress w zakresie wyszukiwania danych. Dzięki temu możemy również używać Gato GraphQL, aby znaleźć potrzebne dane i wstrzyknąć je do WP-CLI.

Poniższe queries pokażą, jak to zrobić.

Wykonywanie query GraphQL z terminala

Użyjmy query GraphQL, aby znaleźć użytkowników z hiszpańskim locale i wykonać polecenie WP-CLI na tym użytkowniku.

Najpierw ograniczamy wynik do tylko 1 użytkownika (przez 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")
  }
}

W terminalu możemy użyć curl (lub podobnego narzędzia), aby wykonać query względem serwera GraphQL, przekazując następujące dane:

  • Wykonanie metody POST
  • Akceptowany typ treści to application/json
  • Ciało to słownik z wpisem "query" i query GraphQL (a jeśli potrzeba, również wpisami "variables" i "operationName")
  • Ciąg query musi być sformatowany: wszystkie " muszą być eskejpowane jako \", a znaki nowej linii muszą być zastąpione przez \n
  • Wskazać na URL endpointu Gato GraphQL (pojedynczy endpoint lub wybrany endpoint niestandardowy)
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/

To wyświetla odpowiedź bezpośrednio w terminalu:

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

Wyodrębnianie ID z odpowiedzi GraphQL

Podobnie jak używanie --field=ID, --format=ids lub --porcelain w WP-CLI, musimy znaleźć sposób na wyodrębnienie konkretnego fragmentu danych, którego potrzebujemy z odpowiedzi GraphQL. W tym przykładzie jest to ID użytkownika.

Przypisujemy odpowiedź GraphQL do zmiennej środowiskowej (np. GRAPHQL_RESPONSE) i identyfikujemy ID użytkownika za pomocą określonego aliasu (np. 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/)

Wykonując echo $GRAPHQL_RESPONSE możemy zobaczyć odpowiedź:

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

Następnie wykonujemy grep z wyrażeniem regularnym dopasowującym wzorzec "spanishLocaleUserID":{ID} i wyodrębniamy ID do zmiennej środowiskowej 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)

Teraz możemy wstrzyknąć wartość tej zmiennej do WP-CLI:

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

Zwiększenie czytelności query GraphQL

Przy formatowaniu query GraphQL do wstawienia w curl stała się ona trudna do odczytania.

Rozwiązaniem jest zastosowanie przekształceń za pomocą poleceń bash, takich jak tr i 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/)

Dodawanie podświetlania składni do query GraphQL

Kolejnym krokiem w stosunku do poprzedniego etapu jest umieszczenie query GraphQL w osobnym pliku .gql, który można następnie edytować w edytorze (takim jak VSCode) i korzystać z jego podświetlania składni:

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

Następnie odczytujemy zawartość tego pliku za pomocą 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/)