Leoloso PoP Versions Save

Interact with all your data in WordPress using GraphQL

1.5.3

4 months ago

Fixed

  • Point the "Missing an extension?" link to the Contact us page
  • Add link to bundles on the Extensions page
  • Fixed typo in readme.txt

1.5.2

4 months ago

Fixed

  • Active bundle or extension, with different version than main plugin, did not show "Active" button in Extensions page

1.5.1

4 months ago

Improvements

Improvements for the WordPress plugin directory (https://wordpress.org/plugins/gatographql/)

  • Plugin description
  • Banner

1.5.0

4 months ago

Automatically deploy plugin to WordPress plugin directory SVN

Whenever creating a new release of the Gato GraphQL plugin, automatically deploy it to the WordPress plugin directory SVN (via 10up/action-wordpress-plugin-deploy).

Improvements

  • Added video to documentation for bundle
  • Added new predefined persisted queries:
    • "Send email to admin about post"
    • "Add comments block to post"

1.4.0

4 months ago

Here's a description of all the changes.

Added predefined custom endpoint "Nested mutations + Entity as mutation payload type"

The new predefined custom endpoint "Nested mutations + Entity as mutation payload type", installed as private, is useful for executing queries that create resources in bulk.

For instance, the "Import posts from CSV" persisted query would need to be run on that client.

Added "Request headers" to GraphiQL clients on single public/private endpoint, and custom endpoints

The GraphiQL client on the single public and private GraphQL endpoints now have the "Request headers" input:

Single private endpoint GraphiQL client with 'Request headers' input

Same for custom endpoints:

Custom endpoint GraphiQL client with 'Request headers' input

(GraphiQL clients on Persisted queries do not have this addition.)

Renamed page "Recipes" to "Tutorial", and added settings to hide it

The page "Recipes" has been renamed to "Tutorial", to better represent its nature. (At the same time, the new "Queries Library" section at gatographql.com demonstrates GraphQL queries to solve common use cases.)

An option to hide the Tutorial section has been added to the Settings page, under "Plugin Configuration > General > Hide Tutorial page?":

Hiding the Tutorial page in the Settings

Alternatively, we can define this value in wp-config.php:

define( 'GATOGRAPHQL_HIDE_TUTORIAL_PAGE', true );

Improvements

  • Renamed existing bundles:
    • “Application Glue & Automator” Bundle => “Tailored WordPress Automator” Bundle
    • “Content Translation” Bundle => “Simplest WordPress Content Translation” Bundle
    • “Public API” Bundle => “Responsible WordPress Public API” Bundle
  • Added documentation for new bundles:
    • “Automated Content Translation & Sync for WordPress Multisite” Bundle
    • “Better WordPress Webhooks” Bundle
    • “Easy WordPress Bulk Transform & Update” Bundle
    • “Private GraphQL Server for WordPress” Bundle
    • “Selective Content Import, Export & Sync for WordPress” Bundle
    • “Unhindered WordPress Email Notifications” Bundle
    • “Versatile WordPress Request API” Bundle

Fixed

  • HTML codes were printed in select inputs in the WordPress editor, they have now been removed

1.3.0

5 months ago

Here's a description of all the changes.

Read GET variables when executing Persisted Queries via POST

When executing a Persisted Query via POST, do still accept variables passed via GET.

For instance:

curl -X POST https://mysite.com/graphql-query/register-a-newsletter-subscriber-from-instawp-to-mailchimp/?mailchimpDataCenterCode=us1&mailchimpAudienceID=88888888

Improvements

  • Pass data via URL params in persisted query "Register a newsletter subscriber from InstaWP to Mailchimp"

Fixed

  • Component docs displayed in the editor were not included in the plugin

1.2.0

6 months ago

Release Notes: 1.2

Here's a description of all the changes.

Added several predefined Persisted Queries

The following Persisted Queries, to execute common admin tasks, are now provided:

Translate content from URL

Given a URL as input, its language, and what language to translate it to, fetches the content from the URL and performs the translation using Google Translate:

query TranslateContent(
  $url: URL!
  $fromLang: String!
  $toLang: String!
) {
  _sendHTTPRequest(input: {
    url: $url,
    method: GET
  }) {
    body
    translated: body @strTranslate(
      from: $fromLang
      to: $toLang
    )
  }
}

For instance, passing the URL of some Markdown file in a GitHub repo, and language code "es":

{
  "url": "https://raw.githubusercontent.com/GatoGraphQL/GatoGraphQL/c870d8906ae1aec3c81acc039c53acc7aab5dff0/layers/GatoGraphQLForWP/plugins/gatographql/docs/modules/single-endpoint/en.md",
  "fromLang": "en",
  "toLang": "es"
}

...will translate the Markdown content to Spanish:

{
  "data": {
    "_sendHTTPRequest": {
      "body": "# Single Endpoint\n\nExecute queries against the GraphQL server through the public single endpoint.\n\nBy default the endpoint is `/graphql/`, and the path can be configured through the Settings.\n\n![Single endpoint in Settings](../../images/settings-single-endpoint.png \"Single endpoint in Settings\")\n\nThe GraphQL single endpoint can be configured by assigning a Schema Configuration to it. To do this, on section \"Schema Configuration\" select the desired entry from the dropdown for \"Schema Configuration for the Single Endpoint\":\n\n<div class=\"img-width-1024\" markdown=1>\n\n![Settings for the Schema Configuration for the Single Endpoint](../../images/settings-schema-configuration-for-single-endpoint.png)\n\n</div>\n\n## Clients\n\nInteract with the single endpoint via the available clients.\n\n### GraphiQL\n\nIf module \"GraphiQL for Single Endpoint\" is enabled, then the single endpoint's GraphiQL client becomes publicly available.\n\nTo open it, click on link \"🟢 GraphiQL (public)\" on the plugin's menu:\n\n<div class=\"img-width-1024\" markdown=1>\n\n![Single endpoint's link to the GraphiQL client](../../images/single-endpoint-graphiql-link.png)\n\n</div>\n\nBy default, the client is exposed under `/graphiql/`. This path can be modified on the Settings, under tab \"GraphiQL for Single Endpoint\":\n\n<div class=\"img-width-1024\" markdown=1>\n\n![Path to GraphiQL client](../../images/settings-graphiql-for-single-endpoint.png)\n\n</div>\n\n### Interactive Schema (Voyager)\n\nIf module \"Interactive Schema for Single Endpoint\" is enabled, then the single endpoint's Voyager client becomes publicly available.\n\nTo open it, click on link \"🟢 Schema (public)\" on the plugin's menu:\n\n<div class=\"img-width-1024\" markdown=1>\n\n![Single endpoint's link to the Interactive Schema client](../../images/single-endpoint-interactive-schema-link.png)\n\n</div>\n\nBy default, the client is exposed under `/schema/`. This path can be modified on the Settings, under tab \"Interactive Schema for Single Endpoint\":\n\n<div class=\"img-width-1024\" markdown=1>\n\n![Path to Voyager client](../../images/settings-interactive-schema-for-single-endpoint.png)\n\n</div>\n",
      "translated": "# Punto final único\n\nEjecute consultas en el servidor GraphQL a través del punto final único público.\n\nDe forma predeterminada, el punto final es `/graphql/` y la ruta se puede configurar a través de Configuración.\n\n![Punto final único en Configuración](../../images/settings-single-endpoint.png \"Punto final único en Configuración\")\n\nEl punto final único GraphQL se puede configurar asignándole una configuración de esquema. Para hacer esto, en la sección \"Configuración del esquema\", seleccione la entrada deseada del menú desplegable para \"Configuración del esquema para el punto final único\":\n\n<div class=\"img-width-1024\" descuento=1>\n\n![Configuración del esquema para el punto final único](../../images/settings-schema-configuration-for-single-endpoint.png)\n\n</div>\n\n## Clientes\n\nInteractúe con el punto final único a través de los clientes disponibles.\n\n### GrafiQL\n\nSi el módulo \"GraphiQL para punto final único\" está habilitado, el cliente GraphiQL del punto final único estará disponible públicamente.\n\nPara abrirlo, haga clic en el enlace \"🟢 GraphiQL (público)\" en el menú del complemento:\n\n<div class=\"img-width-1024\" descuento=1>\n\n![Enlace del punto final único al cliente GraphiQL](../../images/single-endpoint-graphiql-link.png)\n\n</div>\n\nDe forma predeterminada, el cliente está expuesto en `/graphiql/`. Esta ruta se puede modificar en Configuración, en la pestaña \"GraphiQL para punto final único\":\n\n<div class=\"img-width-1024\" descuento=1>\n\n![Ruta al cliente GraphiQL](../../images/settings-graphiql-for-single-endpoint.png)\n\n</div>\n\n### Esquema interactivo (Voyager)\n\nSi el módulo \"Esquema interactivo para punto final único\" está habilitado, el cliente Voyager del punto final único estará disponible públicamente.\n\nPara abrirlo, haga clic en el enlace \"🟢 Esquema (público)\" en el menú del complemento:\n\n<div class=\"img-width-1024\" descuento=1>\n\n![Enlace del punto final único al cliente de esquema interactivo](../../images/single-endpoint-interactive-schema-link.png)\n\n</div>\n\nDe forma predeterminada, el cliente está expuesto en `/schema/`. Esta ruta se puede modificar en Configuración, en la pestaña \"Esquema interactivo para punto final único\":\n\n<div class=\"img-width-1024\" descuento=1>\n\n![Ruta al cliente Voyager](../../images/settings-interactive-schema-for-single-endpoint.png)\n\n</div>\n"
    }
  }
}

It has been added to the Recipes section too, under "Translating content from URL".

Translate post (Classic editor), and Translate posts (Classic editor)

There already were persisted queries "Translate post" and "Translate posts" (in bulk), which deal with translating all the properties inside the Gutenberg blocks in the post.

These have been duly renamed as "Translate post (Gutenberg)" and "Translate posts (Gutenberg)", and new persisted queries have been added to translate content for the Classic editor:

  • Translate post (Classic editor): Translate a single post
  • Translate posts (Classic editor): Translate multiple posts, in bulk

All these queries translate content by calling the Google Translate API, sending all the data within a single request.

Then, if using query "Translate posts (Classic editor)" to translate 5 posts, all data (title, content and excerpt) for all 5 posts is sent all together, providing a rich context that produces a greater accuracy in the translation.

For instance, after translating this post from English to Chinese:

Created posts from CSV

...it became this:

Created posts from CSV

Import post from WordPress RSS feed

Point to the WordPress RSS feed for a post, and create a new post with its data.

For instance, the query will parse the following RSS feed for a single post (normally accessible under https://mysite.com/post-slug/feed/rss/?withoutcomments=1):

<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:wfw="http://wellformedweb.org/CommentAPI/"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:atom="http://www.w3.org/2005/Atom"
  xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
  xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
>
  <channel>
    <title>A tale of two cities &#8211; teaser &#8211; PoP API Demo</title>
    <atom:link href="https://mysite.com/blogroll/a-tale-of-two-cities-teaser/feed/?withoutcomments=1" rel="self" type="application/rss+xml" />
    <link>https://mysite.com</link>
    <description>Just another WordPress site</description>
    <lastBuildDate>Tue, 20 Jul 2021 23:03:59 +0000</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1	</sy:updateFrequency>
    <generator>https://wordpress.org/?v=6.1.1</generator>
    <item>
      <title>A tale of two cities &#8211; teaser</title>
      <link>https://mysite.com/blogroll/a-tale-of-two-cities-teaser/</link>
      <comments>https://mysite.com/blogroll/a-tale-of-two-cities-teaser/#comments</comments>
      <dc:creator><![CDATA[leo]]></dc:creator>
      <pubDate>Mon, 21 Dec 2020 08:24:18 +0000</pubDate>
      <category><![CDATA[Blogroll]]></category>
      <category><![CDATA[championship]]></category>
      <category><![CDATA[book]]></category>
      <guid isPermaLink="false">https://mysite.com/?p=1657</guid>
      <description></description>
      <content:encoded><![CDATA[
<p>It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way—in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>There were a king with a large jaw and a queen with a plain face, on the throne of England; there were a king with a large jaw and a queen with a fair face, on the throne of France. In both countries it was clearer than crystal to the lords of the State preserves of loaves and fishes, that things in general were settled for ever.</p>
<p>It was the year of Our Lord one thousand seven hundred and seventy-five. Spiritual revelations were conceded to England at that favoured period, as at this. Mrs. Southcott had recently attained her five-and-twentieth blessed birthday, of whom a prophetic private in the Life Guards had heralded the sublime appearance by announcing that arrangements were made for the swallowing up of London and Westminster. Even the Cock-lane ghost had been laid only a round dozen of years, after rapping out its messages, as the spirits of this very year last past (supernaturally deficient in originality) rapped out theirs. Mere messages in the earthly order of events had lately come to the English Crown and People, from a congress of British subjects in America: which, strange to relate, have proved more important to the human race than any communications yet received through any of the chickens of the Cock-lane brood.</p>
<p>France, less favoured on the whole as to matters spiritual than her sister of the shield and trident, rolled with exceeding smoothness down hill, making paper money and spending it. Under the guidance of her Christian pastors, she entertained herself, besides, with such humane achievements as sentencing a youth to have his hands cut off, his tongue torn out with pincers, and his body burned alive, because he had not kneeled down in the rain to do honour to a dirty procession of monks which passed within his view, at a distance of some fifty or sixty yards. It is likely enough that, rooted in the woods of France and Norway, there were growing trees, when that sufferer was put to death, already marked by the Woodman, Fate, to come down and be sawn into boards, to make a certain movable framework with a sack and a knife in it, terrible in history. It is likely enough that in the rough outhouses of some tillers of the heavy lands adjacent to Paris, there were sheltered from the weather that very day, rude carts, bespattered with rustic mire, snuffed about by pigs, and roosted in by poultry, which the Farmer, Death, had already set apart to be his tumbrils of the Revolution. But that Woodman and that Farmer, though they work unceasingly, work silently, and no one heard them as they went about with muffled tread: the rather, forasmuch as to entertain any suspicion that they were awake, was to be atheistical and traitorous.</p>
  ]]></content:encoded>          
      <wfw:commentRss>https://mysite.com/blogroll/a-tale-of-two-cities-teaser/feed/</wfw:commentRss>
      <slash:comments>45</slash:comments>
    </item>
  </channel>
</rss>

Import posts from CSV

Provide a CSV to creates posts (as draft) with the corresponding data for each entry (the title, excerpt, content, and author).

For instance, the CSV below will create 3 posts:

Title,Excerpt,Content,Author
Multi-channelled optimal interface,Inventore iste velit et expedita ipsa dolor,"<!-- wp:paragraph -->
<p>Inventore iste velit et expedita ipsa dolor. Optio suscipit qui id harum corporis dignissimos.</p>
<!-- /wp:paragraph -->",admin
Ergonomic motivating parallelism,Consequuntur velit quasi assumenda,"<!-- wp:paragraph -->
<p>Consequuntur velit quasi assumenda. Eum non saepe est. Ut dolorem harum eveniet eaque nemo impedit. Voluptatem commodi modi sed sed animi voluptatem.</p>
<!-- /wp:paragraph -->
<!-- wp:image {""id"":5,""sizeSlug"":""large""} -->
<figure class=""wp-block-image size-large""><img src=""https://mysite.com/wp-content/uploads/2023/09/wordpress0.jpg"" alt="""" class=""wp-image-5""/></figure>
<!-- /wp:image -->
<!-- wp:image {""id"":7,""sizeSlug"":""large""} -->
<figure class=""wp-block-image size-large""><img src=""https://mysite.com/wp-content/uploads/2023/09/wordpress2.jpg"" alt="""" class=""wp-image-7""/></figure>
<!-- /wp:image -->",admin
Down-sized solution-oriented securedline,Ipsam minima qui asperiores dolorum unde voluptas quia voluptate,"<!-- wp:paragraph -->
<p>Ipsam minima qui asperiores dolorum unde voluptas quia voluptate. Incidunt omnis cumque beatae quo deleniti ex. Praesentium nihil et consectetur neque commodi tempora ipsa adipisci. Praesentium perferendis sint est.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Et aut fuga aliquam consequuntur dolore sunt ut ut. Quibusdam in voluptas vitae quia eaque. Eligendi dolorum dolorem vitae et vitae et ut.</p>
<!-- /wp:paragraph -->",admin

After executing the query, we get the results:

Created posts from CSV

Fetch post links

Find all links (i.e. <a href="(...)">(...)</a> strings) in all posts, and lists them down in the response as a JSON object, with properties { href: (...), text: (...) }.

For instance, it may produce this response:

{
  "data": {
    "posts": [
      {
        "id": 1435,
        "title": "Citations from famous authors",
        "links": [
          {
            "href": "https://www.azquotes.com/author/4085-Fyodor_Dostoevsky",
            "text": "Quote by Fyodor Dostoevsky"
          },
          {
            "href": "https://www.azquotes.com/author/14706-Leo_Tolstoy",
            "text": "Quote by Leon Tolstoi"
          },
          {
            "href": "https://www.azquotes.com/author/15138-Voltaire",
            "text": "Quote by Voltaire"
          }
        ]
      },
      {
        "id": 1,
        "title": "Hello world!",
        "links": []
      }
    ]
  }
}

Added XML scalar type

We can now input XML strings via the new XML scalar type, which will validate the correctness of the XML string.

For instance, this query:

{
  _strDecodeXMLAsJSON(xml: """<?xml version="1.0" encoding="UTF-8"?>
  <body>
    <message>Hello world!</message>
  </body>
  """)
}

...will produce:

{
  "data": {
    "_strDecodeXMLAsJSON": {
      "message": "Hello world!"
    }
  }
}

Whereas this query:

{
  _strDecodeXMLAsJSON(xml: """<?xml version="1.0" encoding="UTF-8"?>
  <body>
    <message>Hello world!</message>
  """)
}

...will produce:

{
  "errors": [
    {
      "message": "Cannot cast value '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n  <body>\n  <message>Hello world!<\/message>\n  ' for type 'XML'",
      "locations": [
        {
          "line": 2,
          "column": 31
        }
      ],
      "extensions": {
        "field": "_strDecodeXMLAsJSON(xml: \"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n  <body>\n  <message>Hello world!<\/message>\n  \")",
        "problems": [
          "Premature end of data in tag body line 2\n"
        ]
      }
    }
  ],
  "data": {
    "_strDecodeXMLAsJSON": null
  }
}

Improved documentation

Fixed

  • In predefined persisted queries "Translate post" and "Translate posts", added failIfNonExistingKeyOrPath: false when selecting a block's attributes.{something} property (as it may sometimes not be defined)
  • In predefined persisted query "Import post from WordPress site", added status any to select the post
  • Renamed persisted query "Translate post" to "Translate post (Gutenberg)", and "Translate posts" to "Translate posts (Gutenberg)"

1.1.1

6 months ago

Here's a description of all the changes.

Tested with WordPress 6.4

The plugin has been tested with WordPress 6.4, and the corresponding entry in the plugin's header ("Tested up to") has been updated.

Install setup data: Private "Nested mutations" Custom Endpoint

A "Nested mutations" custom endpoint is already created by the plugin, with a "private" status (i.e. it is accessible only within the wp-admin).

This makes it convenient to compose and execute queries that make use of nested mutations (such as for doing bulk updates) for our internal tasks.

Install setup data: Private Persisted Queries for common admin tasks

Several private persisted queries are already created by the plugin, handling common admin tasks:

  • Fetch posts by thumbnail
  • Fetch users by locale
  • Fetch comments by period
  • Fetch images in core/image blocks
  • Duplicate post
  • Duplicate posts in bulk
  • Replace strings in post
  • Replace string in posts in bulk
  • Regex replace strings in post
  • Regex replace string in posts in bulk
  • Add missing links in post
  • Replace http with https in post
  • Replace and old domain with a new domain in posts in bulk
  • Replace an old post slug with a new post slug in posts in bulk
  • Insert a block in posts in bulk
  • Remove a block from posts in bulk
  • Translate post
  • Translate posts in bulk
  • Import a post from another WordPress site
  • Export a post into another WordPress site
  • (Webhook for InstaWP) Register a new subscriber on Mailchimp (change status from "draft" to "publish to enable it)

Added Settings to enable or disable installing the setup data

An option to enable/disable the installation of the setup data (i.e. the predefined custom endpoints and persisted queries described above) has been added to the Settings page, under "Plugin Configuration > General > Plugin setup: Install Persisted Queries for common admin tasks?":

Manage installing setup data in the Settings

Alternatively, we can define this value in wp-config.php:

define( 'GATOGRAPHQL_INSTALL_PLUGIN_SETUP_DATA', false );

Added AnyStringScalar wildcard scalar type

A new wildcard scalar type AnyStringScalar has been introduced, to represent every scalar type that is represented via a string (eg: HTML, Email, etc).

This is to enable directives performing operations on strings (such as @strReplace) to accept being applied to any of these fields.

Purge container when autoupdating a depended-upon plugin

When executing a plugin update from the WP dashboard, if the plugin is a dependency by a Gato GraphQL extension, then the service container will be purged. This avoid a potential exception thrown when the plugin's new version has incompatible code with the previous version.

Fixed

  • Bug on the caching component (a downgraded reset method was called on a non array)

1.0.15

7 months ago

Fixed

  • Executing introspection query failed in GraphiQL client when passing ?operationName=...

1.0.14

7 months ago

Fixed

  • Configuration alert in recipe "Duplicating multiple blog posts at once"