diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 86f62571..556d8862 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -60,10 +60,6 @@ jobs: ${{ steps.composer-cache.outputs.dir }} key: ${{ github.run_id }}-${{ runner.os }}-${{ hashFiles('composer.json') }}-symfony-${{ matrix.symfony }} - - name: 'Remove portphp/csv if needed' - if: matrix.symfony == '^8.0' - run: composer remove portphp/csv --no-update - - name: "Install dependencies" run: composer update --no-interaction --no-scripts diff --git a/app/Responder/ExportGridToCsvResponder.php b/app/Responder/ExportGridToCsvResponder.php index 1fcd1499..05a71ef9 100644 --- a/app/Responder/ExportGridToCsvResponder.php +++ b/app/Responder/ExportGridToCsvResponder.php @@ -13,8 +13,8 @@ namespace App\Responder; +use League\Csv\Writer; use Pagerfanta\PagerfantaInterface; -use Port\Csv\CsvWriter; use Sylius\Component\Grid\Definition\Field; use Sylius\Component\Grid\Renderer\GridRendererInterface; use Sylius\Component\Grid\View\GridViewInterface; @@ -49,14 +49,11 @@ public function respond(mixed $data, Operation $operation, Context $context): mi throw new \RuntimeException('Unable to open output stream.'); } - $writer = new CsvWriter(); - $writer->setStream($output); + $writer = Writer::from($output); $fields = $this->sortFields($data->getDefinition()->getFields()); $this->writeHeaders($writer, $fields); $this->writeRows($writer, $fields, $data); - - $writer->finish(); }); $response->headers->set('Content-Type', 'text/csv; charset=UTF-8'); @@ -68,17 +65,17 @@ public function respond(mixed $data, Operation $operation, Context $context): mi /** * @param Field[] $fields */ - private function writeHeaders(CsvWriter $writer, array $fields): void + private function writeHeaders(Writer $writer, array $fields): void { $labels = array_map(fn (Field $field) => $this->translator->trans($field->getLabel()), $fields); - $writer->writeItem($labels); + $writer->insertOne($labels); } /** * @param Field[] $fields */ - private function writeRows(CsvWriter $writer, array $fields, GridViewInterface $gridView): void + private function writeRows(Writer $writer, array $fields, GridViewInterface $gridView): void { /** @var PagerfantaInterface $paginator */ $paginator = $gridView->getData(); @@ -94,14 +91,14 @@ private function writeRows(CsvWriter $writer, array $fields, GridViewInterface $ * @param Field[] $fields * @param iterable $pageResults */ - private function writePageResults(CsvWriter $writer, array $fields, GridViewInterface $gridView, iterable $pageResults): void + private function writePageResults(Writer $writer, array $fields, GridViewInterface $gridView, iterable $pageResults): void { foreach ($pageResults as $resource) { $rows = []; foreach ($fields as $field) { $rows[] = $this->getFieldValue($gridView, $field, $resource); } - $writer->writeItem($rows); + $writer->insertOne($rows); } } diff --git a/composer.json b/composer.json index ff71cd65..991ec97d 100644 --- a/composer.json +++ b/composer.json @@ -20,9 +20,9 @@ "doctrine/orm": "^3.3 || ^4.0", "knplabs/knp-menu-bundle": "^3.0", "laminas/laminas-stdlib": "^3.18", + "league/csv": "^9.0", "pagerfanta/doctrine-orm-adapter": "^4.6", "pagerfanta/twig": "^4.6", - "portphp/csv": "^2.0", "sylius/grid-bundle": "^1.13 || ^1.15@alpha", "sylius/resource-bundle": "^1.13 || ^1.14@alpha", "symfony/asset": "^6.4 || ^7.4 || ^8.0", @@ -110,7 +110,7 @@ }, "extra": { "symfony": { - "require": "7.4.*" + "require": "8.0.*" } }, "scripts": { diff --git a/config/reference.php b/config/reference.php index 66c7d9ad..b0452a24 100644 --- a/config/reference.php +++ b/config/reference.php @@ -188,7 +188,7 @@ * only_exceptions?: bool|Param, // Default: false * only_main_requests?: bool|Param, // Default: false * dsn?: scalar|Param|null, // Default: "file:%kernel.cache_dir%/profiler" - * collect_serializer_data?: bool|Param, // Enables the serializer data collector and profiler panel. // Default: false + * collect_serializer_data?: true|Param, // Default: true * }, * workflows?: bool|array{ * enabled?: bool|Param, // Default: false @@ -232,7 +232,6 @@ * enabled?: bool|Param, // Default: false * resource: scalar|Param|null, * type?: scalar|Param|null, - * cache_dir?: scalar|Param|null, // Deprecated: Setting the "framework.router.cache_dir.cache_dir" configuration option is deprecated. It will be removed in version 8.0. // Default: "%kernel.build_dir%" * default_uri?: scalar|Param|null, // The default URI used to generate URLs in a non-HTTP context. // Default: null * http_port?: scalar|Param|null, // Default: 80 * https_port?: scalar|Param|null, // Default: 443 @@ -256,8 +255,6 @@ * gc_maxlifetime?: scalar|Param|null, * save_path?: scalar|Param|null, // Defaults to "%kernel.cache_dir%/sessions" if the "handler_id" option is not null. * metadata_update_threshold?: int|Param, // Seconds to wait between 2 session metadata updates. // Default: 0 - * sid_length?: int|Param, // Deprecated: Setting the "framework.session.sid_length.sid_length" configuration option is deprecated. It will be removed in version 8.0. No alternative is provided as PHP 8.4 has deprecated the related option. - * sid_bits_per_character?: int|Param, // Deprecated: Setting the "framework.session.sid_bits_per_character.sid_bits_per_character" configuration option is deprecated. It will be removed in version 8.0. No alternative is provided as PHP 8.4 has deprecated the related option. * }, * request?: bool|array{ // Request configuration * enabled?: bool|Param, // Default: false @@ -331,11 +328,10 @@ * }, * validation?: bool|array{ // Validation configuration * enabled?: bool|Param, // Default: true - * cache?: scalar|Param|null, // Deprecated: Setting the "framework.validation.cache.cache" configuration option is deprecated. It will be removed in version 8.0. * enable_attributes?: bool|Param, // Default: true * static_method?: list, * translation_domain?: scalar|Param|null, // Default: "validators" - * email_validation_mode?: "html5"|"html5-allow-no-tld"|"strict"|"loose"|Param, // Default: "html5" + * email_validation_mode?: "html5"|"html5-allow-no-tld"|"strict"|Param, // Default: "html5" * mapping?: array{ * paths?: list, * }, @@ -348,9 +344,6 @@ * services?: list, * }>, * }, - * annotations?: bool|array{ - * enabled?: bool|Param, // Default: false - * }, * serializer?: bool|array{ // Serializer configuration * enabled?: bool|Param, // Default: false * enable_attributes?: bool|Param, // Default: true @@ -382,7 +375,7 @@ * }, * property_info?: bool|array{ // Property info configuration * enabled?: bool|Param, // Default: true - * with_constructor_extractor?: bool|Param, // Registers the constructor extractor. + * with_constructor_extractor?: bool|Param, // Registers the constructor extractor. // Default: true * }, * cache?: array{ // Cache configuration * prefix_seed?: scalar|Param|null, // Used to namespace cache keys when using several apps with the same shared backend. // Default: "_%kernel.project_dir%.%kernel.container_class%" @@ -699,7 +692,6 @@ * }>, * autoescape_service?: scalar|Param|null, // Default: null * autoescape_service_method?: scalar|Param|null, // Default: null - * base_template_class?: scalar|Param|null, // Deprecated: The child node "base_template_class" at path "twig.base_template_class" is deprecated. * cache?: scalar|Param|null, // Default: true * charset?: scalar|Param|null, // Default: "%kernel.charset%" * debug?: bool|Param, // Default: "%kernel.debug%" @@ -1170,7 +1162,6 @@ * @psalm-type SecurityConfig = array{ * access_denied_url?: scalar|Param|null, // Default: null * session_fixation_strategy?: "none"|"migrate"|"invalidate"|Param, // Default: "migrate" - * hide_user_not_found?: bool|Param, // Deprecated: The "hide_user_not_found" option is deprecated and will be removed in 8.0. Use the "expose_security_errors" option instead. * expose_security_errors?: \Symfony\Component\Security\Http\Authentication\ExposeSecurityLevel::None|\Symfony\Component\Security\Http\Authentication\ExposeSecurityLevel::AccountStatus|\Symfony\Component\Security\Http\Authentication\ExposeSecurityLevel::All|Param, // Default: "none" * erase_credentials?: bool|Param, // Default: true * access_decision_manager?: array{ @@ -1406,9 +1397,7 @@ * claim?: scalar|Param|null, // Claim which contains the user identifier (e.g.: sub, email..). // Default: "sub" * audience: scalar|Param|null, // Audience set in the token, for validation purpose. * issuers: list, - * algorithm?: array, * algorithms: list, - * key?: scalar|Param|null, // Deprecated: The "key" option is deprecated and will be removed in 8.0. Use the "keyset" option instead. // JSON-encoded JWK used to sign the token (must contain a "kty" key). * keyset?: scalar|Param|null, // JSON-encoded JWKSet used to sign the token (must contain a list of valid public keys). * encryption?: bool|array{ * enabled?: bool|Param, // Default: false diff --git a/docs/cookbook/admin_panel/grid_export.md b/docs/cookbook/admin_panel/grid_export.md index 9bf7b1cf..13bf873e 100644 --- a/docs/cookbook/admin_panel/grid_export.md +++ b/docs/cookbook/admin_panel/grid_export.md @@ -8,7 +8,7 @@ In this example, we'll create a CSV export. ## The responder -First, create the responder using the [https://github.com/portphp/csv](portphp/csv) package. +First, create the responder using the [https://github.com/thephpleague/csv](league/csv) package. {% code title="src/Responder/ExportGridToCsvResponder.php" lineNumbers="true" %} ```php @@ -18,8 +18,8 @@ declare(strict_types=1); namespace App\Responder; +use League\Csv\Writer; use Pagerfanta\PagerfantaInterface; -use Port\Csv\CsvWriter; use Sylius\Component\Grid\Definition\Field; use Sylius\Component\Grid\Renderer\GridRendererInterface; use Sylius\Component\Grid\View\GridViewInterface; @@ -54,14 +54,11 @@ final readonly class ExportGridToCsvResponder implements ResponderInterface throw new \RuntimeException('Unable to open output stream.'); } - $writer = new CsvWriter(); - $writer->setStream($output); + $writer = Writer::from($output); $fields = $this->sortFields($data->getDefinition()->getFields()); $this->writeHeaders($writer, $fields); $this->writeRows($writer, $fields, $data); - - $writer->finish(); }); $response->headers->set('Content-Type', 'text/csv; charset=UTF-8'); @@ -73,17 +70,17 @@ final readonly class ExportGridToCsvResponder implements ResponderInterface /** * @param Field[] $fields */ - private function writeHeaders(CsvWriter $writer, array $fields): void + private function writeHeaders(Writer $writer, array $fields): void { $labels = array_map(fn (Field $field) => $this->translator->trans($field->getLabel()), $fields); - $writer->writeItem($labels); + $writer->insertOne($labels); } /** * @param Field[] $fields */ - private function writeRows(CsvWriter $writer, array $fields, GridViewInterface $gridView): void + private function writeRows(Writer $writer, array $fields, GridViewInterface $gridView): void { /** @var PagerfantaInterface $paginator */ $paginator = $gridView->getData(); @@ -99,21 +96,21 @@ final readonly class ExportGridToCsvResponder implements ResponderInterface * @param Field[] $fields * @param iterable $pageResults */ - private function writePageResults(CsvWriter $writer, array $fields, GridViewInterface $gridView, iterable $pageResults): void + private function writePageResults(Writer $writer, array $fields, GridViewInterface $gridView, iterable $pageResults): void { foreach ($pageResults as $resource) { $rows = []; foreach ($fields as $field) { $rows[] = $this->getFieldValue($gridView, $field, $resource); } - $writer->writeItem($rows); + $writer->insertOne($rows); } } private function getFieldValue(GridViewInterface $gridView, Field $field, object $data): string { $renderedData = $this->gridRenderer->renderField($gridView, $field, $data); - $renderedData = str_replace(PHP_EOL, '', $renderedData); + $renderedData = str_replace(\PHP_EOL, '', $renderedData); return trim(strip_tags($renderedData)); }