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

Add json api query support and include support #508

Merged
merged 37 commits into from
Apr 12, 2017

Conversation

dakota
Copy link
Member

@dakota dakota commented Mar 30, 2017

This adds support to the json api for parsing query parameters. Included as part of this is ability to pass the include query parameter to conditionally load relationships.

@bravo-kernel
Copy link
Contributor

Epic PR 💯

FWIW I am getting the exact same Travis fails here #506 and haven't been able to figure out what causes it yet. So far I see no differences between the previously successful builds and these all-of-a-sudden-fails (I am using the 5.6 to troubleshoot)

@jippi
Copy link
Member

jippi commented Mar 30, 2017

I think it should be possible / required to whitelist the associations that you can pass into include - and not blow it wide open by default :)

@dakota
Copy link
Member Author

dakota commented Mar 30, 2017

I think it should be possible / required to whitelist the associations that you can pass into include - and not blow it wide open by default :)

I definately agree, and will be adding that. Wanted to get the PR open in the meantime

@bravo-kernel
Copy link
Contributor

@dakota since this got discussed on Slack... will this include full sparse fieldsets functionality?

GET /articles?include=author&fields[articles]=title,body&fields[people]=name

@dakota
Copy link
Member Author

dakota commented Mar 30, 2017

@bravo-kernel It does not, and will not, BUT it lays the foundation to add that functionality, as well as filtering. I will be working on that next, as a separate PR. Don't want to introduce too much in a single PR

@bravo-kernel
Copy link
Contributor

I thought so by looking at the code but just wanted to make sure, thanks

@codecov-io
Copy link

codecov-io commented Apr 2, 2017

Codecov Report

Merging #508 into master will decrease coverage by 0.35%.
The diff coverage is 91.33%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master     #508      +/-   ##
============================================
- Coverage     94.72%   94.36%   -0.36%     
- Complexity      614      649      +35     
============================================
  Files            42       42              
  Lines          1913     1989      +76     
============================================
+ Hits           1812     1877      +65     
- Misses          101      112      +11
Impacted Files Coverage Δ Complexity Δ
src/View/JsonApiView.php 98.33% <50%> (-0.82%) 45 <0> (+1)
src/Error/JsonApiExceptionRenderer.php 97.84% <50%> (-2.16%) 22 <0> (+2)
src/Schema/JsonApi/DynamicEntitySchema.php 96.42% <82.35%> (-3.58%) 18 <5> (+2)
src/Listener/JsonApiListener.php 97.65% <95.19%> (-1.83%) 100 <40> (+30)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 41aba34...5bf277c. Read the comment docs.

@dakota dakota force-pushed the add-json-api-query-support branch from 777c80c to 1d9b76e Compare April 3, 2017 11:33
@bravo-kernel
Copy link
Contributor

bravo-kernel commented Apr 4, 2017

UPDATE: ALL RESOLVED

I ❤️ it.

I don't have time to complete a full integration test but here's some initial feedback to start with.

All tested against my CountriesController index action, all my custom behaviors etc. disabled.

OK: including a single hasMany relationship

Tested against /countries?include=cultures.

  • OK: the relationships node contains related data as expected (per resource)
  • OK: the included node gets rendered as expected
{
  "data": [
    {
      "type": "countries",
      "id": "1",
      "attributes": {
        "code": "NL",
        "name": "The Netherlands",
        "native": "Nederland",
        "slug": "nl",
        "approved": true,
        "created": "2017-02-25T20:40:40+00:00",
        "modified": "2017-02-25T20:40:40+00:00"
      },
      "relationships": {
        "cultures": {
          "data": [
            {
              "type": "cultures",
              "id": "1"
            }
          ],
          "links": {
            "self": "/cultures?country_id=1"
          }
        }
      },
      "links": {
        "self": "/countries/1"
      }
    }
  ],
  "included": [
    {
      "type": "cultures",
      "id": "1",
      "attributes": {
        "code": "nl-NL",
        "name": "Dutch",
        "native": "Nederlands",
        "slug": "nl-nl",
        "country_id": 1,
        "approved": true,
        "created": "2017-02-25T20:40:40+00:00",
        "modified": "2017-02-25T20:40:40+00:00"
      }
    }
  ]
}

OK: including a single belongsTo relationship

Tested with `/countries?include=currencies

  • OK: the relationships node contains related data as expected (per resource)
  • OK: the included node gets rendered with expected data
{
  "data": [
    {
      "type": "countries",
      "id": "1",
      "attributes": {
        "code": "NL",
        "name": "The Netherlands",
        "native": "Nederland",
        "slug": "nl",
        "approved": true,
        "created": "2017-02-25T20:40:40+00:00",
        "modified": "2017-02-25T20:40:40+00:00"
      },
      "relationships": {
        "currency": {
          "data": {
            "type": "currencies",
            "id": "1"
          },
          "links": {
            "self": "/currencies/1"
          }
        }
      },
      "links": {
        "self": "/countries/1"
      }
    }
  ],
  "included": [
    {
      "type": "currencies",
      "id": "1",
      "attributes": {
        "code": "EUR",
        "name": "Euro",
        "slug": "eur",
        "approved": true,
        "created": "2017-02-25T20:40:40+00:00",
        "modified": "2017-02-25T20:40:40+00:00"
      }
    }
  ]
}

OK: including two relationships (hasMany-and-belongsTo)

Tested with /countries?include=cultures,currencies:

  • OK: the relationships node contains related data as expected (per resource)
  • OK: the included node gets rendered with expected hasMany and belongsTo data
{
  "data": [
    {
      "type": "countries",
      "id": "1",
      "attributes": {
        "code": "NL",
        "name": "The Netherlands",
        "native": "Nederland",
        "slug": "nl",
        "approved": true,
        "created": "2017-02-25T20:40:40+00:00",
        "modified": "2017-02-25T20:40:40+00:00"
      },
      "relationships": {
        "currency": {
          "data": {
            "type": "currencies",
            "id": "1"
          },
          "links": {
            "self": "/currencies/1"
          }
        },
        "cultures": {
          "data": [
            {
              "type": "cultures",
              "id": "1"
            }
          ],
          "links": {
            "self": "/cultures?country_id=1"
          }
        }
      },
      "links": {
        "self": "/countries/1"
      }
    }
  ],
  "included": [
    {
      "type": "currencies",
      "id": "1",
      "attributes": {
        "code": "EUR",
        "name": "Euro",
        "slug": "eur",
        "approved": true,
        "created": "2017-02-25T20:40:40+00:00",
        "modified": "2017-02-25T20:40:40+00:00"
      }
    },
    {
      "type": "cultures",
      "id": "1",
      "attributes": {
        "code": "nl-NL",
        "name": "Dutch",
        "native": "Nederlands",
        "slug": "nl-nl",
        "approved": true,
        "created": "2017-02-25T20:40:40+00:00",
        "modified": "2017-02-25T20:40:40+00:00"
      }
    }
  ]
}

OK: limiting results when a single belongsTo contain is present in index action

Tested with /countries?include=currencies and the following index action:

    public function index()
    {
       $this->Crud->on('beforePaginate', function (Event $event) {
            $event->subject()->query->contain([
                'Cultures',
            ]);
        });
        return $this->Crud->execute();
    }
  • OK: the relationships node still contains data for currency
  • OK: the included node does not get rendered with belongsTo data
{
  "data": [
    {
      "type": "countries",
      "id": "1",
      "attributes": {
        "code": "NL",
        "name": "The Netherlands",
        "native": "Nederland",
        "slug": "nl",
        "approved": true,
        "created": "2017-02-25T20:40:40+00:00",
        "modified": "2017-02-25T20:40:40+00:00"
      },
      "relationships": {
        "currency": {
          "data": {
            "type": "currencies",
            "id": "1"
          },
          "links": {
            "self": "/currencies/1"
          }
        },
        "cultures": {
          "data": [
            {
              "type": "cultures",
              "id": "1"
            }
          ],
          "links": {
            "self": "/cultures?country_id=1"
          }
        }
      },
      "links": {
        "self": "/countries/1"
      }
    }
  ],
  "included": [
    {
      "type": "currencies",
      "id": "1",
      "attributes": {
        "code": "EUR",
        "name": "Euro",
        "slug": "eur",
        "approved": true,
        "created": "2017-02-25T20:40:40+00:00",
        "modified": "2017-02-25T20:40:40+00:00"
      }
    }
  ]
}

OK: limiting results when a single hasMany contain is present in index action

Tested with /countries?include=cultures and the following index action:

    public function index()
    {
       $this->Crud->on('beforePaginate', function (Event $event) {
            $event->subject()->query->contain([
                'Currencies',
            ]);
        });
        return $this->Crud->execute();
    }
  • OK: the relationships node shows data for cultures
  • OK: the included node gets rendered as expected
{
  "data": [
    {
      "type": "countries",
      "id": "1",
      "attributes": {
        "code": "NL",
        "name": "The Netherlands",
        "native": "Nederland",
        "slug": "nl",
        "approved": true,
        "created": "2017-02-25T20:40:40+00:00",
        "modified": "2017-02-25T20:40:40+00:00"
      },
      "relationships": {
        "currency": {
          "data": {
            "type": "currencies",
            "id": "1"
          },
          "links": {
            "self": "/currencies/1"
          }
        },
        "cultures": {
          "data": [
            {
              "type": "cultures",
              "id": "1"
            }
          ],
          "links": {
            "self": "/cultures?country_id=1"
          }
        }
      },
      "links": {
        "self": "/countries/1"
      }
    }
  ],
  "included": [
    {
      "type": "cultures",
      "id": "1",
      "attributes": {
        "code": "nl-NL",
        "name": "Dutch",
        "native": "Nederlands",
        "slug": "nl-nl",
        "approved": true,
        "created": "2017-02-25T20:40:40+00:00",
        "modified": "2017-02-25T20:40:40+00:00"
      }
    }
  ]
}

OK: limiting results when a two contains are present in index action

Same result as the previous test. This time tested with /countries?include=currencies and the following index action.

  • OK: the relationships node shows data for cultures
  • OK: the included node gets limited to the resource passed with ?include=
    public function index()
    {
       $this->Crud->on('beforePaginate', function (Event $event) {
            $event->subject()->query->contain([
                'Cultures',
                'Currencies',
            ]);
        });
        return $this->Crud->execute();
    }

Usability

I'm ashamed to admit but I was unable to figure out (from the stack trace) which one of the three resources in ?include=cultures,donkey,currencies was causing the following error. I think it would be very useful if the detail message would mention which resource(s) are failing (if even possible ofcourse).

  "errors": [
    {
      "code": "400",
      "title": "Bad Request",
      "detail": "Invalid relationship path supplied in include parameter"

Update:

Thanks, this feedback is much much better ☺️.

It only detects the first invalid so monkey does not show up (in a list) but I guess that's nitpicking. ?include=cultures,donkey,monkey,currencies

{
  "errors": [
    {
      "code": "400",
      "title": "Bad Request",
      "detail": "Invalid relationship path 'donkey' supplied in include parameter"

@bravo-kernel
Copy link
Contributor

bravo-kernel commented Apr 5, 2017

I've added a few more tests.

I hope this also makes clear how badly I need to get the integration tests working for JsonApiListener (#513)

@dakota dakota added the JSONAPI label Apr 6, 2017
@dakota dakota force-pushed the add-json-api-query-support branch from b9fc0a2 to 9aebb9d Compare April 6, 2017 13:34
@dakota
Copy link
Member Author

dakota commented Apr 6, 2017

@bravo-kernel Made quite a few changes now.

Firstly, all your supplied test cases are working (With integration tests 🎉 )

I have also started work on supporting arbitrarily deeply nested includes/contains. Will get that finished soon.

@bravo-kernel
Copy link
Contributor

bravo-kernel commented Apr 8, 2017

UPDATE: RESOLVED

Listener config

I copy-pasted the following from your docs example and it is giving me this error (cake 3.3.9);

"code": "500",
"title": "Internal Server Error",
"detail": "Call to undefined method Crud\Listener\JsonApiListener::setConfig()"

    public function index()
    {
        $this->Crud
          ->listener('jsonApi')
          ->setConfig('queryParameters.include.blacklist', ['countries']);

        $this->Crud->on('beforePaginate', function (Event $event) {
        });

        return $this->Crud->execute();
    }

Stack trace

{
  "errors": [
    {
      "code": "500",
      "title": "Internal Server Error",
      "detail": "Call to undefined method Crud\\Listener\\JsonApiListener::setConfig()"
    }
  ],
  "debug": {
    "class": "Error",
    "trace": [
      {
        "file": "/home/vagrant/projects/alt3-api/vendor/friendsofcake/crud/src/Controller/ControllerTrait.php",
        "line": 51,
        "function": "call_user_func_array",
        "args": [
          [
            {
              "paginate": {
                "sortWhitelist": [
                  "code",
                  "name"
                ]
              },
              "name": "Currencies",
              "helpers": [],
              "request": {
                "params": {
                  "plugin": null,
                  "controller": "Currencies",
                  "action": "index",
                  "_ext": null,
                  "pass": [],
                  "_method": "GET",
                  "_matchedRoute": "/currencies",
                  "isAjax": false
                },
                "data": [],
                "query": [],
                "cookies": {
                  "CAKEPHP": "a93dsl3393955f5lphabses856",
                  "csrfToken": "0d2c72f16a2aaabf9a38f18fa8974f66a2d87967"
                },
                "url": "currencies",
                "base": "",
                "webroot": "/",
                "here": "/currencies",
                "trustProxy": false
              },
              "response": {},
              "autoRender": true,
              "components": [],
              "View": null,
              "plugin": null,
              "passedArgs": [],
              "modelClass": "Currencies",
              "viewClass": null,
              "viewVars": [],
              "dispatchComponents": {
                "Crud": true
              },
              "RequestHandler": {
                "enabled": true,
                "response": {},
                "ext": null,
                "request": {
                  "params": {
                    "plugin": null,
                    "controller": "Currencies",
                    "action": "index",
                    "_ext": null,
                    "pass": [],
                    "_method": "GET",
                    "_matchedRoute": "/currencies",
                    "isAjax": false
                  },
                  "data": [],
                  "query": [],
                  "cookies": {
                    "CAKEPHP": "a93dsl3393955f5lphabses856",
                    "csrfToken": "0d2c72f16a2aaabf9a38f18fa8974f66a2d87967"
                  },
                  "url": "currencies",
                  "base": "",
                  "webroot": "/",
                  "here": "/currencies",
                  "trustProxy": false
                },
                "components": []
              },
              "Crud": {
                "request": {
                  "params": {
                    "plugin": null,
                    "controller": "Currencies",
                    "action": "index",
                    "_ext": null,
                    "pass": [],
                    "_method": "GET",
                    "_matchedRoute": "/currencies",
                    "isAjax": false
                  },
                  "data": [],
                  "query": [],
                  "cookies": {
                    "CAKEPHP": "a93dsl3393955f5lphabses856",
                    "csrfToken": "0d2c72f16a2aaabf9a38f18fa8974f66a2d87967"
                  },
                  "url": "currencies",
                  "base": "",
                  "webroot": "/",
                  "here": "/currencies",
                  "trustProxy": false
                },
                "response": {},
                "components": []
              },
              "Auth": {
                "components": [
                  "RequestHandler",
                  "Flash"
                ],
                "allowedActions": [
                  "home",
                  "index",
                  "view",
                  "index",
                  "view"
                ],
                "request": {
                  "params": {
                    "plugin": null,
                    "controller": "Currencies",
                    "action": "index",
                    "_ext": null,
                    "pass": [],
                    "_method": "GET",
                    "_matchedRoute": "/currencies",
                    "isAjax": false
                  },
                  "data": [],
                  "query": [],
                  "cookies": {
                    "CAKEPHP": "a93dsl3393955f5lphabses856",
                    "csrfToken": "0d2c72f16a2aaabf9a38f18fa8974f66a2d87967"
                  },
                  "url": "currencies",
                  "base": "",
                  "webroot": "/",
                  "here": "/currencies",
                  "trustProxy": false
                },
                "response": {},
                "session": {}
              },
              "Alt3Api": {
                "request": {
                  "params": {
                    "plugin": null,
                    "controller": "Currencies",
                    "action": "index",
                    "_ext": null,
                    "pass": [],
                    "_method": "GET",
                    "_matchedRoute": "/currencies",
                    "isAjax": false
                  },
                  "data": [],
                  "query": [],
                  "cookies": {
                    "CAKEPHP": "a93dsl3393955f5lphabses856",
                    "csrfToken": "0d2c72f16a2aaabf9a38f18fa8974f66a2d87967"
                  },
                  "url": "currencies",
                  "base": "",
                  "webroot": "/",
                  "here": "/currencies",
                  "trustProxy": false
                },
                "response": {},
                "components": []
              },
              "Prg": {
                "request": {
                  "params": {
                    "plugin": null,
                    "controller": "Currencies",
                    "action": "index",
                    "_ext": null,
                    "pass": [],
                    "_method": "GET",
                    "_matchedRoute": "/currencies",
                    "isAjax": false
                  },
                  "data": [],
                  "query": [],
                  "cookies": {
                    "CAKEPHP": "a93dsl3393955f5lphabses856",
                    "csrfToken": "0d2c72f16a2aaabf9a38f18fa8974f66a2d87967"
                  },
                  "url": "currencies",
                  "base": "",
                  "webroot": "/",
                  "here": "/currencies",
                  "trustProxy": false
                },
                "response": {},
                "components": []
              }
            },
            "index"
          ],
          []
        ]
      },
      {
        "file": "/home/vagrant/projects/alt3-api/vendor/cakephp/cakephp/src/Http/ActionDispatcher.php",
        "line": 122,
        "function": "invokeAction",
        "class": "App\\Controller\\AppController",
        "type": "->",
        "args": []
      },
      {
        "file": "/home/vagrant/projects/alt3-api/vendor/cakephp/cakephp/src/Http/ActionDispatcher.php",
        "line": 96,
        "function": "_invoke",
        "class": "Cake\\Http\\ActionDispatcher",
        "type": "->",
        "args": [
          {
            "paginate": {
              "sortWhitelist": [
                "code",
                "name"
              ]
            },
            "name": "Currencies",
            "helpers": [],
            "request": {
              "params": {
                "plugin": null,
                "controller": "Currencies",
                "action": "index",
                "_ext": null,
                "pass": [],
                "_method": "GET",
                "_matchedRoute": "/currencies",
                "isAjax": false
              },
              "data": [],
              "query": [],
              "cookies": {
                "CAKEPHP": "a93dsl3393955f5lphabses856",
                "csrfToken": "0d2c72f16a2aaabf9a38f18fa8974f66a2d87967"
              },
              "url": "currencies",
              "base": "",
              "webroot": "/",
              "here": "/currencies",
              "trustProxy": false
            },
            "response": {},
            "autoRender": true,
            "components": [],
            "View": null,
            "plugin": null,
            "passedArgs": [],
            "modelClass": "Currencies",
            "viewClass": null,
            "viewVars": [],
            "dispatchComponents": {
              "Crud": true
            },
            "RequestHandler": {
              "enabled": true,
              "response": {},
              "ext": null,
              "request": {
                "params": {
                  "plugin": null,
                  "controller": "Currencies",
                  "action": "index",
                  "_ext": null,
                  "pass": [],
                  "_method": "GET",
                  "_matchedRoute": "/currencies",
                  "isAjax": false
                },
                "data": [],
                "query": [],
                "cookies": {
                  "CAKEPHP": "a93dsl3393955f5lphabses856",
                  "csrfToken": "0d2c72f16a2aaabf9a38f18fa8974f66a2d87967"
                },
                "url": "currencies",
                "base": "",
                "webroot": "/",
                "here": "/currencies",
                "trustProxy": false
              },
              "components": []
            },
            "Crud": {
              "request": {
                "params": {
                  "plugin": null,
                  "controller": "Currencies",
                  "action": "index",
                  "_ext": null,
                  "pass": [],
                  "_method": "GET",
                  "_matchedRoute": "/currencies",
                  "isAjax": false
                },
                "data": [],
                "query": [],
                "cookies": {
                  "CAKEPHP": "a93dsl3393955f5lphabses856",
                  "csrfToken": "0d2c72f16a2aaabf9a38f18fa8974f66a2d87967"
                },
                "url": "currencies",
                "base": "",
                "webroot": "/",
                "here": "/currencies",
                "trustProxy": false
              },
              "response": {},
              "components": []
            },
            "Auth": {
              "components": [
                "RequestHandler",
                "Flash"
              ],
              "allowedActions": [
                "home",
                "index",
                "view",
                "index",
                "view"
              ],
              "request": {
                "params": {
                  "plugin": null,
                  "controller": "Currencies",
                  "action": "index",
                  "_ext": null,
                  "pass": [],
                  "_method": "GET",
                  "_matchedRoute": "/currencies",
                  "isAjax": false
                },
                "data": [],
                "query": [],
                "cookies": {
                  "CAKEPHP": "a93dsl3393955f5lphabses856",
                  "csrfToken": "0d2c72f16a2aaabf9a38f18fa8974f66a2d87967"
                },
                "url": "currencies",
                "base": "",
                "webroot": "/",
                "here": "/currencies",
                "trustProxy": false
              },
              "response": {},
              "session": {}
            },
            "Alt3Api": {
              "request": {
                "params": {
                  "plugin": null,
                  "controller": "Currencies",
                  "action": "index",
                  "_ext": null,
                  "pass": [],
                  "_method": "GET",
                  "_matchedRoute": "/currencies",
                  "isAjax": false
                },
                "data": [],
                "query": [],
                "cookies": {
                  "CAKEPHP": "a93dsl3393955f5lphabses856",
                  "csrfToken": "0d2c72f16a2aaabf9a38f18fa8974f66a2d87967"
                },
                "url": "currencies",
                "base": "",
                "webroot": "/",
                "here": "/currencies",
                "trustProxy": false
              },
              "response": {},
              "components": []
            },
            "Prg": {
              "request": {
                "params": {
                  "plugin": null,
                  "controller": "Currencies",
                  "action": "index",
                  "_ext": null,
                  "pass": [],
                  "_method": "GET",
                  "_matchedRoute": "/currencies",
                  "isAjax": false
                },
                "data": [],
                "query": [],
                "cookies": {
                  "CAKEPHP": "a93dsl3393955f5lphabses856",
                  "csrfToken": "0d2c72f16a2aaabf9a38f18fa8974f66a2d87967"
                },
                "url": "currencies",
                "base": "",
                "webroot": "/",
                "here": "/currencies",
                "trustProxy": false
              },
              "response": {},
              "components": []
            }
          }
        ]
      },
      {
        "file": "/home/vagrant/projects/alt3-api/vendor/cakephp/cakephp/src/Routing/Dispatcher.php",
        "line": 60,
        "function": "dispatch",
        "class": "Cake\\Http\\ActionDispatcher",
        "type": "->",
        "args": [
          {
            "params": {
              "plugin": null,
              "controller": "Currencies",
              "action": "index",
              "_ext": null,
              "pass": [],
              "_method": "GET",
              "_matchedRoute": "/currencies",
              "isAjax": false
            },
            "data": [],
            "query": [],
            "cookies": {
              "CAKEPHP": "a93dsl3393955f5lphabses856",
              "csrfToken": "0d2c72f16a2aaabf9a38f18fa8974f66a2d87967"
            },
            "url": "currencies",
            "base": "",
            "webroot": "/",
            "here": "/currencies",
            "trustProxy": false
          },
          {}
        ]
      },
      {
        "file": "/home/vagrant/projects/alt3-api/webroot/index.php",
        "line": 36,
        "function": "dispatch",
        "class": "Cake\\Routing\\Dispatcher",
        "type": "->",
        "args": [
          {
            "params": {
              "plugin": null,
              "controller": "Currencies",
              "action": "index",
              "_ext": null,
              "pass": [],
              "_method": "GET",
              "_matchedRoute": "/currencies",
              "isAjax": false
            },
            "data": [],
            "query": [],
            "cookies": {
              "CAKEPHP": "a93dsl3393955f5lphabses856",
              "csrfToken": "0d2c72f16a2aaabf9a38f18fa8974f66a2d87967"
            },
            "url": "currencies",
            "base": "",
            "webroot": "/",
            "here": "/currencies",
            "trustProxy": false
          },
          {}
        ]
      }
    ]
  }
}

@dakota
Copy link
Member Author

dakota commented Apr 8, 2017

@bravo-kernel Probably because you are using CakePHP 3.3 still :) Will get that updated

@bravo-kernel
Copy link
Contributor

bravo-kernel commented Apr 9, 2017

UPDATE: EXPLAINED (WORKS FOR ME)

The blacklist works as expected except... when there already is a contain in the action itself, like shown below. I expected included to be empty due to the blacklist-config winning. If I'm missing the point here please elaborate.

    public function index()
    {
        $this->Crud
          ->listener('jsonApi')
          ->config('queryParameters.include.blacklist', ['currencies', 'cultures']);

         $this->Crud->on('beforePaginate', function (Event $event) {
            $event->subject()->query->contain([
                'Currencies',
                'Cultures'
            ]);
         });

        return $this->Crud->execute();
    }

@bravo-kernel
Copy link
Contributor

bravo-kernel commented Apr 10, 2017

UPDATE: SOLVED

Just tested the view action with your include and it works like a charm 👍

However, I did notice that the include does not accept/respect my dasherized models and throws the following error when using the expected /users/1?include=user-profiles

"code": "400",
"title": "Bad Request",
"detail": "Invalid relationship path 'user-profiles' supplied in include parameter"

Changing the include to underscored /users/1?include=user_profiles makes it work but produces incorrect underscored json as can be seen below (where only the self-link is using correct dash):

{
  "data": {
    "type": "users",
    "id": "1",
    "attributes": {
      "email": "bravo@kernel.com",
      "username": null,
      "slug": null,
      "confirmed": false,
      "created": "2017-03-08T14:32:31+00:00",
      "modified": "2017-03-08T14:32:31+00:00"
    },
    "relationships": {
      "user_profile": {
        "data": {
          "type": "user_profiles",
          "id": "333"
        },
        "links": {
          "self": "/user-profiles/view/333"
        }
      }
    },
    "links": {
      "self": "/users/1"
    }
  },
  "included": [
    {
      "type": "user_profiles",
      "id": "333",
      "attributes": {
        "newsletter": false,
        "notifications": false,
        "created": "2017-03-08T14:32:31+00:00",
        "modified": "2017-03-08T14:32:31+00:00"
      }
    }
  ]
}

@dakota
Copy link
Member Author

dakota commented Apr 11, 2017

The blacklist works as expected except... when there already is a contain in the action itself

This is the expected behaviour. The blacklist/whitelist ONLY affects the include query parameter. If no query parameter is supplied then the include config option, or auto-determination is used as previously.

@bravo-kernel
Copy link
Contributor

Thanks for explaining mr. @dakota. Since there are no more things on my list I would say this is functionally good to go. Awesome job 💯

@dakota
Copy link
Member Author

dakota commented Apr 12, 2017

If everybody is happy, I'll go ahead and merge?

@jippi jippi merged commit d1d1c0b into FriendsOfCake:master Apr 12, 2017
@jippi
Copy link
Member

jippi commented Apr 12, 2017

Thanks @dakota !

@bravo-kernel
Copy link
Contributor

👏

@ADmad
Copy link
Member

ADmad commented Apr 12, 2017

Does this warrant a new minor release or a bugfix release should suffice?

@dakota dakota deleted the add-json-api-query-support branch April 12, 2017 07:36
@dakota
Copy link
Member Author

dakota commented Apr 12, 2017

Depends on how strict we are about feature additions? It doesn't really change how the default behaviour worked

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

Successfully merging this pull request may close these issues.

5 participants