Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First-party GraphQL Support #96

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from

Conversation

mattstein
Copy link

@mattstein mattstein commented Nov 14, 2019

This PR adds native GraphQL support for fields that didn't already resolve neatly as strings: Address, Notes and PredefinedDate. It may satisfy #93 depending on how elaborately you'd like to support GraphQL.

Changed Behavior

Previously, querying a Notes or Predefined Date field would return null in each case. This instead returns the rendered note and date respectively. The date is formatted according to FormatDateTime::DEFAULT_FORMAT via craft\gql\types\DateTime since that's how Craft returns its own DateTime values via GraphQL.

The Address field was previously returning the complete address as formatted markup. This registers a new GraphQL object entity so that Sprout Fields can make each Address nugget available individually.

Current Behavior (without PR)

Query (each sprout* handle being a custom field type):

{
  entries {
    ... on test_test_Entry {
      sproutAddress
      sproutEmail
      sproutPhone
      sproutPredefined
      sproutGender
      sproutName
      sproutNotes 
      sproutPredefinedDate
      sproutRegularExpression
      sproutUrl
    }
  }
}

Response:

{
  "data": {
    "entries": [
      {
        "sproutAddress": "<p translate=\"no\">\n<span class=\"address-line1\">12345 Balboa Parkway</span><br>\n<span class=\"locality\">Los Angeles</span>, <span class=\"administrative-area\">CA</span> <span class=\"postal-code\">92654</span><br>\n<span class=\"country\">United States</span>\n</p>",
        "sproutEmail": "[email protected]",
        "sproutPhone": "+1 555-555-5555",
        "sproutPredefined": "test-fields",
        "sproutGender": "female",
        "sproutName": "Lucille Bluth",
        "sproutNotes": null,
        "sproutPredefinedDate": null,
        "sproutRegularExpression": ".*",
        "sproutUrl": "https://recurringdevelopments.com/",
      }
    ]
  }
}

Updated Behavior (with PR)

Query:

{
  entries {
    ... on test_test_Entry {
      sproutAddress {
        address1
        address2
        locality
        administrativeAreaCode
        postalCode
        countryCode
      }
      sproutEmail
      sproutPhone
      sproutPredefined
      sproutGender
      sproutName
      sproutNotes 
      sproutPredefinedDate
      sproutRegularExpression
      sproutUrl
    }
  }
}

Response:

{
  "data": {
    "entries": [
      {
        "sproutAddress": {
          "address1": "12345 Balboa Parkway",
          "address2": "",
          "locality": "Los Angeles",
          "administrativAreaCode": "CA",
          "postalCode": "92654",
          "countryCode": "US",
        },
        "sproutEmail": "[email protected]",
        "sproutPhone": "+1 555-555-5555",
        "sproutPredefined": "test-fields",
        "sproutGender": "female",
        "sproutName": "Lucille Bluth",
        "sproutNotes": "<p>Always leave a note.</p>",
        "sproutPredefinedDate": "2019-11-14T10:11:39+00:00",
        "sproutRegularExpression": ".*",
        "sproutUrl": "https://recurringdevelopments.com/",
      }
    ]
  }
}

How it Works

Each modified field type needed to clarify how it should be reduced to scalar types for GraphQL. Craft automatically tries—and mostly succeeds with the rest of the field types—to get and use the string value of a given field. Each adjustment here implements getContentGqlType() on the respective field class.

Predefined Date is the simplest, returning Craft's GqlDateTimeType::getType().

Notes is more atypical for a field type. It returns a string type and uses a resolve parameter that provides the notes property as that string.

Address returns an object with properties that map to strings. To do this, it creates and registers a new object type, each property mapping directly to those that already exist on the field's address pieces. Note that this type is re-used by GqlEntityRegistry::getEntity() if it already exists, for healthy performance.

Limitations

Reasons you may not want to merge immediately:

  1. This requires Craft 3.3.0+ and I'm not sure how you handle versioning and support.
  2. Sprout Fields does a lovely job of validating and storing these bits of information, and this GraphQL implementation could be further improved to take arguments that tailor output in the same way Twig can right now.

If you have any questions, objections or requests let me know!

@BenParizek
Copy link
Member

Thanks @mattstein

We'll review and work on getting this included shortly.

@BenParizek BenParizek changed the base branch from v3 to develop November 15, 2019 11:38
@nickroberts
Copy link

Nice work on this PR! Is there any way we can resolve these conflicts, then possibly get this merged? Or have a different implementation of it that would allow GraphQL to return the object properties.

It would be nice to use the plugin, but without proper GraphQL support, I will end up using something else. Perhaps a Super Table field would work in our case (location addresses).

Also, we would gladly pay a small fee for the use of this plugin, as well. It really is a nice plugin, it just needs to be updated to work with GraphQL.

Thanks!

@BenParizek
Copy link
Member

@nickroberts We're currently catching up on some outstanding Craft 3.4 bugs and once we feel like everything is in a good place with Craft 3.4 support we'll be turning our attention to GraphQL support. We'll update this thread once we do.

@nickroberts
Copy link

Sounds great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants