Tutorial do schema
Tutorial do schemaLição 16: Enviando uma notificação quando há um novo post

Lição 16: Enviando uma notificação quando há um novo post

O Gato GraphQL pode nos ajudar a automatizar tarefas na aplicação, como o envio de um e-mail de notificação ao administrador quando há um novo post.

Nesta lição do tutorial, exploraremos duas maneiras de alcançar esse resultado.

Query GraphQL para enviar um e-mail de notificação ao administrador

Esta query GraphQL envia um e-mail ao usuário administrador, notificando-o da criação de um novo post no site:

query GetEmailData(
  $postTitle: String!,
  $postContent: String!
  $postURL: URL!
) {
  adminEmail: optionValue(name: "admin_email")
    @export(as: "adminEmail")
 
  emailMessageTemplate: _strConvertMarkdownToHTML(
    text: """
 
There is a [new post on the site]({$postURL}):
 
**{$postTitle}**:
 
{$postContent}
 
    """
  )
  emailMessage: _strReplaceMultiple(
    search: ["{$postTitle}", "{$postContent}", "{$postURL}"],
    replaceWith: [$postTitle, $postContent, $postURL],
    in: $__emailMessageTemplate
  )
    @export(as: "emailMessage")
 
  emailSubject: _sprintf(
    string: "New post: \"%s\"",
    values: [$postTitle]
  )
    @export(as: "emailSubject")
}
 
mutation SendEmail @depends(on: "GetEmailData") {
  _sendEmail(
    input: {
      to: $adminEmail
      subject: $emailSubject
      messageAs: {
        html: $emailMessage
      }
    }
  ) {
    status
  }
}

Para enviar o e-mail em texto simples:

  • Use o input messageAs: { text: ... } na mutation _sendEmail
  • Remova as tags HTML do conteúdo do post usando o campo global _htmlStripTags (fornecido pela extensão PHP Functions via Schema)

Vejamos agora como acionar a execução da query GraphQL.

Opção 1: Acionar sempre reagindo aos hooks do WordPress

Nos conectamos à action do WordPress core new_to_publish, recuperamos os dados do post recém-criado e executamos a query GraphQL definida acima contra o servidor GraphQL interno (fornecido pela extensão Internal GraphQL Server):

use GatoGraphQL\InternalGraphQLServer\GraphQLServer;
use WP_Post;
 
// The GraphQL query, under var `$query`, is the one defined above
// $query = '...';
add_action(
  'new_to_publish',
  function (WP_Post $post) use ($query) {
    $variables = [
      'postTitle' => $post->post_title,
      'postContent' => $post->post_content,
      'postURL' => get_permalink($post->ID),
    ]
    GraphQLServer::executeQuery($query, $variables, 'SendEmail');
  }
);

A classe GatoGraphQL\InternalGraphQLServer\GraphQLServer não é acessível como uma API externa. Em vez disso, ela deve ser usada pela aplicação via código PHP, para executar/automatizar tarefas administrativas por meio de queries GraphQL.

Esta classe fornece 3 métodos estáticos para executar queries:

  • executeQuery: Executa uma query GraphQL
  • executeQueryInFile: Executa uma query GraphQL contida em um arquivo (.gql)
  • executePersistedQuery: Executa uma persisted GraphQL query (fornecendo seu ID como int, ou o slug como string)

Esta query GraphQL será executada sempre que um novo post for criado ou, mais precisamente, sempre que a função WordPress wp_insert_post for invocada (pois essa função aciona o hook new_to_publish):

$postID = wp_insert_post([
  'post_title' => 'Hello world!'
]);

Este também é o caso ao executar outra query GraphQL que executa a mutation createPost (pois seu resolver, no código PHP, invoca a função wp_insert_post):

mutation CreatePost {
  createPost(input: {
    title: "Hello world!"
  }) {
    status
    postID
  }
}

O GraphQL Server (que é "externo", acessado como uma API via HTTP) e o Internal GraphQL Server executarão suas queries aplicando sua própria Schema Configuration, mesmo quando suas execuções estiverem entrelaçadas.

Por exemplo, digamos que estamos executando uma query GraphQL contra o single endpoint e ela cria um post ao executar a mutation createPost. A seguinte sequência de etapas ocorre:

(Externo) GraphQL ServerInternal GraphQL Server
Executa a query GraphQL contra o single endpoint, usando sua própria Schema Configuration(não ativo)
Cria um post; isso aciona new_to_publish(não ativo)
(aguardando...)Reage ao hook new_to_publish: Inicializa o Internal GraphQL server, usando sua própria Schema Configuration
(aguardando...)Executa a query para enviar um e-mail
(aguardando...)Envia o e-mail, fim dessa query
(aguardando...)Encerra o servidor
Continua a execução da query, fim dessa query(não ativo)
Encerra o servidor(não ativo)

Opção 2: Acionar encadeando queries GraphQL

A extensão Automation faz com que o GraphQL Server acione um hook após concluir a execução de uma query GraphQL. Isso nos permite encadear queries GraphQL.

Este código PHP executa a operação SendEmail (query GraphQL definida acima), após o servidor GraphQL ter executado outra query com a operação CreatePost (query GraphQL definida acima):

// The GraphQL query, under var `$query`, is the one defined above
// $query = '...';
add_action(
  "gatographql__executed_query:CreatePost",
  function (Response $response) use ($query) {
    // @var string
    $responseContent = $response->getContent();
    // @var array<string,mixed>
    $responseJSON = json_decode($responseContent, true);
    $postID = $responseJSON['data']['createPost']['postID'] ?? null;
    if ($postID === null) {
      // Do nothing
      return;
    }
 
    $post = get_post($postID);
    $variables = [
      'postTitle' => $post->post_title,
      'postContent' => $post->post_content,
      'postURL' => get_permalink($post->ID),
    ]
    GraphQLServer::executeQuery($query, $variables, 'SendEmail');
  }
);

O encadeamento de queries GraphQL nos permite executar uma única query, mesmo quando muitos recursos foram mutados.

Por exemplo, esta query GraphQL atualiza muitos posts:

mutation ReplaceDomains {
  posts {
    id
    rawContent
    adaptedRawContent: _strReplace(
      search: "https://my-old-domain.com"
      replaceWith: "https://my-new-domain.com"
      in: $__rawContent
    )
    update(input: {
      contentAs: { html: $__adaptedRawContent }
    }) {
      status
      postID
    }
  }
}

Dependendo da nossa estratégia, podemos acionar a execução de uma ou mais queries GraphQL adicionais:

Conectando-se a...Aciona o número de queries GraphQL...
post_updated (pelo WordPress core)Uma para cada post atualizado
gatographql__executed_query:ReplaceDomains (pela extensão Automation)Uma no total (receberá os dados de todos os posts atualizados)