datafield-1.x-dev/src/Plugin/Field/FieldWidget/DataFieldTable.php
src/Plugin/Field/FieldWidget/DataFieldTable.php
<?php
namespace Drupal\datafield\Plugin\Field\FieldWidget;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Field\Attribute\FieldWidget;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Site\Settings;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Url;
use Drupal\views\Views;
/**
* Plugin implementation of the 'data_field' widget.
*/
#[FieldWidget(
id: 'data_field_table_widget',
label: new TranslatableMarkup('Data Field Table'),
field_types: ['data_field'],
)]
class DataFieldTable extends DataField {
/**
* {@inheritdoc}
*/
public static function defaultSettings(): array {
$settings = [
'field_reference' => '',
];
return $settings + parent::defaultSettings();
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state): array {
$elements = parent::settingsForm($form, $form_state);
$field_settings = $this->fieldDefinition->getSetting('field_settings');
$storage_settings = $this->fieldDefinition->getFieldStorageDefinition()->getSetting('columns');
$options = [];
foreach ($storage_settings as $subfield => $columns) {
if ($columns['type'] == 'entity_reference') {
$options[$subfield] = $field_settings[$subfield]['label'];
}
}
$field_reference = $this->getSetting('field_reference');
if (!empty($options)) {
$elements['field_reference'] = [
'#type' => 'select',
'#options' => $options,
'#empty_option' => $this->t('- Select -'),
'#title' => $this->t('Reference field'),
'#description' => $this->t('Add a multiple search button on reference, only works with first column entity reference'),
'#default_value' => $field_reference,
];
}
// Make the search entity reference the first column.
if (!empty($field_reference)) {
$elements["widget_settings"][$field_reference]["weight"]["#default_value"] = -1;
}
return $elements;
}
/**
* {@inheritdoc}
*/
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state): array {
$storage = $this->getFormElement($items, $delta, $element, $form, $form_state);
if (empty($storage)) {
return [];
}
$cardinality = $this->fieldDefinition->getFieldStorageDefinition()->getCardinality();
$widget = [
'#type' => 'table',
'#base_type' => 'data_field',
];
if ($cardinality != FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
$widget += [
'#header' => $this->buildTableHeader(),
'#title' => $element["#title"],
'#caption' => $element["#title"],
'#attributes' => [
'class' => ['caption-top'],
],
];
}
return $element + $widget + $storage;
}
/**
* {@inheritDoc}
*/
private function buildTableHeader() {
$header = [];
$subfields = $this->getFieldSetting('columns');
$widgetSettings = $this->getSetting('widget_settings');
if (!empty($widgetSettings)) {
uasort($widgetSettings, [
'Drupal\Component\Utility\SortArray',
'sortByWeightElement',
]);
$subfields = $widgetSettings;
}
$fieldSettings = $this->getFieldSetting('field_settings');
foreach (array_keys($subfields) as $subfield) {
$item = $this->getFieldSetting('columns')[$subfield];
if (!empty($widgetSettings[$subfield]) && empty($widgetSettings[$subfield]['field_display'])) {
continue;
}
if (!empty($widgetSettings[$subfield]) && $widgetSettings[$subfield]['label_display'] == 'hidden') {
$header[] = '';
continue;
}
$header[] = $fieldSettings[$subfield]['label'] ?? $item['name'];
}
$settings = $this->getSettings();
if (!empty($settings['operation'])) {
$header[] = '';
}
return $header;
}
/**
* {@inheritDoc}
*/
public function formMultipleElements(FieldItemListInterface $items, array &$form, FormStateInterface $form_state) {
$field_name = $this->fieldDefinition->getName();
$field_state = static::getWidgetState($form['#parents'], $field_name, $form_state);
$items_total = count($items);
$cardinality = $this->fieldDefinition->getFieldStorageDefinition()->getCardinality();
$removed = 'datafield_removed_empty' . $field_name;
if ($items_total && $cardinality == -1 && !$form_state->get($removed)) {
if (empty($field_state['array_parents'])) {
$field_state['items_count'] -= 1;
static::setWidgetState($form['#parents'], $field_name, $form_state, $field_state);
}
$form_state->set($removed, TRUE);
}
$elements = parent::formMultipleElements($items, $form, $form_state);
if (!empty($field_reference = $this->getSetting('field_reference'))) {
$fieldDefinition = $this->fieldDefinition->getSetting('field_settings');
$elements['#field_reference'] = $field_reference;
$elements['#field_reference_title'] = str_replace('"', '', $fieldDefinition[$field_reference]['label']);
$fieldSettings = $this->getFieldSetting('field_settings')[$field_reference];
$elements['#entity_reference_type'] = $fieldSettings['entity_reference_type'];
$elements['#target_bundles'] = $fieldSettings['target_bundles'];
$selection_settings = [
'match_operator' => 'CONTAINS',
'match_limit' => 10,
];
$checkView = explode(':', $elements['#target_bundles']);
if (empty($checkView[1])) {
$fieldSettings["handler"] = 'default:' . $fieldSettings['entity_reference_type'];
$selection_settings['target_bundles'] = [$elements['#target_bundles'] => $elements['#target_bundles']];
}
else {
$fieldSettings["handler"] = 'views';
$selection_settings['view'] = [
'view_name' => $checkView[0],
'display_name' => $checkView[1],
'arguments' => [],
];
}
$data = serialize($selection_settings) . $fieldSettings['entity_reference_type'] . $fieldSettings["handler"];
$selection_settings_key = Crypt::hmacBase64($data, Settings::getHashSalt());
$key_value_storage = $this->keyValue->get('entity_autocomplete');
if (!$key_value_storage->has($selection_settings_key)) {
$key_value_storage->set($selection_settings_key, $selection_settings);
}
$elements['#field_reference_url'] = Url::fromRoute('datafield.field_reference', [
'target_type' => $fieldSettings['entity_reference_type'],
'selection_handler' => $fieldSettings["handler"],
'selection_settings_key' => $selection_settings_key,
])->toString();
$elements['#attached']['drupalSettings']['field_reference'][$field_reference] = $this->fieldReferenceSettings($fieldSettings['target_bundles']);
}
if ($cardinality != 1) {
$subFormElements = Element::children($elements);
foreach ($subFormElements as $delta) {
if (is_numeric($delta)) {
$childElements = Element::children($elements[$delta]);
$element = [];
foreach ($childElements as $child) {
if (is_numeric($child)) {
$element = $elements[$delta][$child];
}
else {
$element[$child] = $elements[$delta][$child];
}
}
unset($elements[$delta]);
$elements[$delta] = $element;
}
}
}
$elements += [
'#widgetDataFieldTable' => TRUE,
];
$elements['#attached']['library'][] = 'datafield/shortcut';
return $elements;
}
/**
* Set drupal settings for search entity.
*
* @param string $target_bundle
* The bundle select or views.
*
* @return array
* The settings columns.
*/
protected function fieldReferenceSettings(string $target_bundle): array {
$settings = [
'columns' => [
['field' => 'state', 'checkbox' => "true"],
],
];
$searchKey = 'name';
$checkView = explode(':', $target_bundle);
if (!empty($checkView[1])) {
$view = Views::getView($checkView[0]);
$view->setDisplay($checkView[1]);
$displayHandler = $view->displayHandlers->get($checkView[1]);
$styleOptions = $displayHandler->getPlugin('style')->options['search_fields'];
$styleOptions = array_filter($styleOptions);
$searchKey = array_key_first($styleOptions);
$listType = [
'list_default',
'options_select',
'list_key',
'options_buttons',
'list_key',
];
$settings['options'] = $displayHandler->getPlugin('row')->options;
$fields = $displayHandler->getOption('fields');
foreach ($fields as $fieldId => $field) {
$type = $field["type"] ?? '';
$typeSearch = in_array($type, $listType) ? 'select' : 'input';
$settings['columns'][] = [
'field' => $fieldId,
'title' => !empty($field['label']) ? $field['label'] : $field["entity_field"] ?? '',
'sortable' => "true",
'filter-control' => $typeSearch,
];
}
}
else {
$settings['columns'][] = [
'field' => $searchKey,
'title' => $this->t('Name'),
'sortable' => "true",
];
}
$settings['search_key'] = $searchKey;
return $settings;
}
}
