Lección 3: Duplicar una entrada de blog
Duplicar una entrada es un ejemplo de la capacidad de Gato GraphQL para recuperar, manipular y volver a guardar datos en el sitio.
Consulta GraphQL para duplicar una entrada de blog
Esta consulta GraphQL duplica la entrada indicada por la variable $postId:
query InitializeDynamicVariables
@configureWarningsOnExportingDuplicateVariable(enabled: false)
{
authorID: _echo(value: null)
@export(as: "authorID")
@remove
categoryIDs: _echo(value: [])
@export(as: "categoryIDs")
@remove
featuredImageID: _echo(value: null)
@export(as: "featuredImageID")
@remove
tagIDs: _echo(value: [])
@export(as: "tagIDs")
@remove
}
query GetPostAndExportData($postId: ID!)
@depends(on: "InitializeDynamicVariables")
{
post(by: { id : $postId }) {
# Fields not to be duplicated
id
slug
date
status
# Fields to be duplicated
author {
id @export(as: "authorID")
}
categories {
id @export(as: "categoryIDs", type: LIST)
}
rawContent @export(as: "rawContent")
rawExcerpt @export(as: "excerpt")
featuredImage {
id @export(as: "featuredImageID")
}
tags {
id @export(as: "tagIDs", type: LIST)
}
rawTitle @export(as: "title")
}
}
mutation DuplicatePost
@depends(on: "GetPostAndExportData")
{
createPost(input: {
status: draft,
authorBy: {
id: $authorID
},
categoriesBy: {
ids: $categoryIDs
},
contentAs: {
html: $rawContent
},
excerpt: $excerpt
featuredImageBy: {
id: $featuredImageID
},
tagsBy: {
ids: $tagIDs
},
title: $title
}) {
status
errors {
__typename
...on ErrorPayload {
message
}
}
post {
# Fields not to be duplicated
id
slug
date
status
# Fields to be duplicated
author {
id
}
categories {
id
}
rawContent
excerpt
featuredImage {
id
}
tags {
id
}
title
}
}
}Paso a paso: creación de la consulta GraphQL
A continuación se muestra el análisis detallado de cómo funciona la consulta.
Obtener los datos de la entrada
Esta consulta GraphQL obtiene los datos fundamentales de una entrada:
query GetPost($postId: ID!) {
post(by: { id : $postId }) {
# Fields not to be duplicated
id
slug
date
status
# Fields to be duplicated
author {
id
}
categories {
id
}
rawContent
excerpt
featuredImage {
id
}
tags {
id
}
title
}
}Ejecutando la consulta (pasando la variable $postId), la respuesta puede ser:
{
"data": {
"post": {
"id": 25,
"slug": "public-or-private-api-mode-for-extra-security",
"date": "2020-12-12T04:06:52+00:00",
"author": {
"id": 2
},
"categories": [
{
"id": 4
},
{
"id": 3
},
{
"id": 2
}
],
"rawContent": "<!-- wp:heading -->\n<h2>Verse Block</h2>\n<!-- /wp:heading -->\n\n<!-- wp:verse -->\n<pre class=\"wp-block-verse\">Write poetry and other literary expressions honoring all spaces and line-breaks.</pre>\n<!-- /wp:verse -->\n\n<!-- wp:heading -->\n<h2>Table Block</h2>\n<!-- /wp:heading -->\n\n<!-- wp:table {\"className\":\"is-style-stripes\"} -->\n<figure class=\"wp-block-table is-style-stripes\"><table><tbody><tr><td>Row 1 Column 1</td><td>Row 1 Column 2</td></tr><tr><td>Row 2 Column 1</td><td>Row 2 Column 2</td></tr><tr><td>Row 3 Column 1</td><td>Row 3 Column 2</td></tr></tbody></table></figure>\n<!-- /wp:table -->\n\n<!-- wp:heading -->\n<h2>Separator Block</h2>\n<!-- /wp:heading -->\n\n<!-- wp:separator -->\n<hr class=\"wp-block-separator\"/>\n<!-- /wp:separator -->\n\n<!-- wp:heading {\"className\":\"has-top-margin\"} -->\n<h2 class=\"has-top-margin\">Spacer Block</h2>\n<!-- /wp:heading -->\n\n<!-- wp:spacer -->\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"></div>\n<!-- /wp:spacer -->",
"excerpt": "Verse Block Write poetry and other literary expressions honoring all spaces and line-breaks. Table Block Row 1 Column 1 Row 1 Column 2 Row 2 Column 1 Row 2 Column 2 Row 3 Column 1 Row 3 Column 2 Separator Block Spacer Block",
"featuredImage": {
"id": 362
},
"tags": [
{
"id": 12
},
{
"id": 7
}
],
"title": "Public or Private API mode, for extra security"
}
}
}Observa que algunos campos están pensados para ser duplicados (incluyendo el autor, el título y el contenido), mientras que otros no (como el id, el slug y la fecha de creación).
Duplicar la entrada: primer enfoque
Con la extensión Ejecución de múltiples consultas podemos exportar los datos de la entrada e inyectarlos de nuevo en otra query o mutation del mismo documento GraphQL.
Ejecución de múltiples consultas nos permite ejecutar funcionalidad compleja dentro de una sola petición y organizar mejor la lógica dividiendo el documento GraphQL en una serie de unidades lógicas/atómicas:
- No hay límite en cuántas operaciones pueden añadirse al pipeline
- Cualquier operación puede declarar más de una dependencia:
query SomeQuery @depends(on: ["SomePreviousOp", "AnotherPreviousOp"]) {
# ...
}- Cualquier operación puede depender de otra operación, que a su vez depende de otra operación, y así sucesivamente:
query ExecuteFirst
# ...
}
query ExecuteSecond @depends(on: ["ExecuteFirst"]) {
# ...
}
query ExecuteThird @depends(on: ["ExecuteSecond"]) {
# ...
}-
Podemos ejecutar cualquiera de las operaciones del documento:
?operationName=ExecuteThirdejecutaExecuteFirst>ExecuteSecond>ExecuteThird?operationName=ExecuteSecondejecutaExecuteFirst>ExecuteSecond?operationName=ExecuteFirstejecutaExecuteFirst
-
Cuando
@dependsrecibe sólo una operación, puede recibir unString(en lugar de[String]):
query ExecuteFirst
# ...
}
query ExecuteSecond @depends(on: "ExecuteFirst") {
# ...
}- Tanto las operaciones
querycomomutationpueden depender unas de otras:
query GetAndExportData
# ...
}
mutation MutateData @depends(on: "GetAndExportData") {
# ...
}
query CountMutatedResults @depends(on: "MutateData") {
# ...
}- Las variables dinámicas no necesitan declararse en la operación
- Mediante el input
@export(type:)podemos seleccionar la salida de los datos exportados en la variable dinámica:SINGLE(por defecto): un único valor de campoLIST: un array que contiene el valor del campo de varios recursosDICTIONARY: un diccionario que contiene el valor del campo de varios recursos, con clave:${resource ID}y valor:${field value}
La siguiente consulta crea un pipeline de dos operaciones en el documento GraphQL (GetPostAndExportData y DuplicatePost), que pueden compartir datos entre sí:
DuplicatePostindica que se ejecute primeroGetPostAndExportDatamediante la directiva@dependsGetPostAndExportDataexporta datos mediante la directiva@exporta variables dinámicasDuplicatePostluego lee las variables dinámicas y las pasa como input a la mutacióncreatePost
query GetPostAndExportData($postId: ID!) {
post(by: { id : $postId }) {
# Fields not to be duplicated
id
slug
date
status
# Fields to be duplicated
author {
id @export(as: "authorID")
}
categories {
id @export(as: "categoryIDs", type: LIST)
}
rawContent @export(as: "rawContent")
rawExcerpt @export(as: "excerpt")
featuredImage {
id @export(as: "featuredImageID")
}
tags {
id @export(as: "tagIDs", type: LIST)
}
rawTitle @export(as: "title")
}
}
mutation DuplicatePost
@depends(on: "GetPostAndExportData")
{
createPost(input: {
status: draft,
authorBy: {
id: $authorID
},
categoriesBy: {
ids: $categoryIDs
},
contentAs: {
html: $rawContent
},
excerpt: $excerpt
featuredImageBy: {
id: $featuredImageID
},
tagsBy: {
ids: $tagIDs
},
title: $title
}) {
status
errors {
__typename
...on ErrorPayload {
message
}
}
post {
# Fields not to be duplicated
id
slug
date
status
# Fields to be duplicated
author {
id
}
categories {
id
}
rawContent
excerpt
featuredImage {
id
}
tags {
id
}
title
}
}
}En la respuesta podemos visualizar que los campos de la nueva entrada son efectivamente los mismos:
{
"data": {
"post": {
"id": 25,
"slug": "public-or-private-api-mode-for-extra-security",
"date": "2020-12-12T04:06:52+00:00",
"status": "publish",
"author": {
"id": 2
},
"categories": [
{
"id": 4
},
{
"id": 3
},
{
"id": 2
}
],
"rawContent": "<!-- wp:heading -->\n<h2>Verse Block</h2>\n<!-- /wp:heading -->\n\n<!-- wp:verse -->\n<pre class=\"wp-block-verse\">Write poetry and other literary expressions honoring all spaces and line-breaks.</pre>\n<!-- /wp:verse -->\n\n<!-- wp:heading -->\n<h2>Table Block</h2>\n<!-- /wp:heading -->\n\n<!-- wp:table {\"className\":\"is-style-stripes\"} -->\n<figure class=\"wp-block-table is-style-stripes\"><table><tbody><tr><td>Row 1 Column 1</td><td>Row 1 Column 2</td></tr><tr><td>Row 2 Column 1</td><td>Row 2 Column 2</td></tr><tr><td>Row 3 Column 1</td><td>Row 3 Column 2</td></tr></tbody></table></figure>\n<!-- /wp:table -->\n\n<!-- wp:heading -->\n<h2>Separator Block</h2>\n<!-- /wp:heading -->\n\n<!-- wp:separator -->\n<hr class=\"wp-block-separator\"/>\n<!-- /wp:separator -->\n\n<!-- wp:heading {\"className\":\"has-top-margin\"} -->\n<h2 class=\"has-top-margin\">Spacer Block</h2>\n<!-- /wp:heading -->\n\n<!-- wp:spacer -->\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"></div>\n<!-- /wp:spacer -->",
"excerpt": "Verse Block Write poetry and other literary expressions honoring all spaces and line-breaks. Table Block Row 1 Column 1 Row 1 Column 2 Row 2 Column 1 Row 2 Column 2 Row 3 Column 1 Row 3 Column 2 Separator Block Spacer Block",
"featuredImage": {
"id": 362
},
"tags": [
{
"id": 12
},
{
"id": 7
}
],
"title": "Public or Private API mode, for extra security"
},
"createPost": {
"status": "SUCCESS",
"errors": null,
"post": {
"id": 1207,
"slug": "public-or-private-api-mode-for-extra-security-2",
"date": "2023-07-07T02:06:17+00:00",
"status": "draft",
"author": {
"id": 2
},
"categories": [
{
"id": 4
},
{
"id": 3
},
{
"id": 2
}
],
"rawContent": "<!-- wp:heading -->\n<h2>Verse Block</h2>\n<!-- /wp:heading -->\n\n<!-- wp:verse -->\n<pre class=\"wp-block-verse\">Write poetry and other literary expressions honoring all spaces and line-breaks.</pre>\n<!-- /wp:verse -->\n\n<!-- wp:heading -->\n<h2>Table Block</h2>\n<!-- /wp:heading -->\n\n<!-- wp:table {\"className\":\"is-style-stripes\"} -->\n<figure class=\"wp-block-table is-style-stripes\"><table><tbody><tr><td>Row 1 Column 1</td><td>Row 1 Column 2</td></tr><tr><td>Row 2 Column 1</td><td>Row 2 Column 2</td></tr><tr><td>Row 3 Column 1</td><td>Row 3 Column 2</td></tr></tbody></table></figure>\n<!-- /wp:table -->\n\n<!-- wp:heading -->\n<h2>Separator Block</h2>\n<!-- /wp:heading -->\n\n<!-- wp:separator -->\n<hr class=\"wp-block-separator\"/>\n<!-- /wp:separator -->\n\n<!-- wp:heading {\"className\":\"has-top-margin\"} -->\n<h2 class=\"has-top-margin\">Spacer Block</h2>\n<!-- /wp:heading -->\n\n<!-- wp:spacer -->\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"></div>\n<!-- /wp:spacer -->",
"excerpt": "Verse Block Write poetry and other literary expressions honoring all spaces and line-breaks. Table Block Row 1 Column 1 Row 1 Column 2 Row 2 Column 1 Row 2 Column 2 Row 3 Column 1 Row 3 Column 2 Separator Block Spacer Block",
"featuredImage": {
"id": 362
},
"tags": [
{
"id": 12
},
{
"id": 7
}
],
"title": "Public or Private API mode, for extra security"
}
}
}
}Problemas con el primer enfoque
La consulta de arriba devolverá un error cuando un campo de conexión esté vacío, ya que la variable dinámica no se exportará.
Por ejemplo, cuando la entrada a duplicar no tiene imagen destacada, el campo featuredImage será null y por tanto id @export(as: "featuredImageID") nunca se ejecutará:
{
post {
featuredImage {
id @export(as: "featuredImageID")
}
}
}Como la variable dinámica $featuredImageID no existirá, la respuesta dará un error:
{
"errors": [
{
"message": "No value has been exported for dynamic variable 'featuredImageID'",
"locations": [
{
"line": 39,
"column": 22
}
]
}
],
"data": {
// ...
}
}Los dos enfoques siguientes abordan este problema.
Duplicar la entrada: segundo enfoque
Los campos de conexión también almacenan un valor en Gato GraphQL. Cuando se resuelven por primera vez, esos campos contienen el ID o los IDs del recurso o recursos al que apuntan (ya sea el ID del recurso enlazado o un array con los IDs de los recursos enlazados). Solo más tarde, cuando se resuelve la conexión, los IDs se sustituirán por los objetos reales del recurso.
Por ejemplo, en la siguiente consulta:
{
post {
featuredImage {
id
}
tags {
id
}
}
}...el campo featuredImage contendrá inicialmente 362 (ese es el ID de la imagen destacada) y el campo tags contendrá el array [12, 7] (esos son los IDs de las etiquetas).
Cuando el valor a exportar es un ID (como $featuredImageID) o un array de IDs (como $tagIDs), podemos aprovechar esta característica y exportar ya los IDs en el campo de conexión.
En vez de hacer esto:
{
post {
featuredImage {
id @export(as: "featuredImageID")
}
tags {
id @export(as: "tagIDs", type: LIST)
}
}
}...podemos hacer esto:
{
post {
featuredImage @export(as: "featuredImageID") {
id
}
tags @export(as: "tagIDs") {
id
}
}
}(Observa que el argumento type: LIST se ha quitado al exportar $tagIDs, ya que el campo de conexión ya es una lista.)
Ahora estas variables dinámicas siempre se exportarán, con valor:
nullpara$featuredImageIDcuando la entrada no tenga imagen destacada- el array vacío
[]para$tagIDscuando la entrada no tenga etiquetas
Adaptando la consulta GraphQL, ahora queda así:
query GetPostAndExportData($postId: ID!) {
post(by: { id : $postId }) {
# Fields not to be duplicated
id
slug
date
status
# Fields to be duplicated
author @export(as: "authorID") {
id
}
categories @export(as: "categoryIDs") {
id
}
rawContent @export(as: "rawContent")
rawExcerpt @export(as: "excerpt")
featuredImage @export(as: "featuredImageID") {
id
}
tags @export(as: "tagIDs") {
id
}
rawTitle @export(as: "title")
}
}
mutation DuplicatePost
@depends(on: "GetPostAndExportData")
{
createPost(input: {
status: draft,
authorBy: {
id: $authorID
},
categoriesBy: {
ids: $categoryIDs
},
contentAs: {
html: $rawContent
},
excerpt: $excerpt
featuredImageBy: {
id: $featuredImageID
},
tagsBy: {
ids: $tagIDs
},
title: $title
}) {
status
errors {
__typename
...on ErrorPayload {
message
}
}
post {
# Fields not to be duplicated
id
slug
date
status
# Fields to be duplicated
author {
id
}
categories {
id
}
rawContent
excerpt
featuredImage {
id
}
tags {
id
}
title
}
}
}...la respuesta ahora funciona correctamente:
{
"data": {
"post": {
"id": 23,
"slug": "graphql-or-rest-you-can-have-both",
"date": "2020-12-12T04:04:54+00:00",
"status": "publish",
"author": {
"id": 2
},
"categories": [
{
"id": 1
}
],
"rawContent": "<!-- wp:heading -->\n<h2>Audio Block</h2>\n<!-- /wp:heading -->\n\n<!-- wp:audio -->\n<figure class=\"wp-block-audio\"><audio controls src=\"https://freemusicarchive.org/file/music/WFMU/Broke_For_Free/Directionless_EP/Broke_For_Free_-_01_-_Night_Owl.mp3\"></audio></figure>\n<!-- /wp:audio -->\n\n<!-- wp:heading -->\n<h2>Video Block</h2>\n<!-- /wp:heading -->\n\n<!-- wp:video -->\n<figure class=\"wp-block-video\"><video controls src=\"https://archive.org/download/SlowMotionFlame/slomoflame_512kb.mp4\"></video></figure>\n<!-- /wp:video -->\n\n<!-- wp:heading -->\n<h2>Custom HTML Block</h2>\n<!-- /wp:heading -->\n\n<!-- wp:html -->\n<strong>This is a HTML block.</strong>\n<!-- /wp:html -->\n\n<!-- wp:heading {\"className\":\"has-top-margin\"} -->\n<h2 class=\"has-top-margin\">Preformatted Block</h2>\n<!-- /wp:heading -->\n\n<!-- wp:preformatted -->\n<pre class=\"wp-block-preformatted\">This is some preformatted text. Preformatted text keeps your s p a c e s, tabs and<br>linebreaks as they are.</pre>\n<!-- /wp:preformatted -->",
"excerpt": "Audio Block Video Block Custom HTML Block This is a HTML block. Preformatted Block This is some preformatted text. Preformatted text keeps your s p a c e s, tabs andlinebreaks as they are.",
"featuredImage": null,
"tags": [],
"title": "GraphQL or REST? Why not both?"
},
"createPost": {
"status": "SUCCESS",
"errors": null,
"post": {
"id": 1209,
"slug": "graphql-or-rest-why-not-both",
"date": "2023-07-07T03:24:31+00:00",
"status": "draft",
"author": {
"id": 2
},
"categories": [
{
"id": 1
}
],
"rawContent": "<!-- wp:heading -->\n<h2>Audio Block</h2>\n<!-- /wp:heading -->\n\n<!-- wp:audio -->\n<figure class=\"wp-block-audio\"><audio controls src=\"https://freemusicarchive.org/file/music/WFMU/Broke_For_Free/Directionless_EP/Broke_For_Free_-_01_-_Night_Owl.mp3\"></audio></figure>\n<!-- /wp:audio -->\n\n<!-- wp:heading -->\n<h2>Video Block</h2>\n<!-- /wp:heading -->\n\n<!-- wp:video -->\n<figure class=\"wp-block-video\"><video controls src=\"https://archive.org/download/SlowMotionFlame/slomoflame_512kb.mp4\"></video></figure>\n<!-- /wp:video -->\n\n<!-- wp:heading -->\n<h2>Custom HTML Block</h2>\n<!-- /wp:heading -->\n\n<!-- wp:html -->\n<strong>This is a HTML block.</strong>\n<!-- /wp:html -->\n\n<!-- wp:heading {\"className\":\"has-top-margin\"} -->\n<h2 class=\"has-top-margin\">Preformatted Block</h2>\n<!-- /wp:heading -->\n\n<!-- wp:preformatted -->\n<pre class=\"wp-block-preformatted\">This is some preformatted text. Preformatted text keeps your s p a c e s, tabs and<br>linebreaks as they are.</pre>\n<!-- /wp:preformatted -->",
"excerpt": "Audio Block Video Block Custom HTML Block This is a HTML block. Preformatted Block This is some preformatted text. Preformatted text keeps your s p a c e s, tabs andlinebreaks as they are.",
"featuredImage": null,
"tags": [],
"title": "GraphQL or REST? Why not both?"
}
}
}
}Problemas con el segundo enfoque
La solución de arriba sólo funciona para exportar IDs (ya que esos son los valores almacenados en los campos de conexión). No funcionará para nada más, como los slugs de etiquetas:
{
post {
tags {
slug @export(as: "tagSlugs", type: LIST)
}
}
}El siguiente enfoque aborda este problema.
Duplicar la entrada: tercer enfoque
Podemos ejecutar una operación adicional al principio para inicializar cada una de las variables dinámicas con un valor null o vacío (mediante el campo global _echo de la extensión PHP Functions via Schema).
Entonces, cada variable dinámica siempre se exportará al menos una vez. Cuando el valor del campo no esté vacío, se exportará de nuevo y este segundo valor sobreescribirá al primero.
En esta consulta, la variable dinámica $tagSlugs se inicializa con un array vacío y luego se exportará de nuevo si la entrada tiene slugs:
query InitializeDynamicVariables {
tagSlugs: _echo(value: []) @export(as: "tagSlugs")
}
query ExportData
@depends(on: "InitializeDynamicVariables")
{
post {
tags {
slug @export(as: "tagSlugs", type: LIST)
}
}
}- El campo global
_echodevuelve cualquier cosa que se le pase, sea del tipo que sea:
query {
string: _echo(value: "page")
int: _echo(value: 3)
bool: _echo(value: true)
jsonObject: _echo(value: {
name: "Robert"
surname: "Spencer"
})
null: _echo(value: null)
arrayOfString: _echo(value: ["something", "new"])
arrayOfInt: _echo(value: [1, 3, 5])
arrayOfArraysOfBool: _echo(value: [[true, false], [false]])
arrayOfMixed: _echo(value: [1, true, "string", [1, 3, 5], {key: "value"}])
}Esta solución es más completa que la anterior, ya que sirve para exportar cualquier tipo de dato (sean IDs u otros).
Adaptando la consulta GraphQL, ahora queda así:
query InitializeDynamicVariables {
authorID: _echo(value: null) @export(as: "authorID")
categoryIDs: _echo(value: []) @export(as: "categoryIDs")
featuredImageID: _echo(value: null) @export(as: "featuredImageID")
tagIDs: _echo(value: []) @export(as: "tagIDs")}
query GetPostAndExportData($postId: ID!)
@depends(on: "InitializeDynamicVariables")
{
post(by: { id : $postId }) {
# Fields not to be duplicated
id
slug
date
status
# Fields to be duplicated
author {
id @export(as: "authorID")
}
categories {
id @export(as: "categoryIDs", type: LIST)
}
rawContent @export(as: "rawContent")
rawExcerpt @export(as: "excerpt")
featuredImage {
id @export(as: "featuredImageID")
}
tags {
id @export(as: "tagIDs", type: LIST)
}
rawTitle @export(as: "title")
}
}
mutation DuplicatePost
@depends(on: "GetPostAndExportData")
{
createPost(input: {
status: draft,
authorBy: {
id: $authorID
},
categoriesBy: {
ids: $categoryIDs
},
contentAs: {
html: $rawContent
},
excerpt: $excerpt
featuredImageBy: {
id: $featuredImageID
},
tagsBy: {
ids: $tagIDs
},
title: $title
}) {
status
errors {
__typename
...on ErrorPayload {
message
}
}
post {
# Fields not to be duplicated
id
slug
date
status
# Fields to be duplicated
author {
id
}
categories {
id
}
rawContent
excerpt
featuredImage {
id
}
tags {
id
}
title
}
}
}Avisos en el tercer enfoque
Siempre que una variable dinámica se exporta más de una vez, el motor GraphQL añade por defecto un aviso a la respuesta GraphQL:
{
"extensions": {
"warnings": [
{
"message": "Dynamic variable with name 'tagSlugs' had already been set, had its value overridden",
"locations": [
{
"line": 22,
"column": 21
}
]
}
]
},
"data": {
// ...
}
}El enfoque consolidado siguiente aborda este aviso.
Duplicar la entrada: enfoque consolidado
Usamos la consulta GraphQL del enfoque anterior y la optimizamos:
- No mostrando el aviso de "variable dinámica duplicada"
- No imprimiendo los valores de los campos de
InitializeDynamicVariablesen la respuesta GraphQL (ya que no se necesitan, son simplemente campos auxiliares)
Tratamos estos elementos (respectivamente):
- Añadiendo la directiva
@configureWarningsOnExportingDuplicateVariable(enabled: false)a la operación, que desactiva la emisión del aviso - Añadiendo la directiva
@remove(de la extensión Eliminación de la Respuesta de un Campo) a cada uno de los campos a eliminar
Esta es la consulta GraphQL consolidada para duplicar una entrada:
query InitializeDynamicVariables
@configureWarningsOnExportingDuplicateVariable(enabled: false)
{
authorID: _echo(value: null)
@export(as: "authorID")
@remove
categoryIDs: _echo(value: [])
@export(as: "categoryIDs")
@remove
featuredImageID: _echo(value: null)
@export(as: "featuredImageID")
@remove
tagIDs: _echo(value: [])
@export(as: "tagIDs")
@remove
}
query GetPostAndExportData($postId: ID!)
@depends(on: "InitializeDynamicVariables")
{
post(by: { id : $postId }) {
# Fields not to be duplicated
id
slug
date
status
# Fields to be duplicated
author {
id @export(as: "authorID")
}
categories {
id @export(as: "categoryIDs", type: LIST)
}
rawContent @export(as: "rawContent")
rawExcerpt @export(as: "excerpt")
featuredImage {
id @export(as: "featuredImageID")
}
tags {
id @export(as: "tagIDs", type: LIST)
}
rawTitle @export(as: "title")
}
}
mutation DuplicatePost
@depends(on: "GetPostAndExportData")
{
createPost(input: {
status: draft,
authorBy: {
id: $authorID
},
categoriesBy: {
ids: $categoryIDs
},
contentAs: {
html: $rawContent
},
excerpt: $excerpt
featuredImageBy: {
id: $featuredImageID
},
tagsBy: {
ids: $tagIDs
},
title: $title
}) {
status
errors {
__typename
...on ErrorPayload {
message
}
}
post {
# Fields not to be duplicated
id
slug
date
status
# Fields to be duplicated
author {
id
}
categories {
id
}
rawContent
excerpt
featuredImage {
id
}
tags {
id
}
title
}
}
}