Skip to content

Commit 433eea3

Browse files
authored
feat: QiaxcelImport allows to create an import file for a Qiaxcel device from Qiagen
feat: QiaxcelImport allows to create an import file for a Qiaxcel device from Qiagen
1 parent 44ea99c commit 433eea3

File tree

7 files changed

+188
-74
lines changed

7 files changed

+188
-74
lines changed

.github/CONTRIBUTING.md

Lines changed: 0 additions & 59 deletions
This file was deleted.

CONTRIBUTING.md

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,68 @@
1-
# Commit Message Convention
1+
# CONTRIBUTING
22

3-
This project uses [Conventional Commits](https://conventionalcommits.org/) for automated version management and release notes generation.
3+
We are using [GitHub Actions](https://github.com/features/actions) as a continuous integration system.
44

5-
## Format
5+
For details, see [`workflows`](.github/workflows).
6+
7+
## Code Style
8+
9+
We are using [`friendsofphp/php-cs-fixer`](https://github.com/friendsofphp/php-cs-fixer) to automatically format the code.
10+
11+
Run
12+
13+
```bash
14+
make fix
15+
```
16+
17+
to automatically format the code.
18+
19+
## Static Code Analysis
20+
21+
We are using [`phpstan/phpstan`](https://github.com/phpstan/phpstan) to statically analyze the code.
22+
23+
Run
24+
25+
```bash
26+
make stan
27+
```
28+
29+
to run a static code analysis.
30+
31+
## Tests
32+
33+
We are using [`phpunit/phpunit`](https://github.com/sebastianbergmann/phpunit) to drive the development.
34+
35+
Run
36+
37+
```bash
38+
make test
39+
```
40+
41+
to run all the tests.
42+
43+
## Extra lazy?
44+
45+
Run
46+
47+
```bash
48+
make
49+
```
50+
51+
to enforce coding standards, perform a static code analysis, and run tests!
52+
53+
:bulb: Run
54+
55+
```bash
56+
make help
57+
```
58+
59+
to display a list of available targets with corresponding descriptions.
60+
61+
## Commit Message Convention
62+
63+
This project uses [Conventional Commits](https://conventionalcommits.org) for automated version management and release notes generation.
64+
65+
### Format
666

767
```
868
<type>[optional scope]: <description>
@@ -12,7 +72,7 @@ This project uses [Conventional Commits](https://conventionalcommits.org/) for a
1272
[optional footer(s)]
1373
```
1474

15-
## Types
75+
### Types
1676

1777
- **feat**: A new feature (triggers a minor version bump)
1878
- **fix**: A bug fix (triggers a patch version bump)
@@ -23,11 +83,11 @@ This project uses [Conventional Commits](https://conventionalcommits.org/) for a
2383
- **test**: Adding missing tests or correcting existing tests
2484
- **chore**: Changes to the build process or auxiliary tools and libraries
2585

26-
## Breaking Changes
86+
### Breaking Changes
2787

2888
Add `BREAKING CHANGE:` in the footer or append `!` after the type/scope to indicate breaking changes (triggers a major version bump).
2989

30-
## Examples
90+
### Examples
3191

3292
```
3393
feat: add support for PHP 8.4
@@ -39,7 +99,7 @@ feat(csv): add new export format
3999
BREAKING CHANGE: PHP 7.4 is no longer supported
40100
```
41101

42-
## Scopes (optional)
102+
### Scopes (optional)
43103

44104
You can use scopes to specify which part of the codebase is affected:
45105
- `csv`: CSV-related functionality

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,6 @@ test: vendor ## Runs auto-review, unit, and integration tests with phpunit
3636
vendor/bin/phpunit --cache-directory=.build/phpunit
3737

3838
vendor: composer.json
39-
composer validate --strict
4039
composer update
40+
composer validate --strict
4141
composer normalize

composer.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"mll-lab/graphql-php-scalars": "^6.4",
3232
"mll-lab/php-cs-fixer-config": "^5.10",
3333
"orchestra/testbench": "^6.47.1 || ^7.52 || ^8.33 || ^9.11 || ^10",
34+
"phpoffice/phpspreadsheet": "^1.2 || ^5.1",
3435
"phpstan/extension-installer": "^1",
3536
"phpstan/phpstan": "^1.8.11 || ^2.1.6",
3637
"phpstan/phpstan-deprecation-rules": "^1 || ^2.0.1",
@@ -43,6 +44,7 @@
4344
},
4445
"suggest": {
4546
"mll-lab/graphql-php-scalars": "To use the provided scalar types for GraphQL servers, requires version ^6.3",
47+
"phpoffice/phpspreadsheet": "Required if using QiaxcelImport",
4648
"spaze/phpstan-disallowed-calls": "Required when using the PHPStan configuration from rules.neon directly or through the extension installer"
4749
},
4850
"autoload": {

src/Microplate/AbstractMicroplate.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public function sortedWells(FlowDirection $flowDirection): Collection
4949
{
5050
return $this->wells()->sortBy(
5151
/** @param TWell $content */
52-
function ($content, string $key) use ($flowDirection): string { /** @phpstan-ignore missingType.parameter (is in template context) */
52+
function ($content, string $key) use ($flowDirection): string { // @phpstan-ignore missingType.parameter (is in template context)
5353
switch ($flowDirection->value) {
5454
case FlowDirection::ROW:
5555
return $key;
@@ -70,9 +70,9 @@ function ($content, string $key) use ($flowDirection): string { /** @phpstan-ign
7070
/** @return Collection<string, null> */
7171
public function freeWells(): Collection
7272
{
73-
return $this->wells()->filter(
73+
return $this->wells()->filter( // @phpstan-ignore return.type (generic wrongly interpreted)
7474
/** @param TWell $content */
75-
static fn ($content): bool => $content === self::EMPTY_WELL /** @phpstan-ignore missingType.parameter (is in template context) */
75+
static fn ($content): bool => $content === self::EMPTY_WELL // @phpstan-ignore missingType.parameter (is in template context)
7676
);
7777
}
7878

@@ -81,14 +81,14 @@ public function filledWells(): Collection
8181
{
8282
return $this->wells()->filter(
8383
/** @param TWell $content */
84-
static fn ($content): bool => $content !== self::EMPTY_WELL /** @phpstan-ignore missingType.parameter (is in template context) */
84+
static fn ($content): bool => $content !== self::EMPTY_WELL // @phpstan-ignore missingType.parameter (is in template context)
8585
);
8686
}
8787

8888
/** @return callable(TWell|null $content, string $coordinatesString): bool */
8989
public function matchRow(string $row): callable
9090
{
91-
return function ($content, string $coordinatesString) use ($row): bool { /** @phpstan-ignore missingType.parameter (is in template context) */
91+
return function ($content, string $coordinatesString) use ($row): bool { // @phpstan-ignore missingType.parameter (is in template context)
9292
$coordinates = Coordinates::fromString($coordinatesString, $this->coordinateSystem);
9393

9494
return $coordinates->row === $row;
@@ -98,7 +98,7 @@ public function matchRow(string $row): callable
9898
/** @return callable(TWell|null $content, string $coordinatesString): bool */
9999
public function matchColumn(int $column): callable
100100
{
101-
return function ($content, string $coordinatesString) use ($column): bool { /** @phpstan-ignore missingType.parameter (is in template context) */
101+
return function ($content, string $coordinatesString) use ($column): bool { // @phpstan-ignore missingType.parameter (is in template context)
102102
$coordinates = Coordinates::fromString($coordinatesString, $this->coordinateSystem);
103103

104104
return $coordinates->column === $column;
@@ -119,7 +119,7 @@ public function toWellWithCoordinateMapper(): callable
119119
public function toWellWithCoordinatesMapper(): callable
120120
{
121121
// @phpstan-ignore return.type (generic not inferred)
122-
return fn ($content, string $coordinatesString): WellWithCoordinates => new WellWithCoordinates( /** @phpstan-ignore missingType.parameter (is in template context) */
122+
return fn ($content, string $coordinatesString): WellWithCoordinates => new WellWithCoordinates( // @phpstan-ignore missingType.parameter (is in template context)
123123
$content,
124124
Coordinates::fromString($coordinatesString, $this->coordinateSystem)
125125
);

src/Qiaxcel/QiaxcelImport.php

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace MLL\Utils\Qiaxcel;
4+
5+
use Illuminate\Support\Str;
6+
use PhpOffice\PhpSpreadsheet\Cell\Cell;
7+
use PhpOffice\PhpSpreadsheet\IOFactory;
8+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
9+
10+
class QiaxcelImport
11+
{
12+
public string $fileName;
13+
14+
/** @var list<string> */
15+
protected array $entries;
16+
17+
public string $valueForEmptyCell;
18+
19+
/** @param list<string> $entries */
20+
public function __construct(
21+
string $fileName,
22+
array $entries,
23+
string $valueForEmptyCell = 'Leer'
24+
) {
25+
$this->fileName = $fileName;
26+
$this->entries = $entries;
27+
$this->valueForEmptyCell = $valueForEmptyCell;
28+
}
29+
30+
public function generate(): SpreadSheet
31+
{
32+
$sampleSheetData = [];
33+
foreach (array_chunk($this->entries, 12) as $entryChunks) {
34+
$sampleSheetRow = [];
35+
foreach ($entryChunks as $entryChunk) {
36+
$sampleSheetRow[] = Str::substr($entryChunk, 0, 36); // Maximum 36 characters in Qiaxcel
37+
}
38+
$sampleSheetData[] = $sampleSheetRow;
39+
}
40+
41+
$spreadsheet = new Spreadsheet();
42+
$spreadsheet->getActiveSheet()->fromArray($sampleSheetData);
43+
$this->fillEmptyCells($spreadsheet);
44+
45+
return $spreadsheet;
46+
}
47+
48+
public function generateAndSaveImportFile(): void
49+
{
50+
$spreadsheet = $this->generate();
51+
self::saveSampleSheet($this->fileName, $spreadsheet);
52+
}
53+
54+
public static function saveSampleSheet(string $fileName, Spreadsheet $spreadsheet): void
55+
{
56+
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
57+
$writer->save($fileName);
58+
}
59+
60+
private function fillEmptyCells(Spreadsheet &$spreadsheet): void
61+
{
62+
foreach (range(1, 8) as $number) {
63+
foreach (range('A', 'L') as $letter) {
64+
$cell = $spreadsheet->getActiveSheet()->getCell("{$letter}{$number}");
65+
if ($cell instanceof Cell) { // @phpstan-ignore instanceof.alwaysTrue
66+
$value = $cell->getValue();
67+
if ($value === '' || $value === null) {
68+
$cell->setValue($this->valueForEmptyCell);
69+
}
70+
}
71+
}
72+
}
73+
}
74+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace MLL\Utils\Tests\Qiaxcel;
4+
5+
use MLL\Utils\Qiaxcel\QiaxcelImport;
6+
use PHPUnit\Framework\TestCase;
7+
8+
final class QiaxcelImportTest extends TestCase
9+
{
10+
public function testGenerate(): void
11+
{
12+
$entries = [];
13+
foreach (range(1, 13) as $i) {
14+
$entries[] = "Test-Eintrag {$i}";
15+
}
16+
17+
$newQiaxcelImport = new QiaxcelImport('test.xlsx', $entries);
18+
19+
$spreadsheet = $newQiaxcelImport->generate();
20+
$worksheet = $spreadsheet->getActiveSheet();
21+
$cellA1 = $worksheet->getCell('A1');
22+
self::assertNotNull($cellA1); // @phpstan-ignore staticMethod.alreadyNarrowedType
23+
self::assertEquals('Test-Eintrag 1', $cellA1->getValue());
24+
$cellL1 = $worksheet->getCell('L1');
25+
self::assertNotNull($cellL1); // @phpstan-ignore staticMethod.alreadyNarrowedType
26+
self::assertSame('Test-Eintrag 12', $cellL1->getValue());
27+
$cellA2 = $worksheet->getCell('A2');
28+
self::assertNotNull($cellA2); // @phpstan-ignore staticMethod.alreadyNarrowedType
29+
self::assertSame('Test-Eintrag 13', $cellA2->getValue());
30+
$cellB2 = $worksheet->getCell('B2');
31+
self::assertNotNull($cellB2); // @phpstan-ignore staticMethod.alreadyNarrowedType
32+
self::assertSame('Leer', $cellB2->getValue());
33+
$cellL8 = $worksheet->getCell('L8');
34+
self::assertNotNull($cellL8); // @phpstan-ignore staticMethod.alreadyNarrowedType
35+
self::assertSame('Leer', $cellL8->getValue());
36+
}
37+
}

0 commit comments

Comments
 (0)