You are here

function date_recur_update_8201 in Recurring Dates Field 3.0.x

Same name and namespace in other branches
  1. 8.2 date_recur.install \date_recur_update_8201()
  2. 3.x date_recur.install \date_recur_update_8201()
  3. 3.1.x date_recur.install \date_recur_update_8201()

Update date recur fields with new column schema for 'rrule' property.

File

./date_recur.install, line 41

Code

function date_recur_update_8201(&$sandbox) : void {

  // The process is:
  // 1. Determine all entity types with date recur fields and load their
  //    definitions.
  // 2. Update the SQL table schema for all relevant tables.
  // 3. Inform Drupal of the expected table schemas.
  // 4. Update Drupal's entity type definitions.
  $fieldType = 'date_recur';
  $schema = \Drupal::database()
    ->schema();
  $entityTypeManager = \Drupal::entityTypeManager();
  $entityFieldManager = \Drupal::service('entity_field.manager');
  $entityFieldMap = $entityFieldManager
    ->getFieldMapByFieldType($fieldType);
  $entityStorageSchemaSql = \Drupal::keyValue('entity.storage_schema.sql');

  /** @var \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface $lastInstalledSchemaRepository */
  $lastInstalledSchemaRepository = \Drupal::service('entity.last_installed_schema.repository');

  // The new SQL schema for our column.
  $specification = [
    'description' => 'The repeat rule.',
    'type' => 'text',
  ];

  // Iterate over all date_recur fields for all entity types.
  foreach ($entityFieldMap as $entityTypeId => $fields) {
    $entityStorage = $entityTypeManager
      ->getStorage($entityTypeId);
    if (!$entityStorage instanceof SqlEntityStorageInterface) {
      continue;
    }
    $entityType = $entityTypeManager
      ->getDefinition($entityTypeId);

    // Loads definitions for all fields (even non date_recur).
    $entityFieldStorageDefinitions = $entityFieldManager
      ->getFieldStorageDefinitions($entityTypeId);

    /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $tableMapping */
    $tableMapping = $entityStorage
      ->getTableMapping($entityFieldStorageDefinitions);

    // Intersect date_recur fields with storage definitions for all fields.

    /** @var \Drupal\Core\Field\FieldStorageDefinitionInterface[] $fieldDefinitions */
    $fieldDefinitions = array_intersect_key($entityFieldStorageDefinitions, $fields);

    // Iterate over all date_recur field definitions for this entity type.
    foreach ($fieldDefinitions as $fieldDefinition) {
      $fieldName = $fieldDefinition
        ->getName();
      $tables = [];
      $tables[] = $tableMapping
        ->getFieldTableName($fieldName);
      if ($entityType
        ->isRevisionable() && $fieldDefinition
        ->isRevisionable()) {
        $tables[] = $tableMapping
          ->getDedicatedRevisionTableName($fieldDefinition);
      }

      // Field type column names map to real table column names.
      $columns = $tableMapping
        ->getColumnNames($fieldName);
      $rruleColumnName = $columns['rrule'];
      foreach ($tables as $table) {

        // Change the column spec here.
        $schema
          ->changeField($table, $rruleColumnName, $rruleColumnName, $specification);
      }

      // Update the tracked entity table schema.
      $schemaKey = "{$entityTypeId}.field_schema_data.{$fieldName}";
      $fieldSchemaData = $entityStorageSchemaSql
        ->get($schemaKey);
      foreach ($fieldSchemaData as $tableName => $fieldSchema) {

        // Type is now 'text'.
        $fieldSchemaData[$tableName]['fields'][$rruleColumnName]['type'] = 'text';

        // Type previously was 'varchar', remove the length portion.
        unset($fieldSchemaData[$tableName]['fields'][$rruleColumnName]['length']);
      }
      $entityStorageSchemaSql
        ->set($schemaKey, $fieldSchemaData);

      // Update cached entity definitions for entity types with of single
      // cardinality base fields.
      if ($tableMapping
        ->allowsSharedTableStorage($fieldDefinition)) {
        $definitions = $lastInstalledSchemaRepository
          ->getLastInstalledFieldStorageDefinitions($entityTypeId);
        $definitions[$fieldName] = $fieldDefinition;
        $lastInstalledSchemaRepository
          ->setLastInstalledFieldStorageDefinitions($entityTypeId, $definitions);
      }
    }
  }
}