Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic TYPO3 v13 support #632 #633

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@
{
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 @@
}

$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 @@
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 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 @@
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 @@
'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 @@ -2,20 +2,21 @@

declare(strict_types=1);

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 @@
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 @@
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 @@
);

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
Loading