Skip to content

Commit 4cdff1b

Browse files
committed
allow preset id
1 parent 621b7e8 commit 4cdff1b

File tree

15 files changed

+154
-117
lines changed

15 files changed

+154
-117
lines changed

.github/workflows/tests.yml

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,14 @@ name: Tests
22

33
on:
44
push:
5-
branches:
6-
- '**'
75
pull_request:
8-
branches:
9-
- master
6+
types: [ opened, reopened ]
107

118
jobs:
12-
pre_job:
13-
runs-on: ubuntu-latest
14-
outputs:
15-
should_skip: ${{ steps.skip_check.outputs.should_skip }}
16-
steps:
17-
- id: skip_check
18-
uses: fkirc/skip-duplicate-actions@v5
19-
with:
20-
concurrent_skipping: always
21-
skip_after_successful_duplicate: true
22-
do_not_skip: '["pull_request"]'
239

2410
tests:
2511
runs-on: ubuntu-latest
2612
name: Tests
27-
needs: pre_job
28-
if: needs.pre_job.outputs.should_skip != 'true'
2913

3014
strategy:
3115
fail-fast: false

README.md

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ Importing entities with preview and edit features for Symfony.
3737
* [Controller-specific templates](#controller-specific-templates)
3838
* [Main layout](#main-layout)
3939
* [Additional data](#additional-data)
40+
* [Updating entities](#updating-entities)
4041
* [Importing data to array field](#importing-data-to-array-field)
4142
* [Full example of CSV file](#full-example-of-csv-file)
4243

@@ -360,6 +361,25 @@ protected function prepareMatrixEditView(FormInterface $form, Matrix $matrix, bo
360361
}
361362
```
362363

364+
## Updating entities
365+
366+
If you want to update your entities:
367+
- Set `allowOverrideEntity` to `true` in your import configuration file.
368+
- Then in your import file:
369+
- Add `entity_id` in header and:
370+
- Add entity ID to row
371+
- Leave it empty (if you want to set it manually or import it as new record)
372+
- Or if you don't want to add `entity_id` header, you can still manually set each entity to override.
373+
374+
#### CSV file
375+
376+
```csv
377+
entity_id,user_name
378+
2,user_1
379+
,user_2
380+
10,user_3
381+
```
382+
363383
## Importing data to array field
364384

365385
If your entity has an array field, and you want to import data from CSV file to it, this is how you can do it.
@@ -434,8 +454,8 @@ user_3,SUPER_ADMIN
434454
## Full example of CSV file
435455

436456
```csv
437-
user_name,age,email,roles,country:en,name:pl
438-
user_1,21,user_1@test.com,USER&ADMIN&SUPER_ADMIN,Poland,Polska
439-
user_2,34,user_2@test.com,USER,England,Anglia
440-
user_3,56,user_3@test.com,SUPER_ADMIN,Germany,Niemcy
457+
entity_id,user_name,age,email,roles,country:en,name:pl
458+
1,user_1,21,user_1@test.com,USER&ADMIN&SUPER_ADMIN,Poland,Polska
459+
3, user_2,34,user_2@test.com,USER,England,Anglia
460+
,user_3,56,user_3@test.com,SUPER_ADMIN,Germany,Niemcy
441461
```

UPGRADE.md

Lines changed: 32 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,34 @@
1-
UPGRADE TO 3.6
2-
=======================
1+
# UPGRADE TO 3.7
32

4-
Import data to array
5-
--------------
3+
### Preset entity id before updating - [go to the documentation](README.md#updating-entities)
64

7-
* By default, allowed file extensions are set to `'csv', 'xls', 'xlsx', 'ods'`.
8-
However, if you want to change it, you can override this method in your import configuration.
5+
# UPGRADE TO 3.6
96

10-
```php
11-
public function getAllowedFileExtensions(): array
12-
{
13-
return ['csv', 'xls', 'xlsx', 'ods'];
14-
}
15-
```
7+
### Set allowed file extensions - [go to the documentation](README.md#set-allowed-file-extensions)
168

17-
UPGRADE TO 3.5
18-
=======================
19-
20-
Import data to array
21-
--------------
22-
* If your entity has an array field, and you want to import data from CSV file to it, it is now possible.
23-
24-
```php
25-
use JG\BatchEntityImportBundle\Form\Type\ArrayTextType;
26-
use JG\BatchEntityImportBundle\Model\Form\FormFieldDefinition;
27-
28-
public function getFieldsDefinitions(): array
29-
{
30-
return [
31-
'roles' => new FormFieldDefinition(
32-
ArrayTextType::class,
33-
[
34-
'separator' => '&',
35-
]
36-
),
37-
];
38-
}
39-
```
9+
# UPGRADE TO 3.5
4010

11+
### Import data to array - [go to the documentation](README.md#importing-data-to-array-field)
4112

42-
UPGRADE TO 3.1
43-
=======================
13+
# UPGRADE TO 3.1
4414

45-
CSV File
46-
--------------
47-
* Now CSV file can contain spaces and dashes as a header name, for example "my column name" or "my-column-name".
15+
## CSV File
16+
- Now CSV file can contain spaces and dashes as a header name, for example "my column name" or "my-column-name".
4817

49-
Import Configuration class
50-
--------------
51-
* When header name contains spaces we should use underscores instead of spaces when defining fields names in fields definitions and in constraints.
18+
## Import Configuration class
19+
- When header name contains spaces we should use underscores instead of spaces when defining fields names in fields definitions and in constraints.
5220

5321

54-
UPGRADE TO 3.0
55-
=======================
22+
# UPGRADE TO 3.0
5623

57-
Controller
58-
--------------
24+
## Controller
5925
* Passing configuration class by `getSubscribedServices()` was removed. Now it is only possible by autoconfiguration.
6026

6127

62-
UPGRADE TO 2.5
63-
=======================
28+
# UPGRADE TO 2.5
6429

65-
Import Configuration class
66-
--------------
67-
* Added new validator to check matrix record data uniqueness in database.
30+
## Import Configuration class
31+
- Added new validator to check matrix record data uniqueness in database.
6832
```php
6933
use JG\BatchEntityImportBundle\Validator\Constraints\DatabaseEntityUnique;
7034

@@ -76,12 +40,10 @@ public function getMatrixConstraints(): array
7640
}
7741
```
7842

79-
UPGRADE TO 2.4
80-
=======================
43+
# UPGRADE TO 2.4
8144

82-
Import Configuration class
83-
--------------
84-
* Added new validator to check matrix record data uniqueness.
45+
## Import Configuration class
46+
- Added new validator to check matrix record data uniqueness.
8547
```php
8648
use JG\BatchEntityImportBundle\Validator\Constraints\MatrixRecordUnique;
8749

@@ -93,33 +55,27 @@ public function getMatrixConstraints(): array
9355
}
9456
```
9557

96-
Controller
97-
--------------
98-
* List of options passed to form in `createMatrixForm()` method, should contain new `constraints` element:
58+
## Controller
59+
- List of options passed to form in `createMatrixForm()` method, should contain new `constraints` element:
9960
`'constraints' => $importConfiguration->getMatrixConstraints()`
10061

101-
UPGRADE TO 2.3
102-
=======================
62+
# UPGRADE TO 2.3
10363

104-
Controller
105-
--------------
106-
* Passing configuration class by `getSubscribedServices()` method is not needed anymore and will be removed in the future.
107-
* To make sure that configuration class will be injected automatically:
108-
* Interface `JG\BatchEntityImportBundle\Controller\ImportConfigurationAutoInjectInterface` should be implemented.
109-
* Trait `JG\BatchEntityImportBundle\Controller\ImportConfigurationAutoInjectTrait` should be used to add needed methods.
64+
## Controller
65+
- Passing configuration class by `getSubscribedServices()` method is not needed anymore and will be removed in the future.
66+
- To make sure that configuration class will be injected automatically:
67+
- Interface `JG\BatchEntityImportBundle\Controller\ImportConfigurationAutoInjectInterface` should be implemented.
68+
- Trait `JG\BatchEntityImportBundle\Controller\ImportConfigurationAutoInjectTrait` should be used to add needed methods.
11069

11170

112-
UPGRADE TO 2.2
113-
=======================
71+
# UPGRADE TO 2.2
11472

115-
Import Configuration class
116-
--------------
117-
* Now configuration class should be always registered as a service:
73+
## Import Configuration class
74+
- Now configuration class should be always registered as a service:
11875
```yaml
11976
services:
12077
App\Model\ImportConfiguration\UserImportConfiguration: ~
12178
```
12279
123-
Controller
124-
--------------
125-
* Entity Manager is no longer passed as an argument of actions.
80+
## Controller
81+
- Entity Manager is no longer passed as an argument of actions.

src/Controller/BaseImportControllerTrait.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ protected function prepareMatrixEditView(FormInterface $form, Matrix $matrix, bo
8989
$this->getMatrixEditTemplateName(),
9090
[
9191
'header_info' => $matrix->getHeaderInfo($configuration->getEntityClassName()),
92-
'data' => $matrix->getRecords(),
9392
'form' => $form->createView(),
9493
'importConfiguration' => $configuration,
9594
]

src/Form/Type/MatrixRecordType.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
use Symfony\Component\Form\FormBuilderInterface;
2020
use Symfony\Component\Form\FormEvent;
2121
use Symfony\Component\Form\FormEvents;
22+
use Symfony\Component\Form\FormInterface;
23+
use Symfony\Component\Form\FormView;
2224
use Symfony\Component\OptionsResolver\Exception\AccessException;
2325
use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException;
2426
use Symfony\Component\OptionsResolver\OptionsResolver;
@@ -101,4 +103,17 @@ private function addField(array $fieldDefinitions, string $columnName, FormEvent
101103
? $event->getForm()->add($columnName, $definition->getClass(), $definition->getOptions())
102104
: $event->getForm()->add($columnName, TextType::class);
103105
}
106+
107+
public function finishView(FormView $view, FormInterface $form, array $options): void
108+
{
109+
/** @var MatrixRecord $entity */
110+
$entity = $form->getData();
111+
$selectedValue = $entity->entityId;
112+
113+
foreach ($view['entity']->vars['choices'] ?? [] as $index => $choice) {
114+
if ($choice->value === $selectedValue) {
115+
$view['entity']->vars['choices'][$index]->attr['selected'] = 'selected';
116+
}
117+
}
118+
}
104119
}

src/Model/Matrix/Matrix.php

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
class Matrix
1313
{
1414
private const RESERVED_ENTITY_COLUMN_NAME = 'entity';
15+
private const RESERVED_ENTITY_ID_COLUMN_NAME = 'entity_id';
1516
#[Assert\All([
1617
new Assert\NotBlank(),
1718
new Assert\Type('string'),
@@ -33,9 +34,9 @@ public function __construct(array $header = [], array $recordsData = [])
3334
$this->header = $this->clearHeader($header);
3435

3536
foreach ($recordsData as $data) {
36-
$data = $this->clearRecordData($data);
37-
if ($data) {
38-
$this->records[] = new MatrixRecord($data);
37+
$clearedData = $this->clearRecordData($data);
38+
if ($clearedData) {
39+
$this->records[] = new MatrixRecord($clearedData, $this->getEntityIdValue($data));
3940
}
4041
}
4142
}
@@ -65,6 +66,17 @@ public function getHeaderInfo(string $className): array
6566
return $info;
6667
}
6768

69+
private function getEntityIdValue(array $data): int|string|null
70+
{
71+
foreach ($data as $name => $value) {
72+
if (self::RESERVED_ENTITY_ID_COLUMN_NAME === $name) {
73+
return $value;
74+
}
75+
}
76+
77+
return null;
78+
}
79+
6880
private function clearHeader(array $header): array
6981
{
7082
$header = array_values(
@@ -81,6 +93,6 @@ private function clearRecordData(array $data): array
8193

8294
private function isColumnNameValid(?string $name): bool
8395
{
84-
return !empty(trim((string) $name)) && self::RESERVED_ENTITY_COLUMN_NAME !== $name;
96+
return !empty(trim((string) $name)) && !\in_array($name, [self::RESERVED_ENTITY_COLUMN_NAME, self::RESERVED_ENTITY_ID_COLUMN_NAME], true);
8597
}
8698
}

src/Model/Matrix/MatrixFactory.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use JG\BatchEntityImportBundle\Service\CsvDelimiterDetector;
99
use PhpOffice\PhpSpreadsheet\Reader\BaseReader;
1010
use PhpOffice\PhpSpreadsheet\Reader\Csv;
11+
use PhpOffice\PhpSpreadsheet\Reader\Xls;
1112
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
1213
use Symfony\Component\HttpFoundation\File\UploadedFile;
1314

@@ -55,7 +56,7 @@ private static function getReader(UploadedFile $file): BaseReader
5556
if ($reader instanceof Csv) {
5657
$detectedDelimiter = (new CsvDelimiterDetector())->detect($file->getContent());
5758
$reader->setDelimiter($detectedDelimiter->value);
58-
} elseif ($reader instanceof Xlsx) {
59+
} elseif ($reader instanceof Xls || $reader instanceof Xlsx) {
5960
$reader->setIgnoreRowsWithNoCells(true);
6061
}
6162

src/Model/Matrix/MatrixRecord.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class MatrixRecord
99
private ?object $entity = null;
1010
private array $data = [];
1111

12-
public function __construct(array $data = [])
12+
public function __construct(array $data = [], public readonly int|string|null $entityId = null)
1313
{
1414
foreach ($data as $name => $value) {
1515
if (!empty(\trim((string) $name))) {

tests/Controller/ImportControllerTraitTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,28 @@ public function testUpdateExistingRecord(
6666
$this->assertEntityValues($expectedDefaultValues, $updatedEntityId);
6767

6868
$this->submitSelectFileForm(__DIR__ . '/../Fixtures/Resources/test_updated_data.csv');
69+
70+
$this->assertSame(
71+
'2',
72+
$this->client->getCrawler()->filterXpath('//select[@name="matrix[records][0][entity]"]/option[@selected]')->attr('value'),
73+
);
74+
$this->assertSame(
75+
'test',
76+
$this->client->getCrawler()->filterXpath('//input[@name="matrix[records][0][test_private_property]"]')->attr('value'),
77+
);
78+
$this->assertSame(
79+
'lorem ipsum',
80+
$this->client->getCrawler()->filterXpath('//input[@name="matrix[records][0][test-private-property2]"]')->attr('value'),
81+
);
82+
$this->assertSame(
83+
'qwerty',
84+
$this->client->getCrawler()->filterXpath('//input[@name="matrix[records][0][test_public_property]"]')->attr('value'),
85+
);
86+
$this->assertSame(
87+
'arr_val_1000|array_val_1001',
88+
$this->client->getCrawler()->filterXpath('//input[@name="matrix[records][0][test_array_field]"]')->attr('value'),
89+
);
90+
6991
$this->client->submitForm('btn-submit', [
7092
'matrix' => [
7193
'records' => [

tests/Fixtures/Resources/test.xls

8.5 KB
Binary file not shown.

0 commit comments

Comments
 (0)