Skip to content
Snippets Groups Projects
Commit 00b5d40f authored by Geoffrey Roberts's avatar Geoffrey Roberts Committed by Wayne Eaker
Browse files

Issue #3359118 by geoffreyr, mciver87, zengenuity: Allow HTML in Tablefield Cells

parent bd9de048
No related branches found
No related tags found
1 merge request!2#3359118: Allow table cells to have text formats applied
field.formatter.settings.file_table_formatter:
type: mapping
label: 'File Table Formatter settings'
mapping:
header:
type: boolean
label: 'Files include a header row'
use_text_format:
type: boolean
label: 'Use text format in cells'
text_format:
type: string
label: 'Text format'
......@@ -31,4 +31,3 @@ function template_preprocess_file_table_formatter_table(&$variables) {
];
$variables['title'] = $variables['data']->getTitle();
}
......@@ -2,6 +2,10 @@
namespace Drupal\file_table_formatter;
use Drupal\Core\Field\EntityReferenceFieldItemListInterface;
use Drupal\file\Entity\File;
use Drupal\file\Plugin\Field\FieldType\FileItem;
class FileTableData {
/**
......@@ -15,29 +19,30 @@ class FileTableData {
protected $item;
/**
* @var string
* @var mixed[]|null
*/
protected $header;
/**
* @var array
* @var mixed[]
*/
protected $rows;
/**
* @var string
* @var string|null
*/
protected $title;
/**
* FileTableData constructor.
*
* @param \Drupal\file\Entity\File $file
* @param \Drupal\file\Plugin\Field\FieldType\FileItem $item
* @param string $header
* @param array $rows
* @param mixed[] $rows
* @param mixed[]|null $header
* @param string $title
*/
public function __construct(\Drupal\file\Entity\File $file, \Drupal\file\Plugin\Field\FieldType\FileItem $item = NULL, array $rows = NULL, $header = NULL, $title = NULL) {
public function __construct(File $file, FileItem $item = NULL, array $rows = NULL, array $header = NULL, $title = NULL) {
$this->file = $file;
$this->item = $item;
$this->header = $header;
......@@ -48,35 +53,35 @@ class FileTableData {
/**
* @return \Drupal\file\Entity\File
*/
public function getFile() {
public function getFile(): File {
return $this->file;
}
/**
* @return \Drupal\Core\Field\EntityReferenceFieldItemListInterface
*/
public function getItem() {
public function getItem(): EntityReferenceFieldItemListInterface {
return $this->item;
}
/**
* @return string
* @return mixed[]
*/
public function getHeader() {
public function getHeader(): ?array {
return $this->header;
}
/**
* @return array
* @return mixed[]
*/
public function getRows() {
public function getRows(): array {
return $this->rows;
}
/**
* @return string
* @return string|null
*/
public function getTitle() {
public function getTitle(): ?string {
return $this->title;
}
......
......@@ -2,14 +2,14 @@
namespace Drupal\file_table_formatter;
use Drupal\Core\File\FileSystem;
use Drupal\file\Entity\File;
class FileTableFormatterProcessor implements FileTableFormatterProcessorInterface {
/**
* {@inheritdoc}
*/
public function getTableDataFromFile(\Drupal\file\Entity\File $file, $includes_header = FALSE) {
public function getTableDataFromFile(File $file, bool $includes_header = FALSE, ?string $text_format = NULL): FileTableData {
$data = [];
// Currently only supports CSV files
......@@ -17,6 +17,17 @@ class FileTableFormatterProcessor implements FileTableFormatterProcessorInterfac
// Read the file
if (($fhandle = fopen($file->getFileUri(), 'r')) !== FALSE) {
while ($row = fgetcsv($fhandle)) {
foreach ($row as &$col) {
if (!empty($text_format)) {
$col = [
'data' => [
'#type' => 'processed_text',
'#text' => $col,
'#format' => $text_format,
],
];
}
}
$data[] = $row;
}
fclose($fhandle);
......
......@@ -2,13 +2,21 @@
namespace Drupal\file_table_formatter;
use Drupal\file\Entity\File;
interface FileTableFormatterProcessorInterface {
/**
* @param \Drupal\file\Entity\File $file
* @param bool|FALSE $includes_header
* @return FileTableData
* CSV file to process.
* @param bool $includes_header
* Whether the first row should be treated as the header.
* @param string|null $text_format
* Optional text format to apply to cell contents.
*
* @return \Drupal\file_table_formatter\FileTableData
* The FileTableData object, ready to render.
*/
public function getTableDataFromFile(\Drupal\file\Entity\File $file, $includes_header = FALSE);
public function getTableDataFromFile(File $file, bool $includes_header = FALSE, ?string $text_format = NULL): FileTableData;
}
......@@ -2,16 +2,15 @@
namespace Drupal\file_table_formatter\Plugin\Field\FieldFormatter;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\Annotation\FieldFormatter;
use Drupal\Core\Annotation\Translation;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\file\Entity\File;
use Drupal\file\Plugin\Field\FieldFormatter\FileFormatterBase;
use Drupal\file_table_formatter\FileTableData;
use Drupal\file_table_formatter\FileTableFormatterManager;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\file_table_formatter\FileTableFormatterProcessorInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* @FieldFormatter(
......@@ -21,13 +20,61 @@ use Drupal\file_table_formatter\FileTableFormatterManager;
* )
*/
class FileTableFormatter extends FileFormatterBase {
use StringTranslationTrait;
/**
* {@inheritDoc}
*
* @param mixed $plugin_id
* @param mixed $plugin_definition
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* @param mixed[] $settings
* @param mixed $label
* @param mixed $view_mode
* @param mixed[] $third_party_settings
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* @param \Drupal\file_table_formatter\FileTableFormatterProcessorInterface $fileTableFormatterProcessor,
*/
public function __construct(
$plugin_id,
$plugin_definition,
FieldDefinitionInterface $field_definition,
array $settings,
$label,
$view_mode,
array $third_party_settings,
protected EntityTypeManagerInterface $entityTypeManager,
protected FileTableFormatterProcessorInterface $fileTableFormatterProcessor,
) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
}
/**
* {@inheritDoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self {
return new static(
$plugin_id,
$plugin_definition,
$configuration['field_definition'],
$configuration['settings'],
$configuration['label'],
$configuration['view_mode'],
$configuration['third_party_settings'],
$container->get('entity_type.manager'),
$container->get('file_table_formatter.processor'),
);
}
/**
* {@inheritdoc}
*/
public static function defaultSettings() {
return [
'header' => FALSE,
'use_text_format' => FALSE,
'text_format' => '',
];
}
......@@ -37,10 +84,36 @@ class FileTableFormatter extends FileFormatterBase {
public function settingsForm(array $form, FormStateInterface $form_state) {
$elements['header'] = [
'#type' => 'checkbox',
'#title' => t('Files include a header row'),
'#description' => t('If checked first row will be displayed formatted as a table header'),
'#title' => $this->t('Files include a header row'),
'#description' => $this->t('If checked first row will be displayed formatted as a table header'),
'#default_value' => $this->getSetting('header'),
];
$elements['use_text_format'] = [
'#type' => 'checkbox',
'#title' => $this->t('Use text format in cells'),
'#description' => $this->t('Cells display plain text by default. Enabling this lets you select a text format to process cell contents.'),
'#default_value' => $this->getSetting('use_text_format') ?? FALSE,
];
$text_format_options = [];
foreach ($this->entityTypeManager->getStorage('filter_format')->loadMultiple() as $format) {
$text_format_options[$format->id()] = $format->label();
}
$elements['text_format'] = [
'#type' => 'select',
'#title' => $this->t('Text format'),
'#description' => $this->t('Process cell contents using this text format.'),
'#options' => $text_format_options,
'#default_value' => $this->getSetting('text_format') ?? '',
'#states' => [
'visible' => [
':input[name$="[settings][use_text_format]"]' => ['checked' => TRUE],
],
],
];
return $elements;
}
......@@ -49,9 +122,15 @@ class FileTableFormatter extends FileFormatterBase {
*/
public function settingsSummary() {
$includes_header = $this->getSetting('header');
$summary[] = t('Files include a header row: @header', [
'@header' => empty($includes_header) ? t('No') : t('Yes'),
$summary[] = $this->t('Files include a header row: @header', [
'@header' => empty($includes_header) ? $this->t('No') : $this->t('Yes'),
]);
if (!empty($this->getSetting('use_text_format')) && !empty($this->getSetting('text_format'))) {
$format = $this->entityTypeManager->getStorage('filter_format')->load($this->getSetting('text_format'));
$summary[] = $this->t('Use text format: @format', [
'@format' => $format->label(),
]);
}
return $summary;
}
......@@ -64,9 +143,11 @@ class FileTableFormatter extends FileFormatterBase {
if ($files = $this->getEntitiesToView($items, $langcode)) {
$includes_header = $this->getSetting('header');
$processor = \Drupal::service('file_table_formatter.processor');
$text_format = !empty($this->getSetting('use_text_format')) && !empty($this->getSetting('text_format'))
? $this->getSetting('text_format')
: NULL;
foreach ($files as $delta => $file) {
$table_data = $processor->getTableDataFromFile($file, $includes_header);
$table_data = $this->fileTableFormatterProcessor->getTableDataFromFile($file, $includes_header, $text_format);
$elements[$delta] = [
'#theme' => 'file_table_formatter_table',
'#data' => $table_data,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment