Sfoglia il codice sorgente

:octocat: allow for ECI encoded numeric and alphanum segments (???), see https://github.com/chillerlan/php-qrcode/discussions/289

smiley 1 anno fa
parent
commit
53b52b7134
3 ha cambiato i file con 20 aggiunte e 11 eliminazioni
  1. 1 1
      examples/reader.php
  2. 17 8
      src/Data/ECI.php
  3. 2 2
      tests/Data/ECITest.php

+ 1 - 1
examples/reader.php

@@ -24,7 +24,7 @@ try{
 	var_dump($result);
 }
 catch(Throwable $e){
-	echo $e->getMessage();
+	printf("%s(%s): %s\n%s", $e->getFile(), $e->getLine(), $e->getMessage(), $e->getTraceAsString());
 }
 
 exit;

+ 17 - 8
src/Data/ECI.php

@@ -129,17 +129,12 @@ final class ECI extends QRDataModeAbstract{
 	public static function decodeSegment(BitBuffer $bitBuffer, int $versionNumber):string{
 		$eciCharset = self::parseValue($bitBuffer);
 		$nextMode   = $bitBuffer->read(4);
-
-		if($nextMode !== Mode::BYTE){
-			throw new QRCodeDataException(sprintf('ECI designator followed by invalid mode: "%04b"', $nextMode));
-		}
-
-		$data     = Byte::decodeSegment($bitBuffer, $versionNumber);
-		$encoding = $eciCharset->getName();
+		$data       = self::decodeModeSegment($nextMode, $bitBuffer, $versionNumber);
+		$encoding   = $eciCharset->getName();
 
 		if($encoding === null){
 			// The spec isn't clear on this mode; see
-			// section 6.4.5: t does not say which encoding to assuming
+			// section 6.4.5: it does not say which encoding to assuming
 			// upon decoding. I have seen ISO-8859-1 used as well as
 			// Shift_JIS -- without anything like an ECI designator to
 			// give a hint.
@@ -153,4 +148,18 @@ final class ECI extends QRDataModeAbstract{
 		return mb_convert_encoding($data, mb_internal_encoding(), $encoding);
 	}
 
+	/**
+	 * @throws \chillerlan\QRCode\Data\QRCodeDataException
+	 */
+	private static function decodeModeSegment(int $mode, BitBuffer $bitBuffer, int $versionNumber):string{
+
+		switch(true){
+			case $mode === Mode::NUMBER:   return Number::decodeSegment($bitBuffer, $versionNumber);
+			case $mode === Mode::ALPHANUM: return AlphaNum::decodeSegment($bitBuffer, $versionNumber);
+			case $mode === Mode::BYTE:     return Byte::decodeSegment($bitBuffer, $versionNumber);
+		}
+
+		throw new QRCodeDataException(sprintf('ECI designator followed by invalid mode: "%04b"', $mode));
+	}
+
 }

+ 2 - 2
tests/Data/ECITest.php

@@ -12,7 +12,7 @@ namespace chillerlan\QRCodeTest\Data;
 
 use chillerlan\QRCode\QROptions;
 use chillerlan\QRCode\Common\{BitBuffer, ECICharset, Mode};
-use chillerlan\QRCode\Data\{Byte, ECI, Number, QRCodeDataException, QRData, QRDataModeInterface};
+use chillerlan\QRCode\Data\{Byte, ECI, Hanzi, QRCodeDataException, QRData, QRDataModeInterface};
 use PHPUnit\Framework\TestCase;
 
 /**
@@ -125,7 +125,7 @@ final class ECITest extends TestCase{
 		/** @var \chillerlan\QRCode\Data\QRDataModeInterface[] $segments */
 		$segments    = $this->getDataSegments();
 		// follow the ECI segment by a non-8bit-byte segment
-		$segments[1] = new Number('1');
+		$segments[1] = new Hanzi(self::testData);
 		$bitBuffer   = (new QRData($options, $segments))->getBitBuffer();
 		// verify the ECI mode indicator
 		$this::assertSame(Mode::ECI, $bitBuffer->read(4));