diff --git a/lib/Service/ColumnTypes/IColumnTypeBusiness.php b/lib/Service/ColumnTypes/IColumnTypeBusiness.php index b04fd83414..9e3bcf6acc 100644 --- a/lib/Service/ColumnTypes/IColumnTypeBusiness.php +++ b/lib/Service/ColumnTypes/IColumnTypeBusiness.php @@ -26,7 +26,7 @@ interface IColumnTypeBusiness { public function parseValue($value, ?Column $column): string; /** - * tests if the given string can be parsed to a value of the column type + * tests if the given value can be parsed to a value of the column type * * @param mixed $value * @param Column|null $column @@ -42,4 +42,22 @@ public function canBeParsed($value, ?Column $column): bool; * @param int|null $rowId */ public function validateValue(mixed $value, Column $column, string $userId, int $tableId, ?int $rowId): void; + + /** + * tests if the given string can be parsed to a value/id of the column type + * + * @param mixed $value + * @param Column|null $column + * @return bool + */ + public function canBeParsedDisplayValue($value, ?Column $column): bool; + + /** + * parses the given string to a value/id of the column type + * + * @param mixed $value + * @param Column|null $column + * @return string + */ + public function parseDisplayValue($value, ?Column $column): string; } diff --git a/lib/Service/ColumnTypes/SelectionBusiness.php b/lib/Service/ColumnTypes/SelectionBusiness.php index 7f1be94145..3e252526a3 100644 --- a/lib/Service/ColumnTypes/SelectionBusiness.php +++ b/lib/Service/ColumnTypes/SelectionBusiness.php @@ -23,18 +23,28 @@ public function parseValue($value, ?Column $column = null): string { } $intValue = (int)$value; - if ((string)$intValue === (string)$value) { - // if it seems to be an option ID - foreach ($column->getSelectionOptionsArray() as $option) { - if ($option['id'] === $intValue && $option['label'] !== $value) { - return json_encode($option['id']); - } + if (!is_numeric($value) || $intValue != $value) { + return ''; + } + + foreach ($column->getSelectionOptionsArray() as $option) { + if ($option['id'] === $intValue) { + return json_encode($option['id']); } - } else { - foreach ($column->getSelectionOptionsArray() as $option) { - if ($option['label'] === $value) { - return json_encode($option['id']); - } + } + + return ''; + } + + public function parseDisplayValue($value, ?Column $column = null): string { + if (!$column) { + $this->logger->warning('No column given, but expected on ' . __FUNCTION__ . ' within ' . __CLASS__, ['exception' => new \Exception()]); + return ''; + } + + foreach ($column->getSelectionOptionsArray() as $option) { + if ($option['label'] === $value) { + return json_encode($option['id']); } } @@ -56,22 +66,34 @@ public function canBeParsed($value, ?Column $column = null): bool { } $intValue = (int)$value; - if ((string)$intValue === (string)$value) { - // if it seems to be an option ID - foreach ($column->getSelectionOptionsArray() as $option) { - if ($option['id'] === $intValue && $option['label'] !== $value) { - return true; - } - } - } else { - foreach ($column->getSelectionOptionsArray() as $option) { - if ($option['label'] === $value) { - return true; - } + if (!is_numeric($value) || $intValue != $value) { + return false; + } + + foreach ($column->getSelectionOptionsArray() as $option) { + if ($option['id'] === $intValue) { + return true; } } return false; } + public function canBeParsedDisplayValue($value, ?Column $column = null): bool { + if (!$column) { + $this->logger->warning('No column given, but expected on ' . __FUNCTION__ . ' within ' . __CLASS__, ['exception' => new \Exception()]); + return false; + } + if ($value === null) { + return true; + } + + foreach ($column->getSelectionOptionsArray() as $option) { + if ($option['label'] === $value) { + return true; + } + } + + return false; + } } diff --git a/lib/Service/ColumnTypes/SuperBusiness.php b/lib/Service/ColumnTypes/SuperBusiness.php index adec5bb8b0..8adc22b57c 100644 --- a/lib/Service/ColumnTypes/SuperBusiness.php +++ b/lib/Service/ColumnTypes/SuperBusiness.php @@ -28,6 +28,10 @@ public function parseValue($value, ?Column $column = null): string { return json_encode($value); } + public function parseDisplayValue($value, ?Column $column = null): string { + return $this->parseValue($value, $column); + } + /** * @param mixed $value * @param Column|null $column @@ -41,6 +45,10 @@ public function validateValue(mixed $value, Column $column, string $userId, int // override this method in the child class when needed } + public function canBeParsedDisplayValue($value, ?Column $column = null): bool { + return $this->canBeParsed($value, $column); + } + protected function isValidDate(string $dateString, string $format): bool { try { $dateTime = new DateTime($dateString); diff --git a/lib/Service/ImportService.php b/lib/Service/ImportService.php index c24b144e0d..6d2d4f93db 100644 --- a/lib/Service/ImportService.php +++ b/lib/Service/ImportService.php @@ -367,12 +367,12 @@ private function parseValueByColumnType(string $value, Column $column): string { $businessClassName .= ucfirst($column->getType()) . ucfirst($column->getSubtype()) . 'Business'; /** @var IColumnTypeBusiness $columnBusiness */ $columnBusiness = Server::get($businessClassName); - if (!$columnBusiness->canBeParsed($value, $column)) { + if (!$columnBusiness->canBeParsedDisplayValue($value, $column)) { $this->logger->warning('Value ' . $value . ' could not be parsed for column ' . $column->getTitle()); $this->countParsingErrors++; return ''; } - return $columnBusiness->parseValue($value, $column); + return $columnBusiness->parseDisplayValue($value, $column); } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { $this->logger->debug('Column type business class not found', ['exception' => $e]); } diff --git a/tests/unit/Service/ColumnTypes/SelectionBusinessTest.php b/tests/unit/Service/ColumnTypes/SelectionBusinessTest.php new file mode 100644 index 0000000000..068a55ce0d --- /dev/null +++ b/tests/unit/Service/ColumnTypes/SelectionBusinessTest.php @@ -0,0 +1,135 @@ +logger = $this->createMock(LoggerInterface::class); + $this->selectionBusiness = new SelectionBusiness($this->logger); + + $this->column = $this->createMock(Column::class); + $this->column->method('getSelectionOptionsArray') + ->willReturn([ + ['id' => 1, 'label' => 'Option 1'], + ['id' => 2, 'label' => 'Option 2'], + ['id' => 3, 'label' => 'Option 3'], + ['id' => 4, 'label' => '1'], + ]); + } + + public function parseValueProvider(): array { + return [ + 'valid integer value' => [2, '2'], + 'valid string value' => ['2', '2'], + 'valid string value for numeric option' => ['4', '4'], + 'invalid value' => [5, ''], + 'null value' => [null, ''], + 'empty string' => ['', ''], + 'float value' => [1.5, ''], + 'boolean value' => [true, ''], + 'array value' => [[1], ''], + ]; + } + + /** + * @dataProvider parseValueProvider + */ + public function testParseValue($value, string $expected): void { + $result = $this->selectionBusiness->parseValue($value, $this->column); + $this->assertEquals($expected, $result); + } + + public function parseDisplayValueProvider(): array { + return [ + 'valid label' => ['Option 2', '2'], + 'invalid label' => ['Invalid Option', ''], + 'valid label for numeric option' => ['1', '4'], + 'null value' => [null, ''], + 'empty string' => ['', ''], + 'boolean value' => [true, ''], + 'array value' => [[1], ''], + ]; + } + + /** + * @dataProvider parseDisplayValueProvider + */ + public function testParseDisplayValue($value, string $expected): void { + $result = $this->selectionBusiness->parseDisplayValue($value, $this->column); + $this->assertEquals($expected, $result); + } + + public function canBeParsedProvider(): array { + return [ + 'valid integer 1' => [1, true], + 'valid string 4' => ['4', true], + 'invalid integer' => [5, false], + 'invalid integer 0' => [0, false], + 'null value' => [null, true], + 'empty string' => ['', false], + 'float value' => [1.5, false], + 'boolean value' => [true, false], + 'array value' => [[1], false], + ]; + } + + /** + * @dataProvider canBeParsedProvider + */ + public function testCanBeParsed($value, bool $expected): void { + $result = $this->selectionBusiness->canBeParsed($value, $this->column); + $this->assertEquals($expected, $result); + } + + public function canBeParsedDisplayValueProvider(): array { + return [ + 'valid label' => ['Option 2', true], + 'invalid label' => ['Invalid Option', false], + 'valid label for numeric option' => ['1', true], + 'null value' => [null, true], + 'empty string' => ['', false], + 'boolean value' => [true, false], + 'array value' => [[1], false], + ]; + } + + /** + * @dataProvider canBeParsedDisplayValueProvider + */ + public function testCanBeParsedDisplayValue($value, bool $expected): void { + $result = $this->selectionBusiness->canBeParsedDisplayValue($value, $this->column); + $this->assertEquals($expected, $result); + } + + public function withoutColumnProvider(): array { + return [ + 'parseValue' => ['parseValue', 1, ''], + 'parseDisplayValue' => ['parseDisplayValue', 'Option 1', ''], + 'canBeParsed' => ['canBeParsed', 1, false], + 'canBeParsedDisplayValue' => ['canBeParsedDisplayValue', 'Option 1', false], + ]; + } + + /** + * @dataProvider withoutColumnProvider + */ + public function testMethodsWithoutColumn(string $method, $value, $expected): void { + $result = $this->selectionBusiness->$method($value, null); + $this->assertEquals($expected, $result); + } + +}