@snowee@swis.nl

Account created on 8 June 2020, over 4 years ago
  • Developer at SWIS 
#

Recent comments

This patch is a rewrite of the solution in #5, which works but is less readable.

I'm not sure if the issue I ran into today has the exact same cause; but the error messages/behaviour led me to this issue.

In my case, the status report showed that two fields required updates:

Entity/field definitions
Mismatched entity and/or field definitions
The following changes were detected in the entity type and field definitions.
Content

The node.field_duration field needs to be updated.
The node.workshop__duration field needs to be updated.

Trying to save the field settings again, for these duration fields, would throw the SQL exception:

TypeError: array_intersect_key(): Argument #1 ($array) must be of type array, null given in array_intersect_key() (line 2485 of /srv/app/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php)

#0 /srv/app/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php(2485): array_intersect_key()
#1 /srv/app/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php(1755): Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema->hasColumnChanges()
#2 /srv/app/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php(1535): Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema->updateDedicatedTableSchema()
#3 /srv/app/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php(703): Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema->performFieldSchemaOperation()
#4 /srv/app/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(1545): Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema->onFieldStorageDefinitionUpdate()
#5 /srv/app/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(1590): Drupal\Core\Entity\Sql\SqlContentEntityStorage->Drupal\Core\Entity\Sql\{closure}()
#6 /srv/app/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(1548): Drupal\Core\Entity\Sql\SqlContentEntityStorage->wrapSchemaException()
#7 /srv/app/core/lib/Drupal/Core/Field/FieldStorageDefinitionListener.php(104): Drupal\Core\Entity\Sql\SqlContentEntityStorage->onFieldStorageDefinitionUpdate()
#8 /srv/app/core/modules/field/src/Entity/FieldStorageConfig.php(388): Drupal\Core\Field\FieldStorageDefinitionListener->onFieldStorageDefinitionUpdate()
#9 /srv/app/core/modules/field/src/Entity/FieldStorageConfig.php(300): Drupal\field\Entity\FieldStorageConfig->preSaveUpdated()
#10 /srv/app/core/lib/Drupal/Core/Entity/EntityStorageBase.php(562): Drupal\field\Entity\FieldStorageConfig->preSave()
#11 /srv/app/core/lib/Drupal/Core/Entity/EntityStorageBase.php(517): Drupal\Core\Entity\EntityStorageBase->doPreSave()
#12 /srv/app/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php(253): Drupal\Core\Entity\EntityStorageBase->save()
#13 /srv/app/core/lib/Drupal/Core/Entity/EntityBase.php(339): Drupal\Core\Config\Entity\ConfigEntityStorage->save()
#14 /srv/app/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php(608): Drupal\Core\Entity\EntityBase->save()
#15 /srv/app/core/modules/field_ui/src/Form/FieldStorageConfigEditForm.php(229): Drupal\Core\Config\Entity\ConfigEntityBase->save()
#16 [internal function]: Drupal\field_ui\Form\FieldStorageConfigEditForm->save()
#17 /srv/app/core/lib/Drupal/Core/Form/FormSubmitter.php(114): call_user_func_array()
#18 /srv/app/core/lib/Drupal/Core/Form/FormSubmitter.php(52): Drupal\Core\Form\FormSubmitter->executeSubmitHandlers()
#19 /srv/app/core/lib/Drupal/Core/Form/FormBuilder.php(597): Drupal\Core\Form\FormSubmitter->doSubmitForm()
#20 /srv/app/core/lib/Drupal/Core/Form/FormBuilder.php(325): Drupal\Core\Form\FormBuilder->processForm()
#21 /srv/app/core/lib/Drupal/Core/Controller/FormController.php(73): Drupal\Core\Form\FormBuilder->buildForm()
#22 [internal function]: Drupal\Core\Controller\FormController->getContentResult()
#23 /srv/app/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array()
#24 /srv/app/core/lib/Drupal/Core/Render/Renderer.php(580): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#25 /srv/app/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(124): Drupal\Core\Render\Renderer->executeInRenderContext()
#26 /srv/app/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext()
#27 /srv/vendor/symfony/http-kernel/HttpKernel.php(169): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#28 /srv/vendor/symfony/http-kernel/HttpKernel.php(81): Symfony\Component\HttpKernel\HttpKernel->handleRaw()
#29 /srv/app/core/lib/Drupal/Core/StackMiddleware/Session.php(58): Symfony\Component\HttpKernel\HttpKernel->handle()
#30 /srv/app/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session->handle()
#31 /srv/app/core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\Core\StackMiddleware\KernelPreHandle->handle()
#32 /srv/app/core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass()
#33 /srv/app/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\page_cache\StackMiddleware\PageCache->handle()
#34 /srv/app/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle()
#35 /srv/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle()
#36 /srv/app/core/lib/Drupal/Core/DrupalKernel.php(718): Stack\StackedHttpKernel->handle()
#37 /srv/app/index.php(18): Drupal\Core\DrupalKernel->handle()
#38 {main}

After a bunch of testing, I figured out that the issue is the stored entity storage schema; the database fields are 'correct', but this stored schema was not updated. The entity storage schema still listed a _value field, but no _duration or _seconds fields as with a newly added duration field.

I'm not quite sure of the implications, but the _value field appears to be replaced by _duration and _seconds appears to have a simple value (although changing some settings might change that).

In order to resolve my errors I created a script that updates the stored entity storage schema; it renames _value to _duration and adds _seconds with the values my newly created field contained. I am unsure if these values are now completely correct, but I am no longer seeing the warning in the status report and can save the field settings without errors. You can find my script in the form of a drush deploy hook below, but of course; use at your own risk and backup your database. You should only have to change the field names in $fields, the fields will be skipped if there is no _value defined.


/**
 * Fix the stored duration storage schema to prevent SQL errors.
 */

function MODULENAME_deploy_9000() {
  $fields = ['workshop__duration', 'field_duration'];
  $entities = ['node', 'node_revision'];
  $messages = [];

  $entity_storage_schema_sql = \Drupal::keyValue('entity.storage_schema.sql');
  foreach ($fields as $fieldname) {
    $definition = $entity_storage_schema_sql->get('node.field_schema_data.' . $fieldname, []);
    foreach ($entities as $entity) {
      if (!isset($definition[$entity . '__' . $fieldname]['fields'][$fieldname . '_value'])) {
        $messages[] = 'Skipping ' . $entity . ' field ' . $fieldname;
        continue;
      }

      $messages[] = 'Fixing ' . $entity . ' field ' . $fieldname;
      $definition[$entity . '__' . $fieldname]['fields'][$fieldname . '_duration'] = $definition[$entity . '__' . $fieldname]['fields'][$fieldname . '_value'];
      unset($definition[$entity . '__' . $fieldname]['fields'][$fieldname . '_value']);

      $definition[$entity . '__' . $fieldname]['fields'][$fieldname . '_seconds'] = [
        'type' => 'int',
        'size' => 'big',
        'not null' => FALSE,
      ];
    }
    $entity_storage_schema_sql->set('node.field_schema_data.' . $fieldname, $definition);
  }

  return implode(PHP_EOL, $messages);
}

Attached is the patch file containing the changes from MR7, works perfectly.

This patch will always set the response Content-Type to text/calendar.

Attached is the patch from MR11, which is indeed working as intended for installation into a Drupal 10 project.

Production build 0.71.5 2024