Skip to content

Commit

Permalink
Allow to inject unsupported character replacements
Browse files Browse the repository at this point in the history
  • Loading branch information
sprain committed Jun 23, 2024
1 parent eb15893 commit 0e99f88
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 10 deletions.
5 changes: 3 additions & 2 deletions src/QrBill.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ public function addAlternativeScheme(AlternativeScheme $alternativeScheme): self
/**
* @throws InvalidQrBillDataException
*/
public function getQrCode(?string $fileFormat = null): QrCode
public function getQrCode(?string $fileFormat = null, array $unsupportedCharacterReplacements = []): QrCode

Check failure on line 168 in src/QrBill.php

View workflow job for this annotation

GitHub Actions / Static code analysis

Method Sprain\SwissQrBill\QrBill::getQrCode() has parameter $unsupportedCharacterReplacements with no value type specified in iterable type array.
{
if (!$this->isValid()) {
throw new InvalidQrBillDataException(
Expand All @@ -175,7 +175,8 @@ public function getQrCode(?string $fileFormat = null): QrCode

return QrCode::create(
$this->getQrCodeContent(),
$fileFormat
$fileFormat,
$unsupportedCharacterReplacements
);
}

Expand Down
24 changes: 19 additions & 5 deletions src/QrCode/QrCode.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ final class QrCode
public const FILE_FORMAT_PNG = 'png';
public const FILE_FORMAT_SVG = 'svg';

public const SUPPORTED_CHARACTERS = 'a-zA-Z0-9.,;:\'"+\-\/()?*\[\]{}|`´~ !^#%&<>÷=@_$£àáâäçèéêëìíîïñòóôöùúûüýßÀÁÂÄÇÈÉÊËÌÍÎÏÒÓÔÖÙÚÛÜÑ';

private const SUPPORTED_FILE_FORMATS = [
self::FILE_FORMAT_PNG,
self::FILE_FORMAT_SVG
Expand All @@ -34,17 +36,18 @@ final class QrCode
/** @var array<string, bool> $writerOptions */
private array $writerOptions = [SvgWriter::WRITER_OPTION_FORCE_XLINK_HREF => true];

public static function create(string $data, string $fileFormat = null): self
public static function create(string $data, string $fileFormat = null, array $unsupportedCharacterReplacements = []): self

Check failure on line 39 in src/QrCode/QrCode.php

View workflow job for this annotation

GitHub Actions / Static code analysis

Method Sprain\SwissQrBill\QrCode\QrCode::create() has parameter $unsupportedCharacterReplacements with no value type specified in iterable type array.
{
if (null === $fileFormat) {
$fileFormat = self::FILE_FORMAT_SVG;
}

return new self($data, $fileFormat);
return new self($data, $fileFormat, $unsupportedCharacterReplacements);
}

private function __construct(string $data, string $fileFormat)
private function __construct(string $data, string $fileFormat, array $unsupportedCharacterReplacements)

Check failure on line 48 in src/QrCode/QrCode.php

View workflow job for this annotation

GitHub Actions / Static code analysis

Method Sprain\SwissQrBill\QrCode\QrCode::__construct() has parameter $unsupportedCharacterReplacements with no value type specified in iterable type array.
{
$data = $this->replaceUnsupportedCharacters($data, $unsupportedCharacterReplacements);
$data = $this->cleanUnsupportedCharacters($data);

if (class_exists(ErrorCorrectionLevel\ErrorCorrectionLevelMedium::class)) {
Expand Down Expand Up @@ -129,11 +132,22 @@ public function avoidCompactSvgs(): void
}
}

private function replaceUnsupportedCharacters(string $data, array $unsupportedCharacterReplacements): string

Check failure on line 135 in src/QrCode/QrCode.php

View workflow job for this annotation

GitHub Actions / Static code analysis

Method Sprain\SwissQrBill\QrCode\QrCode::replaceUnsupportedCharacters() has parameter $unsupportedCharacterReplacements with no value type specified in iterable type array.
{
foreach ($unsupportedCharacterReplacements as $character => $replacement) {
if (preg_match("/([^" . self::SUPPORTED_CHARACTERS . "])/u", $character)) {
$data = str_replace($character, $replacement, $data);
}
}

return $data;
}

private function cleanUnsupportedCharacters(string $data): string
{
$pattern = '/([^a-zA-Z0-9.,;:\'"+\-\/()?*\[\]{}|`´~ !^#%&<>÷=@_$£àáâäçèéêëìíîïñòóôöùúûüýßÀÁÂÄÇÈÉÊËÌÍÎÏÒÓÔÖÙÚÛÜÑ\\n])/u';
$supportedCharacters = self::SUPPORTED_CHARACTERS . "\\n";

return preg_replace($pattern, '', $data);
return preg_replace("/([^$supportedCharacters])/u", '', $data);
}

private function setWriterByExtension(string $extension): void
Expand Down
37 changes: 37 additions & 0 deletions tests/QrBillTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,43 @@ public function testMaximumTwoAlternativeSchemesAreAllowed()
$this->assertFalse($qrBill->isValid());
}

public function testItReplacesUnsupportedCharacters()
{
$qrBill = $this->createQrBill([
'header',
'creditorInformationQrIban',
'creditorWithUnsupportedCharacters',
'paymentAmountInformation',
'paymentReferenceQr',
]);

$this->assertStringContainsString(
'Team We are the Champions!',
$qrBill->getQrCode()->getText()
);
}

public function testItConsidersReplacementCharacters()
{
$qrBill = $this->createQrBill([
'header',
'creditorInformationQrIban',
'creditorWithUnsupportedCharacters',
'paymentAmountInformation',
'paymentReferenceQr',
]);

$unsupportedCharacterReplacements = [
'«' => '"',
'»' => '"',
];

$this->assertStringContainsString(
'Team "We are the Champions!"',
$qrBill->getQrCode(null, $unsupportedCharacterReplacements)->getText()
);
}

public function testCatchInvalidData()
{
$this->expectException(InvalidQrBillDataException::class);
Expand Down
40 changes: 37 additions & 3 deletions tests/QrCode/QrCodeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,43 @@ public function stringProvider()
}

/**
* @dataProvider invalidCharactersCodeProvider
* @dataProvider replacementCharactersProvider
*/
public function testItRemovesInvalidCharacters(string $providedString, string $expectedString): void
public function testItReplacesUnsupportedCharacters(string $providedString, array $replacements, string $expectedString): void
{
$qrCode = QrCode::create($providedString, null, $replacements);

$this->assertEquals(
$expectedString,
$qrCode->getText()
);
}

public function replacementCharactersProvider(): array
{
return [
'replaceSpecificUnsupportedCharacters' => [
'providedString' => '«This is a test!»',
'replacements' => [
'«' => '"',
'»' => '"'
],
'expectedString' => '"This is a test!"'
],
'ignoreReplacementsOfSupportedCharacters' => [
'providedString' => '«This is a test!»',
'replacements' => [
't' => 'a',
],
'expectedString' => 'This is a test!'
],
];
}

/**
* @dataProvider unsupportedCharactersProvider
*/
public function testItRemovesUnsupportedCharacters(string $providedString, string $expectedString): void
{
$qrCode = QrCode::create($providedString);

Expand All @@ -132,7 +166,7 @@ public function testItRemovesInvalidCharacters(string $providedString, string $e
);
}

public function invalidCharactersCodeProvider(): array
public function unsupportedCharactersProvider(): array
{
return [
'keepAllAllowedCharacters' => [
Expand Down
15 changes: 15 additions & 0 deletions tests/TestQrBillCreatorTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,11 @@ public function creditor(QrBill &$qrBill)
$qrBill->setCreditor($this->structuredAddress());
}

public function creditorWithUnsupportedCharacters(QrBill &$qrBill)
{
$qrBill->setCreditor($this->addressWithUnsupportedCharacters());
}

public function creditorMediumLong(QrBill &$qrBill)
{
$qrBill->setCreditor($this->mediumLongAddress());
Expand Down Expand Up @@ -392,6 +397,16 @@ public function longAddress()
);
}

public function addressWithUnsupportedCharacters()
{
return CombinedAddress::create(
'Team «We are the Champions!»',
'Rue examplaire 22a',
'1000 Lausanne',
'CH'
);
}

public function invalidAddress()
{
return CombinedAddress::create(
Expand Down

0 comments on commit 0e99f88

Please sign in to comment.