summaryrefslogtreecommitdiff
path: root/vendor/chillerlan/php-qrcode/src/QRCode.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/chillerlan/php-qrcode/src/QRCode.php')
-rwxr-xr-x[-rw-r--r--]vendor/chillerlan/php-qrcode/src/QRCode.php203
1 files changed, 103 insertions, 100 deletions
diff --git a/vendor/chillerlan/php-qrcode/src/QRCode.php b/vendor/chillerlan/php-qrcode/src/QRCode.php
index 91f7aa0eb..294a20d83 100644..100755
--- a/vendor/chillerlan/php-qrcode/src/QRCode.php
+++ b/vendor/chillerlan/php-qrcode/src/QRCode.php
@@ -13,51 +13,76 @@
namespace chillerlan\QRCode;
use chillerlan\QRCode\Data\{
- MaskPatternTester, QRCodeDataException, QRDataInterface, QRMatrix
+ AlphaNum, Byte, Kanji, MaskPatternTester, Number, QRCodeDataException, QRDataInterface, QRMatrix
};
use chillerlan\QRCode\Output\{
QRCodeOutputException, QRFpdf, QRImage, QRImagick, QRMarkup, QROutputInterface, QRString
};
use chillerlan\Settings\SettingsContainerInterface;
-use function array_search, call_user_func_array, class_exists, in_array, min, ord, strlen;
+use function call_user_func_array, class_exists, in_array, ord, strlen, strtolower, str_split;
/**
* Turns a text string into a Model 2 QR Code
*
- * @link https://github.com/kazuhikoarase/qrcode-generator/tree/master/php
- * @link http://www.qrcode.com/en/codes/model12.html
- * @link http://www.thonky.com/qr-code-tutorial/
+ * @see https://github.com/kazuhikoarase/qrcode-generator/tree/master/php
+ * @see http://www.qrcode.com/en/codes/model12.html
+ * @see https://www.swisseduc.ch/informatik/theoretische_informatik/qr_codes/docs/qr_standard.pdf
+ * @see https://en.wikipedia.org/wiki/QR_code
+ * @see http://www.thonky.com/qr-code-tutorial/
*/
class QRCode{
- /**
- * API constants
- */
- public const OUTPUT_MARKUP_HTML = 'html';
- public const OUTPUT_MARKUP_SVG = 'svg';
- public const OUTPUT_IMAGE_PNG = 'png';
- public const OUTPUT_IMAGE_JPG = 'jpg';
- public const OUTPUT_IMAGE_GIF = 'gif';
- public const OUTPUT_STRING_JSON = 'json';
- public const OUTPUT_STRING_TEXT = 'text';
- public const OUTPUT_IMAGICK = 'imagick';
- public const OUTPUT_FPDF = 'fpdf';
- public const OUTPUT_CUSTOM = 'custom';
-
+ /** @var int */
public const VERSION_AUTO = -1;
+ /** @var int */
public const MASK_PATTERN_AUTO = -1;
- public const ECC_L = 0b01; // 7%.
- public const ECC_M = 0b00; // 15%.
- public const ECC_Q = 0b11; // 25%.
- public const ECC_H = 0b10; // 30%.
+ // ISO/IEC 18004:2000 Table 2
+ /** @var int */
public const DATA_NUMBER = 0b0001;
+ /** @var int */
public const DATA_ALPHANUM = 0b0010;
+ /** @var int */
public const DATA_BYTE = 0b0100;
+ /** @var int */
public const DATA_KANJI = 0b1000;
+ /**
+ * References to the keys of the following tables:
+ *
+ * @see \chillerlan\QRCode\Data\QRDataInterface::MAX_LENGTH
+ *
+ * @var int[]
+ */
+ public const DATA_MODES = [
+ self::DATA_NUMBER => 0,
+ self::DATA_ALPHANUM => 1,
+ self::DATA_BYTE => 2,
+ self::DATA_KANJI => 3,
+ ];
+
+ // ISO/IEC 18004:2000 Tables 12, 25
+
+ /** @var int */
+ public const ECC_L = 0b01; // 7%.
+ /** @var int */
+ public const ECC_M = 0b00; // 15%.
+ /** @var int */
+ public const ECC_Q = 0b11; // 25%.
+ /** @var int */
+ public const ECC_H = 0b10; // 30%.
+
+ /**
+ * References to the keys of the following tables:
+ *
+ * @see \chillerlan\QRCode\Data\QRDataInterface::MAX_BITS
+ * @see \chillerlan\QRCode\Data\QRDataInterface::RSBLOCKS
+ * @see \chillerlan\QRCode\Data\QRMatrix::formatPattern
+ *
+ * @var int[]
+ */
public const ECC_MODES = [
self::ECC_L => 0,
self::ECC_M => 1,
@@ -65,13 +90,32 @@ class QRCode{
self::ECC_H => 3,
];
- public const DATA_MODES = [
- self::DATA_NUMBER => 0,
- self::DATA_ALPHANUM => 1,
- self::DATA_BYTE => 2,
- self::DATA_KANJI => 3,
- ];
+ /** @var string */
+ public const OUTPUT_MARKUP_HTML = 'html';
+ /** @var string */
+ public const OUTPUT_MARKUP_SVG = 'svg';
+ /** @var string */
+ public const OUTPUT_IMAGE_PNG = 'png';
+ /** @var string */
+ public const OUTPUT_IMAGE_JPG = 'jpg';
+ /** @var string */
+ public const OUTPUT_IMAGE_GIF = 'gif';
+ /** @var string */
+ public const OUTPUT_STRING_JSON = 'json';
+ /** @var string */
+ public const OUTPUT_STRING_TEXT = 'text';
+ /** @var string */
+ public const OUTPUT_IMAGICK = 'imagick';
+ /** @var string */
+ public const OUTPUT_FPDF = 'fpdf';
+ /** @var string */
+ public const OUTPUT_CUSTOM = 'custom';
+ /**
+ * Map of built-in output modules => capabilities
+ *
+ * @var string[][]
+ */
public const OUTPUT_MODES = [
QRMarkup::class => [
self::OUTPUT_MARKUP_SVG,
@@ -95,19 +139,33 @@ class QRCode{
];
/**
+ * Map of data mode => interface
+ *
+ * @var string[]
+ */
+ protected const DATA_INTERFACES = [
+ 'number' => Number::class,
+ 'alphanum' => AlphaNum::class,
+ 'kanji' => Kanji::class,
+ 'byte' => Byte::class,
+ ];
+
+ /**
+ * The settings container
+ *
* @var \chillerlan\QRCode\QROptions|\chillerlan\Settings\SettingsContainerInterface
*/
- protected $options;
+ protected SettingsContainerInterface $options;
/**
- * @var \chillerlan\QRCode\Data\QRDataInterface
+ * The selected data interface (Number, AlphaNum, Kanji, Byte)
*/
- protected $dataInterface;
+ protected QRDataInterface $dataInterface;
/**
* QRCode constructor.
*
- * @param \chillerlan\Settings\SettingsContainerInterface|null $options
+ * Sets the options instance, determines the current mb-encoding and sets it to UTF-8
*/
public function __construct(SettingsContainerInterface $options = null){
$this->options = $options ?? new QROptions;
@@ -116,9 +174,6 @@ class QRCode{
/**
* Renders a QR Code for the given $data and QROptions
*
- * @param string $data
- * @param string|null $file
- *
* @return mixed
*/
public function render(string $data, string $file = null){
@@ -128,9 +183,6 @@ class QRCode{
/**
* Returns a QRMatrix object for the given $data and current QROptions
*
- * @param string $data
- *
- * @return \chillerlan\QRCode\Data\QRMatrix
* @throws \chillerlan\QRCode\Data\QRCodeDataException
*/
public function getMatrix(string $data):QRMatrix{
@@ -142,7 +194,7 @@ class QRCode{
$this->dataInterface = $this->initDataInterface($data);
$maskPattern = $this->options->maskPattern === $this::MASK_PATTERN_AUTO
- ? $this->getBestMaskPattern()
+ ? (new MaskPatternTester($this->dataInterface))->getBestMaskPattern()
: $this->options->maskPattern;
$matrix = $this->dataInterface->initMatrix($maskPattern);
@@ -155,48 +207,23 @@ class QRCode{
}
/**
- * shoves a QRMatrix through the MaskPatternTester to find the lowest penalty mask pattern
- *
- * @see \chillerlan\QRCode\Data\MaskPatternTester
- *
- * @return int
- */
- protected function getBestMaskPattern():int{
- $penalties = [];
-
- for($pattern = 0; $pattern < 8; $pattern++){
- $tester = new MaskPatternTester($this->dataInterface->initMatrix($pattern, true));
-
- $penalties[$pattern] = $tester->testPattern();
- }
-
- return array_search(min($penalties), $penalties, true);
- }
-
- /**
* returns a fresh QRDataInterface for the given $data
*
- * @param string $data
- *
- * @return \chillerlan\QRCode\Data\QRDataInterface
* @throws \chillerlan\QRCode\Data\QRCodeDataException
*/
public function initDataInterface(string $data):QRDataInterface{
- $dataModes = ['Number', 'AlphaNum', 'Kanji', 'Byte'];
- $dataNamespace = __NAMESPACE__.'\\Data\\';
// allow forcing the data mode
// see https://github.com/chillerlan/php-qrcode/issues/39
- if(in_array($this->options->dataMode, $dataModes, true)){
- $dataInterface = $dataNamespace.$this->options->dataMode;
+ $interface = $this::DATA_INTERFACES[strtolower($this->options->dataModeOverride)] ?? null;
- return new $dataInterface($this->options, $data);
+ if($interface !== null){
+ return new $interface($this->options, $data);
}
- foreach($dataModes as $mode){
- $dataInterface = $dataNamespace.$mode;
+ foreach($this::DATA_INTERFACES as $mode => $dataInterface){
- if(call_user_func_array([$this, 'is'.$mode], [$data]) && class_exists($dataInterface)){
+ if(call_user_func_array([$this, 'is'.$mode], [$data])){
return new $dataInterface($this->options, $data);
}
@@ -208,14 +235,12 @@ class QRCode{
/**
* returns a fresh (built-in) QROutputInterface
*
- * @param string $data
- *
- * @return \chillerlan\QRCode\Output\QROutputInterface
* @throws \chillerlan\QRCode\Output\QRCodeOutputException
*/
protected function initOutputInterface(string $data):QROutputInterface{
if($this->options->outputType === $this::OUTPUT_CUSTOM && class_exists($this->options->outputInterface)){
+ /** @phan-suppress-next-line PhanTypeExpectedObjectOrClassName */
return new $this->options->outputInterface($this->options, $this->getMatrix($data));
}
@@ -232,39 +257,25 @@ class QRCode{
/**
* checks if a string qualifies as numeric
- *
- * @param string $string
- *
- * @return bool
*/
public function isNumber(string $string):bool{
- return $this->checkString($string, QRDataInterface::NUMBER_CHAR_MAP);
+ return $this->checkString($string, QRDataInterface::CHAR_MAP_NUMBER);
}
/**
* checks if a string qualifies as alphanumeric
- *
- * @param string $string
- *
- * @return bool
*/
public function isAlphaNum(string $string):bool{
- return $this->checkString($string, QRDataInterface::ALPHANUM_CHAR_MAP);
+ return $this->checkString($string, QRDataInterface::CHAR_MAP_ALPHANUM);
}
/**
* checks is a given $string matches the characters of a given $charmap, returns false on the first invalid occurence.
- *
- * @param string $string
- * @param array $charmap
- *
- * @return bool
*/
protected function checkString(string $string, array $charmap):bool{
- $len = strlen($string);
- for($i = 0; $i < $len; $i++){
- if(!in_array($string[$i], $charmap, true)){
+ foreach(str_split($string) as $chr){
+ if(!isset($charmap[$chr])){
return false;
}
}
@@ -274,10 +285,6 @@ class QRCode{
/**
* checks if a string qualifies as Kanji
- *
- * @param string $string
- *
- * @return bool
*/
public function isKanji(string $string):bool{
$i = 0;
@@ -298,12 +305,8 @@ class QRCode{
/**
* a dummy
- *
- * @param $data
- *
- * @return bool
*/
- protected function isByte(string $data):bool{
+ public function isByte(string $data):bool{
return !empty($data);
}