diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 1a65ac1..e3f1545 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -2,7 +2,7 @@ We are using [GitHub Actions](https://github.com/features/actions) as a continuous integration system. -For details, see [`workflows/continuous-integration.yml`](workflows/continuous-integration.yml). +For details, see [`workflows`](workflows). ## Code Style diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml deleted file mode 100644 index 7108a9d..0000000 --- a/.github/workflows/continuous-integration.yml +++ /dev/null @@ -1,210 +0,0 @@ -# https://help.github.com/en/categories/automating-your-workflow-with-github-actions - -on: - pull_request: - push: - branches: - - master - -name: "Continuous Integration" - -jobs: - composer-validate: - name: "Validate composer dependencies" - - runs-on: ubuntu-latest - - steps: - - name: "Checkout" - uses: actions/checkout@master - - - name: "Install PHP with extensions" - uses: shivammathur/setup-php@v2 - with: - coverage: none - extensions: mbstring - php-version: 8.1 - - - name: "Validate composer.json and composer.lock" - run: composer validate --strict - - composer-normalize: - name: "Normalize composer.json" - - runs-on: ubuntu-latest - - steps: - - name: "Checkout" - uses: actions/checkout@v2 - with: - ref: ${{ github.head_ref }} - - - name: "Install PHP with extensions" - uses: shivammathur/setup-php@v2 - with: - coverage: none - extensions: mbstring - php-version: 8.1 - - - name: "Install locked dependencies with composer" - run: composer install --no-interaction --no-progress --no-suggest - - - name: "Run localheinz/composer-normalize" - run: composer normalize - - - name: "Commit fixes" - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: Normalize composer.json - - php-cs-fixer: - name: "Fix PHP codestyle with php-cs-fixer" - - runs-on: ubuntu-latest - - steps: - - name: "Checkout" - uses: actions/checkout@v2 - with: - ref: ${{ github.head_ref }} - - - name: "Install PHP with extensions" - uses: shivammathur/setup-php@v2 - with: - coverage: none - extensions: mbstring - php-version: 8.1 - - - name: "Install dependencies with composer" - run: composer install --no-interaction --no-progress --no-suggest - - - name: "Run php-cs-fixer" - run: vendor/bin/php-cs-fixer fix - - - name: "Commit fixes" - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: Apply php-cs-fixer changes - - static-code-analysis: - name: "Static Code Analysis" - - runs-on: ubuntu-latest - - steps: - - name: "Checkout" - uses: actions/checkout@master - - - name: "Install PHP with extensions" - uses: shivammathur/setup-php@v2 - with: - coverage: none - extensions: mbstring - php-version: 8.1 - - - name: "Install dependencies with composer" - run: composer install --no-interaction --no-progress --no-suggest - - - name: "Run phpstan" - run: vendor/bin/phpstan analyse --configuration=phpstan.neon - - tests: - name: "Tests - PHP ${{ matrix.php-version }}, Illuminate ${{ matrix.illuminate }}, ${{ matrix.dependencies }}" - - runs-on: ubuntu-latest - - strategy: - matrix: - php-version: - - "7.4" - - "8.0" - - "8.1" - - "8.2" - - dependencies: - - lowest - - highest - - illuminate: - - ^8.73 - - ^9 - - ^10 - exclude: - - php-version: "7.4" - illuminate: ^9 - - php-version: "7.4" - illuminate: ^10 - - php-version: "8.0" - illuminate: ^10 - - steps: - - name: "Checkout" - uses: actions/checkout@master - - - name: "Install PHP with extensions" - uses: shivammathur/setup-php@v2 - with: - coverage: none - extensions: mbstring - php-version: "${{ matrix.php-version }}" - - - name: "Install illuminate" - run: composer require "illuminate/support:${{ matrix.illuminate }}" --no-interaction --no-update - - - name: "Install lowest dependencies with composer" - if: matrix.dependencies == 'lowest' - run: composer update --prefer-lowest --no-interaction --no-progress --no-suggest - - - name: "Install highest dependencies with composer" - if: matrix.dependencies == 'highest' - run: composer update --no-interaction --no-progress --no-suggest - - - name: "Run unit tests with phpunit/phpunit" - run: vendor/bin/phpunit - - code-coverage: - name: "Code Coverage" - - runs-on: ubuntu-latest - - steps: - - name: "Checkout" - uses: actions/checkout@master - - - name: "Install PHP with extensions" - uses: shivammathur/setup-php@v2 - with: - coverage: pcov - extensions: mbstring - php-version: 8.1 - - - name: "Install dependencies with composer" - run: composer install --no-interaction --no-progress --no-suggest - - - name: "Collect code coverage with Xdebug and phpunit/phpunit" - run: vendor/bin/phpunit --coverage-clover=.build/logs/clover.xml - - - name: "Send code coverage report to codecov.io" - uses: codecov/codecov-action@v2 - - mutation-tests: - name: "Mutation Tests" - - runs-on: ubuntu-latest - - steps: - - name: "Checkout" - uses: actions/checkout@master - - - name: "Install PHP with extensions" - uses: shivammathur/setup-php@v2 - with: - coverage: pcov - extensions: mbstring - php-version: 8.1 - - - name: "Install dependencies with composer" - run: composer install --no-interaction --no-progress --no-suggest - - - name: "Run mutation tests with infection/infection" - run: vendor/bin/infection --ignore-msi-with-no-mutations --min-covered-msi=60 --min-msi=60 diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml new file mode 100644 index 0000000..1f12316 --- /dev/null +++ b/.github/workflows/format.yml @@ -0,0 +1,52 @@ +# https://help.github.com/en/categories/automating-your-workflow-with-github-actions + +on: + pull_request: + push: + branches: + - master + +jobs: + composer-normalize: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref }} + + - uses: shivammathur/setup-php@v2 + with: + coverage: none + extensions: mbstring + php-version: 8.3 + + - run: composer install --no-interaction --no-progress --no-suggest + + - run: composer normalize + + - uses: stefanzweifel/git-auto-commit-action@v4 + with: + commit_message: Normalize composer.json + + php-cs-fixer: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref }} + + - uses: shivammathur/setup-php@v2 + with: + coverage: none + extensions: mbstring + php-version: 8.3 + + - run: composer install --no-interaction --no-progress --no-suggest + + - run: vendor/bin/php-cs-fixer fix + + - uses: stefanzweifel/git-auto-commit-action@v4 + with: + commit_message: Apply php-cs-fixer changes diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 0000000..aeb7479 --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,121 @@ +# https://help.github.com/en/categories/automating-your-workflow-with-github-actions + +on: + pull_request: + push: + branches: + - master + +jobs: + composer-validate: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - uses: shivammathur/setup-php@v2 + with: + coverage: none + extensions: mbstring + php-version: 8.3 + + - run: composer validate --strict + + static-code-analysis: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - uses: shivammathur/setup-php@v2 + with: + coverage: none + extensions: mbstring + php-version: 8.3 + + - run: composer install --no-interaction --no-progress --no-suggest + + - run: vendor/bin/phpstan analyse + + tests: + name: "Tests - PHP ${{ matrix.php-version }}, Illuminate ${{ matrix.illuminate }}, ${{ matrix.dependencies }}" + + runs-on: ubuntu-latest + + strategy: + matrix: + php-version: + - "7.4" + - "8.0" + - "8.1" + - "8.2" + - "8.3" + + dependencies: + - lowest + - highest + + illuminate: + - ^8.73 + - ^9 + - ^10 + exclude: + - php-version: "7.4" + illuminate: ^9 + - php-version: "7.4" + illuminate: ^10 + - php-version: "8.0" + illuminate: ^10 + + steps: + - uses: actions/checkout@v4 + + - uses: shivammathur/setup-php@v2 + with: + coverage: none + extensions: mbstring + php-version: "${{ matrix.php-version }}" + + - run: composer require "illuminate/support:${{ matrix.illuminate }}" --no-interaction --no-update + + - if: matrix.dependencies == 'lowest' + run: composer update --prefer-lowest --no-interaction --no-progress --no-suggest + + - if: matrix.dependencies == 'highest' + run: composer update --no-interaction --no-progress --no-suggest + + - run: vendor/bin/phpunit + + code-coverage: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - uses: shivammathur/setup-php@v2 + with: + coverage: pcov + extensions: mbstring + php-version: 8.3 + + - run: composer install --no-interaction --no-progress --no-suggest + + - run: vendor/bin/phpunit --coverage-clover=.build/logs/clover.xml + + - uses: codecov/codecov-action@v3 + + mutation-tests: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - uses: shivammathur/setup-php@v2 + with: + coverage: pcov + extensions: mbstring + php-version: 8.3 + + - run: composer install --no-interaction --no-progress --no-suggest + + - run: vendor/bin/infection --ignore-msi-with-no-mutations --min-covered-msi=60 --min-msi=60 diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e903e4..9bef553 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,12 @@ See [GitHub releases](https://github.com/mll-lab/php-utils/releases). ## Unreleased +## v1.10.0 + +### Added + +- Allow custom line separator in `CSVArray::toCSV()` + ## v1.9.0 ### Added diff --git a/src/CSVArray.php b/src/CSVArray.php index da49df6..fe7fc7f 100644 --- a/src/CSVArray.php +++ b/src/CSVArray.php @@ -51,26 +51,23 @@ public static function toArray(string $csv, string $delimiter = ';', string $enc } /** @param array> $data */ - public static function toCSV(array $data, string $delimiter = ';'): string + public static function toCSV(array $data, string $delimiter = ';', string $lineSeparator = "\r\n"): string { if ($data === []) { throw new \Exception('Array is empty'); } // Use the keys of the array as the headers of the CSV - $headerLine = Arr::first($data); - if (! is_array($headerLine)) { + $headerItem = Arr::first($data); + if (! is_array($headerItem)) { throw new \Exception('Missing column headers.'); } + $headerKeys = array_keys($headerItem); - $content = str_putcsv( - array_keys($headerLine), - $delimiter - ) - . "\r\n"; + $content = str_putcsv($headerKeys, $delimiter) . $lineSeparator; foreach ($data as $line) { - $content .= str_putcsv($line, $delimiter) . "\r\n"; + $content .= str_putcsv($line, $delimiter) . $lineSeparator; } return $content; diff --git a/tests/CSVArrayTest.php b/tests/CSVArrayTest.php index 1a70e34..87500f9 100644 --- a/tests/CSVArrayTest.php +++ b/tests/CSVArrayTest.php @@ -69,6 +69,27 @@ public function testEscapesDelimiter(): void ); } + public function testUnixLike(): void + { + self::assertSame( + << 1, + 'bar' => 2, + ], + ], + ',', + "\n" + ) + ); + } + public function testPrimitives(): void { self::assertSame(