diff --git a/src/Plugin/Field/FieldFormatter/TablefieldFormatter.php b/src/Plugin/Field/FieldFormatter/TablefieldFormatter.php index bcfa2e5..6635179 100644 --- a/src/Plugin/Field/FieldFormatter/TablefieldFormatter.php +++ b/src/Plugin/Field/FieldFormatter/TablefieldFormatter.php @@ -40,6 +40,8 @@ class TablefieldFormatter extends FormatterBase { if (!empty($table->value)) { // Tablefield::rationalizeTable($table->value);. $tabledata = $table->value; + $caption = $tabledata["caption"]; + unset($tabledata["caption"]); // Run the table through input filters. foreach ($tabledata as $row_key => $row) { @@ -97,6 +99,7 @@ class TablefieldFormatter extends FormatterBase { $render_array['tablefield'] = [ '#type' => 'table', '#header' => $header, + '#caption' => $caption, '#rows' => $tabledata, '#attributes' => [ 'id' => 'tablefield-' . $entity_type . '-' . $entity_id . '-' . $field_name . '-' . $delta, diff --git a/src/Plugin/Field/FieldType/TablefieldItem.php b/src/Plugin/Field/FieldType/TablefieldItem.php index ac37e59..8f236c2 100644 --- a/src/Plugin/Field/FieldType/TablefieldItem.php +++ b/src/Plugin/Field/FieldType/TablefieldItem.php @@ -39,6 +39,11 @@ class TablefieldItem extends FieldItemBase { 'length' => 255, 'default value' => '', ], + 'caption' => [ + 'type' => 'varchar', + 'length' => 255, + 'default value' => '', + ], ], ]; } @@ -138,6 +143,9 @@ class TablefieldItem extends FieldItemBase { $properties['format'] = DataDefinition::create('filter_format') ->setLabel(t('Text format')); + $properties['caption'] = DataDefinition::create('string') + ->setLabel(t('Table Caption')); + return $properties; } @@ -164,6 +172,7 @@ class TablefieldItem extends FieldItemBase { } // In case this is being loaded from storage recalculate rows/cols. elseif (empty($values['rebuild'])) { + unset($values['value']['caption']); $values['rebuild']['rows'] = isset($values['value']) ? count($values['value']) : 0; $values['rebuild']['cols'] = isset($values['value'][0]) ? count($values['value'][0]) : 0; } @@ -174,6 +183,8 @@ class TablefieldItem extends FieldItemBase { ksort($values['value']); } + $values['value']['caption'] = $values['caption']; + parent::setValue($values, $notify); } diff --git a/src/Plugin/Field/FieldWidget/TablefieldWidget.php b/src/Plugin/Field/FieldWidget/TablefieldWidget.php index bd8201b..d99461b 100644 --- a/src/Plugin/Field/FieldWidget/TablefieldWidget.php +++ b/src/Plugin/Field/FieldWidget/TablefieldWidget.php @@ -90,6 +90,14 @@ class TablefieldWidget extends WidgetBase { $cols = isset($default_value->rebuild['cols']) ? $default_value->rebuild['cols'] : \Drupal::config('tablefield.settings')->get('cols'); + $element['caption'] = [ + '#type' => 'textfield', + '#title' => $this->t('Table Caption'), + '#default_value' => (!empty($default_value->caption) ? $default_value->caption : NULL), + '#size' => 60, + '#description' => $this->t('Text inserted into tag'), + ]; + $element = [ '#type' => 'tablefield', '#input_type' => $this->getSetting('input_type'), diff --git a/tablefield.install b/tablefield.install index db49ef4..7261168 100644 --- a/tablefield.install +++ b/tablefield.install @@ -61,3 +61,118 @@ function tablefield_update_7000() { function tablefield_update_7001() { tablefield_repair_schema(); } + +/** + * Helper function for HOOK_Update to update the field schema columns. + * + * Copied from + * https://gist.github.com/JPustkuchen/ce53d40303a51ca5f17ce7f48c363b9b + * + * @param $field_type + * The field type id. + * @param array $columns_to_add + * Array of the column names from schema() function. + */ +function _field_type_schema_column_add_helper($field_type, array $columns_to_add = array()) { + $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); + + $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 address fields. + /** @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 (\Drupal\Core\Entity\Sql\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 ($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 ($field_schema_data) { + $recipient_column = $table_mapping->getFieldColumnName($field_storage_definition, 'recipient'); + unset($field_schema_data[$table]['fields'][$recipient_column]); + if ($revision_table) { + unset($field_schema_data[$revision_table]['fields'][$recipient_column]); + } + $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); + } + } + } + } +} + +/** + * Add columns for caption field to the database. + */ +function tablefield_update_8001() { + $spec = [ + 'type' => 'varchar', + 'length' => 255, + 'default value' => '', + ]; + _field_type_schema_column_add_helper('tablefield', ['caption']); +}