Skip to content

Commit

Permalink
[FEATURE] Improve handling of additional fields, resolves #69
Browse files Browse the repository at this point in the history
  • Loading branch information
fsuter committed Oct 2, 2020
1 parent 7fa9be7 commit 13df9fe
Show file tree
Hide file tree
Showing 20 changed files with 438 additions and 192 deletions.
4 changes: 4 additions & 0 deletions ChangeLog
@@ -1,3 +1,7 @@
2020-10-02 Francois Suter (Idéative) <typo3@ideative.ch>

* Improve handling of additional fields, resolves #69

2020-09-30 Francois Suter (Idéative) <typo3@ideative.ch>

* Move general configuration to own "space" in the TCA, resolves #140
Expand Down
108 changes: 97 additions & 11 deletions Classes/Domain/Model/Configuration.php
Expand Up @@ -26,6 +26,8 @@
*/
class Configuration
{
public const DO_NOT_SAVE_KEY = '_txexternalimport_doNotSave';

/**
* @var string Name of the table to which the configuration applies
*/
Expand All @@ -51,7 +53,14 @@ class Configuration
*
* TODO: remove once backward-compatibility with "ctrl" section is dropped
*/
protected $obsolete = false;
protected $obsoleteGeneralConfiguration = false;

/**
* @var bool Whether the additional fields configuration is defined in an obsolete way (comma-separated list) or not
*
* TODO: remove once backward-compatibility with comma-separated syntax is dropped
*/
protected $obsoleteAdditionalFieldsConfiguration = false;

/**
* @var int ID of storage page
Expand Down Expand Up @@ -83,6 +92,11 @@ class Configuration
*/
protected $stepUtility;

public function __toString()
{
return self::class;
}

public function injectStepUtility(StepUtility $stepUtility): void
{
$this->stepUtility = $stepUtility;
Expand Down Expand Up @@ -164,17 +178,22 @@ public function setGeneralConfiguration(array $generalConfiguration, $defaultSte
// It is stored in a separate variable as it might be overridden
$this->storagePid = $generalConfiguration['pid'];

// Perform extra processing for additional fields
// Handle old-style configuration (comma-separated list)
// TODO: remove once backward-compatibility is dropped
if (array_key_exists('additionalFields', $generalConfiguration)) {
$additionalFields = GeneralUtility::trimExplode(
$this->setObsoleteAdditionalFieldsConfiguration(true);
$fields = GeneralUtility::trimExplode(
',',
$generalConfiguration['additionalFields'],
true
);
$additionalFields = [];
foreach ($fields as $field) {
$additionalFields[$field] = [
'field' => $field
];
}
$this->setAdditionalFields($additionalFields);
$this->setCountAdditionalFields(
count($additionalFields)
);
}
}

Expand Down Expand Up @@ -260,6 +279,10 @@ public function getColumnConfiguration(): ?array
*/
public function setColumnConfiguration(array $columnConfiguration): void
{
// Merge with additional fields
if (count($this->additionalFields) > 0) {
$columnConfiguration = array_merge($columnConfiguration, $this->additionalFields);
}
$this->columnConfiguration = $columnConfiguration;
$this->sortTransformationProperties();
}
Expand All @@ -278,24 +301,84 @@ public function getConfigurationForColumn($column): array
return [];
}

/**
* Returns the list of columns that must not be saved to the database.
*
* @return array
*/
public function getColumnsExcludedFromSaving(): array
{
$columns = [];
foreach ($this->columnConfiguration as $name => $configuration) {
if (array_key_exists(self::DO_NOT_SAVE_KEY, $configuration)) {
$columns[] = $name;
}
}
return $columns;
}

/**
* Sets the column as excluded from saving to the database or not.
*
* NOTE: by default all columns are saved and all additional fields are excluded from saving
*
* @param string $column Name of the column
* @param bool $flag
* @throws \Cobweb\ExternalImport\Exception\NoSuchColumnException
*/
public function setExcludedFromSavingFlagForColumn($column, $flag): void
{
if (array_key_exists($column, $this->columnConfiguration)) {
$this->columnConfiguration[$column][self::DO_NOT_SAVE_KEY] = $flag;
} else {
throw new \Cobweb\ExternalImport\Exception\NoSuchColumnException(
sprintf(
'The requested column (%s) does not exist.',
$column
),
1601633669
);
}
}

/**
* TODO: remove once backward-compatibility with "ctrl" section is dropped
*
* @return bool
*/
public function isObsolete(): bool
public function isObsoleteGeneralConfiguration(): bool
{
return $this->obsolete;
return $this->obsoleteGeneralConfiguration;
}

/**
* TODO: remove once backward-compatibility with "ctrl" section is dropped
*
* @param bool $obsolete
* @param bool $obsoleteGeneralConfiguration
*/
public function setObsolete(bool $obsolete): void
public function setObsoleteGeneralConfiguration(bool $obsoleteGeneralConfiguration): void
{
$this->obsolete = $obsolete;
$this->obsoleteGeneralConfiguration = $obsoleteGeneralConfiguration;
}

/**
* TODO: remove once backward-compatibility with comma-separated syntax is dropped
*
* @return bool
*/
public function isObsoleteAdditionalFieldsConfiguration(): bool
{
return $this->obsoleteAdditionalFieldsConfiguration;
}

/**
* TODO: remove once backward-compatibility with comma-separated syntax is dropped
*
* @param bool $obsoleteAdditionalFieldsConfiguration
*/
public function setObsoleteAdditionalFieldsConfiguration(bool $obsoleteAdditionalFieldsConfiguration): void
{
$this->obsoleteAdditionalFieldsConfiguration = $obsoleteAdditionalFieldsConfiguration;
}

/**
Expand Down Expand Up @@ -327,6 +410,9 @@ public function getAdditionalFields(): array
*/
public function setAdditionalFields(array $additionalFields): void
{
foreach ($additionalFields as $fieldName => $fieldConfiguration) {
$additionalFields[$fieldName][self::DO_NOT_SAVE_KEY] = true;
}
$this->additionalFields = $additionalFields;
$this->countAdditionalFields = count($additionalFields);
}
Expand Down
84 changes: 44 additions & 40 deletions Classes/Domain/Repository/ConfigurationRepository.php
Expand Up @@ -67,26 +67,51 @@ public function __construct()
}

/**
* Returns the "ctrl" part of the external import configuration for the given table and index.
* Returns the various sections of the external import configuration for the given table and index.
*
* @param string $table Name of the table
* @param string|integer $index Key of the configuration
* @return array The relevant TCA configuration
*/
public function findByTableAndIndex($table, $index): array
{
$configuration = [
'general' => [],
'additionalFields' => [],
'columns' => []
];

// General configuration
if (isset($GLOBALS['TCA'][$table]['external']['general'][$index])) {
return $this->processCtrlConfiguration(
$configuration['general'] = $this->processGeneralConfiguration(
$GLOBALS['TCA'][$table]['external']['general'][$index]
);
}
// Check for legacy configuration
if (isset($GLOBALS['TCA'][$table]['ctrl']['external'][$index])) {
return $this->processCtrlConfiguration(
// Check for legacy general configuration
} elseif (isset($GLOBALS['TCA'][$table]['ctrl']['external'][$index])) {
$configuration['general'] = $this->processGeneralConfiguration(
$GLOBALS['TCA'][$table]['ctrl']['external'][$index]
);
}
return [];

// Load additional fields configuration
if (isset($GLOBALS['TCA'][$table]['external']['additionalFields'][$index])) {
$configuration['additionalFields'] = $GLOBALS['TCA'][$table]['external']['additionalFields'][$index];
}

// Load columns configuration
// Override the configuration index for columns, if so defined
$columnIndex = $configuration['general']['useColumnIndex'] ?? $index;
if (isset($GLOBALS['TCA'][$table]['columns'])) {
$columnsConfiguration = $GLOBALS['TCA'][$table]['columns'];
ksort($columnsConfiguration);
foreach ($columnsConfiguration as $columnName => $columnData) {
if (isset($columnData['external'][$columnIndex])) {
$configuration['columns'][$columnName] = $columnData['external'][$columnIndex];
}
}
}

return $configuration;
}

/**
Expand Down Expand Up @@ -117,28 +142,6 @@ public function isObsoleteGeneralConfiguration($table, $index): bool
);
}

/**
* Returns the columns part of the external import configuration for the given table and index.
*
* @param string $table Name of the table
* @param string|integer $index Key of the configuration
* @return array The relevant TCA configuration
*/
public function findColumnsByTableAndIndex($table, $index): array
{
$columns = [];
if (isset($GLOBALS['TCA'][$table]['columns'])) {
$columnsConfiguration = $GLOBALS['TCA'][$table]['columns'];
ksort($columnsConfiguration);
foreach ($columnsConfiguration as $columnName => $columnData) {
if (isset($columnData['external'][$index])) {
$columns[$columnName] = $columnData['external'][$index];
}
}
}
return $columns;
}

/**
* Finds all synchronizable configurations and returns them ordered by priority.
*
Expand Down Expand Up @@ -231,30 +234,31 @@ public function findAllGroups(): array
*
* @param string $table Name of the table
* @param string|integer $index Key of the configuration
* @param array $defaultSteps List of default steps (if null will be guessed by the Configuration object)
* @param array|null $defaultSteps List of default steps (if null will be guessed by the Configuration object)
* @return Configuration
*/
public function findConfigurationObject($table, $index, $defaultSteps = null): Configuration
{
$configuration = $this->objectManager->get(Configuration::class);
$ctrlConfiguration = $this->findByTableAndIndex($table, $index);
$externalConfiguration = $this->findByTableAndIndex($table, $index);
try {
$configuration->setObsolete(
$configuration->setObsoleteGeneralConfiguration(
$this->isObsoleteGeneralConfiguration($table, $index)
);
} catch (\Exception $e) {
// Nothing to do, the configuration does not exist anyway
}

// Override the configuration index for columns, if so defined
$columnIndex = $ctrlConfiguration['useColumnIndex'] ?? $index;
$columnsConfiguration = $this->findColumnsByTableAndIndex($table, $columnIndex);

// Set the values in the Configuration object
$configuration->setTable($table);
$configuration->setIndex($index);
$configuration->setGeneralConfiguration($ctrlConfiguration, $defaultSteps);
$configuration->setColumnConfiguration($columnsConfiguration);
$configuration->setGeneralConfiguration($externalConfiguration['general'], $defaultSteps);
// NOTE: this test is only necessary as long as we handle old-style configuration in the call above
// TODO: remove once backward-compatibility with "ctrl" section is dropped
if (count($externalConfiguration['additionalFields'])) {
$configuration->setAdditionalFields($externalConfiguration['additionalFields']);
}
$configuration->setColumnConfiguration($externalConfiguration['columns']);
return $configuration;
}

Expand Down Expand Up @@ -392,12 +396,12 @@ public function findGlobalWriteAccess(): string
}

/**
* Performs some processing on the "ctrl" configuration, like taking global values into account.
* Performs some processing on the general configuration, like taking global values into account.
*
* @param array $configuration The external import configuration to process
* @return array The processed configuration
*/
protected function processCtrlConfiguration($configuration): array
protected function processGeneralConfiguration($configuration): array
{
// If the pid is not set in the current configuration, use global storage pid
$pid = 0;
Expand Down
27 changes: 27 additions & 0 deletions Classes/Exception/NoSuchColumnException.php
@@ -0,0 +1,27 @@
<?php
namespace Cobweb\ExternalImport\Exception;

/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/

use TYPO3\CMS\Core\Exception;

/**
* Exception when the requested column does not exist or has no configuration.
*
* @package Cobweb\ExternalImport\Exception
*/
class NoSuchColumnException extends Exception
{

}
15 changes: 6 additions & 9 deletions Classes/Handler/ArrayHandler.php
Expand Up @@ -25,6 +25,12 @@
*/
class ArrayHandler implements DataHandlerInterface
{

public function __toString()
{
return self::class;
}

/**
* Maps the incoming data to an associative array with TCA column names as keys.
*
Expand Down Expand Up @@ -64,15 +70,6 @@ public function handleData($rawData, Importer $importer): array
}
}

// Get additional fields data, if any
if ($configuration->getCountAdditionalFields() > 0) {
foreach ($configuration->getAdditionalFields() as $fieldName) {
if (isset($theRecord[$fieldName])) {
$data[$referenceCounter][$fieldName] = $theRecord[$fieldName];
}
}
}

// If values were found in substructures, denormalize the data
if (count($rows) > 0) {
// First find the longest substructure result
Expand Down

0 comments on commit 13df9fe

Please sign in to comment.