|
|
|
|
@ -2,29 +2,47 @@
|
|
|
|
|
|
|
|
|
|
namespace Drupal\metadata_profile\Controller; |
|
|
|
|
|
|
|
|
|
use Drupal\Core\Config\Config; |
|
|
|
|
use Drupal\Core\Config\ConfigFactoryInterface; |
|
|
|
|
use Drupal\Core\Controller\ControllerBase; |
|
|
|
|
use Drupal\Core\Entity\EntityFieldManagerInterface; |
|
|
|
|
use Drupal\Core\Field\BaseFieldDefinition; |
|
|
|
|
use Drupal\Core\Field\FieldDefinitionInterface; |
|
|
|
|
use Drupal\Core\Field\FieldStorageDefinitionInterface; |
|
|
|
|
use Drupal\Core\Field\FieldTypePluginManagerInterface; |
|
|
|
|
use Drupal\Core\File\FileSystemInterface; |
|
|
|
|
use Drupal\Core\Link; |
|
|
|
|
use Drupal\Core\Messenger\MessengerTrait; |
|
|
|
|
use Drupal\Core\Config\Config; |
|
|
|
|
use Drupal\Core\Routing\RouteMatchInterface; |
|
|
|
|
use Drupal\Core\Url; |
|
|
|
|
use Drupal\field_permissions\Plugin\FieldPermissionType\Base; |
|
|
|
|
use Drupal\system\FileDownloadController; |
|
|
|
|
use Symfony\Component\DependencyInjection\ContainerInterface; |
|
|
|
|
use Drupal\Core\Entity\EntityFieldManagerInterface; |
|
|
|
|
use Symfony\Component\HttpFoundation\Request; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MetadataProfileController extends ControllerBase { |
|
|
|
|
use MessengerTrait; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* The entity field manager. |
|
|
|
|
* |
|
|
|
|
* @var EntityFieldManagerInterface |
|
|
|
|
*/ |
|
|
|
|
protected EntityFieldManagerInterface $entityFieldManager; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* The Field Type Plugin Manager. |
|
|
|
|
* |
|
|
|
|
* @var FieldTypePluginManagerInterface |
|
|
|
|
*/ |
|
|
|
|
protected FieldTypePluginManagerInterface $fieldTypePluginManager; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* The config factory. |
|
|
|
|
* |
|
|
|
|
* @var ConfigFactoryInterface |
|
|
|
|
*/ |
|
|
|
|
protected $configFactory; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* The route matcher. |
|
|
|
|
* |
|
|
|
|
@ -33,31 +51,46 @@ class MetadataProfileController extends ControllerBase {
|
|
|
|
|
protected $routeMatch; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* The entity type machine name. |
|
|
|
|
* The entity type machine name, e.g. 'node_type'. |
|
|
|
|
* |
|
|
|
|
* @var string |
|
|
|
|
*/ |
|
|
|
|
protected $entityType; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* The bundle machine name. |
|
|
|
|
* The bundle machine name, e.g. 'article'. |
|
|
|
|
* |
|
|
|
|
* @var string |
|
|
|
|
*/ |
|
|
|
|
protected $entityBundle; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* The entity type that our config entity describes bundles of. |
|
|
|
|
* The entity type that our config entity describes bundles of, e.g. 'node'. |
|
|
|
|
* |
|
|
|
|
* @var string |
|
|
|
|
*/ |
|
|
|
|
protected $entityTypeBundleOf; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* File system interface. |
|
|
|
|
* |
|
|
|
|
* @var \Drupal\Core\File\FileSystemInterface |
|
|
|
|
*/ |
|
|
|
|
protected $fileSystem; |
|
|
|
|
/** |
|
|
|
|
* The file download controller. |
|
|
|
|
* |
|
|
|
|
* @var \Drupal\system\FileDownloadController |
|
|
|
|
*/ |
|
|
|
|
protected $fileDownloadController; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function __construct(EntityFieldManagerInterface $entity_field_manager, |
|
|
|
|
FieldTypePluginManagerInterface $field_type_plugin_manager, |
|
|
|
|
ConfigFactoryInterface $config_factory, |
|
|
|
|
RouteMatchInterface $route_match) { |
|
|
|
|
RouteMatchInterface $route_match, |
|
|
|
|
FileSystemInterface $file_system, |
|
|
|
|
FileDownloadController $file_download_controller) { |
|
|
|
|
$this->entityFieldManager = $entity_field_manager; |
|
|
|
|
$this->fieldTypePluginManager = $field_type_plugin_manager; |
|
|
|
|
$this->configFactory = $config_factory; |
|
|
|
|
@ -68,6 +101,8 @@ class MetadataProfileController extends ControllerBase {
|
|
|
|
|
$entity_type = $this->routeMatch->getParameter($this->entityType); |
|
|
|
|
$this->entityBundle = $entity_type->id(); |
|
|
|
|
$this->entityTypeBundleOf = $entity_type->getEntityType()->getBundleOf(); |
|
|
|
|
$this->fileSystem = $file_system; |
|
|
|
|
$this->fileDownloadController = $file_download_controller; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static function create(ContainerInterface $container) { |
|
|
|
|
@ -75,28 +110,27 @@ class MetadataProfileController extends ControllerBase {
|
|
|
|
|
$container->get('entity_field.manager'), |
|
|
|
|
$container->get('plugin.manager.field.field_type'), |
|
|
|
|
$container->get('config.factory'), |
|
|
|
|
$container->get('current_route_match') |
|
|
|
|
$container->get('current_route_match'), |
|
|
|
|
$container->get('file_system'), |
|
|
|
|
FileDownloadController::create($container) |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Returns a render array displaying the metadata profile for $content_type. |
|
|
|
|
* Returns a page (render array) displaying the metadata profile. |
|
|
|
|
* |
|
|
|
|
* @param $content_type |
|
|
|
|
* @return array |
|
|
|
|
*/ |
|
|
|
|
public function profile($content_type = NULL) { |
|
|
|
|
if (!$content_type) { |
|
|
|
|
$content_type = $this->entityBundle; |
|
|
|
|
} |
|
|
|
|
public function profile() { |
|
|
|
|
|
|
|
|
|
// Get core content type information. |
|
|
|
|
$bundle_config = $this->config(str_replace('_', '.', $this->entityType) . '.' . $content_type); |
|
|
|
|
$bundle_config = $this->config(str_replace('_', '.', $this->entityType) . '.' . $this->entityBundle); |
|
|
|
|
if (!$bundle_config) { |
|
|
|
|
return ['#markup'=> 'Not a valid content type.']; |
|
|
|
|
} |
|
|
|
|
$build = $this->format_bundle($bundle_config); |
|
|
|
|
$build = $this->formatBundle($bundle_config); |
|
|
|
|
|
|
|
|
|
$metadata_profile = $this->getMetadataProfile($content_type); |
|
|
|
|
$metadata_profile = $this->getMetadataProfile(); |
|
|
|
|
|
|
|
|
|
$build['summary_table'] = [ |
|
|
|
|
'#type' => 'container', |
|
|
|
|
@ -108,19 +142,19 @@ class MetadataProfileController extends ControllerBase {
|
|
|
|
|
'#type' => 'container', |
|
|
|
|
'#weight' => '9', |
|
|
|
|
]; |
|
|
|
|
// Get field information. |
|
|
|
|
$field_definitions = $this->entityFieldManager->getFieldDefinitions($this->entityTypeBundleOf, $content_type); |
|
|
|
|
// Refactor this to not loop; each thing called by displayField should use metadata profile. |
|
|
|
|
$field_definitions = $this->entityFieldManager->getFieldDefinitions($this->entityTypeBundleOf, $this->entityBundle); |
|
|
|
|
foreach ($field_definitions as $field_name => $field_definition) { |
|
|
|
|
$build['fields'][$field_name] = $this->display_field($field_name, $field_definition, $metadata_profile[$field_name]); |
|
|
|
|
$build['fields'][$field_name] = $this->buildField($metadata_profile[$field_name]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return $build; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Format information about a bundle. |
|
|
|
|
* Format basic information about a bundle. |
|
|
|
|
*/ |
|
|
|
|
protected function format_bundle(Config $bundle) { |
|
|
|
|
protected function formatBundle(Config $bundle) { |
|
|
|
|
if (str_starts_with($bundle->getName(), 'node.type')) { |
|
|
|
|
$label = $bundle->get('name'); |
|
|
|
|
$machine_name = $bundle->get('type'); |
|
|
|
|
@ -160,13 +194,14 @@ class MetadataProfileController extends ControllerBase {
|
|
|
|
|
return $build; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public function getMetadataProfile($bundle) { |
|
|
|
|
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. |
|
|
|
|
@ -175,84 +210,176 @@ class MetadataProfileController extends ControllerBase {
|
|
|
|
|
// * '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' |
|
|
|
|
// * 'facet_name' |
|
|
|
|
// * 'facet_machine_name' |
|
|
|
|
// * 'facet_source' |
|
|
|
|
// * 'url_alias' |
|
|
|
|
// * 'block_visible' |
|
|
|
|
|
|
|
|
|
$metadata_profile = []; |
|
|
|
|
$field_definitions = $this->entityFieldManager->getFieldDefinitions($this->entityTypeBundleOf, $bundle); |
|
|
|
|
$field_definitions = $this->entityFieldManager->getFieldDefinitions($this->entityTypeBundleOf, $this->entityBundle); |
|
|
|
|
foreach ($field_definitions as $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), |
|
|
|
|
'details_link' => $this->getFieldDetailsFragmentLink($field_name, $field_definition), |
|
|
|
|
'description' => $field_definition->getDescription(), |
|
|
|
|
'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), |
|
|
|
|
'base_field' => $field_definition->getFieldStorageDefinition() instanceof BaseFieldDefinition, |
|
|
|
|
]; |
|
|
|
|
// Add solr |
|
|
|
|
$metadata_profile[$field_name]['search_api'] = $this->getSearchApi($field_definition); |
|
|
|
|
} |
|
|
|
|
return $metadata_profile; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private function getSearchApi($field_definition) { |
|
|
|
|
if (!$this->moduleHandler()->moduleExists('search_api')) { |
|
|
|
|
return FALSE; |
|
|
|
|
} |
|
|
|
|
$search_api = [ |
|
|
|
|
'in_search_api' => FALSE, |
|
|
|
|
'fields' => [], |
|
|
|
|
]; |
|
|
|
|
$storage = $field_definition->getFieldStorageDefinition(); |
|
|
|
|
if ($storage instanceof BaseFieldDefinition) { |
|
|
|
|
$field_id = $this->entityTypeBundleOf . '.' . $storage->getName(); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
$field_id = 'field.storage.' . $storage->get('id'); |
|
|
|
|
} |
|
|
|
|
$search_api_indexes = $this->configFactory->listAll('search_api.index'); |
|
|
|
|
foreach ($search_api_indexes as $index) { |
|
|
|
|
$index_config = $this->config($index); |
|
|
|
|
|
|
|
|
|
// 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; |
|
|
|
|
// 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'])) { |
|
|
|
|
$search_api['fields'][$indexed_field_name] = $this->getSearchApiField($search_api_field_name, $search_api_field_setting, $index_config); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// 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); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// 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); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Check dependencies for a dependency on this field. |
|
|
|
|
if (isset($search_api_field_setting['dependencies']) and isset($search_api_field_setting['dependencies']['config'])) { |
|
|
|
|
$field_dependencies = $search_api_field_setting['dependencies']['config']; |
|
|
|
|
if (in_array($field_id, $field_dependencies)) { |
|
|
|
|
$search_api['fields'][$indexed_field_name] = $this->getSearchApiField($search_api_field_name, $search_api_field_setting, $index_config); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Check if the property path equals this field. |
|
|
|
|
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)) { |
|
|
|
|
$search_api['has_facet'] = TRUE; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
$search_api['has_facet'] = FALSE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
return $search_api; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected function buildSummaryTable($metadata_profile) { |
|
|
|
|
$rows = $this->getRows($metadata_profile, TRUE); |
|
|
|
|
return [ |
|
|
|
|
'#type' => 'table', |
|
|
|
|
'#header' => $this->getHeaders(), |
|
|
|
|
'#rows' => $rows, |
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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'])) { |
|
|
|
|
$rows[] = [ |
|
|
|
|
$field_profile['details_link'], |
|
|
|
|
$display ? $field_profile['details_link'] : $field_profile['label'], |
|
|
|
|
$field_profile['machine_name'], |
|
|
|
|
$field_profile['description'], |
|
|
|
|
$field_profile['type'], |
|
|
|
|
$field_profile['required'], |
|
|
|
|
$field_profile['repeatable'], |
|
|
|
|
$field_profile['auto_create'], |
|
|
|
|
$this->formatListForTable($field_profile['target_bundles']), |
|
|
|
|
]; |
|
|
|
|
$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' : '', |
|
|
|
|
]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return $rows; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected function getHeaders() { |
|
|
|
|
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, |
|
|
|
|
$this->t('Field'), |
|
|
|
|
$this->t('Machine name'), |
|
|
|
|
$this->t('Description'), |
|
|
|
|
$this->t('Type'), |
|
|
|
|
$this->t('Required'), |
|
|
|
|
$this->t('Repeatable'), |
|
|
|
|
$this->t('Create new'), |
|
|
|
|
$this->t('Target bundles'), |
|
|
|
|
$this->t('In Search API'), |
|
|
|
|
$this->t('Has Facet'), |
|
|
|
|
// TODO: add more columns |
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected function display_field(string $field_name, FieldDefinitionInterface $field_definition, array $field_profile) { |
|
|
|
|
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'])) { |
|
|
|
|
$render_array = [ |
|
|
|
|
'#type' => 'container', |
|
|
|
|
'#attributes' => ['class' => ['field-info']], |
|
|
|
|
'#weight' => $this->formatWeight($field_definition), // This doesn't work. |
|
|
|
|
// TODO: add weight here from form display defaults. |
|
|
|
|
'title' => [ |
|
|
|
|
'#plain_text' => $field_profile['label'], |
|
|
|
|
'#prefix' => '<h2 id="' . $field_name . '">', |
|
|
|
|
@ -272,10 +399,11 @@ class MetadataProfileController extends ControllerBase {
|
|
|
|
|
], |
|
|
|
|
'description' => [ |
|
|
|
|
'#type' => 'markup', |
|
|
|
|
'#markup' => $field_definition->getDescription() ?: $this->t('[No description]'), |
|
|
|
|
'#markup' => $field_profile['description'] ?: $this->t('[No description]'), |
|
|
|
|
'#prefix' => '<b>Description:</b> ', |
|
|
|
|
], |
|
|
|
|
'search_api' => $this->formatSearchApi($field_definition), |
|
|
|
|
'search_api' => $this->formatSearchApi($field_profile), |
|
|
|
|
'facets' => $this->formatFacets($field_profile), |
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
@ -297,7 +425,6 @@ class MetadataProfileController extends ControllerBase {
|
|
|
|
|
else { |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
return NULL; |
|
|
|
|
@ -312,6 +439,13 @@ class MetadataProfileController extends ControllerBase {
|
|
|
|
|
} |
|
|
|
|
return $edit_url; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private function getFieldDetailsFragmentLink(string $field_name, FieldDefinitionInterface $field_definition) |
|
|
|
|
{ |
|
|
|
|
$url = Url::fromRoute('<current>', [], ['fragment' => $field_name]); |
|
|
|
|
return Link::fromTextAndUrl($field_definition->getLabel(), $url); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected function formatFieldEditLink(Url $edit_url) { |
|
|
|
|
return [ |
|
|
|
|
'#type' => 'link', |
|
|
|
|
@ -321,6 +455,8 @@ class MetadataProfileController extends ControllerBase {
|
|
|
|
|
]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected function getFieldTableRows(array $field_profile) { |
|
|
|
|
$rows = [ |
|
|
|
|
[$this->t('Type:'), $field_profile['type']], |
|
|
|
|
@ -375,8 +511,8 @@ class MetadataProfileController extends ControllerBase {
|
|
|
|
|
|
|
|
|
|
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 = $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'; |
|
|
|
|
} |
|
|
|
|
@ -426,119 +562,182 @@ class MetadataProfileController extends ControllerBase {
|
|
|
|
|
'#type' => 'ul', |
|
|
|
|
]]; |
|
|
|
|
} |
|
|
|
|
protected function formatSearchApi($field_definition) { |
|
|
|
|
if ($this->moduleHandler()->moduleExists('search_api')) { |
|
|
|
|
$build = [ |
|
|
|
|
'#type' => 'table', |
|
|
|
|
'#header' => [ |
|
|
|
|
'col1' => $this->t('Search API field name'), |
|
|
|
|
'col2' => $this->t('Search API machine name'), |
|
|
|
|
'col3' => $this->t('Search API property path'), |
|
|
|
|
'col4' => $this->t('Search API field type'), |
|
|
|
|
'col0' => $this->t('Search API index'), |
|
|
|
|
], |
|
|
|
|
'#rows' => [], |
|
|
|
|
]; |
|
|
|
|
$storage = $field_definition->getFieldStorageDefinition(); |
|
|
|
|
if ($storage instanceof BaseFieldDefinition) { |
|
|
|
|
// Use property_path to find related fields. |
|
|
|
|
$field_id = $this->entityTypeBundleOf . '.' . $storage->getName(); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
$field_id = 'field.storage.' . $storage->get('id'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
$search_api_indexes = $this->configFactory->listAll('search_api.index'); |
|
|
|
|
foreach ($search_api_indexes as $index) { |
|
|
|
|
$index_config = $this->config($index); |
|
|
|
|
// Loop over fields. |
|
|
|
|
foreach ($index_config->get('field_settings') as $field_setting_name => $field_setting) { |
|
|
|
|
// Check dependencies. |
|
|
|
|
$field_dependencies = $field_setting['dependencies']['config'] ?: []; |
|
|
|
|
if (in_array($field_id, $field_dependencies)) { |
|
|
|
|
$build['#rows'][$field_setting_name] = $this->format_search_api_field($field_setting_name, $field_setting, $index_config); |
|
|
|
|
} |
|
|
|
|
// Check by property path. |
|
|
|
|
if ($field_setting['datasource_id'] == 'entity:node' and $field_setting['property_path'] == $field_definition->getName()) { |
|
|
|
|
$build['#rows'][$field_setting_name] = $this->format_search_api_field($field_setting_name, $field_setting, $index_config); |
|
|
|
|
} |
|
|
|
|
// Get Aggregated Fields. |
|
|
|
|
if ($field_setting['property_path'] == 'aggregated_field') { |
|
|
|
|
if (in_array('entity:node/' . $field_definition->getName(), $field_setting['configuration']['fields'])) { |
|
|
|
|
$build['#rows'][$field_setting_name] = $this->format_search_api_field($field_setting_name, $field_setting, $index_config); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if ($field_definition->getType() == 'edtf') { |
|
|
|
|
// Get EDTF year. |
|
|
|
|
if ($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)) { |
|
|
|
|
$build['#rows'][$field_setting_name] = $this->format_search_api_field($field_setting_name, $field_setting, $index_config); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Get EDTF Date |
|
|
|
|
if ($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)) { |
|
|
|
|
$build['#rows'][$field_setting_name] = $this->format_search_api_field($field_setting_name, $field_setting, $index_config); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
protected function formatSearchApi($field_profile) { |
|
|
|
|
if (!$field_profile['search_api']['in_search_api']) { |
|
|
|
|
return []; |
|
|
|
|
} |
|
|
|
|
$build = [ |
|
|
|
|
'#type' => 'table', |
|
|
|
|
'#header' => [ |
|
|
|
|
'col1' => $this->t('Search API field name'), |
|
|
|
|
'col2' => $this->t('Search API machine name'), |
|
|
|
|
'col3' => $this->t('Search API property path'), |
|
|
|
|
'col4' => $this->t('Search API field type'), |
|
|
|
|
'col5' => $this->t('Aggregate field includes'), |
|
|
|
|
'col0' => $this->t('Search API index'), |
|
|
|
|
'col6' => $this->t('Has facet'), |
|
|
|
|
], |
|
|
|
|
'#rows' => [], |
|
|
|
|
]; |
|
|
|
|
foreach ($field_profile['search_api']['fields'] as $search_api_field) { |
|
|
|
|
$build['#rows'][] = $this->formatSearchApiField($search_api_field); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
if (count($build['#rows']) == 0) { |
|
|
|
|
return []; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (count($build['#rows']) == 0) { |
|
|
|
|
return []; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
return $build; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected function getSearchApiField($field_setting_name, $field_setting, $index_config) { |
|
|
|
|
$search_api_field_array = [ |
|
|
|
|
'search_api_field_name' => $field_setting_name, |
|
|
|
|
'search_api_field_label' => $field_setting['label'], |
|
|
|
|
'property_path' => $field_setting['property_path'], |
|
|
|
|
'type' => $field_setting['type'], |
|
|
|
|
'index_name' => $index_config->get('name'), |
|
|
|
|
]; |
|
|
|
|
// Get fields included for aggregated fields. |
|
|
|
|
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 { |
|
|
|
|
return []; |
|
|
|
|
$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(); |
|
|
|
|
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['facets'][] = [ |
|
|
|
|
'field_identifier' => $facet->get('field_identifier'), |
|
|
|
|
'facet_name' => $facet->getName(), |
|
|
|
|
'facet_machine_name' => $facet_id, |
|
|
|
|
'facet_source' => $facet->getFacetSourceId(), |
|
|
|
|
'url_alias' => $facet->getUrlAlias(), |
|
|
|
|
'block_visible' => $this->getBlockVisible($facet), |
|
|
|
|
]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return $search_api_field_array; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected function format_search_api_field($field_setting_name, $field_setting, $index_config) { |
|
|
|
|
$build = [ |
|
|
|
|
protected function getBlockVisible($facet) { |
|
|
|
|
return ''; |
|
|
|
|
} |
|
|
|
|
protected function formatSearchApiField($search_api_field_profile) { |
|
|
|
|
return [ |
|
|
|
|
'data' => [ |
|
|
|
|
$field_setting['label'], |
|
|
|
|
$field_setting_name, |
|
|
|
|
$field_setting['property_path'], |
|
|
|
|
$field_setting['type'], |
|
|
|
|
$index_config->get('name'), |
|
|
|
|
$search_api_field_profile['search_api_field_label'], |
|
|
|
|
$search_api_field_profile['search_api_field_name'], |
|
|
|
|
$search_api_field_profile['property_path'], |
|
|
|
|
$search_api_field_profile['type'], |
|
|
|
|
$this->formatListForTable($search_api_field_profile['fields_included']), |
|
|
|
|
$search_api_field_profile['index_name'], |
|
|
|
|
$search_api_field_profile['has_facet'] ? 'True' : '', |
|
|
|
|
] |
|
|
|
|
]; |
|
|
|
|
if ($field_setting['property_path'] == 'aggregated_field') { |
|
|
|
|
$list_render_array = [ |
|
|
|
|
'#theme' => 'item_list', |
|
|
|
|
'#items' => $field_setting['configuration']['fields'] |
|
|
|
|
]; |
|
|
|
|
$cell_element = [ 'data' => [ |
|
|
|
|
'#type' => 'container', |
|
|
|
|
'label' => ['#markup' => $build['data'][2]], |
|
|
|
|
'list' => $list_render_array, |
|
|
|
|
]]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$build['data'][2] = $cell_element; |
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (in_array($field_setting['property_path'], ['edtf_year', 'edtf_dates'])) { |
|
|
|
|
$list_render_array = [ |
|
|
|
|
'#theme' => 'item_list', |
|
|
|
|
'#items' => $index_config->get('processor_settings')['edtf_year_only']['fields'] ?: $this->t('No fields avaailable') |
|
|
|
|
]; |
|
|
|
|
$cell_element = [ 'data' => [ |
|
|
|
|
'#type' => 'container', |
|
|
|
|
'label' => ['#markup' => $build['data'][2]], |
|
|
|
|
'list' => $list_render_array, |
|
|
|
|
]]; |
|
|
|
|
return $rows; |
|
|
|
|
} |
|
|
|
|
public function download() { |
|
|
|
|
$contentType = $this->entityBundle; |
|
|
|
|
$entityKey = $this->entityTypeBundleOf; |
|
|
|
|
$headers = $this->getHeaders(); |
|
|
|
|
$metadata_profile = $this->getMetadataProfile(); |
|
|
|
|
$rows = $this->getRows($metadata_profile); |
|
|
|
|
$rows = $this->sanitizeRowsForCSV($rows); |
|
|
|
|
$filename_slug = "{$entityKey}__{$contentType}.csv"; |
|
|
|
|
$filename = $this->fileSystem->getTempDirectory() . '/' . $filename_slug; |
|
|
|
|
// Write file to temporary filesystem. |
|
|
|
|
if (file_exists($filename)) { |
|
|
|
|
$this->fileSystem->delete($filename); |
|
|
|
|
} |
|
|
|
|
$fh = fopen($filename, 'w'); |
|
|
|
|
fputcsv($fh, $headers); |
|
|
|
|
foreach ($rows as $row) { |
|
|
|
|
fputcsv($fh, $row); |
|
|
|
|
} |
|
|
|
|
fclose($fh); |
|
|
|
|
$request = new Request(['file' => $filename_slug]); |
|
|
|
|
return $this->fileDownloadController->download($request, 'temporary'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
$build['data'][2] = $cell_element; |
|
|
|
|
private function formatFacets(array $field_profile) |
|
|
|
|
{ |
|
|
|
|
if (!$field_profile['search_api']['has_facet']) { |
|
|
|
|
return []; |
|
|
|
|
} |
|
|
|
|
$build = [ |
|
|
|
|
'#type' => 'table', |
|
|
|
|
'#header' => [ |
|
|
|
|
$this->t('Search API field'), |
|
|
|
|
$this->t('Facet name'), |
|
|
|
|
$this->t('Facet machine name'), |
|
|
|
|
$this->t('Facet source'), |
|
|
|
|
$this->t('URL fragment alias'), |
|
|
|
|
$this->t('Block is placed'), |
|
|
|
|
], |
|
|
|
|
'#rows' => [], |
|
|
|
|
]; |
|
|
|
|
foreach ($field_profile['search_api']['fields'] as $field) { |
|
|
|
|
if ($field['has_facet']) { |
|
|
|
|
foreach ($field['facets'] as $facet) { |
|
|
|
|
$build['#rows'][] = $this->formatFacet($facet); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
if (count($build['#rows']) == 0) { |
|
|
|
|
return []; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
return $build; |
|
|
|
|
} |
|
|
|
|
return $build; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private function getDetailsFragmentLink(string $field_name, FieldDefinitionInterface $field_definition) |
|
|
|
|
private function formatFacet($facet) |
|
|
|
|
{ |
|
|
|
|
$url = Url::fromRoute('<current>', [], ['fragment' => $field_name]); |
|
|
|
|
return Link::fromTextAndUrl($field_definition->getLabel(), $url); |
|
|
|
|
return [ |
|
|
|
|
'data' => [ |
|
|
|
|
$facet['field_identifier'], |
|
|
|
|
$facet['facet_name'], |
|
|
|
|
$facet['facet_machine_name'], |
|
|
|
|
$facet['facet_source'], |
|
|
|
|
$facet['url_alias'], |
|
|
|
|
$facet['block_visible'], |
|
|
|
|
] |
|
|
|
|
]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|