
| Current Path : /var/www/html/12park/web/modules/contrib/webform/src/Controller/ |
Linux ift1.ift-informatik.de 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 |
| Current File : /var/www/html/12park/web/modules/contrib/webform/src/Controller/WebformResultsExportController.php |
<?php
namespace Drupal\webform\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Url;
use Drupal\webform\Entity\Webform;
use Drupal\webform\Entity\WebformSubmission;
use Drupal\webform\WebformInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
/**
* Controller routines for webform submission export.
*/
class WebformResultsExportController extends ControllerBase implements ContainerInjectionInterface {
/**
* The MIME type guesser.
*
* @var \Symfony\Component\Mime\MimeTypesInterface
*/
protected $mimeTypeGuesser;
/**
* The webform submission exporter.
*
* @var \Drupal\webform\WebformSubmissionExporterInterface
*/
protected $submissionExporter;
/**
* The webform request handler.
*
* @var \Drupal\webform\WebformRequestInterface
*/
protected $requestHandler;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
$instance = parent::create($container);
$instance->mimeTypeGuesser = $container->get('file.mime_type.guesser');
$instance->submissionExporter = $container->get('webform_submission.exporter');
$instance->requestHandler = $container->get('webform.request');
return $instance;
}
/**
* Returns webform submission as a CSV.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The current request.
*
* @return array|null|\Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
* A response that renders or redirects to the CSV file.
*/
public function index(Request $request) {
[$webform, $source_entity] = $this->requestHandler->getWebformEntities();
$this->submissionExporter->setWebform($webform);
$this->submissionExporter->setSourceEntity($source_entity);
$query = $request->query->all();
unset($query['destination']);
if (isset($query['filename'])) {
$build = $this->formBuilder()->getForm('Drupal\webform\Form\WebformResultsExportForm');
// Redirect to file export.
$file_path = $this->submissionExporter->getFileTempDirectory() . '/' . $query['filename'];
if (file_exists($file_path)) {
$route_name = $this->requestHandler->getRouteName($webform, $source_entity, 'webform.results_export_file');
$route_parameters = $this->requestHandler->getRouteParameters($webform, $source_entity) + ['filename' => $query['filename']];
$file_url = Url::fromRoute($route_name, $route_parameters, ['absolute' => TRUE])->toString();
$this->messenger()->addStatus($this->t('Export creation complete. Your download should begin now. If it does not start, <a href=":href">download the file here</a>. This file may only be downloaded once.', [':href' => $file_url]));
$build['#attached']['html_head'][] = [
[
'#tag' => 'meta',
'#attributes' => [
'http-equiv' => 'refresh',
'content' => '0; url=' . $file_url,
],
],
'webform_results_export_download_file_refresh',
];
}
return $build;
}
elseif ($query && empty($query['ajax_form']) && isset($query['download'])) {
$default_options = $this->submissionExporter->getDefaultExportOptions();
foreach ($query as $key => $value) {
if (isset($default_options[$key]) && is_array($default_options[$key]) && is_string($value)) {
$query[$key] = explode(',', $value);
}
}
if (!empty($query['excluded_columns'])) {
$query['excluded_columns'] = array_combine($query['excluded_columns'], $query['excluded_columns']);
}
$export_options = $query + $default_options;
$this->submissionExporter->setExporter($export_options);
if ($this->submissionExporter->isBatch()) {
static::batchSet($webform, $source_entity, $export_options);
return batch_process($this->requestHandler->getUrl($webform, $source_entity, 'webform.results_export'));
}
else {
$this->submissionExporter->generate();
$file_path = $this->submissionExporter->getExportFilePath();
return $this->downloadFile($file_path, $export_options['download']);
}
}
else {
return $this->formBuilder()->getForm('Drupal\webform\Form\WebformResultsExportForm', $webform);
}
}
/**
* Returns webform submission results as CSV file.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The current request.
* @param string $filename
* CSV file name.
*
* @return array|\Symfony\Component\HttpFoundation\Response
* A response that renders or redirects to the CSV file.
*/
public function file(Request $request, $filename) {
[$webform, $source_entity] = $this->requestHandler->getWebformEntities();
$this->submissionExporter->setWebform($webform);
$this->submissionExporter->setSourceEntity($source_entity);
$file_path = $this->submissionExporter->getFileTempDirectory() . '/' . $filename;
if (!file_exists($file_path)) {
$t_args = [
':href' => $this->requestHandler->getUrl($webform, $source_entity, 'webform.results_export')->toString(),
];
$build = [
'#markup' => $this->t('No export file ready for download. The file may have already been downloaded by your browser. Visit the <a href=":href">download export webform</a> to create a new export.', $t_args),
];
return $build;
}
else {
return $this->downloadFile($file_path);
}
}
/**
* Download generated CSV file.
*
* @param string $file_path
* The paths the generate CSV file.
* @param bool $download
* Download the generated CSV file. Default to TRUE.
*
* @return \Symfony\Component\HttpFoundation\Response
* A response object containing the CSV file.
*/
public function downloadFile($file_path, $download = TRUE) {
$headers = [];
// If the file is not meant to be downloaded, allow CSV files to be
// displayed as plain text.
if (!$download && preg_match('/\.csv$/', $file_path)) {
$headers['Content-Type'] = 'text/plain';
}
$response = new BinaryFileResponse($file_path, 200, $headers, FALSE, $download ? 'attachment' : 'inline');
// Don't delete the file during automated tests.
// @see \Drupal\webform\Tests\WebformResultsExportDownloadTest
// @see \Drupal\Tests\webform_entity_print\Functional\WebformEntityPrintFunctionalTest
if (!drupal_valid_test_ua()) {
$response->deleteFileAfterSend(TRUE);
}
return $response;
}
/* ************************************************************************ */
// Batch functions.
// Using static method to prevent the service container from being serialized.
// Prevents 'AssertionError: The container was serialized.' exception.
/* ************************************************************************ */
/**
* Batch API; Initialize batch operations.
*
* @param \Drupal\webform\WebformInterface|null $webform
* A webform.
* @param \Drupal\Core\Entity\EntityInterface|null $source_entity
* A webform source entity.
* @param array $export_options
* An array of export options.
*
* @see http://www.jeffgeerling.com/blogs/jeff-geerling/using-batch-api-build-huge-csv
*/
public static function batchSet(WebformInterface $webform, ?EntityInterface $source_entity, array $export_options) {
if (!empty($export_options['excluded_columns']) && is_string($export_options['excluded_columns'])) {
$excluded_columns = explode(',', $export_options['excluded_columns']);
$export_options['excluded_columns'] = array_combine($excluded_columns, $excluded_columns);
}
/** @var \Drupal\webform\WebformSubmissionExporterInterface $submission_exporter */
$submission_exporter = \Drupal::service('webform_submission.exporter');
$submission_exporter->setWebform($webform);
$submission_exporter->setSourceEntity($source_entity);
$submission_exporter->setExporter($export_options);
$parameters = [
$webform,
$source_entity,
$export_options,
];
$batch = [
'title' => t('Exporting submissions'),
'init_message' => t('Creating export file'),
'error_message' => t('The export file could not be created because an error occurred.'),
'operations' => [
[['\Drupal\webform\Controller\WebformResultsExportController', 'batchProcess'], $parameters],
],
'finished' => ['\Drupal\webform\Controller\WebformResultsExportController', 'batchFinish'],
];
batch_set($batch);
}
/**
* Batch API callback; Write the header and rows of the export to the export file.
*
* @param \Drupal\webform\WebformInterface $webform
* The webform.
* @param \Drupal\Core\Entity\EntityInterface|null $source_entity
* A webform source entity.
* @param array $export_options
* An associative array of export options.
* @param mixed|array $context
* The batch current context.
*/
public static function batchProcess(WebformInterface $webform, ?EntityInterface $source_entity = NULL, array $export_options = [], &$context = []) {
/** @var \Drupal\webform\WebformSubmissionExporterInterface $submission_exporter */
$submission_exporter = \Drupal::service('webform_submission.exporter');
$submission_exporter->setWebform($webform);
$submission_exporter->setSourceEntity($source_entity);
$submission_exporter->setExporter($export_options);
if (empty($context['sandbox'])) {
$context['sandbox']['progress'] = 0;
$context['sandbox']['offset'] = 0;
$context['sandbox']['max'] = $submission_exporter->getTotal();
// Store entity ids and not the actual webform or source entity in the
// $context to prevent "The container was serialized" errors.
// @see https://www.drupal.org/node/2822023
$context['results']['webform_id'] = $webform->id();
$context['results']['source_entity_type'] = ($source_entity) ? $source_entity->getEntityTypeId() : NULL;
$context['results']['source_entity_id'] = ($source_entity) ? $source_entity->id() : NULL;
$context['results']['export_options'] = $export_options;
$submission_exporter->writeHeader();
}
// Write CSV records.
$query = $submission_exporter->getQuery();
$query->range($context['sandbox']['offset'], $submission_exporter->getBatchLimit());
$entity_ids = $query->execute();
$webform_submissions = WebformSubmission::loadMultiple($entity_ids);
$submission_exporter->writeRecords($webform_submissions);
// Track progress.
$context['sandbox']['progress'] += count($webform_submissions);
$context['sandbox']['offset'] += $submission_exporter->getBatchLimit();
$context['message'] = t('Exported @count of @total submissions…', ['@count' => $context['sandbox']['progress'], '@total' => $context['sandbox']['max']]);
// Track finished, if there are results and progress does not match the
// expected total, calculate finished percentage. A safety guard is added
// if the current run didn't find any results, then consider it finished as
// well. This could happen when records are added ore removed during the
// export.
if ($entity_ids && $context['sandbox']['max'] > 0 && $context['sandbox']['progress'] !== $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
else {
$context['finished'] = 1;
}
}
/**
* Batch API callback; Completed export.
*
* @param bool $success
* TRUE if batch successfully completed.
* @param array $results
* Batch results.
* @param array $operations
* An array of function calls (not used in this function).
*
* @return \Symfony\Component\HttpFoundation\RedirectResponse
* Redirect to download the exported results.
*/
public static function batchFinish($success, array $results, array $operations) {
$webform_id = $results['webform_id'];
$entity_type = $results['source_entity_type'];
$entity_id = $results['source_entity_id'];
/** @var \Drupal\webform\WebformInterface $webform */
$webform = Webform::load($webform_id);
/** @var \Drupal\Core\Entity\EntityInterface|null $source_entity */
$source_entity = ($entity_type && $entity_id) ? \Drupal::entityTypeManager()->getStorage($entity_type)->load($entity_id) : NULL;
/** @var array $export_options */
$export_options = $results['export_options'];
/** @var \Drupal\webform\WebformSubmissionExporterInterface $submission_exporter */
$submission_exporter = \Drupal::service('webform_submission.exporter');
$submission_exporter->setWebform($webform);
$submission_exporter->setSourceEntity($source_entity);
$submission_exporter->setExporter($export_options);
if (!$success) {
$file_path = $submission_exporter->getExportFilePath();
@unlink($file_path);
$archive_path = $submission_exporter->getArchiveFilePath();
@unlink($archive_path);
\Drupal::messenger()->addStatus(t('Finished with an error.'));
}
else {
$submission_exporter->writeFooter();
$filename = $submission_exporter->getExportFileName();
if ($submission_exporter->isArchive()) {
$submission_exporter->writeExportToArchive();
$filename = $submission_exporter->getArchiveFileName();
}
/** @var \Drupal\webform\WebformRequestInterface $request_handler */
$request_handler = \Drupal::service('webform.request');
$redirect_url = $request_handler->getUrl($webform, $source_entity, 'webform.results_export', ['query' => ['filename' => $filename], 'absolute' => TRUE]);
return new RedirectResponse($redirect_url->toString());
}
}
}