From 13eb3b02b87e23a4b546f1bca23d70d203b5e407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=BDborn=C3=BD=20Adam?= Date: Wed, 18 May 2022 15:06:38 +0200 Subject: [PATCH] Fix PHPStan and PHPCS --- composer.json | 6 +- phpcs.xml | 4 + phpstan-baseline.neon | 402 ---------- phpstan.neon | 2 - .../CsvMap/Exception/BadConfigException.php | 3 + .../CsvMap/Exception/BadDataException.php | 3 + .../CsvMap/Exception/CsvMapperException.php | 21 +- src/Keboola/CsvMap/Mapper.php | 247 +++--- .../CsvMap/MapperEmptyRelationTest.php | 52 +- .../MapperNotAllowedPrimaryKeyValueTest.php | 18 +- tests/Keboola/CsvMap/MapperShorthandTest.php | 30 +- tests/Keboola/CsvMap/MapperTest.php | 715 +++++++++++------- tests/Keboola/CsvMap/MapperWrongPathTest.php | 52 +- 13 files changed, 724 insertions(+), 831 deletions(-) create mode 100644 phpcs.xml delete mode 100644 phpstan-baseline.neon delete mode 100644 phpstan.neon diff --git a/composer.json b/composer.json index 0f71fc6..22ca4f8 100755 --- a/composer.json +++ b/composer.json @@ -23,9 +23,9 @@ "phpunit/phpunit": ">=7.5" }, "scripts": { - "phpstan": "phpstan analyse ./src ./tests --level=max --no-progress -c phpstan.neon", - "phpcs": "phpcs -n --ignore=vendor --extensions=php --standard=psr2 .", - "phpcbf": "phpcbf -n --ignore=vendor --extensions=php --standard=psr2 .", + "phpstan": "phpstan analyse ./src ./tests --level=8 --no-progress", + "phpcs": "phpcs -n --ignore=vendor --extensions=php .", + "phpcbf": "phpcbf -n --ignore=vendor --extensions=php .", "phplint": "parallel-lint -j 10 --exclude vendor .", "tests": "phpunit", "build": [ diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 0000000..67e37cf --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,4 @@ + + + + diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon deleted file mode 100644 index b8fd386..0000000 --- a/phpstan-baseline.neon +++ /dev/null @@ -1,402 +0,0 @@ -parameters: - ignoreErrors: - - - message: "#^Method Keboola\\\\CsvMap\\\\Exception\\\\CsvMapperException\\:\\:getData\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: src/Keboola/CsvMap/Exception/CsvMapperException.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Exception\\\\CsvMapperException\\:\\:setData\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Keboola/CsvMap/Exception/CsvMapperException.php - - - - message: "#^Property Keboola\\\\CsvMap\\\\Exception\\\\CsvMapperException\\:\\:\\$data has no type specified\\.$#" - count: 1 - path: src/Keboola/CsvMap/Exception/CsvMapperException.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:__construct\\(\\) has parameter \\$mapping with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:__construct\\(\\) has parameter \\$type with no type specified\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:addParentPK\\(\\) has no return type specified\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:addParentPK\\(\\) has parameter \\$colName with no type specified\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:checkPrimaryKeyValues\\(\\) has no return type specified\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:checkPrimaryKeyValues\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:expandShorthandDefinitions\\(\\) has no return type specified\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:getHeader\\(\\) has no return type specified\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:getParser\\(\\) has parameter \\$key with no type specified\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:getParser\\(\\) has parameter \\$settings with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:getParser\\(\\) should return static\\(Keboola\\\\CsvMap\\\\Mapper\\) but returns Keboola\\\\CsvMap\\\\Mapper\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:getPrimaryKey\\(\\) has no return type specified\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:getPrimaryKeyValues\\(\\) has no return type specified\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:getPrimaryKeyValues\\(\\) has parameter \\$row with no type specified\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:getPrimaryKeyValues\\(\\) has parameter \\$userData with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:getResultFile\\(\\) has no return type specified\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:mapRow\\(\\) has no return type specified\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:mapRow\\(\\) has parameter \\$row with no type specified\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:mapRow\\(\\) has parameter \\$userData with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:parse\\(\\) has no return type specified\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:parse\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:parse\\(\\) has parameter \\$userData with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:parseRow\\(\\) has no return type specified\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:parseRow\\(\\) has parameter \\$userData with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:setParentKey\\(\\) has no return type specified\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:setParentKey\\(\\) has parameter \\$colName with no type specified\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:setParentKey\\(\\) has parameter \\$keys with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Property Keboola\\\\CsvMap\\\\Mapper\\:\\:\\$mapping type has no value type specified in iterable type array\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Property Keboola\\\\CsvMap\\\\Mapper\\:\\:\\$parentKey type has no value type specified in iterable type array\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Property Keboola\\\\CsvMap\\\\Mapper\\:\\:\\$result \\(Keboola\\\\CsvTable\\\\Table\\) in empty\\(\\) is not falsy\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Unsafe usage of new static\\(\\)\\.$#" - count: 1 - path: src/Keboola/CsvMap/Mapper.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperEmptyRelationTest\\:\\:getSampleDataMulti\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperEmptyRelationTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperEmptyRelationTest\\:\\:getSampleDataMultiFirstEmpty\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperEmptyRelationTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperEmptyRelationTest\\:\\:getSampleDataSimple\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperEmptyRelationTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperEmptyRelationTest\\:\\:testParseEmptyRelation\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperEmptyRelationTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperEmptyRelationTest\\:\\:testParseEmptyRelationFew\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperEmptyRelationTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperNotAllowedPrimaryKeyValueTest\\:\\:getSampleData\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperNotAllowedPrimaryKeyValueTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperNotAllowedPrimaryKeyValueTest\\:\\:testNotAllowedPrimaryKeyValue\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperNotAllowedPrimaryKeyValueTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperShorthandTest\\:\\:getSampleData\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperShorthandTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperShorthandTest\\:\\:testParseShorthand\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperShorthandTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperShorthandTest\\:\\:testParseShorthandWithRelation\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperShorthandTest.php - - - - message: "#^Cannot access offset 0 on array\\\\|false\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:getMixedData\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:getSampleData\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:getSampleDataSimple\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testArrayItemToColumn\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testArrayToString\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testArrayToTable\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testChildSameParser\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testDataInjection\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testDataInjectionNoData\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testDataInjectionPK\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testDeepNestedTable\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testDisableParentKey\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testDontWriteHeader\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testEmptyArray\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testEmptyString\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testMixedDataError\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testNoDestinationNestedTable\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testNoDestinationTable\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testNoMappingKeyColumn\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testNoTableMapping\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testObjectToColumnError\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testObjectToTable\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testParentKeyDestination\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testParentKeyPK\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testParse\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testParseCompositePK\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testParseNoPK\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testPrimaryKey\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testStringToArray\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testUserDataPropagation\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperWrongPathTest\\:\\:getSampleDataMulti\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperWrongPathTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperWrongPathTest\\:\\:getSampleDataSimple\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperWrongPathTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperWrongPathTest\\:\\:testParseWrongBothMainAndRelation\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperWrongPathTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperWrongPathTest\\:\\:testParseWrongMain\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperWrongPathTest.php - - - - message: "#^Method Keboola\\\\CsvMap\\\\MapperWrongPathTest\\:\\:testParseWrongRelation\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/Keboola/CsvMap/MapperWrongPathTest.php - diff --git a/phpstan.neon b/phpstan.neon deleted file mode 100644 index 2ee6a55..0000000 --- a/phpstan.neon +++ /dev/null @@ -1,2 +0,0 @@ -includes: - - phpstan-baseline.neon diff --git a/src/Keboola/CsvMap/Exception/BadConfigException.php b/src/Keboola/CsvMap/Exception/BadConfigException.php index 7c72e49..200e08d 100644 --- a/src/Keboola/CsvMap/Exception/BadConfigException.php +++ b/src/Keboola/CsvMap/Exception/BadConfigException.php @@ -1,4 +1,7 @@ $data + */ + protected array $data = []; /** - * @return array + * @return array */ - public function getData() + public function getData(): array { return $this->data; } /** - * @param array $data - * @return $this + * @param array $data */ - public function setData(array $data) + public function setData(array $data): self { $this->data = $data; diff --git a/src/Keboola/CsvMap/Mapper.php b/src/Keboola/CsvMap/Mapper.php index bc3a0d1..2ffc8d3 100644 --- a/src/Keboola/CsvMap/Mapper.php +++ b/src/Keboola/CsvMap/Mapper.php @@ -1,51 +1,44 @@ |string> */ - protected $mapping; + protected array $mapping; - /** - * @var bool - */ - protected $writeHeader; + protected bool $writeHeader; - /** - * @var string - */ - protected $type; + protected string $type; - /** - * @var Table - */ - protected $result; + protected Table $result; /** * @var Mapper[] */ - protected $parsers = []; + protected array $parsers = []; /** - * @var array + * @var array */ - protected $parentKey; + protected array $parentKey; + + protected string $parentPK; /** - * @var string + * @param array|string> $mapping */ - protected $parentPK; - - public function __construct(array $mapping, bool $writeHeader = true, $type = 'root') + public function __construct(array $mapping, bool $writeHeader = true, string $type = 'root') { $this->mapping = $mapping; $this->writeHeader = $writeHeader; @@ -57,21 +50,29 @@ public function __construct(array $mapping, bool $writeHeader = true, $type = 'r /** * Expands shorthand definitions to theirs full definition */ - private function expandShorthandDefinitions() + private function expandShorthandDefinitions(): void { foreach ($this->mapping as $key => $settings) { if (is_string($key) && is_string($settings)) { $this->mapping[$key] = [ 'type' => 'column', 'mapping' => [ - 'destination' => $settings - ] + 'destination' => $settings, + ], ]; } } } - public function parse(array $data, array $userData = []) + /** + * @param array|object> $data + * @param array $userData + * @throws \Keboola\CsvMap\Exception\BadConfigException + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Csv\Exception + * @throws \Keboola\Utils\Exception + */ + public function parse(array $data, array $userData = []): void { // Create a file, even if there is no data $this->getResultFile(); @@ -82,9 +83,13 @@ public function parse(array $data, array $userData = []) } /** - * @param object|mixed $row + * @param array $userData + * @throws \Keboola\CsvMap\Exception\BadConfigException + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Csv\Exception + * @throws \Keboola\Utils\Exception */ - public function parseRow($row, array $userData = []) + public function parseRow(mixed $row, array $userData = []): void { $file = $this->getResultFile(); $mappedRow = $this->mapRow($row, $userData); @@ -92,7 +97,7 @@ public function parseRow($row, array $userData = []) try { $file->writeRow($mappedRow); } catch (CsvException $e) { - if ($e->getCode() != 3) { + if ($e->getCode() !== 3) { throw $e; } @@ -104,71 +109,81 @@ public function parseRow($row, array $userData = []) } $badCols = join(',', array_keys($columns)); - $exception = new BadDataException("Error writing '{$badCols}' column: " . $e->getMessage(), 0, $e); + $exception = new BadDataException("Error writing '$badCols' column: " . $e->getMessage(), 0, $e); $exception->setData(['bad_columns' => $columns]); throw $exception; } } - protected function mapRow($row, array $userData) + /** + * @param array $userData + * @return array + * @throws \Keboola\CsvMap\Exception\BadConfigException + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Csv\Exception + * @throws \Keboola\Utils\Exception + */ + protected function mapRow(mixed $row, array $userData): array { $result = []; foreach ($this->mapping as $key => $settings) { - $delimiter = empty($settings['delimiter']) ? '.' : $settings['delimiter']; + $delimiter = empty($settings['delimiter']) ? '.' : (string) $settings['delimiter']; // Empty key means "self", ... it is useful to map scalar array values // Eg. row = {"actors":["Patrick Wilson","Rose Byrne","Barbara Hershey"]} // mapping = {"actors: {"type": "table", "destination": "actor", "tableMapping": {"": "name:} } - $propertyValue = $key === '' && is_scalar($row) ? $row : getDataFromPath($key, $row, $delimiter); + $propertyValue = is_object($row) || is_array($row) ? getDataFromPath($key, $row, $delimiter) : $row; - if (empty($settings['type'])) { - $settings['type'] = 'column'; - } - switch ($settings['type']) { - case 'table': - $tableParser = $this->getParser($settings, $key); + if (is_array($settings)) { + if (empty($settings['type'])) { + $settings['type'] = 'column'; + } + switch ($settings['type']) { + case 'table': + $tableParser = $this->getParser($settings, $key); + + if (empty($this->getPrimaryKey()) && empty($propertyValue)) { + if (empty($settings['parentKey']['disable'])) { + $result[$settings['destination']] = null; + } + break; + } + + $primaryKeyValue = $this->getPrimaryKeyValues($row, $userData); + $this->checkPrimaryKeyValues($primaryKeyValue); - if (empty($this->getPrimaryKey()) && empty($propertyValue)) { if (empty($settings['parentKey']['disable'])) { - $result[$settings['destination']] = null; + if (empty($this->getPrimaryKey())) { + $result[$settings['destination']] = join(',', $primaryKeyValue); + } + $parentKeyCol = empty($settings['parentKey']['destination']) + ? $this->type . '_pk' + : $settings['parentKey']['destination']; + + $tableParser->setParentKey($primaryKeyValue, $parentKeyCol); + if (!empty($settings['parentKey']['primaryKey'])) { + $tableParser->addParentPK($parentKeyCol); + } } - break; - } - $primaryKeyValue = $this->getPrimaryKeyValues($row, $userData); - $this->checkPrimaryKeyValues($primaryKeyValue); - - if (empty($settings['parentKey']['disable'])) { - if (empty($this->getPrimaryKey())) { - $result[$settings['destination']] = join(',', $primaryKeyValue); + // If propertyValue != array, wrap it + if (!is_array($propertyValue)) { + $propertyValue = [$propertyValue]; } - $parentKeyCol = empty($settings['parentKey']['destination']) - ? $this->type . '_pk' - : $settings['parentKey']['destination']; + $tableParser->parse($propertyValue, $userData); - $tableParser->setParentKey($primaryKeyValue, $parentKeyCol); - if (!empty($settings['parentKey']['primaryKey'])) { - $tableParser->addParentPK($parentKeyCol); + break; + case 'user': + $result[$settings['mapping']['destination']] = getDataFromPath($key, $userData); + break; + case 'column': + default: + if (!is_scalar($propertyValue) && !is_null($propertyValue) && !empty($settings['forceType'])) { + $propertyValue = json_encode($propertyValue); } - } - - // If propertyValue != array, wrap it - if (!is_array($propertyValue)) { - $propertyValue = [$propertyValue]; - } - $tableParser->parse($propertyValue, $userData); - - break; - case 'user': - $result[$settings['mapping']['destination']] = \Keboola\Utils\getDataFromPath($key, $userData); - break; - case 'column': - default: - if (!is_scalar($propertyValue) && !is_null($propertyValue) && !empty($settings['forceType'])) { - $propertyValue = json_encode($propertyValue); - } - - $result[$settings['mapping']['destination']] = $propertyValue; - break; + + $result[$settings['mapping']['destination']] = $propertyValue; + break; + } } } if (!empty($this->parentKey)) { @@ -178,7 +193,11 @@ protected function mapRow($row, array $userData) return $result; } - private function checkPrimaryKeyValues(array $values) + /** + * @param array $values + * @throws \Keboola\CsvMap\Exception\BadConfigException + */ + private function checkPrimaryKeyValues(array $values): void { foreach ($values as $value) { if (!is_scalar($value) && !is_null($value)) { @@ -189,7 +208,10 @@ private function checkPrimaryKeyValues(array $values) } } - public function getPrimaryKey() + /** + * @return array + */ + public function getPrimaryKey(): array { $primaryKey = []; foreach ($this->mapping as $path => $settings) { @@ -204,7 +226,12 @@ public function getPrimaryKey() return $primaryKey; } - protected function getPrimaryKeyValues($row, array $userData) + /** + * @param array $userData + * @return array + * @throws \Keboola\Utils\Exception + */ + protected function getPrimaryKeyValues(mixed $row, array $userData): array { $values = []; if (empty($this->getPrimaryKey())) { @@ -215,13 +242,13 @@ protected function getPrimaryKeyValues($row, array $userData) } } else { foreach ($this->getPrimaryKey() as $path => $column) { - if (!empty($this->parentKey) && $column == key($this->parentKey)) { + if (!empty($this->parentKey) && $column === key($this->parentKey)) { $values[] = $this->parentKey[$column]; - } elseif (!empty($this->mapping[$path]['type']) && $this->mapping[$path]['type'] == 'user') { + } elseif (!empty($this->mapping[$path]['type']) && $this->mapping[$path]['type'] === 'user') { $values[] = $userData[$path]; } else { $delimiter = empty($this->mapping[$path]['delimiter']) ? '.' : $this->mapping[$path]['delimiter']; - $values[] = \Keboola\Utils\getDataFromPath($path, $row, $delimiter); + $values[] = getDataFromPath($path, $row, $delimiter); } } } @@ -229,7 +256,10 @@ protected function getPrimaryKeyValues($row, array $userData) return $values; } - public function setParentKey(array $keys, $colName) + /** + * @param array $keys + */ + public function setParentKey(array $keys, string $colName): void { $this->parentKey = [$colName => join(',', $keys)]; } @@ -237,17 +267,18 @@ public function setParentKey(array $keys, $colName) /** * Add parent identifier to PK */ - public function addParentPK($colName) + public function addParentPK(string $colName): void { $this->parentPK = $colName; } /** - * @return static + * @param array $settings + * @throws \Keboola\CsvMap\Exception\BadConfigException */ - protected function getParser(array $settings, $key) + protected function getParser(array $settings, string $key): Mapper { - if (!empty($settings['destination']) && $settings['destination'] == $this->type) { + if (!empty($settings['destination']) && $settings['destination'] === $this->type) { if (empty($settings['parentKey']['disable'])) { throw new BadConfigException( "'parentKey.disable' must be true to parse child values into parent's table" @@ -259,18 +290,23 @@ protected function getParser(array $settings, $key) foreach (['tableMapping', 'destination'] as $requiredKey) { if (empty($settings[$requiredKey])) { - throw new BadConfigException("Key '{$requiredKey}' is not set for table '{$key}'."); + throw new BadConfigException("Key '$requiredKey' is not set for table '$key'."); } } if (empty($this->parsers[$settings['destination']])) { $this->parsers[$settings['destination']] = - new static($settings['tableMapping'], $this->writeHeader, $settings['destination']); + new self($settings['tableMapping'], $this->writeHeader, $settings['destination']); } return $this->parsers[$settings['destination']]; } - protected function getResultFile() + /** + * @throws \Keboola\Csv\InvalidArgumentException + * @throws \Keboola\Csv\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + */ + protected function getResultFile(): Table { if (empty($this->result)) { $this->result = new Table($this->type, $this->getHeader(), $this->writeHeader); @@ -280,23 +316,27 @@ protected function getResultFile() return $this->result; } - protected function getHeader() + /** + * @return array + * @throws \Keboola\CsvMap\Exception\BadConfigException + */ + protected function getHeader(): array { $header = []; foreach ($this->mapping as $key => $settings) { if (empty($settings['type']) - || $settings['type'] == 'column' - || $settings['type'] == 'user' + || $settings['type'] === 'column' + || $settings['type'] === 'user' ) { if (empty($settings['mapping']['destination'])) { - throw new BadConfigException("Key 'mapping.destination' is not set for column '{$key}'."); + throw new BadConfigException("Key 'mapping.destination' is not set for column '$key'."); } $header[] = $settings['mapping']['destination']; - } elseif ($settings['type'] == 'table' && empty($this->getPrimaryKey())) { + } elseif ($settings['type'] === 'table' && empty($this->getPrimaryKey())) { // TODO child table link to generate if (empty($settings['destination'])) { - throw new BadConfigException("Key 'destination' is not set for table '{$key}'."); + throw new BadConfigException("Key 'destination' is not set for table '$key'."); } if (empty($settings['parentKey']['disable'])) { @@ -312,22 +352,23 @@ protected function getHeader() /** * Return own result and all children - * @return Table[] + * @return array + * @throws \Keboola\Csv\InvalidArgumentException + * @throws \Keboola\Csv\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException */ - public function getCsvFiles() + public function getCsvFiles(): array { $childResults = []; - foreach ($this->parsers as $type => $parser) { + foreach ($this->parsers as $parser) { $childResults += $parser->getCsvFiles(); } - $results = array_merge( + return array_merge( [ - $this->type => $this->result + $this->type => $this->getResultFile(), ], $childResults ); - - return $results; } } diff --git a/tests/Keboola/CsvMap/MapperEmptyRelationTest.php b/tests/Keboola/CsvMap/MapperEmptyRelationTest.php index 9cc7e98..11b6dd3 100644 --- a/tests/Keboola/CsvMap/MapperEmptyRelationTest.php +++ b/tests/Keboola/CsvMap/MapperEmptyRelationTest.php @@ -1,12 +1,20 @@ [ @@ -14,7 +22,7 @@ public function testParseEmptyRelation() 'mapping' => [ 'destination' => 'pk', 'primaryKey' => true, - ] + ], ], 'timestamp' => 'timestamp', 'reactions' => [ @@ -23,8 +31,8 @@ public function testParseEmptyRelation() 'tableMapping' => [ 'user.id' => 'id', 'user.username' => 'username', - ] - ] + ], + ], ]; // one row @@ -41,7 +49,6 @@ public function testParseEmptyRelation() $this->assertFileExists($file1->getPathname()); $this->assertEquals($expected1, file_get_contents($file1->getPathname())); - $file2 = $parser->getCsvFiles()['reactions']; $expected2 = <<assertFileExists($file1->getPathname()); $this->assertEquals($expected1, file_get_contents($file1->getPathname())); - $file2 = $parser->getCsvFiles()['reactions']; - $expected2 = <<assertFileExists($file2->getPathname()); $this->assertEquals($expected2, file_get_contents($file2->getPathname())); } - public function testParseEmptyRelationFew() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\Csv\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + */ + public function testParseEmptyRelationFew(): void { $mapping = [ 'id' => [ @@ -83,7 +92,7 @@ public function testParseEmptyRelationFew() 'mapping' => [ 'destination' => 'pk', 'primaryKey' => true, - ] + ], ], 'timestamp' => 'timestamp', 'reactions' => [ @@ -92,8 +101,8 @@ public function testParseEmptyRelationFew() 'tableMapping' => [ 'user.id' => 'id', 'user.username' => 'username', - ] - ] + ], + ], ]; // multiple rows @@ -113,7 +122,6 @@ public function testParseEmptyRelationFew() $this->assertFileExists($file1->getPathname()); $this->assertEquals($expected1, file_get_contents($file1->getPathname())); - $file2 = $parser->getCsvFiles()['reactions']; $expected2 = <<assertEquals($expected2, file_get_contents($file2->getPathname())); } - protected function getSampleDataSimple() + /** + * @return array> + */ + protected function getSampleDataSimple(): array { $json = <<> + */ + protected function getSampleDataMulti(): array { $json = <<> + */ + protected function getSampleDataMultiFirstEmpty(): array { $json = << [ @@ -18,15 +23,15 @@ public function testNotAllowedPrimaryKeyValue() 'mapping' => [ 'destination' => 'id', 'primaryKey' => true, - ] + ], ], 'coord' => [ 'type' => 'table', 'destination' => 'coord', 'tableMapping' => [ 'a' => 'a', - ] - ] + ], + ], ]; $data = $this->getSampleData(); @@ -37,7 +42,10 @@ public function testNotAllowedPrimaryKeyValue() $parser->parse($data); } - protected function getSampleData() + /** + * @return array + */ + protected function getSampleData(): array { $json = << 'id', @@ -27,7 +35,13 @@ public function testParseShorthand() $this->assertEquals($expected, file_get_contents($file->getPathname())); } - public function testParseShorthandWithRelation() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + * @throws \Keboola\Csv\Exception + */ + public function testParseShorthandWithRelation(): void { $config = [ 'id' => [ @@ -35,7 +49,7 @@ public function testParseShorthandWithRelation() 'mapping' => [ 'destination' => 'pk', 'primaryKey' => true, - ] + ], ], 'timestamp' => 'timestamp', 'reactions' => [ @@ -44,8 +58,8 @@ public function testParseShorthandWithRelation() 'tableMapping' => [ 'user.id' => 'id', 'user.username' => 'username', - ] - ] + ], + ], ]; $data = $this->getSampleData(); @@ -60,7 +74,6 @@ public function testParseShorthandWithRelation() CSV; $this->assertEquals($expected1, file_get_contents($file1->getPathname())); - $file2 = $parser->getCsvFiles()['reactions']; $expected2 = <<assertEquals($expected2, file_get_contents($file2->getPathname())); } - protected function getSampleData() + /** + * @return array> + */ + protected function getSampleData(): array { $json = << [ 'type' => 'column', 'mapping' => [ - 'destination' => 'timestamp' - ] + 'destination' => 'timestamp', + ], ], 'id' => [ 'type' => 'column', 'mapping' => [ 'destination' => 'post_id', - 'primaryKey' => true - ] + 'primaryKey' => true, + ], ], 'user.id' => [ 'type' => 'column', 'mapping' => [ - 'destination' => 'user_id' - ] + 'destination' => 'user_id', + ], ], 'reactions' => [ 'type' => 'table', @@ -37,17 +45,17 @@ public function testParse() 'user/id' => [ 'type' => 'column', 'mapping' => [ - 'destination' => 'user_id' + 'destination' => 'user_id', ], - 'delimiter' => '/' - ] + 'delimiter' => '/', + ], ], // 'parentKey' => [ // 'primaryKey' => true, // //'columns' => ['id', 'user_id'], // //'hash' => true // ] - ] + ], ]; $data = $this->getSampleData(); @@ -62,26 +70,32 @@ public function testParse() } } - public function testParseNoPK() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + * @throws \Keboola\Csv\Exception + */ + public function testParseNoPK(): void { $config = [ 'timestamp' => [ 'type' => 'column', 'mapping' => [ - 'destination' => 'timestamp' - ] + 'destination' => 'timestamp', + ], ], 'id' => [ 'type' => 'column', 'mapping' => [ - 'destination' => 'post_id' - ] + 'destination' => 'post_id', + ], ], 'user.id' => [ 'type' => 'column', 'mapping' => [ - 'destination' => 'user_id' - ] + 'destination' => 'user_id', + ], ], 'reactions' => [ 'type' => 'table', @@ -90,11 +104,11 @@ public function testParseNoPK() 'user.id' => [ 'type' => 'column', 'mapping' => [ - 'destination' => 'user_id' - ] - ] - ] - ] + 'destination' => 'user_id', + ], + ], + ], + ], ]; $data = $this->getSampleData(); @@ -109,28 +123,34 @@ public function testParseNoPK() } } - public function testParseCompositePK() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + * @throws \Keboola\Csv\Exception + */ + public function testParseCompositePK(): void { $config = [ 'timestamp' => [ 'type' => 'column', 'mapping' => [ - 'destination' => 'timestamp' - ] + 'destination' => 'timestamp', + ], ], 'id' => [ 'type' => 'column', 'mapping' => [ 'destination' => 'post_id', - 'primaryKey' => true - ] + 'primaryKey' => true, + ], ], 'user.id' => [ 'type' => 'column', 'mapping' => [ 'destination' => 'user_id', - 'primaryKey' => true - ] + 'primaryKey' => true, + ], ], 'reactions' => [ 'type' => 'table', @@ -139,11 +159,11 @@ public function testParseCompositePK() 'user.id' => [ 'type' => 'column', 'mapping' => [ - 'destination' => 'user_id' - ] - ] - ] - ] + 'destination' => 'user_id', + ], + ], + ], + ], ]; $data = $this->getSampleData(); @@ -157,15 +177,21 @@ public function testParseCompositePK() } } - public function testParentKeyPK() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + * @throws \Keboola\Csv\Exception + */ + public function testParentKeyPK(): void { $config = [ 'id' => [ 'type' => 'column', 'mapping' => [ 'destination' => 'post_id', - 'primaryKey' => true - ] + 'primaryKey' => true, + ], ], 'reactions' => [ 'type' => 'table', @@ -175,14 +201,14 @@ public function testParentKeyPK() 'type' => 'column', 'mapping' => [ 'destination' => 'user_id', - 'primaryKey' => true - ] - ] + 'primaryKey' => true, + ], + ], ], 'parentKey' => [ - 'primaryKey' => true - ] - ] + 'primaryKey' => true, + ], + ], ]; $data = $this->getSampleData(); @@ -194,15 +220,21 @@ public function testParentKeyPK() $this->assertEquals(['user_id', 'root_pk'], $result['post_reactions']->getPrimaryKey(true)); } - public function testParentKeyDestination() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + * @throws \Keboola\Csv\Exception + */ + public function testParentKeyDestination(): void { $config = [ 'id' => [ 'type' => 'column', 'mapping' => [ 'destination' => 'post_id', - 'primaryKey' => true - ] + 'primaryKey' => true, + ], ], 'reactions' => [ 'type' => 'table', @@ -212,14 +244,14 @@ public function testParentKeyDestination() 'type' => 'column', 'mapping' => [ 'destination' => 'user_id', - 'primaryKey' => true - ] - ] + 'primaryKey' => true, + ], + ], ], 'parentKey' => [ - 'destination' => 'post_id' - ] - ] + 'destination' => 'post_id', + ], + ], ]; $data = $this->getSampleData(); @@ -228,16 +260,26 @@ public function testParentKeyDestination() $parser->parse($data); $result = $parser->getCsvFiles(); - $this->assertEquals('"user_id","post_id"' . PHP_EOL, file($result['post_reactions']->getPathName())[0]); + $file = file($result['post_reactions']->getPathName()); + if ($file === false) { + $this->fail(); + } + $this->assertEquals('"user_id","post_id"' . PHP_EOL, $file[0]); } - public function testEmptyArray() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\Csv\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + */ + public function testEmptyArray(): void { $config = [ 'id' => [ 'mapping' => [ - 'destination' => 'id' - ] + 'destination' => 'id', + ], ], 'arr' => [ 'type' => 'table', @@ -245,17 +287,17 @@ public function testEmptyArray() 'tableMapping' => [ 'child_id' => [ 'mapping' => [ - 'destination' => 'child_id' - ] - ] - ] - ] + 'destination' => 'child_id', + ], + ], + ], + ], ]; $data = [ - (object)[ - 'id' => 1 - ] + (object) [ + 'id' => 1, + ], ]; $parser = new Mapper($config); @@ -265,29 +307,35 @@ public function testEmptyArray() $this->assertEquals(['"id","children"' . PHP_EOL, '"1",""' . PHP_EOL], file($result['root']->getPathName())); } - public function testEmptyString() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\Csv\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + */ + public function testEmptyString(): void { $config = [ 'id' => [ 'mapping' => [ - 'destination' => 'id' - ] + 'destination' => 'id', + ], ], 'str' => [ 'mapping' => [ - 'destination' => 'text' - ] - ] + 'destination' => 'text', + ], + ], ]; $data = [ - (object)[ + (object) [ 'id' => 1, - 'str' => 'asdf' + 'str' => 'asdf', + ], + (object) [ + 'id' => 2, ], - (object)[ - 'id' => 2 - ] ]; $parser = new Mapper($config); @@ -298,34 +346,40 @@ public function testEmptyString() [ '"id","text"' . PHP_EOL, '"1","asdf"' . PHP_EOL, - '"2",""' . PHP_EOL + '"2",""' . PHP_EOL, ], file($result['root']->getPathName()) ); } - public function testPrimaryKey() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + * @throws \Keboola\Csv\Exception + */ + public function testPrimaryKey(): void { $config = [ 'timestamp' => [ 'type' => 'column', 'mapping' => [ - 'destination' => 'timestamp' - ] + 'destination' => 'timestamp', + ], ], 'id' => [ 'type' => 'column', 'mapping' => [ 'destination' => 'post_id', - 'primaryKey' => true - ] + 'primaryKey' => true, + ], ], 'user.id' => [ 'type' => 'column', 'mapping' => [ - 'destination' => 'user_id' - ] - ] + 'destination' => 'user_id', + ], + ], ]; $data = $this->getSampleData(); @@ -337,13 +391,18 @@ public function testPrimaryKey() $this->assertEquals(['post_id'], $result['root']->getPrimaryKey(true)); } - public function testNoMappingKeyColumn() + /** + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Csv\Exception + */ + public function testNoMappingKeyColumn(): void { $config = [ 'timestamp' => [ - 'type' => 'column' - ] + 'type' => 'column', + ], ]; $data = $this->getSampleData(); @@ -355,13 +414,18 @@ public function testNoMappingKeyColumn() $parser->parse($data); } - public function testNoDestinationTable() + /** + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Csv\Exception + */ + public function testNoDestinationTable(): void { $config = [ 'arr' => [ - 'type' => 'table' - ] + 'type' => 'table', + ], ]; $data = $this->getSampleData(); @@ -372,13 +436,18 @@ public function testNoDestinationTable() $parser->parse($data); } - public function testNoTableMapping() + /** + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Csv\Exception + */ + public function testNoTableMapping(): void { $config = [ 'reactions' => [ 'type' => 'table', - 'destination' => 'children' - ] + 'destination' => 'children', + ], ]; $data = $this->getSampleData(); @@ -389,7 +458,12 @@ public function testNoTableMapping() $parser->parse($data); } - public function testNoDestinationNestedTable() + /** + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Csv\Exception + */ + public function testNoDestinationNestedTable(): void { $config = [ 'reactions' => [ @@ -397,11 +471,11 @@ public function testNoDestinationNestedTable() 'tableMapping' => [ 'child_id' => [ 'mapping' => [ - 'destination' => 'child_id' - ] - ] - ] - ] + 'destination' => 'child_id', + ], + ], + ], + ], ]; $data = $this->getSampleData(); @@ -412,20 +486,26 @@ public function testNoDestinationNestedTable() $parser->parse($data); } - public function testDataInjection() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + * @throws \Keboola\Csv\Exception + */ + public function testDataInjection(): void { $config = [ 'id' => [ 'mapping' => [ - 'destination' => 'id' - ] + 'destination' => 'id', + ], ], 'userData' => [ 'type' => 'user', 'mapping' => [ - 'destination' => 'userCol' - ] - ] + 'destination' => 'userCol', + ], + ], ]; $data = $this->getSampleData(); @@ -437,20 +517,26 @@ public function testDataInjection() $this->assertEquals( [ '"id","userCol"' . PHP_EOL, - '"1","blah"' . PHP_EOL + '"1","blah"' . PHP_EOL, ], file($result['root']->getPathName()) ); } - public function testDataInjectionPK() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + * @throws \Keboola\Csv\Exception + */ + public function testDataInjectionPK(): void { $config = [ 'id' => [ 'mapping' => [ 'destination' => 'id', - 'primaryKey' => true - ] + 'primaryKey' => true, + ], ], 'reactions' => [ 'type' => 'table', @@ -459,18 +545,18 @@ public function testDataInjectionPK() 'user.id' => [ 'type' => 'column', 'mapping' => [ - 'destination' => 'user_id' - ] - ] - ] + 'destination' => 'user_id', + ], + ], + ], ], 'userData' => [ 'type' => 'user', 'mapping' => [ 'destination' => 'userCol', - 'primaryKey' => true - ] - ] + 'primaryKey' => true, + ], + ], ]; $data = $this->getSampleData(); @@ -482,7 +568,7 @@ public function testDataInjectionPK() $this->assertEquals( [ '"id","userCol"' . PHP_EOL, - '"1","blah"' . PHP_EOL + '"1","blah"' . PHP_EOL, ], file($result['root']->getPathName()) ); @@ -492,26 +578,32 @@ public function testDataInjectionPK() [ '"user_id","root_pk"' . PHP_EOL, '"456","1,blah"' . PHP_EOL, - '"789","1,blah"' . PHP_EOL + '"789","1,blah"' . PHP_EOL, ], file($result['post_reactions']->getPathName()) ); } - public function testDataInjectionNoData() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\Csv\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + */ + public function testDataInjectionNoData(): void { $config = [ 'id' => [ 'mapping' => [ - 'destination' => 'id' - ] + 'destination' => 'id', + ], ], 'userData' => [ 'type' => 'user', 'mapping' => [ - 'destination' => 'userCol' - ] - ] + 'destination' => 'userCol', + ], + ], ]; $data = $this->getSampleData(); @@ -523,21 +615,27 @@ public function testDataInjectionNoData() $this->assertEquals( [ '"id","userCol"' . PHP_EOL, - '"1",""' . PHP_EOL + '"1",""' . PHP_EOL, ], file($result['root']->getPathName()) ); } - public function testUserDataPropagation() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + * @throws \Keboola\Csv\Exception + */ + public function testUserDataPropagation(): void { $data = $this->getSampleData(); $config = [ 'id' => [ 'mapping' => [ - 'destination' => 'id' - ] + 'destination' => 'id', + ], ], 'user' => [ 'type' => 'table', @@ -546,36 +644,36 @@ public function testUserDataPropagation() 'id' => [ 'mapping' => [ 'destination' => 'id', - 'primaryKey' => true - ] + 'primaryKey' => true, + ], ], 'username' => [ 'mapping' => [ - 'destination' => 'username' - ] + 'destination' => 'username', + ], ], 'keboola_source' => [ 'type' => 'user', 'mapping' => [ - 'destination' => 'keboola_source' - ] - ] + 'destination' => 'keboola_source', + ], + ], ], 'parentKey' => [ - 'disable' => true - ] + 'disable' => true, + ], ], 'user.id' => [ 'mapping' => [ - 'destination' => 'user_id' - ] + 'destination' => 'user_id', + ], ], 'keboola_source' => [ 'type' => 'user', 'mapping' => [ - 'destination' => 'keboola_source' - ] - ] + 'destination' => 'keboola_source', + ], + ], ]; $parser = new Mapper($config); @@ -586,23 +684,29 @@ public function testUserDataPropagation() $this->assertEquals([ '"id","user_id","keboola_source"' . PHP_EOL, - '"1","123","search"' . PHP_EOL + '"1","123","search"' . PHP_EOL, ], file($result['root']->getPathName())); $this->assertEquals([ '"id","username","keboola_source"' . PHP_EOL, - '"123","alois","search"' . PHP_EOL + '"123","alois","search"' . PHP_EOL, ], file($result['users']->getPathName())); } - public function testObjectToTable() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\Csv\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + */ + public function testObjectToTable(): void { $data = $this->getSampleData(); $config = [ 'id' => [ 'mapping' => [ - 'destination' => 'id' - ] + 'destination' => 'id', + ], ], 'user' => [ 'type' => 'table', @@ -611,24 +715,24 @@ public function testObjectToTable() 'id' => [ 'mapping' => [ 'destination' => 'id', - 'primaryKey' => true - ] + 'primaryKey' => true, + ], ], 'username' => [ 'mapping' => [ - 'destination' => 'username' - ] - ] + 'destination' => 'username', + ], + ], ], 'parentKey' => [ - 'disable' => true - ] + 'disable' => true, + ], ], 'user.id' => [ 'mapping' => [ - 'destination' => 'user_id' - ] - ] + 'destination' => 'user_id', + ], + ], ]; $parser = new Mapper($config); @@ -645,15 +749,21 @@ public function testObjectToTable() ); } - public function testDisableParentKey() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + * @throws \Keboola\Csv\Exception + */ + public function testDisableParentKey(): void { $config = [ 'id' => [ 'type' => 'column', 'mapping' => [ - 'destination' => 'post_id' - ] + 'destination' => 'post_id', + ], ], 'reactions' => [ 'type' => 'table', @@ -662,14 +772,14 @@ public function testDisableParentKey() 'user.id' => [ 'type' => 'column', 'mapping' => [ - 'destination' => 'user_id' - ] - ] + 'destination' => 'user_id', + ], + ], ], 'parentKey' => [ - 'disable' => true - ] - ] + 'disable' => true, + ], + ], ]; $data = $this->getSampleData(); @@ -680,48 +790,54 @@ public function testDisableParentKey() $this->assertEquals([ '"post_id"' . PHP_EOL, - '"1"' . PHP_EOL + '"1"' . PHP_EOL, ], file($result['root']->getPathName())); $this->assertEquals([ '"user_id"' . PHP_EOL, '"456"' . PHP_EOL, - '"789"' . PHP_EOL + '"789"' . PHP_EOL, ], file($result['post_reactions']->getPathName())); } - public function testChildSameParser() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\Csv\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + */ + public function testChildSameParser(): void { $data = [ - (object)[ + (object) [ 'id' => 1, - 'child' => (object)[ - 'id' => 1.1 + 'child' => (object) [ + 'id' => 1.1, ], 'arrChild' => [ // redundant? - (object)['id' => '1.2'] - ] - ] + (object) ['id' => '1.2'], + ], + ], ]; $config = [ 'id' => [ 'mapping' => [ - 'destination' => 'post_id' - ] + 'destination' => 'post_id', + ], ], 'child' => [ 'type' => 'table', 'destination' => 'items', 'parentKey' => [ - 'disable' => true - ] + 'disable' => true, + ], ], 'arrChild' => [ 'type' => 'table', 'destination' => 'items', 'parentKey' => [ - 'disable' => true - ] - ] + 'disable' => true, + ], + ], ]; $parser = new Mapper($config, true, 'items'); @@ -732,26 +848,32 @@ public function testChildSameParser() '"post_id"' . PHP_EOL, '"1.1"' . PHP_EOL, '"1.2"' . PHP_EOL, - '"1"' . PHP_EOL + '"1"' . PHP_EOL, ], file($result['items']->getPathName())); } - public function testArrayItemToColumn() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\Csv\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + */ + public function testArrayItemToColumn(): void { $config = [ 'arr.0' => [ 'mapping' => [ - 'destination' => 'first_arr_item' - ] - ] + 'destination' => 'first_arr_item', + ], + ], ]; $data = [ - (object)[ + (object) [ 'arr' => [ - 'one', 'two' - ] - ] + 'one', 'two', + ], + ], ]; $parser = new Mapper($config); @@ -763,14 +885,19 @@ public function testArrayItemToColumn() ); } - public function testObjectToColumnError() + /** + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + * @throws \Keboola\Csv\Exception + */ + public function testObjectToColumnError(): void { $config = [ 'user' => [ 'mapping' => [ - 'destination' => 'user' - ] - ] + 'destination' => 'user', + ], + ], ]; $parser = new Mapper($config); @@ -780,7 +907,13 @@ public function testObjectToColumnError() $parser->parse($this->getSampleData()); } - public function testDeepNestedTable() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + * @throws \Keboola\Csv\Exception + */ + public function testDeepNestedTable(): void { $config = [ 'id' => 'id', @@ -793,27 +926,27 @@ public function testDeepNestedTable() 'type' => 'table', 'destination' => 'grandchild', 'tableMapping' => [ - 'id' => 'gcid' - ] - ] - ] - ] + 'id' => 'gcid', + ], + ], + ], + ], ]; $data = [ - (object)[ + (object) [ 'id' => 1, 'child' => [ - (object)[ + (object) [ 'id' => 2, 'grandchild' => [ - (object)[ - 'id' => 3 - ] - ] - ] - ] - ] + (object) [ + 'id' => 3, + ], + ], + ], + ], + ], ]; $parser = new Mapper($config); @@ -822,16 +955,21 @@ public function testDeepNestedTable() $this->assertEquals(['root', 'child', 'grandchild'], array_keys($parser->getCsvFiles())); } - public function testMixedDataError() + /** + * @throws \Keboola\Utils\Exception + * @throws \Keboola\Csv\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + */ + public function testMixedDataError(): void { $config = [ 'id' => 'id', 'arr' => [ 'type' => 'column', 'mapping' => [ - 'destination' => 'arrStr' - ] - ] + 'destination' => 'arrStr', + ], + ], ]; $data = $this->getMixedData(); @@ -843,17 +981,23 @@ public function testMixedDataError() $parser->parse($data); } - public function testArrayToString() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + * @throws \Keboola\Csv\Exception + */ + public function testArrayToString(): void { $config = [ 'id' => 'id', 'arr' => [ 'type' => 'column', 'mapping' => [ - 'destination' => 'str' + 'destination' => 'str', ], - 'forceType' => true - ] + 'forceType' => true, + ], ]; $data = $this->getMixedData(); @@ -864,29 +1008,35 @@ public function testArrayToString() $expected = [ '"id","str"' . PHP_EOL, '"1","[1.1,1.2]"' . PHP_EOL, - '"2","2.1"' . PHP_EOL + '"2","2.1"' . PHP_EOL, ]; $this->assertEquals($expected, file($parser->getCsvFiles()['root']->getPathName())); } - public function testStringToArray() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + * @throws \Keboola\Csv\Exception + */ + public function testStringToArray(): void { $config = [ 'id' => [ 'mapping' => [ 'destination' => 'id', - 'primaryKey' => true - ] + 'primaryKey' => true, + ], ], 'arr' => [ 'type' => 'table', 'destination' => 'arr', 'tableMapping' => [ - '.' => 'data' + '.' => 'data', ], - 'forceType' => true - ] + 'forceType' => true, + ], ]; $data = $this->getMixedData(); @@ -897,21 +1047,27 @@ public function testStringToArray() $root = [ '"id"' . PHP_EOL, '"1"' . PHP_EOL, - '"2"' . PHP_EOL + '"2"' . PHP_EOL, ]; $arr = [ '"data","root_pk"' . PHP_EOL, '"1.1","1"' . PHP_EOL, '"1.2","1"' . PHP_EOL, - '"2.1","2"' . PHP_EOL + '"2.1","2"' . PHP_EOL, ]; $this->assertEquals($root, file($parser->getCsvFiles()['root']->getPathName())); $this->assertEquals($arr, file($parser->getCsvFiles()['arr']->getPathName())); } - public function testArrayToTable() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + * @throws \Keboola\Csv\Exception + */ + public function testArrayToTable(): void { $config = [ 'rows' => [ @@ -921,17 +1077,17 @@ public function testArrayToTable() '0' => [ 'type' => 'column', 'mapping' => [ - 'destination' => 'date' - ] + 'destination' => 'date', + ], ], '1' => [ 'type' => 'column', 'mapping' => [ - 'destination' => 'clicks' - ] - ] - ] - ] + 'destination' => 'clicks', + ], + ], + ], + ], ]; $data = json_decode('[{ @@ -947,13 +1103,19 @@ public function testArrayToTable() $expected = [ '"date","clicks","root_pk"' . PHP_EOL, '"2017-05-27","83008","20afe46b23b7afa04d50a036bc3b9021"' . PHP_EOL, - '"2017-05-28","105723","20afe46b23b7afa04d50a036bc3b9021"' . PHP_EOL + '"2017-05-28","105723","20afe46b23b7afa04d50a036bc3b9021"' . PHP_EOL, ]; $this->assertEquals($expected, file($parser->getCsvFiles()['report-rows']->getPathName())); } - public function testDontWriteHeader() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + * @throws \Keboola\Csv\Exception + */ + public function testDontWriteHeader(): void { $mapping = [ 'id' => 'id', @@ -969,6 +1131,12 @@ public function testDontWriteHeader() $this->assertEquals(['id', 'time'], $file->getHeader()); } + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + * @throws \Keboola\Csv\Exception + */ public function testScalarArrayToSeparatedTable(): void { $mapping = [ @@ -977,23 +1145,23 @@ public function testScalarArrayToSeparatedTable(): void 'mapping' => [ 'destination' => 'id', 'primaryKey' => true, - ] + ], ], - "title" => "title", + 'title' => 'title', 'actors' => [ 'type' => 'table', 'destination' => 'actor', 'tableMapping' => [ - '' => 'name' // <<<<< empty string means "self" - ] + '' => 'name', // <<<<< empty string means "self" + ], ], ]; $data = [ - ["id" => 1, "title" => 'Rush', "actors" => ["Daniel Bruhl", "Chris Hemsworth", "Olivia Wilde"]], - ["id" => 2, "title" => 'Prisoners', "actors" => ["Hugh Jackman", "Jake Gyllenhaal", "Viola Davis"]], - ["id" => 3, "title" => 'Insidious 2', "actors" => ["Patrick Wilson", "Rose Byrne", "Barbara Hershey"]] + ['id' => 1, 'title' => 'Rush', 'actors' => ['Daniel Bruhl', 'Chris Hemsworth', 'Olivia Wilde']], + ['id' => 2, 'title' => 'Prisoners', 'actors' => ['Hugh Jackman', 'Jake Gyllenhaal', 'Viola Davis']], + ['id' => 3, 'title' => 'Insidious 2', 'actors' => ['Patrick Wilson', 'Rose Byrne', 'Barbara Hershey']], ]; $parser = new Mapper($mapping); @@ -1007,7 +1175,7 @@ public function testScalarArrayToSeparatedTable(): void '"id","title"' . PHP_EOL, '"1","Rush"' . PHP_EOL, '"2","Prisoners"' . PHP_EOL, - '"3","Insidious 2"' . PHP_EOL + '"3","Insidious 2"' . PHP_EOL, ]; $this->assertEquals($expectedRoot, file($files['root']->getPathName())); @@ -1027,53 +1195,62 @@ public function testScalarArrayToSeparatedTable(): void $this->assertEquals($expectedActor, file($files['actor']->getPathName())); } - protected function getMixedData() + /** + * @return array + */ + protected function getMixedData(): array { return [ - (object)[ + (object) [ 'id' => 1, 'arr' => [ 1.1, - 1.2 - ] + 1.2, + ], ], - (object)[ // poor data + (object) [ // poor data 'id' => 2, - 'arr' => 2.1 - ] + 'arr' => 2.1, + ], ]; } - protected function getSampleData() + /** + * @return array + */ + protected function getSampleData(): array { return [ - (object)[ + (object) [ 'timestamp' => 1234567890, 'id' => 1, 'text' => 'asdf', - 'user' => (object)[ + 'user' => (object) [ 'id' => 123, - 'username' => 'alois' + 'username' => 'alois', ], 'reactions' => [ - (object)[ - 'user' => (object)[ + (object) [ + 'user' => (object) [ 'id' => 456, - 'username' => 'jose' - ] + 'username' => 'jose', + ], ], - (object)[ - 'user' => (object)[ + (object) [ + 'user' => (object) [ 'id' => 789, - 'username' => 'mike' - ] - ] - ] - ] + 'username' => 'mike', + ], + ], + ], + ], ]; } - protected function getSampleDataSimple() + /** + * @return array> + */ + protected function getSampleDataSimple(): array { $json = << 'nonExistent1', @@ -41,7 +49,13 @@ public function testParseWrongMain() $this->assertEquals($expected, file_get_contents($file->getPathname())); } - public function testParseWrongRelation() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + * @throws \Keboola\Csv\Exception + */ + public function testParseWrongRelation(): void { $mapping = [ 'id' => [ @@ -49,7 +63,7 @@ public function testParseWrongRelation() 'mapping' => [ 'destination' => 'pk', 'primaryKey' => true, - ] + ], ], 'timestamp' => 'timestamp', 'nonexistent' => [ @@ -58,8 +72,8 @@ public function testParseWrongRelation() 'tableMapping' => [ 'user.id' => 'id', 'user.username' => 'username', - ] - ] + ], + ], ]; // one row @@ -76,7 +90,6 @@ public function testParseWrongRelation() $this->assertFileExists($file1->getPathname()); $this->assertEquals($expected1, file_get_contents($file1->getPathname())); - $file2 = $parser->getCsvFiles()['nonexistent']; $expected2 = <<assertFileExists($file1->getPathname()); $this->assertEquals($expected1, file_get_contents($file1->getPathname())); - $file2 = $parser->getCsvFiles()['nonexistent']; $expected2 = <<assertEquals($expected2, file_get_contents($file2->getPathname())); } - public function testParseWrongBothMainAndRelation() + /** + * @throws \Keboola\CsvMap\Exception\BadDataException + * @throws \Keboola\Utils\Exception + * @throws \Keboola\Csv\Exception + * @throws \Keboola\CsvMap\Exception\BadConfigException + */ + public function testParseWrongBothMainAndRelation(): void { $mapping = [ 'nonexistent1' => [ @@ -121,7 +139,7 @@ public function testParseWrongBothMainAndRelation() 'mapping' => [ 'destination' => 'nonexistent1', 'primaryKey' => true, - ] + ], ], 'nonexistent2' => 'nonexistent2', 'nonexistent3' => [ @@ -130,8 +148,8 @@ public function testParseWrongBothMainAndRelation() 'tableMapping' => [ 'user.id' => 'id', 'user.username' => 'username', - ] - ] + ], + ], ]; // one row @@ -148,7 +166,6 @@ public function testParseWrongBothMainAndRelation() $this->assertFileExists($file1->getPathname()); $this->assertEquals($expected1, file_get_contents($file1->getPathname())); - $file2 = $parser->getCsvFiles()['nonexistent3']; $expected2 = <<assertFileExists($file1->getPathname()); $this->assertEquals($expected1, file_get_contents($file1->getPathname())); - $file2 = $parser->getCsvFiles()['nonexistent3']; $expected2 = <<assertEquals($expected2, file_get_contents($file2->getPathname())); } - protected function getSampleDataSimple() + /** + * @return array> + */ + protected function getSampleDataSimple(): array { $json = <<> + */ + protected function getSampleDataMulti(): array { $json = <<