Giter Club home page Giter Club logo

graphql_api's Introduction

GraphQL API for Drupal 7

Build Status

GraphQL API with GraphiQL

The problems

All the cool thing seems to be happening on Drupal 8 which are includes GraphQL.

This module attempt bring GraphQL to Drupal 7.

For Drupal 8, you should use http://drupal.org/project/graphql

Requirements

  • PHP 5.4+

Installation

Usages

  • /graphqleditor explore your Drupal 7 site's GraphQL schema
  • /graphql use your favorite GraphQL client (Apollo http://www.apollodata.com/) to begin query
  • graphql_api_query_file() execute .GrahpQL query from file

The tools

The plans

  1. Create module graphql_api
  2. Create class Drupal\grapql\_api\Schema to build GraphQL schema
    • use hook_entity_info(), hook_entity_property_info() to build GraphQL schema
    • map Drupal concept to GraphQL concept
      • Entity type -> Interface
      • Entity bundle -> Object
      • Entity revision -> Object
      • Property, Field API -> Property
    • resolve relationship use entity metadata info
      • Base field uid -> Inteface: user
      • Base field rid -> Object: revision
      • Field API: term_reference -> Interface: term
      • Field API: entityreference -> Interface/Object target entity
      • Field API: relation -> Interface/Object target entity
  3. Create GraphQL endpoint /graphql
    • receive POST content with GraphQL query and variables
    • query using Drupal's EntityFieldQuery
    • check entity access using entity_access
    • resolve property using entity_metadata_wrapper
    • return result

Notes

  1. Field will be shortened field_tags -> tags Shortened field name can be duplicate with base table's column or other property. Keep field name intact.
  2. If entity type have single bundle, we skip GraphQL interface and just use GraphQL object. Eg: user, file, ... Entity reference field will resolve to Entity type, not bundle.

graphql_api's People

Contributors

d0t15t avatar klokie avatar olragon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

graphql_api's Issues

Problems after code changes for date fields

@olragon many thanks for fixing #13
Date start and end are returned now. But there are new problems:

Because type 'struct' was deleted from Schema.php i've get this dump() output if i open /graphql

array:6 [▼
  "label" => "CER"
  "description" => "Information about the entity, used internally by CER."
  "type" => "struct"
  "getter callback" => "cer_get_cer_struct"
  "computed" => true
  "property info" => array:4 [▼
    "lineage" => array:5 [▼
      "label" => "Kontext"
      "description" => "The entity's lineage, represented as a string."
      "type" => "text"
      "getter callback" => "cer_get_entity_lineage"
      "computed" => true
    ]
    "depth" => array:5 [▼
      "label" => "Tiefe"
      "description" => "How deeply the entity is embedded."
      "type" => "integer"
      "getter callback" => "cer_get_entity_depth"
      "computed" => true
    ]
    "owner" => array:5 [▼
      "label" => "Eigentümer"
      "description" => "The top-level entity under which this one is embedded."
      "type" => "entity"
      "getter callback" => "cer_get_entity_owner"
      "computed" => true
    ]
    "original" => array:5 [▼
      "label" => "Original"
      "description" => "The original entity (before update), or the current entity if an update has not occurred."
      "type" => "entity"
      "getter callback" => "cer_get_entity_original"
      "computed" => true
    ]
  ]
]

Cannot detect fieldType for cer cer

If i add struct type again, i get a JSON formatted result with debug infos. I can use graphiQL also then. "cer" comes from https://www.drupal.org/project/cer which is used a lot in our project.

Important: There is a problem with text fields now:

query {
  fhp_shop_blocking {
    id
    field_blocking_reason {
      value
      format
    } 
    field_shop_blocking_dates {
      value
      value2
    }
  }
}

Result:

{
  "data": {
    "fhp_shop_blocking": [
      {
        "id": "1",
        "field_blocking_reason": {
          "value": null,
          "format": null
        },
        "field_shop_blocking_dates": {
          "value": "2018-08-01 00:00:00",
          "value2": "2018-08-25 00:00:00"
        }
      },
      {
        "id": "28",
        "field_blocking_reason": {
          "value": null,
          "format": null
        },
        "field_shop_blocking_dates": {
          "value": "2018-07-02 00:00:00",
          "value2": "2018-07-25 00:00:00"
        }
      }
    ]
  }
}

As you can see, the graphiQL autosuggests in query

[...]
    field_blocking_reason {
      value
      format
    } 
[...]

and they return now

[...]
        "field_blocking_reason": {
          "value": null,
          "format": null
        },
[...]

I appreciate your support. Please help us fix the remaining problems soon.

Error with Composer Manager Security Advisory module during installation

Hi,

i'm writing in follow-up to the conversation on #9

During installation with drush i get the following messages and errors:

It is recommended to enable the Composer Manager Security Advisory module to[status]
automatically check for security updates.
One or more extensions have dependencies managed by Composer.
Update packages managed by Composer? (y/n): y
Download and install the Drush Composer extension? (y/n): y
Project composer (8.x-1.x-dev) downloaded to /Users/ibt/.drush/composer.    [success]
Project composer contains 0 modules: .
The drush command 'composer' could not be found.                            [error]
RuntimeException: Autoloader not found:                                     [error]
/Users/ibt/Sites/devdesktop/fhp-portal/drupal/docroot/sites/all/vendor/autoload.php

It's looking for composer in the wrong directory.

Empty results when using graphiql as non-admin.

I've created a role 'api' and assigned it to 'Use GraphQL query' in Drupal-Permissions. The user can then reach the /graphql/graphiql page, but queries return only empty results. When logged in as an admin, the same query returns all nodes as expected.

graphiql___drupal_7_base 2
graphiql___drupal_7_base

"File" value is always `null`

Hello, is there any way to retrieve the URLs of files attached to a node? All I get are null values, e.g.

"field_assets": [
              {
                "file": null,
                "description": ""
              }
            ],

This seems to be the case both for File fields (using Media) and Image fields.

_save mutation does not add field values to created entity

What i am doing wrong here?
The nodes/entities are created but only with title. All other fields are always empty (shown as null ).
(Also: Required fields are not validated if empty)

Test No. 1 for custom entity "fhp_shop_fishing_license_sold" of bundle "fhp_shop"

mutation createOrderline($license: fhp_shop_fishing_license_sold_input_type) {
  fhp_shop_fishing_license_sold_save(entity: $license) {
    id
    title
    field_shop_description {
      value
      format
    }
    field_shop_firstname
    field_shop_lastname
    field_shop_mail
  }
}


{
  "license": {
    "title": "Some title",
    "field_shop_description": "<p>This is the body text.</p>",
    "field_shop_firstname": "Max",
    "field_shop_lastname": "Mustermann",
    "field_shop_street": "Some Street Name",
    "field_shop_housenumber": "123",
    "field_shop_zipcode": 12345,
    "field_shop_city": "MyCity",
    "field_shop_mail": "[email protected]",
    "field_shop_birthdate": 222048000,
    "field_shop_prize": 54,
    "field_shop_license_reference": 17
  }
}

------
Result:

{
  "data": {
    "fhp_shop_fishing_license_sold_save": {
      "id": "50",
      "title": "Some title",
      "field_shop_description": null,
      "field_shop_firstname": null,
      "field_shop_lastname": null,
      "field_shop_mail": null
    }
  }
}

Test No. 2 for node type "faq"

This node type has no default body-field, but a "field_body" which is configured as formatted multiline.

mutation createEntity($entity: node_faq_input_type) {
  node_faq_save(entity: $entity) {
    nid
    title
    field_body {
      value
      summary
      format
    }
  }
}


{
  "entity": {
    "title": "Test FAQ #1",
    "field_body": "<p>Works?</p>"    
  }
}

----------
Result:

{
  "data": {
    "node_faq_save": {
      "nid": "99718",
      "title": "Test FAQ #1",
      "field_body": null
    }
  }
}

more detailed description for installation

Hi Olagon,

I've managed to install the GraphQL module with all de deps and installed all the deps with composer. I see that GraphQL-php is in the vendor dir.

I want to know what the steps after that are?

the error i'm currently having is:

Fatal error: Class 'GraphQL\Type\Definition\ObjectType' not found in /Users/martijnmellema/Documents/Development/Projecten/Djeepo/djeepo/sites/all/modules/graphql_api/graphql_api.graphql.inc on line 16

Kind regards!

Breaks on simplytest.me

Just tried it on simplytest.me. Querying /graphql path yields:

Fatal error: Class 'GraphQL\Type\Definition\ObjectType' not found in /home/duxux/www/sites/default/modules/graphql_api/graphql_api.graphql.inc on line 16

Should this work?
Is this module functional?
Also: What i didn't grok from the source: Does this support mutation queries?

In any case: Thanks a lot for this!

Custom Schema

Hi there!

Awesome module :) We are starting to think about implementing this into an existing project. Is there any way to create our custom schema? And custom mutations?

Thanks for your help!

Ed

Error on date field with end-date

Hi,
we're really enjoying using graphql_api with drupal, thanks so much!

Currently having an issue with date-fields which contain start and end dates - the schema is expecting a string, but receives an object (or array) and returns an error.

"debugMessage": "Expected a value of type \"String\" but received: {\"value\":\"2018-07-06 00:00:00\",\"value2\":\"2018-07-30 00:00:00\",\"timezone\":\"Europe\\/Paris\",\"timezone_db\":\"Europe\\/Paris\",\"date_type\":\"datetime\"}",

When using a date-field with a start date only, the query returns the datestamp as expected, but in this case it would be great to also access the timezone data.

Are you planning to support this? Or could you give any suggestion for how to add the correct schema data for all the date field info?

Thanks!

Error trying to convert link, name, or socialfield to GraphQL type

Similarly to #1 & #3, this module throws an error when trying to serialize fields of the following types:

  1. List
  2. Name Field
  3. Social field

For example,

  1. List
array(4) { 
["entity_type"]=> string(8) "profile2" 
["bundle"]=> NULL 
["property"]=> string(20) "field_relevant_links" 
["info"]=> array(11) { 
["label"]=> string(25) "Additional Personal Links" 
["type"]=> string(21) "list" 
["description"]=> string(29) "Field "field_relevant_links"." 
["getter callback"]=> string(34) "entity_metadata_field_verbatim_get" 
["setter callback"]=> string(34) "entity_metadata_field_verbatim_set" 
["access callback"]=> string(37) "entity_metadata_field_access_callback" 
["translatable"]=> bool(false) 
["field"]=> bool(true) 
["required"]=> bool(false) 
["auto creation"]=> string(22) "link_field_item_create" 
["property info"]=> array(3) { 
["title"]=> array(4) { 
["type"]=> string(4) "text" 
["label"]=> string(22) "The title of the link." 
["setter callback"]=> string(28) "entity_property_verbatim_set" 
["required"]=> bool(true) } 
["url"]=> array(4) { 
["type"]=> string(3) "uri" 
["label"]=> string(20) "The URL of the link." 
["setter callback"]=> string(28) "entity_property_verbatim_set" 
["required"]=> bool(true) } 
["attributes"]=> array(4) { 
["type"]=> string(6) "struct" 
["label"]=> string(27) "The attributes of the link." 
["setter callback"]=> string(28) "entity_property_verbatim_set" 
["getter callback"]=> string(27) "link_attribute_property_get" } } } }
Cannot convert field_item_link to GraphQL type.
  1. Name Field
array(4) { 
["entity_type"]=> string(8) "profile2" 
["bundle"]=> NULL 
["property"]=> string(27) "field_contributor_full_name" 
["info"]=> array(11) { 
["label"]=> string(9) "Full Name" 
["type"]=> string(15) "field_item_name" 
["description"]=> string(36) "Field "field_contributor_full_name"." 
["getter callback"]=> string(34) "entity_metadata_field_verbatim_get" 
["setter callback"]=> string(34) "entity_metadata_field_verbatim_set" 
["access callback"]=> string(37) "entity_metadata_field_access_callback" 
["translatable"]=> bool(false) 
["field"]=> bool(true) 
["required"]=> bool(false) 
["auto creation"]=> string(22) "name_field_item_create" 
["property info"]=> array(3) { 
["given"]=> array(4) { 
["type"]=> string(4) "text" 
["label"]=> string(15) "The given name." 
["setter callback"]=> string(28) "entity_property_verbatim_set" 
["required"]=> bool(false) } 
["middle"]=> array(4) { 
["type"]=> string(4) "text" 
["label"]=> string(23) "The middle of the name." 
["setter callback"]=> string(28) "entity_property_verbatim_set" 
["required"]=> bool(false) } 
["family"]=> array(4) { 
["type"]=> string(4) "text" 
["label"]=> string(23) "The family of the name." 
["setter callback"]=> string(28) "entity_property_verbatim_set" 
["required"]=> bool(false) } } } }
Cannot convert field_item_name to GraphQL type.
  1. Social field
array(4) { 
["entity_type"]=> string(8) "profile2" 
["bundle"]=> NULL 
["property"]=> string(18) "field_social_links" 
["info"]=> array(9) { 
["label"]=> string(12) "Social Links" 
["type"]=> string(11) "socialfield" 
["description"]=> string(27) "Field "field_social_links"." 
["getter callback"]=> string(34) "entity_metadata_field_verbatim_get" 
["setter callback"]=> string(34) "entity_metadata_field_verbatim_set" 
["access callback"]=> string(37) "entity_metadata_field_access_callback" 
["translatable"]=> bool(false) 
["field"]=> bool(true) 
["required"]=> bool(false) } }
Cannot convert socialfield to GraphQL type.

(note that in these examples I've added the field to Profile 2 entities, but I've seen the same error when they are attached to other bundles.)

Support for Paragraphs?

Hello! I have a Paragraphs field that I would like to access via the GraphQL endpoint. However it seems like the only fields available in the schema are those raw properties of the field itself (archived, bundle, field_name, item_id, revision_id).

I can see that the paragraphs fields I want to access (e.g. body, images, etc) are accessible via the individual paragraph bundles (e.g. bundle1{body}, bundle2{images} etc), I would love to be able to access the fields directly within the node query, just like entity reference and taxonomy reference fields now work. What would be required for that to work?

Please let me know if this is unclear.
Thanks!

filter support / filter by url

Hello,
I'm wondering if this module supports the filter parameter for a query?
When I submit the following query,

query node_article {
  node(filter:{ url: "foo" }) {
    nid
    title
    url
  }
}

…I get the response:

{
  "errors": [
    {
      "message": "Unknown argument \"filter\" on field \"node\" of type \"Query\".",
      "locations": [
        {
          "line": 2,
          "column": 8
        }
      ]
    }
  ]
}

Is there a way to make this work? Or maybe some other, easier way to filter results by url?
The url field doesn't seem to be supported by the current resolvers.
Thanks

Must have a sub selection

Hi there!

I am playing around with the module and having an issue that I cannot figure out:

When I try to add a textfield to the query I get an error "field of type field must have a sub selection". So this is something I understand for a textarea or a taxonomy term for example, but not for a simple textfield.

I tried to investigate this a bit but I couldn't find anything.

Thanks!

Heyddi

Cannot convert addressfield to GraphQL type

Hi! This looks like a really promising project. Trying to get up and running, but I ran into the following error, related to use of an Address Field I'm using. Any idea how I can avoid this, other than by deleting the offending field?

Cannot convert addressfield to GraphQL type. Array
(
    [entity_type] => profile2
    [bundle] => contributor
    [property] => field_address
    [info] => Array
        (
            [label] => Address
            [type] => addressfield
            [description] => Field \"field_address\".
            [getter callback] => entity_metadata_field_verbatim_get
            [setter callback] => entity_metadata_field_verbatim_set
            [access callback] => entity_metadata_field_access_callback
            [translatable] => 
            [field] => 1
            [required] => 
            [auto creation] => addressfield_auto_creation
            [property info] => Array
                (
                    [country] => Array
                        (
                            [label] => Country
                            [options list] => _addressfield_country_options_list
                            [description] => 
                            [type] => text
                            [getter callback] => entity_property_verbatim_get
                            [setter callback] => entity_property_verbatim_set
                        )

                    [name_line] => Array
                        (
                            [label] => Full name
                            [description] => 
                            [type] => text
                            [getter callback] => entity_property_verbatim_get
                            [setter callback] => entity_property_verbatim_set
                        )

                    [first_name] => Array
                        (
                            [label] => First name
                            [description] => 
                            [type] => text
                            [getter callback] => entity_property_verbatim_get
                            [setter callback] => entity_property_verbatim_set
                        )

                    [last_name] => Array
                        (
                            [label] => Last name
                            [description] => 
                            [type] => text
                            [getter callback] => entity_property_verbatim_get
                            [setter callback] => entity_property_verbatim_set
                        )

                    [organisation_name] => Array
                        (
                            [label] => Company
                            [description] => 
                            [type] => text
                            [getter callback] => entity_property_verbatim_get
                            [setter callback] => entity_property_verbatim_set
                        )

                    [administrative_area] => Array
                        (
                            [label] => Administrative area (i.e. State / Province)
                            [description] => 
                            [type] => text
                            [getter callback] => entity_property_verbatim_get
                            [setter callback] => entity_property_verbatim_set
                        )

                    [sub_administrative_area] => Array
                        (
                            [label] => Sub administrative area
                            [description] => 
                            [type] => text
                            [getter callback] => entity_property_verbatim_get
                            [setter callback] => entity_property_verbatim_set
                        )

                    [locality] => Array
                        (
                            [label] => Locality (i.e. City)
                            [description] => 
                            [type] => text
                            [getter callback] => entity_property_verbatim_get
                            [setter callback] => entity_property_verbatim_set
                        )

                    [dependent_locality] => Array
                        (
                            [label] => Dependent locality
                            [description] => 
                            [type] => text
                            [getter callback] => entity_property_verbatim_get
                            [setter callback] => entity_property_verbatim_set
                        )

                    [postal_code] => Array
                        (
                            [label] => Postal code
                            [description] => 
                            [type] => text
                            [getter callback] => entity_property_verbatim_get
                            [setter callback] => entity_property_verbatim_set
                        )

                    [thoroughfare] => Array
                        (
                            [label] => Thoroughfare (i.e. Street address)
                            [description] => 
                            [type] => text
                            [getter callback] => entity_property_verbatim_get
                            [setter callback] => entity_property_verbatim_set
                        )

                    [premise] => Array
                        (
                            [label] => Premise (i.e. Apartment / Suite number)
                            [description] => 
                            [type] => text
                            [getter callback] => entity_property_verbatim_get
                            [setter callback] => entity_property_verbatim_set
                        )

                    [sub_premise] => Array
                        (
                            [label] => Sub Premise (i.e. Suite, Apartment, Floor, Unknown.
                            [description] => 
                            [type] => text
                            [getter callback] => entity_property_verbatim_get
                            [setter callback] => entity_property_verbatim_set
                        )

                )

        )

)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.