drupal-quartiersdedemain/patches/image_field_caption_3472997...

1608 lines
57 KiB
Diff
Raw Normal View History

From a3b983a44de65ceb4f0c0347136cca29b3f03349 Mon Sep 17 00:00:00 2001
From: Dieter Holvoet <dieter.holvoet@gmail.com>
Date: Mon, 9 Sep 2024 11:26:03 +0200
Subject: [PATCH 1/4] Rewrite module to use default field storage
---
image_field_caption.info.yml | 3 +-
image_field_caption.install | 376 +++++++++-------
image_field_caption.module | 307 +++----------
image_field_caption.services.yml | 7 -
src/ImageCaptionItem.php | 104 ++++-
src/ImageCaptionStorage.php | 425 ------------------
.../FieldFormatter/ImageCaptionFormatter.php | 2 +
7 files changed, 355 insertions(+), 869 deletions(-)
delete mode 100644 image_field_caption.services.yml
delete mode 100644 src/ImageCaptionStorage.php
diff --git a/image_field_caption.info.yml b/image_field_caption.info.yml
index 17d7bf9..e04a8e9 100644
--- a/image_field_caption.info.yml
+++ b/image_field_caption.info.yml
@@ -2,4 +2,5 @@ name: Image Field Caption
description: 'Provides a caption textarea for image fields.'
package: Other
type: module
-core_version_requirement: ^9 || ^10
+core_version_requirement: ^9.2 || ^10
+php: 7.1
diff --git a/image_field_caption.install b/image_field_caption.install
index 92e9220..63a974b 100644
--- a/image_field_caption.install
+++ b/image_field_caption.install
@@ -1,172 +1,222 @@
<?php
+use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
+use Drupal\Core\Entity\Sql\SqlContentEntityStorageException;
+
/**
- * @file
- * Install, update and uninstall functions for the image caption module.
+ * Implements hook_install().
*/
+function image_field_caption_install(): void {
+ _image_field_caption_field_type_schema_column_add_helper('image', ['caption', 'caption_format']);
+}
/**
- * Implements hook_schema().
+ * Implements hook_uninstall().
*/
-function image_field_caption_schema() {
- // Image Field Caption table.
- $schema['image_field_caption'] = [
- 'description' => 'The base table for the image_field_caption module.',
- 'fields' => [
- 'entity_type' => [
- 'description' => 'The entity type attached to this caption',
- 'type' => 'varchar',
- 'length' => 128,
- 'not null' => TRUE,
- 'default' => '',
- ],
- 'bundle' => [
- 'description' => 'The bundle attached to this caption',
- 'type' => 'varchar',
- 'length' => 128,
- 'not null' => TRUE,
- 'default' => '',
- ],
- 'field_name' => [
- 'description' => 'The field name attached to this caption',
- 'type' => 'varchar',
- 'length' => 32,
- 'not null' => TRUE,
- 'default' => '',
- ],
- 'entity_id' => [
- 'description' => 'The entity id attached to this caption',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- ],
- 'revision_id' => [
- 'description' => 'The entity id attached to this caption, or NULL if the entity type is not versioned',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => FALSE,
- ],
- 'language' => [
- 'description' => 'The language attached to this caption',
- 'type' => 'varchar',
- 'length' => 32,
- 'not null' => TRUE,
- 'default' => '',
- ],
- 'delta' => [
- 'description' => 'The sequence number for this caption, used for multi-value fields',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- ],
- 'caption' => [
- 'description' => 'The caption text.',
- 'type' => 'text',
- 'not null' => FALSE,
- ],
- 'caption_format' => [
- 'description' => 'The caption format.',
- 'type' => 'varchar',
- 'length' => 255,
- 'not null' => FALSE,
- ],
- ],
- 'indexes' => [
- 'entity_type' => ['entity_type'],
- 'bundle' => ['bundle'],
- 'entity_id' => ['entity_id'],
- 'revision_id' => ['revision_id'],
- 'language' => ['language'],
- ],
- 'primary key' => [
- 'entity_type',
- 'field_name',
- 'entity_id',
- 'language',
- 'delta',
- ],
- ];
-
- // Image Field Caption revision table.
- $schema['image_field_caption_revision'] = [
- 'description' => 'The revision table for the image_field_caption module.',
- 'fields' => [
- 'entity_type' => [
- 'description' => 'The entity type attached to this caption',
- 'type' => 'varchar',
- 'length' => 128,
- 'not null' => TRUE,
- 'default' => '',
- ],
- 'bundle' => [
- 'description' => 'The bundle attached to this caption',
- 'type' => 'varchar',
- 'length' => 128,
- 'not null' => TRUE,
- 'default' => '',
- ],
- 'field_name' => [
- 'description' => 'The field name attached to this caption',
- 'type' => 'varchar',
- 'length' => 32,
- 'not null' => TRUE,
- 'default' => '',
- ],
- 'entity_id' => [
- 'description' => 'The entity id attached to this caption',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- ],
- 'revision_id' => [
- 'description' => 'The entity id attached to this caption, or NULL if the entity type is not versioned',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- ],
- 'language' => [
- 'description' => 'The language attached to this caption',
- 'type' => 'varchar',
- 'length' => 32,
- 'not null' => TRUE,
- 'default' => '',
- ],
- 'delta' => [
- 'description' => 'The sequence number for this caption, used for multi-value fields',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- ],
- 'caption' => [
- 'description' => 'The caption text.',
- 'type' => 'text',
- 'not null' => FALSE,
- ],
- 'caption_format' => [
- 'description' => 'The caption format.',
- 'type' => 'varchar',
- 'length' => 255,
- 'not null' => FALSE,
- ],
- ],
- 'indexes' => [
- 'entity_type' => ['entity_type'],
- 'bundle' => ['bundle'],
- 'entity_id' => ['entity_id'],
- 'revision_id' => ['revision_id'],
- 'language' => ['language'],
- ],
- 'primary key' => [
- 'entity_type',
- 'field_name',
- 'entity_id',
- 'revision_id',
- 'language',
- 'delta',
- ],
- ];
-
- return $schema;
+function image_field_caption_uninstall(): void {
+ _image_field_caption_field_type_schema_column_remove_helper('image', ['caption', 'caption_format']);
}
-/* @todo Programmatically set the default formatter for all fields that uses this field formatter using image_field_caption_uninstall(). */
+/**
+ * Helper function to add new columns to a field type.
+ *
+ * @param $field_type
+ * The field type id.
+ * @param array $columns_to_add
+ * array of the column names from schema() function.
+ *
+ * @see https://gist.github.com/JPustkuchen/ce53d40303a51ca5f17ce7f48c363b9b
+ * @see https://www.drupal.org/project/drupal/issues/937442
+ */
+function _image_field_caption_field_type_schema_column_add_helper(string $field_type, array $columns_to_add = []): void {
+ $processed_fields = [];
+ $field_type_manager = \Drupal::service('plugin.manager.field.field_type');
+ $field_definition = $field_type_manager->getDefinition($field_type);
+ $field_item_class = $field_definition['class'];
+
+ $schema = \Drupal::database()->schema();
+ $entity_type_manager = \Drupal::entityTypeManager();
+ $entity_field_manager = \Drupal::service('entity_field.manager');
+ $entity_field_map = $entity_field_manager->getFieldMapByFieldType($field_type);
+ // The key-value collection for tracking installed storage schema.
+ $entity_storage_schema_sql = \Drupal::keyValue('entity.storage_schema.sql');
+ $entity_definitions_installed = \Drupal::keyValue('entity.definitions.installed');
+
+ foreach ($entity_field_map as $entity_type_id => $field_map) {
+ $entity_storage = $entity_type_manager->getStorage($entity_type_id);
+
+ // Only SQL storage based entities are supported / throw known exception.
+ if (!($entity_storage instanceof SqlContentEntityStorage)) {
+ continue;
+ }
+
+ $entity_type = $entity_type_manager->getDefinition($entity_type_id);
+ $field_storage_definitions = $entity_field_manager->getFieldStorageDefinitions($entity_type_id);
+ /** @var Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
+ $table_mapping = $entity_storage->getTableMapping($field_storage_definitions);
+ // Only need field storage definitions of our field type:
+ /** @var \Drupal\Core\Field\FieldStorageDefinitionInterface $field_storage_definition */
+ foreach (array_intersect_key($field_storage_definitions, $field_map) as $field_storage_definition) {
+ $field_name = $field_storage_definition->getName();
+ try {
+ $table = $table_mapping->getFieldTableName($field_name);
+ } catch (SqlContentEntityStorageException $e) {
+ // Custom storage? Broken site? No matter what, if there is no table
+ // or column, there's little we can do.
+ continue;
+ }
+ // See if the field has a revision table.
+ $revision_table = NULL;
+ if ($entity_type->isRevisionable() && $field_storage_definition->isRevisionable()) {
+ if ($table_mapping->requiresDedicatedTableStorage($field_storage_definition)) {
+ $revision_table = $table_mapping->getDedicatedRevisionTableName($field_storage_definition);
+ }
+ elseif ($table_mapping->allowsSharedTableStorage($field_storage_definition)) {
+ $revision_table = $entity_type->getRevisionDataTable() ?: $entity_type->getRevisionTable();
+ }
+ }
+ // Load the installed field schema so that it can be updated.
+ $schema_key = "$entity_type_id.field_schema_data.$field_name";
+ $field_schema_data = $entity_storage_schema_sql->get($schema_key);
+
+ $processed_fields[] = [$entity_type_id, $field_name];
+ // Loop over each new column and add it as a schema column change.
+ foreach ($columns_to_add as $column_id) {
+ $column = $table_mapping->getFieldColumnName($field_storage_definition, $column_id);
+ // Add `initial_from_field` to the new spec, as this will copy over
+ // the entire data.
+ $field_schema = $field_item_class::schema($field_storage_definition);
+ $spec = $field_schema['columns'][$column_id];
+
+ // Add the new column.
+ $schema->addField($table, $column, $spec);
+ if ($revision_table) {
+ $schema->addField($revision_table, $column, $spec);
+ }
+
+ // Add the new column to the installed field schema.
+ if (!empty($field_schema_data)) {
+ $field_schema_data[$table]['fields'][$column] = $field_schema['columns'][$column_id];
+ $field_schema_data[$table]['fields'][$column]['not null'] = FALSE;
+ if ($revision_table) {
+ $field_schema_data[$revision_table]['fields'][$column] = $field_schema['columns'][$column_id];
+ $field_schema_data[$revision_table]['fields'][$column]['not null'] = FALSE;
+ }
+ }
+ }
+
+ // Save changes to the installed field schema.
+ if (!empty($field_schema_data)) {
+ $entity_storage_schema_sql->set($schema_key, $field_schema_data);
+ }
+ if ($table_mapping->allowsSharedTableStorage($field_storage_definition)) {
+ $key = "$entity_type_id.field_storage_definitions";
+ if ($definitions = $entity_definitions_installed->get($key)) {
+ $definitions[$field_name] = $field_storage_definition;
+ $entity_definitions_installed->set($key, $definitions);
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Helper function to remove columns from a field type.
+ *
+ * @param $field_type
+ * The field type id.
+ * @param array $columns_to_remove
+ * array of the column names from schema() function.
+ *
+ * @see https://gist.github.com/JPustkuchen/ce53d40303a51ca5f17ce7f48c363b9b
+ * @see https://www.drupal.org/project/drupal/issues/937442
+ */
+function _image_field_caption_field_type_schema_column_remove_helper(string $field_type, array $columns_to_remove = []): void {
+ $processed_fields = [];
+ $field_type_manager = \Drupal::service('plugin.manager.field.field_type');
+ $field_definition = $field_type_manager->getDefinition($field_type);
+ $field_item_class = $field_definition['class'];
+
+ $schema = \Drupal::database()->schema();
+ $entity_type_manager = \Drupal::entityTypeManager();
+ $entity_field_manager = \Drupal::service('entity_field.manager');
+ $entity_field_map = $entity_field_manager->getFieldMapByFieldType($field_type);
+ // The key-value collection for tracking installed storage schema.
+ $entity_storage_schema_sql = \Drupal::keyValue('entity.storage_schema.sql');
+ $entity_definitions_installed = \Drupal::keyValue('entity.definitions.installed');
+
+ foreach ($entity_field_map as $entity_type_id => $field_map) {
+ $entity_storage = $entity_type_manager->getStorage($entity_type_id);
+
+ // Only SQL storage based entities are supported / throw known exception.
+ if (!($entity_storage instanceof SqlContentEntityStorage)) {
+ continue;
+ }
+
+ $entity_type = $entity_type_manager->getDefinition($entity_type_id);
+ $field_storage_definitions = $entity_field_manager->getFieldStorageDefinitions($entity_type_id);
+ /** @var Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
+ $table_mapping = $entity_storage->getTableMapping($field_storage_definitions);
+ // Only need field storage definitions of our field type:
+ /** @var \Drupal\Core\Field\FieldStorageDefinitionInterface $field_storage_definition */
+ foreach (array_intersect_key($field_storage_definitions, $field_map) as $field_storage_definition) {
+ $field_name = $field_storage_definition->getName();
+ try {
+ $table = $table_mapping->getFieldTableName($field_name);
+ } catch (SqlContentEntityStorageException $e) {
+ // Custom storage? Broken site? No matter what, if there is no table
+ // or column, there's little we can do.
+ continue;
+ }
+ // See if the field has a revision table.
+ $revision_table = NULL;
+ if ($entity_type->isRevisionable() && $field_storage_definition->isRevisionable()) {
+ if ($table_mapping->requiresDedicatedTableStorage($field_storage_definition)) {
+ $revision_table = $table_mapping->getDedicatedRevisionTableName($field_storage_definition);
+ }
+ elseif ($table_mapping->allowsSharedTableStorage($field_storage_definition)) {
+ $revision_table = $entity_type->getRevisionDataTable() ?: $entity_type->getRevisionTable();
+ }
+ }
+ // Load the installed field schema so that it can be updated.
+ $schema_key = "$entity_type_id.field_schema_data.$field_name";
+ $field_schema_data = $entity_storage_schema_sql->get($schema_key);
+
+ $processed_fields[] = [$entity_type_id, $field_name];
+ // Loop over each new column and add it as a schema column change.
+ foreach ($columns_to_remove as $column_id) {
+ $column = $table_mapping->getFieldColumnName($field_storage_definition, $column_id);
+ // Add `initial_from_field` to the new spec, as this will copy over
+ // the entire data.
+ $field_schema = $field_item_class::schema($field_storage_definition);
+ $spec = $field_schema['columns'][$column_id];
+
+ // Add the new column.
+ $schema->dropField($table, $column);
+ if ($revision_table) {
+ $schema->dropField($revision_table, $column);
+ }
+
+ // Remove the column from the installed field schema.
+ if (!empty($field_schema_data)) {
+ unset($field_schema_data[$table]['fields'][$column]);
+ if ($revision_table) {
+ unset($field_schema_data[$revision_table]['fields'][$column]);
+ }
+ }
+ }
+
+ // Save changes to the installed field schema.
+ if (!empty($field_schema_data)) {
+ $entity_storage_schema_sql->set($schema_key, $field_schema_data);
+ }
+ if ($table_mapping->allowsSharedTableStorage($field_storage_definition)) {
+ $key = "$entity_type_id.field_storage_definitions";
+ if ($definitions = $entity_definitions_installed->get($key)) {
+ $definitions[$field_name] = $field_storage_definition;
+ $entity_definitions_installed->set($key, $definitions);
+ }
+ }
+ }
+ }
+}
diff --git a/image_field_caption.module b/image_field_caption.module
index d49aa67..63f8999 100644
--- a/image_field_caption.module
+++ b/image_field_caption.module
@@ -5,112 +5,72 @@
* Provides a caption textarea for image fields.
*/
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
-use Drupal\Component\Utility\NestedArray;
-
-/**
- * List to do.
- *
- * Support for Views, maybe built in in D8?
- * Support the revision management.
- * */
+use Drupal\image\Plugin\Field\FieldWidget\ImageWidget;
+use Drupal\image_field_caption\ImageCaptionItem;
/**
* Implements hook_field_info_alter().
*/
-function image_field_caption_field_info_alter(&$info) {
- // Set a new class for the image fields.
- $info['image']['class'] = '\Drupal\image_field_caption\ImageCaptionItem';
+function image_field_caption_field_info_alter(array &$info): void {
+ // Override the image field type class
+ $info['image']['class'] = ImageCaptionItem::class;
+
+ // Enable translation for the caption property
+ $info['image']['column_groups']['caption'] = [
+ 'label' => t('Caption'),
+ 'translatable' => TRUE,
+ ];
}
/**
* Implements hook_field_widget_single_element_form_alter().
*/
-function image_field_caption_field_widget_single_element_form_alter(&$element, FormStateInterface $form_state, $context) {
- /** @var \Drupal\field\Entity\FieldConfig $field */
+function image_field_caption_field_widget_single_element_form_alter(array &$element, FormStateInterface $form_state, $context): void {
$field = $context['items']->getFieldDefinition();
- // If the current field is an image field.
- if ($field->getType() == 'image') {
- // Get the current field settings.
- $settings = $field->getSettings();
- // Check if the current field has the caption.
- if (!empty($settings['caption_field'])) {
- $element['#caption_field_required'] = $settings['caption_field_required'];
- $element['#process'][] = '_image_field_caption_widget_process';
- }
+ assert($field instanceof FieldDefinitionInterface);
+
+ if ($field->getType() !== 'image') {
+ return;
}
+
+ $settings = $field->getSettings();
+ $element['#caption_field'] = $settings['caption_field'];
+ $element['#caption_field_required'] = $settings['caption_field_required'];
+ $element['#process'][] = '_image_field_caption_widget_process';
}
/**
* Custom callback function for the #process of an image field type.
*/
-function _image_field_caption_widget_process($element, &$form_state, $form) {
- // Get the entity.
- // $entity = $form_state->getFormObject()->getEntity();
- // // Get the fields definitions.
- // $field_definitions = $entity->getFieldDefinitions();
- // // Get the current field definition.
- // if (!empty($field_definitions[$element['#field_name']])) {
- // $field_definition = $field_definitions[$element['#field_name']];
- // }
- // elseif (!empty($field_definitions[$element['#field_parents'][0]])) {
- // $field_definition = $field_definitions[$element['#field_parents'][0]];
- // }
- // else {
- // $field_definition = NULL;
- // }.
- // Get the current field values (form state).
- $field_values = $form_state->getValues();
- // If the field has parents (ex: paragraphs) then get the nested values.
- if (!empty($element['#field_parents'])) {
- $field_values = NestedArray::getValue($field_values, $element['#field_parents']);
- }
- $field_value = (isset($field_values[$element['#field_name']][$element['#delta']]['image_field_caption'])) ? $field_values[$element['#field_name']][$element['#delta']]['image_field_caption'] : [];
+function _image_field_caption_widget_process(array $element, FormStateInterface $form_state, array $form): array {
+ $item = $element['#value'];
+ $item['fids'] = $element['fids']['#value'];
- // Add the additional caption fields.
- $element['image_field_caption'] = [
+ // TODO: Make #allowed_formats configurable.
+
+ $element['caption'] = [
'#title' => t('Caption'),
'#type' => 'text_format',
- '#value' => (!empty($field_value['value'])) ? $field_value['value'] : ((!empty($element['#value']['caption'])) ? $element['#value']['caption'] : []),
- '#default_value' => (!empty($element['#value']['caption'])) ? $element['#value']['caption'] : (!empty($element['#value']['image_field_caption']) ? $element['#value']['image_field_caption']['value'] : ''),
- '#access' => (bool) $element['#value']['fids'],
- '#format' => (!empty($field_value['format'])) ? $field_value['format'] : ((!empty($element['#value']['caption_format'])) ? $element['#value']['caption_format'] : 'plain_text'),
+ '#default_value' => $item['caption'] ?? '',
+ '#access' => $item['fids'] && $element['#caption_field'],
+ '#format' => $item['caption_format'] ?? 'plain_text',
'#required' => $element['#caption_field_required'],
- '#element_validate' => $element['#caption_field_required'] ? ['_image_field_caption_validate_required'] : [],
+ '#element_validate' => $element['#caption_field_required'] ? [[ImageWidget::class, 'validateRequiredFields']] : [],
];
return $element;
}
-/**
- * Validate callback for caption field, if the user wants them required.
- *
- * This is separated in a validate function instead of a #required flag to
- * avoid being validated on the process callback.
- */
-function _image_field_caption_validate_required($element, FormStateInterface $form_state) {
- // Only do validation if the function is triggered from other places than
- // the image process form.
- // Only do validation if the function is triggered from other places than
- // the image process form.
- $triggering_element = $form_state->getTriggeringElement();
- if (!empty($triggering_element['#submit']) && in_array('file_managed_file_submit', $triggering_element['#submit'], TRUE)) {
- $form_state->setLimitValidationErrors([]);
- }
-}
-
/**
* Implements hook_theme().
*/
-function image_field_caption_theme() {
+function image_field_caption_theme(): array {
return [
'image_caption_formatter' => [
// As we extend the default image format, the variables passed to the
- // callback function are the same than the original
- // "callback" function ("image_formatter").
+ // callback function are the same as the original (image_formatter).
'variables' => [
'item' => NULL,
'item_attributes' => NULL,
@@ -131,10 +91,11 @@ function image_field_caption_theme() {
* (template_preprocess_image_formatter()) and also:
* - caption: An optional caption text.
*/
-function template_preprocess_image_caption_formatter(&$variables) {
- Drupal::moduleHandler()->loadInclude('image', 'inc', 'image.field');
+function template_preprocess_image_caption_formatter(array &$variables): void {
// Prepare the variables array with the original function.
+ Drupal::moduleHandler()->loadInclude('image', 'inc', 'image.field');
template_preprocess_image_formatter($variables);
+
// Set the caption value.
$values = $variables['item']->getValue();
if (!empty($values['caption'])) {
@@ -147,187 +108,19 @@ function template_preprocess_image_caption_formatter(&$variables) {
}
/**
- * Implements hook_entity_storage_load().
- */
-function image_field_caption_entity_storage_load(array $entities, $entity_type_id) {
- $imageCaption = Drupal::service('image_field_caption.storage');
-
- if (in_array($entity_type_id, $imageCaption->list('entity_type'))) {
- // This means we already have some captions.
- // No need to do all kinds of checking then.
- /** @var \Drupal\Core\Entity\Entity $entity */
- foreach ($entities as $entity) {
- // Same load avoiding check.
- if (in_array($entity->bundle(), $imageCaption->list('bundle'))) {
- $needToSave = FALSE;
-
- /** @var \Drupal\Core\Field\FieldItemList $field */
- foreach ($entity->getFields() as $fieldName => $field) {
- $values = $entity->get($fieldName)->getValue();
- foreach ($values as $delta => $value) {
- // Get the caption associated to this field.
- $revision_id = (empty($entity->getRevisionId()) ? $entity->id() : $entity->getRevisionId());
- $caption = $imageCaption->getCaption(
- $entity->getEntityTypeId(),
- $entity->bundle(),
- $fieldName,
- $entity->id(),
- $revision_id,
- $entity->language()->getId(),
- $delta
- );
-
- // Set the caption value.
- if (!empty($caption)) {
- $values[$delta] = $values[$delta] + $caption;
- $needToSave = TRUE;
- }
- }
-
- if ($needToSave) {
- // Save all values.
- $entity->get($fieldName)->setValue($values);
- }
- }
-
- }
- }
- }
-}
-
-/**
- * Implements hook_entity_insert().
+ * Implements hook_config_schema_info_alter().
*/
-function image_field_caption_entity_insert(EntityInterface $entity) {
- image_field_caption_entity_update($entity);
-}
-
-/**
- * Implements hook_entity_update().
- */
-function image_field_caption_entity_update(EntityInterface $entity) {
- $imageCaption = Drupal::service('image_field_caption.storage');
-
- // For a fieldable entity.
- if (($entity instanceof FieldableEntityInterface)) {
- // Get the field names of all image fields.
- $field_names = _image_field_caption_get_image_field_names($entity);
- foreach ($field_names as $field_name) {
- // Get the current field settings.
- $settings = $entity->get($field_name)->getSettings();
- // If the caption is not enabled => pass this field.
- if (empty($settings['caption_field'])) {
- continue;
- }
- // Delete the caption associated to this field.
- $imageCaption->deleteCaption($entity->getEntityTypeId(), $entity->bundle(), $field_name, $entity->id(), $entity->language()
- ->getId());
- // Delete the caption revision associated to this field.
- /*
- $imageCaption->deleteCaptionRevision(
- $entity->getEntityTypeId(), $entity->bundle(),
- $field_name, $entity->id(), $entity->getRevisionId(),
- $entity->language()->getId()); */
- // Get the current field values.
- $values = $entity->get($field_name)->getValue();
- foreach ($values as $delta => $value) {
- // If a caption text is defined.
- if (!empty($value['image_field_caption']['value'])) {
- // Insert the caption associated to this field.
- // @todo Do the insertion using a multiple query instead several queries into a foreach;
- $revision_id = (empty($entity->getRevisionId()) ? $entity->id() : $entity->getRevisionId());
- $imageCaption->insertCaption(
- $entity->getEntityTypeId(),
- $entity->bundle(),
- $field_name,
- $entity->id(),
- $revision_id,
- $entity->language()->getId(),
- $delta,
- $value['image_field_caption']['value'],
- $value['image_field_caption']['format']
- );
- // Insert the caption revision associated to this field.
- /*
- if ($entity->isNewRevision()) {
- $imageCaption->insertCaptionRevision(
- $entity->getEntityTypeId(),
- $entity->bundle(),
- $field_name,
- $entity->id(),
- $revision_id,
- $entity->language()->getId(),
- $delta,
- $value['image_field_caption']['value'],
- $value['image_field_caption']['format']
- );
- }
- */
- }
- }
- }
- }
-}
-
-/**
- * Implements hook_entity_delete().
- */
-function image_field_caption_entity_delete(EntityInterface $entity) {
- $imageCaption = Drupal::service('image_field_caption.storage');
-
- // For a fieldable entity.
- if (($entity instanceof FieldableEntityInterface)) {
- // Get the field names of all image fields.
- $field_names = _image_field_caption_get_image_field_names($entity);
- foreach ($field_names as $field_name) {
- // Delete the caption associated to this field.
- $imageCaption->deleteCaption($entity->getEntityTypeId(), $entity->bundle(), $field_name, $entity->id(), $entity->language()
- ->getId());
- // Delete the caption revisions associated to this field.
- /*
- $imageCaption->deleteCaptionRevisions(
- $entity->getEntityTypeId(), $entity->bundle(),
- $field_name, $entity->id(), $entity->language()->getId()
- );*/
- }
- }
-}
-
-/**
- * Implements hook_entity_revision_delete().
- */
-function image_field_caption_entity_revision_delete(EntityInterface $entity) {
- // $imageCaption = Drupal::service('image_field_caption.storage');
- /*
- // For a fieldable entity.
- if (($entity instanceof FieldableEntityInterface)) {
- // Get the field names of all image fields.
- $field_names = _image_field_caption_get_image_field_names($entity);
- if (!empty($field_names)) {
- // Delete the caption revisions associated to this specific revision.
- $imageCaption->deleteCaptionRevisionsByRevisionId($entity->getRevisionId());
- }
- }
- */
-}
-
-/**
- * Determines the image fields on an entity.
- *
- * @param \Drupal\Core\Entity\FieldableEntityInterface $entity
- * An entity whose fields to analyze.
- *
- * @return array
- * The names of the fields on this entity that support formatted text.
- */
-function _image_field_caption_get_image_field_names(FieldableEntityInterface $entity) {
- // Check if fields definitions are available.
- $field_definitions = $entity->getFieldDefinitions();
- if (empty($field_definitions)) {
- return [];
- }
- // Only return image fields.
- return array_keys(array_filter($field_definitions, function (FieldDefinitionInterface $definition) {
- return in_array($definition->getType(), ['image'], TRUE);
- }));
+function image_field_caption_config_schema_info_alter(array &$definitions): void {
+ $definitions['field.field_settings.image']['mapping']['caption_field'] = [
+ 'type' => 'boolean',
+ 'label' => 'Enable Caption field',
+ ];
+ $definitions['field.field_settings.image']['mapping']['caption_field_required'] = [
+ 'type' => 'boolean',
+ 'label' => 'Caption field required',
+ ];
+ $definitions['field_default_image']['mapping']['caption'] = [
+ 'type' => 'label',
+ 'label' => 'Caption',
+ ];
}
diff --git a/image_field_caption.services.yml b/image_field_caption.services.yml
deleted file mode 100644
index 845c2e6..0000000
--- a/image_field_caption.services.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-services:
- image_field_caption.storage:
- class: Drupal\image_field_caption\ImageCaptionStorage
- arguments:
- - '@cache.data'
- - '@cache_tags.invalidator'
- - '@database'
diff --git a/src/ImageCaptionItem.php b/src/ImageCaptionItem.php
index 1367735..02c0ada 100644
--- a/src/ImageCaptionItem.php
+++ b/src/ImageCaptionItem.php
@@ -2,46 +2,90 @@
namespace Drupal\image_field_caption;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\Core\TypedData\DataDefinition;
use Drupal\image\Plugin\Field\FieldType\ImageItem;
/**
- * Class to provide functionlality for ImageCaptionItem.
+ * Class to provide functionality for ImageCaptionItem.
*/
class ImageCaptionItem extends ImageItem {
+ /**
+ * {@inheritdoc}
+ */
+ public static function defaultStorageSettings() {
+ $settings = parent::defaultStorageSettings();
+ $settings['default_image']['caption'] = '';
+
+ return $settings;
+ }
+
/**
* {@inheritdoc}
*/
public static function defaultFieldSettings() {
- return [
- 'default_image' => [
- 'caption' => '',
- ],
- 'caption_field' => FALSE,
- 'caption_field_required' => FALSE,
- ] + parent::defaultFieldSettings();
+ $settings = parent::defaultFieldSettings();
+ $settings['default_image']['caption'] = '';
+ $settings['caption_field'] = FALSE;
+ $settings['caption_field_required'] = FALSE;
+
+ return $settings;
+ }
+
+ public static function schema(FieldStorageDefinitionInterface $field_definition) {
+ $schema = parent::schema($field_definition);
+
+ $schema['columns']['caption'] = [
+ 'description' => 'The caption text.',
+ 'type' => 'text',
+ 'not null' => FALSE,
+ ];
+
+ $schema['columns']['caption_format'] = [
+ 'description' => 'The caption format.',
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => FALSE,
+ ];
+
+ return $schema;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
+ $properties = parent::propertyDefinitions($field_definition);
+
+ $properties['caption'] = DataDefinition::create('string')
+ ->setLabel(new TranslatableMarkup('Caption'))
+ ->setDescription(new TranslatableMarkup("Short description of the image displayed underneath the image."));
+
+ $properties['caption_format'] = DataDefinition::create('filter_format')
+ ->setLabel(new TranslatableMarkup('Text format of the caption'));
+
+ return $properties;
}
/**
* {@inheritdoc}
*/
public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
- // Get base form from ImageItem.
$element = parent::fieldSettingsForm($form, $form_state);
- // Get field settings.
$settings = $this->getSettings();
- // Get the default field settings.
- $settings_default = self::defaultFieldSettings();
// Add caption option.
$element['caption_field'] = [
'#type' => 'checkbox',
'#title' => t('Enable <em>Caption</em> field'),
- '#default_value' => (!empty($settings['caption_field'])) ? $settings['caption_field'] : $settings_default['caption_field'],
- '#description' => t('Adds an extra text area for captions on image fields.'),
+ '#default_value' => $settings['caption_field'],
+ '#description' => $this->t('Short description of the image displayed underneath the image.'),
'#weight' => 13,
];
+
// Add caption (required) option.
$element['caption_field_required'] = [
'#type' => 'checkbox',
@@ -51,16 +95,44 @@ class ImageCaptionItem extends ImageItem {
'#weight' => 14,
'#states' => [
'visible' => [
- ':input[name="settings[image_caption_field]"]' => ['checked' => TRUE],
+ ':input[name="settings[caption_field]"]' => ['checked' => TRUE],
],
],
];
+
// Add default caption.
$element['default_image']['caption'] = [
'#type' => 'value',
- '#value' => (!empty($settings['default_image']['caption'])) ? $settings['default_image']['caption'] : $settings_default['default_image']['caption'],
+ '#value' => $settings['default_image']['caption'] ?? '',
];
return $element;
}
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function defaultImageForm(array &$element, array $settings) {
+ parent::defaultImageForm($element, $settings);
+
+ $element['default_image']['caption'] = [
+ '#type' => 'textfield',
+ '#title' => $this->t('Caption'),
+ '#description' => $this->t('Short description of the image displayed underneath the image.'),
+ '#default_value' => $settings['default_image']['caption'] ?? '',
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setValue($values, $notify = TRUE): void {
+ if (isset($values['caption']) && is_array($values['caption'])) {
+ $values['caption_format'] = $values['caption']['format'];
+ $values['caption'] = $values['caption']['value'];
+ }
+
+ parent::setValue($values, $notify);
+ }
+
}
diff --git a/src/ImageCaptionStorage.php b/src/ImageCaptionStorage.php
deleted file mode 100644
index 9640903..0000000
--- a/src/ImageCaptionStorage.php
+++ /dev/null
@@ -1,425 +0,0 @@
-<?php
-
-namespace Drupal\image_field_caption;
-
-use Drupal\Core\Database\Connection;
-use Drupal\Core\Cache\CacheBackendInterface;
-use Drupal\Core\Cache\Cache;
-use Drupal\Core\Cache\CacheTagsInvalidator;
-
-/**
- * Storage controller class for image captions.
- *
- * @todo Use array with key/value as argument instead several arguments.
- * @todo The methods isCaption() and deleteCaption() must manage the revisions by itself, instead to have two differents methods.
- */
-class ImageCaptionStorage {
-
- /**
- * The Cache Backend.
- *
- * @var \Drupal\Core\Cache\CacheBackendInterface
- */
- protected $cacheBackend;
-
- /**
- * The Cache Tags Invalidator.
- *
- * @var \Drupal\Core\Cache\CacheTagsInvalidator
- */
- protected $cacheTagsInvalidator;
-
- /**
- * The database connection.
- *
- * @var \Drupal\Core\Database\Connection
- */
- protected $database;
-
- /**
- * The name of the data table.
- *
- * @var string
- */
- protected $tableData = 'image_field_caption';
-
- /**
- * The name of the revision table.
- *
- * @var string
- */
- protected $tableRevision = 'image_field_caption_revision';
-
- /**
- * AbstractService constructor.
- *
- * @param \Drupal\Core\Cache\CacheBackendInterface $cacheBackend
- * The Cache Backend.
- * @param \Drupal\Core\Cache\CacheTagsInvalidatorInterface $cacheTagsInvalidator
- * The cache tags invalidator.
- * @param \Drupal\Core\Database\Connection $database
- * The Database.
- */
- public function __construct(
- CacheBackendInterface $cacheBackend,
- CacheTagsInvalidator $cacheTagsInvalidator,
- Connection $database
- ) {
- $this->cacheBackend = $cacheBackend;
- $this->cacheTagsInvalidator = $cacheTagsInvalidator;
- $this->database = $database;
- }
-
- /**
- * Check if a caption is already defined for the specified arguments.
- *
- * @param string $entity_type
- * The entity type, like 'node' or 'comment'.
- * @param string $bundle
- * The bundle, like 'article' or 'news'.
- * @param string $field_name
- * The field name of the image field,
- * like 'field_image' or 'field_article_image'.
- * @param int $entity_id
- * The entity id.
- * @param int $revision_id
- * The revision id.
- * @param string $language
- * The language key, like 'en' or 'fr'.
- * @param int $delta
- * The delta of the image field.
- *
- * @return bool
- * TRUE if a caption exists or FALSE if not.
- */
- public function isCaption($entity_type, $bundle, $field_name, $entity_id, $revision_id, $language, $delta) {
- return (!empty(self::getCaption($entity_type, $bundle, $field_name, $entity_id, $revision_id, $language, $delta))) ? TRUE : FALSE;
- }
-
- /**
- * Get a caption from the database for the specified arguments.
- *
- * @param string $entity_type
- * The entity type, like 'node' or 'comment'.
- * @param string $bundle
- * The bundle, like 'article' or 'news'.
- * @param string $field_name
- * The field name of the image field,
- * like 'field_image' or 'field_article_image'.
- * @param int $entity_id
- * The entity id.
- * @param int $revision_id
- * The revision id.
- * @param string $language
- * The language key, like 'en' or 'fr'.
- * @param int $delta
- * The delta of the image field.
- *
- * @return array
- * A caption array
- * - caption: The caption text.
- * - caption_format: The caption format.
- * or an empty array, if no value found.
- */
- public function getCaption($entity_type, $bundle, $field_name, $entity_id, $revision_id, $language, $delta) {
- $captions = &drupal_static(__FUNCTION__);
-
- $cacheKey = $this->getCacheKey($entity_type, $entity_id, $revision_id, $language, $field_name, $delta);
-
- if (isset($captions[$cacheKey])) {
- $caption = $captions[$cacheKey];
- }
- elseif ($cached = $this->cacheBackend->get($cacheKey)) {
- $caption = $cached->data;
- }
- else {
- // Query.
- $query = $this->database->select($this->tableData, 'ifc');
- $result = $query
- ->fields('ifc', ['caption', 'caption_format'])
- ->condition('entity_type', $entity_type, '=')
- ->condition('bundle', $bundle, '=')
- ->condition('field_name', $field_name, '=')
- ->condition('entity_id', $entity_id, '=')
- ->condition('revision_id', $revision_id, '=')
- ->condition('language', $language, '=')
- ->condition('delta', $delta, '=')
- ->execute()
- ->fetchAssoc();
-
- // Caption array.
- $caption = [];
- if (!empty($result)) {
- $caption = $result;
- }
-
- // Let the cache depends on the entity.
- // @todo Use getCacheTags() to get the default list.
- $this->cacheBackend->set(
- $cacheKey,
- $caption,
- Cache::PERMANENT,
- [
- $field_name,
- 'image_field_caption',
- ]
- );
- }
-
- return $caption;
- }
-
- /**
- * Insert a caption into the database for the specified arguments.
- *
- * @param string $entity_type
- * The entity type, like 'node' or 'comment'.
- * @param string $bundle
- * The bundle, like 'article' or 'news'.
- * @param string $field_name
- * The field name of the image field,
- * like 'field_image' or 'field_article_image'.
- * @param int $entity_id
- * The entity id.
- * @param int $revision_id
- * The revision id.
- * @param string $language
- * The language key, like 'en' or 'fr'.
- * @param int $delta
- * The delta of the image field.
- * @param string $caption
- * The caption text.
- * @param string $caption_format
- * The text format of the caption.
- */
- public function insertCaption($entity_type, $bundle, $field_name, $entity_id, $revision_id, $language, $delta, $caption, $caption_format) {
-
- $query = $this->database->insert($this->tableData);
- $query
- ->fields([
- 'entity_type' => $entity_type,
- 'bundle' => $bundle,
- 'field_name' => $field_name,
- 'entity_id' => $entity_id,
- 'revision_id' => $revision_id,
- 'language' => $language,
- 'delta' => $delta,
- 'caption' => $caption,
- 'caption_format' => $caption_format,
- ])
- ->execute();
- $this->clearCache($field_name);
- }
-
- /**
- * Insert a caption revision into the database for the specified arguments.
- *
- * @param string $entity_type
- * The entity type, like 'node' or 'comment'.
- * @param string $bundle
- * The bundle, like 'article' or 'news'.
- * @param string $field_name
- * The field name of the image field,
- * like 'field_image' or 'field_article_image'.
- * @param int $entity_id
- * The entity id.
- * @param int $revision_id
- * The revision id.
- * @param string $language
- * The language key, like 'en' or 'fr'.
- * @param int $delta
- * The delta of the image field.
- * @param string $caption
- * The caption text.
- * @param string $caption_format
- * The text format of the caption.
- */
- public function insertCaptionRevision($entity_type, $bundle, $field_name, $entity_id, $revision_id, $language, $delta, $caption, $caption_format) {
- $query = $this->database->insert($this->tableRevision);
- $query
- ->fields([
- 'entity_type' => $entity_type,
- 'bundle' => $bundle,
- 'field_name' => $field_name,
- 'entity_id' => $entity_id,
- 'revision_id' => $revision_id,
- 'language' => $language,
- 'delta' => $delta,
- 'caption' => $caption,
- 'caption_format' => $caption_format,
- ])
- ->execute();
- $this->clearCache($field_name);
- }
-
- /**
- * Delete a caption from the database for the specified arguments.
- *
- * @param string $entity_type
- * The entity type, like 'node' or 'comment'.
- * @param string $bundle
- * The bundle, like 'article' or 'news'.
- * @param string $field_name
- * The field name of the image field, like
- * 'field_image' or 'field_article_image'.
- * @param int $entity_id
- * The entity id.
- * @param string $language
- * The language key, like 'en' or 'fr'.
- */
- public function deleteCaption($entity_type, $bundle, $field_name, $entity_id, $language) {
- $query = $this->database->delete($this->tableData);
- $query
- ->condition('entity_type', $entity_type, '=')
- ->condition('bundle', $bundle, '=')
- ->condition('field_name', $field_name, '=')
- ->condition('entity_id', $entity_id, '=')
- ->condition('language', $language, '=')
- ->execute();
- $this->clearCache($field_name);
- // @todo Try to return the count of the affected rows.
- }
-
- /**
- * Delete a caption revision from the database for the specified arguments.
- *
- * @param string $entity_type
- * The entity type, like 'node' or 'comment'.
- * @param string $bundle
- * The bundle, like 'article' or 'news'.
- * @param string $field_name
- * The field name of the image field, like
- * 'field_image' or 'field_article_image'.
- * @param int $entity_id
- * The entity id.
- * @param int $revision_id
- * The revision id.
- * @param string $language
- * The language key, like 'en' or 'fr'.
- */
- public function deleteCaptionRevision($entity_type, $bundle, $field_name, $entity_id, $revision_id, $language) {
- $query = $this->database->delete($this->tableRevision);
- $query
- ->condition('entity_type', $entity_type, '=')
- ->condition('bundle', $bundle, '=')
- ->condition('field_name', $field_name, '=')
- ->condition('entity_id', $entity_id, '=')
- ->condition('revision_id', $revision_id, '=')
- ->condition('language', $language, '=')
- ->execute();
- $this->clearCache($field_name);
- // @todo Try to return the count of the affected rows.
- }
-
- /**
- * Delete all captions revisions for the specified arguments.
- *
- * @param string $entity_type
- * The entity type, like 'node' or 'comment'.
- * @param string $bundle
- * The bundle, like 'article' or 'news'.
- * @param string $field_name
- * The field name of the image field, like 'field_image'
- * or 'field_article_image'.
- * @param int $entity_id
- * The entity id.
- * @param string $language
- * The language key, like 'en' or 'fr'.
- */
- public function deleteCaptionRevisions($entity_type, $bundle, $field_name, $entity_id, $language) {
- $query = $this->database->delete($this->tableRevision);
- $query
- ->condition('entity_type', $entity_type, '=')
- ->condition('bundle', $bundle, '=')
- ->condition('field_name', $field_name, '=')
- ->condition('entity_id', $entity_id, '=')
- ->condition('language', $language, '=')
- ->execute();
- $this->clearCache($field_name);
- // @todo Try to return the count of the affected rows.
- }
-
- /**
- * Delete all captions revisions for a specific revision id.
- *
- * @param int $revision_id
- * The revision id.
- */
- public function deleteCaptionRevisionsByRevisionId($revision_id) {
- $query = $this->database->delete($this->tableRevision);
- $query
- ->condition('revision_id', $revision_id, '=')
- ->execute();
- }
-
- /**
- * Clears the cache for a certain field name.
- *
- * @param string $field_name
- * The field name of the image field, like 'field_image'
- * or 'field_article_image'.
- */
- public function clearCache($field_name) {
- $this->cacheTagsInvalidator->invalidateTags([
- $field_name,
- 'image_field_caption',
- ]);
- }
-
- /**
- * Constructs the cache key.
- *
- * @param string $entity_type
- * The entity type, like 'node' or 'comment'.
- * @param int $entity_id
- * The entity id.
- * @param int $revision_id
- * The revision id.
- * @param string $language
- * The language key, like 'en' or 'fr'.
- * @param string $field_name
- * The field name of the image field, like 'field_image'
- * or 'field_article_image'.
- * @param int $delta
- * The delta of the image field.
- */
- public function getCacheKey($entity_type, $entity_id, $revision_id, $language, $field_name, $delta) {
- return implode(
- ":",
- [
- 'caption',
- $entity_type,
- $entity_id,
- $revision_id,
- $language,
- $field_name,
- $delta,
- ]
- );
- }
-
- /**
- * Function to list out entity type field.
- */
- public function list($key = 'entity_type') {
- $list = &drupal_static(__FUNCTION__);
-
- if (!isset($list[$key])) {
- // Query.
- $query = $this->database->select($this->tableData, 'ifc');
- $result = $query
- ->fields('ifc', [$key])
- ->distinct()
- ->execute()
- ->fetchAll();
-
- $list[$key] = [];
- foreach ($result as $row) {
- $list[$key][] = $row->{$key};
- }
- }
-
- return $list[$key];
- }
-
-}
diff --git a/src/Plugin/Field/FieldFormatter/ImageCaptionFormatter.php b/src/Plugin/Field/FieldFormatter/ImageCaptionFormatter.php
index 7ba4c62..c761a0d 100644
--- a/src/Plugin/Field/FieldFormatter/ImageCaptionFormatter.php
+++ b/src/Plugin/Field/FieldFormatter/ImageCaptionFormatter.php
@@ -23,10 +23,12 @@ class ImageCaptionFormatter extends ImageFormatter {
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = parent::viewElements($items, $langcode);
+
foreach ($elements as $delta => $element) {
// Set a new theme callback function for the image caption formatter.
$elements[$delta]['#theme'] = 'image_caption_formatter';
}
+
return $elements;
}
--
GitLab
From 0066f4a953597385e284bfb5bdee941c4dc78b66 Mon Sep 17 00:00:00 2001
From: Dieter Holvoet <dieter.holvoet@gmail.com>
Date: Mon, 9 Sep 2024 11:28:27 +0200
Subject: [PATCH 2/4] Add back image module dependency
---
image_field_caption.info.yml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/image_field_caption.info.yml b/image_field_caption.info.yml
index e04a8e9..4861584 100644
--- a/image_field_caption.info.yml
+++ b/image_field_caption.info.yml
@@ -1,6 +1,10 @@
name: Image Field Caption
description: 'Provides a caption textarea for image fields.'
package: Other
+
+dependencies:
+ - drupal:image
+
type: module
core_version_requirement: ^9.2 || ^10
php: 7.1
--
GitLab
From 2e5f7c84145f267c1ac44c37e759d48a9aea07b7 Mon Sep 17 00:00:00 2001
From: Dieter Holvoet <dieter.holvoet@gmail.com>
Date: Mon, 9 Sep 2024 11:31:50 +0200
Subject: [PATCH 3/4] Fix cs issues
---
README.md | 3 ++-
image_field_caption.install | 19 +++++++++++++------
image_field_caption.module | 7 +++----
src/ImageCaptionItem.php | 5 ++++-
4 files changed, 22 insertions(+), 12 deletions(-)
diff --git a/README.md b/README.md
index 8bc42d9..2c46688 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,8 @@
Adds an extra text area for captions on image fields.
Similar to the alt and title text fields available with an image field,
-the caption text area can be used to enter text or html descriptions of an image.
+the caption text area can be used to enter text or html descriptions of an
+image.
For a full description of the module, visit the
[Image Field Caption](https://www.drupal.org/project/image_field_caption).
diff --git a/image_field_caption.install b/image_field_caption.install
index 63a974b..dab5ae6 100644
--- a/image_field_caption.install
+++ b/image_field_caption.install
@@ -1,5 +1,10 @@
<?php
+/**
+ * @file
+ * Install, update and uninstall functions for the Image Field Caption module.
+ */
+
use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
use Drupal\Core\Entity\Sql\SqlContentEntityStorageException;
@@ -20,10 +25,10 @@ function image_field_caption_uninstall(): void {
/**
* Helper function to add new columns to a field type.
*
- * @param $field_type
+ * @param string $field_type
* The field type id.
* @param array $columns_to_add
- * array of the column names from schema() function.
+ * Array of the column names from schema() function.
*
* @see https://gist.github.com/JPustkuchen/ce53d40303a51ca5f17ce7f48c363b9b
* @see https://www.drupal.org/project/drupal/issues/937442
@@ -60,7 +65,8 @@ function _image_field_caption_field_type_schema_column_add_helper(string $field_
$field_name = $field_storage_definition->getName();
try {
$table = $table_mapping->getFieldTableName($field_name);
- } catch (SqlContentEntityStorageException $e) {
+ }
+ catch (SqlContentEntityStorageException $e) {
// Custom storage? Broken site? No matter what, if there is no table
// or column, there's little we can do.
continue;
@@ -123,10 +129,10 @@ function _image_field_caption_field_type_schema_column_add_helper(string $field_
/**
* Helper function to remove columns from a field type.
*
- * @param $field_type
+ * @param string $field_type
* The field type id.
* @param array $columns_to_remove
- * array of the column names from schema() function.
+ * Array of the column names from schema() function.
*
* @see https://gist.github.com/JPustkuchen/ce53d40303a51ca5f17ce7f48c363b9b
* @see https://www.drupal.org/project/drupal/issues/937442
@@ -163,7 +169,8 @@ function _image_field_caption_field_type_schema_column_remove_helper(string $fie
$field_name = $field_storage_definition->getName();
try {
$table = $table_mapping->getFieldTableName($field_name);
- } catch (SqlContentEntityStorageException $e) {
+ }
+ catch (SqlContentEntityStorageException $e) {
// Custom storage? Broken site? No matter what, if there is no table
// or column, there's little we can do.
continue;
diff --git a/image_field_caption.module b/image_field_caption.module
index 63f8999..8bae0a6 100644
--- a/image_field_caption.module
+++ b/image_field_caption.module
@@ -14,10 +14,10 @@ use Drupal\image_field_caption\ImageCaptionItem;
* Implements hook_field_info_alter().
*/
function image_field_caption_field_info_alter(array &$info): void {
- // Override the image field type class
+ // Override the image field type class.
$info['image']['class'] = ImageCaptionItem::class;
- // Enable translation for the caption property
+ // Enable translation for the caption property.
$info['image']['column_groups']['caption'] = [
'label' => t('Caption'),
'translatable' => TRUE,
@@ -48,8 +48,7 @@ function _image_field_caption_widget_process(array $element, FormStateInterface
$item = $element['#value'];
$item['fids'] = $element['fids']['#value'];
- // TODO: Make #allowed_formats configurable.
-
+ // @todo Make #allowed_formats configurable.
$element['caption'] = [
'#title' => t('Caption'),
'#type' => 'text_format',
diff --git a/src/ImageCaptionItem.php b/src/ImageCaptionItem.php
index 02c0ada..8fb5d92 100644
--- a/src/ImageCaptionItem.php
+++ b/src/ImageCaptionItem.php
@@ -35,6 +35,9 @@ class ImageCaptionItem extends ImageItem {
return $settings;
}
+ /**
+ * {@inheritdoc}
+ */
public static function schema(FieldStorageDefinitionInterface $field_definition) {
$schema = parent::schema($field_definition);
@@ -65,7 +68,7 @@ class ImageCaptionItem extends ImageItem {
->setDescription(new TranslatableMarkup("Short description of the image displayed underneath the image."));
$properties['caption_format'] = DataDefinition::create('filter_format')
- ->setLabel(new TranslatableMarkup('Text format of the caption'));
+ ->setLabel(new TranslatableMarkup('Text format of the caption'));
return $properties;
}
--
GitLab
From fffc01d559c45e4b43729619d5cef93916d19417 Mon Sep 17 00:00:00 2001
From: Dieter Holvoet <dieter.holvoet@gmail.com>
Date: Mon, 9 Sep 2024 11:45:46 +0200
Subject: [PATCH 4/4] Fix issue reported by phpstan
---
src/ImageCaptionItem.php | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/ImageCaptionItem.php b/src/ImageCaptionItem.php
index 8fb5d92..3ef0772 100644
--- a/src/ImageCaptionItem.php
+++ b/src/ImageCaptionItem.php
@@ -79,6 +79,7 @@ class ImageCaptionItem extends ImageItem {
public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
$element = parent::fieldSettingsForm($form, $form_state);
$settings = $this->getSettings();
+ $defaultSettings = self::defaultFieldSettings();
// Add caption option.
$element['caption_field'] = [
@@ -93,7 +94,7 @@ class ImageCaptionItem extends ImageItem {
$element['caption_field_required'] = [
'#type' => 'checkbox',
'#title' => t('<em>Caption</em> field required'),
- '#default_value' => (!empty($settings['caption_field_required'])) ? $settings['caption_field_required'] : $settings_default['caption_field_required'],
+ '#default_value' => (!empty($settings['caption_field_required'])) ? $settings['caption_field_required'] : $defaultSettings['caption_field_required'],
'#description' => '',
'#weight' => 14,
'#states' => [
--
GitLab