Skip to content
Snippets Groups Projects

#3445656: Allow import/ export of glossary entries as CSV

Files
21
<?php
namespace Drupal\tmgmt_deepl_glossary\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\tmgmt\TranslatorInterface;
use Drupal\tmgmt_deepl_glossary\Entity\DeeplGlossary;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Response;
use Drupal\tmgmt_deepl_glossary\DeeplGlossaryApiInterface;
/**
* Controller for downloading glossary entries as a CSV file.
*/
class DeeplGlossaryDownloadController extends ControllerBase {
/**
* The DeepL glossary API service.
*
* @var \Drupal\tmgmt_deepl_glossary\DeeplGlossaryApiInterface
*/
protected DeeplGlossaryApiInterface $glossaryApi;
/**
* Constructs the controller.
*
* @param \Drupal\tmgmt_deepl_glossary\DeeplGlossaryApiInterface $glossary_api
* The DeepL glossary API service.
*/
public function __construct(DeeplGlossaryApiInterface $glossary_api) {
$this->glossaryApi = $glossary_api;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container): self {
// @phpstan-ignore-next-line
return new static(
$container->get('tmgmt_deepl_glossary.api'),
);
}
/**
* Downloads the glossary as a CSV file.
*
* @param \Drupal\tmgmt_deepl_glossary\Entity\DeeplGlossary $deepl_glossary
* The glossary entity.
*
* @return \Symfony\Component\HttpFoundation\Response
* The file download response.
*/
public function downloadCsv(DeeplGlossary $deepl_glossary): Response {
// Fetch glossary entries.
$translator = $deepl_glossary->getTranslator();
if ($translator instanceof TranslatorInterface && $deepl_glossary->getGlossaryId() !== NULL) {
$this->glossaryApi->setTranslator($translator);
$entries = $this->glossaryApi->getGlossaryEntries($deepl_glossary->getGlossaryId());
// Build the CSV content.
$csv_data = $this->buildCsv($entries);
// Retrieve glossary metadata.
/** @var string $label */
$label = $deepl_glossary->label();
/** @var string $source_lang */
$source_lang = $deepl_glossary->get('source_lang')->value;
/** @var string $target_lang */
$target_lang = $deepl_glossary->get('target_lang')->value;
// Serve the CSV as a file download.
return $this->serveCsv($label, $csv_data, $source_lang, $target_lang);
}
return new Response('Error while downloading the glossary entries.', 403);
}
/**
* Builds the CSV data from glossary entries.
*
* @param array $entries
* The glossary entries.
*
* @return string
* The CSV content.
*/
protected function buildCsv(array $entries): string {
$output = fopen('php://temp', 'r+');
$csv_data = '';
if ($output != NULL) {
foreach ($entries as $source => $target) {
fputcsv($output, [$source, $target]);
}
rewind($output);
$csv_data = stream_get_contents($output);
fclose($output);
}
return is_string($csv_data) ? $csv_data : '';
}
/**
* Serves the CSV file as a download response.
*
* @param string $label
* The label of the glossary.
* @param string $csv_data
* The CSV content.
* @param string $source_lang
* The source language code.
* @param string $target_lang
* The target language code.
*
* @return \Symfony\Component\HttpFoundation\Response
* The response.
*/
protected function serveCsv(string $label, string $csv_data, string $source_lang, string $target_lang): Response {
// Construct the file name with source and target languages.
$raw_filename = sprintf('%s_%s_to_%s', $label, $source_lang, $target_lang);
// Use the Drupal utility to sanitize the file name.
$filename = $this->sanitizeFilename($raw_filename);
$response = new Response($csv_data);
$response->headers->set('Content-Type', 'text/csv; charset=utf-8');
$response->headers->set('Content-Disposition', 'attachment; filename="' . $filename . '.csv"');
return $response;
}
/**
* Sanitizes a file name for safe usage.
*
* @param string $filename
* The original file name.
*
* @return string
* The sanitized file name.
*/
protected function sanitizeFilename(string $filename): string {
// Replace invalid characters with underscores.
$filename = preg_replace('/[^a-zA-Z0-9_.-]/', '_', $filename);
// Remove multiple consecutive underscores.
$filename = preg_replace('/_+/', '_', strval($filename));
// Trim leading or trailing underscores.
return trim(strval($filename), '_');
}
}
Loading