Просмотр исходного кода

Merge branch 'master' into php-7.4

# Conflicts:
#	composer.json
#	src/Output/QROutputAbstract.php
#	src/QROptionsTrait.php
codemasher 6 лет назад
Родитель
Сommit
76afbbb70d

+ 9 - 14
README.md

@@ -65,18 +65,12 @@ Profit!
 - [gaara 嘎啦](https://github.com/xutengx/gaara)
 
 ### Usage
-We want to encode this data into a QRcode image:
+We want to encode this URI for a mobile authenticator into a QRcode image:
 ```php
-// 10 reasons why QR codes are awesome
-$data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s';
-
-// no, for serious, we want to display a QR code for a mobile authenticator
 $data = 'otpauth://totp/test?secret=B3JX4VCVJDVNXNZ5&issuer=chillerlan.net';
-```
 
-Quick and simple:
-```php
-echo '<img src="'.(new QRCode)->render($data).'" />';
+//quick and simple:
+echo '<img src="'.(new QRCode)->render($data).'" alt="QR Code" />';
 ```
 
 <p align="center">
@@ -160,7 +154,7 @@ To map the values and properly render the modules for the given `QROutputInterfa
 ```php
 $options = new QROptions;
 
-// for HTML and SVG
+// for HTML, SVG and ImageMagick
 $options->moduleValues = [
 	// finder
 	1536 => '#A71111', // dark (true)
@@ -201,8 +195,6 @@ $options->moduleValues = [
 ];
 ```
 
-Combined with a custom output interface and your imagination you can create some cool effects that way!
-
 #### Custom `QROutputInterface`
 Instead of bloating your code you can simply create your own output interface by extending `QROutputAbstract`. Have a look at the [built-in output modules](https://github.com/chillerlan/php-qrcode/tree/master/src/Output).
 
@@ -270,7 +262,7 @@ $myCustomOptions = new MyCustomOptions($myOptions);
 
 // using the SettingsContainerInterface
 $myCustomOptions = new class($myOptions) extends SettingsContainerAbstract{
-	use QROptions, MyCustomOptionsTrait;
+	use QROptionsTrait, MyCustomOptionsTrait;
 };
 
 ```
@@ -329,6 +321,9 @@ property | type | default | allowed | description
 `$eol` | string | `PHP_EOL` | * | newline string (HTML, SVG, TEXT)
 `$scale` | int | 5 | * | size of a QR code pixel (SVG, IMAGE_*), HTML -> via CSS
 `$cssClass` | string | `null` | * | a common css class
+`$svgOpacity` | float | 1.0 | 0...1 | 
+`$svgDefs` | string | * | * | anything between [`<defs>`](https://developer.mozilla.org/docs/Web/SVG/Element/defs)
+`$svgViewBoxSize` | int | `null` | * | a positive integer which defines width/height of the [viewBox attribute](https://css-tricks.com/scale-svg/#article-header-id-3)
 `$textDark` | string | '🔴' | * | string substitute for dark
 `$textLight` | string | '⭕' | * | string substitute for light
 `$markupDark` | string | '#000' | * | markup substitute for dark (CSS value)
@@ -359,7 +354,7 @@ method | return | description
 name | light (false) | dark (true) | description
 ---- | ------------- | ----------- | -----------
 `M_NULL` | 0 | - | module not set (should never appear. if so, there's an error)
-`M_DARKMODULE` | - (2) | 512 | once per matrix at `$xy = [8, 4 * $version + 9]`
+`M_DARKMODULE` | - | 512 | once per matrix at `$xy = [8, 4 * $version + 9]`
 `M_DATA` | 4 | 1024 | the actual encoded data
 `M_FINDER` | 6 | 1536 | the 7x7 finder patterns
 `M_SEPARATOR` | 8 | - | separator lines around the finder patterns

+ 2 - 1
composer.json

@@ -25,12 +25,13 @@
 	],
 	"require": {
 		"php": "^7.4",
+		"ext-gd": "*",
 		"ext-json": "*",
 		"ext-mbstring": "*",
 		"chillerlan/php-settings-container": "^1.1"
 	},
 	"require-dev": {
-		"phpunit/phpunit": "^8.2"
+		"phpunit/phpunit": "^8.3"
 	},
 	"suggest": {
 		"chillerlan/php-authenticator": "^3.0"

+ 4 - 2
src/Data/AlphaNum.php

@@ -14,6 +14,8 @@ namespace chillerlan\QRCode\Data;
 
 use chillerlan\QRCode\QRCode;
 
+use function array_search, ord, sprintf;
+
 /**
  * Alphanumeric mode: 0 to 9, A to Z, space, $ % * + - . / :
  */
@@ -42,13 +44,13 @@ class AlphaNum extends QRDataAbstract{
 	 * @throws \chillerlan\QRCode\Data\QRCodeDataException
 	 */
 	protected function getCharCode(string $chr):int{
-		$i = \array_search($chr, $this::ALPHANUM_CHAR_MAP);
+		$i = array_search($chr, $this::ALPHANUM_CHAR_MAP);
 
 		if($i !== false){
 			return $i;
 		}
 
-		throw new QRCodeDataException('illegal char: "'.$chr.'" ['.\ord($chr).']');
+		throw new QRCodeDataException(sprintf('illegal char: "%s" [%d]', $chr, ord($chr)));
 	}
 
 }

+ 3 - 1
src/Data/Byte.php

@@ -14,6 +14,8 @@ namespace chillerlan\QRCode\Data;
 
 use chillerlan\QRCode\QRCode;
 
+use function ord;
+
 /**
  * Byte mode, ISO-8859-1 or UTF-8
  */
@@ -30,7 +32,7 @@ class Byte extends QRDataAbstract{
 		$i = 0;
 
 		while($i < $this->strlen){
-			$this->bitBuffer->put(\ord($data[$i]), 8);
+			$this->bitBuffer->put(ord($data[$i]), 8);
 			$i++;
 		}
 

+ 7 - 5
src/Data/Kanji.php

@@ -14,6 +14,8 @@ namespace chillerlan\QRCode\Data;
 
 use chillerlan\QRCode\QRCode;
 
+use function mb_strlen, ord, sprintf, strlen;
+
 /**
  * Kanji mode: double-byte characters from the Shift JIS character set
  */
@@ -27,17 +29,17 @@ class Kanji extends QRDataAbstract{
 	 * @inheritdoc
 	 */
 	protected function getLength(string $data):int{
-		return \mb_strlen($data, 'SJIS');
+		return mb_strlen($data, 'SJIS');
 	}
 
 	/**
 	 * @throws \chillerlan\QRCode\Data\QRCodeDataException
 	 */
 	protected function write(string $data):void{
-		$len = \strlen($data);
+		$len = strlen($data);
 
 		for($i = 0; $i + 1 < $len; $i += 2){
-			$c = ((0xff & \ord($data[$i])) << 8) | (0xff & \ord($data[$i + 1]));
+			$c = ((0xff & ord($data[$i])) << 8) | (0xff & ord($data[$i + 1]));
 
 			if(0x8140 <= $c && $c <= 0x9FFC){
 				$c -= 0x8140;
@@ -46,7 +48,7 @@ class Kanji extends QRDataAbstract{
 				$c -= 0xC140;
 			}
 			else{
-				throw new QRCodeDataException('illegal char at '.($i + 1).' ['.$c.']');
+				throw new QRCodeDataException(sprintf('illegal char at %d [%d]', $i + 1, $c));
 			}
 
 			$this->bitBuffer->put((($c >> 8) & 0xff) * 0xC0 + ($c & 0xff), 13);
@@ -54,7 +56,7 @@ class Kanji extends QRDataAbstract{
 		}
 
 		if($i < $len){
-			throw new QRCodeDataException('illegal char at '.($i + 1));
+			throw new QRCodeDataException(sprintf('illegal char at %d', $i + 1));
 		}
 
 	}

+ 4 - 2
src/Data/MaskPatternTester.php

@@ -12,6 +12,8 @@
 
 namespace chillerlan\QRCode\Data;
 
+use function abs, call_user_func;
+
 /**
  * The sole purpose of this class is to receive a QRMatrix object and run the pattern tests on it.
  *
@@ -46,7 +48,7 @@ class MaskPatternTester{
 		$penalty  = 0;
 
 		for($level = 1; $level <= 4; $level++){
-			$penalty += \call_user_func([$this, 'testLevel'.$level]);
+			$penalty += call_user_func([$this, 'testLevel'.$level]);
 		}
 
 		return (int)$penalty;
@@ -194,7 +196,7 @@ class MaskPatternTester{
 			}
 		}
 
-		return (\abs(100 * $count / $this->moduleCount / $this->moduleCount - 50) / 5) * 10;
+		return (abs(100 * $count / $this->moduleCount / $this->moduleCount - 50) / 5) * 10;
 	}
 
 }

+ 8 - 7
src/Data/Number.php

@@ -14,6 +14,8 @@ namespace chillerlan\QRCode\Data;
 
 use chillerlan\QRCode\QRCode;
 
+use function ord, sprintf, substr;
+
 /**
  * Numeric mode: decimal digits 0 through 9
  */
@@ -30,18 +32,18 @@ class Number extends QRDataAbstract{
 		$i = 0;
 
 		while($i + 2 < $this->strlen){
-			$this->bitBuffer->put($this->parseInt(\substr($data, $i, 3)), 10);
+			$this->bitBuffer->put($this->parseInt(substr($data, $i, 3)), 10);
 			$i += 3;
 		}
 
 		if($i < $this->strlen){
 
 			if($this->strlen - $i === 1){
-				$this->bitBuffer->put($this->parseInt(\substr($data, $i, $i + 1)), 4);
+				$this->bitBuffer->put($this->parseInt(substr($data, $i, $i + 1)), 4);
 			}
 			// @codeCoverageIgnoreStart
 			elseif($this->strlen - $i === 2){
-				$this->bitBuffer->put($this->parseInt(\substr($data, $i, $i + 2)), 7);
+				$this->bitBuffer->put($this->parseInt(substr($data, $i, $i + 2)), 7);
 			}
 			// @codeCoverageIgnoreEnd
 
@@ -57,14 +59,13 @@ class Number extends QRDataAbstract{
 
 		$len = strlen($string);
 		for($i = 0; $i < $len; $i++){
-			$c = \ord($string[$i]);
+			$c = ord($string[$i]);
 
 			if(!in_array($string[$i], $this::NUMBER_CHAR_MAP, true)){
-				throw new QRCodeDataException('illegal char: "'.$string[$i].'" ['.$c.']');
+				throw new QRCodeDataException(sprintf('illegal char: "%s" [%d]', $string[$i], $c));
 			}
 
-			$c = $c - \ord('0');
-
+			$c   = $c - 48; // ord('0')
 			$num = $num * 10 + $c;
 		}
 

+ 19 - 18
src/Data/QRDataAbstract.php

@@ -16,6 +16,8 @@ use chillerlan\QRCode\{QRCode, QRCodeException};
 use chillerlan\QRCode\Helpers\{BitBuffer, Polynomial};
 use chillerlan\Settings\SettingsContainerInterface;
 
+use function array_fill, array_merge, count, max, mb_convert_encoding, mb_detect_encoding, range, sprintf, strlen;
+
 /**
  * Processes the binary data and maps it on a matrix which is then being returned
  */
@@ -78,7 +80,7 @@ abstract class QRDataAbstract implements QRDataInterface{
 	public function setData(string $data):QRDataInterface{
 
 		if($this->datamode === QRCode::DATA_KANJI){
-			$data = \mb_convert_encoding($data, 'SJIS', \mb_detect_encoding($data));
+			$data = mb_convert_encoding($data, 'SJIS', mb_detect_encoding($data));
 		}
 
 		$this->strlen  = $this->getLength($data);
@@ -126,14 +128,14 @@ abstract class QRDataAbstract implements QRDataInterface{
 			 }
 		 }
 
-		throw new QRCodeDataException('invalid version number: '.$this->version);
+		throw new QRCodeDataException(sprintf('invalid version number: %d', $this->version));
 	}
 
 	/**
 	 * returns the byte count of the $data string
 	 */
 	protected function getLength(string $data):int{
-		return \strlen($data);
+		return strlen($data);
 	}
 
 	/**
@@ -145,7 +147,7 @@ abstract class QRDataAbstract implements QRDataInterface{
 		$maxlength = 0;
 
 		// guess the version number within the given range
-		foreach(\range($this->options->versionMin, $this->options->versionMax) as $version){
+		foreach(range($this->options->versionMin, $this->options->versionMax) as $version){
 			$maxlength = $this::MAX_LENGTH[$version][QRCode::DATA_MODES[$this->datamode]][QRCode::ECC_MODES[$this->options->eccLevel]];
 
 			if($this->strlen <= $maxlength){
@@ -153,7 +155,7 @@ abstract class QRDataAbstract implements QRDataInterface{
 			}
 		}
 
-		throw new QRCodeDataException('data exceeds '.$maxlength.' characters');
+		throw new QRCodeDataException(sprintf('data exceeds %d characters', $maxlength));
 	}
 
 	/**
@@ -169,7 +171,6 @@ abstract class QRDataAbstract implements QRDataInterface{
 	protected function writeBitBuffer(string $data):QRDataInterface{
 		$this->bitBuffer = new BitBuffer;
 
-		// @todo: fixme, get real length
 		$MAX_BITS = $this::MAX_BITS[$this->version][QRCode::ECC_MODES[$this->options->eccLevel]];
 
 		$this->bitBuffer
@@ -182,7 +183,7 @@ abstract class QRDataAbstract implements QRDataInterface{
 
 		// there was an error writing the BitBuffer data, which is... unlikely.
 		if($this->bitBuffer->length > $MAX_BITS){
-			throw new QRCodeException('code length overflow. ('.$this->bitBuffer->length.' > '.$MAX_BITS.'bit)'); // @codeCoverageIgnore
+			throw new QRCodeException(sprintf('code length overflow. (%d > %d bit)', $this->bitBuffer->length, $MAX_BITS)); // @codeCoverageIgnore
 		}
 
 		// end code.
@@ -224,13 +225,13 @@ abstract class QRDataAbstract implements QRDataInterface{
 	protected function maskECC():array{
 		[$l1, $l2, $b1, $b2] = $this::RSBLOCKS[$this->version][QRCode::ECC_MODES[$this->options->eccLevel]];
 
-		$rsBlocks     = \array_fill(0, $l1, [$b1, $b2]);
+		$rsBlocks     = array_fill(0, $l1, [$b1, $b2]);
 		$rsCount      = $l1 + $l2;
-		$this->ecdata = \array_fill(0, $rsCount, null);
+		$this->ecdata = array_fill(0, $rsCount, null);
 		$this->dcdata = $this->ecdata;
 
 		if($l2 > 0){
-			$rsBlocks = \array_merge($rsBlocks, \array_fill(0, $l2, [$b1 + 1, $b2 + 1]));
+			$rsBlocks = array_merge($rsBlocks, array_fill(0, $l2, [$b1 + 1, $b2 + 1]));
 		}
 
 		$totalCodeCount = 0;
@@ -242,9 +243,9 @@ abstract class QRDataAbstract implements QRDataInterface{
 			[$rsBlockTotal, $dcCount] = $block;
 
 			$ecCount            = $rsBlockTotal - $dcCount;
-			$maxDcCount         = \max($maxDcCount, $dcCount);
-			$maxEcCount         = \max($maxEcCount, $ecCount);
-			$this->dcdata[$key] = \array_fill(0, $dcCount, null);
+			$maxDcCount         = max($maxDcCount, $dcCount);
+			$maxEcCount         = max($maxEcCount, $ecCount);
+			$this->dcdata[$key] = array_fill(0, $dcCount, null);
 
 			foreach($this->dcdata[$key] as $a => $_z){
 				$this->dcdata[$key][$a] = 0xff & $this->bitBuffer->buffer[$a + $offset];
@@ -261,13 +262,13 @@ abstract class QRDataAbstract implements QRDataInterface{
 			$totalCodeCount += $rsBlockTotal;
 		}
 
-		$data  = \array_fill(0, $totalCodeCount, null);
+		$data  = array_fill(0, $totalCodeCount, null);
 		$index = 0;
 
 		$mask = function(array $arr, int $count) use (&$data, &$index, $rsCount){
 			for($x = 0; $x < $count; $x++){
 				for($y = 0; $y < $rsCount; $y++){
-					if($x < \count($arr[$y])){
+					if($x < count($arr[$y])){
 						$data[$index] = $arr[$y][$x];
 						$index++;
 					}
@@ -293,19 +294,19 @@ abstract class QRDataAbstract implements QRDataInterface{
 			$rsPoly->multiply($modPoly->getNum());
 		}
 
-		$rsPolyCount = \count($rsPoly->getNum());
+		$rsPolyCount = count($rsPoly->getNum());
 
 		$modPoly
 			->setNum($this->dcdata[$key], $rsPolyCount - 1)
 			->mod($rsPoly->getNum())
 		;
 
-		$this->ecdata[$key] = \array_fill(0, $rsPolyCount - 1, null);
+		$this->ecdata[$key] = array_fill(0, $rsPolyCount - 1, null);
 		$num                = $modPoly->getNum();
 
 		return [
 			$num,
-			\count($num) - \count($this->ecdata[$key]),
+			count($num) - count($this->ecdata[$key]),
 		];
 	}
 

+ 16 - 14
src/Data/QRMatrix.php

@@ -14,6 +14,8 @@ namespace chillerlan\QRCode\Data;
 
 use chillerlan\QRCode\QRCode;
 
+use function array_fill, array_key_exists, array_push, array_unshift, count, floor, in_array, max, min, range;
+
 /**
  * @link http://www.thonky.com/qr-code-tutorial/format-version-information
  */
@@ -29,7 +31,7 @@ class QRMatrix{
 	public const M_FORMAT     = 0x0e;
 	public const M_VERSION    = 0x10;
 	public const M_QUIETZONE  = 0x12;
-	public const M_LOGO       = 0x14; // @todo
+#	public const M_LOGO       = 0x14; // @todo
 
 	public const M_TEST       = 0xff;
 
@@ -184,18 +186,18 @@ class QRMatrix{
 	 */
 	public function __construct(int $version, int $eclevel){
 
-		if(!\in_array($version, \range(1, 40), true)){
+		if(!in_array($version, range(1, 40), true)){
 			throw new QRCodeDataException('invalid QR Code version');
 		}
 
-		if(!\array_key_exists($eclevel, QRCode::ECC_MODES)){
+		if(!array_key_exists($eclevel, QRCode::ECC_MODES)){
 			throw new QRCodeDataException('invalid ecc level');
 		}
 
 		$this->version     = $version;
 		$this->eclevel     = $eclevel;
 		$this->moduleCount = $this->version * 4 + 17;
-		$this->matrix      = \array_fill(0, $this->moduleCount, \array_fill(0, $this->moduleCount, $this::M_NULL));
+		$this->matrix      = array_fill(0, $this->moduleCount, array_fill(0, $this->moduleCount, $this::M_NULL));
 	}
 
 	/**
@@ -365,7 +367,7 @@ class QRMatrix{
 	 */
 	public function setTimingPattern():QRMatrix{
 
-		foreach(\range(8, $this->moduleCount - 8 - 1) as $i){
+		foreach(range(8, $this->moduleCount - 8 - 1) as $i){
 
 			if($this->matrix[6][$i] !== $this::M_NULL || $this->matrix[$i][6] !== $this::M_NULL){
 				continue;
@@ -389,7 +391,7 @@ class QRMatrix{
 		if($bits !== false){
 
 			for($i = 0; $i < 18; $i++){
-				$a = (int)\floor($i / 3);
+				$a = (int)floor($i / 3);
 				$b = $i % 3 + $this->moduleCount - 8 - 3;
 				$v = !$test && (($bits >> $i) & 1) === 1;
 
@@ -450,23 +452,23 @@ class QRMatrix{
 		}
 
 		$size = $size !== null
-			? \max(0, \min($size, \floor($this->moduleCount / 2)))
+			? max(0, min($size, floor($this->moduleCount / 2)))
 			: 4;
 
 		for($y = 0; $y < $this->moduleCount; $y++){
 			for($i = 0; $i < $size; $i++){
-				\array_unshift($this->matrix[$y], $this::M_QUIETZONE);
-				\array_push($this->matrix[$y], $this::M_QUIETZONE);
+				array_unshift($this->matrix[$y], $this::M_QUIETZONE);
+				array_push($this->matrix[$y], $this::M_QUIETZONE);
 			}
 		}
 
 		$this->moduleCount += ($size * 2);
 
-		$r = \array_fill(0, $this->moduleCount, $this::M_QUIETZONE);
+		$r = array_fill(0, $this->moduleCount, $this::M_QUIETZONE);
 
 		for($i = 0; $i < $size; $i++){
-			\array_unshift($this->matrix, $r);
-			\array_push($this->matrix, $r);
+			array_unshift($this->matrix, $r);
+			array_push($this->matrix, $r);
 		}
 
 		return $this;
@@ -482,7 +484,7 @@ class QRMatrix{
 	 */
 	public function mapData(array $data, int $maskPattern):QRMatrix{
 		$this->maskPattern = $maskPattern;
-		$byteCount         = \count($data);
+		$byteCount         = count($data);
 		$size              = $this->moduleCount - 1;
 
 		for($i = $size, $y = $size, $inc = -1, $byteIndex = 0, $bitIndex  = 7; $i > 0; $i -= 2){
@@ -550,7 +552,7 @@ class QRMatrix{
 				$y % 2,
 				$x % 3,
 				$a % 3,
-				(\floor($y / 2) + \floor($x / 3)) % 2,
+				(floor($y / 2) + floor($x / 3)) % 2,
 				$m % 2 + $m % 3,
 				($m % 2 + $m % 3) % 2,
 				($m % 3 + $a % 2) % 2

+ 4 - 2
src/Helpers/BitBuffer.php

@@ -12,6 +12,8 @@
 
 namespace chillerlan\QRCode\Helpers;
 
+use function count, floor;
+
 class BitBuffer{
 
 	/** @var int[] */
@@ -45,9 +47,9 @@ class BitBuffer{
 	 *
 	 */
 	public function putBit(bool $bit):BitBuffer{
-		$bufIndex = \floor($this->length / 8);
+		$bufIndex = floor($this->length / 8);
 
-		if(\count($this->buffer) <= $bufIndex){
+		if(count($this->buffer) <= $bufIndex){
 			$this->buffer[] = 0;
 		}
 

+ 7 - 5
src/Helpers/Polynomial.php

@@ -14,6 +14,8 @@ namespace chillerlan\QRCode\Helpers;
 
 use chillerlan\QRCode\QRCodeException;
 
+use function array_fill, count, sprintf;
+
 /**
  * @link http://www.thonky.com/qr-code-tutorial/error-correction-coding
  */
@@ -78,13 +80,13 @@ class Polynomial{
 	 */
 	public function setNum(array $num, int $shift = null):Polynomial{
 		$offset = 0;
-		$numCount = \count($num);
+		$numCount = count($num);
 
 		while($offset < $numCount && $num[$offset] === 0){
 			$offset++;
 		}
 
-		$this->num = \array_fill(0, $numCount - $offset + ($shift ?? 0), 0);
+		$this->num = array_fill(0, $numCount - $offset + ($shift ?? 0), 0);
 
 		for($i = 0; $i < $numCount - $offset; $i++){
 			$this->num[$i] = $num[$i + $offset];
@@ -97,7 +99,7 @@ class Polynomial{
 	 *
 	 */
 	public function multiply(array $e):Polynomial{
-		$n = \array_fill(0, \count($this->num) + \count($e) - 1, 0);
+		$n = array_fill(0, count($this->num) + count($e) - 1, 0);
 
 		foreach($this->num as $i => $vi){
 			$vi = $this->glog($vi);
@@ -119,7 +121,7 @@ class Polynomial{
 	public function mod(array $e):Polynomial{
 		$n = $this->num;
 
-		if(\count($n) - \count($e) < 0){
+		if(count($n) - count($e) < 0){
 			return $this;
 		}
 
@@ -140,7 +142,7 @@ class Polynomial{
 	public function glog(int $n):int{
 
 		if($n < 1){
-			throw new QRCodeException('log('.$n.')');
+			throw new QRCodeException(sprintf('log(%s)', $n));
 		}
 
 		return Polynomial::table[$n][1];

+ 26 - 21
src/Output/QRImage.php

@@ -13,6 +13,11 @@
 namespace chillerlan\QRCode\Output;
 
 use chillerlan\QRCode\QRCode;
+use Exception;
+
+use function array_values, base64_encode, call_user_func, count, imagecolorallocate, imagecolortransparent,
+	imagecreatetruecolor, imagedestroy, imagefilledrectangle, imagegif, imagejpeg, imagepng, in_array,
+	is_array, ob_end_clean, ob_get_contents, ob_start, range, sprintf;
 
 /**
  * Converts the matrix into GD images, raw or base64 output
@@ -42,13 +47,13 @@ class QRImage extends QROutputAbstract{
 		foreach($this::DEFAULT_MODULE_VALUES as $M_TYPE => $defaultValue){
 			$v = $this->options->moduleValues[$M_TYPE] ?? null;
 
-			if(!\is_array($v) || \count($v) < 3){
+			if(!is_array($v) || count($v) < 3){
 				$this->moduleValues[$M_TYPE] = $defaultValue
 					? [0, 0, 0]
 					: [255, 255, 255];
 			}
 			else{
-				$this->moduleValues[$M_TYPE] = \array_values($v);
+				$this->moduleValues[$M_TYPE] = array_values($v);
 			}
 
 		}
@@ -59,18 +64,18 @@ class QRImage extends QROutputAbstract{
 	 *
 	 */
 	public function dump(string $file = null):string{
-		$this->image = \imagecreatetruecolor($this->length, $this->length);
+		$this->image = imagecreatetruecolor($this->length, $this->length);
 
 		// avoid: Indirect modification of overloaded property $imageTransparencyBG has no effect
 		// https://stackoverflow.com/a/10455217
 		$tbg = $this->options->imageTransparencyBG;
-		$background  = \imagecolorallocate($this->image, ...$tbg);
+		$background  = imagecolorallocate($this->image, ...$tbg);
 
-		if((bool)$this->options->imageTransparent && \in_array($this->options->outputType, $this::TRANSPARENCY_TYPES, true)){
-			\imagecolortransparent($this->image, $background);
+		if((bool)$this->options->imageTransparent && in_array($this->options->outputType, $this::TRANSPARENCY_TYPES, true)){
+			imagecolortransparent($this->image, $background);
 		}
 
-		\imagefilledrectangle($this->image, 0, 0, $this->length, $this->length, $background);
+		imagefilledrectangle($this->image, 0, 0, $this->length, $this->length, $background);
 
 		foreach($this->matrix->matrix() as $y => $row){
 			foreach($row as $x => $M_TYPE){
@@ -81,7 +86,7 @@ class QRImage extends QROutputAbstract{
 		$imageData = $this->dumpImage($file);
 
 		if((bool)$this->options->imageBase64){
-			$imageData = 'data:image/'.$this->options->outputType.';base64,'.\base64_encode($imageData);
+			$imageData = sprintf('data:image/%s;base64,%s', $this->options->outputType, base64_encode($imageData));
 		}
 
 		return $imageData;
@@ -91,13 +96,13 @@ class QRImage extends QROutputAbstract{
 	 *
 	 */
 	protected function setPixel(int $x, int $y, array $rgb):void{
-		\imagefilledrectangle(
+		imagefilledrectangle(
 			$this->image,
 			$x * $this->scale,
 			$y * $this->scale,
 			($x + 1) * $this->scale,
 			($y + 1) * $this->scale,
-			\imagecolorallocate($this->image, ...$rgb)
+			imagecolorallocate($this->image, ...$rgb)
 		);
 	}
 
@@ -111,22 +116,22 @@ class QRImage extends QROutputAbstract{
 	protected function dumpImage(string $file = null):string{
 		$file ??= $this->options->cachefile;
 
-		\ob_start();
+		ob_start();
 
 		try{
-			\call_user_func([$this, $this->outputMode ?? $this->defaultMode]);
+			call_user_func([$this, $this->outputMode ?? $this->defaultMode]);
 		}
 		// not going to cover edge cases
 		// @codeCoverageIgnoreStart
-		catch(\Exception $e){
+		catch(Exception $e){
 			throw new QRCodeOutputException($e->getMessage());
 		}
 		// @codeCoverageIgnoreEnd
 
-		$imageData = \ob_get_contents();
-		\imagedestroy($this->image);
+		$imageData = ob_get_contents();
+		imagedestroy($this->image);
 
-		\ob_end_clean();
+		ob_end_clean();
 
 		if($file !== null){
 			$this->saveToFile($imageData, $file);
@@ -139,10 +144,10 @@ class QRImage extends QROutputAbstract{
 	 * @return void
 	 */
 	protected function png():void{
-		\imagepng(
+		imagepng(
 			$this->image,
 			null,
-			\in_array($this->options->pngCompression, \range(-1, 9), true)
+			in_array($this->options->pngCompression, range(-1, 9), true)
 				? $this->options->pngCompression
 				: -1
 		);
@@ -153,17 +158,17 @@ class QRImage extends QROutputAbstract{
 	 * @return void
 	 */
 	protected function gif():void{
-		\imagegif($this->image);
+		imagegif($this->image);
 	}
 
 	/**
 	 * @return void
 	 */
 	protected function jpg():void{
-		\imagejpeg(
+		imagejpeg(
 			$this->image,
 			null,
-			\in_array($this->options->jpegQuality, \range(0, 100), true)
+			in_array($this->options->jpegQuality, range(0, 100), true)
 				? $this->options->jpegQuality
 				: 85
 		);

+ 2 - 0
src/Output/QRImagick.php

@@ -14,6 +14,8 @@ namespace chillerlan\QRCode\Output;
 
 use Imagick, ImagickDraw, ImagickPixel;
 
+use function is_string;
+
 /**
  * ImageMagick output module
  * requires ext-imagick

+ 8 - 6
src/Output/QRMarkup.php

@@ -14,6 +14,8 @@ namespace chillerlan\QRCode\Output;
 
 use chillerlan\QRCode\QRCode;
 
+use function is_string, sprintf, strip_tags, trim;
+
 /**
  * Converts the matrix into markup types: HTML, SVG, ...
  */
@@ -34,13 +36,13 @@ class QRMarkup extends QROutputAbstract{
 		foreach($this::DEFAULT_MODULE_VALUES as $M_TYPE => $defaultValue){
 			$v = $this->options->moduleValues[$M_TYPE] ?? null;
 
-			if(!\is_string($v)){
+			if(!is_string($v)){
 				$this->moduleValues[$M_TYPE] = $defaultValue
 					? $this->options->markupDark
 					: $this->options->markupLight;
 			}
 			else{
-				$this->moduleValues[$M_TYPE] = \trim(\strip_tags($v), '\'"');
+				$this->moduleValues[$M_TYPE] = trim(strip_tags($v), '\'"');
 			}
 
 		}
@@ -78,7 +80,7 @@ class QRMarkup extends QROutputAbstract{
 	protected function svg():string{
 		$matrix = $this->matrix->matrix();
 
-		$svg = \sprintf($this->svgHeader, $this->options->cssClass, $this->options->svgViewBoxSize ?? $this->moduleCount)
+		$svg = sprintf($this->svgHeader, $this->options->cssClass, $this->options->svgViewBoxSize ?? $this->moduleCount)
 		       .$this->options->eol
 		       .'<defs>'.$this->options->svgDefs.'</defs>'
 		       .$this->options->eol;
@@ -100,14 +102,14 @@ class QRMarkup extends QROutputAbstract{
 							$start = $x;
 						}
 
-						if($row[$x + 1] ?? false){
+						if(isset($row[$x + 1])){
 							continue;
 						}
 					}
 
 					if($count > 0){
 						$len = $count;
-						$path .= 'M' .$start. ' ' .$y. ' h'.$len.' v1 h-'.$len.'Z ';
+						$path .= sprintf('M%s %s h%s v1 h-%sZ ', $start, $y, $len, $len);
 
 						// reset count
 						$count = 0;
@@ -119,7 +121,7 @@ class QRMarkup extends QROutputAbstract{
 			}
 
 			if(!empty($path)){
-				$svg .= '<path class="qr-'.$M_TYPE.' '.$this->options->cssClass.'" stroke="transparent" fill="'.$value.'" fill-opacity="'.$this->options->svgOpacity.'" d="'.$path.'" />';
+				$svg .= sprintf('<path class="qr-%s %s" stroke="transparent" fill="%s" fill-opacity="%s" d="%s" />', $M_TYPE, $this->options->cssClass, $value, $this->options->svgOpacity, $path);
 			}
 
 		}

+ 8 - 6
src/Output/QROutputAbstract.php

@@ -15,6 +15,8 @@ namespace chillerlan\QRCode\Output;
 use chillerlan\QRCode\{Data\QRMatrix, QRCode};
 use chillerlan\Settings\SettingsContainerInterface;
 
+use function call_user_func, dirname, file_put_contents, get_called_class, in_array, is_writable, sprintf;
+
 /**
  * common output abstract
  */
@@ -46,9 +48,9 @@ abstract class QROutputAbstract implements QROutputInterface{
 		$this->scale       = $this->options->scale;
 		$this->length      = $this->moduleCount * $this->scale;
 
-		$class = \get_called_class();
+		$class = get_called_class();
 
-		if(\array_key_exists($class, QRCode::OUTPUT_MODES) && \in_array($this->options->outputType, QRCode::OUTPUT_MODES[$class])){
+		if(isset(QRCode::OUTPUT_MODES[$class]) && in_array($this->options->outputType, QRCode::OUTPUT_MODES[$class])){
 			$this->outputMode = $this->options->outputType;
 		}
 
@@ -67,18 +69,18 @@ abstract class QROutputAbstract implements QROutputInterface{
 	 */
 	protected function saveToFile(string $data, string $file):bool{
 
-		if(!\is_writable(\dirname($file))){
-			throw new QRCodeOutputException('Could not write data to cache file: '.$file);
+		if(!is_writable(dirname($file))){
+			throw new QRCodeOutputException(sprintf('Could not write data to cache file: %s', $file));
 		}
 
-		return (bool)\file_put_contents($file, $data);
+		return (bool)file_put_contents($file, $data);
 	}
 
 	/**
 	 *
 	 */
 	public function dump(string $file = null){
-		$data = \call_user_func([$this, $this->outputMode ?? $this->defaultMode]);
+		$data = call_user_func([$this, $this->outputMode ?? $this->defaultMode]);
 		$file ??= $this->options->cachefile;
 
 		if($file !== null){

+ 5 - 3
src/Output/QRString.php

@@ -14,6 +14,8 @@ namespace chillerlan\QRCode\Output;
 
 use chillerlan\QRCode\QRCode;
 
+use function implode, is_string, json_encode;
+
 /**
  * Converts the matrix data into string types
  */
@@ -55,17 +57,17 @@ class QRString extends QROutputAbstract{
 				$r[] = $this->moduleValues[$M_TYPE];
 			}
 
-			$str[] = \implode('', $r);
+			$str[] = implode('', $r);
 		}
 
-		return \implode($this->options->eol, $str);
+		return implode($this->options->eol, $str);
 	}
 
 	/**
 	 *
 	 */
 	protected function json():string{
-		return \json_encode($this->matrix->matrix());
+		return json_encode($this->matrix->matrix());
 	}
 
 }

+ 13 - 11
src/QRCode.php

@@ -20,6 +20,8 @@ use chillerlan\QRCode\Output\{
 };
 use chillerlan\Settings\SettingsContainerInterface;
 
+use function array_search, call_user_func_array, class_exists, in_array, mb_internal_encoding, min, ord, strlen;
+
 /**
  * Turns a text string into a Model 2 QR Code
  *
@@ -102,9 +104,9 @@ class QRCode{
 	 */
 	public function __construct(SettingsContainerInterface $options = null){
 		// save the current mb encoding (in case it differs from UTF-8)
-		$this->mbCurrentEncoding = \mb_internal_encoding();
+		$this->mbCurrentEncoding = mb_internal_encoding();
 		// use UTF-8 from here on
-		\mb_internal_encoding('UTF-8');
+		mb_internal_encoding('UTF-8');
 
 		$this->options = $options ?? new QROptions;
 	}
@@ -114,7 +116,7 @@ class QRCode{
 	 */
 	public function __destruct(){
 		// restore the previous mb_internal_encoding, so that we don't mess up the rest of the script
-		\mb_internal_encoding($this->mbCurrentEncoding);
+		mb_internal_encoding($this->mbCurrentEncoding);
 	}
 
 	/**
@@ -166,7 +168,7 @@ class QRCode{
 			$penalties[$pattern] = $tester->testPattern();
 		}
 
-		return \array_search(\min($penalties), $penalties, true);
+		return array_search(min($penalties), $penalties, true);
 	}
 
 	/**
@@ -179,7 +181,7 @@ class QRCode{
 		foreach(['Number', 'AlphaNum', 'Kanji', 'Byte'] as $mode){
 			$dataInterface = __NAMESPACE__.'\\Data\\'.$mode;
 
-			if(\call_user_func_array([$this, 'is'.$mode], [$data]) && \class_exists($dataInterface)){
+			if(call_user_func_array([$this, 'is'.$mode], [$data]) && class_exists($dataInterface)){
 				return new $dataInterface($this->options, $data);
 			}
 
@@ -195,13 +197,13 @@ class QRCode{
 	 */
 	protected function initOutputInterface(string $data):QROutputInterface{
 
-		if($this->options->outputType === $this::OUTPUT_CUSTOM && \class_exists($this->options->outputInterface)){
+		if($this->options->outputType === $this::OUTPUT_CUSTOM && class_exists($this->options->outputInterface)){
 			return new $this->options->outputInterface($this->options, $this->getMatrix($data));
 		}
 
 		foreach($this::OUTPUT_MODES as $outputInterface => $modes){
 
-			if(in_array($this->options->outputType, $modes, true) && \class_exists($outputInterface)){
+			if(in_array($this->options->outputType, $modes, true) && class_exists($outputInterface)){
 				return new $outputInterface($this->options, $this->getMatrix($data));
 			}
 
@@ -228,10 +230,10 @@ class QRCode{
 	 * checks is a given $string matches the characters of a given charmap, returns false on the first invalid occurence.
 	 */
 	protected function checkString(string $string, array $charmap):bool{
-		$len = \strlen($string);
+		$len = strlen($string);
 
 		for($i = 0; $i < $len; $i++){
-			if(!\in_array($string[$i], $charmap, true)){
+			if(!in_array($string[$i], $charmap, true)){
 				return false;
 			}
 		}
@@ -244,10 +246,10 @@ class QRCode{
 	 */
 	public function isKanji(string $string):bool{
 		$i   = 0;
-		$len = \strlen($string);
+		$len = strlen($string);
 
 		while($i + 1 < $len){
-			$c = ((0xff&\ord($string[$i])) << 8)|(0xff&\ord($string[$i + 1]));
+			$c = ((0xff & ord($string[$i])) << 8) | (0xff & ord($string[$i + 1]));
 
 			if(!($c >= 0x8140 && $c <= 0x9FFC) && !($c >= 0xE040 && $c <= 0xEBBF)){
 				return false;

+ 24 - 27
src/QROptionsTrait.php

@@ -12,6 +12,8 @@
 
 namespace chillerlan\QRCode;
 
+use function array_values, count, is_array, is_numeric, max, min, sprintf;
+
 trait QROptionsTrait{
 
 	/**
@@ -186,33 +188,28 @@ trait QROptionsTrait{
 	protected array $moduleValues;
 
 	/**
-	 * set/clamp some special values, call the parent setter otherwise
+	 * clamp min/max version number
 	 */
-	public function __set(string $property, $value):void{
-
-		if($property === 'versionMin'){
-			$this->setMinMaxVersion($value, $this->versionMax);
-
-			return;
-		}
-		elseif($property === 'versionMax'){
-			$this->setMinMaxVersion($this->versionMin, $value);
-
-			return;
-		}
+	protected function setMinMaxVersion(int $versionMin, int $versionMax):void{
+		$min = max(1, min(40, $versionMin));
+		$max = max(1, min(40, $versionMax));
 
-		parent::__set($property, $value);
+		$this->versionMin = min($min, $max);
+		$this->versionMax = max($min, $max);
 	}
 
 	/**
-	 * clamp min/max version number
+	 *
 	 */
-	protected function setMinMaxVersion(int $versionMin, int $versionMax):void{
-		$min = \max(1, \min(40, $versionMin));
-		$max = \max(1, \min(40, $versionMax));
+	protected function set_versionMin(int $version):void{
+		$this->setMinMaxVersion($version, $this->versionMax);
+	}
 
-		$this->versionMin = \min($min, $max);
-		$this->versionMax = \max($min, $max);
+	/**
+	 *
+	 */
+	protected function set_versionMax(int $version):void{
+		$this->setMinMaxVersion($this->versionMin, $version);
 	}
 
 	/**
@@ -221,7 +218,7 @@ trait QROptionsTrait{
 	protected function set_eccLevel(int $eccLevel):void{
 
 		if(!isset(QRCode::ECC_MODES[$eccLevel])){
-			throw new QRCodeException('Invalid error correct level: '.$eccLevel);
+			throw new QRCodeException(sprintf('Invalid error correct level: %s', $eccLevel));
 		}
 
 		$this->eccLevel = $eccLevel;
@@ -233,7 +230,7 @@ trait QROptionsTrait{
 	protected function set_maskPattern(int $maskPattern):void{
 
 		if($maskPattern !== QRCode::MASK_PATTERN_AUTO){
-			$this->maskPattern = \max(0, \min(7, $maskPattern));
+			$this->maskPattern = max(0, min(7, $maskPattern));
 		}
 
 	}
@@ -244,7 +241,7 @@ trait QROptionsTrait{
 	protected function set_imageTransparencyBG($imageTransparencyBG):void{
 
 		// invalid value - set to white as default
-		if(!\is_array($imageTransparencyBG) || \count($imageTransparencyBG) < 3){
+		if(!is_array($imageTransparencyBG) || count($imageTransparencyBG) < 3){
 			$this->imageTransparencyBG = [255, 255, 255];
 
 			return;
@@ -252,16 +249,16 @@ trait QROptionsTrait{
 
 		foreach($imageTransparencyBG as $k => $v){
 
-			if(!\is_numeric($v)){
+			if(!is_numeric($v)){
 				throw new QRCodeException('Invalid RGB value.');
 			}
 
 			// clamp the values
-			$this->imageTransparencyBG[$k] = \max(0, \min(255, (int)$v));
+			$this->imageTransparencyBG[$k] = max(0, min(255, (int)$v));
 		}
 
 		// use the array values to not run into errors with the spread operator (...$arr)
-		$this->imageTransparencyBG = \array_values($this->imageTransparencyBG);
+		$this->imageTransparencyBG = array_values($this->imageTransparencyBG);
 	}
 
 	/**
@@ -270,7 +267,7 @@ trait QROptionsTrait{
 	protected function set_version(int $version):void{
 
 		if($version !== QRCode::VERSION_AUTO){
-			$this->version = \max(1, \min(40, $version));
+			$this->version = max(1, min(40, $version));
 		}
 
 	}