-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
TASK: Improve export when form definition changes, allow setting node…
…TypesIgnoredInExport This package only stores the FormElement identifier at the time of form submission in its entry data. This has some drawbacks: * If a field identifier is added or removed later, it breaks the export * The field identifier could be a uuid which makes it hard to read This change improves this as follows: * A unique list of each field identifier of each submission is compiled * The ContentRepository is used to look up the actual field labels if the form still exists. * There is a fallback to the field identifier if the form or field don't exist anymore. Furthermore, the export contains too much information, such as Sections, Captchas (if configured) and possibly sensible information such as Passwords. A new configuration nodeTypesIgnoredInExport is added to prevent the output of fields configured. The following types are excluded by default: - Neos.Form.Builder:Section - Neos.Form.Builder:StaticText - Neos.Form.Builder:Password - Neos.Form.Builder:PasswordWithConfirmation
- Loading branch information
1 parent
d4c7c6a
commit 895cdba
Showing
4 changed files
with
394 additions
and
106 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,8 +5,6 @@ | |
* | ||
* This file is part of the Flow Framework Package "Wegmeister.DatabaseStorage". | ||
* | ||
* PHP version 7 | ||
* | ||
* @category Controller | ||
* @package Wegmeister\DatabaseStorage | ||
* @author Benjamin Klix <[email protected]> | ||
|
@@ -19,8 +17,6 @@ | |
use Neos\Flow\Annotations as Flow; | ||
use Neos\Flow\I18n\Translator; | ||
use Neos\Flow\Mvc\Controller\ActionController; | ||
use Neos\Flow\ResourceManagement\ResourceManager; | ||
use Neos\Flow\ResourceManagement\PersistentResource; | ||
|
||
use Wegmeister\DatabaseStorage\Domain\Model\DatabaseStorage; | ||
use Wegmeister\DatabaseStorage\Domain\Repository\DatabaseStorageRepository; | ||
|
@@ -29,6 +25,7 @@ | |
use PhpOffice\PhpSpreadsheet\Style\Alignment; | ||
use PhpOffice\PhpSpreadsheet\IOFactory; | ||
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException; | ||
use Wegmeister\DatabaseStorage\Service\DatabaseStorageService; | ||
|
||
/** | ||
* The Database Storage controller | ||
|
@@ -45,23 +42,23 @@ class DatabaseStorageController extends ActionController | |
protected static $types = [ | ||
'Xls' => [ | ||
'extension' => 'xls', | ||
'mimeType' => 'application/vnd.ms-excel', | ||
'mimeType' => 'application/vnd.ms-excel', | ||
], | ||
'Xlsx' => [ | ||
'extension' => 'xlsx', | ||
'mimeType' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', | ||
'mimeType' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', | ||
], | ||
'Ods' => [ | ||
'extension' => 'ods', | ||
'mimeType' => 'application/vnd.oasis.opendocument.spreadsheet', | ||
'mimeType' => 'application/vnd.oasis.opendocument.spreadsheet', | ||
], | ||
'Csv' => [ | ||
'extension' => 'csv', | ||
'mimeType' => 'text/csv', | ||
'mimeType' => 'text/csv', | ||
], | ||
'Html' => [ | ||
'extension' => 'html', | ||
'mimeType' => 'text/html', | ||
'mimeType' => 'text/html', | ||
], | ||
]; | ||
|
||
|
@@ -74,12 +71,9 @@ class DatabaseStorageController extends ActionController | |
protected $databaseStorageRepository; | ||
|
||
/** | ||
* Instance of the resource manager. | ||
* | ||
* @Flow\Inject | ||
* @var ResourceManager | ||
* @var DatabaseStorageService | ||
*/ | ||
protected $resourceManager; | ||
protected $databaseStorageService; | ||
|
||
/** | ||
* Instance of the translator interface. | ||
|
@@ -96,7 +90,6 @@ class DatabaseStorageController extends ActionController | |
*/ | ||
protected $settings; | ||
|
||
|
||
/** | ||
* Inject the settings | ||
* | ||
|
@@ -119,7 +112,6 @@ public function indexAction() | |
$this->view->assign('identifiers', $this->databaseStorageRepository->findStorageidentifiers()); | ||
} | ||
|
||
|
||
/** | ||
* List entries of a given storage identifier. | ||
* | ||
|
@@ -130,30 +122,34 @@ public function indexAction() | |
*/ | ||
public function showAction(string $identifier) | ||
{ | ||
$this->databaseStorageService = new DatabaseStorageService($identifier); | ||
|
||
$entries = $this->databaseStorageRepository->findByStorageidentifier($identifier); | ||
$titles = []; | ||
if (isset($entries[0])) { | ||
foreach ($entries[0]->getProperties() as $title => $value) { | ||
$titles[] = $title; | ||
} | ||
foreach ($entries as $entry) { | ||
$properties = $entry->getProperties(); | ||
$formElementLabels = $this->databaseStorageService->getFormElementLabels( | ||
$entries | ||
); | ||
|
||
foreach ($properties as &$value) { | ||
$value = $this->getStringValue($value); | ||
} | ||
if (empty($entries)) { | ||
$this->redirect('index'); | ||
} | ||
|
||
$entry->setProperties($properties); | ||
/** @var DatabaseStorage $entry */ | ||
foreach ($entries as $entry) { | ||
$values = []; | ||
foreach ($formElementLabels as $formElementLabel) { | ||
$values[$formElementLabel] = $this->databaseStorageService->getValueFromEntryProperty( | ||
$entry, | ||
$formElementLabel | ||
); | ||
} | ||
$this->view->assign('identifier', $identifier); | ||
$this->view->assign('titles', $titles); | ||
$this->view->assign('entries', $entries); | ||
$this->view->assign('datetimeFormat', $this->settings['datetimeFormat']); | ||
} else { | ||
$this->redirect('index'); | ||
$entry->setProperties($values); | ||
} | ||
} | ||
|
||
$this->view->assign('identifier', $identifier); | ||
$this->view->assign('titles', $formElementLabels); | ||
$this->view->assign('entries', $entries); | ||
$this->view->assign('datetimeFormat', $this->settings['datetimeFormat']); | ||
} | ||
|
||
/** | ||
* Delete an entry from the list of identifiers. | ||
|
@@ -166,16 +162,24 @@ public function deleteAction(DatabaseStorage $entry) | |
{ | ||
$identifier = $entry->getStorageidentifier(); | ||
$this->databaseStorageRepository->remove($entry); | ||
$this->addFlashMessage($this->translator->translateById('storage.flashmessage.entryRemoved', [], null, null, 'Main', 'Wegmeister.DatabaseStorage')); | ||
$this->addFlashMessage( | ||
$this->translator->translateById( | ||
'storage.flashmessage.entryRemoved', | ||
[], | ||
null, | ||
null, | ||
'Main', | ||
'Wegmeister.DatabaseStorage' | ||
) | ||
); | ||
$this->redirect('show', null, null, ['identifier' => $identifier]); | ||
} | ||
|
||
|
||
/** | ||
* Delete all entries for the given identifier. | ||
* | ||
* @param string $identifier The storage identifier for the entries to be removed. | ||
* @param bool $redirect Redirect to index? | ||
* @param bool $redirect Redirect to index? | ||
* | ||
* @return void | ||
*/ | ||
|
@@ -192,18 +196,26 @@ public function deleteAllAction(string $identifier, bool $redirect = false) | |
|
||
if ($redirect) { | ||
// TODO: Translate flash message. | ||
$this->addFlashMessage($this->translator->translateById('storage.flashmessage.entriesRemoved', [], null, null, 'Main', 'Wegmeister.DatabaseStorage')); | ||
$this->addFlashMessage( | ||
$this->translator->translateById( | ||
'storage.flashmessage.entriesRemoved', | ||
[], | ||
null, | ||
null, | ||
'Main', | ||
'Wegmeister.DatabaseStorage' | ||
) | ||
); | ||
$this->redirect('index'); | ||
} | ||
} | ||
|
||
|
||
/** | ||
* Export all entries for a specific identifier as xls. | ||
* | ||
* @param string $identifier The storage identifier that should be exported. | ||
* @param string $writerType The writer type/export format to be used. | ||
* @param bool $exportDateTime Should the datetime be exported? | ||
* @param string $identifier The storage identifier that should be exported. | ||
* @param string $writerType The writer type/export format to be used. | ||
* @param bool $exportDateTime Should the datetime be exported? | ||
* | ||
* @return void | ||
*/ | ||
|
@@ -213,46 +225,46 @@ public function exportAction(string $identifier, string $writerType = 'Xlsx', bo | |
throw new WriterException('No writer available for type ' . $writerType . '.', 1521787983); | ||
} | ||
|
||
$entries = $this->databaseStorageRepository->findByStorageidentifier($identifier)->toArray(); | ||
$this->databaseStorageService = new DatabaseStorageService($identifier); | ||
|
||
$entries = $this->databaseStorageRepository->findByStorageidentifier($identifier); | ||
|
||
$dataArray = []; | ||
|
||
$spreadsheet = new Spreadsheet(); | ||
|
||
$spreadsheet->getProperties() | ||
->setCreator($this->settings['creator']) | ||
->setTitle($this->settings['title']) | ||
->setSubject($this->settings['subject']); | ||
$spreadsheet->getProperties()->setCreator($this->settings['creator'])->setTitle( | ||
$this->settings['title'] | ||
)->setSubject($this->settings['subject']); | ||
|
||
$spreadsheet->setActiveSheetIndex(0); | ||
$spreadsheet->getActiveSheet()->setTitle($this->settings['title']); | ||
|
||
$titles = []; | ||
$columns = 0; | ||
foreach ($entries[0]->getProperties() as $title => $value) { | ||
$titles[] = $title; | ||
$columns++; | ||
} | ||
$formElementLabels = $this->databaseStorageService->getFormElementLabels( | ||
$entries | ||
); | ||
$columns = count($formElementLabels); | ||
|
||
if ($exportDateTime) { | ||
// TODO: Translate title for datetime | ||
$titles[] = 'DateTime'; | ||
$formElementLabels['DateTime'] = 'DateTime'; | ||
$columns++; | ||
} | ||
|
||
$dataArray[] = $titles; | ||
|
||
$dataArray[] = $formElementLabels; | ||
|
||
/** @var DatabaseStorage $entry */ | ||
foreach ($entries as $entry) { | ||
$values = []; | ||
|
||
foreach ($entry->getProperties() as $value) { | ||
$values[] = $this->getStringValue($value); | ||
foreach ($formElementLabels as $formElementLabel) { | ||
$values[$formElementLabel] = $this->databaseStorageService->getValueFromEntryProperty( | ||
$entry, | ||
$formElementLabel | ||
); | ||
} | ||
|
||
if ($exportDateTime) { | ||
$values[] = $entry->getDateTime()->format($this->settings['datetimeFormat']); | ||
$values['DateTime'] = $entry->getDateTime()->format($this->settings['datetimeFormat']); | ||
} | ||
|
||
$dataArray[] = $values; | ||
} | ||
|
||
|
@@ -265,17 +277,16 @@ public function exportAction(string $identifier, string $writerType = 'Xlsx', bo | |
$index = $i % 26; | ||
$columnStyle = $spreadsheet->getActiveSheet()->getStyle($prefixKey . chr(65 + $index) . '1'); | ||
$columnStyle->getFont()->setBold(true); | ||
$columnStyle->getAlignment() | ||
->setHorizontal(Alignment::HORIZONTAL_CENTER) | ||
->setVertical(Alignment::VERTICAL_CENTER); | ||
$columnStyle->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER)->setVertical( | ||
Alignment::VERTICAL_CENTER | ||
); | ||
|
||
if ($index + 1 > 25) { | ||
$prefixIndex++; | ||
$prefixKey = chr($prefixIndex); | ||
} | ||
} | ||
|
||
|
||
if (ini_get('zlib.output_compression')) { | ||
ini_set('zlib.output_compression', 'Off'); | ||
} | ||
|
@@ -300,41 +311,4 @@ public function exportAction(string $identifier, string $writerType = 'Xlsx', bo | |
exit; | ||
} | ||
|
||
/** | ||
* Internal function to replace value with a string for export / listing. | ||
* | ||
* @param mixed $value The database column value. | ||
* @param int $indent The level of indentation (for array values). | ||
* | ||
* @return string | ||
*/ | ||
protected function getStringValue($value, int $indent = 0): string | ||
{ | ||
if ($value instanceof PersistentResource) { | ||
return $this->resourceManager->getPublicPersistentResourceUri($value) ?: '-'; | ||
} elseif (is_string($value)) { | ||
return $value; | ||
} elseif (is_object($value) && method_exists($value, '__toString')) { | ||
return (string)$value; | ||
} elseif (isset($value['dateFormat'], $value['date'])) { | ||
$timezone = null; | ||
if (isset($value['timezone'])) { | ||
$timezone = new \DateTimeZone($value['timezone']); | ||
} | ||
$dateTime = \DateTime::createFromFormat($value['dateFormat'], $value['date'], $timezone); | ||
return $dateTime->format($this->settings['datetimeFormat']); | ||
} elseif (is_array($value)) { | ||
foreach ($value as &$innerValue) { | ||
$innerValue = $this->getStringValue($innerValue, $indent + 1); | ||
} | ||
$prefix = str_repeat(' ', $indent * 2) . '- '; | ||
return sprintf( | ||
'%s%s', | ||
$prefix, | ||
implode("\r\n" . $prefix, $value) | ||
); | ||
} | ||
|
||
return '-'; | ||
} | ||
} |
Oops, something went wrong.