diff --git a/config/schema/file_table_formatter.schema.yml b/config/schema/file_table_formatter.schema.yml new file mode 100644 index 0000000000000000000000000000000000000000..90e32c71925ec30318cf0f801e072f90f446d6c7 --- /dev/null +++ b/config/schema/file_table_formatter.schema.yml @@ -0,0 +1,13 @@ +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' diff --git a/file_table_formatter.module b/file_table_formatter.module index 668e9d59029a0f6df6a18b5c2096cc7955a347a0..f691bfb7a2cb58fd8658c2f6f9e5a62ab05f7a36 100644 --- a/file_table_formatter.module +++ b/file_table_formatter.module @@ -31,4 +31,3 @@ function template_preprocess_file_table_formatter_table(&$variables) { ]; $variables['title'] = $variables['data']->getTitle(); } - diff --git a/src/FileTableData.php b/src/FileTableData.php index 69d7da8bfbe9bd2d5dbb724ea4f0812fce90860d..a835a2f1e8767e880dc43af749ebe9ad78959071 100644 --- a/src/FileTableData.php +++ b/src/FileTableData.php @@ -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; } diff --git a/src/FileTableFormatterProcessor.php b/src/FileTableFormatterProcessor.php index 0275d6330747ea7df6588a1af1681890a073f35c..4275e31bbf2418e928477dd39f63767db17c6f79 100644 --- a/src/FileTableFormatterProcessor.php +++ b/src/FileTableFormatterProcessor.php @@ -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); diff --git a/src/FileTableFormatterProcessorInterface.php b/src/FileTableFormatterProcessorInterface.php index 3acb89cdd01b7366ace55d550e7f04a1329d9935..e14b3df21c8236d053ad0b7b2092109134dbb6e6 100644 --- a/src/FileTableFormatterProcessorInterface.php +++ b/src/FileTableFormatterProcessorInterface.php @@ -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; } diff --git a/src/Plugin/Field/FieldFormatter/FileTableFormatter.php b/src/Plugin/Field/FieldFormatter/FileTableFormatter.php index a9762e9cbe4d93d3f271283ec2c84ad7a06f8792..93b427d3b73061fba1c1e63d60a565c23f7b00b0 100644 --- a/src/Plugin/Field/FieldFormatter/FileTableFormatter.php +++ b/src/Plugin/Field/FieldFormatter/FileTableFormatter.php @@ -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,