Browse Source

added usage count

main
astanley 3 days ago
parent
commit
e7d03ed94c
  1. 7
      css/metadata_profile.css
  2. 19
      metadata_profile.module
  3. 531
      src/Controller/MetadataProfileController.php

7
css/metadata_profile.css

@ -18,3 +18,10 @@
.scrolling-table-container {
overflow-x: auto;
}
.yes-icon {
color: #2e7d32;
}
.no-icon {
color: #c62828;
}

19
metadata_profile.module

@ -1,5 +1,6 @@
<?php
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Url;
/**
* Implements hook_entity_type_alter().
*
@ -38,3 +39,19 @@ function metadata_profile_file_download($uri){
}
return NULL;
}
/**
* Implements hook_entity_operation_alter().
*/
function metadata_profile_entity_operation_alter(array &$operations, EntityInterface $entity) {
if ($entity->getEntityTypeId() === 'node_type') {
$operations['metadata_profile'] = [
'title' => t('Metadata profile'),
'weight' => 50,
'url' => Url::fromRoute('entity.node_type.metadata_profile', [
'node_type' => $entity->id(),
]),
];
}
}

531
src/Controller/MetadataProfileController.php

@ -5,7 +5,6 @@ namespace Drupal\metadata_profile\Controller;
use Drupal\Core\Config\Config;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Field\FieldDefinitionInterface;
@ -15,13 +14,14 @@ use Drupal\Core\Link;
use Drupal\Core\Messenger\MessengerTrait;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
use Drupal\node\NodeForm;
use Drupal\system\FileDownloadController;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeManagerInterface;
class MetadataProfileController extends ControllerBase {
use MessengerTrait;
/**
@ -79,6 +79,7 @@ class MetadataProfileController extends ControllerBase {
* @var \Drupal\Core\File\FileSystemInterface
*/
protected $fileSystem;
/**
* The file download controller.
*
@ -86,13 +87,30 @@ class MetadataProfileController extends ControllerBase {
*/
protected $fileDownloadController;
/**
* The Database connection.
*
* @var \Drupal\Core\Database\Connection
*/
protected Connection $database;
public function __construct(EntityFieldManagerInterface $entity_field_manager,
FieldTypePluginManagerInterface $field_type_plugin_manager,
ConfigFactoryInterface $config_factory,
RouteMatchInterface $route_match,
FileSystemInterface $file_system,
FileDownloadController $file_download_controller) {
/**
* The Entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected EntityTypeManagerInterface $entityTypeManagerService;
public function __construct(
EntityFieldManagerInterface $entity_field_manager,
FieldTypePluginManagerInterface $field_type_plugin_manager,
ConfigFactoryInterface $config_factory,
RouteMatchInterface $route_match,
FileSystemInterface $file_system,
FileDownloadController $file_download_controller,
Connection $database,
EntityTypeManagerInterface $entity_type_manager // ✅ ADD THIS
) {
$this->entityFieldManager = $entity_field_manager;
$this->fieldTypePluginManager = $field_type_plugin_manager;
$this->configFactory = $config_factory;
@ -105,6 +123,8 @@ class MetadataProfileController extends ControllerBase {
$this->entityTypeBundleOf = $entity_type->getEntityType()->getBundleOf();
$this->fileSystem = $file_system;
$this->fileDownloadController = $file_download_controller;
$this->database = $database;
$this->entityTypeManagerService = $entity_type_manager;
}
public static function create(ContainerInterface $container) {
@ -114,7 +134,9 @@ class MetadataProfileController extends ControllerBase {
$container->get('config.factory'),
$container->get('current_route_match'),
$container->get('file_system'),
FileDownloadController::create($container)
FileDownloadController::create($container),
$container->get('database'),
$container->get('entity_type.manager'),
);
}
@ -124,11 +146,10 @@ class MetadataProfileController extends ControllerBase {
* @return array
*/
public function profile() {
// Get core content type information.
$bundle_config = $this->config(str_replace('_', '.', $this->entityType) . '.' . $this->entityBundle);
$bundle_config = $this->config(str_replace('_', '.', $this->entityType) . '.' . $this->entityBundle);
if (!$bundle_config) {
return ['#markup'=> 'Not a valid content type.'];
return ['#markup' => 'Not a valid content type.'];
}
$build = $this->formatBundle($bundle_config);
@ -136,7 +157,7 @@ class MetadataProfileController extends ControllerBase {
$build['summary_table'] = [
'#type' => 'container',
'#attributes'=> ['class' => ['scrolling-table-container']],
'#attributes' => ['class' => ['scrolling-table-container']],
'data' => $this->buildSummaryTable($metadata_profile),
];
@ -175,7 +196,7 @@ class MetadataProfileController extends ControllerBase {
'#type' => 'container',
'#attached' => ['library' => ['metadata_profile/metadata_profile']],
'title' => [
'title' => [
'#plain_text' => $label,
'#prefix' => '<h1>',
'#suffix' => '</h1>',
@ -194,40 +215,73 @@ class MetadataProfileController extends ControllerBase {
return $build;
}
/**
* Builds a metadata profile for the current entity bundle.
*
* The returned array is keyed by field machine name and contains
* structured metadata describing each field.
*
* Each field profile contains:
* - label: string
* - machine_name: string
* - id: string
* - edit_url: \Drupal\Core\Url|null
* - details_link: \Drupal\Core\Link
* - description: string
* - type: string (human readable)
* - type_machine_name: string
* - required: render array
* - repeatable: render array|string
* - auto_create: render array|null
* - target_bundles: array
* - base_field: bool
* - usage_count: int
* - search_api: array
*
* @return array
* Metadata profile keyed by field machine name.
*/
public function getMetadataProfile() {
// $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).
// * 'description' - the help text for the field.
// * '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' - '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.
// * 'has_facet' - True|False. True if some field has a facet.
// * 'fields' - array. The 'fields' array is keyed by the machine names of the search api fields,
// which are arrays with the following fields:
// * 'search_api_field_name' - the machine name of the search api field.
// * 'search_api_field_label' - the human readable label of the search api field.
// * 'property_path' - the method for getting the values.
// * 'type' = the search api field type.
// * 'index_name' - the name of the Search API index (in case there are more than one)
// * 'fields_included' - for aggregate and EDTF processor fields, which fields are in that field.
// * 'facets' - associative array. has the following keys
// * 'has_facet' - True|False. True if there is a facet, even if not showing up (can use with url alias)
// * 'facets' - array. the 'facets' array is keyed by the machine name of the facet. each facet is an
// array with keys:
// * 'facet_name'
// * 'facet_machine_name'
// * 'facet_source'
// * 'url_alias'
// * 'block_visible' -- not yet implemented.
/**
* Metadata profile structure.
*
* $metadata_profile is an associative array keyed by field machine names
* (e.g. "field_abstract"). Each value is an array with the following keys:
*
* - label: (string) Human-readable field label.
* - machine_name: (string) Short machine name (e.g. "field_abstract").
* - id: (string) Full machine name
* (e.g. "node.islandora_object.field_abstract").
* - edit_url: (\Drupal\Core\Url) Link to edit the field configuration.
* - description: (string) Field help text.
* - type: (string) Human-readable field type (e.g. "Entity Reference").
* - type_machine_name: (string) Field type machine name
* (e.g. "entity_reference").
* - required: (string) "Required" or "Not required".
* - cardinality: (string) "Not repeatable", "Repeatable",
* or "Repeatable, limit N".
* - auto_create: (string|null) Whether referenced entities can be created:
* "Create new", "Create new (bundle)", or "Do not create new".
* - target_bundles: (string[]) List of allowed target bundles.
* - search_api: (array) Search API metadata:
* - in_search_api: (bool) TRUE if indexed.
* - has_facet: (bool) TRUE if any facet exists.
* - fields: (array) Indexed by Search API field machine name:
* - search_api_field_name: (string)
* - search_api_field_label: (string)
* - property_path: (string)
* - type: (string)
* - index_name: (string)
* - fields_included: (array) Included fields (aggregated/EDTF).
* - facets: (array) Facet definitions:
* - has_facet: (bool)
* - facets: (array) Each facet contains:
* - facet_name: (string)
* - facet_machine_name: (string)
* - facet_source: (string)
* - url_alias: (string)
* - block_visible: (string) Not yet implemented.
*/
$metadata_profile = [];
$field_definitions = $this->entityFieldManager->getFieldDefinitions($this->entityTypeBundleOf, $this->entityBundle);
@ -246,13 +300,27 @@ class MetadataProfileController extends ControllerBase {
'auto_create' => $this->formatCreateNew($field_definition),
'target_bundles' => $this->formatTargetBundles($field_definition),
'base_field' => $field_definition->getFieldStorageDefinition() instanceof BaseFieldDefinition,
'usage_count' => $this->getUsageCount($field_name),
];
$metadata_profile[$field_name]['search_api'] = $this->getSearchApi($field_definition);
$metadata_profile[$field_name]['search_api'] = $this->getSearchApi($field_definition);
}
$metadata_profile = $this->addWeights($metadata_profile);
return $metadata_profile;
}
/**
* Builds Search API metadata for a field definition.
*
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* The field definition.
*
* @return array|false
* An associative array containing:
* - in_search_api: bool
* - has_facet: bool
* - fields: array
* Or FALSE if Search API module is not enabled.
*/
private function getSearchApi($field_definition) {
if (!$this->moduleHandler()->moduleExists('search_api')) {
return FALSE;
@ -274,7 +342,7 @@ class MetadataProfileController extends ControllerBase {
// Loop over fields.
foreach ($index_config->get('field_settings') as $search_api_field_name => $search_api_field_setting) {
$indexed_field_name = $index_config->getName() . '.' .$search_api_field_name;
$indexed_field_name = $index_config->getName() . '.' . $search_api_field_name;
// Get Aggregated Fields.
if ($search_api_field_setting['property_path'] == 'aggregated_field') {
if (in_array('entity:node/' . $field_definition->getName(), $search_api_field_setting['configuration']['fields'])) {
@ -282,19 +350,23 @@ class MetadataProfileController extends ControllerBase {
}
}
// Get EDTF fields.
else if ($field_definition->getType() == 'edtf') {
// Get EDTF year.
if ($search_api_field_setting['property_path'] == 'edtf_year') {
$edtf_year_fields = $index_config->get('processor_settings')['edtf_year_only']['fields'] ?: [];
if (in_array(str_replace('.', '|', $field_definition->id()), $edtf_year_fields)) {
$search_api['fields'][$indexed_field_name] = $this->getSearchApiField($search_api_field_name, $search_api_field_setting, $index_config);
else {
if ($field_definition->getType() == 'edtf') {
// Get EDTF year.
if ($search_api_field_setting['property_path'] == 'edtf_year') {
$edtf_year_fields = $index_config->get('processor_settings')['edtf_year_only']['fields'] ?: [];
if (in_array(str_replace('.', '|', $field_definition->id()), $edtf_year_fields)) {
$search_api['fields'][$indexed_field_name] = $this->getSearchApiField($search_api_field_name, $search_api_field_setting, $index_config);
}
}
}
// Get EDTF Date
else if ($search_api_field_setting['property_path'] == 'edtf_dates') {
$edtf_date_fields = $index_config->get('processor_settings')['edtf_date_processor']['fields'] ?: [];
if (in_array(str_replace('.', '|', $field_definition->id()), $edtf_date_fields)) {
$search_api['fields'][$indexed_field_name] = $this->getSearchApiField($search_api_field_name, $search_api_field_setting, $index_config);
// Get EDTF Date
else {
if ($search_api_field_setting['property_path'] == 'edtf_dates') {
$edtf_date_fields = $index_config->get('processor_settings')['edtf_date_processor']['fields'] ?: [];
if (in_array(str_replace('.', '|', $field_definition->id()), $edtf_date_fields)) {
$search_api['fields'][$indexed_field_name] = $this->getSearchApiField($search_api_field_name, $search_api_field_setting, $index_config);
}
}
}
}
}
@ -310,22 +382,29 @@ class MetadataProfileController extends ControllerBase {
if (isset($search_api_field_setting['datasource_id']) and $search_api_field_setting['property_path'] == $field_definition->getName()) {
$search_api['fields'][$indexed_field_name] = $this->getSearchApiField($search_api_field_name, $search_api_field_setting, $index_config);
}
}
if (count($search_api['fields']) > 0) {
$search_api['in_search_api'] = TRUE;
}
if (in_array(TRUE, array_column($search_api['fields'], 'has_facet'), true)) {
if (in_array(TRUE, array_column($search_api['fields'], 'has_facet'), TRUE)) {
$search_api['has_facet'] = TRUE;
}
else {
$search_api['has_facet'] = FALSE;
}
}
return $search_api;
}
/**
* Builds a render array for the summary table.
*
* @param array $metadata_profile
* Metadata profile array.
*
* @return array
* Render array for a Drupal table.
*/
protected function buildSummaryTable($metadata_profile) {
$rows = $this->getRows($metadata_profile, TRUE);
return [
@ -333,13 +412,43 @@ class MetadataProfileController extends ControllerBase {
'#header' => $this->getHeaders(),
'#rows' => $rows,
];
}
protected function getRows($metadata_profile, $display=NULL) {
/**
* Builds table rows from a metadata profile array.
*
* Each row is a numerically indexed array representing a table row:
* 0 => Field label or link
* 1 => Machine name
* 2 => Description
* 3 => Field type (human readable)
* 4 => Required indicator (render array)
* 5 => Repeatable indicator (render array)
* 6 => Auto-create indicator (render array|null)
* 7 => In Search API (render array)
* 8 => Has Facet (render array)
* 9 => Target bundles (array|string|render array)
* 10 => Weight (int|float)
* 11 => Usage count (int)
*
* Rows are sorted descending by usage count (index 11).
*
* @param array $metadata_profile
* Structured metadata profile keyed by field machine name.
* @param bool|null $display
* Whether to return renderable values (TRUE) or raw values (FALSE/NULL).
*
* @return array
* A numerically indexed array of row arrays.
*/
protected function getRows($metadata_profile, $display = NULL) {
$rows = [];
foreach ($metadata_profile as $field_name => $field_profile) {
if (str_starts_with( $field_name, 'field_') or in_array($field_name, ['title', 'name'])) {
if (str_starts_with($field_name, 'field_') or in_array($field_name, [
'title',
'name',
])) {
$bundles = $field_profile['target_bundles'] ?? [];
$rows[] = [
$display ? $field_profile['details_link'] : $field_profile['label'],
$field_profile['machine_name'],
@ -348,13 +457,20 @@ class MetadataProfileController extends ControllerBase {
$field_profile['required'],
$field_profile['repeatable'],
$field_profile['auto_create'],
$display ? $this->formatListForTable($field_profile['target_bundles']) : $field_profile['target_bundles'],
$field_profile['search_api']['in_search_api'] ? 'Indexed' : '',
$field_profile['search_api']['has_facet'] ? 'Facet' : '',
$this->yesNoIcon($field_profile['search_api']['in_search_api']),
$this->YesNoIcon($field_profile['search_api']['has_facet']),
$display
? $this->formatListForTable($bundles)
: $bundles,
$field_profile['weight'],
];
$field_profile['usage_count'],
];
}
}
usort($rows, function($a, $b) {
return $b[11] <=> $a[11];
});
return $rows;
}
@ -367,10 +483,11 @@ class MetadataProfileController extends ControllerBase {
$this->t('Required'),
$this->t('Repeatable'),
$this->t('Create new'),
$this->t('Target bundles'),
$this->t('In Search API'),
$this->t('Has Facet'),
$this->t('Target bundles'),
$this->t('Weight'),
$this->t("Usage count"),
// TODO: add more columns
];
@ -379,7 +496,10 @@ class MetadataProfileController extends ControllerBase {
protected function buildField(array $field_profile) {
$render_array = [];
$field_name = $field_profile['machine_name'];
if (str_starts_with($field_name, 'field_') or in_array($field_name, ['title', 'name'])) {
if (str_starts_with($field_name, 'field_') or in_array($field_name, [
'title',
'name',
])) {
$render_array = [
'#type' => 'container',
'#attributes' => ['class' => ['field-info']],
@ -395,10 +515,20 @@ class MetadataProfileController extends ControllerBase {
'#prefix' => '(',
'#suffix' => ') ',
],
'usage_count' => [
'#markup' => $this->formatPlural(
$field_profile['usage_count'],
"Used <strong>1</strong> time.",
"Used <strong>@count</strong> times."
),
'#prefix' => '</ br>',
],
'edit_link' => $field_profile['edit_url'] ? $this->formatFieldEditLink($field_profile['edit_url']) : [],
'table' => [
'#type' => 'table',
'#header' => ['Field Configuration',''],
'#header' => ['Field Configuration', ''],
'#rows' => $this->getFieldTableRows($field_profile),
'#attributes' => ['class' => ['field-info-table']],
'#prefix' => '<h3>' . $this->t('Field Information') . '</h3>',
@ -411,9 +541,6 @@ class MetadataProfileController extends ControllerBase {
'search_api' => $this->formatSearchApi($field_profile),
'facets' => $this->formatFacets($field_profile),
];
}
return $render_array;
@ -427,7 +554,7 @@ class MetadataProfileController extends ControllerBase {
$edit_url = Url::fromRoute('entity.base_field_override.' . $this->entityTypeBundleOf . '_base_field_override_edit_form', [
$this->entityType => $field_definition->getTargetBundle(),
'base_field_override' => $field_definition->id(),
'destination' => $redirect_url->toString()
'destination' => $redirect_url->toString(),
]);
}
else {
@ -439,7 +566,7 @@ class MetadataProfileController extends ControllerBase {
}
}
else {
$edit_url = Url::fromRoute('entity.field_config.' . $this->entityTypeBundleOf . '_field_edit_form', [
$edit_url = Url::fromRoute('entity.field_config.' . $this->entityTypeBundleOf . '_field_edit_form', [
$this->entityType => $field_definition->getTargetBundle(),
'field_config' => $field_definition->id(),
'destination' => $redirect_url->toString(),
@ -448,8 +575,7 @@ class MetadataProfileController extends ControllerBase {
return $edit_url;
}
private function getFieldDetailsFragmentLink(string $field_name, FieldDefinitionInterface $field_definition)
{
private function getFieldDetailsFragmentLink(string $field_name, FieldDefinitionInterface $field_definition) {
$url = Url::fromRoute('<current>', [], ['fragment' => $field_name]);
return Link::fromTextAndUrl($field_definition->getLabel(), $url);
}
@ -463,20 +589,21 @@ class MetadataProfileController extends ControllerBase {
];
}
protected function getFieldTableRows(array $field_profile) {
$rows = [
$rows = [
[$this->t('Type:'), $field_profile['type']],
[$this->t('Required:'), $field_profile['required']],
[$this->t('Repeatable:'), $field_profile['repeatable']],
];
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']),
];
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;
}
@ -489,24 +616,22 @@ class MetadataProfileController extends ControllerBase {
}
return $type_label;
}
protected function formatRequired(FieldDefinitionInterface $field_definition) {
if ($field_definition->isRequired()) {
return $this->t('Required');
}
else {
return $this->t('Not required');
}
$cardinality = $field_definition->isRequired();
return $this->yesNoIcon($cardinality);
}
/**
* This does not work - most fields dont have a form weight specified in getDisplayOptions.
* This does not work - most fields dont have a form weight specified in
* getDisplayOptions.
*/
protected function getWeight(string $field_name, array $form) {
if (isset($form[$field_name])) {
$local_weight = $form[$field_name]['#weight'];
if ($parent = $form['#group_children'][$field_name]) {
$parent_weight = $this->getWeight($parent, $form);
return $this->combine_weights($parent_weight, $local_weight);
return $this->combineWeights($parent_weight, $local_weight);
}
else {
return $local_weight;
@ -518,32 +643,35 @@ class MetadataProfileController extends ControllerBase {
}
protected function formatCardinality(FieldDefinitionInterface $field_definition) {
$cardinality = $field_definition->getFieldStorageDefinition()->getCardinality();
if ($cardinality == 1) {
return $this->t('Not repeatable');
} elseif ($cardinality < 0) {
return $this->t('Repeatable');
} elseif ($cardinality > 1) {
return $this->t('Repeatable, limit :limit', [':limit' => $cardinality]);
$cardinality = $field_definition
->getFieldStorageDefinition()
->getCardinality();
if ($cardinality === 1) {
return $this->yesNoIcon($cardinality);
}
return NULL;
if ($cardinality === -1) {
return $this->yesNoIcon($cardinality);
}
return $this->t('Yes (max @limit)', [
'@limit' => $cardinality,
]);
}
protected function formatCreateNew(FieldDefinitionInterface $field_definition) {
if (in_array($field_definition->getType(), ['entity_reference', 'typed_relation'])) {
$create_new_bundle = $field_definition->getSetting('handler_settings')['auto_create_bundle'] ? $create_new_bundle = $field_definition->getSetting('handler_settings')['auto_create_bundle'] : '';
$create_new = $field_definition->getSetting('handler_settings')['auto_create'] || '';
if ($create_new) {
return $create_new_bundle ? 'Create new (' . $create_new_bundle . ')' : 'Create new';
}
else {
return $this->t('Do not create new');
}
}
else {
if (!in_array($field_definition->getType(), [
'entity_reference',
'typed_relation',
], TRUE)) {
return NULL;
}
$settings = $field_definition->getSetting('handler_settings') ?? [];
$create_new = !empty($settings['auto_create']);
return $this->yesNoIcon($create_new);
}
protected function formatTargetBundles(FieldDefinitionInterface $field_definition) {
@ -555,10 +683,14 @@ class MetadataProfileController extends ControllerBase {
$target_bundles = $setting['target_bundles'];
foreach ($target_bundles as $index => $bundle) {
if ($handler == 'default:taxonomy_term') {
$bundle_config = $this->entityTypeManager()->getStorage('taxonomy_vocabulary')->load($bundle);
$bundle_config = $this->entityTypeManager()
->getStorage('taxonomy_vocabulary')
->load($bundle);
}
if ($handler == 'default:node') {
$bundle_config = $this->entityTypeManager()->getStorage('node_type')->load($bundle);
$bundle_config = $this->entityTypeManager()
->getStorage('node_type')
->load($bundle);
}
// TODO: ADD MEDIA, PARAGRAPHS ETC
if ($bundle_config) {
@ -571,16 +703,18 @@ class MetadataProfileController extends ControllerBase {
'#theme' => 'item_list',
'#title' => $this->t('Target bundles:'),
'#items' => $target_bundles,
'#type' => 'ul'
];
'#type' => 'ul',
];
}
protected function formatListForTable(array $list) {
return ['data' => [
'#theme' => 'item_list',
'#items' => array_values($list),
'#type' => 'ul',
]];
return [
'data' => [
'#theme' => 'item_list',
'#items' => array_values($list),
'#type' => 'ul',
],
];
}
protected function formatSearchApi($field_profile) {
@ -613,9 +747,8 @@ class MetadataProfileController extends ControllerBase {
}
}
protected function getSearchApiField($field_setting_name, $field_setting, $index_config) {
$search_api_field_array = [
$search_api_field_array = [
'search_api_field_name' => $field_setting_name,
'search_api_field_label' => $field_setting['label'],
'property_path' => $field_setting['property_path'],
@ -626,24 +759,30 @@ class MetadataProfileController extends ControllerBase {
if ($field_setting['property_path'] == 'aggregated_field') {
$search_api_field_array['fields_included'] = $field_setting['configuration']['fields'];
}
else if ($field_setting['property_path'] == 'edtf_year') {
$search_api_field_array['fields_included'] = $index_config->get('processor_settings')['edtf_year_only']['fields'];
}
else if ($field_setting['property_path'] == 'edtf') {
$search_api_field_array['fields_included'] = $index_config->get('processor_settings')['edtf_date_processor']['fields'];
}
else {
$search_api_field_array['fields_included'] = [];
if ($field_setting['property_path'] == 'edtf_year') {
$search_api_field_array['fields_included'] = $index_config->get('processor_settings')['edtf_year_only']['fields'];
}
else {
if ($field_setting['property_path'] == 'edtf') {
$search_api_field_array['fields_included'] = $index_config->get('processor_settings')['edtf_date_processor']['fields'];
}
else {
$search_api_field_array['fields_included'] = [];
}
}
}
// Get facet info.
$search_api_field_array['has_facet'] = FALSE;
if ($this->moduleHandler()->moduleExists('facets')) {
$all_facets = \Drupal::entityTypeManager()->getStorage('facets_facet')->loadMultiple();
$all_facets = \Drupal::entityTypeManager()
->getStorage('facets_facet')
->loadMultiple();
foreach ($all_facets as $facet_id => $facet) {
// If facet uses this solr field... then add it to the array.
if ($facet->get('field_identifier') == $field_setting_name) {
$search_api_field_array['has_facet'] = True;
$search_api_field_array['has_facet'] = TRUE;
$search_api_field_array['facets'][] = [
'field_identifier' => $facet->get('field_identifier'),
'facet_name' => $facet->getName(),
@ -661,6 +800,7 @@ class MetadataProfileController extends ControllerBase {
protected function getBlockVisible($facet) {
return '';
}
protected function formatSearchApiField($search_api_field_profile) {
return [
'data' => [
@ -671,26 +811,48 @@ class MetadataProfileController extends ControllerBase {
$this->formatListForTable($search_api_field_profile['fields_included']),
$search_api_field_profile['index_name'],
$search_api_field_profile['has_facet'] ? 'True' : '',
]
],
];
}
/**
* Sanitizes table rows for CSV export.
*
* Converts renderable elements and objects into scalar values:
* - Link objects are converted to their text.
* - Arrays are flattened into pipe-delimited strings.
*
* @param array $rows
* A numerically indexed array of row arrays.
*
* @return array
* Sanitized rows suitable for fputcsv().
*/
public function sanitizeRowsForCSV($rows) {
foreach ($rows as $row_key => $row) {
foreach ($row as $element_key => $element) {
if ($element instanceof Link) {
$rows[$row_key][$element_key] = $element->getText();
}
else if (is_array($element)) {
$rows[$row_key][$element_key] = implode('|', $element);
else {
if (is_array($element)) {
$rows[$row_key][$element_key] = implode('|', $element);
}
}
}
}
return $rows;
}
/**
* Generates and returns a CSV download of the metadata profile.
*
* Writes a temporary CSV file and serves it using Drupal's
* file download controller.
*
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
* The file download response.
*/
public function download() {
$contentType = $this->entityBundle;
$entityKey = $this->entityTypeBundleOf;
@ -714,8 +876,7 @@ class MetadataProfileController extends ControllerBase {
return $this->fileDownloadController->download($request, 'temporary');
}
private function formatFacets(array $field_profile)
{
private function formatFacets(array $field_profile) {
if (!$field_profile['search_api']['has_facet']) {
return [];
}
@ -738,7 +899,6 @@ class MetadataProfileController extends ControllerBase {
$build['#rows'][] = $this->formatFacet($facet);
}
}
}
if (count($build['#rows']) == 0) {
return [];
@ -748,8 +908,7 @@ class MetadataProfileController extends ControllerBase {
}
}
private function formatFacet($facet)
{
private function formatFacet($facet) {
return [
'data' => [
$facet['field_identifier'],
@ -758,49 +917,95 @@ class MetadataProfileController extends ControllerBase {
$facet['facet_source'],
$facet['url_alias'],
$facet['block_visible'],
]
],
];
}
private function addWeights(array $metadata_profile)
{
private function addWeights(array $metadata_profile) {
if ($this->entityTypeBundleOf == 'node') {
$node = \Drupal\node\Entity\Node::create(['type' => $this->entityBundle]);
$form = \Drupal::service('entity.form_builder')->getForm($node);
foreach($metadata_profile as $field_name => $field_profile) {
foreach ($metadata_profile as $field_name => $field_profile) {
$metadata_profile[$field_name]['weight'] = $this->getWeight($field_name, $form);
}
$weights = array_column($metadata_profile, 'weight');
array_multisort($weights, SORT_ASC, $metadata_profile);
}
return $metadata_profile;
}
private function combine_weights($parent_weight, $local_weight)
{
$parent_int = (string)floor($parent_weight);
$parent_fraction = (string)($parent_weight - $parent_int);
private function combineWeights($parent_weight, $local_weight) {
$parent_int = (string) floor($parent_weight);
$parent_fraction = (string) ($parent_weight - $parent_int);
$parent_fraction = str_replace('0.', '', $parent_fraction);
$local_int = (string)floor($local_weight);
$local_fraction = (string)($local_weight - $local_int);
$local_int = (string) floor($local_weight);
$local_fraction = (string) ($local_weight - $local_int);
$combined_weight = $parent_int;
$combined_weight .= '.';
if ($parent_fraction) {
# pad so its length is a multiple of 2
$length = mb_strlen($parent_fraction);
if (fmod($length, 2) != 0){
if (fmod($length, 2) != 0) {
$parent_fraction .= '0';
}
$combined_weight .= $parent_fraction;
}
$combined_weight .= str_pad($local_int, 2, '0', STR_PAD_LEFT);
if ($local_fraction) {
$a=2;
$a = 2;
}
return (float)$combined_weight;
return (float) $combined_weight;
}
/**
* Gets usage count for a field.
*
* For configurable fields, counts rows in the field table.
* For base fields, counts nodes of the current bundle.
*
* @param string $field_name
* The field machine name.
*
* @return int
* Number of usages.
*/
private function getUsageCount($field_name) {
if (str_starts_with($field_name, 'field_')) {
$connection = $this->database;
$count = $connection->select("node__{$field_name}", 'f')
->countQuery()
->execute()
->fetchField();
return $count;
}
return $this->entityTypeManagerService
->getStorage('node')
->getQuery()
->accessCheck(FALSE)
->condition('type', $this->entityBundle)
->count()
->execute();
}
/**
* Returns a render array representing a yes/no icon.
*
* @param bool $value
* TRUE for yes, FALSE for no.
*
* @return array
* Render array containing markup for the icon.
*/
protected function yesNoIcon(bool $value): array {
return [
'data' => [
'#markup' => $value
? '<span class="yes-icon" title="Yes"></span>'
: '<span class="no-icon" title="No"></span>',
],
];
}
}

Loading…
Cancel
Save