Skip to content

Commit

Permalink
[TASK] basic support v13
Browse files Browse the repository at this point in the history
  • Loading branch information
Metzger, Fabian committed Oct 9, 2024
1 parent 35d4a35 commit 3ec4a6d
Show file tree
Hide file tree
Showing 11 changed files with 161 additions and 242 deletions.
89 changes: 47 additions & 42 deletions Classes/Form/Element/DataInputElement.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@
use PhpOffice\PhpSpreadsheet\Reader\Exception as ReaderException;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use TYPO3\CMS\Backend\Form\Element\AbstractFormElement;
use TYPO3\CMS\Backend\Form\NodeFactory;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Page\JavaScriptModuleInstruction;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Resource\FileReference;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Fluid\View\StandaloneView;
Expand All @@ -23,78 +22,84 @@ class DataInputElement extends AbstractFormElement
{
private const DEFAULT_TEMPLATE_PATH = 'EXT:spreadsheets/Resources/Private/Templates/FormElement/DataInput.html';

private readonly ReaderService $readerService;

private readonly ExtractorService $extractorService;
private ReaderService $readerService;

Check failure on line 25 in Classes/Form/Element/DataInputElement.php

View workflow job for this annotation

GitHub Actions / Check Coding Standards (locked, 8.3, ubuntu-latest)

Required promotion of property $readerService.
private ExtractorService $extractorService;

Check failure on line 26 in Classes/Form/Element/DataInputElement.php

View workflow job for this annotation

GitHub Actions / Check Coding Standards (locked, 8.3, ubuntu-latest)

Required promotion of property $extractorService.
private StandaloneView $view;

Check failure on line 27 in Classes/Form/Element/DataInputElement.php

View workflow job for this annotation

GitHub Actions / Check Coding Standards (locked, 8.3, ubuntu-latest)

Required promotion of property $view.

/**
* @var array<string, string>
*/
private array $config;

private readonly StandaloneView $view;

/**
* @param array<mixed> $data
*/
public function __construct(NodeFactory $nodeFactory, array $data)
private array $config = [];

public function __construct(

Check failure on line 34 in Classes/Form/Element/DataInputElement.php

View workflow job for this annotation

GitHub Actions / Check Coding Standards (locked, 8.3, ubuntu-latest)

Expected 1 blank line after method, found 0.
ReaderService $readerService,
ExtractorService $extractorService,
StandaloneView $view
) {
$this->readerService = $readerService;
$this->extractorService = $extractorService;
$this->view = $view;
}
public function setData(array $data): void

Check failure on line 43 in Classes/Form/Element/DataInputElement.php

View workflow job for this annotation

GitHub Actions / Static analysis (locked, 8.3, ubuntu-latest)

Method Hoogi91\Spreadsheets\Form\Element\DataInputElement::setData() has parameter $data with no value type specified in iterable type array.
{
parent::__construct($nodeFactory, $data);
$this->readerService = GeneralUtility::makeInstance(ReaderService::class);
$this->extractorService = GeneralUtility::makeInstance(ExtractorService::class);
$this->config = $this->data['parameterArray']['fieldConf']['config'] ?? [];

$this->view = GeneralUtility::makeInstance(StandaloneView::class);
$this->view->setTemplatePathAndFilename($this->getTemplatePath());
$this->view->assign('inputSize', (int)($this->config['size'] ?? 0));
$this->data = $data;
}

/**
* @return array<mixed> As defined in initializeResultArray() of AbstractNode
* @return array<mixed> As defined in initializeResultArray() of AbstractFormElement
*/
public function render(): array
{
// get initialize result array from parent abstract node
// Access the $data array
$data = $this->data;

// Initialize the result array
$resultArray = $this->initializeResultArray();

// upload fields hasn't been specified
if (array_key_exists($this->config['uploadField'], $this->data['processedTca']['columns'] ?? []) === false) {
// Initialize configuration
$this->config = $data['parameterArray']['fieldConf']['config'] ?? [];

// Set the template path
$this->view->setTemplatePathAndFilename($this->getTemplatePath());
$this->view->assign('inputSize', (int)($this->config['size'] ?? 0));

// Check if upload field is specified
if (!isset($this->config['uploadField']) || !array_key_exists($this->config['uploadField'], $data['processedTca']['columns'] ?? [])) {
$resultArray['html'] = $this->view->assign('missingUploadField', true)->render();

return $resultArray;
}

// return alert if non valid file references were uploaded
// Get valid file references
$references = $this->getValidFileReferences($this->config['uploadField']);
if (empty($references)) {
$resultArray['html'] = $this->view->assign('nonValidReferences', true)->render();

return $resultArray;
}

// register additional assets only when input will be rendered
$resultArray['requireJsModules'][] = JavaScriptModuleInstruction::forRequireJS(
'TYPO3/CMS/Spreadsheets/SpreadsheetDataInput'
)->instance($this->data['parameterArray']['itemFormElName'] ?? null);
$resultArray['stylesheetFiles'] = ['EXT:spreadsheets/Resources/Public/Css/SpreadsheetDataInput.css'];
// Register additional assets only when input will be rendered
/** @var PageRenderer $pageRenderer */
$pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
$pageRenderer->loadJavaScriptModule('@hoogi91/spreadsheets/SpreadsheetDataInput.js');
$pageRenderer->addCssFile('EXT:spreadsheets/Resources/Public/Css/SpreadsheetDataInput.css');

try {
$valueObject = DsnValueObject::createFromDSN($this->data['parameterArray']['itemFormElValue'] ?? '');
$valueObject = DsnValueObject::createFromDSN($data['parameterArray']['itemFormElValue'] ?? '');
} catch (InvalidDataSourceNameException) {
$valueObject = '';
}

$this->view->assignMultiple(
[
'inputName' => $this->data['parameterArray']['itemFormElName'] ?? null,
'inputName' => $data['parameterArray']['itemFormElName'] ?? null,
'config' => $this->config,
'sheetFiles' => $references,
'sheetData' => $this->getFileReferencesSpreadsheetData($references),
'valueObject' => $valueObject,
]
);

// render view and return result array
// Render view and return result array
$resultArray['html'] = $this->view->render();

return $resultArray;
Expand All @@ -107,7 +112,7 @@ private function getTemplatePath(): string
}

$templatePath = GeneralUtility::getFileAbsFileName($this->config['template']);
if (is_file($templatePath) === false) {
if (!is_file($templatePath)) {
return GeneralUtility::getFileAbsFileName(self::DEFAULT_TEMPLATE_PATH);
}

Expand All @@ -128,7 +133,7 @@ private function getValidFileReferences(string $fieldName): array
return [];
}

// filter references by allowed types
// Filter references by allowed types
return array_filter(
$references,
static fn ($reference) => in_array($reference->getExtension(), ReaderService::ALLOWED_EXTENSIONS, true)
Expand All @@ -141,16 +146,16 @@ private function getValidFileReferences(string $fieldName): array
*/
private function getFileReferencesSpreadsheetData(array $references): array
{
// read all spreadsheet from valid file references and filter out invalid references
// Read all spreadsheets from valid file references and filter out invalid references
$spreadsheets = $this->getSpreadsheetsByFileReferences($references);

// get data from file references
// Get data from file references
$sheetData = [];
foreach ($spreadsheets as $fileUid => $spreadsheet) {
$sheetData[$fileUid] = $this->getWorksheetDataFromSpreadsheet($spreadsheet);
}

// convert whole sheet data content to UTF-8
// Convert whole sheet data content to UTF-8
array_walk_recursive(
$sheetData,
static function (&$item): void {
Expand All @@ -174,7 +179,7 @@ private function getSpreadsheetsByFileReferences(array $references): array
try {
$spreadsheets[$reference->getUid()] = $this->readerService->getSpreadsheet($reference);
} catch (ReaderException) {
// ignore reading non-existing or invalid file reference
// Ignore reading non-existing or invalid file reference
}
}

Expand All @@ -195,7 +200,7 @@ private function getWorksheetDataFromSpreadsheet(Spreadsheet $spreadsheet): arra
'cells' => $this->extractorService->rangeToCellArray($worksheet, $worksheetRange),
];
} catch (SpreadsheetException) {
// ignore sheet when an exception occurs
// Ignore sheet when an exception occurs
}
}

Expand Down
15 changes: 8 additions & 7 deletions Classes/Service/ExtractorService.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@

namespace Hoogi91\Spreadsheets\Service;

Check failure on line 5 in Classes/Service/ExtractorService.php

View workflow job for this annotation

GitHub Actions / Check Coding Standards (locked, 8.3, ubuntu-latest)

Expected 1 line after namespace statement, found 2.

Check failure on line 5 in Classes/Service/ExtractorService.php

View workflow job for this annotation

GitHub Actions / Check Coding Standards (locked, 8.3, ubuntu-latest)

Header blocks must be separated by a single blank line

use Hoogi91\Spreadsheets\Domain\ValueObject;

use Iterator;

Check failure on line 8 in Classes/Service/ExtractorService.php

View workflow job for this annotation

GitHub Actions / Check Coding Standards (locked, 8.3, ubuntu-latest)

Expected 1 line before first use statement, found 2.
use PhpOffice\PhpSpreadsheet\Cell\Cell;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Exception as SpreadsheetException;
use PhpOffice\PhpSpreadsheet\Reader\Exception as SpreadsheetReaderException;
use PhpOffice\PhpSpreadsheet\Worksheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Column;
use PhpOffice\PhpSpreadsheet\Worksheet\Row;
use Hoogi91\Spreadsheets\Domain\ValueObject;

Check failure on line 14 in Classes/Service/ExtractorService.php

View workflow job for this annotation

GitHub Actions / Check Coding Standards (locked, 8.3, ubuntu-latest)

Use statements should be sorted alphabetically. The first wrong one is Hoogi91\Spreadsheets\Domain\ValueObject.
use PhpOffice\PhpSpreadsheet\Exception as SpreadsheetException;
use PhpOffice\PhpSpreadsheet\Reader\Exception as SpreadsheetReaderException;
use TYPO3\CMS\Core\Http\ApplicationType;
use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException;
use TYPO3\CMS\Core\Resource\FileRepository;
use TYPO3\CMS\Core\Resource\ResourceFactory;

class ExtractorService
{
Expand All @@ -28,7 +29,7 @@ public function __construct(
private readonly SpanService $spanService,
private readonly RangeService $rangeService,
private readonly ValueMappingService $mappingService,
private readonly FileRepository $fileRepository
private readonly ResourceFactory $resourceFactory
) {
}

Expand All @@ -41,7 +42,7 @@ public function getDataByDsnValueObject(
bool $returnCellRef = false
): ValueObject\ExtractionValueObject {
$spreadsheet = $this->readerService->getSpreadsheet(
$this->fileRepository->findFileReferenceByUid($dsnValue->getFileReference())
$this->resourceFactory->getFileReferenceObject($dsnValue->getFileReference())
);

try {
Expand All @@ -65,7 +66,7 @@ public function getDataByDsnValueObject(
);

return ValueObject\ExtractionValueObject::create($spreadsheet, $cellData);
} catch (SpreadsheetException) {
} catch (SpreadsheetException) {

Check failure on line 69 in Classes/Service/ExtractorService.php

View workflow job for this annotation

GitHub Actions / Check Coding Standards (locked, 8.3, ubuntu-latest)

Expected 1 space after closing brace; 2 found

Check failure on line 69 in Classes/Service/ExtractorService.php

View workflow job for this annotation

GitHub Actions / Check Coding Standards (locked, 8.3, ubuntu-latest)

Duplicate spaces at position 10.
return ValueObject\ExtractionValueObject::create($spreadsheet, []);
}
}
Expand Down
12 changes: 12 additions & 0 deletions Configuration/JavaScriptModules.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

return [
// required import configurations of other extensions,
// in case a module imports from another package
'dependencies' => ['backend'],
'imports' => [
// recursive definiton, all *.js files in this folder are import-mapped
// trailing slash is required per importmap-specification
'@hoogi91/spreadsheets/' => 'EXT:spreadsheets/Resources/Public/JavaScript/',
],
];
6 changes: 6 additions & 0 deletions Configuration/Services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,9 @@ services:

Hoogi91\Spreadsheets\Service\ReaderService:
public: true

Hoogi91\Spreadsheets\Form\Element\DataInputElement:
arguments:
$readerService: '@Hoogi91\Spreadsheets\Service\ReaderService'
$extractorService: '@Hoogi91\Spreadsheets\Service\ExtractorService'
$view: '@TYPO3\CMS\Fluid\View\StandaloneView'
31 changes: 16 additions & 15 deletions Configuration/TCA/Overrides/tt_content.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,29 @@
);
}

// add own assets upload field
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns($table, [
'tx_spreadsheets_assets' => [
'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig(
'tx_spreadsheets_assets',
[
'foreign_table' => 'sys_file_reference',
'appearance' => [
'createNewRelationLinkTitle' => 'LLL:EXT:frontend/Resources/Private/Language/Database.xlf:tt_content.asset_references.addFileReference',
],
'overrideChildTca' => [
'types' => [
'0' => [
'showitem' => '--palette--;;filePalette',
],
'exclude' => 1,
'label' => 'LLL:EXT:' . $extKey . '/Resources/Private/Language/locallang.xlf:tx_spreadsheets_assets.label',
'config' => [
'type' => 'file',
'appearance' => [
'createNewRelationLinkTitle' => 'LLL:EXT:frontend/Resources/Private/Language/Database.xlf:tt_content.asset_references.addFileReference',
],
'overrideChildTca' => [
'types' => [
\TYPO3\CMS\Core\Resource\File::FILETYPE_APPLICATION => [
'showitem' => '--palette--;;filePalette',
],
],
],
implode(',', \Hoogi91\Spreadsheets\Service\ReaderService::ALLOWED_EXTENSIONS)
),
'allowed' => implode(',', \Hoogi91\Spreadsheets\Service\ReaderService::ALLOWED_EXTENSIONS),
'maxitems' => 1, // Adjust this based on how many items can be uploaded
],
],
'tx_spreadsheets_ignore_styles' => [
'exclude' => 1,
'label' => 'LLL:EXT:' . $extKey . '/Resources/Private/Language/locallang.xlf:tca.tx_spreadsheets_ignore_styles.label',
'config' => [
'type' => 'check',
'items' => [
Expand Down
5 changes: 5 additions & 0 deletions Configuration/page.tsconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

// add content element to insert tables in content element wizard
// register template for backend preview rendering
@import 'EXT:spreadsheets/Configuration/PageTSconfig/NewContentElementWizard.typoscript'
@import 'EXT:spreadsheets/Configuration/PageTSconfig/BackendPreview.typoscript'
2 changes: 1 addition & 1 deletion Resources/Private/Assets/JavaScript/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import DSN from './dsn.js';
import Renderer from './renderer.js';
import Spreadsheet from './spreadsheet.js';
import Selector from "./selector.js";
import DocumentService from 'DocumentService';
import DocumentService from '@typo3/core/document-service.js';

class SpreadsheetDataInput {
constructor(element) {
Expand Down
Loading

0 comments on commit 3ec4a6d

Please sign in to comment.