From ead61a3fcd75fb09a5b66bace224519fa8d98c8e Mon Sep 17 00:00:00 2001 From: Benjamin Klix Date: Fri, 23 Mar 2018 17:02:11 +0100 Subject: [PATCH] Initial commit with export --- .../Controller/DatabaseStorageController.php | 159 ++++++++++++++++++ Classes/Domain/Model/DatabaseStorage.php | 100 +++++++++++ .../Repository/DatabaseStorageRepository.php | 55 ++++++ Classes/Finishers/DatabaseStorageFinisher.php | 58 +++++++ Configuration/Policy.yaml | 35 ++++ Configuration/Settings.yaml | 9 + Resources/Private/Layouts/Default.html | 14 ++ .../Templates/DatabaseStorage/Index.html | 44 +++++ composer.json | 19 +++ 9 files changed, 493 insertions(+) create mode 100644 Classes/Controller/DatabaseStorageController.php create mode 100644 Classes/Domain/Model/DatabaseStorage.php create mode 100644 Classes/Domain/Repository/DatabaseStorageRepository.php create mode 100644 Classes/Finishers/DatabaseStorageFinisher.php create mode 100644 Configuration/Policy.yaml create mode 100644 Configuration/Settings.yaml create mode 100644 Resources/Private/Layouts/Default.html create mode 100644 Resources/Private/Templates/DatabaseStorage/Index.html create mode 100644 composer.json diff --git a/Classes/Controller/DatabaseStorageController.php b/Classes/Controller/DatabaseStorageController.php new file mode 100644 index 0000000..c4ffbb1 --- /dev/null +++ b/Classes/Controller/DatabaseStorageController.php @@ -0,0 +1,159 @@ + [ + 'extension' => 'xls', + 'mimeType' => 'application/vnd.ms-excel', + ], + 'Xlsx' => [ + 'extension' => 'xlsx', + 'mimeType' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + ], + 'Ods' => [ + 'extension' => 'ods', + 'mimeType' => 'application/vnd.oasis.opendocument.spreadsheet', + ], + 'Csv' => [ + 'extension' => 'csv', + 'mimeType' => '', + ], + 'Html' => [ + 'extension' => 'html', + 'mimeType' => 'text/html', + ], + ]; + + /** + * @Flow\Inject + * @var DatabaseStorageRepository + */ + protected $databaseStorageRepository; + + + /** + * Show list of identifiers + * + * @return void + */ + public function indexAction() + { + $this->view->assign('identifiers', $this->databaseStorageRepository->findStorageidentifiers()); + } + + + /** + * Export all entries for a specific identifier as xls. + * + * @param string $identifier + * @param string $writerType + * + * @return void + */ + public function exportAction(string $identifier, $writerType = 'Xlsx') + { + if (!isset(self::$types[$writerType])) { + throw new WriterException('No writer available for type ' . $writerType . '.', 1521787983); + } + + $entries = $this->databaseStorageRepository->findByStorageidentifier($identifier)->toArray(); + + $dataArray = []; + + $spreadsheet = new Spreadsheet(); + + $spreadsheet->getProperties() + ->setCreator('die wegmeister gmbh') + ->setTitle('Database Export') + ->setSubject('Database Export'); + + $spreadsheet->setActiveSheetIndex(0); + $spreadsheet->getActiveSheet()->setTitle('Database-Export'); + + $titles = []; + $columns = 0; + foreach ($entries[0]->getProperties() as $title => $value) { + $titles[] = $title; + $columns++; + } + + $dataArray[] = $titles; + + + foreach ($entries as $entry) { + $values = []; + + foreach ($entry->getProperties() as $value) { + $values[] = $value; + } + + $dataArray[] = $values; + } + + $spreadsheet->getActiveSheet()->fromArray($dataArray); + + // TODO: Set headline bold + $prefixIndex = 64; + $prefixKey = ''; + for ($i = 0; $i < $columns; $i++) { + $index = $i % 26; + $columnStyle = $spreadsheet->getActiveSheet()->getStyle($prefixKey . chr(65 + $i) . '1'); + $columnStyle->getFont()->setBold(true); + $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'); + } + + header("Pragma: public"); // required + header("Expires: 0"); + header('Cache-Control: max-age=0'); + header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); + header("Cache-Control: private", false); // required for certain browsers + header('Content-Type: ' . self::$types[$writerType]['mimeType']); + header(sprintf( + 'Content-Disposition: attachment; filename="Database-Storage-%s.%s"', + $identifier, + self::$types[$writerType]['extension'] + )); + header("Content-Transfer-Encoding: binary"); + + $writer = IOFactory::createWriter($spreadsheet, $writerType); + $writer->save('php://output'); + exit; + } +} diff --git a/Classes/Domain/Model/DatabaseStorage.php b/Classes/Domain/Model/DatabaseStorage.php new file mode 100644 index 0000000..725797f --- /dev/null +++ b/Classes/Domain/Model/DatabaseStorage.php @@ -0,0 +1,100 @@ + + */ + protected $properties = []; + + /** + * @var \DateTime + * @Flow\Validate(type="NotEmpty") + */ + protected $datetime; + + /** + * Get identifier + * + * @return string + */ + public function getStorageidentifier() + { + return $this->storageidentifier; + } + + /** + * Set the identifier + * @param string $identifier + * @return DatabaseStorage + */ + public function setStorageidentifier(string $identifier) + { + $this->storageidentifier = $identifier; + return $this; + } + + /** + * Get properties + * @return array + */ + public function getProperties() + { + return $this->properties; + } + + /** + * Set properties + * @param array $properties + * @return DatabaseStorage + */ + public function setProperties(array $properties) + { + $this->properties = $properties; + return $this; + } + + /** + * Get datetime + * + * @return \DateTime + */ + public function getDateTime() + { + return $this->datetime; + } + + /** + * Set datetime + * @param \DateTime $datetime + * @return DatabaseStorage + */ + public function setDateTime(\DateTime $datetime) + { + $this->datetime = $datetime; + return $this; + } +} diff --git a/Classes/Domain/Repository/DatabaseStorageRepository.php b/Classes/Domain/Repository/DatabaseStorageRepository.php new file mode 100644 index 0000000..46745ff --- /dev/null +++ b/Classes/Domain/Repository/DatabaseStorageRepository.php @@ -0,0 +1,55 @@ + QueryInterface::ORDER_ASCENDING, + 'datetime' => QueryInterface::ORDER_DESCENDING + ]; + + /** + * @var string + */ + protected $currentIdentifier = false; + + /** + * @var array + */ + protected $identifiers = []; + + + /** + * Find all identifiers. + * + * @return mixed + */ + public function findStorageidentifiers() + { + if ($this->identifiers === []) { + foreach ($this->findAll() as $item) { + if ($this->currentIdentifier !== $item->getStorageidentifier()) { + $this->identifiers[] = $item->getStorageidentifier(); + $this->currentIdentifier = $item->getStorageidentifier(); + } + } + } + + return $this->identifiers; + } +} diff --git a/Classes/Finishers/DatabaseStorageFinisher.php b/Classes/Finishers/DatabaseStorageFinisher.php new file mode 100644 index 0000000..cefca17 --- /dev/null +++ b/Classes/Finishers/DatabaseStorageFinisher.php @@ -0,0 +1,58 @@ +finisherContext->getFormRuntime(); + $formValues = $formRuntime->getFormState()->getFormValues(); + + $identifier = $this->parseOption('identifier'); + if (!$identifier) { + $identifier = '__undefined__'; + } + + $dbStorage = new DatabaseStorage(); + $dbStorage + ->setStorageidentifier($identifier) + ->setProperties($formValues) + ->setDateTime(new \DateTime()); + + $this->databaseStorageRepository->add($dbStorage); + } +} diff --git a/Configuration/Policy.yaml b/Configuration/Policy.yaml new file mode 100644 index 0000000..d454327 --- /dev/null +++ b/Configuration/Policy.yaml @@ -0,0 +1,35 @@ +privilegeTargets: + 'Neos\Flow\Security\Authorization\Privilege\Method\MethodPrivilege': + 'Wegmeister.DatabaseStorage:Backend.DatabaseStorageViewer': + matcher: 'method(Wegmeister\DatabaseStorage\Controller\DatabaseStorageController->(index)Action())' + 'Neos\Flow\Security\Authorization\Privilege\Method\MethodPrivilege': + 'Wegmeister.DatabaseStorage:Backend.DatabaseStorageExporter': + matcher: 'method(Wegmeister\DatabaseStorage\Controller\DatabaseStorageController->(export)Action())' + + +roles: + 'Wegmeister.DatabaseStorage:DatabaseStorageViewer': + privileges: + - + privilegeTarget: + 'Wegmeister.DatabaseStorage:Backend.DatabaseStorageViewer' + permission: GRANT + + 'Wegmeister.DatabaseStorage:DatabaseStorageExporter': + privileges: + - + privilegeTarget: + 'Wegmeister.DatabaseStorage:Backend.DatabaseStorageExporter' + permission: GRANT + + 'Neos.Neos:Administrator': + privileges: + - + privilegeTarget: + 'Wegmeister.DatabaseStorage:Backend.DatabaseStorageViewer' + permission: GRANT + + - + privilegeTarget: + 'Wegmeister.DatabaseStorage:Backend.DatabaseStorageExporter' + permission: GRANT diff --git a/Configuration/Settings.yaml b/Configuration/Settings.yaml new file mode 100644 index 0000000..512bba8 --- /dev/null +++ b/Configuration/Settings.yaml @@ -0,0 +1,9 @@ +Neos: + Neos: + modules: + databaseStorage: + label: 'Database storage' + controller: \Wegmeister\DatabaseStorage\Controller\DatabaseStorageController + description: 'List database storage entries' + icon: icon-database + privilegeTarget: 'Wegmeister.DatabaseStorage:Backend.DatabaseStorageViewer' diff --git a/Resources/Private/Layouts/Default.html b/Resources/Private/Layouts/Default.html new file mode 100644 index 0000000..b10fec4 --- /dev/null +++ b/Resources/Private/Layouts/Default.html @@ -0,0 +1,14 @@ + + + + + <f:render section="Title" /> + + + + + +

+ + + diff --git a/Resources/Private/Templates/DatabaseStorage/Index.html b/Resources/Private/Templates/DatabaseStorage/Index.html new file mode 100644 index 0000000..b39f745 --- /dev/null +++ b/Resources/Private/Templates/DatabaseStorage/Index.html @@ -0,0 +1,44 @@ +{namespace neos=Neos\Neos\ViewHelpers} + + +Database Storage + + + + +
+ + + + + + + + + + + + + + + +
Identifier 
{identifier} +
+ + + +
+
+
+ +

No entries yet.

+
+
+
+
diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..61e42b5 --- /dev/null +++ b/composer.json @@ -0,0 +1,19 @@ +{ + "name": "wegmeister/databasestorage", + "type": "neos-plugin", + "description": "This package adds the ability to store inputs of a form (or other input) into database and export the stored data as xlsx.", + "require": { + "neos/flow": "*", + "phpoffice/phpspreadsheet": "^1.2" + }, + "autoload": { + "psr-4": { + "Wegmeister\\DatabaseStorage\\": "Classes/" + } + }, + "extra": { + "neos": { + "package-key": "Wegmeister.DatabaseStorage" + } + } +}