Skip to content

Commit

Permalink
CSV Delimiter (#29)
Browse files Browse the repository at this point in the history
* Allow sources to provide config options

* Add "CSV Delimiter" config option

* Fix failing tests.

* Make the setting `csv_delimiter`.
  • Loading branch information
duncanmcclean authored Nov 7, 2024
1 parent 0016b5a commit fc888fc
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 11 deletions.
11 changes: 5 additions & 6 deletions src/Fieldtypes/ImportMappingsFieldtype.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,17 @@ private function fields(): Collection
$import = $this->field()->parent();

$row = match ($import->get('type')) {
'csv' => (new Csv($import))->getItems($import->get('path'), [])->first(),
'xml' => (new Xml($import))->getItems($import->get('path'), [])->first(),
'csv' => (new Csv($import))->getItems($import->get('path'))->first(),
'xml' => (new Xml($import))->getItems($import->get('path'))->first(),
};

return $import->destinationBlueprint()->fields()->all()
->reject(function (Field $field) {
$transformer = Importer::getTransformer($field->type());

return in_array($field->type(), ['section', 'grid', 'replicator', 'group'])
&& ! $transformer;
return ! $transformer && in_array($field->type(), ['section', 'grid', 'replicator', 'group']);
})
->mapWithKeys(function (Field $field) use ($row) {
->mapWithKeys(function (Field $field) use ($import, $row) {
$fields = [];

if ($transformer = Importer::getTransformer($field->type())) {
Expand All @@ -119,7 +118,7 @@ private function fields(): Collection
'clearable' => true,
],
...$fields,
])->setHandle('mappings-'.$field->handle());
])->setHandle("import-mappings-{$field->handle()}".md5($import->config()->toJson()));

return [$field->handle() => $blueprint->fields()];
});
Expand Down
10 changes: 8 additions & 2 deletions src/Http/Controllers/ExtractFromImportFields.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@

trait ExtractFromImportFields
{
protected function extractFromFields($import, $fields)
protected function extractFromFields($import, $blueprint)
{
$fields = $fields->preProcess();
$fields = $blueprint
->fields()
->setParent($import)
->addValues($import->config()->merge([
'name' => $import->name(),
])->all())
->preProcess();

$values = $fields->values();

Expand Down
3 changes: 2 additions & 1 deletion src/Http/Controllers/ImportController.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ public function update(Request $request, Import $import)
'path' => $path,
'destination' => collect($values['destination'])->filter()->all(),
'strategy' => $values['strategy'],
'source' => $values['source'],
'mappings' => $values['mappings'],
'unique_field' => $values['unique_field'],
]));
Expand All @@ -185,7 +186,7 @@ public function update(Request $request, Import $import)
// We need to refresh the blueprint after saving, so the field conditions are up-to-date.
$blueprint = $import->blueprint();

[$values, $meta] = $this->extractFromFields($import, $fields);
[$values, $meta] = $this->extractFromFields($import, $blueprint);

return [
'data' => array_merge((new ImportResource($import->fresh()))->resolve()['data'], [
Expand Down
32 changes: 31 additions & 1 deletion src/Imports/Blueprint.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
use Statamic\Facades;
use Statamic\Facades\Collection;
use Statamic\Facades\Site;
use Statamic\Importer\Sources\Csv;
use Statamic\Importer\Sources\Xml;

class Blueprint
{
Expand Down Expand Up @@ -78,7 +80,7 @@ function (string $attribute, mixed $value, Closure $fail) {
'field' => [
'type' => 'button_group',
'display' => __('Data Type'),
'instructions' => __('Choose what type of data are you importing'),
'instructions' => __('Choose what type of data are you importing.'),
'width' => 50,
'options' => [
['key' => 'entries', 'value' => __('Entries')],
Expand Down Expand Up @@ -159,6 +161,7 @@ function (string $attribute, mixed $value, Closure $fail) {
'display' => __('Configuration'),
'instructions' => __('importer::messages.configuration_instructions'),
'fields' => [
...static::getSourceFields($import),
[
'handle' => 'mappings',
'field' => [
Expand Down Expand Up @@ -206,6 +209,33 @@ function (string $attribute, mixed $value, Closure $fail) {
]);
}

private static function getSourceFields(?Import $import = null): array
{
if (! $import) {
return [];
}

$fields = match ($import->get('type')) {
'csv' => (new Csv($import))->fields(),
'xml' => (new Xml($import))->fields(),
};

if ($fields->items()->isEmpty()) {
return [];
}

return [[
'handle' => 'source',
'field' => [
'type' => 'group',
'hide_display' => true,
'fullscreen' => false,
'border' => false,
'fields' => $fields->items()->all(),
],
]];
}

private static function buildFieldConditions(Import $import): array
{
$conditions = [
Expand Down
21 changes: 21 additions & 0 deletions src/Sources/AbstractSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,31 @@

namespace Statamic\Importer\Sources;

use Illuminate\Support\Arr;
use Illuminate\Support\LazyCollection;
use Statamic\Extend\HasFields;
use Statamic\Importer\Contracts\Source;
use Statamic\Importer\Imports\Import;

abstract class AbstractSource implements Source
{
use HasFields;

public function __construct(public ?Import $import = null) {}

abstract public function getItems(string $path): LazyCollection;

public function fieldItems(): array
{
return [];
}

protected function config(?string $key = null, $default = null): mixed
{
if (is_null($key)) {
return collect($this->import->get('source'));
}

return Arr::get($this->import->get('source'), $key, $default);
}
}
16 changes: 15 additions & 1 deletion src/Sources/Csv.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,20 @@ class Csv extends AbstractSource
{
public function getItems(string $path): LazyCollection
{
return SimpleExcelReader::create($path)->getRows();
return SimpleExcelReader::create($path)
->useDelimiter($this->config('csv_delimiter', ','))
->getRows();
}

public function fieldItems(): array
{
return [
'csv_delimiter' => [
'display' => __('CSV Delimiter'),
'instructions' => __('Specify the delimiter to be used when reading the CSV file. You will need to save the import for the options to be updated.'),
'type' => 'text',
'default' => ',',
],
];
}
}
2 changes: 2 additions & 0 deletions tests/Imports/UpdateImportTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public function can_update_an_import()
'name' => 'Old Posts',
'destination' => ['type' => 'entries', 'collection' => ['posts']],
'strategy' => ['create', 'update'],
'source' => ['csv_delimiter' => ','],
'mappings' => [
'title' => ['key' => 'Title'],
'slug' => ['key' => 'Slug'],
Expand Down Expand Up @@ -95,6 +96,7 @@ public function can_replace_the_file()
'file' => ['123456789/latest-posts.csv'],
'destination' => ['type' => 'entries', 'collection' => ['posts']],
'strategy' => ['create', 'update'],
'source' => ['csv_delimiter' => ','],
'mappings' => [
'title' => ['key' => 'Title'],
'slug' => ['key' => 'Slug'],
Expand Down

0 comments on commit fc888fc

Please sign in to comment.