Lição 5: Personalizando conteúdo para diferentes usuários
Podemos recuperar uma resposta diferente em um campo dependendo de algum dado consultado, como os papéis do usuário logado.
Query GraphQL para personalizar conteúdo para diferentes usuários
Esta query GraphQL recupera o conteúdo da publicação, adicionando um link "Editar esta publicação" ao final do conteúdo apenas para o usuário administrador:
query InitializeDynamicVariables
@configureWarningsOnExportingDuplicateVariable(enabled: false)
{
isAdminUser: _echo(value: false)
@export(as: "isAdminUser")
@remove
}
query ExportConditionalVariables
@depends(on: "InitializeDynamicVariables")
{
me {
roleNames @remove
isAdminUser: _inArray(
value: "administrator",
array: $__roleNames
)
@export(as: "isAdminUser")
}
}
query RetrieveContentForAdminUser($postId: ID!)
@depends(on: "ExportConditionalVariables")
@include(if: $isAdminUser)
{
post(by: { id : $postId }) {
originalContent: content @remove
wpAdminEditURL @remove
content: _sprintf(
string: "%s<p><a href=\"%s\">%s</a></p>",
values: [
$__originalContent,
$__wpAdminEditURL,
"(Admin only) Edit post"
]
)
}
}
query RetrieveContentForNonAdminUser($postId: ID!)
@depends(on: "ExportConditionalVariables")
@skip(if: $isAdminUser)
{
post(by: { id : $postId }) {
content
}
}
query ExecuteAll
@depends(on: [
"RetrieveContentForAdminUser",
"RetrieveContentForNonAdminUser"
])
{
id @remove
}Para usuários administradores, a resposta será:
{
"data": {
"user": {
"isAdminUser": true
},
"post": {
"content": "\n<p>Welcome to WordPress. This is your first post. Edit or delete it, then start writing!<\/p>\n<p><a href=\"https:\/\/mysite.com\/wp-admin\/post.php?post=1&action=edit\">(Admin only) Edit post<\/a><\/p>"
}
}
}Para usuários não administradores, a resposta será:
{
"data": {
"user": {
"isAdminUser": false
},
"post": {
"content": "\n<p>Welcome to WordPress. This is your first post. Edit or delete it, then start writing!<\/p>\n"
}
}
}Deixar o servidor GraphQL (considerando todas as possíveis condições) calcular dinamicamente o valor necessário para um campo:
- Simplifica a lógica da aplicação, pois há uma única fonte de verdade, o código se torna DRY e os clientes não precisam mais implementar a lógica correspondente
- Torna a aplicação mais confiável, especialmente quando múltiplos clientes acessam dados do servidor, pois implementações diferentes da mesma lógica podem não ser idênticas, podendo levar a bugs (ainda mais quando os clientes são baseados em tecnologias diferentes, como JavaScript para um site, Java para um app Android, Swift para um app iPhone, entre outros)
Passo a passo: criando a query GraphQL
Abaixo está a análise detalhada de como a query funciona.
Verificando se o usuário é administrador
Esta query verifica se o usuário logado possui o papel "administrator" e exporta essa condição na variável dinâmica $isAdminUser:
query
{
me {
roleNames
isAdminUser: _inArray(
value: "administrator",
array: $__roleNames
)
@export(as: "isAdminUser")
}
}Execução condicional de operações
Quando a Execução de Múltiplas Queries está habilitada, as diretivas @include e @skip também podem ser aplicadas a operações. Dessa forma, podemos executar ou não uma operação dependendo do valor de alguma variável dinâmica.
Na query abaixo, apenas uma das duas operações será executada:
RetrieveContentForAdminUseré executada somente quando$isAdminUserétrueRetrieveContentForNonAdminUseré executada somente quando$isAdminUseréfalse
query RetrieveContentForAdminUser
@depends(on: "ExportConditionalVariables")
@include(if: $isAdminUser)
{
# ...
}
query RetrieveContentForNonAdminUser
@depends(on: "ExportConditionalVariables")
@skip(if: $isAdminUser)
{
# ...
}Vamos fornecer duas respostas diferentes para o campo content da publicação dependendo se o usuário é administrador ou não:
- A primeira operação usa
contentcomo alias e calcula o valor do campo dinamicamente, combinando os camposoriginalContentewpAdminEditURLvia_sprintf - A segunda operação recupera o campo
contentdiretamente
query RetrieveContentForAdminUser($postId: ID!)
@depends(on: "ExportConditionalVariables")
@include(if: $isAdminUser)
{
post(by: { id : $postId }) {
originalContent: content
wpAdminEditURL
content: _sprintf(
string: "%s<p><a href=\"%s\">%s</a></p>",
values: [
$__originalContent,
$__wpAdminEditURL,
"(Admin only) Edit post"
]
)
}
}
query RetrieveContentForNonAdminUser($postId: ID!)
@depends(on: "ExportConditionalVariables")
@skip(if: $isAdminUser)
{
post(by: { id : $postId }) {
content
}
}Adicionando a operação a ser executada
Agora temos duas operações que podem ser executadas, porém podemos fornecer apenas um ?operationName=... ao executar a query.
Então, adicionamos a operação ExecuteAll que depende tanto de RetrieveContentForAdminUser quanto de RetrieveContentForNonAdminUser, contendo o campo simples id (porque precisamos consultar algo na operação):
query ExecuteAll
@depends(on: [
"RetrieveContentForAdminUser",
"RetrieveContentForNonAdminUser"
])
{
id
}Ao invocar o endpoint com ?operationName=ExecuteAll, ambas as operações serão carregadas, porém apenas uma delas será efetivamente executada.
Removendo dados desnecessários
O passo final é remover todos os campos que são auxiliares (e que, portanto, não precisamos imprimir na resposta) via @remove.
A query GraphQL consolidada é:
query InitializeDynamicVariables
@configureWarningsOnExportingDuplicateVariable(enabled: false)
{
isAdminUser: _echo(value: false)
@export(as: "isAdminUser")
@remove
}
query ExportConditionalVariables
@depends(on: "InitializeDynamicVariables")
{
me {
roleNames @remove
isAdminUser: _inArray(
value: "administrator",
array: $__roleNames
)
@export(as: "isAdminUser")
}
}
query RetrieveContentForAdminUser($postId: ID!)
@depends(on: "ExportConditionalVariables")
@include(if: $isAdminUser)
{
post(by: { id : $postId }) {
originalContent: content @remove
wpAdminEditURL @remove
content: _sprintf(
string: "%s<p><a href=\"%s\">%s</a></p>",
values: [
$__originalContent,
$__wpAdminEditURL,
"(Admin only) Edit post"
]
)
}
}
query RetrieveContentForNonAdminUser($postId: ID!)
@depends(on: "ExportConditionalVariables")
@skip(if: $isAdminUser)
{
post(by: { id : $postId }) {
content
}
}
query ExecuteAll
@depends(on: [
"RetrieveContentForAdminUser",
"RetrieveContentForNonAdminUser"
])
{
id @remove
}