diff --git a/src/Fieldtypes/ImportMappingsFieldtype.php b/src/Fieldtypes/ImportMappingsFieldtype.php index 42b1dba..ea9e6d4 100644 --- a/src/Fieldtypes/ImportMappingsFieldtype.php +++ b/src/Fieldtypes/ImportMappingsFieldtype.php @@ -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())) { @@ -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()]; }); diff --git a/src/Http/Controllers/ExtractFromImportFields.php b/src/Http/Controllers/ExtractFromImportFields.php index 59427ce..efd924d 100644 --- a/src/Http/Controllers/ExtractFromImportFields.php +++ b/src/Http/Controllers/ExtractFromImportFields.php @@ -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(); diff --git a/src/Http/Controllers/ImportController.php b/src/Http/Controllers/ImportController.php index 416ec5c..dd39b82 100644 --- a/src/Http/Controllers/ImportController.php +++ b/src/Http/Controllers/ImportController.php @@ -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'], ])); @@ -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'], [ diff --git a/src/Imports/Blueprint.php b/src/Imports/Blueprint.php index 127f586..44dc4ee 100644 --- a/src/Imports/Blueprint.php +++ b/src/Imports/Blueprint.php @@ -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 { @@ -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')], @@ -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' => [ @@ -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 = [ diff --git a/src/Sources/AbstractSource.php b/src/Sources/AbstractSource.php index b8bdac6..7bcd1af 100644 --- a/src/Sources/AbstractSource.php +++ b/src/Sources/AbstractSource.php @@ -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); + } } diff --git a/src/Sources/Csv.php b/src/Sources/Csv.php index 67de359..eb0861b 100644 --- a/src/Sources/Csv.php +++ b/src/Sources/Csv.php @@ -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' => ',', + ], + ]; } } diff --git a/tests/Imports/UpdateImportTest.php b/tests/Imports/UpdateImportTest.php index df8a277..d890b14 100644 --- a/tests/Imports/UpdateImportTest.php +++ b/tests/Imports/UpdateImportTest.php @@ -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'], @@ -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'],