Move csv handling to SubmissionService

Signed-off-by: Jonas Rittershofer <jotoeri@users.noreply.github.com>
This commit is contained in:
Jonas Rittershofer 2021-02-08 17:09:04 +01:00
Родитель 7a9961d1c5
Коммит f59d2392f0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: A865740F334316E0
2 изменённых файлов: 196 добавлений и 93 удалений

Просмотреть файл

@ -27,7 +27,6 @@
namespace OCA\Forms\Controller;
use DateTimeZone;
use Exception;
use OCA\Forms\Activity\ActivityManager;
@ -43,6 +42,7 @@ use OCA\Forms\Db\QuestionMapper;
use OCA\Forms\Db\Submission;
use OCA\Forms\Db\SubmissionMapper;
use OCA\Forms\Service\FormsService;
use OCA\Forms\Service\SubmissionService;
use OCP\AppFramework\OCSController;
use OCP\AppFramework\Db\DoesNotExistException;
@ -51,8 +51,6 @@ use OCP\AppFramework\Http\DataDownloadResponse;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCS\OCSBadRequestException;
use OCP\AppFramework\OCS\OCSForbiddenException;
use OCP\IConfig;
use OCP\IDateTimeFormatter;
use OCP\IL10N;
use OCP\ILogger;
use OCP\IRequest;
@ -61,10 +59,6 @@ use OCP\IUserManager;
use OCP\IUserSession;
use OCP\Security\ISecureRandom;
use League\Csv\EscapeFormula;
use League\Csv\Reader;
use League\Csv\Writer;
class ApiController extends OCSController {
protected $appName;
@ -89,11 +83,8 @@ class ApiController extends OCSController {
/** @var FormsService */
private $formsService;
/** @var IConfig */
private $config;
/** @var IDateTimeFormatter */
private $dateTimeFormatter;
/** @var SubmissionService */
private $submissionService;
/** @var IL10N */
private $l10n;
@ -118,8 +109,7 @@ class ApiController extends OCSController {
QuestionMapper $questionMapper,
SubmissionMapper $submissionMapper,
FormsService $formsService,
IConfig $config,
IDateTimeFormatter $dateTimeFormatter,
SubmissionService $submissionService,
IL10N $l10n,
ILogger $logger,
IRequest $request,
@ -135,9 +125,8 @@ class ApiController extends OCSController {
$this->questionMapper = $questionMapper;
$this->submissionMapper = $submissionMapper;
$this->formsService = $formsService;
$this->submissionService = $submissionService;
$this->config = $config;
$this->dateTimeFormatter = $dateTimeFormatter;
$this->l10n = $l10n;
$this->logger = $logger;
$this->userManager = $userManager;
@ -1077,82 +1066,7 @@ class ApiController extends OCSController {
throw new OCSForbiddenException();
}
try {
$submissionEntities = $this->submissionMapper->findByForm($form->getId());
} catch (DoesNotExistException $e) {
// Just ignore, if no Data. Returns empty Submissions-Array
}
$questions = $this->questionMapper->findByForm($form->getId());
$defaultTimeZone = date_default_timezone_get();
$userTimezone = $this->config->getUserValue('core', 'timezone', $this->currentUser->getUID(), $defaultTimeZone);
// Process initial header
$header = [];
$header[] = $this->l10n->t('User display name');
$header[] = $this->l10n->t('Timestamp');
foreach ($questions as $question) {
$header[] = $question->getText();
}
// Init dataset
$data = [];
// Process each answers
foreach ($submissionEntities as $submission) {
$row = [];
// User
$user = $this->userManager->get($submission->getUserId());
if ($user === null) {
$row[] = $this->l10n->t('Anonymous user');
} else {
$row[] = $user->getDisplayName();
}
// Date
$row[] = $this->dateTimeFormatter->formatDateTime($submission->getTimestamp(), 'full', 'full', new DateTimeZone($userTimezone), $this->l10n);
// Answers, make sure we keep the question order
$answers = array_reduce($this->answerMapper->findBySubmission($submission->getId()), function (array $carry, Answer $answer) {
$carry[$answer->getQuestionId()] = $answer->getText();
return $carry;
}, []);
foreach ($questions as $question) {
$row[] = key_exists($question->getId(), $answers)
? $answers[$question->getId()]
: null;
}
$data[] = $row;
}
$fileName = $form->getTitle() . ' (' . $this->l10n->t('responses') . ').csv';
return new DataDownloadResponse($this->array2csv($header, $data), $fileName, 'text/csv');
}
/**
* Convert an array to a csv string
* @param array $array
* @return string
*/
private function array2csv(array $header, array $records): string {
if (empty($header) && empty($records)) {
return '';
}
// load the CSV document from a string
$csv = Writer::createFromString('');
$csv->setOutputBOM(Reader::BOM_UTF8);
$csv->addFormatter(new EscapeFormula());
// insert the header
$csv->insertOne($header);
// insert all the records
$csv->insertAll($records);
return $csv->getContent();
$csv = $this->submissionService->getSubmissionsCsv($hash);
return new DataDownloadResponse($csv['data'], $csv['fileName'], 'text/csv');
}
}

Просмотреть файл

@ -0,0 +1,189 @@
<?php
/**
* @copyright Copyright (c) 2021 Jonas Rittershofer <jotoeri@users.noreply.github.com>
*
* @author John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
* @author Jonas Rittershofer <jotoeri@users.noreply.github.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Forms\Service;
use DateTimeZone;
use OCA\Forms\Db\FormMapper;
use OCA\Forms\Db\QuestionMapper;
use OCA\Forms\Db\SubmissionMapper;
use OCA\Forms\Db\Answer;
use OCA\Forms\Db\AnswerMapper;
use OCP\IConfig;
use OCP\IDateTimeFormatter;
use OCP\IL10N;
use OCP\ILogger;
use OCP\IUserManager;
use OCP\IUserSession;
use League\Csv\EscapeFormula;
use League\Csv\Reader;
use League\Csv\Writer;
class SubmissionService {
/** @var FormMapper */
private $formMapper;
/** @var QuestionMapper */
private $questionMapper;
/** @var SubmissionMapper */
private $submissionMapper;
/** @var AnswerMapper */
private $answerMapper;
/** @var IConfig */
private $config;
/** @var IDateTimeFormatter */
private $dateTimeFormatter;
/** @var IL10N */
private $l10n;
/** @var ILogger */
private $logger;
/** @var IUserManager */
private $userManager;
public function __construct(FormMapper $formMapper,
QuestionMapper $questionMapper,
SubmissionMapper $submissionMapper,
AnswerMapper $answerMapper,
IConfig $config,
IDateTimeFormatter $dateTimeFormatter,
IL10N $l10n,
ILogger $logger,
IUserManager $userManager,
IUserSession $userSession) {
$this->formMapper = $formMapper;
$this->questionMapper = $questionMapper;
$this->submissionMapper = $submissionMapper;
$this->answerMapper = $answerMapper;
$this->config = $config;
$this->dateTimeFormatter = $dateTimeFormatter;
$this->l10n = $l10n;
$this->logger = $logger;
$this->userManager = $userManager;
$this->currentUser = $userSession->getUser();
}
/**
* Create CSV from Submissions to form
* @param string $hash Hash of the form
* @return array Array with 'fileName' and 'data'
*/
public function getSubmissionsCsv(string $hash): array {
$form = $this->formMapper->findByHash($hash);
try {
$submissionEntities = $this->submissionMapper->findByForm($form->getId());
} catch (DoesNotExistException $e) {
// Just ignore, if no Data. Returns empty Submissions-Array
}
$questions = $this->questionMapper->findByForm($form->getId());
$defaultTimeZone = date_default_timezone_get();
$userTimezone = $this->config->getUserValue('core', 'timezone', $this->currentUser->getUID(), $defaultTimeZone);
// Process initial header
$header = [];
$header[] = $this->l10n->t('User display name');
$header[] = $this->l10n->t('Timestamp');
foreach ($questions as $question) {
$header[] = $question->getText();
}
// Init dataset
$data = [];
// Process each answers
foreach ($submissionEntities as $submission) {
$row = [];
// User
$user = $this->userManager->get($submission->getUserId());
if ($user === null) {
$row[] = $this->l10n->t('Anonymous user');
} else {
$row[] = $user->getDisplayName();
}
// Date
$row[] = $this->dateTimeFormatter->formatDateTime($submission->getTimestamp(), 'full', 'full', new DateTimeZone($userTimezone), $this->l10n);
// Answers, make sure we keep the question order
$answers = array_reduce($this->answerMapper->findBySubmission($submission->getId()), function (array $carry, Answer $answer) {
$carry[$answer->getQuestionId()] = $answer->getText();
return $carry;
}, []);
foreach ($questions as $question) {
$row[] = key_exists($question->getId(), $answers)
? $answers[$question->getId()]
: null;
}
$data[] = $row;
}
$fileName = $form->getTitle() . ' (' . $this->l10n->t('responses') . ').csv';
return [
'fileName' => $fileName,
'data' => $this->array2csv($header, $data),
];
}
/**
* Convert an array to a csv string
* @param array $array
* @return string
*/
private function array2csv(array $header, array $records): string {
if (empty($header) && empty($records)) {
return '';
}
// load the CSV document from a string
$csv = Writer::createFromString('');
$csv->setOutputBOM(Reader::BOM_UTF8);
$csv->addFormatter(new EscapeFormula());
// insert the header
$csv->insertOne($header);
// insert all the records
$csv->insertAll($records);
return $csv->getContent();
}
}