You are here

abstract class OpenApiGeneratorBase in OpenAPI 8.2

Same name and namespace in other branches
  1. 8 src/Plugin/openapi/OpenApiGeneratorBase.php \Drupal\openapi\Plugin\openapi\OpenApiGeneratorBase

Defines base class for OpenApi Generator plugins.

Hierarchy

Expanded class hierarchy of OpenApiGeneratorBase

1 file declares its use of OpenApiGeneratorBase
NullGenerator.php in tests/modules/openapi_test/src/Plugin/openapi/OpenApiGenerator/NullGenerator.php

File

src/Plugin/openapi/OpenApiGeneratorBase.php, line 22

Namespace

Drupal\openapi\Plugin\openapi
View source
abstract class OpenApiGeneratorBase extends PluginBase implements OpenApiGeneratorInterface, ContainerFactoryPluginInterface {
  use StringTranslationTrait;

  /**
   * Separator for using in definition id strings.
   *
   * @var string
   */
  static $DEFINITION_SEPARATOR = ':';

  /**
   * The generator label.
   *
   * @var string
   */
  public $label;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The route provider.
   *
   * @var \Drupal\Core\Routing\RouteProviderInterface
   */
  protected $routingProvider;

  /**
   * The Field Manager.
   *
   * @var \Drupal\Core\Entity\EntityFieldManagerInterface
   */
  protected $fieldManager;

  /**
   * The serializer.
   *
   * @var \Symfony\Component\Serializer\SerializerInterface
   */
  protected $serializer;

  /**
   * The configuration object factory.
   *
   * @var \Symfony\Component\HttpFoundation\Request
   */
  protected $request;

  /**
   * The configuration object factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * The request options parameter.
   *
   * @var mixed|array
   */
  protected $options;

  /**
   * The configuration object factory.
   *
   * @var \Drupal\Core\Authentication\AuthenticationCollectorInterface
   */
  protected $authenticationCollector;

  /**
   * OpenApiGeneratorBase constructor.
   *
   * @param array $configuration
   *   Plugin configuration.
   * @param string $plugin_id
   *   Unique plugin id.
   * @param array|mixed $plugin_definition
   *   Plugin instance definition.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Routing\RouteProviderInterface $routing_provider
   *   The routing provider.
   * @param \Drupal\Core\Entity\EntityFieldManagerInterface $field_manager
   *   The field manager.
   * @param \Symfony\Component\Serializer\SerializerInterface $serializer
   *   The serializer.
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   The current request stack.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The configuration object factory.
   * @param \Drupal\Core\Authentication\AuthenticationCollectorInterface $authentication_collector
   *   The authentication collector.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, RouteProviderInterface $routing_provider, EntityFieldManagerInterface $field_manager, SerializerInterface $serializer, RequestStack $request_stack, ConfigFactoryInterface $config_factory, AuthenticationCollectorInterface $authentication_collector) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->label = $this
      ->getPluginDefinition()["label"];
    $this->entityTypeManager = $entity_type_manager;
    $this->routingProvider = $routing_provider;
    $this->fieldManager = $field_manager;
    $this->serializer = $serializer;
    $this->request = $request_stack
      ->getCurrentRequest();
    $this->configFactory = $config_factory;
    $this->authenticationCollector = $authentication_collector;
    $this->options = [];
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static($configuration, $plugin_id, $plugin_definition, $container
      ->get('entity_type.manager'), $container
      ->get('router.route_provider'), $container
      ->get('entity_field.manager'), $container
      ->get('serializer'), $container
      ->get('request_stack'), $container
      ->get('config.factory'), $container
      ->get('authentication_collector'));
  }

  /**
   * {@inheritdoc}
   */
  public function setOptions($options) {
    $this->options = $options;
  }

  /**
   * {@inheritdoc}
   */
  public function getOptions() {
    return $this->options;
  }

  /**
   * {@inheritdoc}
   */
  public function getId() {
    return $this
      ->getPluginId();
  }

  /**
   * {@inheritdoc}
   */
  public function getLabel() {
    if ($this->label === NULL) {

      // Load value from definition.
      $this->label = $this
        ->get()["label"];
    }
    return $this->label;
  }

  /**
   * {@inheritdoc}
   */
  public function getSpecification() {
    $basePath = $this
      ->getBasePath();
    $spec = [
      'swagger' => "2.0",
      'schemes' => [
        $this->request
          ->getScheme(),
      ],
      'info' => $this
        ->getInfo(),
      'host' => $this->request
        ->getHttpHost(),
      'basePath' => empty($basePath) ? '/' : $basePath,
      'securityDefinitions' => $this
        ->getSecurityDefinitions(),
      'security' => $this
        ->getSecurity(),
      'tags' => $this
        ->getTags(),
      'definitions' => $this
        ->getDefinitions(),
      'consumes' => $this
        ->getConsumes(),
      'produces' => $this
        ->getProduces(),
      'paths' => $this
        ->getPaths(),
    ];

    // Strip any empty arrays which aren't required.
    $required = [
      'swagger',
      'info',
      'paths',
    ];
    foreach ($spec as $key => $item) {
      if (!in_array($key, $required) && is_array($item) && !count($item)) {
        unset($spec[$key]);
      }
    }
    return $spec;
  }

  /**
   * Creates the 'info' portion of the API.
   *
   * @return array
   *   The info elements.
   */
  protected function getInfo() {
    $site_name = $this->configFactory
      ->get('system.site')
      ->get('name');
    return [
      'description' => $this
        ->getApiDescription(),
      'title' => $site_name . ' - ' . $this
        ->getApiName(),
      'version' => 'Versioning not supported',
    ];
  }

  /**
   * Gets the API name.
   *
   * @return string
   *   The API name.
   */
  public abstract function getApiName();

  /**
   * {@inheritdoc}
   */
  public function getBasePath() {
    return $this->request
      ->getBasePath();
  }

  /**
   * {@inheritdoc}
   */
  public function getSecurityDefinitions() {
    $base_url = $this->request
      ->getSchemeAndHttpHost() . '/' . $this->request
      ->getBasePath();
    $auth_providers = $this->authenticationCollector
      ->getSortedProviders();
    $security_definitions = [];
    foreach ($auth_providers as $provider => $info) {
      $def = NULL;
      switch ($provider) {
        case 'basic_auth':
          $def = [
            'type' => 'basic',
          ];
          break;
        case 'oauth2':
          $def = [
            'type' => 'oauth2',
            'description' => 'For more information see https://developers.getbase.com/docs/rest/articles/oauth2/requests',
            'flows' => [
              'password' => [
                'tokenUrl' => $base_url . 'oauth/token',
                'refreshUrl' => $base_url . 'oauth/token',
              ],
              'authorizationCode' => [
                'authorizationUrl' => $base_url . 'oauth/authorize',
                'tokenUrl' => $base_url . 'oauth/token',
                'refreshUrl' => $base_url . 'oauth/token',
              ],
              'implicit' => [
                'authorizationUrl' => $base_url . 'oauth/authorize',
                'refreshUrl' => $base_url . 'oauth/token',
              ],
              'clientCredentials' => [
                'tokenUrl' => $base_url . 'oauth/token',
                'refreshUrl' => $base_url . 'oauth/token',
              ],
            ],
          ];
          break;
        default:
          continue 2;
      }
      if ($def !== NULL) {
        $security_definitions[$provider] = $def;
      }
    }

    // Core's CSRF token doesn't have an auth provider.
    $security_definitions['csrf_token'] = [
      'type' => 'apiKey',
      'name' => 'X-CSRF-Token',
      'in' => 'header',
      'x-tokenUrl' => $base_url . 'user/token',
    ];
    return $security_definitions;
  }
  public function getSecurity() {

    // @TODO: #2977109 - Calculate oauth scopes required.
    $security = [];
    foreach (array_keys($this
      ->getSecurityDefinitions()) as $method) {
      $security[$method] = [];
    }
    return $security;
  }

  /**
   * {@inheritdoc}
   */
  public function getTags() {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function getDefinitions() {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function getPaths() {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function getConsumes() {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function getProduces() {
    return [];
  }

  /**
   * Gets the JSON Schema for an entity type or entity type and bundle.
   *
   * @param string $described_format
   *   The format that will be described, json, json_api, etc.
   * @param string $entity_type_id
   *   The entity type id.
   * @param string $bundle_name
   *   The bundle name.
   *
   * @return array
   *   The JSON schema.
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  protected abstract function getJsonSchema($described_format, $entity_type_id, $bundle_name = NULL);

  /**
   * Cleans JSON schema definitions for OpenAPI.
   *
   * @todo Just to test if fixes
   *       https://github.com/OAI/OpenAPI-Specification/issues/229
   *
   * @param array $json_schema
   *   The JSON Schema elements.
   *
   * @return array
   *   The cleaned JSON Schema elements.
   */
  protected function cleanSchema(array $json_schema) {
    foreach ($json_schema as &$value) {
      if ($value === NULL) {
        $value = '';
      }
      else {
        if (is_array($value)) {
          $this
            ->fixDefaultFalse($value);
          $value = $this
            ->cleanSchema($value);
        }
      }
    }
    return $json_schema;
  }

  /**
   * Fix default field value as zero instead of FALSE.
   *
   * @param array $value
   *   JSON Schema field value.
   */
  protected function fixDefaultFalse(array &$value) {
    $type_is_array = isset($value['type']) && $value['type'] === 'array';
    $has_properties = isset($value['items']['properties']) && is_array($value['items']['properties']);
    $has_default = isset($value['default']) && is_array($value['default']);
    if ($type_is_array && $has_properties && $has_default) {
      foreach ($value['items']['properties'] as $property_key => $property) {
        if ($property['type'] === 'boolean') {
          foreach ($value['default'] as &$default_values) {
            if (isset($default_values[$property_key]) && empty($default_values[$property_key])) {
              $default_values[$property_key] = FALSE;
            }
          }
        }
      }
    }
  }

  /**
   * Get possible responses for an entity type.
   *
   * @param string $entity_type_id
   *   The entity type.
   * @param string $method
   *   The method.
   * @param string $bundle_name
   *   The bundle name.
   *
   * @return array
   *   The entity responses.
   */
  protected function getEntityResponses($entity_type_id, $method, $bundle_name = NULL) {
    $method = strtolower($method);
    $responses = [];
    $schema_response = [];
    if ($definition_ref = $this
      ->getDefinitionReference($entity_type_id, $bundle_name)) {
      $schema_response = [
        'schema' => [
          '$ref' => $definition_ref,
        ],
      ];
    }
    switch ($method) {
      case 'get':
        $responses['200'] = [
          'description' => 'successful operation',
        ] + $schema_response;
        break;
      case 'post':
        unset($responses['200']);
        $responses['201'] = [
          'description' => 'Entity created',
        ] + $schema_response;
        break;
      case 'delete':
        unset($responses['200']);
        $responses['201'] = [
          'description' => 'Entity deleted',
        ];
        break;
    }
    return $responses;
  }

  /**
   * Gets the reference to the definition in the document.
   *
   * @param string $entity_type_id
   *   The entity type id.
   * @param string $bundle_name
   *   The bundle name.
   *
   * @return string
   *   The reference to the definition.
   */
  protected function getDefinitionReference($entity_type_id, $bundle_name = NULL) {
    $definition_key = $this
      ->getEntityDefinitionKey($entity_type_id, $bundle_name);
    if ($this
      ->definitionExists($definition_key)) {
      $definition_ref = '#/definitions/' . $definition_key;
      return $definition_ref;
    }
    return '';
  }

  /**
   * Gets the entity definition key.
   *
   * @param string $entity_type_id
   *   The entity type.
   * @param string $bundle_name
   *   The bundle name.
   *
   * @return string
   *   The entity definition key. Either [entity_type] or
   *   [entity_type]:[bundle_name]
   */
  protected function getEntityDefinitionKey($entity_type_id, $bundle_name = NULL) {
    $definition_key = $entity_type_id;
    if ($bundle_name) {
      $definition_key .= static::$DEFINITION_SEPARATOR . $bundle_name;
    }
    return $definition_key;
  }

  /**
   * Check whether a definitions exists for a key.
   *
   * @param string $definition_key
   *   The definition to check.
   *
   * @return bool
   *   TRUE if it exists.
   */
  protected function definitionExists($definition_key) {
    $definitions = $this
      ->getDefinitions();
    return isset($definitions[$definition_key]);
  }

  /**
   * Determines if an entity type and/or bundle show be included.
   *
   * @param string $entity_type_id
   *   The entity type id.
   * @param string|null $bundle_name
   *   The bundle name.
   *
   * @return bool
   *   True if the entity type or bundle should be included.
   */
  protected function includeEntityTypeBundle($entity_type_id, $bundle_name = NULL) {

    // Entity types or a specific bundle be can excluded.
    if (isset($this->options['exclude'])) {
      if (array_intersect([
        $entity_type_id,
        $this
          ->getEntityDefinitionKey($entity_type_id, $bundle_name),
      ], $this->options['exclude'])) {
        return FALSE;
      }
    }
    if (isset($this->options['entity_mode'])) {
      $entity_type = $this->entityTypeManager
        ->getDefinition($entity_type_id);
      if ($this->options['entity_mode'] == 'content_entities') {
        return $entity_type instanceof ContentEntityTypeInterface;
      }
      if ($this->options['entity_mode'] == 'config_entities') {
        return $entity_type instanceof ConfigEntityTypeInterface;
      }
    }
    if (isset($this->options['entity_type_id']) && $this->options['entity_type_id'] !== $entity_type_id) {
      return FALSE;
    }
    if (isset($bundle_name) && isset($this->options['bundle_name']) && $this->options['bundle_name'] !== $bundle_name) {
      return FALSE;
    }
    return TRUE;
  }

  /**
   * Gets API description.
   *
   * @return string
   *   The API Description.
   */
  protected abstract function getApiDescription();

}

Members

Namesort descending Modifiers Type Description Overrides
OpenApiGeneratorBase::$authenticationCollector protected property The configuration object factory.
OpenApiGeneratorBase::$configFactory protected property The configuration object factory.
OpenApiGeneratorBase::$DEFINITION_SEPARATOR static property Separator for using in definition id strings.
OpenApiGeneratorBase::$entityTypeManager protected property The entity type manager.
OpenApiGeneratorBase::$fieldManager protected property The Field Manager.
OpenApiGeneratorBase::$label public property The generator label.
OpenApiGeneratorBase::$options protected property The request options parameter.
OpenApiGeneratorBase::$request protected property The configuration object factory.
OpenApiGeneratorBase::$routingProvider protected property The route provider.
OpenApiGeneratorBase::$serializer protected property The serializer.
OpenApiGeneratorBase::cleanSchema protected function Cleans JSON schema definitions for OpenAPI.
OpenApiGeneratorBase::create public static function Creates an instance of the plugin. Overrides ContainerFactoryPluginInterface::create
OpenApiGeneratorBase::definitionExists protected function Check whether a definitions exists for a key.
OpenApiGeneratorBase::fixDefaultFalse protected function Fix default field value as zero instead of FALSE.
OpenApiGeneratorBase::getApiDescription abstract protected function Gets API description. 1
OpenApiGeneratorBase::getApiName abstract public function Gets the API name. 1
OpenApiGeneratorBase::getBasePath public function Get base path for schema. Overrides OpenApiGeneratorInterface::getBasePath
OpenApiGeneratorBase::getConsumes public function Get a list of all MIME Type that the API Consumes Overrides OpenApiGeneratorInterface::getConsumes 1
OpenApiGeneratorBase::getDefinitionReference protected function Gets the reference to the definition in the document.
OpenApiGeneratorBase::getDefinitions public function Get model definitions for Drupal entities and bundles. Overrides OpenApiGeneratorInterface::getDefinitions
OpenApiGeneratorBase::getEntityDefinitionKey protected function Gets the entity definition key.
OpenApiGeneratorBase::getEntityResponses protected function Get possible responses for an entity type.
OpenApiGeneratorBase::getId public function Get plugin id. Overrides OpenApiGeneratorInterface::getId
OpenApiGeneratorBase::getInfo protected function Creates the 'info' portion of the API.
OpenApiGeneratorBase::getJsonSchema abstract protected function Gets the JSON Schema for an entity type or entity type and bundle. 1
OpenApiGeneratorBase::getLabel public function Get plugin label. Overrides OpenApiGeneratorInterface::getLabel
OpenApiGeneratorBase::getOptions public function Get the options for the current schema download. Overrides OpenApiGeneratorInterface::getOptions
OpenApiGeneratorBase::getPaths public function Returns the paths information. Overrides OpenApiGeneratorInterface::getPaths
OpenApiGeneratorBase::getProduces public function Get a list of all MIME Type that the API Produces Overrides OpenApiGeneratorInterface::getProduces 1
OpenApiGeneratorBase::getSecurity public function Returns a list of valid security types for the api. Overrides OpenApiGeneratorInterface::getSecurity
OpenApiGeneratorBase::getSecurityDefinitions public function Get a list a valid security method definitions. Overrides OpenApiGeneratorInterface::getSecurityDefinitions
OpenApiGeneratorBase::getSpecification public function Generates OpenAPI specification. Overrides OpenApiGeneratorInterface::getSpecification
OpenApiGeneratorBase::getTags public function Get tags for schema. Overrides OpenApiGeneratorInterface::getTags 1
OpenApiGeneratorBase::includeEntityTypeBundle protected function Determines if an entity type and/or bundle show be included.
OpenApiGeneratorBase::setOptions public function Set the options for the current schema download. Overrides OpenApiGeneratorInterface::setOptions
OpenApiGeneratorBase::__construct public function OpenApiGeneratorBase constructor. Overrides PluginBase::__construct
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$pluginDefinition protected property The plugin implementation definition. 1
PluginBase::$pluginId protected property The plugin_id.
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition 3
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::isConfigurable public function Determines if the plugin is configurable.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
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.