Internal GraphQL Server
Internal GraphQL ServerInternal GraphQL Server

Internal GraphQL Server

Included in the “Power Extensions” bundle

Esta extensão instala um servidor GraphQL interno, que pode ser invocado dentro da sua aplicação utilizando código PHP.

Entre outros casos de uso, você pode disparar a execução de uma query GraphQL sempre que alguma ação ocorrer, para realizar uma tarefa relacionada (como enviar uma notificação, adicionar uma entrada de log, validar uma condição, etc).

Descrição

O servidor GraphQL interno é acessado por meio da classe GatoGraphQL\InternalGraphQLServer\GraphQLServer, através destes três métodos:

  • executeQuery: Executa uma query GraphQL
  • executeQueryInFile: Executa uma query GraphQL contida em um arquivo (.gql)
  • executePersistedQuery: Executa uma query GraphQL persistida (fornecendo seu ID como int, ou seu slug como string) (a extensão Persisted Queries é necessária)

Estas são as assinaturas dos métodos:

namespace GatoGraphQL\InternalGraphQLServer;
 
use PoP\Root\HttpFoundation\Response;
 
class GraphQLServer {
  /**
   * Execute a GraphQL query
   */
  public static function executeQuery(
    string $query,
    array $variables = [],
    ?string $operationName = null,
    int|string|null $schemaConfigurationIDOrSlug = null,
  ): Response {
    // ...
  }
 
 
  /**
   * Execute a GraphQL query contained in a (`.gql`) file
   */
  public static function executeQueryInFile(
    string $file,
    array $variables = [],
    ?string $operationName = null,
    int|string|null $schemaConfigurationIDOrSlug = null,
  ): Response {
    // ...
  }
 
 
  /**
   * Execute a persisted GraphQL query (providing its object
   * of type WP_Post, ID as an int, or slug as a string)
   */
  public static function executePersistedQuery(
    WP_Post|string|int $persistedQuery,
    array $variables = [],
    ?string $operationName = null
  ): Response {
    // ...
  }
}

Para executar uma query GraphQL e obter o conteúdo da resposta:

// Provide the GraphQL query
$query = "{ ... }";
 
// Execute the query against the internal server
$response = GraphQLServer::executeQuery($query);
 
// Get the content and decode it
$responseContent = json_decode($response->getContent(), true);
 
// Access the data and errors from the response
$responseData = $responseContent["data"] ?? [];
$responseErrors = $responseContent["errors"] ?? [];

O objeto Response também contém qualquer header produzido (por exemplo: se uma Cache Control List foi aplicada, ela adicionaria o header Cache-Control):

$responseHeaders = $response->getHeaders();
$responseCacheControlHeader = $response->getHeaderLine('Cache-Control');

Observe que a classe GraphQLServer não está pronta antes do hook init do core do WordPress.

Configuração do Schema

O Internal GraphQL Server aplica sua própria Configuração de Schema. Por exemplo, a padrão é selecionada na página de Configurações, na aba "Internal GraphQL Server".

Configurando o Internal GraphQL Server nas Configurações

Esta configuração também se aplica sempre que a query executada contra o internal GraphQL server foi disparada por outra query GraphQL enquanto estava sendo resolvida em um endpoint com uma configuração diferente (como o endpoint público graphql/).

Para ilustrar, digamos que configuramos o endpoint único graphql/ para aplicar uma Access Control List a fim de validar usuários por IP, e executamos a mutation createPost contra esse endpoint:

mutation {
  createPost(input: {...}) {
    # ...
  }
}

Assim, apenas visitantes daquele IP poderão executar essa mutation.

Em seguida, há um hook em publish_post que executa uma query contra o internal GraphQL server (por exemplo: para enviar uma notificação ao administrador do site):

add_action(
  "publish_post",
  fn (int $post_id) => GraphQLServer::executeQuery("...", ["postID" => $post_id])
);

Essa query GraphQL será resolvida usando a configuração de schema aplicada ao internal GraphQL server, e não ao endpoint único graphql/.

Como resultado, a validação por IP do usuário não ocorrerá (a não ser que essa Access Control List também tenha sido aplicada ao internal GraphQL server).

Depurando problemas

Para rastrear a execução da query, podemos consultar os logs.

Consulte Resolução de problemas para mais detalhes.

Exemplo

Neste fluxo de trabalho de exemplo (que também utiliza os módulos Multiple Query Execution, Helper Function Collection e Field to Input), quando um novo post é criado no site, enviamos uma notificação ao usuário administrador.

Fazemos o hook na ação do core do WordPress new_to_publish, recuperamos os dados do post recém-criado e chamamos GraphQLServer::executeQuery:

add_action(
  'new_to_publish',
  function (WP_Post $post) {
    if ($post->post_type !== 'post') {
      return;
    }
    // Check the contents of the query below
    $query = ' ... ';
    $variables = [
      'postTitle' => $post->post_title,
      'postContent' => $post->post_content,
    ]
    GraphQLServer::executeQuery($query, $variables, 'SendEmail');
  }
);

...com esta query GraphQL:

query GetEmailData(
  $postTitle: String!,
  $postContent: String!
) {
  emailMessageTemplate: _strConvertMarkdownToHTML(
    text: """
 
There is a new post on the site: 
 
**{$postTitle}**:
 
{$postContent}
 
    """
  )
  emailMessage: _strReplaceMultiple(
    search: ["{$postTitle}", "{$postContent}"],
    replaceWith: [$postTitle, $postContent],
    in: $__emailMessageTemplate
  )
    @export(as: "emailMessage")
}
 
mutation SendEmail @depends(on: "GetEmailData") {
  _sendEmail(
    input: {
      to: "admin@site.com"
      subject: "There is a new post"
      messageAs: {
        html: $emailMessage
      }
    }
  ) {
    status
  }
}