Comments

e0ipso created an issue. See original summary.

e0ipso’s picture

Pasting feedback for readability


This is just some review while going through some of the code.

  1. +++ b/core/composer.json
    index 0000000..ab01a11
    --- /dev/null
    
    --- /dev/null
    +++ b/core/modules/jsonapi/README.md
    

    Note: We don't yet use markdown files in core ... I'm fine with adding some, its much easier to read.

  2. +++ b/core/modules/jsonapi/README.md
    @@ -0,0 +1,24 @@
    +## Compatibility
    +
    +This module is compatible with Drupal core 8.2.x and higher.
    
    +++ b/core/modules/jsonapi/jsonapi.info.yml
    @@ -0,0 +1,8 @@
    +  - drupal:system (>=8.2)
    

    I guess we talk about 8.3.x as of this core patch.

  3. +++ b/core/modules/jsonapi/jsonapi.module
    @@ -0,0 +1,65 @@
    +      $spec_link = Link::fromTextAndUrl(t('JSON API Specification'), $spec_url);
    ...
    +          '@spec' => $spec_link->toString(),
    +          '@online' => $youtube_link->toString(),
    

    Nitpick: Afaik we use <a href="">:url</a> instead of generating links, in help texts.

  4. +++ b/core/modules/jsonapi/jsonapi.services.yml
    @@ -0,0 +1,98 @@
    +  serializer.normalizer.entity_reference_item.jsonapi:
    ...
    +      - { name: normalizer, priority: 21 }
    +  serializer.normalizer.field_item.jsonapi:
    ...
    +      - { name: normalizer, priority: 21 }
    +  serializer.normalizer.scalar.jsonapi:
    ...
    +      - { name: normalizer, priority: 5 }
    

    For easier readability: Could we reorder the entries in this file to be ordered by priority somehow?

  5. +++ b/core/modules/jsonapi/jsonapi.services.yml
    index 0000000..686fca8
    --- /dev/null
    
    --- /dev/null
    +++ b/core/modules/jsonapi/phpcs.xml
    

    Nice!

  6. +++ b/core/modules/jsonapi/src/Access/CustomParameterNames.php
    @@ -0,0 +1,59 @@
    +  public function access(Request $request) {
    +    $json_api_params = $request->attributes->get('_json_api_params', []);
    

    Wow, its sad that we don't use the controller resolver, so we cannot easily pull values out of the request attributes.

  7. +++ b/core/modules/jsonapi/src/Access/CustomParameterNames.php
    @@ -0,0 +1,59 @@
    +
    +    foreach (array_keys($json_api_params) as $name) {
    +      if (strpbrk($name, '+,.[]!”#$%&’()*/:;<=>?@^`{}~|')) {
    +        $valid = FALSE;
    +        break;
    +      }
    +
    +      if (strpbrk($name[0], '-_ ') || strpbrk($name[strlen($name) - 1], '-_ ')) {
    +        $valid = FALSE;
    +        break;
    

    Can we point to the place in the space where this is defined?

  8. +++ b/core/modules/jsonapi/src/Context/CurrentContext.php
    @@ -0,0 +1,142 @@
    +    $params = $this
    +      ->requestStack
    +      ->getCurrentRequest()
    +      ->attributes
    +      ->get('_json_api_params');
    +    return (isset($params[$parameter_key])) ? $params[$parameter_key] : NULL;
    +  }
    

    Note: We could use ->get("_json_api_params[$parameter_key]", NULL, TRUE) instead of this isset

  9. +++ b/core/modules/jsonapi/src/Controller/EntityResource.php
    @@ -0,0 +1,735 @@
    +use Drupal\jsonapi\Error\SerializableHttpException;
    +use Drupal\jsonapi\Error\UnprocessableHttpEntityException;
    ...
    +      $exception = new UnprocessableHttpEntityException();
    

    Is there a reason why these exceptions are in the Error and not Exception namespace?

  10. +++ b/core/modules/jsonapi/src/Controller/EntityResource.php
    @@ -0,0 +1,735 @@
    +    $params = $request->attributes->get('_route_params');
    +    $query = $this->getCollectionQuery($entity_type_id, $params['_json_api_params']);
    

    As somewhere else on the patch, this could use $request->attributes->get('_route_params[_json_api_params]', NULL, TRUE)

  11. +++ b/core/modules/jsonapi/src/Controller/EntityResource.php
    @@ -0,0 +1,735 @@
    +    // We request N+1 items to find out if there is a next page for the pager. We may need to remove that extra item
    +    // before loading the entities.
    +    $pager_size = $query->getMetaData('pager_size');
    +    if ($has_next_page = $pager_size < count($results)) {
    +      // Drop the last result.
    +      array_pop($results);
    +    }
    

    <3 mini pagers!

  12. +++ b/core/modules/jsonapi/src/Controller/EntityResource.php
    @@ -0,0 +1,735 @@
    +    if (!($field_list = $entity->get($related_field)) || !$this->isRelationshipField($field_list)) {
    ...
    +      if (!$destination_field_list = $destination->get($field_name)) {
    +        throw new SerializableHttpException(400, sprintf('The provided field (%s) does not exist in the entity with ID %d.', $field_name, $destination->id()));
    +      }
    

    ... When $field_name doens't exist, it throws an exception, according to the documentation on \Drupal\Core\Entity\FieldableEntityInterface::get

  13. +++ b/core/modules/jsonapi/src/Controller/EntityResource.php
    @@ -0,0 +1,735 @@
    +    if ($origin instanceof ContentEntityInterface && $destination instanceof ContentEntityInterface) {
    

    I'm wondering whether we should check for FieldableEntityInterface instead, as these are the methods called here

  14. +++ b/core/modules/jsonapi/src/Controller/EntityResource.php
    @@ -0,0 +1,735 @@
    +    $field_type_manager = \Drupal::service('plugin.manager.field.field_type');
    

    Don't we have this service injected?

  1. +++ b/core/MAINTAINERS.txt
    @@ -243,6 +243,9 @@ Installer
    +JSON-API
    
    +++ b/core/modules/jsonapi/jsonapi.info.yml
    @@ -0,0 +1,8 @@
    +name: JSON API
    

    Ubernitpick: What's the reason for this dash?

  2. +++ b/core/modules/jsonapi/src/Normalizer/NormalizerBase.php
    @@ -0,0 +1,51 @@
    +    return in_array($format, $this->formats) && parent::supportsNormalization($data, $format);
    ...
    +    if (in_array($format, $this->formats) && (class_exists($this->supportedInterfaceOrClass) || interface_exists($this->supportedInterfaceOrClass))) {
    

    Just for sanity reason I would also use $strict=TRUE as the third parameter.

  3. +++ b/core/modules/jsonapi/src/Normalizer/Value/EntityNormalizerValue.php
    @@ -0,0 +1,147 @@
    +    $this->includes = array_reduce($this->includes, function ($carry, $includes) {
    +      return array_merge($carry, $includes);
    +    }, []);
    

    Nitpick: You can also use array_reduce($this->includes, 'array_merge', []) here.

  4. +++ b/core/modules/jsonapi/src/Normalizer/Value/JsonApiDocumentTopLevelNormalizerValue.php
    @@ -0,0 +1,175 @@
    +    $this->includes = array_reduce($this->includes, function ($carry, $includes) {
    +      array_walk($includes, function ($include) {
    +        $this->addCacheableDependency($include);
    +      });
    +      return array_merge($carry, $includes);
    +    }, []);
    

    Isn't it just sad how OOP code just doesn't really compose together. Note: You could use array_walk($includes, [$this, 'addCacheableDependency']) to save some lines.

  5. +++ b/core/modules/jsonapi/src/Query/GroupOption.php
    @@ -0,0 +1,157 @@
    +      };
    

    Wow, I had no idea that this is actually possible

  6. +++ b/core/modules/jsonapi/src/Query/GroupOption.php
    @@ -0,0 +1,157 @@
    +      // If we already know that we have the child, skip evaluation and return.
    +      if (!$has_child) {
    +        // Determine if this group or any of its children match the $id.
    +        $has_child = ($group->id() == $id || $group->hasChild($id));
    +      }
    +      return $has_child;
    +    }, FALSE);
    

    I wonder whether we should use return $has_child || $group_id == $id | $group->hasChild($id)

    I thought PHP actually lazy evaluates in this case.

  7. +++ b/core/modules/jsonapi/src/Resource/EntityCollection.php
    @@ -0,0 +1,89 @@
    +   * @var array
    +   */
    +  protected $entities;
    +
    ...
    +   * @param array $entities
    

    Can we document using EntityInterface[]

  8. +++ b/core/modules/jsonapi/src/Routing/Param/JsonApiParamInterface.php
    @@ -0,0 +1,41 @@
    +  /**
    +   * The key name.
    +   *
    +   * @var string
    +   */
    +  const KEY_NAME = NULL;
    

    I couldn't find any usecase for this, was this basically meant as abstract constant or so?

  9. +++ b/core/modules/jsonapi/tests/src/Unit/Routing/JsonApiParamEnhancerTest.php
    @@ -0,0 +1,97 @@
    +  public function testApplies() {
    +    $object = new JsonApiParamEnhancer($this->prophesize(EntityFieldManagerInterface::class)->reveal());
    +    $route = $this->prophesize(Route::class);
    +    $route->getDefault(RouteObjectInterface::CONTROLLER_NAME)->will(new ReturnPromise([Routes::FRONT_CONTROLLER, 'lorem']));
    +
    +    $this->assertTrue($object->applies($route->reveal()));
    +    $this->assertFalse($object->applies($route->reveal()));
    +  }
    

    Wow, that's cool

hampercm’s picture

Assigned: Unassigned » hampercm

Working on a patch...

hampercm’s picture

StatusFileSize
new21.04 KB

Addressed first block of code review comments from #1:

hampercm’s picture

Ugh, bad patch uploaded...

hampercm’s picture

StatusFileSize
new9.81 KB

Correct patch for #4:

Addressed first block of code review comments from #1:
1) Leaving README.md as-is for now.
2) Change this in the core patch only, as the module is supported on 8.2.x?
3) Fixed
4) Reordered
7) Add @see to PHPDoc
8) Changed as suggested
10) Changed as suggested
12) Replaced with try/catch and added test.
13) Leaving as-is for clarity, since this check is verifying both are content entities.
14) Fixed

5, 6, and 11 didn't require any changes (I think, please verify @e0ipso!)

9) needs further consideration: move the Exception classes into an Exception namespace, and leave the ErrorHandler where it is?

Patch for second block of comments in #1 still to come.

e0ipso’s picture

Status: Active » Needs review

The patch in #6 looks good!

dawehner’s picture

5, 6, and 11 didn't require any changes (I think, please verify @e0ipso!)

Yeah totally ...

9) needs further consideration: move the Exception classes into an Exception namespace, and leave the ErrorHandler where it is?

You know, I just like things to be named what they are :)

  1. +++ b/jsonapi.module
    @@ -18,15 +18,9 @@ function jsonapi_help($route_name, RouteMatchInterface $route_match) {
    +      $output .= '<p>' . t('The JSON API module is a fully compliant implementation of the <a href=":spec">JSON API Specification</a>. By following shared conventions, you can increase productivity, take advantage of generalized tooling, and focus on what matters: your application. Clients built around JSON API are able to take advantage of its features such as efficiently caching responses, sometimes eliminating network requests entirely. For more information, see the <a href=":docs">online documentation for the JSON API module</a>.', [
    

    Note: Once we have committed it to core we should certainly try to get us up on http://jsonapi.org/implementations/

  2. +++ b/jsonapi.services.yml
    @@ -1,4 +1,18 @@
    +  serializer.normalizer.htt_exception.jsonapi:
    +    class: Drupal\jsonapi\Normalizer\HttpExceptionNormalizer
    +    arguments: ['@current_user']
    +    tags:
    +      - { name: normalizer, priority: 1 }
    +  serializer.normalizer.unprocessable_entity_exception.jsonapi:
    +    class: Drupal\jsonapi\Normalizer\UnprocessableHttpEntityExceptionNormalizer
    +    arguments: ['@current_user']
    +    tags:
    +      - { name: normalizer, priority: 2 }
    +  serializer.normalizer.scalar.jsonapi:
    +    class: Drupal\jsonapi\Normalizer\ScalarNormalizer
    +    tags:
    +      - { name: normalizer, priority: 5 }
    

    Thank you! That's much better

hampercm’s picture

StatusFileSize
new14.27 KB
new4.46 KB

Addressing second block of comments from #1:
1) Needs to be addressed in the core patch.
2) Done
3) This seems to break something. Leaving as-is.
4) Simplified.
6) Simplified.
7) PHPDoc adjusted
8) Yes, this appears to document that constant being needed in all classes that extend JsonApiParamInterface. I added a bit more documentation explaining it.

Nothing to be done for 5 and 9.

hampercm’s picture

StatusFileSize
new27.8 KB
new13.72 KB

Move exception classes to \Drupal\jsonapi\Exception namespace.

All above comments that can be addressed here have been.

hampercm’s picture

Assigned: hampercm » Unassigned
dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Cool, thank you!

e0ipso’s picture

Status: Reviewed & tested by the community » Fixed

  • e0ipso committed 05e9cb4 on 8.x-1.x authored by hampercm
    fix(Misc) Address core feedback 2843147#comment-11872253 (#2844373 by...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.