Commit e95c8ab8 authored by Stephen Lucero's avatar Stephen Lucero
Browse files

Issue #3297124 by slucero, krisahil: Flatten Schema References During Schema Loading

parent 90c54968
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -16,9 +16,13 @@
    "require": {
        "php": ">=7.4.0",
        "ext-json": "*",
        "marcj/topsort": "^2.0.0",
        "swaggest/json-schema": "^0.12",
        "symfony/finder": "^3.4 || ^4.0",
        "symfony/polyfill-php80": "^1",
        "symfony/polyfill-php81": "^1",
        "symfony/yaml": "^3.4 || ^4.0",
        "webmozart/assert": "^1.0",
        "webmozart/path-util": "^2.1.0"
    },
    "require-dev": {
+1 −0
Original line number Diff line number Diff line
@@ -5,5 +5,6 @@ services:
      - '@entity_type.manager'
      - '@patternkit.asset.library'
      - '@patternkit.pattern.discovery'
      - '@patternkit.pattern.repository'
    tags:
      - { name: drush.command }
+14 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ use Drupal\Core\Entity\EntityViewBuilder;
use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
use Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\patternkit\Commands\PatternkitCommands;
use Drupal\patternkit\Entity\Pattern;
use Drupal\patternkit\Entity\PatternRouteProvider;
@@ -202,3 +203,16 @@ function patternkit_update_8005(&$sandbox) {
    $config_current->save();
  }
}

/**
 * Adds 'dependencies' field to 'patternkit_pattern' entities.
 */
function patternkit_update_9001(&$sandbox) {
  $field_storage_definition = BaseFieldDefinition::create('string')
    ->setLabel(t('Dependencies'))
    ->setDescription(t('A collection of pattern reference dependencies detected within the Pattern.'))
    ->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);

  \Drupal::entityDefinitionUpdateManager()
    ->installFieldStorageDefinition('dependencies', 'patternkit_pattern', 'patternkit', $field_storage_definition);
}
+76 −0
Original line number Diff line number Diff line
<?php

/**
 * @file
 * Post-update operations for the Patternkit module.
 */

use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Utility\UpdateException;
use Drupal\Component\Plugin\Exception\PluginException;

/**
 * Populate the dependencies field for all existing pattern entities.
 */
function patternkit_post_update_set_pattern_dependencies(): TranslatableMarkup {
  $libraryPluginManager = \Drupal::service('plugin.manager.library.pattern');
  $pattern_storage = \Drupal::entityTypeManager()
    ->getStorage('patternkit_pattern');

  // Cache parser plugins once they're loaded to avoid repetitive plugin
  // creation.
  $parsers = [];

  // Count how many patterns were updated for final reporting.
  $updated = 0;

  // Load all existing pattern entities.
  $entities = $pattern_storage->loadMultiple();

  // Iterate through all pattern entities to set dependencies.
  /** @var \Drupal\patternkit\Entity\PatternInterface $pattern */
  foreach ($entities as $id => $pattern) {
    try {
      // Load the specific parser for the pattern.
      $plugin_id = $pattern->getLibraryPluginId();
      $parsers[$plugin_id] ??= $libraryPluginManager->createInstance($plugin_id)
        ->getParser();
      $plugin = $parsers[$plugin_id];

      // Use the parser to get all pattern dependencies.
      if (method_exists($plugin, 'getSchemaDependencies')) {
        $dependencies = $plugin->getSchemaDependencies($pattern->getSchema(), $pattern->getAssetId());
      }

      if ($dependencies) {
        // Set the discovered dependencies on the pattern entity.
        $pattern->setDependencies($dependencies);

        // Update the revision in place to avoid breaking references.
        $pattern->setNewRevision(FALSE);

        // Store the updated values.
        $pattern->save();

        $updated++;
      }
    }
    catch (PluginException $pluginException) {
      $message = sprintf('Failed to load plugin "%s" for pattern entity %d for pattern %s.',
        $pattern->getLibraryPluginId(), $id, $pattern->getAssetId());
      \Drupal::logger('patternkit')->error($message);
      throw new UpdateException($message);
    }
    catch (EntityStorageException $exception) {
      $message = sprintf('Failed to update pattern entity %d for pattern %s: %s',
        $id, $pattern->getAssetId(), $exception->getMessage());
      \Drupal::logger('patternkit')->error($message);
      throw new UpdateException($message);
    }
  }

  return t('Set dependencies on @count existing patterns.', [
    '@count' => $updated,
  ]);
}
+72 −5
Original line number Diff line number Diff line
@@ -12,7 +12,18 @@ services:
    deprecated: 'The "%service_id%" service is deprecated. Use "patternkit.library.namespace_resolver" or "patternkit.pattern.discovery" instead.'
  patternkit.asset.library.parser.base:
    abstract: true
    arguments: [ '@serialization.json', '%app.root%', '@module_handler', '@theme.manager', '@stream_wrapper_manager', '@library.libraries_directory_file_finder', '@extension.path.resolver', '@entity_type.manager' ]
    arguments:
      - '@serialization.json'
      - '%app.root%'
      - '@module_handler'
      - '@theme.manager'
      - '@stream_wrapper_manager'
      - '@library.libraries_directory_file_finder'
      - '@extension.path.resolver'
      - '@entity_type.manager'
      - '@patternkit.schema.data_preprocessor.factory'
      - '@patternkit.pattern.dependency_resolver'
      - '@logger.channel.patternkit'
  patternkit.asset.library.parser.file:
    parent: patternkit.asset.library.parser.base
    class: Drupal\patternkit\Asset\PatternLibraryParser\FilePatternLibraryParser
@@ -40,6 +51,24 @@ services:
    arguments: [ '@cache.discovery', '@lock', '@patternkit.library.namespace_resolver', '@plugin.manager.library.pattern', '@logger.channel.patternkit']
    tags:
      - { name: needs_destruction }
  patternkit.pattern.dependency_resolver:
    class: Drupal\patternkit\Asset\PatternDependencyResolver
    arguments:
      - '@patternkit.pattern.discovery'
      - '@entity_type.manager'
      - '@patternkit.schema.data_preprocessor.factory'
      - '@logger.channel.patternkit'
    calls:
      - ['setContextBuilder', ['@patternkit.schema.context_builder']]
  patternkit.pattern.repository:
    class: Drupal\patternkit\PatternRepository
    arguments:
      - '@patternkit.pattern.discovery'
      - '@patternkit.pattern.dependency_resolver'
      - '@patternkit.schema.data_preprocessor.factory'
      - '@entity_type.manager'
    calls:
      - ['setContextBuilder', ['@patternkit.schema.context_builder']]
  plugin.manager.library.pattern:
    class: Drupal\patternkit\PatternLibraryPluginManager
    arguments: ['@container.namespaces', '@cache.discovery', '@module_handler', '@theme_handler']
@@ -75,16 +104,54 @@ services:
  patternkit.schema.schema_factory:
    class: Drupal\patternkit\Schema\SchemaFactory
    arguments:
      - '@patternkit.schema.ref_provider'
      - '@patternkit.schema.context_builder'
  patternkit.schema.context_builder:
    class: Drupal\patternkit\Schema\ContextBuilder
    calls:
      - ['setRemoteRefProvider', ['@patternkit.schema.ref_provider']]
      - ['setDataPreProcessor', ['@patternkit.schema.data_preprocessor.objects']]
  patternkit.schema.ref_handler:
    class: Drupal\patternkit\Schema\SchemaRefHandler
  patternkit.schema.ref_provider:
    class: Drupal\patternkit\Schema\PatternkitRefProvider
    arguments:
      - '@patternkit.pattern.discovery'
      - '@patternkit.library.namespace_resolver'
      - '@entity_type.manager'
      - '@patternkit.schema.ref_handler'
      - '@logger.channel.patternkit'
    public: false
  patternkit.schema.schema_walker_factory:
    class: Drupal\patternkit\Schema\SchemaWalkerFactory
    arguments:
      - '@patternkit.schema.schema_factory'
    public: false

  # Define schema data preprocessors used for various operations.
  patternkit.schema.data_preprocessor.factory:
    class: Drupal\patternkit\Schema\DataPreProcessorFactory
    tags:
      - { name: 'service_collector', tag: 'schema_data_preprocessor', call: 'addPreProcessor' }
  patternkit.schema.data_preprocessor.objects:
    class: Drupal\patternkit\Schema\DataPreProcessor\ObjectCoercionDataPreProcessor
    tags:
      - { name: 'schema_data_preprocessor', alias: 'objects' }
    public: false
  patternkit.schema.data_preprocessor.bundler:
    class: Drupal\patternkit\Schema\DataPreProcessor\BundleReferenceDataPreProcessor
    arguments:
      - '@patternkit.schema.ref_handler'
    tags:
      - { name: 'schema_data_preprocessor', alias: 'bundler' }
    public: false
  patternkit.schema.data_preprocessor.normalizer:
    class: Drupal\patternkit\Schema\DataPreProcessor\RefNormalizerDataPreProcessor
    arguments:
      - '@patternkit.schema.ref_handler'
    tags:
      - { name: 'schema_data_preprocessor', alias: 'normalizer' }
    public: false
  patternkit.schema.data_preprocessor.ref_observer:
    class: Drupal\patternkit\Schema\DataPreProcessor\SchemaRefObserver
    arguments:
      - '@patternkit.schema.ref_handler'
    tags:
      - { name: 'schema_data_preprocessor', alias: 'ref_observer' }
    public: false
Loading