From d7bacdc942c3c81c603ece7fbfd68c24a586d9d1 Mon Sep 17 00:00:00 2001 From: smiley Date: Thu, 28 Dec 2017 17:50:29 +0100 Subject: [PATCH] :sparkles: load custom output module via options --- README.md | 20 +++++++++++++++++--- examples/custom_output.php | 12 ++++++++++++ src/QRCode.php | 6 ++++++ src/QROptions.php | 9 +++++++++ tests/QRCodeTest.php | 14 ++++++++++++++ 5 files changed, 58 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d77eb8a1f..a82919481 100644 --- a/README.md +++ b/README.md @@ -264,13 +264,25 @@ class MyCustomOptions extends QROptions{ } ``` -Invoke a fresh custom `QROutputInterface`, see also `QRCode::initOutputInterface()`. +You can then call `QRCode` with the custom modules... ```php -$qrOutputInterface = new MyCustomOutput($myCustomOptions, (new QRCode($myCustomOptions))->getMatrix($data)); +$myCustomOptions = new MyCustomOptions([ + 'version' => 5, + 'eccLevel' => QRCode::ECC_L, + 'outputType' => QRCode::OUTPUT_CUSTOM, + 'outputInterface' => MyCustomOutput::class, + // custom settings + 'myParam' => 'whatever value', +]); + +(new QRCode($myCustomOptions))->render($data); ``` -...and dump the output, which is equivalent to `QRCode::render()` +...or you can invoke the `QROutputInterface` manually. ```php +$qrOutputInterface = new MyCustomOutput($myCustomOptions, (new QRCode($myCustomOptions))->getMatrix($data)); + +//dump the output, which is equivalent to QRCode::render() $qrOutputInterface->dump(); ``` @@ -296,6 +308,7 @@ name | description `OUTPUT_MARKUP_SVG`, `OUTPUT_MARKUP_HTML` | `QROptions::$outputType` markup `OUTPUT_IMAGE_PNG`, `OUTPUT_IMAGE_JPG`, `OUTPUT_IMAGE_GIF` | `QROptions::$outputType` image `OUTPUT_STRING_JSON`, `OUTPUT_STRING_TEXT` | `QROptions::$outputType` string +`OUTPUT_CUSTOM` | `QROptions::$outputType`, requires `QROptions::$outputInterface` `ECC_L`, `ECC_M`, `ECC_Q`, `ECC_H`, | ECC-Level: 7%, 15%, 25%, 30% in `QROptions::$eccLevel` `DATA_NUMBER`, `DATA_ALPHANUM`, `DATA_BYTE`, `DATA_KANJI` | `QRDataInterface::$datamode` @@ -310,6 +323,7 @@ property | type | default | allowed | description `$addQuietzone` | bool | true | - | Add a "quiet zone" (margin) according to the QR code spec `$quietzoneSize` | int | 4 | clamped to 0 ... `$matrixSize / 2` | Size of the quiet zone `$outputType` | string | `QRCode::OUTPUT_IMAGE_PNG` | `QRCode::OUTPUT_*` | built-in output type +`$outputInterface` | string | null | * | FQCN of the custom `QROutputInterface` if `QROptions::$outputType` is set to `QRCode::OUTPUT_CUSTOM` `$cachefile` | string | null | * | optional cache file path `$eol` | string | `PHP_EOL` | * | newline string (HTML, SVG, TEXT) `$scale` | int | 5 | * | size of a QR code pixel (SVG, IMAGE_*), HTML -> via CSS diff --git a/examples/custom_output.php b/examples/custom_output.php index 54cda1e6b..71ea62682 100644 --- a/examples/custom_output.php +++ b/examples/custom_output.php @@ -16,6 +16,7 @@ require_once __DIR__.'/../vendor/autoload.php'; $data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s'; +// invoke the QROutputInterface manually $options = new QROptions([ 'version' => 5, 'eccLevel' => QRCode::ECC_L, @@ -24,3 +25,14 @@ $options = new QROptions([ $qrOutputInterface = new MyCustomOutput($options, (new QRCode($options))->getMatrix($data)); var_dump($qrOutputInterface->dump()); + + +// or just +$options = new QROptions([ + 'version' => 5, + 'eccLevel' => QRCode::ECC_L, + 'outputType' => QRCode::OUTPUT_CUSTOM, + 'outputInterface' => MyCustomOutput::class, +]); + +var_dump((new QRCode($options))->render($data)); diff --git a/src/QRCode.php b/src/QRCode.php index 849974fe3..137ed24bc 100644 --- a/src/QRCode.php +++ b/src/QRCode.php @@ -44,6 +44,8 @@ class QRCode{ const OUTPUT_STRING_JSON = 'json'; const OUTPUT_STRING_TEXT = 'text'; + const OUTPUT_CUSTOM = 'custom'; + const VERSION_AUTO = -1; const MASK_PATTERN_AUTO = -1; @@ -244,6 +246,10 @@ class QRCode{ */ protected function initOutputInterface(string $data):QROutputInterface{ + if($this->options->outputType === $this::OUTPUT_CUSTOM && $this->options->outputInterface !== null){ + return $this->loadClass($this->options->outputInterface, QROutputInterface::class, $this->options, $this->getMatrix($data)); + } + foreach($this::OUTPUT_MODES as $outputInterface => $modes){ if(in_array($this->options->outputType, $modes, true)){ diff --git a/src/QROptions.php b/src/QROptions.php index f52cccaea..85693116c 100644 --- a/src/QROptions.php +++ b/src/QROptions.php @@ -25,6 +25,7 @@ use chillerlan\Traits\Container; * @property bool $quietzoneSize * * @property string $outputType + * @property string $outputInterface * @property string $cachefile * * @property string $eol @@ -111,11 +112,19 @@ class QROptions{ * QRCode::OUTPUT_MARKUP_XXXX where XXXX = HTML, SVG * QRCode::OUTPUT_IMAGE_XXX where XXX = PNG, GIF, JPG * QRCode::OUTPUT_STRING_XXXX where XXXX = TEXT, JSON + * QRCode::OUTPUT_CUSTOM * * @var string */ protected $outputType = QRCode::OUTPUT_IMAGE_PNG; + /** + * the FQCN of the custom QROutputInterface if $outputType is set to QRCode::OUTPUT_CUSTOM + * + * @var string + */ + protected $outputInterface; + /** * /path/to/cache.file * diff --git a/tests/QRCodeTest.php b/tests/QRCodeTest.php index ee61cfe76..c9430bc8e 100644 --- a/tests/QRCodeTest.php +++ b/tests/QRCodeTest.php @@ -14,6 +14,7 @@ namespace chillerlan\QRCodeTest; use chillerlan\QRCode\QROptions; use chillerlan\QRCode\QRCode; +use chillerlan\QRCodeExamples\MyCustomOutput; class QRCodeTest extends QRTestAbstract{ @@ -99,4 +100,17 @@ class QRCodeTest extends QRTestAbstract{ $this->assertSame([255,255,255], $this->getProperty('options')->getValue($this->qrcode)->imageTransparencyBG); } + public function testCustomOutput(){ + + $options = new QROptions([ + 'version' => 5, + 'eccLevel' => QRCode::ECC_L, + 'outputType' => QRCode::OUTPUT_CUSTOM, + 'outputInterface' => MyCustomOutput::class, + ]); + + $expected = '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111110111010000101111010000011111110000000010000010111000001101011000001010000010000000010111010101101011000001101011010111010000000010111010110100111110010100111010111010000000010111010000001101011000001101010111010000000010000010100111110010100111110010000010000000011111110101010101010101010101011111110000000000000000010010100111110010100000000000000000011001110000101111010000101111001011110000000000000000111010000101111010000111100010000000001011010100111110010100111110011001010000000010000101111101011000001101011110011110000000000011010100011000001101011000101110100000000011001100001001101011000001101010011010000000010110111110000001101011000001100110100000000010000100100010100111110010100001100100000000011111110111101111010000101111010100110000000011010000111010000101111010000111100100000000010101111111111110010100111110011001000000000010110001110101011000001101011110011010000000001001111100011000001101011000101110010000000011000100110001101011000001101010011100000000001000011001000001101011000001100110000000000011101001011010100111110010100001100000000000010111010001101111010000101111010100110000000011100000001010000101111010000111100000000000000001110110111110010100111110011001000000000000011001011101011000001101011110011100000000011111110101011000001101011001111110110000000000000000110001101011000001101000111100000000011111110001000001101011000011010110000000000010000010101010100111110010101000100100000000010111010111101111010000101111111100110000000010111010011010000101111010001101100010000000010111010000111110010100111100101101100000000010000010101101011000001101001100111100000000011111110101011000001101011000110010110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'; + + $this->assertSame($expected, $this->reflection->newInstanceArgs([$options])->render('test')); + } }