diff --git a/css/metadata_profile.css b/css/metadata_profile.css index 5c453a8..9f8670e 100644 --- a/css/metadata_profile.css +++ b/css/metadata_profile.css @@ -15,3 +15,6 @@ .field-info .edit-link { display: block; } +.scrolling-table-container { + overflow-x: auto; +} diff --git a/src/Controller/MetadataProfileController.php b/src/Controller/MetadataProfileController.php index 81e6a16..cac8808 100644 --- a/src/Controller/MetadataProfileController.php +++ b/src/Controller/MetadataProfileController.php @@ -8,9 +8,11 @@ use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Field\FieldTypePluginManagerInterface; +use Drupal\Core\Link; use Drupal\Core\Messenger\MessengerTrait; use Drupal\Core\Config\Config; use Drupal\Core\Url; +use Drupal\field_permissions\Plugin\FieldPermissionType\Base; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Core\Entity\EntityFieldManagerInterface; @@ -54,17 +56,22 @@ class MetadataProfileController extends ControllerBase { } $build = $this->format_bundle($node_type); - $metadata_profile = $this->getMetadataProfile($node_type); + $metadata_profile = $this->getMetadataProfile($content_type); + $build['summary_table'] = [ + '#type' => 'container', + '#attributes'=> ['class' => ['scrolling-table-container']], + 'data' => $this->buildSummaryTable($metadata_profile), + ]; - $build['children'] = [ + $build['fields'] = [ '#type' => 'container', '#weight' => '9', ]; // Get field information. $field_definitions = $this->entityFieldManager->getFieldDefinitions('node', $content_type); foreach ($field_definitions as $field_name => $field_definition) { - $build['children'][$field_name] = $this->format_field($field_name, $field_definition); + $build['fields'][$field_name] = $this->display_field($field_name, $field_definition, $metadata_profile[$field_name]); } return $build; @@ -98,18 +105,17 @@ class MetadataProfileController extends ControllerBase { } public function getMetadataProfile($bundle) { - // $metadata_profile is an array of arrays. Its keys are the "long" machine names of the fields - // such as node.islandora_object.field_abstract. The values are arrays with the following keys: + // $metadata_profile is an array of arrays. Its keys are the "short" machine names of the fields + // such as field_abstract. The values are arrays with the following keys: // * 'label' - text. the bundle's human-readable label. // * 'machine_name' - text. The short machine name such as 'field_abstract'. // * 'id' - text. The long machine name such as 'node.islandora_object.field_abstract'. (same as this array's key) // * 'edit_url' - Url object. The link to the edit page for that field (or to the base field override page). // * 'type' - text. The human readable type of the field. (e.g. "Entity Reference") // * 'type_machine_name' - text. The machine name of the type (e.g. 'entity_reference') - // * 'required' - True|False. Whether the field is required. - // * 'cardinality' - int. -1 for no limit, positive integer for a limited number. - // * 'auto_create' - True|False (Optional). Whether a relationship field allows new entity creation on the fly. - // * 'auto_create_bundle' - string. The bundle new entities are created into. + // * 'required' - 'Required'|'Not required'. Whether the field is required. + // * 'cardinality' - 'Not repeatable'|'Repeatable'|'Repeatable, limit N' + // * 'auto_create' - 'Create new'|'Create new #bundle'|'Do not create new'|NULL Whether a relationship field allows new entity creation on the fly. // * 'target_bundles' - array. List of bundle names that are the target of this field. // * 'search_api' - associative array. Has the following keys: // * 'in_search_api' - True|False. True if some field matches. @@ -133,18 +139,66 @@ class MetadataProfileController extends ControllerBase { $metadata_profile = []; $field_definitions = $this->entityFieldManager->getFieldDefinitions('node', $bundle); foreach ($field_definitions as $field_name => $field_definition) { - $metadata_profile[$field_name] = $this->format_field($field_name, $field_definition); + $metadata_profile[$field_name] = [ + 'label' => $field_definition->getLabel(), + 'machine_name' => $field_name, + 'id' => method_exists($field_definition, 'id') ? $field_definition->id() : $field_definition->getUniqueIdentifier(), + 'edit_url' => $this->getFieldEditUrl($field_definition), + 'details_link' => $this->getDetailsFragmentLink($field_name, $field_definition), + 'type' => $this->formatType($field_definition), + 'type_machine_name' => $field_definition->getType(), + 'required' => $this->formatRequired($field_definition), + 'repeatable' => $this->formatCardinality($field_definition), + 'auto_create' => $this->formatCreateNew($field_definition), + 'target_bundles' => $this->formatTargetBundles($field_definition), + ]; + // Add solr } + return $metadata_profile; } - protected function format_field(string $field_name, FieldDefinitionInterface $field_definition) { + + protected function buildSummaryTable($metadata_profile) { + $rows = []; + foreach ($metadata_profile as $field_name => $field_profile) { + if (str_starts_with( $field_name, 'field_') or $field_name == 'title') { + $rows[] = [ + $field_profile['details_link'], + $field_profile['machine_name'], + $field_profile['type'], + $field_profile['required'], + $field_profile['repeatable'], + $field_profile['auto_create'], + $this->formatListForTable($field_profile['target_bundles']), + ]; + } + } + return [ + '#type' => 'table', + '#header' => [ + $this->t('Field'), + $this->t('Machine name'), + $this->t('Type'), + $this->t('Required'), + $this->t('Repeatable'), + $this->t('Create new'), + $this->t('Target bundles') + // TODO: add more columns + ], + '#rows' => $rows, + ]; + + } + + protected function display_field(string $field_name, FieldDefinitionInterface $field_definition, array $field_profile) { $render_array = []; + if (str_starts_with($field_name, 'field_') or $field_name == 'title') { $render_array = [ '#type' => 'container', '#attributes' => ['class' => ['field-info']], - '#weight' => $this->formatWeight($field_definition), + '#weight' => $this->formatWeight($field_definition), // This doesn't work. 'title' => [ - '#plain_text' => $field_definition->getLabel(), + '#plain_text' => $field_profile['label'], '#prefix' => '

', '#suffix' => '

', ], @@ -153,11 +207,11 @@ class MetadataProfileController extends ControllerBase { '#prefix' => '(', '#suffix' => ') ', ], - 'edit_link' => $this->formatFieldEditLink($field_definition), + 'edit_link' => $field_profile['edit_url'] ? $this->formatFieldEditLink($field_profile['edit_url']) : [], 'table' => [ '#type' => 'table', '#header' => ['Field Configuration',''], - '#rows' => $this->getFieldTableRows($field_definition), + '#rows' => $this->getFieldTableRows($field_profile), '#attributes' => ['class' => ['field-info-table']], ], 'description' => [ @@ -165,11 +219,6 @@ class MetadataProfileController extends ControllerBase { '#markup' => $field_definition->getDescription() ?: $this->t('[No description]'), '#prefix' => 'Description: ', ], - 'target_bundles' => [ - '#title' => $this->t('Target Bundles'), - '#type' => 'container', - 'bundles' => $this->formatTargetBundles($field_definition), - ], 'search_api' => $this->formatSearchApi($field_definition), ]; @@ -178,26 +227,36 @@ class MetadataProfileController extends ControllerBase { return $render_array; } - protected function formatFieldEditLink(FieldDefinitionInterface $field_definition) { + protected function getFieldEditUrl(FieldDefinitionInterface $field_definition) { + $redirect_url = Url::fromRoute('', ['fragment' => $field_definition->getName()]); if ($field_definition->getFieldStorageDefinition() instanceof BaseFieldDefinition) { if ($this->moduleHandler()->moduleExists('base_field_override_ui')) { - $edit_url = Url::fromRoute('entity.base_field_override.node_base_field_override_edit_form', [ - 'node_type' => $field_definition->getTargetBundle(), - 'base_field_override' => $field_definition->id(), - 'destination' => Url::fromRoute('metadata_profile.node_profile', ['content_type' => $field_definition->getTargetBundle()], ['fragment' => $field_definition->getName()])->toString(), - ]); + if (method_exists($field_definition, 'id')) { + $edit_url = Url::fromRoute('entity.base_field_override.node_base_field_override_edit_form', [ + 'node_type' => $field_definition->getTargetBundle(), + 'base_field_override' => $field_definition->id(), + 'destination' => $redirect_url->toString() + ]); + } + else { + return NULL; + } + } else { - return []; + return NULL; } } else { $edit_url = Url::fromRoute('entity.field_config.node_field_edit_form', [ 'node_type' => $field_definition->getTargetBundle(), 'field_config' => $field_definition->id(), - 'destination' => Url::fromRoute('metadata_profile.node_profile', ['content_type' => $field_definition->getTargetBundle()], ['fragment' => $field_definition->getName()])->toString(), + 'destination' => $redirect_url->toString(), ]); } + return $edit_url; + } + protected function formatFieldEditLink(Url $edit_url) { return [ '#type' => 'link', '#url' => $edit_url, @@ -206,16 +265,18 @@ class MetadataProfileController extends ControllerBase { ]; } - protected function getFieldTableRows(FieldDefinitionInterface $field_definition) { + protected function getFieldTableRows(array $field_profile) { $rows = [ - [$this->t('Type:'), $this->formatType($field_definition)], - [$this->t('Required:'), $this->formatRequired($field_definition)], - [$this->t('Repeatable:'), $this->formatCardinality($field_definition)], + [$this->t('Type:'), $field_profile['type']], + [$this->t('Required:'), $field_profile['required']], + [$this->t('Repeatable:'), $field_profile['repeatable']], ]; - // TODO: use a class inheritance method to get entity reference and typed relation in one shot. - if (in_array($field_definition->getType(), ['entity_reference', 'typed_relation'])) { - $rows[] = [$this->t('Create new:'), $this->formatCreateNew($field_definition)]; + if ($field_profile['auto_create']) { + $rows[] = [$this->t('Create new:'), $field_profile['auto_create']]; } + if ($field_profile['target_bundles']) { + $rows[] = [$this->t('Target bundles:'), $this->formatListForTable($field_profile['target_bundles'])]; + } return $rows; } @@ -224,7 +285,7 @@ class MetadataProfileController extends ControllerBase { $type = $field_definition->getType(); $type_label = $this->fieldTypePluginManager->getDefinition($type)['label']; if (in_array($type, ['entity_reference', 'typed_relation'])) { - $type_label = $type_label . ' (' . $field_definition->getSetting('target_type') . ')'; + $type_label = $type_label . ' > ' . $field_definition->getSetting('target_type'); } return $type_label; } @@ -257,14 +318,20 @@ class MetadataProfileController extends ControllerBase { } protected function formatCreateNew(FieldDefinitionInterface $field_definition) { - $create_new_bundle = $field_definition->getSetting('handler_settings')['auto_create_bundle']; - $create_new = $field_definition->getSetting('handler_settings')['auto_create_bundle']; - if ($create_new) { - return $create_new_bundle ? 'Create new (' . $create_new_bundle . ')' : 'Create new'; + if (in_array($field_definition->getType(), ['entity_reference', 'typed_relation'])) { + $create_new_bundle = $field_definition->getSetting('handler_settings')['auto_create_bundle']; + $create_new = $field_definition->getSetting('handler_settings')['auto_create_bundle']; + if ($create_new) { + return $create_new_bundle ? 'Create new (' . $create_new_bundle . ')' : 'Create new'; + } + else { + return $this->t('Do not create new'); + } } else { - return $this->t('Do not create new'); + return NULL; } + } protected function formatTargetBundles(FieldDefinitionInterface $field_definition) { @@ -281,11 +348,13 @@ class MetadataProfileController extends ControllerBase { if ($handler == 'default:node') { $bundle_config = $this->entityTypeManager()->getStorage('node_type')->load($bundle); } - // TODO: ADD NODE ETC + // TODO: ADD MEDIA, PARAGRAPHS ETC if ($bundle_config) { $target_bundles[$index] = $bundle_config->get('name') . ' (' . $bundle . ')'; } } + return $target_bundles; + return [ '#theme' => 'item_list', '#title' => $this->t('Target bundles:'), @@ -294,6 +363,13 @@ class MetadataProfileController extends ControllerBase { ]; } + protected function formatListForTable(array $list) { + return ['data' => [ + '#theme' => 'item_list', + '#items' => array_values($list), + '#type' => 'ul', + ]]; + } protected function formatSearchApi($field_definition) { if ($this->moduleHandler()->moduleExists('search_api')) { $build = [ @@ -428,4 +504,10 @@ class MetadataProfileController extends ControllerBase { return $build; } + + private function getDetailsFragmentLink(string $field_name, FieldDefinitionInterface $field_definition) + { + $url = Url::fromRoute('', [], ['fragment' => $field_name]); + return Link::fromTextAndUrl($field_definition->getLabel(), $url); + } }