class JsonapiHooks

Hook implementations for jsonapi.

Hierarchy

Expanded class hierarchy of JsonapiHooks

File

core/modules/jsonapi/src/Hook/JsonapiHooks.php, line 18

Namespace

Drupal\jsonapi\Hook
View source
class JsonapiHooks {
  use StringTranslationTrait;
  
  /**
   * Implements hook_help().
   */
  public function help($route_name, RouteMatchInterface $route_match) : ?string {
    switch ($route_name) {
      case 'help.page.jsonapi':
        $output = '<h2>' . $this->t('About') . '</h2>';
        $output .= '<p>' . $this->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 features like efficient response caching, which can sometimes eliminate network requests entirely. For more information, see the <a href=":docs">online documentation for the JSON:API module</a>.', [
          ':spec' => 'https://jsonapi.org',
          ':docs' => 'https://www.drupal.org/docs/8/modules/json-api',
        ]) . '</p>';
        $output .= '<dl>';
        $output .= '<dt>' . $this->t('General') . '</dt>';
        $output .= '<dd>' . $this->t('JSON:API is a particular implementation of REST that provides conventions for resource relationships, collections, filters, pagination, and sorting. These conventions help developers build clients faster and encourages reuse of code.') . '</dd>';
        $output .= '<dd>' . $this->t('The <a href=":jsonapi-docs">JSON:API</a> and <a href=":rest-docs">RESTful Web Services</a> modules serve similar purposes. <a href=":comparison">Read the comparison of the RESTFul Web Services and JSON:API modules</a> to determine the best choice for your site.', [
          ':jsonapi-docs' => 'https://www.drupal.org/docs/8/modules/json-api',
          ':rest-docs' => 'https://www.drupal.org/docs/8/core/modules/rest',
          ':comparison' => 'https://www.drupal.org/docs/8/modules/jsonapi/jsonapi-vs-cores-rest-module',
        ]) . '</dd>';
        $output .= '<dd>' . $this->t('Some multilingual features currently do not work well with JSON:API. See the <a href=":jsonapi-docs">JSON:API multilingual support documentation</a> for more information on the current status of multilingual support.', [
          ':jsonapi-docs' => 'https://www.drupal.org/docs/8/modules/jsonapi/translations',
        ]) . '</dd>';
        $output .= '<dd>' . $this->t('Revision support is currently read-only and only for the "Content" and "Media" entity types in JSON:API. See the <a href=":jsonapi-docs">JSON:API revision support documentation</a> for more information on the current status of revision support.', [
          ':jsonapi-docs' => 'https://www.drupal.org/docs/8/modules/jsonapi/revisions',
        ]) . '</dd>';
        $output .= '</dl>';
        return $output;
    }
    return NULL;
  }
  
  /**
   * Implements hook_modules_installed().
   */
  public function modulesInstalled($modules) : void {
    $potential_conflicts = [
      'content_translation',
      'config_translation',
      'language',
    ];
    if (!empty(array_intersect($modules, $potential_conflicts))) {
      \Drupal::messenger()->addWarning($this->t('Some multilingual features currently do not work well with JSON:API. See the <a href=":jsonapi-docs">JSON:API multilingual support documentation</a> for more information on the current status of multilingual support.', [
        ':jsonapi-docs' => 'https://www.drupal.org/docs/8/modules/jsonapi/translations',
      ]));
    }
  }
  
  /**
   * Implements hook_entity_bundle_create().
   */
  public function entityBundleCreate() : void {
    Routes::rebuild();
  }
  
  /**
   * Implements hook_entity_bundle_delete().
   */
  public function entityBundleDelete() : void {
    Routes::rebuild();
  }
  
  /**
   * Implements hook_entity_create().
   */
  public function entityCreate(EntityInterface $entity) : void {
    if (in_array($entity->getEntityTypeId(), [
      'field_storage_config',
      'field_config',
    ])) {
      // @todo Only do this when relationship fields are updated, not just any field.
      Routes::rebuild();
    }
  }
  
  /**
   * Implements hook_entity_delete().
   */
  public function entityDelete(EntityInterface $entity) : void {
    if (in_array($entity->getEntityTypeId(), [
      'field_storage_config',
      'field_config',
    ])) {
      // @todo Only do this when relationship fields are updated, not just any field.
      Routes::rebuild();
    }
  }
  
  /**
   * Implements hook_jsonapi_entity_filter_access().
   */
  public function jsonapiEntityFilterAccess(EntityTypeInterface $entity_type, AccountInterface $account) : array {
    // All core entity types and most or all contrib entity types allow users
    // with the entity type's administrative permission to view all of the
    // entities, so enable similarly permissive filtering to those users as
    // well. A contrib module may override this decision by returning
    // AccessResult::forbidden() from its implementation of this hook.
    if ($admin_permission = $entity_type->getAdminPermission()) {
      return [
        JsonApiFilter::AMONG_ALL => AccessResult::allowedIfHasPermission($account, $admin_permission),
      ];
    }
    return [];
  }
  
  /**
   * Implements hook_jsonapi_ENTITY_TYPE_filter_access() for 'block_content'.
   */
  public function jsonapiBlockContentFilterAccess(EntityTypeInterface $entity_type, AccountInterface $account) : array {
    // @see \Drupal\block_content\BlockContentAccessControlHandler::checkAccess()
    // \Drupal\jsonapi\Access\TemporaryQueryGuard adds the condition for
    // (isReusable()), so this does not have to.
    return [
      JsonApiFilter::AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'access block library'),
      JsonApiFilter::AMONG_PUBLISHED => AccessResult::allowed(),
    ];
  }
  
  /**
   * Implements hook_jsonapi_ENTITY_TYPE_filter_access() for 'comment'.
   */
  public function jsonapiCommentFilterAccess(EntityTypeInterface $entity_type, AccountInterface $account) : array {
    // @see \Drupal\comment\CommentAccessControlHandler::checkAccess()
    // \Drupal\jsonapi\Access\TemporaryQueryGuard adds the condition for
    // (access to the commented entity), so this does not have to.
    return [
      JsonApiFilter::AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'administer comments'),
      JsonApiFilter::AMONG_PUBLISHED => AccessResult::allowedIfHasPermission($account, 'access comments'),
    ];
  }
  
  /**
   * Implements hook_jsonapi_ENTITY_TYPE_filter_access() for 'entity_test'.
   */
  public function jsonapiEntityTestFilterAccess(EntityTypeInterface $entity_type, AccountInterface $account) : array {
    // @see \Drupal\entity_test\EntityTestAccessControlHandler::checkAccess()
    return [
      JsonApiFilter::AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'view test entity'),
    ];
  }
  
  /**
   * Implements hook_jsonapi_ENTITY_TYPE_filter_access() for 'file'.
   */
  public function jsonapiFileFilterAccess(EntityTypeInterface $entity_type, AccountInterface $account) : array {
    // @see \Drupal\file\FileAccessControlHandler::checkAccess()
    // \Drupal\jsonapi\Access\TemporaryQueryGuard adds the condition for
    // (public OR owner), so this does not have to.
    return [
      JsonApiFilter::AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'access content'),
    ];
  }
  
  /**
   * Implements hook_jsonapi_ENTITY_TYPE_filter_access() for 'media'.
   */
  public function jsonapiMediaFilterAccess(EntityTypeInterface $entity_type, AccountInterface $account) : array {
    // @see \Drupal\media\MediaAccessControlHandler::checkAccess()
    return [
      JsonApiFilter::AMONG_PUBLISHED => AccessResult::allowedIfHasPermission($account, 'view media'),
    ];
  }
  
  /**
   * Implements hook_jsonapi_ENTITY_TYPE_filter_access() for 'node'.
   */
  public function jsonapiNodeFilterAccess(EntityTypeInterface $entity_type, AccountInterface $account) : array {
    // @see \Drupal\node\NodeAccessControlHandler::access()
    if ($account->hasPermission('bypass node access')) {
      return [
        JsonApiFilter::AMONG_ALL => AccessResult::allowed()->cachePerPermissions(),
      ];
    }
    if (!$account->hasPermission('access content')) {
      $forbidden = AccessResult::forbidden("The 'access content' permission is required.")->cachePerPermissions();
      return [
        JsonApiFilter::AMONG_ALL => $forbidden,
        JsonApiFilter::AMONG_OWN => $forbidden,
        JsonApiFilter::AMONG_PUBLISHED => $forbidden,
        // For legacy reasons, the Node entity type has a "status" key, so
        // forbid this subset as well, even though it has no semantic meaning.
JsonApiFilter::AMONG_ENABLED => $forbidden,
      ];
    }
    return [
      // @see \Drupal\node\NodeAccessControlHandler::checkAccess()
JsonApiFilter::AMONG_OWN => AccessResult::allowedIfHasPermission($account, 'view own unpublished content'),
      // @see \Drupal\node\NodeGrantDatabaseStorage::access()
      // Note that:
      // - This is just for the default grant. Other node access conditions
      //   are added via the 'node_access' query tag.
      // - Permissions were checked earlier in this function, so we must
      //   vary the cache by them.
JsonApiFilter::AMONG_PUBLISHED => AccessResult::allowed()->cachePerPermissions(),
    ];
  }
  
  /**
   * Implements hook_jsonapi_ENTITY_TYPE_filter_access() for 'shortcut'.
   */
  public function jsonapiShortcutFilterAccess(EntityTypeInterface $entity_type, AccountInterface $account) : array {
    // @see \Drupal\shortcut\ShortcutAccessControlHandler::checkAccess()
    // \Drupal\jsonapi\Access\TemporaryQueryGuard adds the condition for
    // "shortcut_set = $shortcut_set_storage->getDisplayedToUser($current_user)"
    // so this does not have to.
    return [
      JsonApiFilter::AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'administer shortcuts')->orIf(AccessResult::allowedIfHasPermissions($account, [
        'access shortcuts',
        'customize shortcut links',
      ])),
    ];
  }
  
  /**
   * Implements hook_jsonapi_ENTITY_TYPE_filter_access() for 'taxonomy_term'.
   */
  public function jsonapiTaxonomyTermFilterAccess(EntityTypeInterface $entity_type, AccountInterface $account) : array {
    // @see \Drupal\taxonomy\TermAccessControlHandler::checkAccess()
    return [
      JsonApiFilter::AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'administer taxonomy'),
      JsonApiFilter::AMONG_PUBLISHED => AccessResult::allowedIfHasPermission($account, 'access content'),
    ];
  }
  
  /**
   * Implements hook_jsonapi_ENTITY_TYPE_filter_access() for 'user'.
   */
  public function jsonapiUserFilterAccess(EntityTypeInterface $entity_type, AccountInterface $account) : array {
    // @see \Drupal\user\UserAccessControlHandler::checkAccess()
    // \Drupal\jsonapi\Access\TemporaryQueryGuard adds the condition for
    // (!isAnonymous()), so this does not have to.
    return [
      JsonApiFilter::AMONG_OWN => AccessResult::allowed(),
      JsonApiFilter::AMONG_ENABLED => AccessResult::allowedIfHasPermission($account, 'access user profiles'),
    ];
  }
  
  /**
   * Implements hook_jsonapi_ENTITY_TYPE_filter_access() for 'workspace'.
   */
  public function jsonapiWorkspaceFilterAccess(EntityTypeInterface $entity_type, AccountInterface $account) : array {
    // @see \Drupal\workspaces\WorkspaceAccessControlHandler::checkAccess()
    return [
      JsonApiFilter::AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'view any workspace'),
      JsonApiFilter::AMONG_OWN => AccessResult::allowedIfHasPermission($account, 'view own workspace'),
    ];
  }

}

Members

Title Sort descending Modifiers Object type Summary Overrides
JsonapiHooks::entityBundleCreate public function Implements hook_entity_bundle_create().
JsonapiHooks::entityBundleDelete public function Implements hook_entity_bundle_delete().
JsonapiHooks::entityCreate public function Implements hook_entity_create().
JsonapiHooks::entityDelete public function Implements hook_entity_delete().
JsonapiHooks::help public function Implements hook_help().
JsonapiHooks::jsonapiBlockContentFilterAccess public function Implements hook_jsonapi_ENTITY_TYPE_filter_access() for &#039;block_content&#039;.
JsonapiHooks::jsonapiCommentFilterAccess public function Implements hook_jsonapi_ENTITY_TYPE_filter_access() for &#039;comment&#039;.
JsonapiHooks::jsonapiEntityFilterAccess public function Implements hook_jsonapi_entity_filter_access().
JsonapiHooks::jsonapiEntityTestFilterAccess public function Implements hook_jsonapi_ENTITY_TYPE_filter_access() for &#039;entity_test&#039;.
JsonapiHooks::jsonapiFileFilterAccess public function Implements hook_jsonapi_ENTITY_TYPE_filter_access() for &#039;file&#039;.
JsonapiHooks::jsonapiMediaFilterAccess public function Implements hook_jsonapi_ENTITY_TYPE_filter_access() for &#039;media&#039;.
JsonapiHooks::jsonapiNodeFilterAccess public function Implements hook_jsonapi_ENTITY_TYPE_filter_access() for &#039;node&#039;.
JsonapiHooks::jsonapiShortcutFilterAccess public function Implements hook_jsonapi_ENTITY_TYPE_filter_access() for &#039;shortcut&#039;.
JsonapiHooks::jsonapiTaxonomyTermFilterAccess public function Implements hook_jsonapi_ENTITY_TYPE_filter_access() for &#039;taxonomy_term&#039;.
JsonapiHooks::jsonapiUserFilterAccess public function Implements hook_jsonapi_ENTITY_TYPE_filter_access() for &#039;user&#039;.
JsonapiHooks::jsonapiWorkspaceFilterAccess public function Implements hook_jsonapi_ENTITY_TYPE_filter_access() for &#039;workspace&#039;.
JsonapiHooks::modulesInstalled public function Implements hook_modules_installed().
StringTranslationTrait::$stringTranslation protected property The string translation service. 3
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language. 1

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.