From ba10c91f783b366794737bad6bf99cd27dd4860d Mon Sep 17 00:00:00 2001 From: smiley Date: Tue, 9 Feb 2016 21:06:42 +0100 Subject: [PATCH] :godmode: --- src/QRCode.php | 48 ++++++++++++++++----------------- tests/QRCodeTest.php | 63 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 76 insertions(+), 35 deletions(-) diff --git a/src/QRCode.php b/src/QRCode.php index db8efd639..109df0532 100644 --- a/src/QRCode.php +++ b/src/QRCode.php @@ -12,6 +12,10 @@ namespace chillerlan\QRCode; +use chillerlan\QRCode\Data\AlphaNum; +use chillerlan\QRCode\Data\Byte; +use chillerlan\QRCode\Data\Kanji; +use chillerlan\QRCode\Data\Number; use chillerlan\QRCode\Output\QROutputInterface; /** @@ -114,10 +118,12 @@ class QRCode{ $options = new QROptions; } - if(!array_key_exists($options->errorCorrectLevel, QRConst::RSBLOCK)){ + if(!in_array($options->errorCorrectLevel, QRConst::RSBLOCK, true)){ throw new QRCodeException('Invalid error correct level: '.$options->errorCorrectLevel); } + $this->errorCorrectLevel = $options->errorCorrectLevel; + switch(true){ case Util::isAlphaNum($data): $mode = Util::isNumber($data) ? QRConst::MODE_NUMBER : QRConst::MODE_ALPHANUM; @@ -130,18 +136,17 @@ class QRCode{ break; } - - $qrDataInterface = __NAMESPACE__.'\\Data\\'.[ - QRConst::MODE_ALPHANUM => 'AlphaNum', - QRConst::MODE_BYTE => 'Byte', - QRConst::MODE_KANJI => 'Kanji', - QRConst::MODE_NUMBER => 'Number', + $qrDataInterface = [ + QRConst::MODE_ALPHANUM => AlphaNum::class, + QRConst::MODE_BYTE => Byte::class, + QRConst::MODE_KANJI => Kanji::class, + QRConst::MODE_NUMBER => Number::class, ][$mode]; - $this->errorCorrectLevel = $options->errorCorrectLevel; - $this->typeNumber = intval($options->typeNumber); $this->qrDataInterface = new $qrDataInterface($data); + $this->typeNumber = intval($options->typeNumber); + if($this->typeNumber < 1 || $this->typeNumber > 10){ $this->typeNumber = $this->getTypeNumber($mode); } @@ -183,10 +188,10 @@ class QRCode{ */ public function getRawData(){ $minLostPoint = 0; - $pattern = 0; + $maskPattern = 0; - for($i = 0; $i < 8; $i++){ - $this->getMatrix(true, $i); + for($pattern = 0; $pattern <= 7; $pattern++){ + $this->getMatrix(true, $pattern); $lostPoint = 0; // LEVEL1 @@ -289,14 +294,14 @@ class QRCode{ $ratio = abs(100 * $darkCount / $this->pixelCount / $this->pixelCount - 50) / 5; $lostPoint += $ratio * 10; - if($i === 0 || $minLostPoint > $lostPoint){ + if($pattern === 0 || $minLostPoint > $lostPoint){ $minLostPoint = $lostPoint; - $pattern = $i; + $maskPattern = $pattern; } } - $this->getMatrix(false, $pattern); + $this->getMatrix(false, $maskPattern); return $this->matrix; } @@ -350,11 +355,6 @@ class QRCode{ * @throws \chillerlan\QRCode\QRCodeException */ protected function createData(){ - - if(!isset($this->errorCorrectLevel)){ - throw new QRCodeException('Invalid error correct level '.$this->errorCorrectLevel); - } - $this->bitBuffer->clear(); $MAX_BITS = QRConst::MAX_BITS; // php5 compat @@ -605,20 +605,20 @@ class QRCode{ /** * @param bool $test - * @param int $pattern + * @param int $maskPattern * * @throws \chillerlan\QRCode\QRCodeException */ - protected function getMatrix($test, $pattern){ + protected function getMatrix($test, $maskPattern){ $this->pixelCount = $this->typeNumber * 4 + 17; $this->matrix = array_fill(0, $this->pixelCount, array_fill(0, $this->pixelCount, null)); - $this->setTypeInfo($test, $pattern); + $this->setTypeInfo($test, $maskPattern); if($this->typeNumber >= 7){ $this->setTypeNumber($test); } - $this->mapData($pattern); + $this->mapData($maskPattern); } } diff --git a/tests/QRCodeTest.php b/tests/QRCodeTest.php index 248223615..8f0b3a0e7 100644 --- a/tests/QRCodeTest.php +++ b/tests/QRCodeTest.php @@ -11,13 +11,11 @@ namespace chillerlan\QRCodeTest; +use chillerlan\QRCode\Output\QRString; use chillerlan\QRCode\QRCode; use chillerlan\QRCode\QRConst; use chillerlan\QRCode\QROptions; -use chillerlan\QRCode\Output\QRImage; -use chillerlan\QRCode\Output\QRImageOptions; -use chillerlan\QRCode\Output\QRString; -use chillerlan\QRCode\Output\QRStringOptions; +use ReflectionClass; class QRCodeTest extends \PHPUnit_Framework_TestCase{ @@ -31,15 +29,21 @@ class QRCodeTest extends \PHPUnit_Framework_TestCase{ */ protected $output; + /** + * @var \ReflectionClass + */ + protected $reflectionClass; + protected function setUp(){ $this->options = new QROptions; $this->output = new QRString; + $this->reflectionClass = new ReflectionClass(QRCode::class); } public function testInstance(){ $this->assertInstanceOf(QRString::class, $this->output); $this->assertInstanceOf(QROptions::class, $this->options); - $this->assertInstanceOf(QRCode::class, new QRCode('foobar', $this->output, $this->options)); + $this->assertInstanceOf(QRCode::class, $this->reflectionClass->newInstanceArgs(['foobar', $this->output, $this->options])); } public function stringDataProvider(){ @@ -55,7 +59,7 @@ class QRCodeTest extends \PHPUnit_Framework_TestCase{ * @dataProvider stringDataProvider */ public function testDataCoverage($data){ - (new QRCode($data, new QRString))->getRawData(); + (new QRCode($data, $this->output))->getRawData(); } /** @@ -66,7 +70,7 @@ class QRCodeTest extends \PHPUnit_Framework_TestCase{ foreach(QRConst::RSBLOCK as $eclevel => $y){ $this->options->typeNumber = $type; $this->options->errorCorrectLevel = $eclevel; - $this->assertInstanceOf(QRCode::class, new QRCode($data, new QRString, $this->options)); + $this->assertInstanceOf(QRCode::class, new QRCode($data, $this->output, $this->options)); } } } @@ -76,7 +80,42 @@ class QRCodeTest extends \PHPUnit_Framework_TestCase{ */ public function testTypeAutoOverride($data){ $this->options->typeNumber = QRCode::TYPE_05; - new QRCode($data, new QRString, $this->options); + new QRCode($data, $this->output, $this->options); + } + + + public function getTypeNumberDataProvider(){ + return [ + [true, QRCode::TYPE_05, 'foobar'], + [false, QRCode::TYPE_05, 'foobar'], + [true, QRCode::TYPE_10, 'foobar'], + [false, QRCode::TYPE_10, 'foobar'], + [true, QRCode::TYPE_05, '1234567890'], + [false, QRCode::TYPE_05, '1234567890'], + [true, QRCode::TYPE_10, '1234567890'], + [false, QRCode::TYPE_10, '1234567890'], + [true, QRCode::TYPE_05, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 $%*+-./:'], + [false, QRCode::TYPE_05, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 $%*+-./:'], + [true, QRCode::TYPE_10, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 $%*+-./:'], + [false, QRCode::TYPE_10, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 $%*+-./:'], + [true, QRCode::TYPE_05, '茗荷'], + [false, QRCode::TYPE_05, '茗荷'], + [true, QRCode::TYPE_10, '茗荷'], + [false, QRCode::TYPE_10, '茗荷'], + ]; + } + + /** + * @dataProvider getTypeNumberDataProvider + */ + public function testInternalGetTypeNumber($test, $type, $data){ + $method = $this->reflectionClass->getMethod('getMatrix'); + $method->setAccessible(true); + $this->options->typeNumber = $type; + + for($i = 0; $i <= 7; $i++){ + $method->invokeArgs($this->reflectionClass->newInstanceArgs([$data, $this->output, $this->options]), [$test, $i]); + } } /** @@ -84,7 +123,7 @@ class QRCodeTest extends \PHPUnit_Framework_TestCase{ * @expectedExceptionMessage No data given. */ public function testNoDataException(){ - new QRCode('', new QRString); + $this->reflectionClass->newInstanceArgs(['', $this->output]); } /** @@ -93,7 +132,7 @@ class QRCodeTest extends \PHPUnit_Framework_TestCase{ */ public function testErrorCorrectLevelException(){ $this->options->errorCorrectLevel = 42; - new QRCode('foobar', new QRString, $this->options); + $this->reflectionClass->newInstanceArgs(['foobar', $this->output, $this->options]); } /** @@ -103,7 +142,9 @@ class QRCodeTest extends \PHPUnit_Framework_TestCase{ public function testCodeLengthOverflowException(){ $this->options->typeNumber = QRCode::TYPE_01; $this->options->errorCorrectLevel = QRCode::ERROR_CORRECT_LEVEL_H; - (new QRCode('ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 $%*+-./:', new QRString, $this->options))->getRawData(); + + $method = $this->reflectionClass->getMethod('getRawData'); + $method->invoke($this->reflectionClass->newInstanceArgs(['ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 $%*+-./:', $this->output, $this->options])); } }