Skip to content
Permalink
Browse files

Feature: added CSV structural parser/helper

  • Loading branch information
f3l1x committed Oct 28, 2019
1 parent c79a754 commit ac04f2aa76dd5d2823e9108f678ef90e5612be56
@@ -13,6 +13,7 @@ There are many classes in this package. Almost all are extending from `nette/uti
- [Strings](#strings)
- [Urls](#urls)
- [Validators](#validators)
- [CSV](#csv)

## Setup

@@ -38,62 +39,114 @@ services:

Another useful methods added to `DateTime`:

- `setCurrentTime()`
- `setZeroTime() && resetTime()`
- `setMidnight()`
- `setToday()`
- `getFirstDayOfWeek()`
- `getLastDayOfWeek()`
- `getFirstDayOfMonth()`
- `getLastDayOfMonth()`
- `getFirstDayOfYear()`
- `getLastDayOfYear()`
- `DateTime::setCurrentTime()`
- `DateTime::setZeroTime() && resetTime()`
- `DateTime::setMidnight()`
- `DateTime::setToday()`
- `DateTime::getFirstDayOfWeek()`
- `DateTime::getLastDayOfWeek()`
- `DateTime::getFirstDayOfMonth()`
- `DateTime::getLastDayOfMonth()`
- `DateTime::getFirstDayOfYear()`
- `DateTime::getLastDayOfYear()`

## `Fields`

Collections of functions for normalizing input:

- `inn($s)`
- `tin($s)`
- `zip($s)`
- `phone($s)`
- `Fields::inn($s)`
- `Fields::tin($s)`
- `Fields::zip($s)`
- `Fields::phone($s)`

## `FileSystem`

Collection of extra functions:

- `pathalize($path)`
- `extension($file)`
- `purge($dir)`
- `FileSystem::pathalize($path)`
- `FileSystem::extension($file)`
- `FileSystem::purge($dir)`


## `Strings`

Collection of extra functions:

- `replacePrefix($s, $search, $replacement = '')`
- `replaceSuffix($s, $search, $replacement = '')`
- `spaceless($s)`
- `doublespaceless($s)`
- `dashless($s)`
- `slashless($s)`
- `Strings::replacePrefix($s, $search, $replacement = '')`
- `Strings::replaceSuffix($s, $search, $replacement = '')`
- `Strings::spaceless($s)`
- `Strings::doublespaceless($s)`
- `Strings::dashless($s)`
- `Strings::slashless($s)`

## `Urls`

Collection of extra functions:

- `hasFragment($url)`
- `Urls::hasFragment($url)`

## `Validators`

Collection of extra functions:

- `isIco($s)` - trader identification number (Czech only)
- `isRc($s)`- personal identification number (Czech and Slovak only)

- `Validators::isIco($s)` - trader identification number (Czech only)
- `Validators::isRc($s)`- personal identification number (Czech and Slovak only)

## `Http`

Collection of extra functions:

- `metadata($s)` - gets http metadata from string, returns as `[name => content]`
- `Http::metadata($s)` - gets http metadata from string, returns as `[name => content]`

## `CSV`

Csv class helps you transform flat line into the described structure.

Consider this CSV files:

```
"Milan";"Sulc";"HK";"123456";"foo"
"John";"Doe";"Doens";"111111";"bar"
```

Setup scheme according to the columns:

```php
$scheme = [
0 => 'user.name',
1 => 'user.surname',
2 => 'city',
3 => 'extra.id',
4 => 'extra.x',
];
$result = Csv::structural($scheme, __DIR__ . '/some.csv');
```

Result will be like this:

```
0 => [
'user' => [
'name' => 'Milan',
'surname' => 'Sulc',
],
'city' => 'HK',
'extra' => [
'id' => '123456',
'x' => 'foo',
],
],
1 => [
'user' => [
'name' => 'John',
'surname' => 'Doe',
],
'city' => 'Doens',
'extra' => [
'id' => '111111',
'x' => 'bar',
],
],
```
@@ -23,6 +23,7 @@ Extra contribution to [`nette/utils`](https://github.com/nette/utils).
- [Strings](.docs/README.md#strings)
- [Urls](.docs/README.md#urls)
- [Validators](.docs/README.md#validators)
- [CSV](.docs/README.md#csv)

## Versions

@@ -23,8 +23,8 @@
},
"require-dev": {
"nette/di": "~3.0.0",
"ninjify/nunjuck": "^0.2.0",
"ninjify/qa": "^0.9.0",
"ninjify/nunjuck": "^0.3.0",
"ninjify/qa": "^0.10.0",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan-deprecation-rules": "^0.11",
"phpstan/phpstan-nette": "^0.11",
@@ -44,7 +44,7 @@
},
"autoload-dev": {
"psr-4": {
"Tests\\Contributte\\Utils\\": "tests"
"Tests\\Contributte\\Utils\\": "tests/cases/Unit"
}
},
"minimum-stability": "dev",
@@ -8,16 +8,16 @@
</rule>

<!-- Package specific rules -->
<rule ref="SlevomatCodingStandard.Files.TypeNameMatchesFileName">
<properties>
<property name="rootNamespaces" type="array" value="
src=>Contributte\Utils,
tests=>Tests\Contributte\Utils,
"/>
<rule ref="SlevomatCodingStandard.Files.TypeNameMatchesFileName">
<properties>
<property name="rootNamespaces" type="array" value="
src=>Contributte\Utils,
tests/cases=>Tests\Contributte\Utils,
"/>
<property name="extensions" type="array" value="php, phpt"/>
</properties>
</rule>
</properties>
</rule>

<!-- Exclude folders -->
<exclude-pattern>/tests/tmp</exclude-pattern>
<!-- Exclude folders -->
<exclude-pattern>/tests/tmp</exclude-pattern>
</ruleset>
@@ -0,0 +1,70 @@
<?php declare(strict_types = 1);

namespace Contributte\Utils;

use Nette\InvalidStateException;

class Csv
{

/**
* @param mixed[] $scheme
* @return mixed[]
*/
public static function structural(array $scheme, string $file, string $delimiter = ';', string $enclosure = '"'): array
{
$data = [];

// Read and parse CSV file
$content = (array) file($file);
foreach ($content as $n => $line) {
$data[$n] = str_getcsv((string) $content[$n], $delimiter, $enclosure);
}

// No data at all
if (count($data) <= 0) {
return [];
}

// Validate scheme and CSV row
if (count($scheme) > count($data[0])) {
throw new InvalidStateException('Scheme has more fields then CSV line');
}

$result = [];
foreach ($data as $line) {
$liner = [];
foreach ($line as $n => $v) {
// Skip it
if (!isset($scheme[$n]) || $scheme[$n] === null) {
continue;
}
// Match value
self::matchValue($v, $liner, explode('.', $scheme[$n]));
}
$result[] = $liner;
}

return $result;
}

/**
* @param mixed $value
* @param mixed[] $liner
* @param string[] $keys
*/
protected static function matchValue($value, array &$liner, array $keys): void
{
if (count($keys) > 1) {
$tmp = array_shift($keys);
if (!isset($liner[$tmp])) {
$liner[$tmp] = [];
}
$liner[$tmp][current($keys)] = [];
self::matchValue($value, $liner[$tmp], $keys);
} else {
$liner[current($keys)] = $value;
}
}

}
@@ -3,7 +3,7 @@
use Contributte\Utils\Arrays;
use Tester\Assert;

require_once __DIR__ . '/../bootstrap.php';
require_once __DIR__ . '/../../bootstrap.php';

test(function (): void {
$array1 = ['a', 'b', 'c', 'd'];
@@ -1,6 +1,6 @@
<?php declare(strict_types = 1);

require_once __DIR__ . '/../bootstrap.php';
require_once __DIR__ . '/../../bootstrap.php';

use Contributte\Utils\Config;
use Tester\Assert;

0 comments on commit ac04f2a

Please sign in to comment.
You can’t perform that action at this time.