Skip to content

Commit

Permalink
Merge pull request #21 from luyadev/csv-from-resource
Browse files Browse the repository at this point in the history
Add ImportHelper::csvFromResource() method to import CSV from a resou…
  • Loading branch information
nadar committed Feb 14, 2024
2 parents df68dbf + 3bc941e commit a32e153
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 25 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/).

## 1.5.1
## 1.6.0 (14. February 2024)

+ [#19](https://github.com/luyadev/yii-helpers/pull/19) Fixed issue with ordinal numbers.
+ [#21](https://github.com/luyadev/yii-helpers/pull/21) Added `ImportHelper::csvFromResource()` method to import CSV from a resource object like `fopen()`.

## 1.5.0 (26. October 2023)

Expand Down
65 changes: 41 additions & 24 deletions src/helpers/ImportHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,17 @@
class ImportHelper
{
/**
* Import a CSV from a string or filename and return array.
*
* The filename can be either a resource from `fopen()` or a string containing the CSV data. Filenames will be wrapped through {{`Yii::getAlias()`}} method.
* Import a CSV from a resource and return array.
*
* @param string $filename Can be either a filename which is parsed by {{luya\yii\helpers\FileHelper::getFileContent()}} or a string with the contained CSV data.
* @param array $options Provide options to the CSV
* + `removeHeader`: boolean, Whether the import CSV contains a header in the first row to skip or not. Default value is false.
* + `delimiter`: string, The delimiter which is used to explode the columns. Default value is `,`.
* + `enclosure`: string, The enclosure which is used between the columns. Default value is `"`.
* + `fields`: array, An array with filenames (based on the array header if any, or position) which should be parsed into the final export.
* ```php
* 'fields' => ['firstname', 'lastname'] // will only parse those fields based on table header (row 0)
* 'fields' => [0,1,3] // will only parse fields by those positions if no table header is present. Positions starts at 0.
* ```
* @return array an array with the CSV data.
* @param resource $resource
* @param array $options See {{luya\yii\helpers\ExportHelper::csv()}} for all options.
* @return array
* @since 1.6.0
*/
public static function csv($filename, array $options = [])
public static function csvFromResource($resource, array $options = []): array
{
$filename = Yii::getAlias($filename);

// check if a given file name is provided or a CSV based on the content
if (FileHelper::getFileInfo($filename)->extension) {
$resource = fopen($filename, 'r');
} else {
$resource = fopen('php://memory', 'rw');
fwrite($resource, $filename);
rewind($resource);
if (!is_resource($resource)) {
throw new \InvalidArgumentException("The provided resource is not a valid resource.");
}
$data = [];
while (($row = fgetcsv($resource, 0, ArrayHelper::getValue($options, 'delimiter', ','), ArrayHelper::getValue($options, 'enclosure', '"'))) !== false) {
Expand Down Expand Up @@ -74,4 +58,37 @@ public static function csv($filename, array $options = [])

return $data;
}

/**
* Import a CSV from a string or filename and return array.
*
* The filename can be either a resource from `fopen()` or a string containing the CSV data. Filenames will be wrapped through {{`Yii::getAlias()`}} method.
*
* @param string $filename Can be either a filename which is parsed by {{luya\yii\helpers\FileHelper::getFileContent()}} or a string with the contained CSV data.
* @param array $options Provide options to the CSV
* + `removeHeader`: boolean, Whether the import CSV contains a header in the first row to skip or not. Default value is false.
* + `delimiter`: string, The delimiter which is used to explode the columns. Default value is `,`.
* + `enclosure`: string, The enclosure which is used between the columns. Default value is `"`.
* + `fields`: array, An array with filenames (based on the array header if any, or position) which should be parsed into the final export.
* ```php
* 'fields' => ['firstname', 'lastname'] // will only parse those fields based on table header (row 0)
* 'fields' => [0,1,3] // will only parse fields by those positions if no table header is present. Positions starts at 0.
* ```
* @return array an array with the CSV data.
*/
public static function csv($filename, array $options = [])
{
$filename = Yii::getAlias($filename);

// check if a given file name is provided or a CSV based on the content
if (FileHelper::getFileInfo($filename)->extension) {
$resource = fopen($filename, 'r');
} else {
$resource = fopen('php://memory', 'rw');
fwrite($resource, $filename);
rewind($resource);
}

return self::csvFromResource($resource, $options);
}
}
14 changes: 14 additions & 0 deletions tests/helpers/ImportHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace luya\yii\tests\helpers;

use luya\console\Importer;
use luya\yii\helpers\ExportHelper;
use luya\yii\helpers\ImportHelper;
use luya\yii\tests\HelpersTestCase;
Expand Down Expand Up @@ -50,4 +51,17 @@ public function testCsvWithNewline()
2 => ['Jane', 'World\nHello'],
], ImportHelper::csv($csv));
}

public function testResourceImport()
{
$resource = fopen('php://memory', 'rw');
fwrite($resource, 'foobarcontent');
rewind($resource);

$result = ImportHelper::csvFromResource($resource);

$this->assertSame([
0 => ['foobarcontent'],
], $result);
}
}

0 comments on commit a32e153

Please sign in to comment.